Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions src-tauri/src/chat_manager/execution/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1197,6 +1197,24 @@ pub(super) fn resolve_llama_xtc_threshold(
.or(settings.advanced_model_settings.llama_xtc_threshold)
}

pub(super) fn resolve_llama_top_n_sigma(
session: &Session,
model: &Model,
settings: &Settings,
) -> Option<f64> {
session
.advanced_model_settings
.as_ref()
.and_then(|cfg| cfg.llama_top_n_sigma)
.or_else(|| {
model
.advanced_model_settings
.as_ref()
.and_then(|cfg| cfg.llama_top_n_sigma)
})
.or(settings.advanced_model_settings.llama_top_n_sigma)
}

pub(super) fn resolve_llama_adaptive_target(
session: &Session,
model: &Model,
Expand Down
9 changes: 7 additions & 2 deletions src-tauri/src/chat_manager/execution/provider_fields.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ use super::{
resolve_llama_sampler_order, resolve_llama_sampler_profile, resolve_llama_seed,
resolve_llama_single_gpu_device_id_leveled, resolve_llama_streaming_enabled,
resolve_llama_strict_mode, resolve_llama_swa_full, resolve_llama_threads,
resolve_llama_threads_batch, resolve_llama_ubatch_size, resolve_llama_xtc_probability,
resolve_llama_threads_batch, resolve_llama_top_n_sigma, resolve_llama_ubatch_size,
resolve_llama_xtc_probability,
resolve_llama_xtc_threshold, resolve_max_tokens, resolve_presence_penalty, resolve_temperature,
resolve_top_k, resolve_top_p,
};
Expand Down Expand Up @@ -191,6 +192,9 @@ fn build_llama_extra_fields(
if let Some(v) = resolve_llama_xtc_threshold(session, model, settings) {
extra.insert("llamaXtcThreshold".to_string(), json!(v));
}
if let Some(v) = resolve_llama_top_n_sigma(session, model, settings) {
extra.insert("llamaTopNSigma".to_string(), json!(v));
}
if let Some(v) = resolve_llama_adaptive_target(session, model, settings) {
extra.insert("llamaAdaptiveTarget".to_string(), json!(v));
}
Expand Down Expand Up @@ -261,6 +265,7 @@ mod tests {
llama_dry_sequence_breakers: Some(vec![":".to_string()]),
llama_xtc_probability: Some(0.5),
llama_xtc_threshold: Some(0.1),
llama_top_n_sigma: Some(1.5),
llama_adaptive_target: Some(0.3),
llama_adaptive_decay: Some(0.95),
..Default::default()
Expand Down Expand Up @@ -307,7 +312,7 @@ mod tests {
assert_eq!(extra.get("llamaNPenRange"), Some(&json!(64)));
assert_eq!(
extra.len(),
44,
45,
"unexpected llama extra-body key count; a resolver stopped emitting or a new field was added without updating this fixture: {:?}",
extra.keys().collect::<Vec<_>>()
);
Expand Down
2 changes: 2 additions & 0 deletions src-tauri/src/chat_manager/feature_generation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ impl FeatureGenerationSettings {
llama_n_pen_range: self.llama_n_pen_range,
llama_xtc_probability: self.llama_xtc_probability,
llama_xtc_threshold: self.llama_xtc_threshold,
llama_top_n_sigma: self.llama_top_n_sigma,
llama_dry_multiplier: self.llama_dry_multiplier,
llama_dry_base: self.llama_dry_base,
llama_dry_allowed_length: self.llama_dry_allowed_length,
Expand Down Expand Up @@ -124,6 +125,7 @@ impl FeatureGenerationSettings {
|| self.llama_n_pen_range.is_some()
|| self.llama_xtc_probability.is_some()
|| self.llama_xtc_threshold.is_some()
|| self.llama_top_n_sigma.is_some()
|| self.llama_dry_multiplier.is_some()
|| self.llama_dry_base.is_some()
|| self.llama_dry_allowed_length.is_some()
Expand Down
5 changes: 5 additions & 0 deletions src-tauri/src/chat_manager/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,8 @@ pub struct FeatureGenerationSettings {
#[serde(default)]
pub llama_xtc_threshold: Option<f64>,
#[serde(default)]
pub llama_top_n_sigma: Option<f64>,
#[serde(default)]
pub llama_adaptive_target: Option<f64>,
#[serde(default)]
pub llama_adaptive_decay: Option<f64>,
Expand Down Expand Up @@ -878,6 +880,8 @@ pub struct AdvancedModelSettings {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub llama_xtc_threshold: Option<f64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub llama_top_n_sigma: Option<f64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub llama_adaptive_target: Option<f64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub llama_adaptive_decay: Option<f64>,
Expand Down Expand Up @@ -1032,6 +1036,7 @@ impl Default for AdvancedModelSettings {
llama_dry_sequence_breakers: None,
llama_xtc_probability: None,
llama_xtc_threshold: None,
llama_top_n_sigma: None,
llama_adaptive_target: None,
llama_adaptive_decay: None,
llama_last_runtime_report: None,
Expand Down
8 changes: 5 additions & 3 deletions src-tauri/src/hf_browser/image_bundle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ fn to_search_result(detail: ApiModel) -> super::HfSearchResult {
fn vae_family_term(profile: &sdcpp::HfBundleProfile) -> &'static str {
if profile.id.starts_with("krea") {
"wan"
} else if profile.id == "qwen-image-edit-2511" {
} else if profile.id.starts_with("qwen-image") {
"qwen"
} else {
"flux"
Expand Down Expand Up @@ -453,10 +453,10 @@ fn role_compatible(profile: &sdcpp::HfBundleProfile, role: &str, model_id: &str,
match role {
"diffusion_model" => profile.diffusion_markers.iter().any(|marker| evidence.contains(marker)),
"text_encoder" => profile.encoder_markers.iter().any(|marker| evidence.contains(marker)),
"vision_encoder" => profile.id == "qwen-image-edit-2511"
"vision_encoder" => profile.id.starts_with("qwen-image")
&& (evidence.contains("mmproj") || evidence.contains("vision")),
"vae" if profile.id.starts_with("krea") => evidence.contains("wan") && evidence.contains("vae"),
"vae" if profile.id == "qwen-image-edit-2511" => evidence.contains("qwen") && evidence.contains("vae"),
"vae" if profile.id.starts_with("qwen-image") => evidence.contains("qwen") && evidence.contains("vae"),
"vae" => (evidence.contains("flux") || evidence.contains("ae.")) && (evidence.contains("vae") || evidence.contains("ae.")),
_ => false,
}
Expand All @@ -482,6 +482,8 @@ async fn gguf_architecture_hint(
[
"qwen2.5-vl-7b",
"qwen2.5vl-7b",
"qwen3-vl-8b",
"qwen3vl-8b",
"qwen3-vl-4b",
"qwen3vl-4b",
"qwen3-8b",
Expand Down
111 changes: 111 additions & 0 deletions src-tauri/src/image_generator/sdcpp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,80 @@ const QWEN_VARIANTS: &[VariantSpec] = &[
},
];

const QWEN21_SHARED: &[ComponentSpec] = &[
ComponentSpec {
role: "text_encoder",
repo: "unsloth/Qwen3-VL-8B-Instruct-GGUF",
revision: "b93a7ee713758252c555be4210c00540df954dc2",
filename: "Qwen3-VL-8B-Instruct-Q4_K_M.gguf",
bytes: 5_027_785_568,
sha256: "108e7ff92b78eefd3db4741885104acba514255c11b617d3c7b197a5f46efe89",
},
ComponentSpec {
role: "vision_encoder",
repo: "unsloth/Qwen3-VL-8B-Instruct-GGUF",
revision: "b93a7ee713758252c555be4210c00540df954dc2",
filename: "mmproj-BF16.gguf",
bytes: 1_162_569_280,
sha256: "6516bb64bae1503a0fcd7ec9fa39655f8c481580be0a0a066397941d9761c9f4",
},
ComponentSpec {
role: "vae",
repo: "Comfy-Org/Qwen-Image-2.1",
revision: "0217efd1d9c9452e84f6448903d6e21bfa171ffd",
filename: "vae/qwen_image_2.1_vae_bf16.safetensors",
bytes: 675_509_688,
sha256: "bb21f7473051e1ac368515dd3f2e15cd44d7a11748ee8823e1ddca3e4876b7c9",
},
];
const QWEN21_VARIANTS: &[VariantSpec] = &[
VariantSpec {
id: "q3-k",
label: "Q3 K (smaller)",
description: "Lower memory use with a modest quality tradeoff.",
recommended: false,
smaller: true,
diffusion: ComponentSpec {
role: "diffusion_model",
repo: "leejet/Qwen-Image-2.1-GGUF",
revision: "cc11433936a06e9765f7c0c0b1f0436cfd2b9856",
filename: "qwen_image_2.1-Q3_K.gguf",
bytes: 3_270_553_632,
sha256: "5a6352cb450d334ba17a9d18c7fd8c3e774799245b9da0f963ce0c6624deb758",
},
},
VariantSpec {
id: "q4-k",
label: "Q4 K (recommended)",
description: "Best default balance of image quality, speed, and memory.",
recommended: true,
smaller: false,
diffusion: ComponentSpec {
role: "diffusion_model",
repo: "leejet/Qwen-Image-2.1-GGUF",
revision: "cc11433936a06e9765f7c0c0b1f0436cfd2b9856",
filename: "qwen_image_2.1-Q4_K.gguf",
bytes: 4_197_494_816,
sha256: "29f9c83c249ff0292fb2943fceddfa2319b446601866c82a4f8be062abea72c2",
},
},
VariantSpec {
id: "q6-k",
label: "Q6 K (higher quality)",
description: "Higher precision with greater memory and storage use.",
recommended: false,
smaller: false,
diffusion: ComponentSpec {
role: "diffusion_model",
repo: "leejet/Qwen-Image-2.1-GGUF",
revision: "cc11433936a06e9765f7c0c0b1f0436cfd2b9856",
filename: "qwen_image_2.1-Q6_K.gguf",
bytes: 5_996_851_232,
sha256: "1c51d1a8e6cf2b215719dea0c4f0f4cbfff9214a1c7571e57913f57d6a9c3c12",
},
},
];

const PROFILES: &[ProfileSpec] = &[
ProfileSpec {
id: "z-image-turbo",
Expand Down Expand Up @@ -703,6 +777,26 @@ const PROFILES: &[ProfileSpec] = &[
variants: QWEN_VARIANTS,
shared_components: QWEN_SHARED,
},
ProfileSpec {
id: "qwen-image-2.1",
display_name: "Qwen Image 2.1",
family: "Qwen",
description: "Unified text-to-image and multi-reference editing with native transparency and strong in-image text rendering.",
license: "Qwen-Image Research License (non-commercial)",
source_url: "https://huggingface.co/Qwen/Qwen-Image-2.1",
supports_text_to_image: true,
supports_image_edit: true,
max_reference_images: Some(10),
requires_reference_image: false,
recommended_for_scenes: true,
default_width: 1024,
default_height: 1024,
default_steps: 35,
default_cfg: 6.0,
minimum_runtime_build: Some(883),
variants: QWEN21_VARIANTS,
shared_components: QWEN21_SHARED,
},
];

#[derive(Debug, Clone, Serialize)]
Expand Down Expand Up @@ -763,6 +857,11 @@ fn hf_profile_rules(profile: &ProfileSpec) -> (Vec<&'static str>, Vec<&'static s
vec!["qwen2.5-vl-7b", "qwen2.5vl-7b"],
7.0,
),
"qwen-image-2.1" => (
vec!["qwen-image-2.1", "qwen_image_2.1", "qwen-image-2-1", "qwen_image_2_1"],
vec!["qwen3-vl-8b", "qwen3vl-8b"],
8.0,
),
_ => (Vec::new(), Vec::new(), 0.0),
}
}
Expand Down Expand Up @@ -3852,6 +3951,7 @@ fn profile_lora_architecture(profile_id: Option<&str>) -> Option<&'static str> {
"flux-2-klein-9b" | "flux-2-klein-base-9b" => Some("flux2-klein-9b"),
"krea-2-turbo" | "krea-2-raw" => Some("krea-2"),
"qwen-image-edit-2511" => Some("qwen-image-edit-2511"),
"qwen-image-2.1" => Some("qwen-image-2.1"),
_ => None,
}
}
Expand Down Expand Up @@ -4882,6 +4982,13 @@ async fn ensure_server(
if let Some(params_backend_spec) = params_backend_spec {
command.arg("--params-backend").arg(params_backend_spec);
}
} else if runtime_build_number(&config.sdcpp_runtime_release)
.map_or(true, |build| build >= AUTO_FIT_VALUE_MIN_BUILD)
{
// stable-diffusion.cpp master-962 (PR #2132) turned --auto-fit into a
// value-taking option; older builds still expect the bare flag, and an
// unknown/non-numbered tag is treated as current.
command.arg("--auto-fit").arg("on");
} else {
command.arg("--auto-fit");
}
Expand Down Expand Up @@ -5832,6 +5939,10 @@ fn find_profile_variant(
Ok((profile, variant))
}

/// stable-diffusion.cpp build at which `--auto-fit` became a value-taking
/// option (`on`/`off`) instead of a bare flag (PR #2132, commit d763dae).
const AUTO_FIT_VALUE_MIN_BUILD: u32 = 962;

fn runtime_build_number(release: &str) -> Option<u32> {
release
.strip_prefix("master-")?
Expand Down
15 changes: 14 additions & 1 deletion src-tauri/src/llama_cpp/desktop/sampler.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use super::*;

pub(super) const DEFAULT_LLAMA_SAMPLER_PROFILE: &str = "balanced";
pub(super) const DEFAULT_LLAMA_SAMPLER_ORDER: [&str; 10] = [
pub(super) const DEFAULT_LLAMA_SAMPLER_ORDER: [&str; 11] = [
"penalties",
"grammar",
"top_k",
Expand All @@ -10,6 +10,7 @@ pub(super) const DEFAULT_LLAMA_SAMPLER_ORDER: [&str; 10] = [
"dry",
"typical",
"xtc",
"top_n_sigma",
"temp",
"adaptive_p",
];
Expand Down Expand Up @@ -44,6 +45,7 @@ pub(super) struct ResolvedSamplerConfig {
pub(super) dry_sequence_breakers: Option<Vec<String>>,
pub(super) xtc_probability: Option<f64>,
pub(super) xtc_threshold: Option<f64>,
pub(super) top_n_sigma: Option<f64>,
pub(super) frequency_penalty: Option<f64>,
pub(super) presence_penalty: Option<f64>,
pub(super) adaptive_target: Option<f64>,
Expand Down Expand Up @@ -176,6 +178,7 @@ fn normalize_sampler_stage(value: &str) -> Option<&'static str> {
"dry" => Some("dry"),
"typical" | "typ_p" | "typical_p" => Some("typical"),
"xtc" => Some("xtc"),
"top_n_sigma" | "top_nsigma" | "topnsigma" | "nsigma" => Some("top_n_sigma"),
"temp" | "temperature" => Some("temp"),
"adaptive_p" | "adaptivep" | "adaptive" => Some("adaptive_p"),
_ => None,
Expand Down Expand Up @@ -416,6 +419,10 @@ pub(super) fn build_sampler(
config.seed.unwrap_or_else(rand::random::<u32>),
)
});
let mut top_n_sigma_sampler = config.top_n_sigma.filter(|n| *n > 0.0).map(|n| {
active_params.insert("top_n_sigma".to_string(), json!(n));
LlamaSampler::top_n_sigma(n as f32)
});

let mut adaptive_requested = false;
for stage in requested_order {
Expand Down Expand Up @@ -468,6 +475,12 @@ pub(super) fn build_sampler(
samplers.push(sampler);
}
}
"top_n_sigma" => {
if let Some(sampler) = top_n_sigma_sampler.take() {
order.push("top_n_sigma");
samplers.push(sampler);
}
}
"temp" => {
if config.temperature > 0.0 {
order.push("temp");
Expand Down
8 changes: 8 additions & 0 deletions src-tauri/src/llama_cpp/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1298,6 +1298,13 @@ mod desktop {
.or_else(|| body.get("llamaXtcThreshold"))
.or_else(|| body.get("llama_xtc_threshold"))
.and_then(|v| v.as_f64());
let top_n_sigma = body
.get("top_n_sigma")
.or_else(|| body.get("topNSigma"))
.or_else(|| body.get("llamaTopNSigma"))
.or_else(|| body.get("llama_top_n_sigma"))
.and_then(|v| v.as_f64())
.filter(|v| *v > 0.0);
let adaptive_target = body
.get("adaptive_target")
.or_else(|| body.get("adaptiveTarget"))
Expand Down Expand Up @@ -3984,6 +3991,7 @@ mod desktop {
dry_sequence_breakers: dry_sequence_breakers.clone(),
xtc_probability,
xtc_threshold,
top_n_sigma,
frequency_penalty,
presence_penalty,
adaptive_target,
Expand Down
1 change: 1 addition & 0 deletions src-tauri/src/providers/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ fn supported_extra_body_keys(provider_id: &str) -> &'static [&'static str] {
"llamaDrySequenceBreakers",
"llamaXtcProbability",
"llamaXtcThreshold",
"llamaTopNSigma",
"llamaAdaptiveTarget",
"llamaAdaptiveDecay",
"llamaDisableSamplerProfileDefaults",
Expand Down
Loading
Loading