Prhub

#31989 feat: Support nvidia/MiniMax-M3-NVFP4

原始 PR 作者 trevor-m 合并时间 2026-07-31 05:32 文件变更 6 提交数 2 评论 6 代码增减 +156 / -16

执行摘要

支持 MiniMax-M3 NVFP4 混合精度模型加载

此 PR 修复 Issue #31827,该问题报告 nvidia/MiniMax-M3-NVFP4 模型在加载时崩溃,原因是 fused MoE 回退到未量化方法,以及 MXFP8 线性层权重被静默丢弃。通过正确处理混合精度量化配置,使该模型能够正常加载和推理。

建议读者关注 ModelOptMixedPrecisionConfig 的扩展方式以及如何通过 hf_to_sglang_mapperpacked_modules_mapping 解决权重名称映射问题。这种设计模式值得在其他需要适配不同前缀的量化模型中复用。

讨论亮点

此 PR 无代码评审评论,只有一次审批(b8zhong 批准)。主要讨论在关联 Issue #31827 中,该 Issue 详细描述了问题的两个根因:① fused MoE 量化方法无法解析(因 HF 前缀 block_sparse_moe 未映射到 SGLang 的 mlp);② MXFP8 线性层在混合精度配置中被忽略。

实现拆解

  1. modelopt_quant.pyModelOptMixedPrecisionConfig 中添加 mxfp8_config 属性,并在 from_config 中从 hf_quant_configquantized_layers 提取 MXFP8 配置;get_quant_method 中新增对 "MXFP8" 的处理,返回 Fp8LinearMethod(线性层)和 Fp8MoEMethod(MoE 层)。
  2. minimax_m3.pyminimax_m3_vl.py 的模型类中添加 hf_to_sglang_mapper 类属性,将 HF 权重前缀 block_sparse_moe 映射为 SGLang 的 mlp,使量化配置在运行时能正确匹配路由专家层。
  3. 在上述两个模型的 determine_num_fused_shared_experts 方法中增加对 modelopt_mixed 量化配置的检测,当共享专家和路由专家使用不同量化格式时禁用共享专家融合,避免计算错误。
  4. overrides.py_minimax_m3_overrides 中为 MiniMax-M3 添加默认 MoE 后端选择,当量化方法为 modelopt_mixed 时自动选择 flashinfer_trtllm_routed
  5. flashinfer_trtllm.pyFlashInferTrtllmFp4MoeQuantInfo 中添加 gemm1_alphagemm1_beta 属性,并在 fused_experts_none_to_flashinfer_trtllm_fp4 函数中将其传给底层 kernel,支持 NVFP4 的 alpha/beta 缩放。
  6. 新增单元测试 test_minimax_mixed_precision_resolves_runtime_names_and_mxfp8,验证权重名称映射、量化算法解析以及 MXFP8 方法分发是否正确。
文件 模块 状态 重要度
python/sglang/srt/layers/quantization/modelopt_quant.py 量化配置 modified 7.29
python/sglang/srt/models/minimax_m3.py 模型定义 modified 6.71
python/sglang/srt/models/minimax_m3_vl.py 模型定义 modified 6.71
test/registered/unit/model_loader/test_modelopt_loader.py 测试加载 modified 6.43
python/sglang/srt/layers/moe/moe_runner/flashinfer_trtllm.py MoE 运行器 modified 5.57
python/sglang/srt/arg_groups/overrides.py 参数覆盖 modified 5.5

关键符号

ModelOptMixedPrecisionConfig.__init__ ModelOptMixedPrecisionConfig.from_config ModelOptMixedPrecisionConfig.get_quant_method MiniMaxM3SparseForCausalLM.determine_num_fused_shared_experts MiniMaxM3SparseForConditionalGeneration._determine_num_fused_shared_experts FlashInferTrtllmFp4MoeQuantInfo.__init__ fused_experts_none_to_flashinfer_trtllm_fp4 _minimax_m3_overrides

关键源码片段

python/sglang/srt/layers/quantization/modelopt_quant.py data-contract

核心配置变更:添加 mxfp8_config 支持 MXFP8 层,扩展 get_quant_method 分发逻辑

class ModelOptMixedPrecisionConfig(ModelOptQuantConfig):
    """Configuration for ModelOpt MIXED_PRECISION checkpoints."""
​
    def __init__(
        self,
        kv_cache_quant_algo: Optional[str],
        exclude_modules: Optional[List[str]],
        packed_modules_mapping: Optional[Dict[str, List[str]]],
        quantized_layers: Dict[str, Dict[str, Any]],
        fp8_config: ModelOptFp8Config,
        nvfp4_config: ModelOptFp4Config,
        nvfp4a16_config: ModelOptFp4Config,
        mxfp8_config: Fp8Config, # <-- 新增:存储 MXFP8 配置
    ) -> None:
        super().__init__(kv_cache_quant_algo, exclude_modules, packed_modules_mapping)
        self.quantized_layers = quantized_layers
        self.fp8_config = fp8_config
        self.mxfp8_config = mxfp8_config # <-- 新增
        self.nvfp4_config = nvfp4_config
        self.nvfp4a16_config = nvfp4a16_config
