Prhub

#44980 Fix/minicpmv46 missing version

原始 PR 作者 wjinxu 合并时间 2026-06-11 17:20 文件变更 3 提交数 4 评论 2 代码增减 +32 / -2

执行摘要

修复 MiniCPM-V 4.6 处理器启动崩溃

修复用户报告的问题(OpenBMB/MiniCPM-V#1113):vllm serve openbmb/MiniCPM-V-4_6 启动时因 MiniCPMV4_6ImageProcessor 缺少 version 属性而崩溃。PR body 指出 4.6 版本已有自己的图像/视频处理和提示更新逻辑,无需且不兼容为 2.x/4.0/4.5 设计的 vendored 处理器。

建议尽快合并。这是一个严重 bug 的聚焦修复,遵循了低风险、目标明确的模式。getattr 回退模式是一个好的防御性编程实践,值得在类似场景中推广。

讨论亮点

PR 没有正式的代码审查评论。作者在 PR body 中对 fix 的双层机制(get_hf_processor 覆写 + 防御性 getattr)做了清晰解释,并附带了 2.5/4.5/4.6 三个版本的端到端测试表。作者还解释了 RTD 构建状态是 stale 的(源自标签/合并计数门控,并非实际构建失败)。

实现拆解

  1. 覆写 MiniCPMV4_6ProcessingInfo.get_hf_processor():在 vllm/model_executor/models/minicpmv4_6.py 中新增方法,直接调用 self.ctx.get_hf_processor(**kwargs) 返回原生 HF 处理器,并添加 numpy ndarray 到 list 的转换以兼容 transformers v5+ 的 image_mean/image_std 归一化。
  2. 防御性修复 MiniCPMVProcessor.__init__:在 vllm/transformers_utils/processors/minicpmv.py 中将 self.version = image_processor.version 改为 self.version = getattr(image_processor, "version", None),避免硬崩溃。
  3. 同样修复 MiniCPMOProcessor.__init__:在 vllm/transformers_utils/processors/minicpmo.py 中应用相同的 getattr 回退,保持一致性。
  4. 回归验证:PR body 列出了通过 vllm serve 对 2.5、4.5 和 4.6 版本的端到端测试结果,确保旧版本路径不受影响。
文件 模块 状态 重要度
vllm/model_executor/models/minicpmv4_6.py 模型执行器 modified 7.03
vllm/transformers_utils/processors/minicpmv.py 变换器工具 modified 5.4
vllm/transformers_utils/processors/minicpmo.py 变换器工具 modified 4.83

关键符号

MiniCPMV4_6ProcessingInfo.get_hf_processor

关键源码片段

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

核心修复:覆写 get_hf_processor() 以绕过 vendored 处理器,直接返回原生 HF 处理器。

# vllm/model_executor/models/minicpmv4_6.pydef get_hf_processor(self, **kwargs: object):
    # MiniCPM-V 4.6 使用 transformers v5.7+ 原生 MiniCPMV4_6Processor,
    # 该模型有自己的图像 / 视频处理和提示更新逻辑,因此不需要(且不兼容)
    # 为 2.x/4.0/4.5 设计的 vendored MiniCPMVProcessor(其 __init__ 假设
    # 存在 legacy 的 `image_processor.version` 属性,而 4.6 已无此属性)。
    hf_processor = self.ctx.get_hf_processor(**kwargs)
​
    # NumPy 数组在 transformers 的 image_transforms.py 中被视为 Iterable 而非 Sequence
    # 参考:https://github.com/huggingface/transformers/blob/main/src/transformers/image_transforms.py#L428
    image_processor = getattr(hf_processor, "image_processor", None)
    if image_processor is not None:
        # transformers v5+ 将 `mean`/`std` 重命名为 `image_mean`/`image_std`
        for attr in ("mean", "std", "image_mean", "image_std"):
            val = getattr(image_processor, attr, None)
            if isinstance(val, np.ndarray):
                setattr(image_processor, attr, val.tolist())
​
    return hf_processor
vllm/transformers_utils/processors/minicpmv.py core-logic

防御性修复:防止因 image_processor 缺少 version 属性而硬崩溃。

# vllm/transformers_utils/processors/minicpmv.pyclass MiniCPMVProcessor(ProcessorMixin):
    # ...
    def __init__(self, image_processor=None, tokenizer=None):
        super().__init__(image_processor, tokenizer)
        # 新版(transformers v5.7+)MiniCPM-V 图像处理器(如 MiniCPMV4_6ImageProcessor)
        # 不再携带 `version` 属性。回退到 None 而非硬崩溃:`version` 仅在 `_convert`
        # 中用于特殊处理 2.5 版本的分词路径,任何非 "2.5" 的值都会走默认分支。
        self.version = getattr(image_processor, "version", None)

评论区精华

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

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

风险与影响

低风险。变更范围限于 MiniCPM-V 4.6 模型路径和两个 vendored 处理器的初始化。getattr 回退是安全的,因为 version 仅在 _convert 中用于特殊处理 2.5 版本的分词路径,任何其他值都会走默认分支。numpy ndarray 到 list 的转换兼容 transformers v5+。主要风险在于未覆盖的 AI 图像处理器变体,但目前看来影响有限。

直接影响:MiniCPM-V 4.6 模型用户现在可以在 transformers v5+ 上成功启动和运行。间接影响:MiniCPMOProcessor 的修复为 MiniCPM-o 模型提供了同样的防御性保护。对其他旧版模型(2.5/4.5)无退化风险。对整体代码库的影响很小,仅修改了三个源文件。

模型特定修复 缺少测试覆盖

关联 Issue

#1113 vllm 部署报错 AttributeError: 'MiniCPMV4_6ImageProcessor' object has no attribute 'version'

完整报告

参与讨论