Prhub

#53999 [Bugfix] Raise clear error on interleaved multimodal placeholder overcount

原始 PR 作者 hungnnvidia 合并时间 2026-08-27 17:49 文件变更 2 提交数 1 评论 7 代码增减 +31 / -1

执行摘要

多模态占位符超量时抛出清晰校验错误

在启用 interleave_mm_strings 时,_get_interleaved_text_prompt 通过 list.pop(0) 按顺序用实际占位符替换文本中的占位符。若用户文本中的占位符数量超过实际多模态数据项,pop 会在空列表上执行并抛出 IndexError,而缺少清晰的校验信息。非交错路径已在此场景下抛出 VLLMValidationError,为了一致性和更好的错误提示,需要在交错路径上也做同样的校验。

本 PR 值得精读,特别是对多模态预处理的维护者。值得关注的设计决策是:将内部低层异常(IndexError)转换为用户可读的 VLLMValidationError,并保持与非交错路径的一致性。

讨论亮点

评审中 DarkLight1337 建议仅保留端到端测试,作者随即移除了两个直接单元测试,只保留 parse_chat_messages 的端到端测试。这体现了对测试有效性的关注,避免测试过度耦合内部实现。

实现拆解

  1. 修改源码:在 vllm/entrypoints/chat_utils.py 的 _get_interleaved_text_prompt 中,将 texts[idx] = placeholder_storage[elem].pop(0) 改为先取出槽位列表 slots,若为空则抛出 VLLMValidationError,否则执行 pop(0)。
  2. 添加测试:在 tests/entrypoints/unit_tests/test_chat_utils.py 中新增 test_parse_chat_messages_interleave_placeholder_overcount_raises,通过 parse_chat_messages 验证在占位符超量时抛出 VLLMValidationError。
  3. 调整测试策略:根据评审意见,删除了两个直接针对底层函数的单元测试,仅保留通过 parse_chat_messages 的端到端测试,确保覆盖实际调用链路。
文件 模块 状态 重要度
vllm/entrypoints/chat_utils.py 前端入口 modified 6.01
tests/entrypoints/unit_tests/test_chat_utils.py 测试 modified 5.35

关键符号

_get_interleaved_text_prompt test_parse_chat_messages_interleave_placeholder_overcount_raises

关键源码片段

vllm/entrypoints/chat_utils.py core-logic

核心逻辑修改,解决占位符超量时的错误提示问题

# vllm/entrypoints/chat_utils.py
def _get_interleaved_text_prompt(
    placeholder_storage: dict[str, list], texts: list[str]
) -> str:
    for idx, elem in enumerate(texts):
        if elem in placeholder_storage:
            slots = placeholder_storage[elem]
            # 当文本中的占位符数量超过实际多模态数据项时,
            # 槽位列表为空,抛出清晰的用户可读错误,
            # 避免底层 `IndexError` 导致的困惑。
            if not slots:
                raise VLLMValidationError(
                    f"Found more '{elem}' placeholders in input prompt than "
                    "actual multimodal data items."
                )
            texts[idx] = slots.pop(0)
​
    return "\n".join(texts)
tests/entrypoints/unit_tests/test_chat_utils.py test-coverage

新增端到端测试,验证占位符超量时抛出明确错误

# tests/entrypoints/unit_tests/test_chat_utils.py
def test_parse_chat_messages_interleave_placeholder_overcount_raises(
    phi3v_model_config_mm_interleaved,
    image_url,
):
    # 仅提供一张图片,但用户文本中包含了内部图片哨兵 `<##IMAGE##>`,
    # 导致交错 prompt 引用的图片占位符多于实际图片数量。
    # 这必须作为清晰的校验错误呈现,而不是从空列表 pop 时的 `IndexError`。
    with pytest.raises(VLLMValidationError, match="placeholders in input prompt"):
        parse_chat_messages(
            [
                {
                    "role": "user",
                    "content": [
                        {"type": "image_url", "image_url": {"url": image_url}},
                        {"type": "text", "text": "<##IMAGE##>"},
                    ],
                }
            ],
            phi3v_model_config_mm_interleaved,
            content_format="string",
        )

评论区精华

测试范围调整 测试

DarkLight1337 建议仅保留端到端测试,作者移除了两个直接单元测试。

结论:仅通过 `parse_chat_messages` 进行端到端测试 · 已解决

风险与影响

该变更仅影响 _get_interleaved_text_prompt 的异常路径,对正常路径的行为无影响。风险较低,但需注意:新增的 VLLMValidationError 可能对依赖 IndexError 的调用方产生行为变化,但此类调用方本应被引导为处理正确的输入。

影响范围:启用 interleave_mm_strings 的多模态模型(如 Phi-3.5-vision)用户。改动将显著改善错误提示,便于用户定位 prompt 中占位符数量不匹配的问题。对现有正常请求无影响。

错误类型变更:`IndexError` 改为 `VLLMValidationError`

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论