input_scale is for ACTIVATIONS, not weights. The correct NVFP4 weight
dequantization formula is: weight_bf16 = e2m1_value * block_scale * global_scale
Including input_scale made weights ~5000x too small, causing completely
garbled output (multilingual gibberish with repeating patterns).
- Add patches/deepseek_v4.py: patched vllm source file with modelopt NVFP4
weight name mappings (expert gate_proj→w1, mlp→ffn, self_attn→attn.mla_attn,
compressor.kv_proj→wkv, etc.), E2M1 FP4→BF16 unpacking for stacked params,
skip patterns for NVFP4 scale tensors on MergedColumnParallelLinear, and
resilient loading for unknown params.
- Update docker-compose.yml: copy patched deepseek_v4.py over original at
container startup, remove --moe-backend=deep_gemm_mega_moe (no NVFP4 kernel).
- Update patches/patch_vllm_weights.py: legacy runtime monkey-patch approach
(doesn't work with worker processes), kept for reference.
- Update README.md: added vLLM serving run history table (S1-S10), documented
all open issues (MergedColumnParallelLinear+NVFP4, no mega_moe kernel,
resilient loading), added vLLM-specific bug list and key notes.
- Update scripts/serve_vllm.py: add WARN comment on mega_moe flag.
- scripts/upcast_to_bf16.py: Converts mixed-precision V4 Pro to pure BF16
by upcasting all FP8 tensors (float8_e8m0fnu etc.) to bfloat16.
Needed because modelopt PTQ calibration crashes on Blackwell with FP8
kernels (DeepGEMM unsupported, Triton finegrained-fp8 has K mismatches).
- patches/patch_finegrained_fp8_blackwell.py: Patches transformers to
reject DeepGEMM on SM100+ (Blackwell), letting it fall back to Triton.
Note: the Triton fallback also fails during modelopt calibration on
quantized weights, so upcasting to BF16 is the working solution.
- Patch fixes iter_weights_for_calibration() for DeepseekV4Experts
(ModuleList quantizers vs singular)
- Run script uses official NVIDIA hf_ptq.py with FP8 source
- Documents flags to avoid (--low_memory_mode, wrong arg names)