Prhub

#41254 [Model] Support MiniCPM-V 4.6

原始 PR 作者 tc-mb 合并时间 2026-05-12 22:28 文件变更 5 提交数 23 评论 28 代码增减 +1302 / -5

执行摘要

支持 MiniCPM-V 4.6 多模态模型

来自 PR body: 'MiniCPM-V 4.6 has just been merged into huggingface/transformers (v5.7.0) as a standalone architecture rather than a sub-version of MiniCPMV. This PR adapts vLLM to that upstream layout.' 目的是支持新发布的 MiniCPM-V 4.6 模型。

值得精读,尤其是如何将新模型集成到 vLLM 多模态框架中的模式:利用共享基类加版本分支、处理器适配、注册体系。对于多模态模型贡献者,可以借鉴 MiniCPMV4_6MultiModalProcessorprocess_images/process_videos 的 NaViT 输入重排和 prompt 生成逻辑。

讨论亮点
  1. Critical 问题:gemini-code-assist 指出 MiniCPMV 类被修改为继承 HasInnerStateIsHybrid,导致非 hybrid 的旧版模型(如 2.0、2.5、4.0)错误地分配 Mamba 资源。作者通过移除重复定义并恢复 MiniCPMV 原始签名解决。
  2. 版本号错误MiniCPMV4_6get_model_version 返回 (4,5) 应为 (4,6),已修复。
  3. Backbone 初始化:gemini-code-assist 建议在初始化 LLM 骨干时临时 swap model_type,作者采用类似逻辑。
  4. Spec Decode 改动:DarkLight1337 指出 scheduler 和 engine 中的 spec decode 变更与模型无关,作者删除。
  5. 代码风格:DarkLight1337 建议使用 vLLM 标准注意力、get_act_fn、移动导入到顶层,均已采纳。

实现拆解

  1. 新增模型文件 vllm/model_executor/models/minicpmv4_6.py:实现 MiniCPMV4_6ForConditionalGeneration 类,包含 ViT 编码器、LLM 骨干(基于 Qwen3_5ForCausalLM)和多模态处理器。定义了 _minicpmv4_6_field_config 映射 HF 输入到 vLLM 字段,以及 MiniCPMV4_6MultiModalProcessor 处理图片和视频的 prompt 生成、NaViT 风格输入重排。

  2. 修改共享模块 vllm/model_executor/models/minicpmv.py:在 MiniCPMVProcessingInfo 中添加 version == (4, 6) 分支,适配 transformers v5.7 的 API 重命名(image_mean/image_stdim_id_start/im_id_end 等),并覆盖 get_slice_image_placeholderget_num_image_tokens 等方法以支持新的视觉 token 计算。

  3. 注册模型 vllm/model_executor/models/registry.py:添加 MiniCPMV4_6ForConditionalGeneration 到映射表,模型类型为 minicpmv4_6

  4. 添加 Chat Template Fallback vllm/transformers_utils/chat_templates/registry.py:将 minicpmv4_6 映射到已有的 _get_minicpmv_chat_template_fallback 函数。

  5. 集成测试注册 tests/models/registry.py:添加 MiniCPMV4_6ForConditionalGeneration 条目,指定 min_transformers_version=5.7.0

文件 模块 状态 重要度
vllm/model_executor/models/minicpmv4_6.py 模型定义 added 9.17
vllm/model_executor/models/minicpmv.py 共享逻辑 modified 7.16
vllm/model_executor/models/registry.py 模型注册 modified 5.28
vllm/transformers_utils/chat_templates/registry.py 模板回退 modified 4.35
tests/models/registry.py 测试注册 modified 4.2

关键符号

_minicpmv4_6_field_config MiniCPMV4_6MultiModalProcessor.process_images MiniCPMV4_6MultiModalProcessor.process_videos MiniCPMV4_6MultiModalProcessor.get_video_prompt_texts MiniCPMVProcessingInfo.get_slice_image_placeholder

关键源码片段

vllm/model_executor/models/minicpmv.py data-contract

共享模型代码,添加 version (4,6) 分支以适配 transformers v5.7 API。

def get_slice_image_placeholder(self, image_size, image_idx=0, max_slice_nums=None, use_image_id=True):
    image_processor = self.get_image_processor()
    version = self.get_model_version()
    # v2.0/2.5 使用旧式接口
    if version == (2, 0) or version == (2, 5):
        return image_processor.get_slice_image_placeholder(image_size)
    # v4.6 需要手动计算 visual tokens 再调用处理器
    if version == (4, 6):
        if max_slice_nums is None:
            max_slice_nums = image_processor.max_slice_nums
        grids = image_processor.get_sliced_grid(
            image_size, max_slice_nums=max_slice_nums)
        patch_size = image_processor.patch_size
        scale_resolution = image_processor.scale_resolution
        allow_upscale = grids is None
        best_size = image_processor.find_best_resize(
            image_size, scale_resolution, patch_size,
            allow_upscale=allow_upscale)
        h_patches = best_size[1] // patch_size
        w_patches = best_size[0] // patch_size
        source_image_visual_tokens = (h_patches // 4) * (w_patches // 4)
        if grids is not None:
            refine_size = image_processor.get_refine_size(
                image_size, grids, scale_resolution, patch_size,
                allow_upscale=True)
            pw = refine_size[0] // grids[0]
            ph = refine_size[1] // grids[1]
            patch_visual_tokens = (ph // patch_size // 4) * (pw // patch_size // 4)
        else:
            patch_visual_tokens = source_image_visual_tokens
        return image_processor.get_slice_image_placeholder(
            grids if grids is not None else [0, 0],
            image_idx=image_idx,
            max_slice_nums=max_slice_nums,
            use_image_id=use_image_id,
            source_image_visual_tokens=source_image_visual_tokens,
            patch_visual_tokens=patch_visual_tokens,
        )
    # 其他版本使用标准接口
    return image_processor.get_slice_image_placeholder(
        image_size, image_idx=image_idx,
        max_slice_nums=max_slice_nums, use_image_id=use_image_id)

评论区精华

MiniCPMV 类错误继承 HasInnerState/IsHybrid 影响旧版本 正确性

gemini-code-assist 指出硬编码 Mamba 代理到 4.6,导致非 hybrid 模型异常。

结论:作者移除 MiniCPMV4_6 在 minicpmv.py 中的重复定义,恢复原始签名。 · 已解决

get_model_version 返回 (4,5) 应为 (4,6) 正确性

gemini-code-assist 发现版本号错误。

结论:作者修正为 (4,6)。 · 已解决

移除与模型无关的 spec decode 改动 设计

DarkLight1337 质疑 scheduler.py 变更是否必要。

结论:作者删除相关提交。 · 已解决

使用 vLLM 标准注意力代替原生 PyTorch 性能

DarkLight1337 建议复用 vLLM 的 attention 层。

结论:作者替换为 vLLM 的 attention 类。 · 已解决

为 backbone 初始化临时 swap model_type 设计

gemini-code-assist 指出 Qwen3_5 初始化可能失败。

结论:作者添加类似 minicpmv.py 中的 _mark_language_model 逻辑。 · 已解决

风险与影响

  • 共享代码分支风险minicpmv.py 中新增的 version == (4,6) 分支不影响旧版本,但增加了后续维护的复杂度(需确保分支隔离)。
  • 上游依赖:模型依赖 transformers v5.7.0,旧版本用户需升级,可能导致兼容性中断。
  • 测试覆盖:仅包含注册测试,缺乏端到端多模态推理测试,可能隐藏集成问题。
  • 早期 Critical Bug:虽已修复,但暗示共享代码的设计需要更严格的回归验证。
  • 用户:现在可以使用 openbmb/MiniCPM-V-4_6 模型进行图像和视频多模态推理。
  • 系统:不影响现有 MiniCPM-V 其他版本(2.0、2.5、4.0、4.5)的行为。
  • 团队:需跟进 transformers 对 MiniCPMV4_6 的后续更新,并维护 minicpmv.py 中的版本分支。
共享代码分支变更 上游 transformers 版本依赖 新模型测试覆盖有限

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论