feat: DeepSeek V4 Flash 0731 added

This commit is contained in:
Georg Bauer
2026-08-01 08:40:06 +02:00
parent 4175706533
commit d1c380f79d
7 changed files with 85 additions and 21 deletions

View File

@@ -2566,6 +2566,7 @@ mod tests {
Some(Message::FocusPrevious)
));
assert!(ModelChoice::DeepSeekV4Flash.supports_dspark());
assert!(!ModelChoice::DeepSeekV4Flash0731.supports_dspark());
assert!(!ModelChoice::DeepSeekV4Pro.supports_dspark());
assert!(!ModelChoice::Glm52.supports_dspark());
}

View File

@@ -150,6 +150,11 @@ const FLASH: Shape = Shape {
original_context: 65_536,
};
const FLASH_0731: Shape = Shape {
model: ModelChoice::DeepSeekV4Flash0731,
..FLASH
};
const PRO: Shape = Shape {
model: ModelChoice::DeepSeekV4Pro,
layers: 61,

View File

@@ -1985,7 +1985,7 @@ impl SsdPlan {
let mut by_layer = vec![Vec::<(i32, u32)>::new(); model.shape.layers as usize];
let mut loaded = 0_u32;
let hotlist = match model.shape.model {
ModelChoice::DeepSeekV4Flash => hotlist::FLASH,
ModelChoice::DeepSeekV4Flash | ModelChoice::DeepSeekV4Flash0731 => hotlist::FLASH,
ModelChoice::DeepSeekV4Pro => hotlist::PRO,
ModelChoice::Glm52 => unreachable!("GLM uses its dedicated executor"),
};
@@ -3437,8 +3437,10 @@ impl DeepSeekExecutor {
if self.session.position == 0 && self.ssd.is_some() {
unsafe { ds4_gpu_stream_expert_cache_reset_route_hotness() };
}
let streaming_decode_cap = if self.model.shape.model == ModelChoice::DeepSeekV4Flash
&& self.weights.layers.first().is_some_and(|layer| {
let streaming_decode_cap = if matches!(
self.model.shape.model,
ModelChoice::DeepSeekV4Flash | ModelChoice::DeepSeekV4Flash0731
) && self.weights.layers.first().is_some_and(|layer| {
layer.expert_gate.kind == Q4_K
&& layer.expert_up.kind == Q4_K
&& layer.expert_down.kind == Q4_K
@@ -6469,16 +6471,23 @@ fn update_compressor_stage(
fn compression_ratio(shape: super::Shape, layer: u32) -> u32 {
match shape.model {
crate::model::ModelChoice::DeepSeekV4Flash if layer < 2 => 0,
crate::model::ModelChoice::DeepSeekV4Flash
| crate::model::ModelChoice::DeepSeekV4Flash0731
if layer < 2 =>
{
0
}
crate::model::ModelChoice::DeepSeekV4Pro if layer < 2 => 128,
crate::model::ModelChoice::DeepSeekV4Flash | crate::model::ModelChoice::DeepSeekV4Pro
crate::model::ModelChoice::DeepSeekV4Flash
| crate::model::ModelChoice::DeepSeekV4Flash0731
| crate::model::ModelChoice::DeepSeekV4Pro
if layer.is_multiple_of(2) =>
{
4
}
crate::model::ModelChoice::DeepSeekV4Flash | crate::model::ModelChoice::DeepSeekV4Pro => {
128
}
crate::model::ModelChoice::DeepSeekV4Flash
| crate::model::ModelChoice::DeepSeekV4Flash0731
| crate::model::ModelChoice::DeepSeekV4Pro => 128,
crate::model::ModelChoice::Glm52 => 0,
}
}

View File

@@ -223,10 +223,11 @@ pub(super) fn validate_main(model: &Gguf, expected: ModelChoice) -> Result<Shape
};
let shape = match family {
ModelFamily::Glm => GLM,
ModelFamily::DeepSeek => match model.u32("deepseek4.block_count")? {
43 => FLASH,
61 => PRO,
layers => return Err(format!("unsupported DeepSeek layer count: {layers}")),
ModelFamily::DeepSeek => match (model.u32("deepseek4.block_count")?, expected) {
(43, ModelChoice::DeepSeekV4Flash0731) => FLASH_0731,
(43, _) => FLASH,
(61, _) => PRO,
(layers, _) => return Err(format!("unsupported DeepSeek layer count: {layers}")),
},
};
if shape.model != expected {
@@ -993,10 +994,18 @@ fn float_eq(actual: f32, expected: f32) -> bool {
fn compression_ratio(shape: &Shape, layer: u32) -> u32 {
match shape.model {
ModelChoice::DeepSeekV4Flash if layer < 2 => 0,
ModelChoice::DeepSeekV4Flash | ModelChoice::DeepSeekV4Flash0731 if layer < 2 => 0,
ModelChoice::DeepSeekV4Pro if layer < 2 => 128,
ModelChoice::DeepSeekV4Flash | ModelChoice::DeepSeekV4Pro if layer.is_multiple_of(2) => 4,
ModelChoice::DeepSeekV4Flash | ModelChoice::DeepSeekV4Pro => 128,
ModelChoice::DeepSeekV4Flash
| ModelChoice::DeepSeekV4Flash0731
| ModelChoice::DeepSeekV4Pro
if layer.is_multiple_of(2) =>
{
4
}
ModelChoice::DeepSeekV4Flash
| ModelChoice::DeepSeekV4Flash0731
| ModelChoice::DeepSeekV4Pro => 128,
ModelChoice::Glm52 => 0,
}
}

View File

@@ -847,6 +847,7 @@ fn model_code(model: ModelChoice) -> u8 {
ModelChoice::DeepSeekV4Flash => 1,
ModelChoice::DeepSeekV4Pro => 2,
ModelChoice::Glm52 => 3,
ModelChoice::DeepSeekV4Flash0731 => 4,
}
}
@@ -855,6 +856,7 @@ fn model_name(value: u8) -> &'static str {
1 => "DeepSeek V4 Flash",
2 => "DeepSeek V4 Pro",
3 => "GLM 5.2",
4 => "DeepSeek V4 Flash 0731",
_ => "No model loaded",
}
}

View File

@@ -9,20 +9,23 @@ use std::fmt;
use std::fs;
use std::path::{Path, PathBuf};
pub(crate) const MODEL_CHOICES: [ModelChoice; 3] = [
pub(crate) const MODEL_CHOICES: [ModelChoice; 4] = [
ModelChoice::DeepSeekV4Flash,
ModelChoice::DeepSeekV4Flash0731,
ModelChoice::DeepSeekV4Pro,
ModelChoice::Glm52,
];
pub(crate) const MANAGED_ARTIFACTS: [ManagedArtifactId; 5] = [
pub(crate) const MANAGED_ARTIFACTS: [ManagedArtifactId; 6] = [
ManagedArtifactId::DeepSeekV4Flash,
ManagedArtifactId::DeepSeekV4FlashMtp,
ManagedArtifactId::DeepSeekV4FlashDspark,
ManagedArtifactId::DeepSeekV4Flash0731,
ManagedArtifactId::DeepSeekV4Pro,
ManagedArtifactId::Glm52,
];
const DEEPSEEK_REPOSITORY: &str = "antirez/deepseek-v4-gguf";
const DEEPSEEK_FLASH_0731_REPOSITORY: &str = "Rednalreden/DeepSeek-V4-Flash-0731-dwarfstar-q2-gguf";
const GLM_REPOSITORY: &str = "antirez/glm-5.2-gguf";
const FLASH: Artifact = Artifact {
@@ -49,6 +52,14 @@ const FLASH_MTP: Artifact = Artifact {
sha256: "afd481ee689dce9037f70f39085fcdae5a5b096d521cdad43b19fa52bf8f4083",
support: Some(true),
};
const FLASH_0731: Artifact = Artifact {
label: "DeepSeek V4 Flash 0731 model",
file_name: "DeepSeek-V4-Flash-0731-IQ2XXS-w2Q2K-AProjQ8-SExpQ8-OutQ8-imatrix.gguf",
repository: DEEPSEEK_FLASH_0731_REPOSITORY,
size: 86_720_111_520,
sha256: "0b39f9c337d6b49c77db2190556b8563abf3c5fbb98be3b58cf8d3a1db191e5f",
support: Some(false),
};
const PRO: Artifact = Artifact {
label: "DeepSeek V4 Pro model",
file_name: "DeepSeek-V4-Pro-IQ2XXS-w2Q2K-AProjQ8-SExpQ8-OutQ8-Instruct-imatrix.gguf",
@@ -71,6 +82,8 @@ pub(crate) enum ModelChoice {
#[default]
#[serde(rename = "deepseek-v4-flash")]
DeepSeekV4Flash,
#[serde(rename = "deepseek-v4-flash-0731")]
DeepSeekV4Flash0731,
#[serde(rename = "deepseek-v4-pro")]
DeepSeekV4Pro,
#[serde(rename = "glm-5.2")]
@@ -81,6 +94,7 @@ impl ModelChoice {
pub(crate) fn id(self) -> &'static str {
match self {
Self::DeepSeekV4Flash => "deepseek-v4-flash",
Self::DeepSeekV4Flash0731 => "deepseek-v4-flash-0731",
Self::DeepSeekV4Pro => "deepseek-v4-pro",
Self::Glm52 => "glm-5.2",
}
@@ -97,6 +111,7 @@ impl ModelChoice {
fn main_artifact(self) -> &'static Artifact {
match self {
Self::DeepSeekV4Flash => &FLASH,
Self::DeepSeekV4Flash0731 => &FLASH_0731,
Self::DeepSeekV4Pro => &PRO,
Self::Glm52 => &GLM,
}
@@ -147,6 +162,7 @@ pub(crate) enum ManagedArtifactId {
DeepSeekV4Flash,
DeepSeekV4FlashMtp,
DeepSeekV4FlashDspark,
DeepSeekV4Flash0731,
DeepSeekV4Pro,
Glm52,
}
@@ -157,6 +173,7 @@ impl ManagedArtifactId {
Self::DeepSeekV4Flash | Self::DeepSeekV4FlashMtp | Self::DeepSeekV4FlashDspark => {
ModelChoice::DeepSeekV4Flash
}
Self::DeepSeekV4Flash0731 => ModelChoice::DeepSeekV4Flash0731,
Self::DeepSeekV4Pro => ModelChoice::DeepSeekV4Pro,
Self::Glm52 => ModelChoice::Glm52,
}
@@ -167,6 +184,7 @@ impl ManagedArtifactId {
Self::DeepSeekV4Flash => &FLASH,
Self::DeepSeekV4FlashMtp => &FLASH_MTP,
Self::DeepSeekV4FlashDspark => &FLASH_DSPARK,
Self::DeepSeekV4Flash0731 => &FLASH_0731,
Self::DeepSeekV4Pro => &PRO,
Self::Glm52 => &GLM,
}
@@ -261,6 +279,7 @@ impl fmt::Display for ModelChoice {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str(match self {
Self::DeepSeekV4Flash => "DeepSeek V4 Flash",
Self::DeepSeekV4Flash0731 => "DeepSeek V4 Flash 0731",
Self::DeepSeekV4Pro => "DeepSeek V4 Pro",
Self::Glm52 => "GLM 5.2",
})

View File

@@ -325,17 +325,31 @@ mod tests {
#[test]
fn catalog_and_checksum_verification_are_explicit() {
assert_eq!(ModelChoice::from_id("glm-5.2"), Some(ModelChoice::Glm52));
assert_eq!(
ModelChoice::from_id("deepseek-v4-flash-0731"),
Some(ModelChoice::DeepSeekV4Flash0731)
);
assert!(ModelChoice::from_id("unknown").is_none());
assert_eq!(
ModelChoice::DeepSeekV4Flash.main_artifact().size,
86_720_111_488
);
assert_eq!(ModelChoice::Glm52.main_artifact().size, 211_075_856_448);
assert_eq!(
ModelChoice::DeepSeekV4Flash0731.main_artifact().size,
86_720_111_520
);
assert_eq!(
ModelChoice::DeepSeekV4Flash.artifacts(true, true).count(),
3
);
assert_eq!(ModelChoice::Glm52.artifacts(true, true).count(), 1);
assert_eq!(
ModelChoice::DeepSeekV4Flash0731
.artifacts(true, true)
.count(),
1
);
let id = SystemTime::now()
.duration_since(UNIX_EPOCH)
@@ -351,6 +365,11 @@ mod tests {
engine.mtp.as_deref().and_then(Path::file_name),
Some(std::ffi::OsStr::new(FLASH_DSPARK.file_name))
);
assert!(
engine_artifacts(ModelChoice::DeepSeekV4Flash0731, true, true, &models_path)
.mtp
.is_none()
);
let empty = Artifact {
label: "empty",
file_name: "empty",