OpenAI Tool Calls
请求结构
json
{
"model": "gpt-4.1",
"messages": [
{ "role": "user", "content": "帮我查上海天气" }
],
"tools": [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "获取指定城市天气",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "城市名"
}
},
"required": ["city"]
}
}
}
],
"tool_choice": "auto"
}响应结构
json
{
"choices": [
{
"message": {
"role": "assistant",
"content": null,
"tool_calls": [
{
"id": "call_123",
"type": "function",
"function": {
"name": "get_weather",
"arguments": "{\"city\":\"Shanghai\"}"
}
}
]
}
}
]
}Python 完整闭环示例
python
from openai import OpenAI
import json
client = OpenAI()
def get_weather(city: str):
return {"city": city, "temp": 25, "condition": "sunny"}
tools = [{
"type": "function",
"function": {
"name": "get_weather",
"description": "获取指定城市天气",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string"}
},
"required": ["city"]
}
}
}]
messages = [{"role": "user", "content": "上海天气怎么样?"}]
resp = client.chat.completions.create(
model="gpt-4.1",
messages=messages,
tools=tools
)
msg = resp.choices[0].message
if msg.tool_calls:
new_messages = list(messages)
new_messages.append({
"role": "assistant",
"content": msg.content,
"tool_calls": [tc.model_dump() for tc in msg.tool_calls]
})
for tc in msg.tool_calls:
args = json.loads(tc.function.arguments)
if tc.function.name == "get_weather":
result = get_weather(**args)
else:
result = {"error": f"unknown tool {tc.function.name}"}
new_messages.append({
"role": "tool",
"tool_call_id": tc.id,
"content": json.dumps(result, ensure_ascii=False)
})
final_resp = client.chat.completions.create(
model="gpt-4.1",
messages=new_messages,
tools=tools
)
print(final_resp.choices[0].message.content)常见注意点
arguments 是字符串
function.arguments 很多时候是 JSON 字符串,不是已经解析好的对象。
tool_choice 不同模式的含义
auto:模型自己判断none:完全不调用required:至少调用一个- 指定函数:强制某个工具
不要相信模型一定传对参数
即使 schema 写得很好,也仍然应该在宿主侧做:
- JSON 解析保护
- 类型校验
- 字段默认值处理
- 非法值拦截