You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When loading a ModelOpt NVFP4 GGUF for NemotronHForCausalLM (the MoE variant, LLM_ARCH_NEMOTRON_H_MOE), the model generates repetitive garbage:
Prompt: "The capital of France is"
Output: "the capital of the United States.. The capital of the United States is the capital..."
The root cause is that nemotron-h.cpp's load_arch_tensors() creates the expert weight tensors (ffn_down_exps, ffn_up_exps, ffn_down_shexp, ffn_up_shexp) but never creates the corresponding scale tensors (ffn_up_exps_s, ffn_down_exps_s, ffn_up_shexp_s, ffn_down_shexp_s).
The graph code at build_ffn_layer() correctly passes these to build_moe_ffn() and build_ffn():
Since the pointers are NULL, build_moe_ffn and build_ffn skip the ggml_mul(res, w_s) step, leaving the NVFP4 expert outputs unscaled by the per-tensor scale2 factor. This produces wrong logits and the model degrades to repetitive output.
Additional converter fixes needed for Nemotron-H NVFP4
Two more bugs in convert_hf_to_gguf.py (already fixed locally):
NVFP4 detection: The code checks quant_algo == "NVFP4" but ModelOpt uses "W4A16_NVFP4" per-layer. Fixed with substring match: "NVFP4" in (v.get("quant_algo") or "").
FP8/NVFP4 routing in modelopt handler: The dequant_simple lambda was applied to ALL .weight_scale tensors, including NVFP4 expert tensors (uint8 weight with 2D E4M3 scale). This causes a broadcast error ([2688, 116] vs [2688, 928]). Fixed by checking w().dtype and skipping non-FP8 (uint8) weights.
Nemotron-H MoE: expert NVFP4 scale2 tensors not loaded — repetitive garbage output
Problem
When loading a ModelOpt NVFP4 GGUF for
NemotronHForCausalLM(the MoE variant,LLM_ARCH_NEMOTRON_H_MOE), the model generates repetitive garbage:The root cause is that
nemotron-h.cpp'sload_arch_tensors()creates the expert weight tensors (ffn_down_exps,ffn_up_exps,ffn_down_shexp,ffn_up_shexp) but never creates the corresponding scale tensors (ffn_up_exps_s,ffn_down_exps_s,ffn_up_shexp_s,ffn_down_shexp_s).The graph code at
build_ffn_layer()correctly passes these tobuild_moe_ffn()andbuild_ffn():Since the pointers are NULL,
build_moe_ffnandbuild_ffnskip theggml_mul(res, w_s)step, leaving the NVFP4 expert outputs unscaled by the per-tensor scale2 factor. This produces wrong logits and the model degrades to repetitive output.Model
nvidia/NVIDIA-Nemotron-3.5-Lightning-30B-A3B-NVFP4(ModelOpt W4A16_NVFP4, 128 routed experts + shared expert)convert_hf_to_gguf.pywith PR NVFP4: native load + quantize support, and fix vision with draft-mtp #70 (NVFP4 support) + fixes for W4A16_NVFP4 detectionblk.N.ffn_up_exps.scale,blk.N.ffn_down_exps.scale, etc.)Fix
Add
create_tensorcalls for the expert/shared-expert scale tensors inload_arch_tensors()insrc/models/nemotron-h.cpp:Workaround (converter-side)
I worked around this by baking the scale2 into the E4M3 per-sub-block scales during conversion:
ggml_mulis a no-op)With this workaround, the model generates correctly:
Environment
Additional converter fixes needed for Nemotron-H NVFP4
Two more bugs in
convert_hf_to_gguf.py(already fixed locally):NVFP4 detection: The code checks
quant_algo == "NVFP4"but ModelOpt uses"W4A16_NVFP4"per-layer. Fixed with substring match:"NVFP4" in (v.get("quant_algo") or "").FP8/NVFP4 routing in modelopt handler: The
dequant_simplelambda was applied to ALL.weight_scaletensors, including NVFP4 expert tensors (uint8 weight with 2D E4M3 scale). This causes a broadcast error ([2688, 116] vs [2688, 928]). Fixed by checkingw().dtypeand skipping non-FP8 (uint8) weights.