Repository navigation
Conversation
…ion projections GLM-5.3-Flash builds its KDA, MLA and DSA-indexer projections with quant_config=None because they load as BF16 in every checkpoint, so online quantization requested with --quantization-config silently skipped them. Give them only the explicitly requested online config (bf16_projection_quant_config), keep kv_b_proj unquantized, and leave the --quantization shorthands on BF16 checkpoints unchanged. Add tests on real decoder layers. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Ao Tang <aot@nvidia.com>
suiyoubi
requested review from
AndreasKaratzas,
DarkLight1337 and
ywang96
as code owners
October 28, 2026 21:22
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Overview
GLM-5.3-Flash builds its BF16 attention projections (KDA, MLA, DSA indexer) with
quant_config=None, so online quantization requested with--quantization-config '{"targets": ...}'silently skips them. This PR passes them only that explicitly requested online config, so they can run in MXFP8. Related: #59833, #55741 (see Details).Claims
--quantization-confignames them. Onnvidia/GLM-5.3-Flash-NVFP4, the targets under Recommended configuration now quantize 196 layers (attention + shared experts) instead of 84 (shared experts only).--quantization-confignothing changes; the checkpoint's own method never applies to these BF16 weights;kv_b_projstays unquantized; the--quantization mxfp8/fp8_per_*shorthands keep these projections BF16, as today. No change to shared quantization code, no new flag.Validation
Unit tests
45 passed, 8 skipped (ROCm-only
test_sparse_indexer_topk_dispatchcases), on one NVIDIA Blackwell GPU. The branch is onmain@cdd2750cd; its Python tree was installed over thecu134-nightly-edad8b03image (no compiled code changed in between). CI selects these tests in theglm5next-unit-testsstep (pytest -v -s models/glm5next, H200; the MI355 mirror step runs them on ROCm).pre-commit(ruff, mypy, typos, test tethering) passes on the changed files.The new tests (
tests/models/glm5next/test_online_quantization.py, 12 cases, ~1 min on one GPU) build realGlm5NextDecoderLayers (KDA and sparse MLA) with a realVllmConfig. Only the sparse MLA attention backend is stubbed, since it depends on the GPU and is built after every projection. They check:targets, composed withlinear, pure onlinetargets, and the--quantization mxfp8shorthand, withkv_b_proj, the indexerwk_weights_projand the KDAconv1dalways unquantized;q_b_proj, andq_a_proj+kv_a_proj_with_mqa→fused_qkv_a_proj) loaded through_try_load_fp8_attn_projand the real weight loader give exactly the same online-MXFP8 parameters as loading their BF16 dequantization directly.On
mainwithout this change (same test file), the 8 cases where online quantization should reach attention fail, and the 4 no-change cases pass:End to end and performance (GB300)
nvidia/GLM-5.3-Flash-NVFP4(da920bb), upstream nightlyedad8b03with this branch'svllm/models/glm5nextmounted over the installed package (the stock nightly for the BF16 rows), Dynamo frontend, sa-bench random prompts (8K in / 1K out, all requests at once, concurrency-capped),--max-num-batched-tokens 32768(prefill / aggregated),--kernel-config '{"linear_backend_per_quant": {"mxfp8": "torch"}}'for the MXFP8 rows. These runs predate the rebase ontocdd2750cd; the commits in between change no compiled code, and the only one touching GLM-5.3 (#61457) affects AITER fused shared experts on ROCm. Every run completed all requests (0 failed), and the startup log showed the expectedQuantizing N layerscount (none on the BF16 rows and on the disaggregated decode instance).Aggregated, 1 node, DP2 + expert parallel (2 GPUs), 5,120 / 10,240 requests:
Disaggregated, 2 prefill instances (TP1, 1 GPU each) + 1 decode instance (DP2 + expert parallel), 4 GPUs on 2 nodes, NIXL KV transfer:
Single runs per point, so the sub-1% C128 / C256 disaggregated differences are not significant. At C512 the 2 prefill GPUs are the bottleneck (17.5 s TTFT), and faster prefill roughly halves TTFT and raises output throughput by 12%; decode step time is unchanged at C128 / C256 (TPOT 20.6 / 25.8 ms in both).
Accuracy
Setup:
nvidia/GLM-5.3-Flash-NVFP4(revisionda920bb), served with--quantization modelopt_fp4.mainnightly with this branch'sglm5nextpackage. The reference is the same nightly without the branch, so its projections are BF16. Only the--quantization-configtargets differ between the arms.Output length, paired by (problem, seed), both finished, ties excluded. Under BF16-vs-BF16 replicates, "shorter" stays near 50% (z within about ±1.5):
Broader coverage: all 196 on an earlier build (8 benchmarks + RULER 64K)
Same quantization path (
mxfp8_e4m3_quantizeplusTorchMxFp8LinearKernelon the same 196 layers, at every M, decode included) on a downstream build of the same model code. The reference is the same build with BF16 projections.Details
Why the projections were unreachable
GLM-5.3-Flash loads its attention projections as BF16 in every checkpoint:
in_proj_qkvbfg_a,f_b_proj,g_b_proj,o_proj;fused_qkv_a_proj,q_b_proj,o_proj;wq_b.The KDA and indexer projections are BF16 in every official checkpoint. The MLA projections are BF16 in the NVFP4 checkpoint and block-FP8 in the Z.ai FP8 checkpoint, which vLLM dequantizes to BF16 at load (
_try_load_fp8_attn_proj). The model therefore builds all of them with no quant config: MLA passesquant_config=None, and KDA clearsvllm_config.quant_configaround its constructor. With--quantization modelopt_fp4 --quantization-config '{"targets": {...}}', composition with the checkpoint method works for the shared-expert linears (84 layers) but silently skips the 112 attention projections. No warning is printed.What changes
bf16_projection_quant_config()in a new hardware-neutralvllm/models/glm5next/quant_config.py(following the model-levelquant_config.pyofdeepseek_v4/deepseek_v41) returns the config these projections get:--quantization-config(any form);--quantization online), that config only when it namestargets;None, as today.Layers that match no online target get
UnquantizedLinearMethod(existingOnlineQuantizationConfigbehavior), so the user picks the projections with thetargetsregex.kv_b_projis pinned toquant_config=None, because it is absorbed into the W_UK / W_UV bmm weights after loading. Loading is unchanged; the change is construction-time only, with no effect on the forward path when no target matches.The MLA attention module (
self_attn.attn) and the indexer now also receive the online config instead ofNone. The online config returns no method for non-linear layers, so the KV-cache scales stay at their defaults, as before. Atargetspattern that also matchesself_attn.attnis now rejected at startup ("online quantization is not supported for MLAAttention"), as for DeepSeek-V2, whose MLA attention already receives the quant config; before, it was silently ignored. The recommended patterns below name the projections, so they do not match it.vllm/models/glm5next/quant_config.pybf16_projection_quant_config()(32 lines)vllm/models/glm5next/common/model.pybf16_projection_quant_config(quant_config)instead ofNonevllm/models/glm5next/common/kda.pyvllm/models/glm5next/common/attention.pykv_b_projpinned toNonetests/models/glm5next/test_online_quantization.pyNo docs change: the projections now follow the existing contract in
docs/features/quantization/online.md("Online quantization on unquantized layers from partially-quantized checkpoints"). The GLM-5.3-Flash-specific recommendation stays in this description.Recommended configuration
All measurements use NVIDIA's NVFP4 checkpoint,
nvidia/GLM-5.3-Flash-NVFP4(revisionda920bb). Its routed experts and dense MLPs are NVFP4. The 196 projections studied are BF16:in_proj_qkvbfg_a,o_projfused_qkv_a_proj,q_b_proj,o_proj,indexer.wq_bgate_up_proj,down_projWe tested MXFP8 (E4M3 values, one E8M0 scale per 32 elements, for weights and dynamic activations). Accuracy holds in every configuration. However, MXFP8 on the 68 KDA in/out projections at decode measurably changes reasoning behavior: traces get 20-30% shorter on AIME/GPQA, with fewer hesitation and self-correction tokens, and accuracy on hard long-output problems trends lower (not significant). The other 128 projections leave behavior unchanged.
wq_b, shared expert); KDA in/out stay BF16in_proj_qkvbfg_a(4096 → 24,896), so excluding the KDA projections keeps only part of the gain in aggregated serving (+2% instead of +8% on GB300).--kernel-config '{"linear_backend_per_quant": {"mxfp8": "torch"}}'). On SM10x, the automatic choice (FlashInfer CuTe-DSL) was markedly slower for these shapes at large M. The kernel priority is a separate follow-up.Commands for the NVFP4 checkpoint. Each regex covers layers 0-44, so the MTP layer (45) is excluded; the K=128 KDA gate projections,
kv_b_proj, the indexerwk_weights_projand the dense MLPs never match.Non-KDA, 128 layers (aggregated; behavior-preserving). The MLA layer indices are those of the released 45-layer config:
All 196 (prefill instances of a disaggregated deployment; or the disclosed aggregated opt-in):
The startup log confirms the coverage, e.g.
Quantizing 196 layers of types: ... self_attn.in_proj_qkvbfg_a: 34, self_attn.o_proj: 45, ...(128 layers for the non-KDA regex).Other checkpoints and other FP8 schemes
Other checkpoints (static analysis; only the NVFP4 checkpoint was run):
mlp.shared_expertsalternative (44 or 112 attention layers). With it, those checkpoint methods cannot re-quantize (nodequantize_weight) and loading fails, as onmain. For the FP8 checkpoint, the MLA weights go FP8 → BF16 (load-time dequant) → MXFP8.zai-org/GLM-5.3-Flash-BF16)--quantization online;--quantization-configalone is ignored (existing behavior)--quantization-configdoes not reach the MTP draft today (existing behavior), so the MTP layer keeps the checkpoint method. If #49900 lands, the regexes above still exclude layer 45.fp8_per_tensoruses per-token activation scales on CUTLASS-capable GPUs and does not have this coupling; we did not evaluate it.fp8_per_channel) on all 196 mostly avoids the behavior change but also keeps only a small part of the throughput gain, so it offers nothing over the non-KDA MXFP8 config.Limitations
RocmDotScaledMxfp8LinearKernel) and is untested.AI assistance
This change was prepared with AI assistance (Claude Code). The submitter reviewed every changed line and ran the tests above.
Pull Request Checklist
I used vLLM's
/pr-checklistskill. (Mandatory for agents, optional for humans).AI assistance was used during the creation of this PR.
Design Fit: Minimizes impact on core components, reuses existing functionality, and justifies added complexity.
Testing and Validation: Validates the change and ensures any added tests are meaningful and reliable, with CI coverage or documented CI resource constraints and validation performed outside CI.
Code Quality and Style: Keeps code and comments clear and concise, and updates relevant documentation and examples.
Pull Request Contents: Includes a brief summary and relevant links, supports claims with evidence, explains root causes and implementation trade-offs, and follows the contributing guide.
🤖 Generated with Claude Code