mirror of
https://github.com/vllm-project/vllm.git
synced 2026-08-21 05:00:15 +00:00
[Bugfix][Tool Parser] poolside_v1: accept tool calls without newline after function name (#47311)
Signed-off-by: Joe Rowell <[email protected]>
This commit is contained in:
@@ -220,6 +220,108 @@ def test_responses_extract_tool_calls_with_flat_tools() -> None:
|
||||
assert args["content"] == content
|
||||
|
||||
|
||||
def _weather_tool() -> dict[str, Any]:
|
||||
return {
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "get_weather",
|
||||
"description": "Get the weather for a city",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {"city": {"type": "string"}},
|
||||
"required": ["city"],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def _build_weather_request(*, tool_choice: str) -> ChatCompletionRequest:
|
||||
return ChatCompletionRequest.model_validate(
|
||||
{
|
||||
"model": "poolside-test",
|
||||
"messages": [{"role": "user", "content": "weather in Paris?"}],
|
||||
"tools": [_weather_tool()],
|
||||
"tool_choice": tool_choice,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
def test_no_newline_after_name_non_streaming() -> None:
|
||||
request = _build_weather_request(tool_choice="auto")
|
||||
parser = _make_parser(request)
|
||||
|
||||
model_output = (
|
||||
"<tool_call>get_weather"
|
||||
"<arg_key>city</arg_key><arg_value>Paris</arg_value>"
|
||||
"</tool_call>"
|
||||
)
|
||||
|
||||
result = parser.extract_tool_calls(model_output, request)
|
||||
|
||||
assert result.tools_called
|
||||
assert len(result.tool_calls) == 1
|
||||
assert result.tool_calls[0].function.name == "get_weather"
|
||||
args = json.loads(result.tool_calls[0].function.arguments)
|
||||
assert args == {"city": "Paris"}
|
||||
|
||||
|
||||
def test_newline_after_name_still_parses_non_streaming() -> None:
|
||||
request = _build_weather_request(tool_choice="auto")
|
||||
parser = _make_parser(request)
|
||||
|
||||
model_output = (
|
||||
"<tool_call>get_weather\n"
|
||||
"<arg_key>city</arg_key>\n<arg_value>Paris</arg_value>\n"
|
||||
"</tool_call>"
|
||||
)
|
||||
|
||||
result = parser.extract_tool_calls(model_output, request)
|
||||
|
||||
assert result.tools_called
|
||||
assert result.tool_calls[0].function.name == "get_weather"
|
||||
args = json.loads(result.tool_calls[0].function.arguments)
|
||||
assert args == {"city": "Paris"}
|
||||
|
||||
|
||||
def test_no_newline_after_name_streaming() -> None:
|
||||
request = _build_weather_request(tool_choice="auto")
|
||||
parser = _make_parser(request)
|
||||
|
||||
model_output = (
|
||||
"<tool_call>get_weather"
|
||||
"<arg_key>city</arg_key><arg_value>Paris</arg_value>"
|
||||
"</tool_call>"
|
||||
)
|
||||
|
||||
name = ""
|
||||
args = ""
|
||||
prev = ""
|
||||
for ch in model_output:
|
||||
cur = prev + ch
|
||||
delta = parser.extract_tool_calls_streaming(
|
||||
previous_text=prev,
|
||||
current_text=cur,
|
||||
delta_text=ch,
|
||||
previous_token_ids=[],
|
||||
current_token_ids=[],
|
||||
delta_token_ids=[],
|
||||
request=request,
|
||||
)
|
||||
prev = cur
|
||||
if delta is None:
|
||||
continue
|
||||
for tc in delta.tool_calls or []:
|
||||
if tc.function is None:
|
||||
continue
|
||||
if tc.function.name:
|
||||
name += tc.function.name
|
||||
if tc.function.arguments:
|
||||
args += tc.function.arguments
|
||||
|
||||
assert name == "get_weather"
|
||||
assert json.loads(args) == {"city": "Paris"}
|
||||
|
||||
|
||||
def _stream_partial_start_token(request: ResponsesRequest):
|
||||
parser = _make_parser(request)
|
||||
delta = parser.tool_call_start_token[0]
|
||||
|
||||
@@ -76,7 +76,7 @@ class PoolsideV1ToolParser(ToolParser):
|
||||
|
||||
self.func_call_regex = re.compile(r"<tool_call>.*?</tool_call>", re.DOTALL)
|
||||
self.func_detail_regex = re.compile(
|
||||
r"<tool_call>([^\n]*)\n(.*)</tool_call>", re.DOTALL
|
||||
r"<tool_call>\s*([^\n<]+?)\s*\n?\s*(<arg_key>.*?)?</tool_call>", re.DOTALL
|
||||
)
|
||||
self.func_arg_regex = re.compile(
|
||||
r"<arg_key>(.*?)</arg_key>\s*<arg_value>(.*?)</arg_value>", re.DOTALL
|
||||
|
||||
Reference in New Issue
Block a user