工具调用 / Function Calling
让模型按你定义的工具(函数)签名输出结构化的调用参数,你在后端执行真正的函数,再把结果喂回模型形成对话闭环。是 Agent / 自动化 / 外部系统集成的标准模式。
何时使用
- 模型需要调用你的业务系统(查订单、下单、发消息、改配置)
- 模型需要访问实时数据(数据库、搜索、内部 API)
- 对输出要求严格 schema(比纯
response_formatJSON 更适合动态分派) - 构建 Agent / 多步任务闭环
不需要 tool 调用、只想让输出严格符合某个 schema?用 结构化输出 更轻。
基础用法(OpenAI 协议 / Chat Completions)
三步循环:定义 → 模型决定调用 → 你执行并回传。
from openai import OpenAI
client = OpenAI(
api_key="your-api-key",
base_url="https://live-turing.cn.llm.tcljd.com/api/v1",
)
tools = [{
"type": "function",
"function": {
"name": "get_weather",
"description": "查询指定城市当前天气",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string", "description": "城市名"},
"unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}
},
"required": ["city"]
}
}
}]
# Turn 1: 模型决定调用工具
r1 = client.chat.completions.create(
model="turing/gpt-5.4-mini",
messages=[{"role": "user", "content": "上海今天多少度?"}],
tools=tools,
)
tool_call = r1.choices[0].message.tool_calls[0]
args = json.loads(tool_call.function.arguments)
# args == {"city": "上海", "unit": "celsius"}
# Turn 2: 你执行真函数并回传结果
r2 = client.chat.completions.create(
model="turing/gpt-5.4-mini",
messages=[
{"role": "user", "content": "上海今天多少度?"},
r1.choices[0].message, # 包含 tool_calls
{
"role": "tool",
"tool_call_id": tool_call.id,
"content": '{"temp_c": 22, "condition": "晴"}',
},
],
tools=tools,
)
print(r2.choices[0].message.content)
# -> "上海今天 22°C,晴天。"
curl $TURING_BASE_URL/chat/completions \
-H "Authorization: Bearer $TURING_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "turing/gpt-5.4-mini",
"messages": [{"role": "user", "content": "上海今天多少度?"}],
"tools": [{
"type": "function",
"function": {
"name": "get_weather",
"description": "查询指定城市当前天气",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string"},
"unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}
},
"required": ["city"]
}
}
}]
}'
控制工具选择(tool_choice)
| 取值 | 行为 |
|---|---|
"auto"(默认) | 模型自己决定是否调用工具 |
"none" | 禁止工具调用,强制走普通对话回复 |
"required" | 必须调用至少一个工具 |
{"type": "function", "function": {"name": "X"}} | 强制调用指定的工具 X |
并行调用
多数现代模型(GPT-4.1+、Claude 3.5+、Gemini 2.0+、Qwen-Plus)默认支持一次响应里发起多个并行 tool 调用。想禁用:parallel_tool_calls: false。
Anthropic Messages 协议(Claude 原生)
Claude 原生协议的 tool 定义字段名不同——用 input_schema 而不是 parameters,工具结果用 tool_result content block 回传。
from anthropic import Anthropic
client = Anthropic(
base_url="https://live-turing.cn.llm.tcljd.com/api/v1",
auth_token="your-api-key",
)
tools = [{
"name": "get_weather",
"description": "查询指定城市当前天气",
"input_schema": {
"type": "object",
"properties": {
"city": {"type": "string"},
"unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}
},
"required": ["city"]
}
}]
# Turn 1
r1 = client.messages.create(
model="turing/claude-sonnet-5",
max_tokens=1024,
messages=[{"role": "user", "content": "上海今天多少度?"}],
tools=tools,
)
# 找到 tool_use block
tool_use = next(b for b in r1.content if b.type == "tool_use")
# Turn 2: 回传结果
r2 = client.messages.create(
model="turing/claude-sonnet-5",
max_tokens=1024,
messages=[
{"role": "user", "content": "上海今天多少度?"},
{"role": "assistant", "content": r1.content},
{
"role": "user",
"content": [{
"type": "tool_result",
"tool_use_id": tool_use.id,
"content": '{"temp_c": 22, "condition": "晴"}'
}],
},
],
tools=tools,
)
Claude 原生 tool_choice
{"type": "auto"} // 默认
{"type": "any"} // 必须调用工具
{"type": "tool", "name": "X"} // 强制调用指定工具
{"type": "none"} // 禁止调用
厂商差异速查
| 供应商 | Schema 字段名 | 工具结果回传 | 强制调用 | 并行 | 特殊 |
|---|---|---|---|---|---|
| OpenAI | parameters | "role": "tool" + tool_call_id + content | tool_choice: "required" 或显式 function 对象 | ✅ | JSON Schema 全量支持 |
| Anthropic | input_schema | tool_result content block | tool_choice: "any" 或显式 tool 对象 | ✅ | 支持 cache_control 缓存工具定义 |
| Gemini | parameters | tool role message | tool_choice: "any" | ✅ | Gemini 3:多轮必须带 thought_signature(见 Gemini Thought Signatures) |
| Qwen | parameters | "role": "tool" | tool_choice 显式对象 | ✅ | 建议 qwen-plus / qwen-max 系列;部分小模型 JSON 稳定性差 |
| DeepSeek | parameters | "role": "tool" | tool_choice | ✅ | DeepSeek R1 开启思考模式时可能影响 tool 稳定性 |
跨厂商最佳实践:你走 Chat Completions 协议时,Turing 会把 OpenAI 风格的 tools 自动映射到各厂商原生格式——直接按 OpenAI 规范写即可,大部分情况无需感知厂商差异。对于 Claude 也可以走 Messages 协议获得更精细控制。
参数参考
完整请求 / 响应 schema 见:
- Chat Completions:
/api/create-chat-completion(tools、tool_choice、parallel_tool_calls) - Messages:
/api/create-message(tools、tool_choice) - Responses:
/api/create-response(tools扁平结构,无function外层)
计费影响
工具定义本身要占输入 token(description / parameters / input_schema 都会编码进去)。定义越多 / 越啰嗦,输入成本越高。建议:
- 工具定义稳定后用 Prompt 缓存 缓存
tools块(Claude 支持cache_control) - 精简
description,避免每次请求重复长文本 - 一次请求里的工具数量控制在 20 个以内,更多会降低模型准确率
常见问题
- 模型一直不调用工具 → 把
tool_choice从auto改成required,或在 system prompt 里强调"必要时使用工具" - 参数 JSON 格式错误 / 幻觉参数 → 轻量模型或临近退役模型更容易;升级到能力更强的近期模型,或加强
description约束 - Gemini 3 多轮对话报 400 → 缺
thought_signature,见 Gemini Thought Signatures - 并行调用时拿不到所有结果 → 确保 Turn 2 的消息里每个 tool_call_id 都有对应的 tool message
See also
- 结构化输出 — 单次拿到严格符合 schema 的 JSON(无需 tool 执行闭环)
- Chat Completions — 基础协议概念
- Messages (Anthropic) — Claude 原生协议下的 tool use
- Gemini Thought Signatures — Gemini 3 多轮必需
- Prompt 缓存 — 缓存
tools定义降低重复成本