Skip to content

Commit be82abf

Browse files
Denizclaude
authored andcommitted
fix: handle missing </tool_call> closing tag in parse_tool_call
When using `</tool_call>` as the stop string, vLLM stops generation BEFORE outputting the closing tag. This caused parse_tool_call() to fail because the regex required both opening and closing tags. Now handles both cases: 1. Full tag: <tool_call>...</tool_call> 2. Partial tag: <tool_call>... (when stop string is </tool_call>) This was causing 0% reward in all Fleet task training runs because valid tool calls were being rejected as "No tool call found". 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 7fa4aac commit be82abf

File tree

1 file changed

+8
-0
lines changed
  • skyrl-train/integrations/fleet

1 file changed

+8
-0
lines changed

skyrl-train/integrations/fleet/env.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,19 @@ def parse_tool_call(action: str) -> Optional[Dict[str, Any]]:
7878
- <tool_call>{"name": "...", "arguments": {...}}</tool_call>
7979
- <function_call>{"name": "...", "arguments": {...}}</function_call>
8080
81+
Also handles cases where the closing tag is missing (e.g., when </tool_call>
82+
is used as the stop string and not included in the output).
83+
8184
Returns dict with "name" and "arguments" keys, or None if not found.
8285
"""
8386
# Try common tag formats
8487
for tag in ["tool_call", "function_call"]:
88+
# First try with closing tag
8589
match = re.search(rf"<{tag}>(.*?)</{tag}>", action, re.DOTALL)
90+
if not match:
91+
# Try without closing tag (for when </tool_call> is the stop string)
92+
# Match from opening tag to end of string or next special token
93+
match = re.search(rf"<{tag}>(.*?)(?:<\||\Z)", action, re.DOTALL)
8694
if match:
8795
try:
8896
parsed = json.loads(match.group(1).strip())

0 commit comments

Comments
 (0)