Skip to content

Fix B12X NVFP4 prepare for forced W4A16 - #20

Merged
lukealonso merged 1 commit into
dev/chthonic-consecrationfrom
codex/glm51-w4a16-fix-20260615
Jun 16, 2026
Merged

lukealonso merged 1 commit into
dev/chthonic-consecrationfrom
codex/glm51-w4a16-fix-20260615

Conversation

@voipmonitor

@voipmonitor voipmonitor commented Jun 15, 2026

Copy link
Copy Markdown

Summary

Fix GLM 5.1 NVFP4 corruption when B12X_MOE_FORCE_A16=1 forces the B12X MoE path to prepare ModelOpt NVFP4 experts as W4A16.

The normal native B12X NVFP4 prepare path is correct for A16-off. The forced W4A16 path, however, needs the existing FI/B12X gated W13 reorder before B12xExperts prepares W4A16 weights. Without that reorder, the gate/up halves are consumed in the wrong order and GLM emits corrupted output immediately.

This PR keeps native B12X NVFP4 on prepare_nvfp4_moe_layer_for_b12x, switches to the FI/B12X prepare only when use_a16 or B12X_MOE_FORCE_A16=1 is active, and propagates ModelOpt's explicit use_a16 flag into the converter.

Validation

Tested on voipmonitor/vllm:chthonic-consecration-5e83948-b12x-465cb6e-cu132 with only these fix files bind-mounted:

  • GLM v10 recipe, DCP1, MTP off, port 5329, B12X_MOE_FORCE_A16=1.
  • GLM v10 recipe, DCP1, MTP off, port 5330, B12X_MOE_FORCE_A16=0.
  • Both runs logged V2 model runner, B12X_MLA_SPARSE, and Using 'B12X' NvFp4 MoE backend.
  • Both runs completed /mnt/test.py -L until timeout with coherent output and CJK characters in output: 0.
  • git diff --check passed.
  • python3 -m py_compile vllm/model_executor/layers/fused_moe/oracle/nvfp4.py vllm/model_executor/layers/quantization/modelopt.py passed.

Summary by CodeRabbit

  • New Features
    • Added configurable NVFP4 Mixture of Experts kernel preparation options via environment variables and new parameters to optimize activation precision handling during inference.

Chthonic's native B12X NVFP4 prepare path is correct for normal NVFP4, but forced W4A16 reuses the prepared ModelOpt weights through B12xExperts. That path needs the FI/B12X gated W13 reorder before b12x prepares the W4A16 weights; otherwise the gate/up halves are consumed in the wrong order and GLM emits corrupted output.

Keep native B12X NVFP4 on prepare_nvfp4_moe_layer_for_b12x, switch to the FI/B12X prepare only when use_a16 or B12X_MOE_FORCE_A16=1 is active, and propagate ModelOpt's explicit use_a16 flag into the converter.

Validated on the chthonic 5e83948 / b12x 465cb6e image with GLM v10 DCP1 MTP-off: B12X_MOE_FORCE_A16=1 on port 5329 and B12X_MOE_FORCE_A16=0 on port 5330 both start with B12X MLA sparse + B12X NvFp4 MoE and run /mnt/test.py -L coherently until timeout with CJK count 0. Also ran git diff --check and py_compile for the touched files.
@coderabbitai

coderabbitai Bot commented Jun 15, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds a _env_flag boolean env-var helper and a use_a16: bool = False parameter to convert_to_nvfp4_moe_kernel_format. The B12X branch now conditionally calls prepare_nvfp4_moe_layer_for_fi_or_cutlass with backend=FLASHINFER_B12X when use_a16 is set or B12X_MOE_FORCE_A16 is defined in the environment, otherwise retaining the existing path. The modelopt.py caller passes use_a16=self.use_a16.

Changes

NVFP4 MoE B12X A16 path selection

