Skip to content

Commit db44417

Browse files
jmroblesChema
andauthored
convert : apply Q/K RoPE permutation in NVFP4 repack path (ggml-org#22611)
Llama-architecture q_proj/k_proj weights need an axis-0 row permutation to match GGML's RoPE convention. The BF16 path applies this in LlamaModel.modify_tensors via LlamaModel.permute, but the NVFP4 path bypasses modify_tensors and writes weights directly through ModelBase._repack_nvfp4. Without the permutation, attention heads end up scrambled at inference and the model produces gibberish. This change overrides _repack_nvfp4 on LlamaModel and applies the same permutation to both the nibble-packed weight and the per-block scale before delegating to ModelBase._repack_nvfp4 via super(). Reuses the existing LlamaModel.permute static helper and respects the existing undo_permute flag, so subclasses (Mistral, Granite, Llama4, etc.) inherit the fix automatically. Verified on TinyLlama-1.1B reproducer: perplexity drops from 4419 (gibberish) to 43.9, matching the BF16-dequantized baseline (44.0). Also verified end-to-end on ALIA-40b-instruct-2601 (BSC, Llama architecture) with multilingual generation in Spanish/Catalan/Basque/ Galician all coherent with the fix applied. Co-authored-by: Chema <chema@montevive.ai>
1 parent d05fe1d commit db44417

1 file changed

Lines changed: 14 additions & 0 deletions

File tree

convert_hf_to_gguf.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2889,6 +2889,20 @@ def permute(weights: Tensor, n_head: int, n_head_kv: int | None):
28892889
.swapaxes(1, 2)
28902890
.reshape(weights.shape))
28912891

2892+
def _repack_nvfp4(self, name: str, weight: Tensor, scale: Tensor, scale2: Tensor, input_scale: Tensor):
2893+
# Mirror the BF16 Q/K RoPE permutation site in modify_tensors; the NVFP4 path bypasses it.
2894+
if self.undo_permute:
2895+
n_head = self.find_hparam(["n_heads", "num_attention_heads"], optional=True)
2896+
n_kv_head = self.find_hparam(["n_kv_heads", "num_key_value_heads"], optional=True)
2897+
if n_head is not None:
2898+
if name.endswith("q_proj.weight"):
2899+
weight = LlamaModel.permute(weight, n_head, n_head)
2900+
scale = LlamaModel.permute(scale, n_head, n_head)
2901+
elif name.endswith("k_proj.weight"):
2902+
weight = LlamaModel.permute(weight, n_head, n_kv_head)
2903+
scale = LlamaModel.permute(scale, n_head, n_kv_head)
2904+
super()._repack_nvfp4(name, weight, scale, scale2, input_scale)
2905+
28922906
_experts: list[dict[str, Tensor]] | None = None
28932907

28942908
def modify_tensors(self, data_torch: Tensor, name: str, bid: int | None) -> Iterable[tuple[str, Tensor]]:

0 commit comments

Comments
 (0)