Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/transformers/cli/serving/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,8 @@ def parse_tool_calls(processor, generated_ids, schema: dict) -> list[dict] | Non

Returns a list of ``{"name": str, "arguments": str}`` dicts, or ``None`` if none found.
"""
parsed = processor.parse_response(generated_ids, schema, prefix="")
parse_kwargs = {"prefix": ""} if isinstance(schema, dict) and ("version" in schema or "fields" in schema) else {}
parsed = processor.parse_response(generated_ids, schema, **parse_kwargs)
# The new response_template path returns a dict like {"tool_calls": [...]}; unwrap.
if isinstance(parsed, dict) and "tool_calls" in parsed:
parsed = parsed["tool_calls"]
Expand All @@ -225,7 +226,7 @@ def parse_tool_calls(processor, generated_ids, schema: dict) -> list[dict] | Non
if not isinstance(parsed, list):
parsed = [parsed]
tool_calls = [_normalize_tool_call(tool_call) for tool_call in parsed]
return tool_calls if tool_calls else None
return tool_calls or None


# Default start/end tokens + schema. The opening token is optional so prefilled
Expand Down
11 changes: 11 additions & 0 deletions tests/cli/test_serve.py
Original file line number Diff line number Diff line change
Expand Up @@ -1826,6 +1826,17 @@ def test_parse_multiple_tool_calls_from_text(self):
calls = parse_tool_calls(processor, text, schema)
self.assertEqual(len(calls), 2)

def test_parse_tool_calls_with_legacy_schema_does_not_pass_prefix(self):
def parse_legacy(response, schema):
return [{"name": "get_weather", "arguments": {"city": "Paris"}}]

processor = MagicMock()
processor.parse_response.side_effect = parse_legacy
schema = next(v["schema"] for k, v in _TOOL_CALL_FALLBACKS.items() if "qwen3_5" in k)
calls = parse_tool_calls(processor, "unused", schema)

self.assertEqual(calls, [{"name": "get_weather", "arguments": '{"city": "Paris"}'}])


class TestCBWorkerDeadServerIntegration(unittest.TestCase):
"""End-to-end FastAPI behavior when the CB worker has died.
Expand Down