Layer / File(s) Summary
env-flag helper and use_a16 parameter
vllm/model_executor/layers/fused_moe/oracle/nvfp4.py
Adds os import, introduces _env_flag(name, default) for boolean env-var parsing, and appends use_a16: bool = False to the convert_to_nvfp4_moe_kernel_format signature.
B12X conditional dispatch and caller wiring
vllm/model_executor/layers/fused_moe/oracle/nvfp4.py, vllm/model_executor/layers/quantization/modelopt.py
B12X branch dispatches to prepare_nvfp4_moe_layer_for_fi_or_cutlass(backend=FLASHINFER_B12X) when use_a16 or B12X_MOE_FORCE_A16 is active, otherwise keeps prepare_nvfp4_moe_layer_for_b12x. modelopt.py passes use_a16=self.use_a16 to propagate the flag.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the main change: fixing B12X NVFP4 preparation for forced W4A16 configurations, which is the core objective of this pull request.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/glm51-w4a16-fix-20260615

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@vllm/model_executor/layers/fused_moe/oracle/nvfp4.py`:
- Around line 347-390: Update the `make_nvfp4_moe_quant_config()` function to
apply the same A16 logic as the weight preparation code. The weight preparation
at line 347 checks `use_a16 or _env_flag("B12X_MOE_FORCE_A16")` to decide
between two backends, but the quant config function only checks `use_a16`,
ignoring the environment flag override. Modify `make_nvfp4_moe_quant_config()`
to include the same `_env_flag("B12X_MOE_FORCE_A16")` check when determining the
quantization method, ensuring the returned config reflects the same A16
determination as the prepared weights.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 0c8cc6fb-4636-4ba7-a01c-dbf72b894a84

📥 Commits

Reviewing files that changed from the base of the PR and between 5e83948 and 76378e8.

📒 Files selected for processing (2)
  • vllm/model_executor/layers/fused_moe/oracle/nvfp4.py
  • vllm/model_executor/layers/quantization/modelopt.py

Comment on lines +347 to +390
if use_a16 or _env_flag("B12X_MOE_FORCE_A16"):
(
w13,
w13_scale,
w13_scale_2,
a13_scale,
w2,
w2_scale,
w2_scale_2,
a2_scale,
) = prepare_nvfp4_moe_layer_for_fi_or_cutlass(
backend=NvFp4MoeBackend.FLASHINFER_B12X,
layer=layer,
w13=w13,
w13_scale=w13_scale,
w13_scale_2=w13_scale_2,
a13_scale=a13_scale,
w2=w2,
w2_scale=w2_scale,
w2_scale_2=w2_scale_2,
a2_scale=a2_scale,
is_act_and_mul=is_act_and_mul,
)
else:
(
w13,
w13_scale,
w13_scale_2,
a13_scale,
w2,
w2_scale,
w2_scale_2,
a2_scale,
) = prepare_nvfp4_moe_layer_for_b12x(
w13=w13,
w13_scale=w13_scale,
w13_scale_2=w13_scale_2,
a13_scale=a13_scale,
w2=w2,
w2_scale=w2_scale,
w2_scale_2=w2_scale_2,
a2_scale=a2_scale,
is_act_and_mul=is_act_and_mul,
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Locate all A16 gating points ==="
rg -n "B12X_MOE_FORCE_A16|use_a16|make_nvfp4_moe_quant_config|nvfp4_w4a16_moe_quant_config|convert_to_nvfp4_moe_kernel_format" \
  vllm/model_executor/layers/fused_moe/oracle/nvfp4.py \
  vllm/model_executor/layers/quantization/modelopt.py \
  vllm/model_executor/layers/fused_moe/b12x_moe.py

echo
echo "=== Inspect B12X experts implementation for force-A16 behavior ==="
sed -n '1,260p' vllm/model_executor/layers/fused_moe/b12x_moe.py

Repository: local-inference-lab/vllm

Length of output: 9754


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Extract convert_to_nvfp4_moe_kernel_format function (lines 323-400) ==="
sed -n '323,400p' vllm/model_executor/layers/fused_moe/oracle/nvfp4.py | cat -n

echo
echo "=== Extract make_nvfp4_moe_quant_config function (lines 501-525) ==="
sed -n '501,525p' vllm/model_executor/layers/fused_moe/oracle/nvfp4.py | cat -n

echo
echo "=== Extract b12x_moe.py context around line 563 (lines 555-575) ==="
sed -n '555,575p' vllm/model_executor/layers/fused_moe/b12x_moe.py | cat -n

echo
echo "=== Search for callers of convert_to_nvfp4_moe_kernel_format ==="
rg -B 2 -A 2 "convert_to_nvfp4_moe_kernel_format\(" vllm/model_executor/layers/quantization/modelopt.py

Repository: local-inference-lab/vllm

Length of output: 5183


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Check modelopt.py around lines 1567-1614 to see the full call sequence ==="
sed -n '1560,1620p' vllm/model_executor/layers/quantization/modelopt.py | cat -n

echo
echo "=== Search for where make_nvfp4_moe_quant_config result is used ==="
rg -A 3 "make_nvfp4_moe_quant_config" vllm/model_executor/layers/quantization/modelopt.py | head -40

Repository: local-inference-lab/vllm

Length of output: 3344


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Check if quant_config is actually used or just overridden by _quant_mode ==="
rg -B 5 -A 5 "self._quant_mode\(\)|_quant_mode|self.moe_quant_config" vllm/model_executor/layers/fused_moe/b12x_moe.py | head -80

echo
echo "=== Find where quant_mode is set in plan_b12x_moe_fp4_scratch ==="
rg -B 2 -A 2 "quant_mode=" vllm/model_executor/layers/fused_moe/b12x_moe.py | head -40

Repository: local-inference-lab/vllm

Length of output: 4383


Verify A16 gating is consistent between tensor preparation and quant config.

Line 347 enables weight preparation as A16 when use_a16 or B12X_MOE_FORCE_A16=1, but make_nvfp4_moe_quant_config() at lines 514–517 only checks use_a16, ignoring the environment flag. This creates a split where:

  • Weights are prepared as A16 when the env flag is set
  • FusedMoEQuantConfig object returned does not reflect this override
  • Runtime _quant_mode() in b12x_moe.py correctly forces w4a16

Any code path relying on quant_config.quant_method to determine behavior will miss the B12X_MOE_FORCE_A16 override, causing prepared weights and quant configuration to diverge.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@vllm/model_executor/layers/fused_moe/oracle/nvfp4.py` around lines 347 - 390,
Update the `make_nvfp4_moe_quant_config()` function to apply the same A16 logic
as the weight preparation code. The weight preparation at line 347 checks
`use_a16 or _env_flag("B12X_MOE_FORCE_A16")` to decide between two backends, but
the quant config function only checks `use_a16`, ignoring the environment flag
override. Modify `make_nvfp4_moe_quant_config()` to include the same
`_env_flag("B12X_MOE_FORCE_A16")` check when determining the quantization
method, ensuring the returned config reflects the same A16 determination as the
prepared weights.

@lukealonso
lukealonso merged commit 08cb39d into dev/chthonic-consecration Jun 16, 2026
4 of 5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants