Prhub

#40967 [Model] Add MiMo-V2.5 support

原始 PR 作者 Isotr0py 合并时间 2026-04-27 21:26 文件变更 16 提交数 48 评论 11 代码增减 +4737 / -5

执行摘要

新增 MiMo-V2.5 模型系列,含 Omni 与 MTP 推测解码

MiMo-V2.5 是小米发布的最新多模态模型系列,支持文本、图像、视频和音频的联合理解与生成。添加该模型支持以满足用户对最新多模态模型的需求,并扩展 vLLM 的模型库。

强烈建议仔细 review 权重加载逻辑(特别是 mimo_v2.pymimo_v2_mtp.py)中手动分片的替代方案,优先使用 vLLM 原生的 weight_loader。同时,应在文档中明确标注音频功能所需的额外依赖,并修复 cuda 硬编码问题以保障硬件兼容性。尽管 PR 已合并,但上述风险点可能影响生产部署的稳定性,建议尽快跟进修正。

讨论亮点

主要的 review 讨论集中在以下几个方面:

  • 手动分片权重兼容性:gemini-code-assist 指出 mimo_v2.py 中手动 chunk 加载 Fused QKV 权重并调用 default_weight_loader 会绕过 vLLM 的分布式 sharding 逻辑,在 TP>1 时导致形状不匹配。作者尝试修复后回退,最终合并时保留原实现,风险未完全解决。
  • 音频 tokenizer 路径硬编码:使用 os.path.join(model_path, "audio_tokenizer") 在从 Hugging Face 加载时会因 model_path 为 repo ID 而失败。
  • cuda 设备硬编码torch.cuda.current_device() 使非 CUDA 环境崩溃,推荐使用 get_device() 替代。
  • 配置参数错误vllm_config.rms_norm_eps 属性不存在,应使用 config.layernorm_epsilon,否则始终使用默认值。
  • 推理路径分布式通信_ema_inplace 中的 dist.all_reduce 在推理时可能触发同步导致性能下降或挂起。
  • 权重加载 prefix 错误AutoWeightsLoaderskip_prefixes 应为 "audio_encoder.audio_tokenizer." 而非 "audio_tokenizer."
  • 测试注册表缺失:jeejeelee 要求将 MTP 草稿模型也加入 tests/models/registry.py,但未在后续 commit 中看见对应改动。

实现拆解

  1. 模型架构实现:新增 mimo_v2_omni.py 定义视觉编码器(MiMoVisionAttentionMiMoVisionBlock)和多模态主干;新增 mimo_audio.py 实现音频编码器和 VQ 编解码;新增 mimo_v2_mtp.py 实现 MTP 层用于推测解码。
  2. 配置与权重转换:新增 mimo_v2_omni.py 配置文件 Mimo_VLVisionConfig;在 model_arch_config_convertor.py 中添加 MimoV2ModelArchConfigConvertorMimoV2MTPModelArchConfigConvertor,剔除 attention_chunk_size 以避免禁用混合 KV cache。
  3. 多模态处理器:新增 processors/mimo_v2_omni.py 实现 MiMoOmniProcessor,处理图像、视频、音频输入,包括智能缩放、帧提取和音频特征计算,依赖 torchaudiotorchcodec
  4. 注册与集成:在模型注册表和配置文件中注册新架构,更新 kv_cache_utils.py 支持滑动窗口注意力 (SWA) 配置,修改 speculative.py 支持 MTP 草稿模型。
  5. 测试与文档:在 tests/models/registry.py 添加示例项,更新 docs/models/ 文档。
文件 模块 状态 重要度
vllm/model_executor/models/mimo_v2_omni.py 模型层 added 9.17
vllm/model_executor/models/mimo_audio.py 模型层 added 9.17
vllm/model_executor/models/mimo_v2_mtp.py 推测解码 added 9.28
vllm/transformers_utils/processors/mimo_v2_omni.py 多模态处理 added 8.98
vllm/transformers_utils/model_arch_config_convertor.py 配置转换 modified 7.94

关键符号

MiMoVisionMLP MiMoVisionPatchEmbed MiMoVisionPatchMerger.forward MiMoVisionAttention.__init__ MiMoVisionBlock.__init__ MiMoV2MTPLayer.__init__ MiMoV2MultiTokenPredictor.compute_logits MimoAudioEncoder _kmeans _smart_resize

关键源码片段

vllm/model_executor/models/mimo_v2_mtp.py core-logic

实现 Multi-Token Prediction (MTP) 草稿模型,用于推测解码,支持 MiMo-V2.5 系列更高性能推理。

class MiMoV2MTPLayer(nn.Module):
    """Single MTP predictor layer for MiMo-V2 (Pro and Flash).    Mirrors the single-layer MiMo-V2 nextn reference implementation.
    """
​
    def __init__(
        self,
        config: PretrainedConfig,
        prefix: str,
        quant_config: QuantizationConfig | None = None,
    ) -> None:
        super().__init__()
​
        # 预测头组件:对 token 嵌入和前一隐藏状态分别归一化
        self.enorm = RMSNorm(config.hidden_size, eps=config.layernorm_epsilon)
        self.hnorm = RMSNorm(config.hidden_size, eps=config.layernorm_epsilon)
        # 拼接归一化后的嵌入和隐藏状态,投影回 hidden_size
        self.eh_proj = ReplicatedLinear(
            config.hidden_size * 2, config.hidden_size, bias=False
        )
​
        # MTP 使用滑动窗口注意力 (SWA) 配置
        swa_rope_theta = getattr(
            config,
            "swa_rope_theta",
            getattr(config, "rope_theta", 1000000),
        )
        sliding_window_size = getattr(config, "sliding_window_size", -1)
​
        self.input_layernorm = RMSNorm(config.hidden_size, eps=config.layernorm_epsilon)
        self.self_attn = MiMoV2Attention(
            hidden_size=config.hidden_size,
            num_heads=config.swa_num_attention_heads,
            num_kv_heads=config.swa_num_key_value_heads,
            head_dim=config.swa_head_dim,
            v_head_dim=getattr(config, "swa_v_head_dim", None),
            v_scale=getattr(config, "attention_value_scale", None),
            sliding_window_size=sliding_window_size,
            attention_bias=config.attention_bias,
            add_swa_attention_sink_bias=getattr(
                config, "add_swa_attention_sink_bias", False
            ),
            layer_id=0,
            rope_theta=swa_rope_theta,
            max_position_embeddings=getattr(config, "max_position_embeddings", 32768),
            quant_config=quant_config,
            partial_rotary_factor=getattr(config, "partial_rotary_factor", 1.0),
            prefix=f"{prefix}.self_attn",
        )
        self.pre_mlp_layernorm = RMSNorm(config.hidden_size, eps=config.layernorm_epsilon)
        self.mlp = MiMoV2MLP(
            hidden_size=config.hidden_size,
            intermediate_size=config.intermediate_size,
            hidden_act=config.hidden_act,
            quant_config=quant_config,
            prefix=f"{prefix}.mlp",
        )
        self.final_layernorm = RMSNorm(config.hidden_size, eps=config.layernorm_epsilon)

评论区精华

手动拆分 fused QKV 权重干扰 TP 推理 正确性

gemini-code-assist 指出在 mimo_v2.py 中手动 chunk 加载权重并调用 default_weight_loader 会绕过 vLLM 的分布式 sharding 逻辑,导致 TP>1 时形状不匹配。

结论:作者尝试修复后回退(commit revert),最终合并时保留原实现,风险未完全解决。 · unresolved

音频 tokenizer 路径硬编码 bug

gemini-code-assist 指出使用 os.path.join(model_path, 'audio_tokenizer') 在模型从 Hugging Face 加载时会因为 model_path 是 repo ID 而失败,建议使用已解析的本地路径。

结论:未在评论中得到回应,状态未解决。 · unresolved

cuda 设备硬编码 compatibility

gemini-code-assist 指出 torch.cuda.current_device() 在非 CUDA 环境会崩溃,建议使用 get_device() 等通用方式。

结论:未回复,未解决。 · unresolved

rms_norm_eps 获取方式错误 正确性

gemini-code-assist 指出 vllm_config.rms_norm_eps 属性不存在,应使用 config.layernorm_epsilon,否则始终使用默认 1e-6,不能匹配模型配置。

结论:未回复,未解决。 · unresolved

音频 tokenizer 推理路径中的分布式通信 性能

gemini-code-assist 指出 _ema_inplace 中的 dist.all_reduce 在推理阶段可能触发同步,影响性能甚至导致挂起。

结论:未回复,未解决。 · unresolved

添加 MTP 模型到测试注册表 测试

jeejeelee 要求将 MTP 草稿模型也添加到 tests/models/registry.py 的示例列表中。

结论:评论未被回应,后续 commit 中未出现对应改动。 · unresolved

风险与影响

  1. 分布式推理风险:手动对 QKV 权重进行 chunk 再调用 default_weight_loader 会绕过 vLLM 的内部分片逻辑,在 TP>1 时可能导致权重分配错误或形状不匹配。
  2. 音频 tokenizer 加载失败:硬编码拼接音频 tokenizer 路径使得从 Hugging Face 加载模型时无法找到文件,功能静默降级。
  3. 硬件兼容性torch.cuda.current_device() 在 CPU 或 XPU 环境直接崩溃,限制了模型可部署的硬件范围。
  4. 配置默认值错误rms_norm_eps 获取方式错误导致忽略模型配置中的 epsilon 值,可能引入数值精度偏差。
  5. 性能风险:音频编码器 _ema_inplace 在推理路径中使用 dist.all_reduce,可能造成非预期同步,影响吞吐。
  6. 权重丢失AutoWeightsLoaderskip_prefixes 未匹配子模块前缀,导致音频 tokenizer 权重在加载过程中被遗漏并产生警告。

用户可以使用 vllm serve 部署 MiMo-V2.5 Pro/Flash/Omni 系列模型,并利用 MTP 进行推测解码加速。新增多模态处理器支持图像、视频、音频输入,但需要安装 torchaudiotorchcodec 等可选依赖。代码库新增约 4700 行 Python,模型层、配置转换和多模态处理等模块耦合度增加。

手动权重分片风险 音频路径硬编码 cuda 硬编码兼容性 prefix 跳跃权重缺失 推理路径集体通信 配置 epsilon 默认值错误

关联 Issue

未识别关联 Issue

当前没有检测到明确关联的 Issue 链接,后续同步到相关引用后会出现在这里。

完整报告

参与讨论