你用豆包让它自动搜网页、用 Claude 让它分析 Excel、用 AI Agent 操作电脑...... 你以为 AI 真的有自我意识?
作为开发者,我必须告诉你一个真相:这是精心设计的错觉。
那个在显卡里疯狂跑的 LLM,本质上还是个词语接龙的游戏 。它是被困在服务器里的缸中大脑 ------ 看不见屏幕、摸不到键盘,唯一能做的事是预测下一个词(Next Token Prediction)。
那么问题来了:
一个只能预测下一个词的概率模型,是怎么突破物理限制、调用 API、读数据库、操作物理世界的?
答案就在三个阶段里:认知植入 + 意图识别 + runtime 介入。
一、核心公式:LLM + tools = Agent
markdown
┌─────────────────┐
│ LLM │ ← 缸中大脑(只会预测下一个词)
│ Next Token Pred │
└────────┬────────┘
│ 配上 tools
▼
┌─────────────────┐
│ tools (函数) │ ← 真正能干活的代码
└────────┬────────┘
│
▼
┌──────────┐
│ Agent │ ← 有行动力的智能体
└──────────┘
工具就是函数。LLM 本身不会执行函数,但它能「决策」要调哪个函数、填什么参数。
二、阶段 1:认知植入 ------ 把工具「降维为语言」
在 system prompt 里配置工具时,就在做一件非常精妙的事 ------ 认知植入。
2.1 为什么叫「认知植入」?
LLM 不懂什么是天气 API、也不懂数据库查询,但它听得懂语言。
所以把工具翻译成大模型能理解的使用说明书:
javascript
原始工具(传统软件世界) 认知植入(降维为语言)
───────────────────── ──────────────────
function get_weather(city) { → {
return fetch(...) "name": "get_weather",
} "description": "获取指定城市的天气",
"parameters": { "city": "string" }
}
2.2 JSON Schema ------ 约束即说明书
回忆一下数据库的 schema:
c
users 表的 schema:
name string NOT NULL UNIQUE
age int
email string
工具的 JSON Schema 也是同一个意思 ------ 用约束告诉 LLM:
js
"parameters": {
"type": "object",
"properties": {
"name": {
"type": "string", // ← 类型约束
"description": "股票名称" // ← 语义说明
}
},
"required": ["name"] // ← 必填约束
}
2.3 为什么 description 要「具体清晰」?
因为 LLM 是基于概率的,描述越模糊,决策越容易跑偏:
| description 写法 | LLM 可能的决策 |
|---|---|
"获取价格" |
拿去查菜价、房价、油价(全乱套) |
"获取指定股票的收盘价" |
精准知道这是查股票的 |
2.4 认知植入后的 LLM 状态
arduino
配置前:LLM 脑子里只有训练数据,啥外部工具都没有
配置后:LLM 脑子里多了 N 个"工具说明书"
它知道「我有 get_weather 和 get_closing_price 这两个工具可以用」
对应到代码:
js
const tools = [
{
"type": "function",
"function": {
"name": "get_closing_price", // 工具名
"description": "获取指定股票的收盘价", // 认知植入
"parameters": { ... } // 约束
}
}
]
三、阶段 2:意图识别 ------ LLM 的自言自语
3.1 用户提问后,LLM 内心的推理过程
用户问:上海的天气怎么样?
LLM 推理引擎开始工作,它会进行一系列的快速评估:
- 首先,在原始训练语料中,不能回答(因为 LLM 不知道实时天气)
- 接着绕回来,认知植入里有工具吗?
- 它真有,
get_weather工具。
3.2 LLM 的「决策动作」:停止对话,开始自言自语
AI 会停止和你的对话 ,转而开始自言自语(思考),它严格按照刚刚定义的那套说明书,去生成一段自然语言的调用代码。
LLM 输出的不是答案,而是:
js
tool_calls: [{
"type": "function",
"function": {
"name": "get_weather",
"arguments": JSON.stringify({"city": "上海"})
}
}]
3.3 关键认知:LLM 不能执行,开发者可以
LLM 不能执行,开发者可以。 它依赖的是强大的模式识别和逻辑推理 能力。 它赌这段代码发出后,会有人响应,即开发者。
这是整个 Agent 设计最妙的一点:
arduino
LLM 像个高位指挥官: "我要调 get_weather,参数是 {city: '上海'}"
↓ 它只是「说」了这句话
↓ 真正执行的是开发者的代码
你的代码(runtime): "收到!我替你调 get_weather('上海')"
↓ 拿到结果
↓ 塞回 messages 给 LLM
LLM 再次开口: "上海今天 28°C,晴"
3.4 意图识别的输出结构
js
{
role: 'assistant',
content: null, // ← 注意:content 是 null!LLM 没说人话
tool_calls: [ // ← 真正的意图在这里
{
id: 'call_abc123',
type: 'function',
function: {
name: 'get_closing_price',
arguments: '{"name":"青岛啤酒"}' // ← 字符串,要 JSON.parse
}
}
]
}
四、阶段 3:runtime 介入 ------ 真正干活的环节
4.1 什么是 runtime?
传统软件 runtime 调用工具,执行任务。node / python / java。 人 / AI 都可以调用,只管一件事,执行,拿到结果。
runtime 就是「真正执行代码的环境」:
| 谁来调 | 例子 |
|---|---|
| 人 | 程序员手写 get_closing_price('青岛啤酒') |
| AI | LLM 决策后,由你的 Node.js 代码执行 get_closing_price(args.name) |
对函数本身来说,谁调它都一样,函数只管「给我参数,我返回结果」。
4.2 关键:runtime 的结果不是直接返回给用户
不是直接返回给用户,而是返回给大模型(用户交互接口), 大模型再根据结果继续执行。
这是 Agent 和普通程序最大的区别:
普通程序:调函数 → 结果直接给用户
Agent: 调函数 → 结果给 LLM → LLM 再加工 → 给用户
为什么?因为用户问的是「青岛啤酒收盘价是多少」,工具返回的是 67.92。 如果直接把 67.92 给用户,用户看到的是个干巴巴的数字。 让 LLM 加工一下,输出「青岛啤酒的收盘价是 67.92 元」,体验好得多。
4.3 runtime 对应的代码
js
// ① 执行函数(runtime 真正干活)
const price = get_closing_price(args.name);
// ② 结果塞回 messages(不是直接给用户!)
messages.push({
role: 'tool',
content: price,
tool_call_id: toolCall.id
});
// ③ 再调一次 LLM,让它用自然语言回答用户
const finalRes = await sendMessage(messages);
五、三阶段的完整流程图
javascript
┌─────────────────────────────────────────────────────────────────┐
│ 阶段 0:认知植入(启动前一次性配置) │
│ 把所有工具翻译成 JSON Schema,塞进 tools 数组 │
│ LLM 脑子里多了一份「工具说明书」 │
└──────────────────────────────┬──────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ 用户:"青岛啤酒的收盘价是多少?" │
└──────────────────────────────┬──────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ 阶段 1:意图识别(第一次调 LLM) │
│ LLM 内心独白: │
│ ① 训练语料里有答案吗?→ 没有(实时数据) │
│ ② 认知植入里有工具吗?→ 有 get_closing_price │
│ ③ 那我调它,参数 {name: '青岛啤酒'} │
│ │
│ 输出:content=null, tool_calls=[{name, arguments}] │
└──────────────────────────────┬──────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ 阶段 2:runtime 介入(你的代码执行) │
│ ① JSON.parse(arguments) 拿到 {name:'青岛啤酒'} │
│ ② 执行 get_closing_price('青岛啤酒') → '67.92' │
│ ③ 把结果塞回 messages(role:'tool') │
└──────────────────────────────┬──────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ 阶段 3:LLM 收尾(第二次调 LLM) │
│ LLM 看到 messages 里有工具结果,开始「说人话」: │
│ "青岛啤酒的收盘价是 67.92 元" │
└─────────────────────────────────────────────────────────────────┘
六、三个核心认知
认知 1:LLM 是「决策者」,不是「执行者」
| 角色 | 干啥 | 谁来当 |
|---|---|---|
| 决策者 | 决定调哪个工具、填什么参数 | LLM |
| 执行者 | 真正跑代码、调 API、拿结果 | 你的 runtime(Node/Python) |
| 表达者 | 把干巴巴的结果加工成自然语言 | LLM(第二次调用) |
认知 2:「认知植入」是 Agent 设计的精髓
一个复杂的软件工具(get_closing_price 等),被降维成了一个纯粹的文本描述(JSON Schema)。
这不是技术妥协,而是架构选择:
- LLM 不需要真的「理解」什么是股票
- 它只需要理解「这是查股票收盘价的工具,参数是股票名」
- 这份「说明书」足够 LLM 做决策
认知 3:runtime 是 LLM 的「手脚」
LLM 是缸中大脑,runtime 就是它的手脚。
- 没有 runtime,LLM 只能停留在「我要调工具」这句话,永远执行不了
- 没有 LLM,runtime 只是个普通程序,永远不知道什么时候该调什么工具
- 两者结合,就是 Agent
七、核心知识点速记表
| 概念 | 一句话理解 |
|---|---|
| 缸中大脑 | LLM 有推理无行动力,困在服务器里只会预测下一个词 |
| Next Token Prediction | LLM 唯一能做的事:预测下一个词 |
| LLM + tools = Agent | 大脑 + 工具 = 智能体 |
| 认知植入 | 启动前把工具翻译成 JSON Schema 塞进 LLM 脑子 |
| 降维为语言 | 把复杂软件工具变成纯文本描述(说明书) |
| JSON Schema | 约束 + 说明书,告诉 LLM 工具长啥样 |
| description 要清晰 | LLM 概率随机,描述越具体决策越准 |
| 意图识别 | LLM 判断「要不要调工具、调哪个」 |
| 自言自语 | LLM 停止对话,输出 tool_calls(content=null) |
| LLM 不能执行 | LLM 只决策,真正执行靠开发者代码 |
| runtime 介入 | 你的代码真正执行函数,拿到结果 |
| 结果回传 | runtime 结果给 LLM,不是直接给用户 |
| 第二次调 LLM | 让 LLM 把工具结果加工成自然语言 |
| 精心设计的错觉 | 用户以为 AI 自主完成,其实是 LLM+runtime 配合 |
八、总结
Tool Use 的本质,是让 LLM 这个「缸中大脑」通过「认知植入」知道有哪些工具,通过「意图识别」决策调哪个,通过「runtime 介入」真正执行,最后再让 LLM 把结果说成人话。
三个阶段口诀
javascript
认知植入 → 开局配置 tools,把函数翻译成 JSON 说明书
意图识别 → LLM 决策调哪个工具,输出 tool_calls
runtime → 开发者代码执行函数,结果回传给 LLM
为什么这是个「精心设计的错觉」
| 用户看到的 | 真实发生的 |
|---|---|
| AI 自己查了股价并回答 | LLM 只是「说」要调工具,开发者代码执行了 |
| AI 有自我意识 | LLM 只是在做概率预测,runtime 在配合演戏 |
| AI 一气呵成 | 实际是「调 LLM → 执行工具 → 再调 LLM」多步流程 |
但这个错觉不是欺骗,而是工程上的精妙分工:LLM 负责「想」,runtime 负责「做」,组合起来就是 Agent。所有复杂的 AI 应用(Claude Code、Cursor、豆包、Copilot)都是这个模式的延伸。