[Frontend] Support Tool Calling with both tool_choice='required' and $defs. (#20629)

Signed-off-by: chaunceyjiang <chaunceyjiang@gmail.com>
This commit is contained in:
Chauncey 2025-07-10 13:56:35 +08:00 committed by GitHub
parent ad6c2e1a0b
commit 8f2720def9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 56 additions and 0 deletions

View File

@ -72,8 +72,43 @@ async def test_function_tool_use(client: openai.AsyncOpenAI, model_name: str,
"The unit to fetch the temperature in",
"enum": ["celsius", "fahrenheit"],
},
"options": {
"$ref": "#/$defs/WeatherOptions",
"description":
"Optional parameters for weather query",
},
},
"required": ["country", "unit"],
"$defs": {
"WeatherOptions": {
"title": "WeatherOptions",
"type": "object",
"additionalProperties": False,
"properties": {
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"default": "celsius",
"description": "Temperature unit",
"title": "Temperature Unit",
},
"include_forecast": {
"type": "boolean",
"default": False,
"description":
"Whether to include a 24-hour forecast",
"title": "Include Forecast",
},
"language": {
"type": "string",
"default": "zh-CN",
"description": "Language of the response",
"title": "Language",
"enum": ["zh-CN", "en-US", "ja-JP"],
},
},
},
},
},
},
},

View File

@ -707,6 +707,24 @@ class ChatCompletionRequest(OpenAIBaseModel):
"required": ["name", "parameters"]
}
def get_tool_schema_defs(
tools: list[ChatCompletionToolsParam]) -> dict:
all_defs = dict[str, dict[str, Any]]()
for tool in tools:
if tool.function.parameters is None:
continue
defs = tool.function.parameters.pop("$defs", {})
for def_name, def_schema in defs.items():
if def_name in all_defs and all_defs[
def_name] != def_schema:
raise ValueError(
f"Tool definition '{def_name}' has "
"multiple schemas, which is not "
"supported.")
else:
all_defs[def_name] = def_schema
return all_defs
json_schema = {
"type": "array",
"minItems": 1,
@ -715,6 +733,9 @@ class ChatCompletionRequest(OpenAIBaseModel):
"anyOf": [get_tool_schema(tool) for tool in self.tools]
}
}
json_schema_defs = get_tool_schema_defs(self.tools)
if json_schema_defs:
json_schema["$defs"] = json_schema_defs
return json_schema
return None