Prhub

#40251 [Bugfix] Forward mm_processor_kwargs in offline generate APIs

原始 PR 作者 wuyingjun-lucky 合并时间 2026-04-20 15:56 文件变更 2 提交数 2 评论 7 代码增减 +279 / -4

执行摘要

修复离线生成 API 中多模态处理器参数未传递的问题,确保与聊天 API 行为一致。

根据PR body,该变更旨在修复离线生成API中mm_processor_kwargs未传递的问题,以解决多模态处理在离线路径与聊天API之间的不一致性。关联issue #40134描述了LLM离线推理中mm_processor_kwargs缺失,导致用户无法覆盖处理器参数。

建议开发者精读_preprocess_cmpl方法中的条件逻辑,这是避免配置覆盖的关键设计决策,体现了API设计中对向后兼容性和用户灵活性的权衡。同时,测试文件展示了如何通过mock验证参数传递,值得作为单元测试的参考范例。

讨论亮点

review中,gemini-code-assist[bot]指出初始实现中当mm_processor_kwargs为None时直接传递到prompt_extras会覆盖prompt字典中的配置,作者随后修正为条件性传递(只在参数非None时添加)。DarkLight1337要求添加LLM.chat的测试覆盖,作者在后续提交中补充了test_chat_forwards_mm_processor_kwargs测试函数,确保聊天路径也被验证。

实现拆解

  1. 入口点参数添加: 在vllm/entrypoints/llm.pygenerateenqueue方法中添加mm_processor_kwargs参数(类型为dict[str, Any] | None),并更新文档字符串说明其作用为覆盖processor.__call__
  2. 参数穿透链扩展: 修改_run_completion_add_completion_requests_preprocess_cmpl_preprocess_cmpl_one_preprocess_chat等方法,将mm_processor_kwargs作为关键字参数逐层传递,确保从公共API到底层渲染器的完整链路。
  3. 预处理逻辑条件化: 在_preprocess_cmpl中,只有当mm_processor_kwargs非None时,才将其构建为prompt_extras字典并传递给renderer.render_cmpl,避免覆盖prompt字典中已有的配置(关键决策点)。
  4. 测试配套全覆盖: 新增测试文件tests/entrypoints/llm/test_mm_processor_kwargs.py,包含test_generate_forwards_mm_processor_kwargstest_enqueue_forwards_mm_processor_kwargstest_chat_forwards_mm_processor_kwargs等7个测试函数,使用mock对象验证参数在公共API和内部方法中的正确传递。
文件 模块 状态 重要度
vllm/entrypoints/llm.py 入口点 modified 6.67
tests/entrypoints/llm/test_mm_processor_kwargs.py 测试 added 7.46

关键符号

generate enqueue _run_completion _add_completion_requests _preprocess_cmpl _preprocess_cmpl_one _preprocess_chat

关键源码片段

vllm/entrypoints/llm.py core-logic

核心入口点文件,修改了 generate、enqueue 等公共 API 以及内部预处理方法,是实现 mm_processor_kwargs 参数传递的关键。

def _preprocess_cmpl(
    self,
    prompts: Sequence[PromptType],
    tokenization_kwargs: dict[str, Any] | None = None,
    mm_processor_kwargs: dict[str, Any] | None = None,
) -> Sequence[EngineInput]:
    """将提示输入转换为引擎输入,支持多模态参数覆盖。    关键设计:只有当mm_processor_kwargs非None时才添加到prompt_extras,
    避免覆盖prompt字典中已有的配置。"""
    parsed_prompts = [parse_model_prompt(self.model_config, p) for p in prompts]
    renderer = self.renderer
    tok_params = renderer.default_cmpl_tok_params.with_kwargs(
        **(tokenization_kwargs or {})
    )
    # 条件性构建 prompt_extras,确保仅当显式提供参数时覆盖
    prompt_extras = (
        None
        if mm_processor_kwargs is None
        else {"mm_processor_kwargs": mm_processor_kwargs}
    )
    return renderer.render_cmpl(
        parsed_prompts,
        tok_params,
        prompt_extras=prompt_extras,
    )

评论区精华

避免覆盖 prompt 字典中的 mm_processor_kwargs 正确性

gemini-code-assist[bot] 指出:'Passing `mm_processor_kwargs` directly into `prompt_extras` when it is `None` will cause any existing `mm_processor_kwargs` defined within a `DictPrompt` to be overwritten by `None`.'

结论:作者修正实现,只在 `mm_processor_kwargs` 非 None 时添加到 `prompt_extras` 中,避免配置覆盖。 · 已解决

测试聊天路径覆盖 测试

DarkLight1337 要求:'can you also test `LLM.chat` in this file though?'

结论:作者添加了 `test_chat_forwards_mm_processor_kwargs` 测试函数,扩展测试覆盖到聊天 API。 · 已解决

风险与影响

主要风险在于参数传递逻辑可能引入回归,例如错误地覆盖prompt本地配置或遗漏传递。但通过在_preprocess_cmpl中添加条件检查mm_processor_kwargs is None来避免覆盖,降低了风险。新增的测试文件覆盖了所有关键路径,减少了未发现bug的可能性。此外,变更仅限于前端API层和预处理逻辑,对核心引擎无影响,安全性和兼容性风险较低。

对用户而言,离线生成API现在支持多模态处理器参数覆盖,使LLM.generate()LLM.enqueue()LLM.chat()行为一致,提高了API易用性和一致性。对系统影响有限,仅涉及入口点和预处理逻辑的修改,不改变推理引擎或性能特性。对团队,此修复强化了多模态功能的可靠性,并为后续相关开发提供了测试基准。

参数传递覆盖风险 测试覆盖完整性

关联 Issue

#40134 [Bug]: LLM offline infer miss mm_processor_kwargs

完整报告

参与讨论