metrale_model_layers/weight_map/
ssm_qwen35_more.rs1#![allow(unused_imports)]
9
10use anyhow::{Context, Result, bail, ensure};
11use metrale_gpu_runtime::gpu::{DevicePtr, GpuBackend};
12use metrale_model_weights::weights::{WeightDtype, WeightStore};
13
14use super::*;
15
16#[allow(clippy::too_many_arguments)]
27pub fn load_moe_minimax(
28 store: &WeightStore,
29 layer_prefix: &str,
30 num_experts: usize,
31 gpu: &dyn GpuBackend,
32 config: &metrale_config::ModelConfig,
33 variant: Nvfp4Variant,
34 absmax_k: metrale_gpu_runtime::gpu::KernelHandle,
35 quantize_k: metrale_gpu_runtime::gpu::KernelHandle,
36 stream: u64,
37) -> Result<MoeWeights> {
38 let p = format!("{layer_prefix}.block_sparse_moe");
39
40 let gate = dense_f32_safe(store, &format!("{p}.gate.weight"), gpu)?;
42 let bias_key = format!("{p}.e_score_correction_bias");
45 let bias_t = store.get(&bias_key)?;
46 let correction_bias = if bias_t.dtype == metrale_model_weights::weights::WeightDtype::BF16 {
47 let n = bias_t.num_elements();
48 let mut bf16_buf = vec![0u8; n * 2];
49 gpu.copy_d2h(bias_t.ptr, &mut bf16_buf)?;
50 let mut f32_buf = vec![0u8; n * 4];
51 for i in 0..n {
52 f32_buf[i * 4 + 2] = bf16_buf[i * 2];
54 f32_buf[i * 4 + 3] = bf16_buf[i * 2 + 1];
55 }
56 let ptr = gpu.alloc(f32_buf.len())?;
57 gpu.copy_h2d(&f32_buf, ptr)?;
58 DenseWeight { weight: ptr }
59 } else {
60 dense(store, &bias_key)?
61 };
62
63 let h = config.hidden_size;
68 let inter = config.moe_intermediate_size;
69 let group_size = 16usize;
70 let ceil_div = |n: usize, d: usize| -> usize { n.div_ceil(d) };
71 let gu_packed_bytes = (inter * h).div_ceil(2).max(1);
72 let gu_scale_bytes = (inter * ceil_div(h, group_size)).max(1);
73 let d_packed_bytes = (h * inter).div_ceil(2).max(1);
74 let d_scale_bytes = (h * ceil_div(inter, group_size)).max(1);
75
76 let alloc_zero = |size: usize| -> Result<DevicePtr> {
77 let sz = size.max(1);
78 let ptr = gpu.alloc(sz)?;
79 gpu.memset(ptr, 0, sz)?;
80 Ok(ptr)
81 };
82 let mk_zero_quant = |packed_sz: usize, scale_sz: usize| -> Result<QuantizedWeight> {
83 Ok(QuantizedWeight {
84 weight: alloc_zero(packed_sz)?,
85 weight_scale: alloc_zero(scale_sz)?,
86 weight_scale_2: 0.0,
87 input_scale: DevicePtr::NULL,
88 weight_scale_2_vec: DevicePtr::NULL,
89 act: metrale_config::Nvfp4Act::Unstamped,
90 })
91 };
92 let shared_expert = ExpertWeight {
93 gate_proj: mk_zero_quant(gu_packed_bytes, gu_scale_bytes)?,
94 up_proj: mk_zero_quant(gu_packed_bytes, gu_scale_bytes)?,
95 down_proj: mk_zero_quant(d_packed_bytes, d_scale_bytes)?,
96 };
97 let shared_expert_gate = DenseWeight {
98 weight: alloc_zero(h * 2)?,
99 };
100
101 let quant = |ep: &str, n: usize, k: usize| -> Result<QuantizedWeight> {
109 let is_compressed = store.contains(&format!("{ep}.weight_packed"));
112 let is_standard_nvfp4 = matches!(variant, Nvfp4Variant::Standard)
113 && store.contains(&format!("{ep}.weight_scale_2"));
114 if (matches!(
115 variant,
116 Nvfp4Variant::Standard | Nvfp4Variant::CompressedTensors
117 ) && is_compressed)
118 || is_standard_nvfp4
119 {
120 return quantized_auto(store, ep, gpu, variant);
121 }
122 let wkey = format!("{ep}.weight");
126 let scale_key = format!("{ep}.weight_scale_inv");
127 let (src_ptr, src_is_fp8) = {
128 let t = store.get(&wkey)?;
129 (
130 t.ptr,
131 t.dtype == metrale_model_weights::weights::WeightDtype::FP8E4M3,
132 )
133 };
134 let scale_ptr = if store.contains(&scale_key) {
135 Some(store.get(&scale_key)?.ptr)
136 } else {
137 None
138 };
139 let (dense_w, owned_bf16, need_free_src) = if scale_ptr.is_some() {
140 (dequant_fp8_blockscaled_to_bf16(store, ep, gpu)?, true, true)
141 } else {
142 (dense_auto(store, &wkey, gpu)?, src_is_fp8, src_is_fp8)
143 };
144 let nvfp4 = quantize_to_nvfp4(&dense_w, n, k, gpu, absmax_k, quantize_k, stream)?;
145 if owned_bf16 {
146 gpu.free(dense_w.weight)?;
147 }
148 if need_free_src {
149 gpu.free(src_ptr)?;
150 if let Some(sp) = scale_ptr {
151 gpu.free(sp)?;
152 }
153 }
154 Ok(nvfp4)
155 };
156 let inter_moe = config.moe_intermediate_size;
157 let mut experts = Vec::with_capacity(num_experts);
158 for e in 0..num_experts {
159 if config.is_local_expert(e) {
160 experts.push(ExpertWeight {
161 gate_proj: quant(&format!("{p}.experts.{e}.w1"), inter_moe, h)?,
162 down_proj: quant(&format!("{p}.experts.{e}.w2"), h, inter_moe)?,
163 up_proj: quant(&format!("{p}.experts.{e}.w3"), inter_moe, h)?,
164 });
165 } else {
166 experts.push(ExpertWeight::null());
167 }
168 }
169
170 Ok(MoeWeights {
171 gate,
172 shared_expert,
173 shared_expert_gate,
174 experts,
175 router_pre_norm: None,
176 correction_bias: Some(correction_bias),
177 })
178}
179
180pub fn load_moe_gemma4(
189 store: &WeightStore,
190 layer_prefix: &str,
191 num_experts: usize,
192 gpu: &dyn GpuBackend,
193 config: &metrale_config::ModelConfig,
194 variant: Nvfp4Variant,
195 qctx: QuantizeCtx,
196) -> Result<MoeWeights> {
197 let h = config.hidden_size;
198 let inter = config.moe_intermediate_size;
199
200 let gate_key = format!("{layer_prefix}.router.proj.weight");
201 let scale_key = format!("{layer_prefix}.router.scale");
202 let per_exp_key = format!("{layer_prefix}.router.per_expert_scale");
203
204 let gate_wt = store.get(&gate_key)?;
205 let gate_bytes = num_experts * h * 2;
206 let mut gate_buf = vec![0u8; gate_bytes];
207 gpu.copy_d2h(gate_wt.ptr, &mut gate_buf)?;
208
209 let router_pre_norm = if store.contains(&scale_key) {
212 let scale_wt = store.get(&scale_key)?;
213 let mut scale_buf = vec![0u8; h * 2];
214 gpu.copy_d2h(scale_wt.ptr, &mut scale_buf)?;
215 let scalar_root = 1.0f32 / (h as f32).sqrt();
216 for dim in 0..h {
217 let bits = u16::from_le_bytes([scale_buf[dim * 2], scale_buf[dim * 2 + 1]]);
218 let f = f32::from_bits((bits as u32) << 16) * scalar_root;
219 let out = (f.to_bits() >> 16) as u16;
220 scale_buf[dim * 2] = out as u8;
221 scale_buf[dim * 2 + 1] = (out >> 8) as u8;
222 }
223 let pre_norm_ptr = gpu.alloc(h * 2)?;
224 gpu.copy_h2d(&scale_buf, pre_norm_ptr)?;
225 tracing::info!("Gemma-4 MoE: router pre-norm weight = scale * hidden_size^(-0.5)");
226 Some(DenseWeight {
227 weight: pre_norm_ptr,
228 })
229 } else {
230 None
231 };
232
233 let gate_ptr = gpu.alloc(gate_bytes)?;
234 gpu.copy_h2d(&gate_buf, gate_ptr)?;
235 let gate = DenseWeight { weight: gate_ptr };
236
237 let group_size = 16usize;
238 let gu_packed = inter * h / 2;
239 let gu_scale = inter * (h / group_size);
240 let d_packed = h * inter / 2;
241 let d_scale = h * (inter / group_size);
242
243 let alloc_zero = |size: usize| -> Result<DevicePtr> {
244 let ptr = gpu.alloc(size)?;
245 gpu.memset(ptr, 0, size)?;
246 Ok(ptr)
247 };
248 let mk_zero = |p: usize, s: usize| -> Result<QuantizedWeight> {
249 Ok(QuantizedWeight {
250 weight: alloc_zero(p)?,
251 weight_scale: alloc_zero(s)?,
252 weight_scale_2: 0.0,
253 input_scale: DevicePtr::NULL,
254 weight_scale_2_vec: DevicePtr::NULL,
255 act: metrale_config::Nvfp4Act::Unstamped,
256 })
257 };
258 let shared_expert = ExpertWeight {
259 gate_proj: mk_zero(gu_packed, gu_scale)?,
260 up_proj: mk_zero(gu_packed, gu_scale)?,
261 down_proj: mk_zero(d_packed, d_scale)?,
262 };
263 let shared_expert_gate = DenseWeight {
264 weight: alloc_zero(h * 2)?,
265 };
266
267 let per_expert_scales: Vec<f32> = if store.contains(&per_exp_key) {
269 let per_exp_wt = store.get(&per_exp_key)?;
270 let mut buf = vec![0u8; num_experts * 2];
271 gpu.copy_d2h(per_exp_wt.ptr, &mut buf)?;
272 (0..num_experts)
273 .map(|e| {
274 let bits = u16::from_le_bytes([buf[e * 2], buf[e * 2 + 1]]);
275 f32::from_bits((bits as u32) << 16)
276 })
277 .collect()
278 } else {
279 vec![1.0f32; num_experts]
280 };
281
282 let mut experts = Vec::with_capacity(num_experts);
283 for e in 0..num_experts {
284 let ep = format!("{layer_prefix}.moe.experts.{e}");
285 if config.is_local_expert(e) {
286 let mut down = quantized_any(
287 store,
288 &format!("{ep}.down_proj"),
289 h,
290 inter,
291 gpu,
292 variant,
293 qctx,
294 )?;
295 down.weight_scale_2 *= per_expert_scales[e];
298 experts.push(ExpertWeight {
299 gate_proj: quantized_any(
300 store,
301 &format!("{ep}.gate_proj"),
302 inter,
303 h,
304 gpu,
305 variant,
306 qctx,
307 )?,
308 up_proj: quantized_any(
309 store,
310 &format!("{ep}.up_proj"),
311 inter,
312 h,
313 gpu,
314 variant,
315 qctx,
316 )?,
317 down_proj: down,
318 });
319 } else {
320 experts.push(ExpertWeight::null());
321 }
322 }
323
324 Ok(MoeWeights {
325 gate,
326 shared_expert,
327 shared_expert_gate,
328 experts,
329 router_pre_norm,
330 correction_bias: None,
331 })
332}