一句话定义
工具调用(Tool Calling / Function Calling)是一种约定:你把可用工具的名称、用途、参数结构告诉模型,模型在需要时不再输出自然语言,而是输出一个结构化的调用请求。真正执行的是你的代码,模型只负责决定调用什么。
这是模型从「说」到「做」的分界线。
为什么重要
它解决了语言模型最根本的局限:模型无法访问外部世界,也无法改变外部世界。
没有工具调用,模型只能依赖训练数据里的知识;有了它,模型可以查数据库、发消息、读文件、跑代码、下单。所有 Agent 能力都建立在这个机制上。
同时它解决了一个工程难题:如何让模型的输出可被程序可靠消费。 与其解析自由文本,不如让它按 JSON Schema 输出。
一次调用的完整流程
- 你在请求里附带工具定义(JSON Schema)。
- 模型判断需要工具,返回
tool_calls,包含函数名与参数。 - 你的程序执行该函数,得到结果。
- 你把结果作为
role: "tool"的消息追加进 messages。 - 再次请求模型,它基于结果生成最终回答。
注意第 3 步:模型从不直接执行任何东西。这个「人类在环」的设计正是安全性的来源,也是所有权限控制的插入点。
设计好工具的原则
- 描述写给模型看。 工具描述是提示词,不是文档注释。要说清「什么时候该用」。
- 参数少而明确。 参数越多,模型填错概率越高。枚举优于自由文本。
- 返回结果要裁剪。 返回 10 万行日志会淹没上下文,返回摘要加关键字段更好。
- 幂等优先。 读操作远比写操作安全。写操作必须有确认机制。
- 错误要可读。 返回「参数 start_date 格式应为 YYYY-MM-DD」比返回 500 更有用。
常见的失败模式
| 现象 | 原因 | 对策 |
|---|---|---|
| 该调用时不调用 | 工具描述太模糊 | 在描述里写清触发条件 |
| 参数格式错 | 参数设计太复杂 | 减少参数、给出枚举与示例 |
| 反复调用同一个工具 | 结果不符合预期 | 在结果里明确说明「已无更多数据」 |
| 编造工具返回 | 模型幻觉 | 严格区分 tool 消息与 model 输出 |
常见误解
- 「模型在执行代码」:不是。它只是生成一个结构化的请求。
- 「工具越多越好」:工具数量会显著影响选择准确率。超过二三十个通常需要分组或按场景裁剪。
- 「有了工具就不需要 RAG」:工具是动作,RAG 是知识。两者互补。