Repository navigation
[tool] feat: add Gemma4 tool parser with stop token and response formatting - #6406
Conversation
50bf31d to
8451763
Compare
There was a problem hiding this comment.
Code Review
This pull request introduces support for Gemma4 tool parsing by adding a dedicated Gemma4ToolParser and updating the agent loop to handle its specific token formatting and stop conditions. Feedback focuses on ensuring that injected stop tokens are merged with existing sampling parameters rather than overwriting them, and correctly handling multi-modal content in tool responses to prevent formatting errors.
| for msg, name in zip(add_messages, tool_call_names): | ||
| content = msg.get("content", "") | ||
| parts.append(f'<|tool_response>response:{name}{{value:<|"|>{content}<|"|>}}<tool_response|>') | ||
| tool_response_text = "".join(parts) |
There was a problem hiding this comment.
When formatting tool responses for Gemma4, the code assumes msg["content"] is a string. However, for multi-modal tools, content is a list of dictionaries. Using a list in the f-string will result in an incorrect format for the model. The text content should be extracted if it's a list.
for msg, name in zip(add_messages, tool_call_names):
content = msg.get("content", "")
if isinstance(content, list):
content = "".join([item.get("text", "") for item in content if item.get("type") == "text"])
parts.append(f'<|tool_response>response:{name}{{value:<|"|>{content}<|"|>}}<tool_response|>')
tool_response_text = "".join(parts)8451763 to
af459af
Compare
af459af to
85e697e
Compare
|
@wuxibin89 Done — ran ruff check --fix and ruff format per the contributing guide and pre-commit showed all green. Anything else needed? |
What does this PR do?
Adds Gemma4 support to the multi-turn agent loop for tool calling. Gemma4 has two differences from existing models (Qwen, GPT-OSS) that prevent tool calling from working:
No EOS after tool calls — Gemma4 generates
<|tool_call>call:func{args}<tool_call|>then immediately continues generating. Without an explicit stop token, vLLM never stops and the model generates all toolcalls in one turn, hallucinating responses.
Tool response format requires function name — Gemma4's chat template needs
<|tool_response>response:FUNC_NAME{value:"content"}<tool_response|>. The standardapply_chat_template({"role": "tool"})pathsilently drops the content because it lacks the function name context.
Changes
verl/experimental/agent_loop/tool_parser.pystop_token_idsproperty toToolParserbase class (returns[]by default)Gemma4ToolParserclass withstop_token_ids=[49](<tool_call|>token)<|tool_call>call:func{args}<tool_call|>verl/experimental/agent_loop/tool_agent_loop.pystop_token_idsfrom tool parser intosampling_paramsbefore generationgpt-osscase)Config
Tested with Gemma4-26B-A4B on multi-turn tool dataset
Checklist Before Starting
[{modules}] {type}: {description}(This will be checked by the CI){modules}includefsdp,megatron,veomni,sglang,vllm,rollout,trainer,ci,training_utils,recipe,hardware,deployment,ray,worker,single_controller,misc,perf,model,algo,env,tool,ckpt,doc,data,cfg,reward,fully_async,one_step_off,like[megatron, fsdp, doc]{type}is infeat,fix,refactor,chore,test[BREAKING]to the beginning of the title.[BREAKING][fsdp, megatron] feat: dynamic batchingTest
No stop token, no response fix - 0%
Stop token only - 13.6%
Stop token + response formatting - 59.2%
Design & Code Changes
Follows the same pattern as the existing
gpt-osstool parser implementation:Gemma4ToolParserintool_parser.py— parses Gemma4's special-token tool call formattool_agent_loop.py— manual formatting whenapply_chat_templatecan't handle the model's response formatOne addition to the base class:
stop_token_idsproperty onToolParser(returns[]by default). This is needed because Gemma4 doesn't emit EOS after tool calls — unlike Qwen/GPT-OSS which do. The agent loopinjects these into
sampling_paramsbefore generation.Checklist Before Submitting
Important
Please check all the following items before requesting a review, otherwise the reviewer might deprioritize this PR for review.
pre-commit install && pre-commit run --all-files --show-diff-on-failure --color=alwaysci-requestchannel in theverlSlack workspace. (If not accessible, please try the Feishu group (飞书群).)recipesubmodule, please also update the reference to the submodule commit viagit submodule update --remoteorcd recipe && git pull origin main.