​
    @classmethod
    def from_config(cls, config: Dict[str, Any]) -> ModelOptMixedPrecisionConfig:
        # ... 省略前面的解析逻辑 ...
        # 创建 MXFP8 配置,使用 block_size [1, 32] 和 dynamic activation
        mxfp8_config = Fp8Config(
            is_checkpoint_fp8_serialized=True,
            activation_scheme="dynamic",
            weight_block_size=[1, 32],
            packed_modules_mapping=packed_modules_mapping,
            use_mxfp8=True, # <-- 启用 MXFP8 模式
        )
        return cls(
            kv_cache_quant_algo=kv_cache_quant_algo,
            exclude_modules=exclude_modules,
            packed_modules_mapping=packed_modules_mapping,
            quantized_layers=quantized_layers,
            fp8_config=fp8_config,
            mxfp8_config=mxfp8_config, # <-- 传递新配置
            nvfp4_config=nvfp4_config,
            nvfp4a16_config=nvfp4a16_config,
        )
​
    def get_quant_method(self, layer, prefix):
        quant_algo = self._resolve_quant_algo(prefix)
        # ... 前面的 quant_algo 检查 ...
        if isinstance(layer, LinearBase):
            if quant_algo == "MXFP8":
                return Fp8LinearMethod(self.mxfp8_config) # <-- 新增 MXFP8 线性层方法
        if isinstance(layer, FusedMoE):
            if quant_algo == "MXFP8":
                return Fp8MoEMethod(self.mxfp8_config) # <-- 新增 MXFP8 MoE 层方法
python/sglang/srt/models/minimax_m3.py data-contract

添加 hf_to_sglang_mapper 解决前缀映射,并禁用混合精度下的共享专家融合

from sglang.srt.models.utils import WeightsMapperclass MiniMaxM3SparseForCausalLM(nn.Module):
    # 将 HF 的 block_sparse_moe 前缀映射为 SGLang 的 mlp 前缀,确保量化配置能匹配路由专家层
    hf_to_sglang_mapper = WeightsMapper(
        orig_to_new_substr={".block_sparse_moe.": ".mlp."}
    )
    packed_modules_mapping = {
        "qkv_proj": ["q_proj", "k_proj", "v_proj"],
        "index_qkv_proj": ["index_q_proj", "index_k_proj", "index_v_proj"],
        "gate_up_proj": ["gate_proj", "up_proj"],
    }
​
    # ... 其他方法 ...
​
    def determine_num_fused_shared_experts(self):
        if get_server_args().disable_shared_experts_fusion:
            return
        disable_reason = None
        if not getattr(self.config, "n_shared_experts", None):
            disable_reason = "No shared experts are defined in the config."
        # 当使用 ModelOpt 混合精度时,共享专家与路由专家可能采用不同量化格式(如 MXFP8 vs NVFP4),
        # 此时必须禁用共享专家融合,避免计算错误
        elif (
            self.quant_config is not None
            and self.quant_config.get_name() == "modelopt_mixed"
        ):
            disable_reason = (
                "Shared and routed experts may use different quantization formats "
                "in ModelOpt mixed-precision checkpoints."
            )
        # ... 其他条件 ...

评论区精华

没有提炼出高价值讨论线程

当前评论区没有形成足够清晰的争议点或结论,后续有更多讨论时会体现在这里。

风险与影响

更改了 modelopt_quant.py 中的配置解析,可能影响其他使用 ModelOptMixedPrecisionConfig 的模型(如 Nemotron-H),但由于添加的是新选项(MXFP8)并保持向后兼容,风险较低。修改了 overrides.py 中 MiniMax-M3 的默认 MoE 后端,但条件严格限定为 modelopt_mixed,不会影响其他量化方法。禁用共享专家融合可能影响性能,但这是混合精度所必需的。

用户:能够成功加载并使用 nvidia/MiniMax-M3-NVFP4 模型,精度测试通过(GSM8K 0.925)。系统:SGLang 现在支持包含 MXFP8 层的 modelopt_mixed 混合精度模型,扩展了对更多 NVIDIA 量化模型的支持。团队:新增了少量维护点,但添加了单元测试覆盖,降低了回归风险。

量化配置变更 MoE 后端默认值变更 共享专家融合禁用

关联 Issue

#31827 [Bug] MiniMax-M3 NVFP4 fails to load: fused MoE falls back to UnquantizedFusedMoEMethod (6144 vs 3072) and MXFP8 linear scales are dropped

完整报告

参与讨论