工具调用
工具调用让模型返回一个结构化的函数调用意图,由你的代码执行并把结果交回模型。模型本身不会执行任何代码。
工具调用是两轮以上的对话。第一轮模型只返回「想调用什么、参数是什么」, 真正的执行由你完成,再把结果作为新消息发回去换取最终回答。
哪些模型支持
当前公开目录中声明了工具调用能力的模型共 10 个:
gpt-5.6-luna、gpt-5.6-sol、gpt-5.6-terra、grok-4.20-0309-non-reasoning、grok-4.20-0309-reasoning、grok-4.20-multi-agent-0309、grok-4.3、grok-4.5、grok-4.6、grok-build-0.1
该清单来自构建期的公开目录快照,会随目录变化。以 模型目录 的实时字段为准;对未声明该能力的模型传 tools 可能被忽略或直接报错。
定义工具
用 JSON Schema 描述参数。description 是提示词的一部分——模型靠它判断何时该调用,写清触发条件比堆字段更有效。
tools = [{
"type": "function",
"function": {
"name": "get_order_status",
"description": "按订单号查询订单当前状态。仅在用户明确提供订单号时调用。",
"parameters": {
"type": "object",
"properties": {
"order_id": {
"type": "string",
"description": "订单号,形如 WC-20260818-0001",
}
},
"required": ["order_id"],
"additionalProperties": False,
},
},
}]把必填项放进 required,并设置 additionalProperties: false, 可以显著减少模型编造多余参数的情况。
完整多轮流程
from openai import OpenAI
import json
client = OpenAI(api_key="...", base_url="https://chuanapi.com/v1")
messages = [{"role": "user", "content": "帮我查下 WC-20260818-0001 到哪了"}]
# 第 1 轮:模型决定要不要调用工具
first = client.chat.completions.create(
model="MODEL_ID", messages=messages, tools=tools,
)
reply = first.choices[0].message
if reply.tool_calls:
# 必须把带 tool_calls 的这条 assistant 消息原样加回历史
messages.append(reply)
for call in reply.tool_calls:
args = json.loads(call.function.arguments)
result = get_order_status(**args) # 你自己的实现
messages.append({
"role": "tool",
"tool_call_id": call.id, # 必须回填,用于配对
"content": json.dumps(result, ensure_ascii=False),
})
# 第 2 轮:把工具结果交回模型,产出面向用户的回答
second = client.chat.completions.create(
model="MODEL_ID", messages=messages, tools=tools,
)
print(second.choices[0].message.content)
else:
print(reply.content)两个细节最容易出错:带 tool_calls 的 assistant 消息 必须原样加回消息历史;每条 role: "tool" 的结果必须回填对应的 tool_call_id。 少了任一条,模型就无法把结果和请求配对。
控制是否调用工具
# 默认:由模型决定
tool_choice="auto"
# 禁止调用工具,强制直接回答
tool_choice="none"
# 强制调用指定函数(适合表单抽取这类确定场景)
tool_choice={"type": "function", "function": {"name": "get_order_status"}}并行工具调用
一次响应里 tool_calls 可能包含多项, 代表模型希望同时调用多个函数。要遍历全部并为每一项都追加一条 tool 消息——只处理第一项是常见 bug, 表现为模型反复索要同一个工具结果。
常见失败模式
- 参数幻觉:模型编造了不存在的订单号。工具内部要做校验并把错误作为结果返回, 让模型有机会追问,而不是直接抛异常中断对话。
- 死循环:模型持续请求同一个工具。给多轮流程设一个上限(例如 5 轮), 超出后改为直接回答或返回失败。
- arguments 不是合法 JSON:它是字符串,需要自己解析。解析失败时应把错误回传给模型重试, 而不是让整个请求崩掉。
- 历史无限增长:工具结果会累积进上下文并计入输入费用。长会话要裁剪旧的工具结果。