Repository navigation
[Quantization] Anchor should_convert_module regex to stop prefix-matching siblings - #47990
Ilya-a-sergeyev-ger wants to merge 1 commit into
Conversation
|
[For maintainers] Suggested jobs to run (before merge) run-slow: mxfp4 |
…hing siblings
`re.match(f"{key}", full_name)` was unanchored, so a `modules_to_not_convert`
entry like `mlp.gate` also matched `mlp.gate_proj`, leaving it a plain
nn.Linear with FP8 weights -> "mat1 BFloat16 != mat2 Float8_e4m3fn" on
finegrained-fp8 MoE checkpoints. Anchor with `$`; exact and `layer.*`
wildcards still match.
Co-Authored-By: Claude <noreply@anthropic.com>
8427f37 to
30c295f
Compare
CI recapDashboard: View test results in Grafana |
… and tokenizer boundary fixes Preserve the upstream Qwen parser/streaming-engine and tokenizer corrections as attributed source patches. Keep parser state, configuration and token handling together so the integration can validate the complete compatible source set. Provenance Upstream PRs and authors: - vllm-project/vllm#56113 — Svliverse-1 - vllm-project/vllm#56661 — JordiPosthumus - huggingface/transformers#45422 — qgallouedec - huggingface/transformers#47855 — ameerhmz - huggingface/transformers#47990 — Ilya-a-sergeyev-ger - huggingface/transformers#48708 — albertvillanova
… and tokenizer boundary fixes Preserve the upstream Qwen parser/streaming-engine and tokenizer corrections as attributed source patches. Keep parser state, configuration and token handling together so the integration can validate the complete compatible source set. Provenance Upstream PRs and authors: - vllm-project/vllm#56113 — Svliverse-1 - vllm-project/vllm#56661 — JordiPosthumus - huggingface/transformers#45422 — qgallouedec - huggingface/transformers#47855 — ameerhmz - huggingface/transformers#47990 — Ilya-a-sergeyev-ger - huggingface/transformers#48708 — albertvillanova
|
hey, thanks for the report and the repro! the |
…uggingface#49771) * Match a skip-list entry from the start only up to a module boundary should_convert_module matched an entry from the start of the module name with no boundary after it, so "model.layers.1" also skipped model.layers.10 to 19, and Qwen3.8-27B-FP8's router entry "mlp.gate" also skipped the quantized mlp.gate_proj (its FP8 weight then reached a bf16 linear). A match from the start now has to end on a "." it consumed, or right before a "." or the end of the name, which keeps regex entries that carry their own boundary such as "^model\.audio_tower(?:\.|$)". The endswith clause Hub skip-lists rely on ("gate" covering shared_expert_gate) is unchanged. Supersedes huggingface#47990, which anchors with "$" and so stops matching such regex entries. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Shorten the should_convert_module docstring Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Restore the matching-rules comment of should_convert_module Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Move the should_convert_module test to a general quantizer utils test file Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Explain why the skip-list key is grouped Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Fit the skip-list comment within the noisy-comment limits Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Name the skip-list test's exclusion lists modules_to_not_convert Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
What
should_convert_moduleinsrc/transformers/quantizers/quantizers_utils.pymatches eachmodules_to_not_convertentry against the module's full name with an unanchoredre.match(f"{key}", full_name).Because
re.matchanchors at the start but not the end, a literal pattern such as...mlp.gatealso matches...mlp.gate_proj. Whengate_projis not supposed to be converted, the result is inverted:gate_projgets skipped whengatewas the intended target (or vice versa), so the quantizer leaves it as a plainnn.Linearwhile its weight is FP8 — a BF16 × FP8 matmul then dies at forward withmat1 BFloat16 != mat2 Float8_e4m3fn.Repro
Real checkpoint:
Qwen/Qwen3.8-27B-FP8(quant_method"fp8"), whose config listsmodel.language_model.layers.N.mlp.gateamong 882modules_to_not_convertentries. The MoE routermlp.gatemust not be quantized, butmlp.gate_projmust be.re.match("model.language_model.layers.0.mlp.gate", "model.language_model.layers.0.mlp.gate_proj.weight")→True(bug: skipsgate_proj)re.match(f"{key}$", full_name)→False,gate_projconverts correctly.Fix
Anchor the regex to exact match, preserving the existing
layer.*wildcard semantics:A regression test is added to
tests/quantization/mxfp4/test_mxfp4.py::test_should_convert_moduleasserting that a literal pattern does not skip a longer sibling that only shares its prefix.Why this matters
It is not a niche cosmetic issue: any finegrained-FP8 MoE checkpoint whose config names a router submodule that is a prefix of another module (e.g.
mlp.gatevsmlp.gate_proj) either fails to load or silently mis-quantizes. The current logic has no way to express "exactly this module" for such names.