跳到主要内容

工具调用 / Function Calling

让模型按你定义的工具(函数)签名输出结构化的调用参数,你在后端执行真正的函数,再把结果喂回模型形成对话闭环。是 Agent / 自动化 / 外部系统集成的标准模式。

何时使用

  • 模型需要调用你的业务系统(查订单、下单、发消息、改配置)
  • 模型需要访问实时数据(数据库、搜索、内部 API)
  • 对输出要求严格 schema(比纯 response_format JSON 更适合动态分派)
  • 构建 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 字段名工具结果回传强制调用并行特殊
OpenAIparameters"role": "tool" + tool_call_id + contenttool_choice: "required" 或显式 function 对象JSON Schema 全量支持
Anthropicinput_schematool_result content blocktool_choice: "any" 或显式 tool 对象支持 cache_control 缓存工具定义
Geminiparameterstool role messagetool_choice: "any"Gemini 3:多轮必须带 thought_signature(见 Gemini Thought Signatures
Qwenparameters"role": "tool"tool_choice 显式对象建议 qwen-plus / qwen-max 系列;部分小模型 JSON 稳定性差
DeepSeekparameters"role": "tool"tool_choiceDeepSeek R1 开启思考模式时可能影响 tool 稳定性

跨厂商最佳实践:你走 Chat Completions 协议时,Turing 会把 OpenAI 风格的 tools 自动映射到各厂商原生格式——直接按 OpenAI 规范写即可,大部分情况无需感知厂商差异。对于 Claude 也可以走 Messages 协议获得更精细控制。


参数参考

完整请求 / 响应 schema 见:


计费影响

工具定义本身要占输入 token(description / parameters / input_schema 都会编码进去)。定义越多 / 越啰嗦,输入成本越高。建议

  • 工具定义稳定后用 Prompt 缓存 缓存 tools 块(Claude 支持 cache_control
  • 精简 description,避免每次请求重复长文本
  • 一次请求里的工具数量控制在 20 个以内,更多会降低模型准确率

常见问题

  • 模型一直不调用工具 → 把 tool_choiceauto 改成 required,或在 system prompt 里强调"必要时使用工具"
  • 参数 JSON 格式错误 / 幻觉参数 → 轻量模型或临近退役模型更容易;升级到能力更强的近期模型,或加强 description 约束
  • Gemini 3 多轮对话报 400 → 缺 thought_signature,见 Gemini Thought Signatures
  • 并行调用时拿不到所有结果 → 确保 Turn 2 的消息里每个 tool_call_id 都有对应的 tool message

See also