揭开 AI Agent 工具调用的神秘面纱 ------ 一个"缸中大脑"如何突破物理限制,完成调用 API、查询数据库、操作工具等任务。
📑 目录
- [一、Tool Use 是什么?](#一、Tool Use 是什么? "#%E4%B8%80tool-use-%E6%98%AF%E4%BB%80%E4%B9%88")
- [1.1 Agent 的核心公式](#1.1 Agent 的核心公式 "#11-agent-%E7%9A%84%E6%A0%B8%E5%BF%83%E5%85%AC%E5%BC%8F")
- [1.2 缸中大脑 ------ LLM 的物理困境](#1.2 缸中大脑 —— LLM 的物理困境 "#12-%E7%BC%B8%E4%B8%AD%E5%A4%A7%E8%84%91--llm-%E7%9A%84%E7%89%A9%E7%90%86%E5%9B%B0%E5%A2%83")
- [1.3 现实中的 Tool Use](#1.3 现实中的 Tool Use "#13-%E7%8E%B0%E5%AE%9E%E4%B8%AD%E7%9A%84-tool-use")
- [二、Tool Use 三阶段原理](#二、Tool Use 三阶段原理 "#%E4%BA%8Ctool-use-%E4%B8%89%E9%98%B6%E6%AE%B5%E5%8E%9F%E7%90%86")
- [2.1 第一阶段:认知植入](#2.1 第一阶段:认知植入 "#21-%E7%AC%AC%E4%B8%80%E9%98%B6%E6%AE%B5%E8%AE%A4%E7%9F%A5%E6%A4%8D%E5%85%A5")
- [2.2 第二阶段:意图识别](#2.2 第二阶段:意图识别 "#22-%E7%AC%AC%E4%BA%8C%E9%98%B6%E6%AE%B5%E6%84%8F%E5%9B%BE%E8%AF%86%E5%88%AB")
- [2.3 第三阶段:Runtime 介入](#2.3 第三阶段:Runtime 介入 "#23-%E7%AC%AC%E4%B8%89%E9%98%B6%E6%AE%B5runtime-%E4%BB%8B%E5%85%A5")
- [三、动手实战 Demo](#三、动手实战 Demo "#%E4%B8%89%E5%8A%A8%E6%89%8B%E5%AE%9E%E6%88%98-demo")
- [3.1 项目结构](#3.1 项目结构 "#31-%E9%A1%B9%E7%9B%AE%E7%BB%93%E6%9E%84")
- [3.2 工具定义 ------ JSON Schema 说明书](#3.2 工具定义 —— JSON Schema 说明书 "#32-%E5%B7%A5%E5%85%B7%E5%AE%9A%E4%B9%89--json-schema-%E8%AF%B4%E6%98%8E%E4%B9%A6")
- [3.3 完整调用流程](#3.3 完整调用流程 "#33-%E5%AE%8C%E6%95%B4%E8%B0%83%E7%94%A8%E6%B5%81%E7%A8%8B")
- 四、核心概念关系总图
- 五、关键要点总结
一、Tool Use 是什么?
1.1 Agent 的核心公式
ini
LLM + Tools = Agent
Tool Use(工具调用)是让大语言模型突破"纯文本生成"限制的关键技术。它赋予了 LLM 与外部世界交互的能力,将"只会说话的模型"变成了"能办事的智能体"。
这就解释了为什么:
- 豆包 可以自动搜索网页(日期工具 + 网络搜索工具)
- Claude 可以分析 Excel 表格(文件读取 + 数据分析工具)
- AI Agent 可以操作电脑(模拟鼠标键盘 + 屏幕识别)
1.2 缸中大脑 ------ LLM 的物理困境
那个在显卡里疯狂跑的 LLM,本质上还是个词语接龙游戏 。它是被困在服务器里的缸中大脑。它看不见屏幕,摸不到键盘。
LLM 本质上是一个 Next Token Prediction(下一个词预测)的概率模型。它的核心局限在于:
| 能力 | LLM 能做吗? |
|---|---|
| 预测下一个词 | ✅ 可以 |
| 调用外部 API | ❌ 不能 |
| 查询数据库 | ❌ 不能 |
| 读取实时文件 | ❌ 不能 |
| 操作物理世界 | ❌ 不能 |
那么问题来了:一个只能预测下一个词的概率模型,怎么突破物理限制?
答案就是 ------ Tool Use。它不是一个功能开关,而是一套精心设计的协作协议。
1.3 现实中的 Tool Use
| 产品 | 工具能力 | 实际场景 |
|---|---|---|
| 豆包 | 日期获取 + 网页搜索 | 自动检索最新信息 |
| Claude | 文件读取 + 数据分析 | 分析 Excel 表格 |
| AI Agent | 屏幕识别 + 键鼠操作 | Mac mini 上操作电脑 |
二、Tool Use 三阶段原理
Tool Use 不是让 LLM 直接调用工具,而是通过三个精心设计的阶段,将工具降维为语言,让 LLM 间接完成任务。
2.1 第一阶段:认知植入
核心思想:将工具降维为语言。
在 System Prompt 中配置工具时,开发者就在做一件非常精妙的事情 ------ 认知植入。LLM 不懂什么是天气 API,也不懂数据库查询,但它听得懂语言。
通过 JSON Schema ,复杂的软件接口被翻译成大模型能理解的使用说明书:
json
{
"type": "function",
"function": {
"name": "get_weather",
"description": "获取指定城市的天气",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "城市名称"
}
},
"required": ["city"]
}
}
}
scss
┌──────────────────────┐ JSON Schema ┌──────────────────────┐
│ 复杂软件函数 │ ◀─────────────────▶ │ LLM 可理解的语言 │
│ │ 认知植入 │ │
│ getWeather(city) │ 降维为说明书 │ "获取指定城市的天气" │
│ queryDB(sql) │ │ "查询数据库" │
│ readFile(path) │ │ "读取文件内容" │
└──────────────────────┘ └──────────────────────┘
关键要点:
- LLM 有概率随机性,工具描述必须具体、清晰
- Schema 中的
description决定 LLM 何时选择使用工具 - 参数约束(
required、type)保证调用格式正确
2.2 第二阶段:意图识别
核心思想:LLM 不执行工具,它只负责"说出"要调用哪个工具。
当用户提问 "上海的天气怎么样?",LLM 推理引擎开始工作:
bash
用户:"上海的天气怎么样?"
│
▼
┌──────────────────────────────────────┐
│ LLM 推理引擎快速评估: │
│ ① 训练语料中能回答吗?→ 不能(实时数据)│
│ ② 认知植入中有工具吗?→ 有!get_weather │
│ ③ 生成 tool_calls,中断文字生成 │
└──────────────────────────────────────┘
│
▼
tool_calls: [{
id: "call_xxx",
type: "function",
function: {
name: "get_weather",
arguments: '{"city": "上海"}'
}
}]
LLM 并不是在执行工具调用 ------ 它只是按照说明书格式,生成了一个结构化的"调用请求"。它依赖强大的模式识别 和逻辑推理能力,赌这段代码发出后会有人响应。
2.3 第三阶段:Runtime 介入
核心思想:LLM 不能执行的,开发者可以。
这是 Tool Use 中最关键的环节 ------ 运行时(Runtime) 负责真正执行工具:
┌──────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────┐
│ 用户提问 │───▶│ LLM 推理 │───▶│ Runtime 执行 │───▶│ LLM 生成 │
│ │ │ 返回tool_calls│ │ 调用真实API │ │ 最终回答 │
└──────────┘ └──────────────┘ └──────────────┘ └──────────┘
│
┌──────▼──────┐
│ Node/Python │
│ 执行工具 │
│ 获取结果 │
└─────────────┘
完整的对话轮次:
| 轮次 | 角色 | 内容 |
|---|---|---|
| 1 | User | "青岛啤酒的收盘价是多少?" |
| 2 | Assistant (LLM) | tool_calls: [{ name: "get_closing_price", arguments: { name: "青岛啤酒" } }] |
| 3 | Tool (Runtime) | "67.92" |
| 4 | Assistant (LLM) | "青岛啤酒的收盘价是 67.92 元。" |
⚠️ 注意:Runtime 拿到工具结果后,不是直接返回给用户 ,而是返回给大模型。LLM 根据最开始的问题、自己的决策、Runtime 的结果这一整段上下文,生成最终的自然语言回复。
三、动手实战 Demo
项目位于 demo/ 目录,演示了完整的 Tool Use 流程。
📄 核心文件: index.mjs
3.1 项目结构
| 文件 | 说明 |
|---|---|
index.mjs |
主程序:工具定义 + 调用流程 |
package.json |
依赖:openai、dotenv |
.env |
DeepSeek API Key 配置 |
3.2 工具定义 ------ JSON Schema 说明书
javascript
const tools = [
{
type: "function",
function: {
name: "get_closing_price",
description: "获取指定股票的收盘价",
parameters: {
type: "object",
properties: {
name: { type: "string", description: "股票名称" }
},
required: ["name"]
}
}
},
{
type: "function",
function: {
name: "get_weather",
description: "获取指定城市的天气",
parameters: {
type: "object",
properties: {
city: { type: "string", description: "城市名称" }
},
required: ["city"]
}
}
}
];
3.3 完整调用流程
javascript
// ① 用户提问
let messages = [{ role: 'user', content: '青岛啤酒的收盘价是多少?' }];
// ② 第一次调用 LLM(带 tools 配置)
const response = await sendMessage(messages);
// → LLM 返回 tool_calls,而非文本回答
// ③ Runtime 执行工具函数
if (response.choices[0].message.tool_calls) {
const toolCall = response.choices[0].message.tool_calls[0];
if (toolCall.function.name === 'get_closing_price') {
const args = JSON.parse(toolCall.function.arguments);
const price = get_closing_price(args.name); // Runtime 执行!
// ④ 将工具结果追加到对话上下文
messages.push({
role: 'tool',
content: price,
tool_call_id: toolCall.id // 用 id 关联多个工具调用
});
// ⑤ 再次调用 LLM,让它根据结果生成最终回答
const finalRes = await sendMessage(messages);
// → "青岛啤酒的收盘价是 67.92 元。"
}
}
sql
Demo 执行流程
User LLM Runtime LLM
│ │ │ │
│ "收盘价?" │ │ │
│────────────────▶│ │ │
│ │ 识别意图 │ │
│ │ 生成tool_calls │ │
│ │─────────────────▶│ │
│ │ │ 执行函数 │
│ │ │ 返回 "67.92" │
│ │ │───────────────▶│
│ │ │ │ 生成回答
│ "67.92元" │ │ │
│◀─────────────────────────────────────────────────│
四、核心概念关系总图
ini
┌──────────────────────────────────────────────────────────────────────┐
│ Tool Use 知识体系 │
│ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ LLM + Tools = Agent │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ┌─────────────────┼─────────────────┐ │
│ ▼ ▼ ▼ │
│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │
│ │ 第一阶段 │ │ 第二阶段 │ │ 第三阶段 │ │
│ │ 认知植入 │ │ 意图识别 │ │ Runtime 介入 │ │
│ └─────────────────┘ └─────────────────┘ └─────────────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │
│ │ JSON Schema │ │ tool_calls │ │ 开发者执行函数 │ │
│ │ 函数 → 语言 │ │ id + name │ │ Node/Python │ │
│ │ 工具说明书 │ │ + arguments │ │ 返回结果给 LLM │ │
│ └─────────────────┘ └─────────────────┘ └─────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ 完整链路: │ │
│ │ 用户提问 → LLM识别意图 → 生成tool_calls → Runtime执行 → │ │
│ │ → 追加对话上下文 → LLM生成最终回答 → 返回用户 │ │
│ └─────────────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────────┘
三阶段对比
| 阶段 | 核心动作 | 做什么 | 关键物 |
|---|---|---|---|
| ① 认知植入 | 将工具降维为语言 | System Prompt 中配置 JSON Schema | tools 数组 |
| ② 意图识别 | LLM 决定调用哪个工具 | 中断文字生成,输出 tool_calls | tool_calls 对象 |
| ③ Runtime 介入 | 开发者执行真实函数 | 调用 API/数据库/文件系统 | role: "tool" 消息 |
五、关键要点总结
| 序号 | 要点 | 一句话 |
|---|---|---|
| ① | LLM 是缸中大脑 | 只能预测下一个词,无法直接操作物理世界 |
| ② | 工具 = 函数 | 通过 JSON Schema 将函数"翻译"成 LLM 能理解的语言 |
| ③ | LLM 不执行工具 | LLM 只负责生成 tool_calls,由 Runtime 执行 |
| ④ | 多轮对话是关键 | User → LLM → Tool → LLM,需要完整上下文链 |
| ⑤ | Agent = LLM + Tools | Tool Use 是 AI Agent 区别于普通聊天机器人的核心能力 |