深色模式
02 · 工具调用:模型怎么「按按钮」
学完你能说出:
- 工具调用(Function Calling)的完整 4 步:告诉模型有哪些工具 → 模型返回调用请求 → 程序执行 → 结果交回模型。
- 工具说明(名字、描述、参数)为什么要写清楚。
- 程序端必须做哪些检查。
先看地图
上一篇说 Agent 的核心是「模型决定调哪个工具」。这一篇讲它具体是怎么「说」出来的:不是随便一句话,而是一段程序能直接解析的结构化数据。
本篇讲 4 个点:① 工具怎么描述 → ② 一次调用的完整来回 → ③ 为什么要结构化 → ④ 程序端要防什么。
一句话本质
工具调用 = 先把「有哪些按钮、每个按钮要填什么」告诉模型;模型需要时,返回「按哪个按钮、填什么」的 JSON,由程序去按。
生活类比:餐厅点单
- 菜单(工具说明):每道菜的名字、介绍、可选项(辣度、份量)。
- 顾客(模型):看着菜单,写出点单:「宫保鸡丁,微辣,一份」。
- 后厨(程序):照单做菜,把菜端回来。
- 顾客点了菜单上没有的东西,或者写了「辣度:999」,后厨要退回去,不能照做。
一步步看:「北京明天几度?」
第 1 步:告诉模型有哪些工具
用 JSON Schema(一种描述数据格式的标准写法)描述工具:
json
{
"name": "get_weather",
"description": "查询某个城市某一天的天气预报。用户问天气、温度、要不要带伞时使用。",
"parameters": {
"type": "object",
"properties": {
"city": { "type": "string", "description": "城市名,如 北京" },
"date": { "type": "string", "description": "日期,格式 YYYY-MM-DD" }
},
"required": ["city", "date"]
}
}第 2 步:模型返回「调用请求」,而不是直接回答
json
{ "tool": "get_weather", "arguments": { "city": "北京", "date": "2026-11-10" } }第 3 步:程序检查并执行
python
args = call["arguments"] # arguments = 参数
if call["tool"] not in ALLOWED_TOOLS: # allowed 允许的;不在白名单里就拒绝
raise ValueError("未知工具")
result = get_weather(args["city"], args["date"]) # 真正去调天气接口第 4 步:把结果交回模型,让它生成最终回答
[tool 结果] {"city": "北京", "temp_low": 3, "temp_high": 12, "weather": "晴"}
[assistant] 北京明天晴,气温 3–12℃。一次工具调用,模型至少被调用两次:第一次决定调用什么,第二次根据结果写回答。
为什么这么设计
为什么要返回结构化的 JSON,而不是一句话?
- 问题:如果模型说「我想查一下北京明天的天气」,程序还得再去理解这句话,容易出错。
- 方案:约定模型输出固定格式的 JSON:工具名 + 参数。
- 好处:程序能直接解析、校验、执行,稳定可靠。
一句话答法
结构化输出让程序可以直接解析和校验调用请求,不用再理解自然语言,减少出错。
为什么工具的「描述」要写清楚?
- 问题:模型选不选这个工具、参数怎么填,全靠读描述。描述含糊,它就会选错工具或填错参数。
- 方案:描述写清楚「做什么、什么时候用」,每个参数写清含义和格式,例如「日期,格式 YYYY-MM-DD」。
- 好处:选对工具、填对参数的概率大大提高。
一句话答法
模型完全依赖工具描述来决定是否调用、怎么填参数,描述就是给模型看的说明书,写清用途和格式才能调用准确。
为什么程序端一定要校验?
- 问题:模型可能编造不存在的工具、漏填参数、填错格式,甚至被恶意输入诱导去调危险工具。
- 方案:程序端做白名单检查(只允许注册过的工具)、参数校验(类型、范围)、权限检查;危险操作需要用户确认。
- 好处:模型出错时不会造成实际损害,错误还能反馈给模型,让它重试。
一句话答法
模型的输出不可完全信任,程序必须校验工具名、参数和权限;校验失败就把错误信息返回给模型重试,危险操作要人工确认。
英文术语拆解
| 术语 | 拆开看 | 一句话意思 |
|---|---|---|
| Function Calling | function 函数 + calling 调用 | 让模型以结构化方式请求调用函数(工具) |
| Tool Use | tool 工具 + use 使用 | 同上,不同厂商的叫法 |
| JSON | JavaScript Object Notation(JS 对象表示法) | 一种通用的数据格式,{"键": 值} |
| Schema | 结构、模式 | 描述数据长什么样、有哪些字段 |
| Parameters / Arguments | 参数(定义时)/ 实参(调用时实际填的值) | 工具需要的输入 |
| required | 必需的 | 必须填的参数 |
| Whitelist | white 白 + list 名单 | 白名单:只允许名单里的 |
面试怎么问
Q:讲一下 Function Calling 的流程。
应用把可用工具的名称、描述和参数 Schema 随请求发给模型;模型判断需要调用时,返回工具名和 JSON 参数;应用校验后执行对应函数,把结果作为工具消息追加到对话中再次调用模型;模型根据结果生成最终回答,或继续发起下一次调用。
Q:模型调用工具时参数填错了怎么办?
应用端做 Schema 校验,失败时把具体的错误信息作为工具结果返回给模型,让它修正后重试,并限制重试次数;同时优化工具描述,比如写明格式和示例。
Q:工具很多(比如上百个)时会有什么问题?
所有工具描述都要占用上下文,成本上升,模型也更容易选错。可以按任务先筛出相关的少量工具再交给模型,或者把工具分组、分层。
容易混的地方
- 模型不会运行你的函数:它只返回 JSON,执行永远在你的程序里。
- 「调用了一次工具」= 至少两次模型请求:一次决定调用,一次读结果写回答。
- 一次可以请求多个工具:有的模型支持一次返回多个调用请求(比如同时查北京和上海的天气),程序可以并行执行。
和其他知识的连接
- ← 来自 Agent 是什么:这是 Agent 循环里「行动」那一步的具体实现。
- ← 来自 Prompt 与采样参数:工具描述和「只输出 JSON」本质上都是提示的一部分。
- → 影响 记忆与 MCP:MCP 把「怎么描述工具、怎么调用工具」做成了统一标准。
- → 影响 安全与评估:校验、白名单、人工确认是 Agent 安全的第一道防线。
自测 3 问
Q1:Function Calling 的 4 步是什么?
点开看答案
① 把工具的名称、描述、参数格式告诉模型;② 模型返回「调用哪个工具 + JSON 参数」;③ 程序校验后执行;④ 把执行结果交回模型,模型生成最终回答(或继续调用)。
Q2:为什么说「工具描述就是给模型看的说明书」?
点开看答案
模型完全靠读描述来判断什么时候用这个工具、参数怎么填。描述含糊就会选错工具、填错参数,所以要写清用途、使用时机和每个参数的格式。
Q3:程序端至少要做哪些检查?
点开看答案
① 工具名是否在白名单里;② 参数是否齐全、类型和格式是否正确;③ 是否有权限执行;④ 危险操作是否需要用户确认。校验失败就把错误返回给模型重试。
✅ 验收清单
- 能用「餐厅点单」类比讲清工具调用中模型和程序的分工
- 能看懂一个工具的 JSON Schema,说出 name、description、parameters、required 各是什么
- 能说出「一次工具调用至少两次模型请求」的原因
- 能讲清「为什么要结构化」「为什么要写清描述」「为什么要校验」(问题 → 方案 → 好处)
- 能说出参数填错时的处理办法
下一步该懂什么
- 一次调用会了,多步任务里「想」和「做」怎么交替进行?→ ReAct 与规划