问 AI「明天北京要不要带伞」,它张口就报降雨概率。训练数据里没有明天的天气,这个数从哪来的?
答案藏在一个叫 Function Calling(工具调用)的机制里。你平时用的联网搜索、查股价、设闹钟、读数据库,背后全是它在干活。
今天把这件事讲透。看完你就能自己给 AI 装上「手脚」。
AI 不替你干活,只给你递纸条
很多人以为 AI 会自己去查天气。其实不会。
它做的事情只有一件:输出一段 JSON,意思是「请帮我查北京的天气」。真正去调天气接口的,是你写的程序。
Kimi 官方文档里有个很清楚的比喻场景:用户、机器人、大模型三个角色。用户问机器人「今天北京天气怎么样」,机器人带着工具清单去问大模型,大模型回一张「参数纸条」,机器人照着执行,把结果再交回大模型,大模型这才生成用户看到的最终回答。
整个过程对用户是透明的。用户只看到一句「明天有雨,记得带伞」,看不到中间这张纸条飞了几个来回。
所以说白了:模型负责决定调什么、参数填什么;你的代码负责真的去干。
一轮完整的工具调用,只有六步
官方文档把流程列得很清楚,我压缩成六步:
1. 用 JSON Schema 定义工具(名字、功能、参数)
2. 通过 tools 参数把工具提交给模型,可以一次提交多个
3. 模型看当前对话,决定用哪个工具,也可以决定不用
4. 模型输出调用工具需要的参数,JSON 格式
5. 你的程序拿这些参数去执行工具,把结果回传给模型
6. 模型根据结果,生成给用户的回复
注意第三步:模型有选择权。你挂了工具,不代表它每次都用。聊「你好」这种闲聊,它直接就回了,不会碰工具。
动手定义一个工具
纸面上说完了,看真实代码。定义一个查天气的工具:
tools = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "查询指定城市的实时天气。当用户问天气、温度、要不要带伞时调用。",
"parameters": {
"type": "object",
"required": ["city"],
"properties": {
"city": {
"type": "string",
"description": "城市名,如:北京、上海"
}
}
}
}
}
]
四个字段,每个都有讲究。
name 只能用英文、数字、减号、下划线。description 要写两件事:这个工具干什么、什么时候该用它。parameters 里的每个参数也都要写 description,模型是照着它填参数的。
description 不是装饰。模型选工具、填参数,全靠这些描述文字,写得含糊它就会选错工具。智谱官方给的三条设计原则:单一职责、清晰命名、完整描述。一个函数只干一件事,别贪。
最容易踩的坑:消息要原样放回去
工具调用最劝退新手的地方,是消息列表的管理。
平时聊天,消息就是 system、user、assistant 交替。有了工具调用,中间会插进 role 为 tool 的消息,序列变成这样:
system → user → assistant(带 tool_calls) → tool(执行结果) → assistant(最终回答)
官方文档专门强调:模型返回的 assistant 消息,必须完整包含 tool_calls 字段,原样放回 messages 列表。你要是只拷了文字、丢了 tool_calls 字段,下一轮请求直接报错 tool_call_id not found。
这段代码我第一次写就报了这个错,翻文档才发现,最稳的做法是每次收到响应就把返回的 message 整个 append 进去,别自己重新拼。
还有一条:每个 tool_call 都要有对应的 tool 消息,tool_call_id 要对得上。模型一次返回两个调用,你就得回传两条结果,少一条都报错。
tool_choice:给模型上紧箍咒
默认情况下,模型自己决定调不调工具(auto)。有些场景你需要更强的控制,tool_choice 参数就是干这个的,一共四个档位:
• auto:默认,模型自己看着办
• required:强制本轮至少调一个工具
• none:禁止调用,只许纯文本回复
• 指定函数:强制调用某个具体工具
强制检索的场景用 required 很顺手,比如要求模型必须查数据库、不许凭记忆编。none 能省 token、降延迟,纯聊天时开着挺干净。
两个细节要注意。指定函数这个模式,在思考模式开启时会直接报 400,Kimi 官方原话:tool_choice 'specified' is incompatible with thinking enabled。另外各家支持程度不一样,智谱目前就只支持 auto,写跨模型代码前先查文档。
三个进阶玩法
工具挂多了,新的问题就来了。
第一,tools 定义也吃 token。官方注意事项里明确写了,tools 参数的内容会计入总 token。你挂 50 个工具,每个定义几百 token,还没开始聊,上下文先烧掉一大块。token 怎么算钱,之前写过一篇AI API 计费,可以配套看。
第二,并行调用。Kimi 支持一次返回多个 tool_calls,互不依赖的调用模型会倾向并行给出。比如「北京和上海今天多少度」,它一次返回两个调用,你并发执行,一轮搞定。
第三,工具太多时用「工具搜索」。K3 最佳实践文档给的方案:平时只声明一个 search_tools 工具,模型先搜出要用哪几个,再按需把定义注入对话。几十上百个工具的场景,这比全量塞进去省得多,选工具也更准。
执行前,把参数再验一遍
模型输出的参数,本质是生成的文本,不是你写的代码。它会填错格式,偶尔也会填出你没想到的东西。这和temperature 采样是同一件事:输出有随机性。
所以工具执行侧要做三件事:验证参数(类型、范围、必填项),控制权限(危险操作加白名单),记日志(出了问题能回溯)。这也是智谱官方文档里的安全建议。
工具调用是 Agent 的地基。你看到的 AI 帮你订机票、操作电脑、跑代码,拆开看都是这一套循环在转:模型出主意,代码干活,结果回传,模型接着想。
把这篇看懂,再去看AI Agent 科普和Agent Skills的资料就顺了。