Skip to content

Add MiniMax-M3 modelopt nvfp4 support - #46756

Merged
vllm-bot merged 2 commits into
vllm-project:mainfrom
jasonlizhengjian:codex/minimax-m3-nvfp4-modelopt
Jun 29, 2026
Merged

vllm-bot merged 2 commits into
vllm-project:mainfrom
jasonlizhengjian:codex/minimax-m3-nvfp4-modelopt

Conversation

@jasonlizhengjian

@jasonlizhengjian jasonlizhengjian commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Summary

Ports #46380 from minimax-m3-perf onto current main.

The original PR was merged into minimax-m3-perf, but current main was still missing the relevant support points when checked locally: ModelOpt mixed MXFP8 dispatch, the parent-prefix fallback for fused projections, and the NVFP4 MoE SwiGLU-OAI alpha/beta/clamp wiring.

Changes

  • Add ModelOpt mixed-precision MXFP8 Linear and RoutedExperts dispatch.
  • Add fallback resolution for fused projection prefixes such as qkv_proj and gate_up_proj.
  • Pass per-expert gemm1_alpha, gemm1_beta, and gemm1_clamp_limit into FlashInfer TRTLLM NVFP4 MoE kernels, including moe_config.swiglu_* fallback.
  • Map both SwiGLU-OAI activation variants to FlashInfer Swiglu.

Validation

  • uvx --from pre-commit>=4.5.1 pre-commit run --files vllm/model_executor/layers/fused_moe/experts/trtllm_nvfp4_moe.py vllm/model_executor/layers/quantization/modelopt.py vllm/model_executor/layers/quantization/utils/flashinfer_utils.py

Tested with and without the patch:

vllm serve nvidia/MiniMax-M3-NVFP4 \
    --served-model-name nvidia/MiniMax-M3-NVFP4 \
    --tensor-parallel-size 4 \
    --host 0.0.0.0 \
    --port 8040 \
    --gpu-memory-utilization 0.90 \
    --max-model-len 10240 \
    --block-size 128 \
    --max-num-batched-tokens 16384 \
    --stream-interval 20 \
    --no-enable-prefix-caching \
    --language-model-only \
    --trust-remote-code \
    --enforce-eager

Without patch outputs are garbage.
With patch, outputs are normal.

@claude claude 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.

Claude Code Review

This pull request is from a fork — automated review is disabled. A repository maintainer can comment @claude review to run a one-time review.

@jasonlizhengjian jasonlizhengjian changed the title [codex] Add MiniMax-M3 modelopt nvfp4 support Add MiniMax-M3 modelopt nvfp4 support Jun 25, 2026
@jasonlizhengjian
jasonlizhengjian marked this pull request as draft June 25, 2026 18:38
@jasonlizhengjian
jasonlizhengjian marked this pull request as ready for review June 25, 2026 18:39
@xinli-sw

Copy link
Copy Markdown
Contributor

@jasonlizhengjian please attach vllm serve command and effect of PR (with / w/o behavior), thanks!!

@mgoin mgoin left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM just some nits

Comment on lines +39 to +45
# Both OAI variants map to Swiglu: FlashInfer has no SwigluOAI enum;
# the clamped/biased behavior is driven by the per-expert gemm1_alpha/
# gemm1_beta/gemm1_clamp_limit tensors (see trtllm_nvfp4_moe.py).
# The interleaved-vs-contiguous row layout difference between the two
# is resolved in process_weights_after_loading, not here.
MoEActivation.SWIGLUOAI: ActivationType.Swiglu,
MoEActivation.SWIGLUOAI_UNINTERLEAVE: ActivationType.Swiglu,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Does this behavior work for all the trtllm backends? I see we use this utility in trtllm_bf16_moe.py, trtllm_fp8_moe.py, and trtllm_nvfp4_moe.py
It is probably fine for now if we don't advertise support for those in _supports_activation

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

good point, I'll check in parallel

Comment on lines +102 to +108
logger.info_once(
"activation=%s, gemm1_alpha=%s, gemm1_beta=%s, gemm1_clamp_limit=%s",
moe_config.activation,
alpha,
beta,
clamp,
)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Is this debug cruft we can remove? Maybe it could be demoted to debug_once

@github-project-automation github-project-automation Bot moved this to Ready in NVIDIA Jun 25, 2026
@mgoin mgoin added ready ONLY add when PR is ready to merge/full CI is needed quantization labels Jun 25, 2026
@mergify

mergify Bot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Hi @jasonlizhengjian, the pre-commit checks have failed. Please run:

uv pip install pre-commit>=4.5.1
pre-commit install
pre-commit run --all-files

Then, commit the changes and push to your branch.

For future commits, pre-commit will run automatically on changed files before each commit.

