[DeepSeek-V4] Loading nvidia/DeepSeek-V4-Pro-NVFP4 crashes: 'Linear' object has no attribute 'weight_scale' in fused_a loader (MIXED_PRECISION attn excluded → built BF16 but stored as FP8)
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 14.7k
- Forks
- 2.8k
- Avg merge
- 2d 23h
- Merged PRs (30d)
- 489
Description
System / environment
- Images (both reproduce, empirically verified 2026-07-09):
nvcr.io/nvidia/tensorrt-llm/release:1.3.0rc15.post1and1.3.0rc20(NVIDIA Release 26.02, PyTorch 2.11.0a0). Note the DeepSeek-V4 model file was refactored between the two: inrc15.post1the loader lives in_torch/models/modeling_deepseekv4.py; inrc20it was folded into_torch/models/modeling_deepseekv3.py(there is nomodeling_deepseekv4.pyin rc20). The bug survives the refactor — see line refs for both below. - Hardware: single node, 8× B300. Failure is during weight loading (per-rank, at
Loading weights 0%), so it is hardware/parallelism independent — reproduces with TP4 and reproduces identically under both monolithictrtllm-serve serveand PD-disaggregated serving. - Checkpoint:
nvidia/DeepSeek-V4-Pro-NVFP4— the ModelOpt experts-only NVFP4 re-quantization (hf_quant_config.json→producer.version: "dsv4-nvfp4-experts").
Reproduce
trtllm-serve serve /path/to/DeepSeek-V4-Pro-NVFP4 \
--tp_size 4 --host 0.0.0.0 --port 8001
# crashes before serving, during model weight loading — no tokenizer/parser flags needed
# to reproduce. (In rc20 the `--tool_parser deepseek_v4` value was also removed; the valid
# set is deepseek_v3/deepseek_v31/deepseek_v32 — orthogonal to this bug.)
Actual behavior
File ".../tensorrt_llm/_torch/models/modeling_deepseekv4.py", line 1030, in load_weights
_copy_deepseek_v4_fused_a_weight_scale(module, fused_a, fused_a_scale)
File ".../tensorrt_llm/_torch/models/modeling_deepseekv4.py", line 240, in _copy_deepseek_v4_fused_a_weight_scale
if tuple(module.weight_scale.shape) == tuple(fused_a_scale.shape):
File ".../torch/nn/modules/module.py", line 1967, in __getattr__
raise AttributeError(...)
AttributeError: 'Linear' object has no attribute 'weight_scale'
Root cause (traced through the code)
This checkpoint is MIXED_PRECISION: only the routed MoE experts are NVFP4; the attention projections are stored as native DeepSeek block-scale FP8 — every layers.N.attn.{wq_a,wkv,wo_a,wo_b,wq_b} leaf carries both .weight (fp8) and .scale. Its hf_quant_config.json:
{
"producer": {"name": "modelopt", "version": "dsv4-nvfp4-experts"},
"quantization": {
"quant_algo": "MIXED_PRECISION",
"quantized_layers": { "layers.0.ffn.experts": {"quant_algo": "NVFP4", "group_size": 16}, "...": "... (61 layers)" },
"exclude_modules": ["*.attn.*", "*.ffn.shared_experts.*", "head", "mtp.*"]
}
}
- The attention Linears (
q_a_proj/kv_a_proj_with_mqa, and MTPe_proj/h_proj) are built withmodel_config.get_quant_config()called with noname(e.g.modeling_deepseekv4.py:2177/2185/2197/2208).ModelConfig.get_quant_config(name=None)returns the globalQuantConfig(model_config.py:249-250). - The per-layer table (
quantized_layers→per_layer_quant_configs) is consulted only when anameis passed, and raisesValueErroron a miss (model_config.py:252-254). In practice it is used only for the MoE experts (which are wired through a separateoverride_quant_config,modeling_deepseekv4.py:1467/1504). So nohf_quant_config.json/quant_cfg.jsonentry can reach the attention modules. - The global algo is
MIXED_PRECISION+exclude_modules: "*.attn.*"(matched viafnmatch,quantization/quantize.py:51) → the attn Linear is built unquantized (BF16), with noweight_scale. - In
load_weights,nvfp4_fused_aisFalse(attn weights are FP8, not FP4), so the code takes the else branch (~modeling_deepseekv4.py:1015-1032). That branch findskv_a_proj_with_mqa.weight_scale_invin the checkpoint and calls_copy_deepseek_v4_fused_a_weight_scale(module, fused_a, fused_a_scale), which dereferencesmodule.weight_scale→AttributeError.
Note the same branch also does module.weight.data.copy_(fused_a) where fused_a is the FP8 weight and module.weight is BF16 — i.e. even if the weight_scale access were guarded, the FP8 weight would be loaded into a BF16 module without applying the block scale, silently producing wrong values. The branch implicitly assumes the fused_a module is FP8_BLOCK_SCALES.
Expectation / suggested fix
When the fused_a target module is unquantized (excluded → BF16) but the checkpoint stores it as block-scale FP8, the else branch should dequantize (weight_dequant, already present at modeling_deepseekv4.py:97-147) the FP8 fused_a with its fused_a_scale and copy the resulting BF16 into module.weight, instead of copying the scale onto a non-existent module.weight_scale. (Equivalently: guard on hasattr(module, "weight_scale") and branch to dequant.)
What we ruled out
- Image version — reproduced on both
1.3.0rc15.post1and1.3.0rc20(empirically). rc20 refactored the V4 loader intomodeling_deepseekv3.pyand reworkedmodel_config.py, but still setsexclude_modulesfrom the HF quant config and crashes identically (rc20 crash sitemodeling_deepseekv3.py:~557). - PD-disaggregated vs monolithic — identical crash (both workers run
trtllm-serve serve; loading is the same code path). - Removing
*.attn.*fromexclude_modules— still crashes; under aMIXED_PRECISIONglobal there is no per-module algo for the now-un-excluded attn, so it is not built as FP8. - Missing
quant_cfg.json— neither the checkpoint nor the ModelOpt extended file exists in the repo; adding per-layer entries there cannot help, since attn queriesget_quant_config()without a name (point 2 above).
Additional note
The native DeepSeek checkpoint deepseek-ai/DeepSeek-V4-Pro (FP8 + MXFP4 routed experts; config-level quantization_config: {quant_method: fp8, weight_block_size: [128,128]}, no exclude_modules) loads and serves fine — verified end-to-end on rc15.post1, TP4 on 4× B300: weights load to 100%, Application startup complete, and chat completions generate correctly. Because the global algo is FP8_BLOCK_SCALES (not MIXED_PRECISION) and attn is not excluded, every attn Linear is built as FP8_BLOCK_SCALES and has a weight_scale. So TensorRT-LLM can serve DeepSeek-V4-Pro on this hardware; the crash is specific to the ModelOpt experts-only NVFP4 packaging (nvidia/DeepSeek-V4-Pro-NVFP4), where attn is exclude_modules'd (→ built BF16) yet physically stored as FP8 with a scale.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with load_weights and _copy_deepseek_v4_fused_a_weight_scale in _torch/models/modeling_deepseekv4.py for rc15.post1, then compare the corresponding path in modeling_deepseekv3.py for rc20. Read the existing weight_dequant helper and verify that loading nvidia/DeepSeek-V4-Pro-NVFP4 handles excluded BF16 attention modules without crashing or silently copying scaled FP8 values incorrectly.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python, pytorch
- Domain
- ai-infra-agents
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 48/100