Tool Use:从"缸中大脑"到 AI Agent 的技术真相

摘要:LLM本质是一个只会预测下一个词的缸中大脑,看不见屏幕也摸不到键盘。Tool Use通过认知植入、意图识别和Runtime执行三步,让模型"假装"会调API。本文用一个股票查询实战拆解Function Calling完整链路,揭开Agent工具调用真相。


目录

  1. [缸中大脑:LLM 的本质是一个 NTP 模型](#缸中大脑:LLM 的本质是一个 NTP 模型 "#%E4%B8%80%E7%BC%B8%E4%B8%AD%E5%A4%A7%E8%84%91llm-%E7%9A%84%E6%9C%AC%E8%B4%A8%E6%98%AF%E4%B8%80%E4%B8%AA-ntp-%E6%A8%A1%E5%9E%8B")
  2. [Tool Use 三步曲](#Tool Use 三步曲 "#%E4%BA%8Ctool-use-%E4%B8%89%E6%AD%A5%E6%9B%B2")
  3. 实战:股票查询中的完整调用链路
  4. 总结

一、缸中大脑:LLM 的本质是一个 NTP 模型

豆包能自动搜索网页,Claude 能分析 Excel 表格,AI Agent 能操作电脑------这些能力看起来像是 AI 有了自我意识,能够自主操作外部工具。

但这是一个精心设计的错觉

那个在显卡里疯狂跑的 LLM,本质上还是一个词语接龙游戏------Next Token Prediction,根据上文预测下一个最可能的词。它是被困在服务器里的"缸中大脑":看不见屏幕,摸不到键盘,不知道今天几号,也查不了数据库。

那它是怎么调用 API、读取数据库、操作物理世界工具的?答案在三个字:Tool Use。

ini 复制代码
LLM + Tools = Agent

二、Tool Use 三步曲

Tool Use 的核心,可以拆成三个阶段:认知植入 → 意图识别 → Runtime 执行

第一步:认知植入------把函数降维成语言

LLM 不懂什么是天气 API,也不懂数据库查询。但它听得懂语言。

在执行任务之前,开发者在 system prompt 中配置工具 时,做了一件极其精妙的事:把复杂的软件接口函数,翻译成大模型能理解的"说明书"------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"]
            }
        }
    }
];

这个过程就是认知植入(Cognitive Implantation) :把 SDK 函数、API 接口降维为一段纯文本描述。LLM 不需要知道 get_closing_price 在底层如何实现,它只需要知道"有一个叫做获取股票收盘价的工具,需要一个股票名称参数"。

工具描述必须足够具体清晰------LLM 是一个概率模型,描述的模糊程度直接决定它能否在正确时机选择正确工具。

第二步:意图识别------LLM 的"自言自语"

用户问:"青岛啤酒的收盘价是多少?"

LLM 的推理引擎开始工作。它在原始训练语料中学不到这个实时价格,但认知植入给了它一条线索:存在一个 get_closing_price 工具

于是 LLM 停止和用户的直接对话,转而开始"自言自语"------它严格按照工具 JSON Schema 的定义,生成一段结构化的调用代码,告诉外界它需要什么:

json 复制代码
{
    "tool_calls": [{
        "type": "function",
        "function": {
            "name": "get_closing_price",
            "arguments": "{\"name\": \"青岛啤酒\"}"
        }
    }]
}

LLM 不能执行这段代码------它只是一个预测下一个 Token 的概率模型。它只是在"赌":这段调用代码发出后,会有人响应。

这是 Tool Use 哲学上最深刻的一点:LLM 不是调用函数,而是表达了希望调用某个函数的意图。它依赖强大的模式识别和逻辑推理能力,把用户的自然语言问题翻译为精确的函数调用请求。

第三步:Runtime 介入------人(或代码)来执行

LLM 发出 tool_calls 后,轮到开发者写的 Runtime 代码上场:

javascript 复制代码
// 传统软件世界 ------ 这是真实存在的函数
function get_closing_price(name) {
    if (name === '青岛啤酒') {
        return '67.92';
    } else if (name === '贵州茅台') {
        return '1488.21';
    } else {
        return '未找到该股票';
    }
}

Runtime 拿到 tool_calls,解析出函数名和参数,执行真实函数,拿到结果------然后做一件关键的事:不是把结果直接返回给用户,而是返回给 LLM。

LLM 拿到 runtime 的执行结果后,结合原始问题和上下文,生成最终的、流畅的自然语言回复给用户。用户看来是"AI 帮我查了股价",实际上 AI 只是充当了自然语言与函数调用之间的翻译层。

