feat: support Nemotron-H / Nemotron-Cascade-2 (#1711)#1712
Conversation
615e3fe to
69f04b4
Compare
|
Thanks for the PR. Are all these file changes necessary? It seems to modify many unrelated files. |
|
|
||
| - **Residual-stream precision (`norm_dtype`):** | ||
|
|
||
| Opt-in kwarg on `quantize_and_save` / `save_quantized`. In deep residual architectures — especially hybrid SSM + MoE models such as Nemotron-H — accumulating residuals through BF16 norm outputs can lose precision layer over layer. Passing `norm_dtype="fp32"` exports norm weights in FP32 without touching quantized linears; disk/VRAM cost is <0.1% of a 30B model. Recommended for such hybrid architectures; optional elsewhere. Accepts `"fp16" | "bf16" | "fp32"` (string aliases) or a raw `torch.dtype`. Default (kwarg omitted): norm dtype follows the compute `amp_dtype` (FP16 on GPU/XPU with an FP16 checkpoint, BF16 on CPU/HPU). |
There was a problem hiding this comment.
For this case, we should provide a better solution, similar to e_score_correction_bias's handling in deepseek
@xin3he is it a regression as I just found the dtype of https://huggingface.co/Intel/DeepSeek-V3.2-int4-AutoRound/blob/main/model-00059-of-00071.safetensors if bf16
I'm afraid it is, but haven't optimized (reduced) much after I got coherent and stable output. Very welcome if we can reduce the number of changes, nemotron models seem to behave way different to others and are more sensitive to low dtypes. |
Thanks for the prompt reply. Could you let me know what indicator led you to change the norm dtype to FP32? I checked the model and noticed that the original norm weights are in BF16. I’m wondering whether modifying the norm dtype in the weights might cause issues with vLLM or SGLang, and whether they would still behave as expected. For MoE models, I would generally suggest using higher precision for certain parts, for example, 8-bit for critical components (non-moe modules) and 4-bit for others (experts). This is a more common approach when pure 4-bit quantization leads to a significant accuracy drop and avoids the API change. Please feel free to correct me if I’m mistaken, as I’m not very familiar with this model. Thanks again for your pr. |
|
for mixed-bits, you could try scheme="int4_mixed" |
Ah, I missed the proper documentation (I'll fix that tonight). You're right that the original norm weights are BF16, and BF16 is numerically fine for the norm weights themselves — upcasting them to FP32 is lossless but gains nothing at the weight level. The purpose of norm_dtype="fp32" is different: it's a lever for the residual stream, not for the norm weights. In HuggingFace-style RMSNorm the norm output's dtype follows the weight's dtype, so storing norm weights as FP32 pulls the post-norm tensor — and via the residual add, the residual stream itself — into FP32 at runtime. Over 50+ layers the residual is a sum of many block outputs, and keeping that accumulation in FP32 reduces BF16 rounding drift. Two caveats: this only helps on engines that honor the stored norm-weight dtype (HF transformers does, fused-kernel runtimes like vLLM/SGLang often don't). And the Nemotron-H coherence fix itself was not norm_dtype — it was the always-on post-load restore of the SSM core tensors and the router correction bias to FP32, which are the tensors with genuine FP32 requirements. norm_dtype is orthogonal and optional. So: FP32 norm weights aren't about upgrading the norm weights themselves — they're an export-side lever for residual-stream precision on compliant inference stacks. Please correct me, if I'm wrong. I'm new to the club and still in the learning phase ;). |
|
Progressing, the comments were helpful and can reduce the number of changes. |
a7e2f31 to
33313a9
Compare
|
I tried to remove everything not absolutely necessary (some fallbacks added), I ran a couple of autoround runs to verify the results (BF16 wasn't the actual issue, ignore that comment, the differences are neglectable). |
Hybrid Mamba2 + Attention + MoE via the unfused-MoE path: - register nemotron_h: LinearNemotronHMoE block_patch + MIXER_TYPES dispatch, backbone.* <-> model.* conversion mapping, post-load FP32 SSM/router and Zamba2 group_size fix-ups, bf16 out_proj scale default - ModelContext._load_model: run the registered post_load_fn after model load - missing_tensors: backbone.* <-> model.* trunk alias (avoid false-missing dup) - INT4 export: honor per-layer scale_dtype in packed buffers Signed-off-by: Michael Rabe <michaelrabe1896@gmail.com>
4400f1e to
837d2f2
Compare
Adds initial support for hybrid Mamba2 + Attention + MoE models via the unfused_moe registry. A bare
AutoRound("nvidia/...")call now produces a coherent INT4 checkpoint without launcher-side workarounds.Core additions:
unfused_moe/nemotron_h.py: linear-discoverable MoE blockunfused_moe/nemotron_h_setup.py: post-load fixups (Zamba2 group_size, SSM/router FP32 restore)utils/source_tensor_overrides.py: generic source-checkpoint tensor reload utilityMODEL_CONFIG["nemotron_h"]: dispatch + upstream-rename preservationcompressors/base.py:apply_post_load_fixupshook (non-NH no-op)norm_dtypeandscale_dtypeper-layer overridesDocumentation:
.claude/skills/adapt-unfused-moeskill covering the pipelineadapt-new-llmslimmed to point at the dedicated skillTests: 89 CPU tests across registration, post-load, export dtype controls, source-tensor overrides, and missing-tensors symmetry.
Closes #1711
Description
Please briefly describe your main changes, the motivation.
Type of Change
Related Issues
Fixes or relates to #
Checklist Before Submitting