File size: 3,169 Bytes
1a09ed0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
diff --git a/conversion/deepseek.py b/conversion/deepseek.py
index 817eb76..a49f27a 100644
--- a/conversion/deepseek.py
+++ b/conversion/deepseek.py
@@ -694,7 +694,11 @@ class DeepseekV4Model(TextModel):
 
         def dequant_fp8_weight(weight: Tensor, scale: Tensor) -> Tensor:
             out_features, in_features = weight.shape
-            scale_f = self._e8m0_to_float(scale)
+            # Lna-Lab 2026-09-09: Nex-N2.5-Max stores block scales as F32 values (ue8m0 semantics), not e8m0 bytes
+            if scale.dtype in (torch.float32, torch.float16, torch.bfloat16):
+                scale_f = scale.float()
+            else:
+                scale_f = self._e8m0_to_float(scale)
             scale_f = scale_f.repeat_interleave(128, 0)[:out_features]
             scale_f = scale_f.repeat_interleave(128, 1)[:, :in_features]
             return weight.float() * scale_f
@@ -780,6 +784,20 @@ class DeepseekV4Model(TextModel):
         for bid in range(self.block_count):
             if self.mtp_only and bid < main_layers:
                 continue
+            if f"layers.{bid}.ffn.experts.0.w1.weight" in self._dsv4_fp8_dequantized:
+                # Lna-Lab 2026-09-09: FP8 routed experts (Nex-N2.5-Max) -> stack per projection, no MXFP4 repack
+                n_experts = self.hparams["n_routed_experts"]
+                for proj in ("w1", "w2", "w3"):
+                    parts = []
+                    for eid in range(n_experts):
+                        wname = f"layers.{bid}.ffn.experts.{eid}.{proj}.weight"
+                        parts.append(self.model_tensors[wname]().to(torch.bfloat16))  # lazy: evaluated at write time
+                        consumed.append(wname)
+                    stacked_name = f"layers.{bid}.ffn.experts.{proj}.weight"
+                    self._dsv4_fp8_dequantized.add(stacked_name)
+                    logger.info(f"{stacked_name}: stacked {n_experts} FP8-dequantized experts")
+                    yield (stacked_name, torch.stack(parts, dim=0))
+                continue
             consumed.extend(self._write_mxfp4_expert_tensor(bid, "w1", gguf.MODEL_TENSOR.FFN_GATE_EXP))
             consumed.extend(self._write_mxfp4_expert_tensor(bid, "w2", gguf.MODEL_TENSOR.FFN_DOWN_EXP))
             consumed.extend(self._write_mxfp4_expert_tensor(bid, "w3", gguf.MODEL_TENSOR.FFN_UP_EXP))
@@ -857,6 +875,9 @@ class DeepseekV4Model(TextModel):
             "ffn.gate.bias": (gguf.MODEL_TENSOR.FFN_EXP_PROBS_B, ".bias"),
             "ffn.gate.bias_vl": (gguf.MODEL_TENSOR.FFN_EXP_PROBS_B_VL, ".bias"),
             "ffn.gate.tid2eid": (gguf.MODEL_TENSOR.FFN_GATE_TID2EID, ".weight"),
+            "ffn.experts.w1.weight": (gguf.MODEL_TENSOR.FFN_GATE_EXP, ".weight"),
+            "ffn.experts.w2.weight": (gguf.MODEL_TENSOR.FFN_DOWN_EXP, ".weight"),
+            "ffn.experts.w3.weight": (gguf.MODEL_TENSOR.FFN_UP_EXP, ".weight"),
             "ffn.shared_experts.w1.weight": (gguf.MODEL_TENSOR.FFN_GATE_SHEXP, ".weight"),
             "ffn.shared_experts.w2.weight": (gguf.MODEL_TENSOR.FFN_DOWN_SHEXP, ".weight"),
             "ffn.shared_experts.w3.weight": (gguf.MODEL_TENSOR.FFN_UP_SHEXP, ".weight"),