flowchart LR A[用户提问] --> B[LLM 意图识别] B --> C[tool_calls 函数调用请求] C --> D[Runtime 执行真实函数] D --> E[结果返回LLM] E --> F[LLM 生成自然语言回复] F --> G[用户看到答案]

三、实战:股票查询中的完整调用链路

把三步曲串成能跑的代码。首先是 LLM 客户端和发送函数------注意 tools 参数和 tool_choice: 'auto'

javascript 复制代码
import OpenAI from 'openai';
import dotenv from 'dotenv';
dotenv.config();

const client = new OpenAI({
    apiKey: process.env.DEEPSEEK_API_KEY,
    baseURL: process.env.DEEPSEEK_BASE_URL
});

async function sendMessage(messages) {
    const res = await client.chat.completions.create({
        model: 'deepseek-v4-pro',
        messages,
        tools,              // 工具配置在此传入
        tool_choice: 'auto' // 让LLM自行判断是否调用工具
    });
    return res;
}

然后是主流程:

javascript 复制代码
async function main() {
    let messages = [
        { role: 'user', content: '青岛啤酒的收盘价是多少?' }
    ];

    // 第一次调用 ------ LLM 识别意图,返回 tool_calls
    const response = await sendMessage(messages);
    const message = response.choices[0].message;

    // 把LLM的tool_calls响应存入对话历史
    messages.push({
        role: message.role,
        content: message.content,
        tool_calls: message.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);

            // 将工具执行结果存入对话历史 ------ 关键!
            messages.push({
                role: 'tool',
                content: price,
                tool_call_id: toolCall.id  // 用id关联,支持多工具并发
            });

            // 第二次调用 ------ LLM 综合结果生成回复
            const finalRes = await sendMessage(messages);
            console.log(finalRes.choices[0].message.content);
            // "青岛啤酒的收盘价是67.92元。"
        }
    }
}
main();

完整消息流拆解

整个交互过程中 messages 数组的演化:

步骤 role content
初始 user 青岛啤酒的收盘价是多少?
LLM 返回 assistant tool_calls: [{get_closing_price, name:"青岛啤酒"}]
Runtime 注入 tool 67.92(附带 tool_call_id
LLM 再次返回 assistant 青岛啤酒的收盘价是 67.92 元

tool_call_id 的作用:当一次请求中涉及多个工具调用时(如同时查股票A和股票B),每条 tool 消息必须通过 tool_call_id 关联到对应的 tool_call,LLM 才能正确区分哪个结果对应哪个请求。


四、总结

Tool Use 用三步完成了一次"LLM 假装会调 API"的魔术:

  1. 认知植入:用 JSON Schema 把函数降维为 LLM 能懂的自然语言说明书,配置在 tools 参数中。
  2. 意图识别 :LLM 判断用户问题需要调用哪个工具,生成结构化 tool_calls 请求,停止直接回复。
  3. Runtime 执行 :开发者代码解析 tool_calls、执行真实函数、把结果注入对话历史、再次调用 LLM 生成最终回复。

理解 Tool Use,就理解了为什么 LLM 不是一个"有意识的数字大脑",而是一个被精心设计的自然语言操作系统------它不做任何事,只是不停地预测下一个 Token;真正做事的是 Runtime 里开发者写的函数。LLM 是翻译官,Runtime 是执行者,两者协作才构成了一个完整的 Agent。


------ LLM 不会调 API,但它能告诉你它想调哪个,然后你替它调。

相关推荐
前端君2 小时前
Claude Code 如何配置本地Ollama模型或别的模型(Deepseek等)
llm·agent·claude
程序员小假2 小时前
RAG文档存储与切割策略详解:从基础到进阶
agent
沉默王二3 小时前
震惊!Claude Code这五个核心概念我居然才知道!
agent·ai编程·claude
老梁agent4 小时前
一个 Agent 不够用?工业场景下的多 Agent 路由模式实战
物联网·agent
默_笙4 小时前
🍞 我用 CSS 画了一个会转的 3D 立方体,同事以为我学了 Three.js(这节课真的很神奇,我很喜欢)
javascript
贵慜_Derek4 小时前
复杂系统没法一把梭重构:Semi-Autoresearch 怎么小步迁移还不掉功能
人工智能·agent·ai编程
HjhIron4 小时前
工具调用:当LLM学会使用"武器",AI Agent的底层逻辑拆解
llm·agent
sarasuki4 小时前
JavaScript的对象、new的机制与原型包装类
javascript·后端