metrale_model_arch/weight_loader/
deepseek_v4.rs1mod assemble;
12mod attn_sink;
13mod compute;
14mod csa_ape;
15mod load_layers;
16pub mod mtp;
17pub(crate) use mtp::DeepseekV4MtpModule;
18
19use anyhow::{Context, Result};
20use metrale_cache::kv_cache::KvCacheDtype;
21use metrale_config::ModelConfig;
22use metrale_gpu_runtime::gpu::GpuBackend;
23use metrale_model_weights::weights::WeightStore;
24
25use super::ModelWeightLoader;
26use metrale_model_layers::layer::TransformerLayer;
27use metrale_model_layers::weight_map::quant_helpers::dense_auto;
28use metrale_model_layers::weight_map::{DenseWeight, MtpWeights, dense};
29
30pub struct DeepSeekV4WeightLoader;
31
32impl ModelWeightLoader for DeepSeekV4WeightLoader {
33 fn supports_tp(&self) -> bool {
34 false
35 }
36
37 fn load_layers(
38 &self,
39 store: &WeightStore,
40 config: &ModelConfig,
41 gpu: &dyn GpuBackend,
42 layer_kv_dtypes: &[KvCacheDtype],
43 ) -> Result<Vec<Box<dyn TransformerLayer>>> {
44 load_layers::load_all_layers(store, config, gpu, layer_kv_dtypes)
45 }
46
47 fn load_embedding(
48 &self,
49 store: &WeightStore,
50 _config: &ModelConfig,
51 _gpu: &dyn GpuBackend,
52 ) -> Result<DenseWeight> {
53 if let Ok(w) = dense(store, "embed.weight") {
54 return Ok(w);
55 }
56 if let Ok(w) = dense(store, "model.embed_tokens.weight") {
57 return Ok(w);
58 }
59 dense(store, "embed_tokens.weight")
60 .context("DeepSeek-V4: no embedding tensor found (tried embed.weight, model.embed_tokens.weight, embed_tokens.weight)")
61 }
62
63 fn load_final_norm(
64 &self,
65 store: &WeightStore,
66 _config: &ModelConfig,
67 _gpu: &dyn GpuBackend,
68 ) -> Result<DenseWeight> {
69 if let Ok(w) = dense_auto(store, "norm.weight", _gpu) {
73 return Ok(w);
74 }
75 if let Ok(w) = dense_auto(store, "model.norm.weight", _gpu) {
76 return Ok(w);
77 }
78 dense_auto(store, "final_norm.weight", _gpu)
79 .context("DeepSeek-V4: no final norm tensor found (tried norm.weight, model.norm.weight, final_norm.weight)")
80 }
81
82 fn load_lm_head(
83 &self,
84 store: &WeightStore,
85 config: &ModelConfig,
86 _gpu: &dyn GpuBackend,
87 ) -> Result<DenseWeight> {
88 if store.contains("lm_head.weight") {
89 return dense(store, "lm_head.weight");
90 }
91 if store.contains("output.weight") {
92 return dense(store, "output.weight");
93 }
94 if store.contains("head.weight") {
95 return dense(store, "head.weight");
96 }
97 if config.tie_word_embeddings
98 || store.contains("embed.weight")
99 || store.contains("model.embed_tokens.weight")
100 {
101 if let Ok(w) = dense(store, "embed.weight") {
102 return Ok(w);
103 }
104 if let Ok(w) = dense(store, "model.embed_tokens.weight") {
105 return Ok(w);
106 }
107 return dense(store, "embed_tokens.weight")
108 .context("DeepSeek-V4: tied lm_head — no embedding tensor found");
109 }
110 anyhow::bail!(
111 "DeepSeek-V4: lm_head not found (tried lm_head.weight, output.weight, head.weight, and tied embeddings)"
112 )
113 }
114
115 fn load_mtp_weights(
116 &self,
117 _store: &WeightStore,
118 _config: &ModelConfig,
119 _gpu: &dyn GpuBackend,
120 ) -> Result<Option<MtpWeights>> {
121 Ok(None)
122 }
123}