执行摘要
- 一句话:修复Gemma4工具消息中多模态占位符丢失
- 推荐动作:建议合并。该 PR 修复了用户报告的问题,且与上游 HuggingFace 模板保持同步。测试覆盖充分,风险低。值得关注的是多模态 tool 消息的模板处理方式,可推广到其他支持 tool-calling 的模型。
功能与动机
Issue #41452 报告 Gemma4 无法处理工具消息中的多模态内容。PR body 指出上游 chat_template.jinja 只提取 type == "text" 部分,丢弃图像/音频/视频条目。通过此 PR 修复了 vLLM 的示例模板,并同时提交了上游 HF PR 修复。
实现拆解
- 修改 Jinja 模板:在
examples/tool_chat_template_gemma4.jinja 的工具消息文本内容渲染之后,新增循环 tool_body 部分,对每个内容项检查类型,若非文本则输出对应占位符(image/audio/video)。
- 添加测试用例:在
tests/renderers/test_gemma4_chat_template.py 中新增 test_tool_response_with_multimodal_content 和 test_tool_response_with_all_modalities,分别测试单一模态和所有模态在工具响应中的渲染。
- 验证:运行通过全部模板测试(16 个)、多模态处理和工具/推理解析器测试(77 个),未引入回归。
关键文件:
tests/renderers/test_gemma4_chat_template.py(模块 模板测试;类别 test;类型 test-coverage;符号 test_tool_response_with_multimodal_content, test_tool_response_with_all_modalities): 新增两个测试用例,验证多模态内容在工具消息中被正确渲染,防止回归。
examples/tool_chat_template_gemma4.jinja(模块 工具模板;类别 other;类型 core-logic): 核心修复:在工具响应文本后增加非文本内容占位符输出,使多模态内容不再被丢弃。
关键符号:test_tool_response_with_multimodal_content, test_tool_response_with_all_modalities
关键源码片段
tests/renderers/test_gemma4_chat_template.py
新增两个测试用例,验证多模态内容在工具消息中被正确渲染,防止回归。
def test_tool_response_with_multimodal_content(self, gemma4_template):
"""Multimodal placeholders in tool messages are emitted after the
tool_response block."""
# 构造包含图像的工具响应消息
messages = [
{"role": "user", "content": "Download the image and describe it."},
{
"role": "assistant",
"content": "",
"tool_calls": [
{
"id": "call_1",
"type": "function",
"function": {
"name": "download_image",
"arguments": '{"url": "https://example.com/x.png"}',
},
},
],
},
{
"role": "tool",
"tool_call_id": "call_1",
"content": [
{"type": "text", "text": "Image downloaded successfully."},
{"type": "image"},
],
},
]
result = _render(gemma4_template, messages, add_generation_prompt=True)
# 断言工具响应块和图像占位符正确出现
assert "<|tool_response>" in result
assert "response:download_image{" in result
assert "<tool_response|>" in result
assert "<|image|>" in result
def test_tool_response_with_all_modalities(self, gemma4_template):
"""All multimodal types (image, audio, video) in a single tool
response are rendered."""
# 构造包含多种多模态内容的工具响应
messages = [
{"role": "user", "content": "Process media"},
{
"role": "assistant",
"content": "",
"tool_calls": [
{
"id": "c1",
"type": "function",
"function": {
"name": "process",
"arguments": "{}",
},
},
],
},
{
"role": "tool",
"tool_call_id": "c1",
"content": [
{"type": "text", "text": "Results."},
{"type": "image"},
{"type": "audio"},
{"type": "video"},
],
},
]
result = _render(gemma4_template, messages, add_generation_prompt=True)
# 断言所有占位符都被渲染
assert "<|image|>" in result
assert "<|audio|>" in result
assert "<|video|>" in result
评论区精华
Review 中主要讨论了与上游 HuggingFace 模板的同步策略。
风险与影响
- 风险:低风险。变更仅影响 Gemma4 模型的聊天模板渲染,作用域明确。新增测试覆盖了主要多模态场景,确保模板正确处理。需要注意的是,如果上游模板未来有改动,此示例模板可能再次不同步,但这是维护成本而非直接风险。
- 影响:对使用 Gemma4 模型且启用 tool-calling 并传入多模态 tool 响应的用户有直接影响:之前多模态内容被静默丢弃,现在被正确渲染为占位符。影响程度中等,修复了明确 bug。对其他模型无影响。
- 风险标记:低风险, 测试覆盖新增
关联脉络
参与讨论