From 0e9a092d651a690c7d10420fe70bf7a368e5284b Mon Sep 17 00:00:00 2001 From: leejet Date: Mon, 6 Jul 2026 22:58:38 +0800 Subject: [PATCH] refactor: move model-specific args into model parsers --- docs/chroma.md | 3 +-- docs/qwen_image_edit.md | 6 ++--- examples/common/common.cpp | 32 ++++++------------------ examples/common/common.h | 7 +----- include/stable-diffusion.h | 5 +--- src/conditioning/conditioner.hpp | 22 +++++++++++++++- src/model/diffusion/flux.hpp | 22 +++++++++++----- src/model/diffusion/qwen_image.hpp | 17 ++++++++++--- src/stable-diffusion.cpp | 40 +++++++++++++----------------- 9 files changed, 81 insertions(+), 73 deletions(-) diff --git a/docs/chroma.md b/docs/chroma.md index 4370eed77..606a85fe5 100644 --- a/docs/chroma.md +++ b/docs/chroma.md @@ -24,10 +24,9 @@ You can download the preconverted gguf weights from [silveroxides/Chroma-GGUF](h For example: ``` - .\bin\Release\sd-cli.exe --diffusion-model ..\models\chroma-unlocked-v40-q8_0.gguf --vae ..\models\ae.sft --t5xxl ..\models\t5xxl_fp16.safetensors -p "a lovely cat holding a sign says 'chroma.cpp'" --cfg-scale 4.0 --sampling-method euler -v --chroma-disable-dit-mask --clip-on-cpu + .\bin\Release\sd-cli.exe --diffusion-model ..\models\chroma-unlocked-v40-q8_0.gguf --vae ..\models\ae.sft --t5xxl ..\models\t5xxl_fp16.safetensors -p "a lovely cat holding a sign says 'chroma.cpp'" --cfg-scale 4.0 --sampling-method euler -v --model-args chroma_use_dit_mask=false --clip-on-cpu ``` ![](../assets/flux/chroma_v40.png) - diff --git a/docs/qwen_image_edit.md b/docs/qwen_image_edit.md index d97631c0b..2f0885028 100644 --- a/docs/qwen_image_edit.md +++ b/docs/qwen_image_edit.md @@ -39,10 +39,10 @@ ### Qwen Image Edit 2511 -To use the new Qwen Image Edit 2511 mode, the `--qwen-image-zero-cond-t` flag must be enabled; otherwise, image editing quality will degrade significantly. +To use the new Qwen Image Edit 2511 mode, `--model-args qwen_image_zero_cond_t=true` must be enabled; otherwise, image editing quality will degrade significantly. ``` -.\bin\Release\sd-cli.exe --diffusion-model ..\models\diffusion_models\qwen-image-edit-2511-Q4_K_M.gguf --vae ..\models\vae\qwen_image_vae.safetensors --llm ..\models\text_encoders\qwen_2.5_vl_7b.safetensors --cfg-scale 2.5 --sampling-method euler -v --offload-to-cpu --diffusion-fa --flow-shift 3 -r ..\assets\flux\flux1-dev-q8_0.png -p "change 'flux.cpp' to 'edit.cpp'" --qwen-image-zero-cond-t +.\bin\Release\sd-cli.exe --diffusion-model ..\models\diffusion_models\qwen-image-edit-2511-Q4_K_M.gguf --vae ..\models\vae\qwen_image_vae.safetensors --llm ..\models\text_encoders\qwen_2.5_vl_7b.safetensors --cfg-scale 2.5 --sampling-method euler -v --offload-to-cpu --diffusion-fa --flow-shift 3 -r ..\assets\flux\flux1-dev-q8_0.png -p "change 'flux.cpp' to 'edit.cpp'" --model-args qwen_image_zero_cond_t=true ``` -qwen_image_edit_2509 \ No newline at end of file +qwen_image_edit_2509 diff --git a/examples/common/common.cpp b/examples/common/common.cpp index e019f0cdd..1dfb6aa70 100644 --- a/examples/common/common.cpp +++ b/examples/common/common.cpp @@ -443,6 +443,12 @@ ArgOptions SDContextParams::get_options() { "weight type per tensor pattern (example: \"^vae\\.=f16,model\\.=q8_0\")", (int)',', &tensor_type_rules}, + {"", + "--model-args", + "extra model args, key=value list. Supports chroma_use_dit_mask, chroma_use_t5_mask, " + "chroma_t5_mask_pad, qwen_image_zero_cond_t", + (int)',', + &model_args}, {"", "--photo-maker", "path to PHOTOMAKER model", @@ -493,10 +499,6 @@ ArgOptions SDContextParams::get_options() { "number of threads to use during computation (default: -1). " "If threads <= 0, then threads will be set to the number of CPU physical cores", &n_threads}, - {"", - "--chroma-t5-mask-pad", - "t5 mask pad size of chroma", - &chroma_t5_mask_pad}, }; options.bool_options = { @@ -554,18 +556,6 @@ ArgOptions SDContextParams::get_options() { "--vae-conv-direct", "use ggml_conv2d_direct in the vae model", true, &vae_conv_direct}, - {"", - "--chroma-disable-dit-mask", - "disable dit mask for chroma", - false, &chroma_use_dit_mask}, - {"", - "--qwen-image-zero-cond-t", - "enable zero_cond_t for qwen image", - true, &qwen_image_zero_cond_t}, - {"", - "--chroma-enable-t5-mask", - "enable t5 mask for chroma", - true, &chroma_use_t5_mask}, }; auto on_type_arg = [&](int argc, const char** argv, int index) { @@ -832,6 +822,7 @@ std::string SDContextParams::to_string() const { << " backend: \"" << backend << "\",\n" << " params_backend: \"" << params_backend << "\",\n" << " split_mode: \"" << split_mode << "\",\n" + << " model_args: \"" << model_args << "\",\n" << " auto_fit: " << (auto_fit ? "true" : "false") << ",\n" << " enable_mmap: " << (enable_mmap ? "true" : "false") << ",\n" << " control_net_cpu: " << (control_net_cpu ? "true" : "false") << ",\n" @@ -841,10 +832,6 @@ std::string SDContextParams::to_string() const { << " diffusion_flash_attn: " << (diffusion_flash_attn ? "true" : "false") << ",\n" << " diffusion_conv_direct: " << (diffusion_conv_direct ? "true" : "false") << ",\n" << " vae_conv_direct: " << (vae_conv_direct ? "true" : "false") << ",\n" - << " chroma_use_dit_mask: " << (chroma_use_dit_mask ? "true" : "false") << ",\n" - << " qwen_image_zero_cond_t: " << (qwen_image_zero_cond_t ? "true" : "false") << ",\n" - << " chroma_use_t5_mask: " << (chroma_use_t5_mask ? "true" : "false") << ",\n" - << " chroma_t5_mask_pad: " << chroma_t5_mask_pad << ",\n" << " prediction: " << sd_prediction_name(prediction) << ",\n" << " lora_apply_mode: " << sd_lora_apply_mode_name(lora_apply_mode) << ",\n" << " force_sdxl_vae_conv_scale: " << (force_sdxl_vae_conv_scale ? "true" : "false") << "\n" @@ -898,10 +885,6 @@ sd_ctx_params_t SDContextParams::to_sd_ctx_params_t(bool taesd_preview) { sd_ctx_params.diffusion_conv_direct = diffusion_conv_direct; sd_ctx_params.vae_conv_direct = vae_conv_direct; sd_ctx_params.force_sdxl_vae_conv_scale = force_sdxl_vae_conv_scale; - sd_ctx_params.chroma_use_dit_mask = chroma_use_dit_mask; - sd_ctx_params.chroma_use_t5_mask = chroma_use_t5_mask; - sd_ctx_params.chroma_t5_mask_pad = chroma_t5_mask_pad; - sd_ctx_params.qwen_image_zero_cond_t = qwen_image_zero_cond_t; sd_ctx_params.vae_format = str_to_vae_format(vae_format); sd_ctx_params.max_vram = max_vram.c_str(); sd_ctx_params.stream_layers = stream_layers; @@ -911,6 +894,7 @@ sd_ctx_params_t SDContextParams::to_sd_ctx_params_t(bool taesd_preview) { sd_ctx_params.split_mode = split_mode.c_str(); sd_ctx_params.auto_fit = auto_fit; sd_ctx_params.rpc_servers = rpc_servers.c_str(); + sd_ctx_params.model_args = model_args.empty() ? nullptr : model_args.c_str(); return sd_ctx_params; } diff --git a/examples/common/common.h b/examples/common/common.h index b32998146..3a5b107bc 100644 --- a/examples/common/common.h +++ b/examples/common/common.h @@ -152,6 +152,7 @@ struct SDContextParams { std::string backend; std::string params_backend; std::string split_mode; + std::string model_args; bool auto_fit = false; std::string rpc_servers; std::string effective_backend; @@ -165,12 +166,6 @@ struct SDContextParams { bool diffusion_conv_direct = false; bool vae_conv_direct = false; - bool chroma_use_dit_mask = true; - bool chroma_use_t5_mask = false; - int chroma_t5_mask_pad = 1; - - bool qwen_image_zero_cond_t = false; - prediction_t prediction = PREDICTION_COUNT; lora_apply_mode_t lora_apply_mode = LORA_APPLY_AUTO; diff --git a/include/stable-diffusion.h b/include/stable-diffusion.h index 9010d6294..93084fe29 100644 --- a/include/stable-diffusion.h +++ b/include/stable-diffusion.h @@ -217,10 +217,6 @@ typedef struct { bool diffusion_conv_direct; bool vae_conv_direct; bool force_sdxl_vae_conv_scale; - bool chroma_use_dit_mask; - bool chroma_use_t5_mask; - int chroma_t5_mask_pad; - bool qwen_image_zero_cond_t; enum sd_vae_format_t vae_format; const char* max_vram; // GiB budget or backend assignment spec for graph-cut segmented param offload (0 = disabled, -1 = auto) bool stream_layers; // Enable residency+prefetch streaming on top of --max-vram (no effect without --max-vram) @@ -230,6 +226,7 @@ typedef struct { const char* split_mode; // weight distribution for multi-device modules: layer (default) or row, or per-module assignments e.g. "diffusion=row" bool auto_fit; const char* rpc_servers; + const char* model_args; } sd_ctx_params_t; typedef struct { diff --git a/src/conditioning/conditioner.hpp b/src/conditioning/conditioner.hpp index da5aa74f0..3d315985b 100644 --- a/src/conditioning/conditioner.hpp +++ b/src/conditioning/conditioner.hpp @@ -6,6 +6,7 @@ #include #include "core/tensor_ggml.hpp" +#include "core/util.h" #include "model/te/clip.hpp" #include "model/te/llm.hpp" #include "model/te/t5.hpp" @@ -1217,8 +1218,27 @@ struct T5CLIPEmbedder : public Conditioner { bool use_mask = false, int mask_pad = 0, bool is_umt5 = false, - std::shared_ptr weight_manager = nullptr) + std::shared_ptr weight_manager = nullptr, + const char* model_args = nullptr) : use_mask(use_mask), mask_pad(mask_pad), t5_tokenizer(is_umt5) { + for (const auto& [key, value] : parse_key_value_args(model_args, "model arg")) { + if (key == "chroma_use_t5_mask") { + bool parsed = false; + if (parse_strict_bool(value, parsed)) { + this->use_mask = parsed; + } else { + LOG_WARN("ignoring invalid Chroma T5 model arg '%s=%s'", key.c_str(), value.c_str()); + } + } else if (key == "chroma_t5_mask_pad") { + int parsed = 0; + if (parse_strict_int(value, parsed)) { + this->mask_pad = parsed; + } else { + LOG_WARN("ignoring invalid Chroma T5 model arg '%s=%s'", key.c_str(), value.c_str()); + } + } + } + bool use_t5 = false; for (auto pair : tensor_storage_map) { if (pair.first.find("text_encoders.t5xxl") != std::string::npos) { diff --git a/src/model/diffusion/flux.hpp b/src/model/diffusion/flux.hpp index e3cd6ba7c..e5d795f74 100644 --- a/src/model/diffusion/flux.hpp +++ b/src/model/diffusion/flux.hpp @@ -4,6 +4,7 @@ #include #include +#include "core/util.h" #include "model/adapter/pulid.hpp" #include "model/common/rope.hpp" #include "model/diffusion/dit.hpp" @@ -1400,18 +1401,28 @@ namespace Flux { std::vector dct_vec; sd::Tensor guidance_tensor; SDVersion version; - bool use_mask = false; + bool use_mask = true; FluxRunner(ggml_backend_t backend, const String2TensorStorage& tensor_storage_map = {}, const std::string prefix = "", SDVersion version = VERSION_FLUX, - bool use_mask = false, - std::shared_ptr weight_manager = nullptr) + std::shared_ptr weight_manager = nullptr, + const char* model_args = nullptr) : DiffusionModelRunner(backend, prefix, weight_manager), config(FluxConfig::detect_from_weights(tensor_storage_map, prefix, version)), - version(version), - use_mask(use_mask) { + version(version) { + for (const auto& [key, value] : parse_key_value_args(model_args, "model arg")) { + if (key == "chroma_use_dit_mask") { + bool parsed = true; + if (parse_strict_bool(value, parsed)) { + use_mask = parsed; + } else { + LOG_WARN("ignoring invalid Chroma DiT model arg '%s=%s'", key.c_str(), value.c_str()); + } + } + } + if (config.is_chroma) { LOG_INFO("Using pruned modulation (Chroma)"); } @@ -1718,7 +1729,6 @@ namespace Flux { tensor_storage_map, "model.diffusion_model", VERSION_FLUX2, - false, model_manager); if (!model_manager->register_runner_params("Flux test", diff --git a/src/model/diffusion/qwen_image.hpp b/src/model/diffusion/qwen_image.hpp index 5dabbb176..52edc0d56 100644 --- a/src/model/diffusion/qwen_image.hpp +++ b/src/model/diffusion/qwen_image.hpp @@ -3,6 +3,7 @@ #include +#include "core/util.h" #include "model/common/block.hpp" #include "model/diffusion/dit.hpp" #include "model/diffusion/flux.hpp" @@ -566,12 +567,21 @@ namespace Qwen { const String2TensorStorage& tensor_storage_map = {}, const std::string prefix = "", SDVersion version = VERSION_QWEN_IMAGE, - bool zero_cond_t = false, - std::shared_ptr weight_manager = nullptr) + std::shared_ptr weight_manager = nullptr, + const char* model_args = nullptr) : DiffusionModelRunner(backend, prefix, weight_manager), config(QwenImageConfig::detect_from_weights(tensor_storage_map, prefix)), version(version) { - config.zero_cond_t = config.zero_cond_t || zero_cond_t; + for (const auto& [key, value] : parse_key_value_args(model_args, "model arg")) { + if (key == "qwen_image_zero_cond_t") { + bool parsed = false; + if (parse_strict_bool(value, parsed)) { + config.zero_cond_t = config.zero_cond_t || parsed; + } else { + LOG_WARN("ignoring invalid Qwen Image model arg '%s=%s'", key.c_str(), value.c_str()); + } + } + } if (version == VERSION_QWEN_IMAGE_LAYERED) { config.use_additional_t_cond = true; } @@ -775,7 +785,6 @@ namespace Qwen { tensor_storage_map, "model.diffusion_model", VERSION_QWEN_IMAGE, - false, model_manager); if (!model_manager->register_runner_params("Qwen image test", diff --git a/src/stable-diffusion.cpp b/src/stable-diffusion.cpp index eb0f05492..466a88fa5 100644 --- a/src/stable-diffusion.cpp +++ b/src/stable-diffusion.cpp @@ -57,11 +57,11 @@ #include "name_conversion.h" #include "runtime/latent-preview.h" +#include + const char* sd_vae_format_name(enum sd_vae_format_t format); static SDVersion sd_vae_format_to_version(enum sd_vae_format_t format, SDVersion fallback); -#include - const char* model_version_to_str[] = { "SD 1.x", "SD 1.x Inpaint", @@ -921,10 +921,11 @@ class StableDiffusionGGML { if (is_chroma) { cond_stage_model = std::make_shared(backend_for(SDBackendModule::TE), tensor_storage_map, - sd_ctx_params->chroma_use_t5_mask, - sd_ctx_params->chroma_t5_mask_pad, false, - model_manager); + 1, + false, + model_manager, + sd_ctx_params->model_args); } else if (version == VERSION_OVIS_IMAGE) { cond_stage_model = std::make_shared(backend_for(SDBackendModule::TE), tensor_storage_map, @@ -941,8 +942,8 @@ class StableDiffusionGGML { tensor_storage_map, "model.diffusion_model", version, - sd_ctx_params->chroma_use_dit_mask, - model_manager); + model_manager, + sd_ctx_params->model_args); } else if (sd_version_is_flux2(version) || sd_version_is_sefi_image(version)) { bool is_chroma = false; cond_stage_model = std::make_shared(backend_for(SDBackendModule::TE), @@ -955,8 +956,8 @@ class StableDiffusionGGML { tensor_storage_map, "model.diffusion_model", version, - sd_ctx_params->chroma_use_dit_mask, - model_manager); + model_manager, + sd_ctx_params->model_args); } else if (sd_version_is_ltxav(version)) { cond_stage_model = std::make_shared(backend_for(SDBackendModule::TE), tensor_storage_map, @@ -1014,8 +1015,8 @@ class StableDiffusionGGML { tensor_storage_map, "model.diffusion_model", version, - sd_ctx_params->qwen_image_zero_cond_t, - model_manager); + model_manager, + sd_ctx_params->model_args); } else if (sd_version_is_longcat(version)) { cond_stage_model = std::make_shared(backend_for(SDBackendModule::TE), tensor_storage_map, @@ -1027,8 +1028,8 @@ class StableDiffusionGGML { tensor_storage_map, "model.diffusion_model", version, - sd_ctx_params->chroma_use_dit_mask, - model_manager); + model_manager, + sd_ctx_params->model_args); } else if (version == VERSION_HIDREAM_O1) { cond_stage_model = std::make_shared(backend_for(SDBackendModule::TE), tensor_storage_map, @@ -1364,7 +1365,6 @@ class StableDiffusionGGML { high_noise_diffusion_model->set_flash_attention_enabled(true); } } - } LOG_DEBUG("validating model metadata"); @@ -3048,15 +3048,13 @@ void sd_ctx_params_init(sd_ctx_params_t* sd_ctx_params) { sd_ctx_params->eager_load = false; sd_ctx_params->enable_mmap = false; sd_ctx_params->diffusion_flash_attn = false; - sd_ctx_params->chroma_use_dit_mask = true; - sd_ctx_params->chroma_use_t5_mask = false; - sd_ctx_params->chroma_t5_mask_pad = 1; sd_ctx_params->vae_format = SD_VAE_FORMAT_AUTO; sd_ctx_params->backend = nullptr; sd_ctx_params->params_backend = nullptr; sd_ctx_params->split_mode = nullptr; sd_ctx_params->auto_fit = false; sd_ctx_params->rpc_servers = nullptr; + sd_ctx_params->model_args = nullptr; sd_ctx_params->pulid_weights_path = nullptr; } @@ -3096,12 +3094,10 @@ char* sd_ctx_params_to_str(const sd_ctx_params_t* sd_ctx_params) { "backend: %s\n" "params_backend: %s\n" "split_mode: %s\n" + "model_args: %s\n" "auto_fit: %s\n" "flash_attn: %s\n" "diffusion_flash_attn: %s\n" - "chroma_use_dit_mask: %s\n" - "chroma_use_t5_mask: %s\n" - "chroma_t5_mask_pad: %d\n" "vae_format: %s\n", SAFE_STR(sd_ctx_params->model_path), SAFE_STR(sd_ctx_params->clip_l_path), @@ -3132,12 +3128,10 @@ char* sd_ctx_params_to_str(const sd_ctx_params_t* sd_ctx_params) { SAFE_STR(sd_ctx_params->backend), SAFE_STR(sd_ctx_params->params_backend), SAFE_STR(sd_ctx_params->split_mode), + SAFE_STR(sd_ctx_params->model_args), BOOL_STR(sd_ctx_params->auto_fit), BOOL_STR(sd_ctx_params->flash_attn), BOOL_STR(sd_ctx_params->diffusion_flash_attn), - BOOL_STR(sd_ctx_params->chroma_use_dit_mask), - BOOL_STR(sd_ctx_params->chroma_use_t5_mask), - sd_ctx_params->chroma_t5_mask_pad, sd_vae_format_name(sd_ctx_params->vae_format)); return buf;