Fix conversion of fused qkvz & FP8 for Qwen3-Next

This commit is contained in:
Oliver Simons
2026-10-09 21:06:17 +02:00
parent 2a29ae5db2
commit ae7e0bf54e
3 changed files with 19 additions and 6 deletions
+7 -4
View File
@@ -620,6 +620,9 @@ class ModelBase:
def _transform_fp8_scale(self, name: str, scale: Tensor) -> Tensor: def _transform_fp8_scale(self, name: str, scale: Tensor) -> Tensor:
return scale return scale
def _map_fp8_weight_names(self, name: str) -> tuple[str, ...]:
return (self.map_tensor_name(name),)
def _prepare_fp8_e4m3_tensors(self): def _prepare_fp8_e4m3_tensors(self):
if self._fp8_as_q8: if self._fp8_as_q8:
return return
@@ -686,10 +689,10 @@ class ModelBase:
assert isinstance(entries, list) assert isinstance(entries, list)
cast(list[tuple[int, float]], entries).append((expert_id, float(input_scale[0]))) cast(list[tuple[int, float]], entries).append((expert_id, float(input_scale[0])))
else: else:
new_name = self.map_tensor_name(weight_name) for new_name in self._map_fp8_weight_names(weight_name):
scale_tensors[new_name.replace(".weight", ".scale")] = scale.numpy() scale_tensors[new_name.replace(".weight", ".scale")] = scale.numpy()
if input_scale is not None: if input_scale is not None:
input_scale_tensors[new_name.replace(".weight", ".input_scale")] = input_scale.numpy() input_scale_tensors[new_name.replace(".weight", ".input_scale")] = input_scale.numpy()
for name in consumed: for name in consumed:
self.model_tensors.pop(name, None) self.model_tensors.pop(name, None)
+10
View File
@@ -373,6 +373,16 @@ class _QwenMtpMixin:
class Qwen3NextModel(_QwenMtpMixin, Qwen2MoeModel): class Qwen3NextModel(_QwenMtpMixin, Qwen2MoeModel):
model_arch = gguf.MODEL_ARCH.QWEN3NEXT model_arch = gguf.MODEL_ARCH.QWEN3NEXT
def _map_fp8_weight_names(self, name: str) -> tuple[str, ...]:
if name.endswith(".linear_attn.in_proj_qkvz.weight"):
bid = next(int(part) for part in self.map_tensor_name(name).split(".") if part.isdecimal())
# Both split projections keep the original per-tensor scales.
return (
self.format_tensor_name(gguf.MODEL_TENSOR.ATTN_QKV, bid),
self.format_tensor_name(gguf.MODEL_TENSOR.ATTN_GATE, bid),
)
return super()._map_fp8_weight_names(name)
def set_gguf_parameters(self): def set_gguf_parameters(self):
super().set_gguf_parameters() super().set_gguf_parameters()
self.gguf_writer.add_ssm_conv_kernel(self.hparams["linear_conv_kernel_dim"]) self.gguf_writer.add_ssm_conv_kernel(self.hparams["linear_conv_kernel_dim"])
+2 -2
View File
@@ -324,11 +324,11 @@ std::pair<ggml_tensor *, ggml_tensor *> llama_model_qwen3next::graph::build_qkvz
if (model.layers[il].wqkv) { if (model.layers[il].wqkv) {
// optimized path // optimized path
ggml_tensor * qkv_mixed = build_lora_mm(model.layers[il].wqkv, input); ggml_tensor * qkv_mixed = build_lora_mm(model.layers[il].wqkv, input, model.layers[il].wqkv_s);
qkv_mixed = ggml_reshape_3d(ctx0, qkv_mixed, qkv_mixed->ne[0], n_seq_tokens, n_seqs); qkv_mixed = ggml_reshape_3d(ctx0, qkv_mixed, qkv_mixed->ne[0], n_seq_tokens, n_seqs);
cb(qkv_mixed, "linear_attn_qkv_mixed", il); cb(qkv_mixed, "linear_attn_qkv_mixed", il);
ggml_tensor * z = build_lora_mm(model.layers[il].wqkv_gate, input); ggml_tensor * z = build_lora_mm(model.layers[il].wqkv_gate, input, model.layers[il].wqkv_gate_s);
cb(z, "z", il); cb(z, "z", il);
return { qkv_mixed, z }; return { qkv_mixed, z };