mirror of
https://github.com/leejet/stable-diffusion.cpp.git
synced 2026-11-14 12:56:33 +00:00
feat: allow the P-H3-Image text encoder for MiniMax-H3-Image (#2337)
This commit is contained in:
1 parent
766ce0ec4e
commit
8b1e9df27d
4 files changed
+38
-7
No files matched your search
@@ -16,10 +16,19 @@ Use the MiniMax-H3 text encoder, including its Qwen3-VL vision tower and
|
|||||||
DeepStack mergers. An existing MiniMax-H3 text encoder can be reused. If the
|
DeepStack mergers. An existing MiniMax-H3 text encoder can be reused. If the
|
||||||
vision tower is stored separately, pass it with `--llm_vision`.
|
vision tower is stored separately, pass it with `--llm_vision`.
|
||||||
|
|
||||||
|
The P-H3-Image text encoder can be used instead: Qwen3-VL-4B with the P-H3
|
||||||
|
text connector. It needs much less memory (about 5 GB for the INT8 ConvRot
|
||||||
|
file, versus 18 GB for the 32B encoder in Q4_K_M) and works for both
|
||||||
|
text-to-image and reference-image editing. Pass the P-H3-Image text encoder,
|
||||||
|
which includes the connector, with `--llm`. Alternatively, pass Qwen3-VL-4B
|
||||||
|
with `--llm` and the [separate text connector](https://huggingface.co/PrunaAI/P-H3-Image/blob/main/text_connector/diffusion_pytorch_model.safetensors)
|
||||||
|
with `--embeddings-connectors`. Reference-image editing needs the Qwen3-VL-4B
|
||||||
|
vision tower in the text encoder or in `--llm_vision`.
|
||||||
|
|
||||||
Use a single-file diffusion checkpoint with the six-step PDD output heads
|
Use a single-file diffusion checkpoint with the six-step PDD output heads
|
||||||
included, such as `minimax_h3_image_pruned_bf16.safetensors` or its INT8 ConvRot
|
included, such as `minimax_h3_image_pruned_bf16.safetensors` or its INT8 ConvRot
|
||||||
version. Use the MiniMax-H3-Image VAE; the MiniMax-H3 video VAE and P-H3-Image
|
version. Use the MiniMax-H3-Image VAE; the MiniMax-H3 video VAE and P-H3-Image
|
||||||
VAE are incompatible. No audio VAE or P-H3 text connector is needed.
|
VAE are incompatible. No audio VAE is needed.
|
||||||
|
|
||||||
### Download weights
|
### Download weights
|
||||||
|
|
||||||
@@ -28,6 +37,8 @@ VAE are incompatible. No audio VAE or P-H3 text connector is needed.
|
|||||||
- Download qwen3vl_32b_minimax_h3
|
- Download qwen3vl_32b_minimax_h3
|
||||||
- safetensors: https://huggingface.co/Comfy-Org/MiniMax-H3-Image/tree/main/text_encoders
|
- safetensors: https://huggingface.co/Comfy-Org/MiniMax-H3-Image/tree/main/text_encoders
|
||||||
- gguf: https://huggingface.co/leejet/MiniMax-H3-GGUF/tree/main
|
- gguf: https://huggingface.co/leejet/MiniMax-H3-GGUF/tree/main
|
||||||
|
- Or download the P-H3-Image text encoder (Qwen3-VL-4B with the text connector)
|
||||||
|
- safetensors: https://huggingface.co/PrunaAI/P-H3-Image-Comfy/tree/main/text_encoders
|
||||||
- Download vae
|
- Download vae
|
||||||
- safetensors: https://huggingface.co/Comfy-Org/MiniMax-H3-Image/tree/main/vae
|
- safetensors: https://huggingface.co/Comfy-Org/MiniMax-H3-Image/tree/main/vae
|
||||||
|
|
||||||
@@ -37,6 +48,12 @@ VAE are incompatible. No audio VAE or P-H3 text connector is needed.
|
|||||||
.\bin\Release\sd-cli.exe --diffusion-model ..\models\diffusion_models\minimax_h3_image_pruned_bf16.safetensors --vae ..\models\vae\minimax_h3_image_vae_fp16.safetensors --llm ..\models\text_encoders\qwen3vl_32b_minimax_h3-Q4_K_M.gguf -p "A silver tabby kitten holding a sign reading 'sd.cpp', natural daylight" --cfg-scale 1.0 --steps 6 --sampling-method euler --sigmas minimax-h3-image -v -W 1024 -H 1024 --offload-to-cpu --rng cpu --diffusion-fa --vae-tiling
|
.\bin\Release\sd-cli.exe --diffusion-model ..\models\diffusion_models\minimax_h3_image_pruned_bf16.safetensors --vae ..\models\vae\minimax_h3_image_vae_fp16.safetensors --llm ..\models\text_encoders\qwen3vl_32b_minimax_h3-Q4_K_M.gguf -p "A silver tabby kitten holding a sign reading 'sd.cpp', natural daylight" --cfg-scale 1.0 --steps 6 --sampling-method euler --sigmas minimax-h3-image -v -W 1024 -H 1024 --offload-to-cpu --rng cpu --diffusion-fa --vae-tiling
|
||||||
```
|
```
|
||||||
|
|
||||||
|
With the P-H3-Image text encoder, replace the `--llm` argument:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
--llm ..\models\text_encoders\p-h3-image_text_encoder_int8_convrot.safetensors
|
||||||
|
```
|
||||||
|
|
||||||
Use Euler, CFG 1, and `--sigmas minimax-h3-image` for the model's six-step
|
Use Euler, CFG 1, and `--sigmas minimax-h3-image` for the model's six-step
|
||||||
schedule. The default discrete scheduler also produces this schedule with
|
schedule. The default discrete scheduler also produces this schedule with
|
||||||
`--steps 6`. Prompt expansion is not included.
|
`--steps 6`. Prompt expansion is not included.
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"id": "minimax-h3-image",
|
"id": "minimax-h3-image",
|
||||||
"name": "MiniMax H3 Image",
|
"name": "MiniMax H3 Image",
|
||||||
"size_multiple": 32,
|
"size_multiple": 32,
|
||||||
"description": "Text-to-image and reference-image editing with the six-step PDD checkpoint. Requires the MiniMax-H3-Image 2D VAE and MiniMax-H3 Qwen3-VL-32B text encoder with its vision tower.",
|
"description": "Text-to-image and reference-image editing with the six-step PDD checkpoint. Requires the MiniMax-H3-Image 2D VAE and either the MiniMax-H3 Qwen3-VL-32B text encoder with its vision tower or the smaller P-H3-Image text encoder (Qwen3-VL-4B with the P-H3 text connector).",
|
||||||
"model_url": "https://huggingface.co/MiniMaxAI/MiniMax-H3-Image",
|
"model_url": "https://huggingface.co/MiniMaxAI/MiniMax-H3-Image",
|
||||||
"slots": [
|
"slots": [
|
||||||
{
|
{
|
||||||
@@ -13,13 +13,18 @@
|
|||||||
{
|
{
|
||||||
"id": "llm",
|
"id": "llm",
|
||||||
"required": true,
|
"required": true,
|
||||||
"label": "MiniMax-H3 Qwen 3 VL 32B Text Encoder"
|
"label": "MiniMax-H3 Qwen 3 VL 32B or P-H3 Qwen 3 VL 4B Text Encoder"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "llm_vision",
|
"id": "llm_vision",
|
||||||
"required": false,
|
"required": false,
|
||||||
"label": "Vision tower (required when not included in the text encoder)"
|
"label": "Vision tower (required when not included in the text encoder)"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "embeddings_connectors",
|
||||||
|
"required": false,
|
||||||
|
"label": "P-H3 Text Connector (for Qwen 3 VL 4B, when not included in the text encoder)"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "vae",
|
"id": "vae",
|
||||||
"required": true,
|
"required": true,
|
||||||
|
|||||||
@@ -2030,11 +2030,20 @@ struct LLMEmbedder : public Conditioner {
|
|||||||
"text_encoders.llm",
|
"text_encoders.llm",
|
||||||
enable_vision,
|
enable_vision,
|
||||||
weight_manager);
|
weight_manager);
|
||||||
if (version == VERSION_P_H3_IMAGE) {
|
// MiniMax-H3-Image also accepts the P-H3-Image text encoder in place of the MiniMax-H3 Qwen3-VL-32B encoder.
|
||||||
|
const bool has_ph3_connector = tensor_storage_map.find(std::string(PH3ImageTextConnectorRunner::prefix) + ".proj.weight") !=
|
||||||
|
tensor_storage_map.end();
|
||||||
|
if (version == VERSION_P_H3_IMAGE || (version == VERSION_MINIMAX_H3_IMAGE && has_ph3_connector)) {
|
||||||
if (llm->config.num_layers != 36 || llm->config.hidden_size != 2560) {
|
if (llm->config.num_layers != 36 || llm->config.hidden_size != 2560) {
|
||||||
throw std::runtime_error("P-H3-Image requires the Qwen3-VL-4B text encoder");
|
throw std::runtime_error(version == VERSION_P_H3_IMAGE
|
||||||
|
? "P-H3-Image requires the Qwen3-VL-4B text encoder"
|
||||||
|
: "The P-H3-Image text connector requires the Qwen3-VL-4B text encoder");
|
||||||
}
|
}
|
||||||
ph3_connector = std::make_shared<PH3ImageTextConnectorRunner>(backend, tensor_storage_map, weight_manager);
|
ph3_connector = std::make_shared<PH3ImageTextConnectorRunner>(backend, tensor_storage_map, weight_manager);
|
||||||
|
} else if (version == VERSION_MINIMAX_H3_IMAGE && llm->config.hidden_size == 2560) {
|
||||||
|
throw std::runtime_error(
|
||||||
|
"MiniMax-H3-Image with Qwen3-VL-4B requires the P-H3-Image text connector; "
|
||||||
|
"pass it with --embeddings-connectors or use the MiniMax-H3 Qwen3-VL-32B text encoder");
|
||||||
}
|
}
|
||||||
int pad_id = 151643;
|
int pad_id = 151643;
|
||||||
if (arch == LLM::LLMArch::MISTRAL_SMALL_3_2 || arch == LLM::LLMArch::MINISTRAL_3_3B) {
|
if (arch == LLM::LLMArch::MISTRAL_SMALL_3_2 || arch == LLM::LLMArch::MINISTRAL_3_3B) {
|
||||||
@@ -2493,7 +2502,7 @@ struct LLMEmbedder : public Conditioner {
|
|||||||
if (sd_version_is_minimax_h3(version)) {
|
if (sd_version_is_minimax_h3(version)) {
|
||||||
prompt_template_encode_start_idx = 0;
|
prompt_template_encode_start_idx = 0;
|
||||||
// The final tap is normalized; LLMRunner exposes it at num_layers + 1.
|
// The final tap is normalized; LLMRunner exposes it at num_layers + 1.
|
||||||
out_layers = version == VERSION_P_H3_IMAGE ? std::set<int>{13, 19, 25, 31, 37} : std::set<int>{50};
|
out_layers = ph3_connector ? std::set<int>{13, 19, 25, 31, 37} : std::set<int>{50};
|
||||||
prompt_attn_range = {0, 0};
|
prompt_attn_range = {0, 0};
|
||||||
|
|
||||||
if (llm->enable_vision) {
|
if (llm->enable_vision) {
|
||||||
|
|||||||
@@ -1741,7 +1741,7 @@ std::string convert_tensor_name(std::string name, SDVersion version) {
|
|||||||
|
|
||||||
const std::vector<std::pair<std::string, std::string>> connector_prefix_map = {
|
const std::vector<std::pair<std::string, std::string>> connector_prefix_map = {
|
||||||
{"embeddings_connectors.text_encoders.", "text_encoders."},
|
{"embeddings_connectors.text_encoders.", "text_encoders."},
|
||||||
{"embeddings_connectors.", version == VERSION_P_H3_IMAGE ? "text_encoders.ph3_image_connector." : ""},
|
{"embeddings_connectors.", sd_version_is_minimax_h3_image(version) ? "text_encoders.ph3_image_connector." : ""},
|
||||||
};
|
};
|
||||||
replace_with_prefix_map(name, connector_prefix_map);
|
replace_with_prefix_map(name, connector_prefix_map);
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user