AI AgentFunction CallingTool Calling工具调用JSON Schema
Function Calling 与工具调用
工具调用的完整往返机制:tools 定义、tool_calls 响应、结果回传循环,以及失败处理与安全边界。
Function Calling 与工具调用
一句话:把工具的「说明书」(名称/描述/参数 JSON Schema)随 prompt 发给模型 → 模型不直接执行,而是输出结构化的「我要调 tool_x,参数是 {...}」→ 程序解析并执行真实函数 → 把结果以 tool 消息回传 → 模型基于结果继续生成。
完整往返(OpenAI/DeepSeek 兼容格式,背熟)
① 请求:messages 数组里追加 tools 参数(工具定义,JSON Schema):
{
"model": "deepseek-chat",
"messages": [
{"role": "system", "content": "你是门店助手,可调用工具查天气"},
{"role": "user", "content": "明天广州会下雨吗?"}
],
"tools": [
{
"type": "function",
"function": {
"name": "weather_query",
"description": "查询指定城市的天气",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string", "description": "城市名"},
"days": {"type": "integer", "enum": [1, 3, 7]}
},
"required": ["city"]
}
}
}
]
}
② 模型响应(它不会直接答,而是要求调工具):
{
"choices": [{
"message": {
"role": "assistant",
"content": null,
"tool_calls": [
{
"id": "call_abc123",
"type": "function",
"function": {
"name": "weather_query",
"arguments": "{\"city\": \"广州\", \"days\": 1}"
}
}
]
}
}]
}
③ 程序执行真实工具,把结果以 role: "tool" 回传(tool_call_id 与 ② 对应)。
④ 模型拿到工具结果后,才组织最终回答:"明天广州有小雨,记得提醒门店做雨天促销。"
Python 侧循环(核心代码,能默写)
def run_with_tools(messages, tools):
resp = client.chat.completions.create(model="deepseek-chat", messages=messages, tools=tools)
msg = resp.choices[0].message
# 有 tool_call → 执行 → 回传 → 再请求(循环直到无 tool_call/达到上限)
while msg.tool_calls:
messages.append(msg) # 把 assistant 的 tool_call 请求加进历史
for tc in msg.tool_calls: # 允许一次多个工具调用
result = exec_tool(tc.function.name, json.loads(tc.function.arguments))
messages.append({"role": "tool", "tool_call_id": tc.id, "content": json.dumps(result)})
resp = client.chat.completions.create(model="deepseek-chat", messages=messages, tools=tools)
msg = resp.choices[0].message
return msg.content
Tool 定义包含哪些要素
名称、功能描述(让模型知道何时用)、入参 JSON Schema(含类型/必填/枚举)、出参格式、调用示例。Schema 不清 → 模型大概率 1/10 场景输出格式错误 JSON。
为什么 LLM 能「选对」工具:靠的是描述写得好(什么时候用哪个、参数规则写成 if-then),不是模型有魔法。
关键工程点(面试加分)
- 模型只「提议」不执行:安全边界——真正执行在程序侧(可加白名单/审批)
- arguments 是 JSON 字符串:必须
json.loads解析,解析失败/参数非法走降级(不崩流水线) - 历史必须完整回传:assistant 的 tool_call 和 tool 的结果都要进 messages,否则模型「失忆」
- 循环上限:tool_calls 可能连环触发,要设最大轮数(防死循环烧 token)
- 多工具并行:一次响应可带多个 tool_calls,逐个执行后一起回传
工具调用失败怎么处理(结构化错误)
不能裸抛异常让模型看到堆栈。做法:对工具调用 try-catch,返回结构化错误信息({error_code, message, 是否可重试}),模型看到错误后自主决定重试/换工具/降级/告知用户。
安全硬隔离:工具层是信任边界——LLM 生成参数不可信,必须做 schema 校验、权限校验、敏感操作需确认。
为什么用 Function Calling(好处,必答)
- 突破知识截止:工具能取实时数据(天气/库存/竞品/用户画像)
- 突破能力边界:模型只会生成文本,Function Calling 让 LLM 变成「指挥中枢」,执行交给程序
- 准确可信:参数由 JSON Schema 结构化约束,输出可解析、可校验,不会幻觉出假数据
- 安全可管控:「模型只提议、程序才执行」,执行前可过白名单/权限/HITL 审批
- 可观测可留痕:每次 tool_call 的参数和结果都能落事件日志,可回放、可追责
- 组合能力:Agent = LLM 决策 + Function Calling 执行 + 循环控制——没有 Function Calling 就没有真正的 Agent