@jasonlizhengjian
jasonlizhengjian force-pushed the codex/minimax-m3-nvfp4-modelopt branch from 1996180 to a412730 Compare June 25, 2026 18:52
# gemm1_beta/gemm1_clamp_limit tensors (see trtllm_nvfp4_moe.py).
# The interleaved-vs-contiguous row layout difference between the two
# is resolved in process_weights_after_loading, not here.
MoEActivation.SWIGLUOAI: ActivationType.Swiglu,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Do you need add SWIGLUOAI in this PR? I think for M3 we only need to add SWIGLUOAI_UNINTERLEAVE and it would just reduce the potential untested cases

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

ok I will test without

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

removed

Signed-off-by: Xin Li <xinli@nvidia.com>
(cherry picked from commit 6c08558)
Signed-off-by: jasonlizhengjian <jasonlizhengjian@gmail.com>
@jasonlizhengjian
jasonlizhengjian force-pushed the codex/minimax-m3-nvfp4-modelopt branch from a412730 to 513fc60 Compare June 25, 2026 19:13
@mgoin

mgoin commented Jun 26, 2026

Copy link
Copy Markdown
Member

@jasonlizhengjian Looks like some failures are related, PTAL

For instance

[2026-06-25T20:08:01Z] FAILED quantization/test_modelopt.py::test_modelopt_mixed_precision_quantizes_parallel_lm_head - TypeError: ModelOptMixedPrecisionConfig.__init__() missing 1 required positional argument: 'mxfp8_config'

Signed-off-by: jasonlizhengjian <jasonlizhengjian@gmail.com>
@jasonlizhengjian

Copy link
Copy Markdown
Contributor Author

@mgoin remaining failures should not be related

@mgoin mgoin left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Confirmed unrelated failures

@vllm-bot
vllm-bot merged commit debec64 into vllm-project:main Jun 29, 2026
107 of 113 checks passed
@github-project-automation github-project-automation Bot moved this from Ready to Done in NVIDIA Jun 29, 2026
@eugr

eugr commented Jun 30, 2026

Copy link
Copy Markdown

@jasonlizhengjian - this PR breaks modelOpt mixed precision checkpoints such as nvidia/Qwen3.6-35B-A3B-NVFP4 and nvidia/Nemotron-3-Super-120B-A10B-NVFP4 on DGX Spark, possibly on other hardware too.

The regression was detected by my nightly CI pipeline:

  • Good vLLM ref (previous nightly run): a4e3cb40
  • Bad vLLM ref (this nightly run): 8e9d70fd

I traced the regression to the following commit: debec6440 from this PR

With today nightly build, simple queries with temperature=0 and chat_template_kwargs={"enable_thinking": false} produce only exclamation marks for nvidia/Qwen3.6-35B-A3B-NVFP4 checkpoint:

  • What is the capital of France? Respond with one word. -> !!!!!!!!!!!!!!!!!!!!!!!!
  • What is 2+2? Respond with one number. -> !!!!!!!!!!!!!!!!!!!!!!!!

The same recipe on the previous nightly returns Paris and 4.

I then reverted only debec6440 inside the 20260630 container and restarted the same recipe. Output recovered to Paris and 4.

Similar situation with Nemotron-3-Super.

This also regresses on 20260630, producing <unk> / repetitive garbage for the same simple France query. Reverting debec6440 fixes the underlying bad generation behavior there as well.

Likely mechanism (as suggested by Codex, haven't looked into the PR in more detail myself): this PR makes modelopt_mixed actively dispatch MXFP8 layers via ModelOptMxFp8LinearMethod / ModelOptMxFp8FusedMoE, and adds parent-prefix fallback for fused projections. It looks like some existing mixed ModelOpt NVFP4 checkpoints now route a layer or fused projection through an incompatible MXFP8 path, causing numerically corrupted logits without a shape/dtype crash.

@mgoin - FYI.

noooop pushed a commit to noooop/vllm that referenced this pull request Jul 9, 2026
Signed-off-by: Xin Li <xinli@nvidia.com>
Signed-off-by: jasonlizhengjian <jasonlizhengjian@gmail.com>
Co-authored-by: Xin Li <xinli@nvidia.com>
Signed-off-by: wang.yuqi <yuqi.wang@daocloud.io>
philippesic pushed a commit to philippesic/vllm-semantic-cache that referenced this pull request Jul 19, 2026
Signed-off-by: Xin Li <xinli@nvidia.com>
Signed-off-by: jasonlizhengjian <jasonlizhengjian@gmail.com>
Co-authored-by: Xin Li <xinli@nvidia.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

nvidia quantization ready ONLY add when PR is ready to merge/full CI is needed

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

5 participants