From 69c9f199574e7fe3a05847f6652bf914639f4c08 Mon Sep 17 00:00:00 2001 From: Harshal Janjani Date: Fri, 29 May 2026 01:48:12 +0400 Subject: [PATCH] fix(frontend): Add multimodal placeholders to Gemma4 tool message template (#41459) Signed-off-by: Harshal Janjani Co-authored-by: Ben Browning --- examples/tool_chat_template_gemma4.jinja | 9 +++ tests/renderers/test_gemma4_chat_template.py | 69 ++++++++++++++++++++ 2 files changed, 78 insertions(+) diff --git a/examples/tool_chat_template_gemma4.jinja b/examples/tool_chat_template_gemma4.jinja index d61dd795b5..ef76582310 100644 --- a/examples/tool_chat_template_gemma4.jinja +++ b/examples/tool_chat_template_gemma4.jinja @@ -295,6 +295,15 @@ {%- endif -%} {%- endfor -%} {{- format_tool_response_block(ns_tname.name, ns_txt.s) -}} + {%- for part in tool_body -%} + {%- if part.get('type') == 'image' -%} + {{- '<|image|>' -}} + {%- elif part.get('type') == 'audio' -%} + {{- '<|audio|>' -}} + {%- elif part.get('type') == 'video' -%} + {{- '<|video|>' -}} + {%- endif -%} + {%- endfor -%} {%- else -%} {{- format_tool_response_block(ns_tname.name, tool_body) -}} {%- endif -%} diff --git a/tests/renderers/test_gemma4_chat_template.py b/tests/renderers/test_gemma4_chat_template.py index a4a0b41d05..ac13c0d4d5 100644 --- a/tests/renderers/test_gemma4_chat_template.py +++ b/tests/renderers/test_gemma4_chat_template.py @@ -343,3 +343,72 @@ class TestGemma4ChatTemplate: assert '<|"|>Alice<|"|>' in result assert "active:true" in result assert "count:42" in result + + 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 "" 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