2026-05-14AILLMFunction CallingAgent架构

LLM Tool Use 架构解密:从 Function Calling 到 Agent 工具链

大型语言模型能对话、能写作,但这只是表层能力。真正让它变成"数字员工"的,是**工具调用(Tool Use / Function Calling)**——让 LLM 能够搜索网页、执行代码、读写文件、操作数据库。本质上,工具调用是给 LLM 安装"手脚",让它从被动回答者变为主动执行者。

biluo·5478 words

大型语言模型能对话、能写作,但这只是表层能力。真正让它变成"数字员工"的,是工具调用(Tool Use / Function Calling)——让 LLM 能够搜索网页、执行代码、读写文件、操作数据库。本质上,工具调用是给 LLM 安装"手脚",让它从被动回答者变为主动执行者。

2025-2026年,Tool Use 已经成为所有主流 LLM API 的标配能力。GPT-4o、Claude 4、Gemini 2.5、DeepSeek-V3 都有成熟的函数调用实现。但背后的架构设计,门道很多。

为什么需要 Tool Use:超越纯文本生成

纯文本生成的 LLM 有三个根本局限:

1. 知识有截止日期。模型的权重是冻结的,无法获取实时信息。

2. 没有执行能力。它能描述"如何安装 Node.js",但无法真的执行安装。

3. 缺乏状态修改。它可以写 SQL,但无法真的操作数据库。

Tool Use 本质上是把 LLM 的"推理能力"和外部系统的"执行能力"解耦再缝合:你用 LLM 做大脑,用工具做手脚,各司其职。

Function Calling 的三种实现模式

模式一:JSON Schema 强制约束(ChatGPT Style)

这是 OpenAI 在 2023 年首创的方案,也是目前最广泛采用的模式:

`json

// 用户请求

{

"messages": [

{"role": "user", "content": "北京现在多少度?"}

],

"tools": [

{

"type": "function",

"function": {

"name": "get_weather",

"description": "获取指定城市的当前天气",

"parameters": {

"type": "object",

"properties": {

"city": {"type": "string", "description": "城市名称"}

},

"required": ["city"]

}

}

}

],

"tool_choice": "auto"

}

`

模型输出会停止生成文本,改为输出一个特殊的 tool_calls 块:

`json

{

"finish_reason": "tool_calls",

"model": "gpt-4o",

"tool_calls": [

{

"id": "call_abc123",

"type": "function",

"function": {

"name": "get_weather",

"arguments": "{\"city\": \"北京\"}"

}

}

]

}

`

前端拿到这个调用,执行工具,把结果塞回 messages 继续对话:

`json

{

"role": "tool",

"tool_call_id": "call_abc123",

"content": "{\"temperature\": \"28°C\", \"condition\": \"晴\"}"

}

`

这是同步两步式:生成 → 停止 → 执行 → 继续。优点是实现简单、可靠;缺点是交互延迟高,多工具场景下要串行等待。

模式二:Stream with Tool Delta(Anthropic Style)

Claude 3.5 和 GPT-4o 的 streaming 模式做了优化:在生成文本 token 的同时,实时流式返回 tool_use 事件,不需要等文本生成完才开始执行。

`typescript

// 伪代码:流式处理 tool_call

for await (const event of model.stream()) {

if (event.type === 'content_block_start') {

// 开始输出文本

}

if (event.type === 'content_block_delta') {

process.stdout.write(event.delta.text);

}

if (event.type === 'tool_use') {

// 工具调用请求,可以提前执行

const result = await executeTool(event.tool);

messages.push({ role: 'tool', tool_call_id: event.id, content: result });

}

}

`

这种模式的优势是工具调用可以被提前发现和处理,适合需要并行执行多个工具的场景。

模式三:Think Clause + Action Separation(DeepSeek Style)

DeepSeek-V3 采用了另一种思路:让模型在生成 tool_call 之前,先输出一段推理过程(Think),再决定调用什么工具。

`json

{

"arguments": {

"thought": "用户想知道北京天气。我需要先调用天气API...",

"city": "北京"

}

}

`

这个设计的好处是:模型在调用工具前会先自我反思,减少"工具调用幻觉"(明明不需要调用工具却调用了,或者调用了错误工具)。

多工具编排:从单步到 Agent 循环

单次工具调用场景有限,真正体现 LLM Agent 能力的是多步工具链编排

典型场景:用户说"帮我查一下特斯拉股价,然后告诉我如果我买100股,现在要花多少钱"

这需要三步:

1. 查股价(web search / financial API)

2. 计算 100 * 股价

3. 用计算结果回复用户

实现这个逻辑,有三种编排架构:

架构 A:ReAct(Reasoning + Acting)

`

Thought: 用户想知道买100股特斯拉花多少钱。我需要先查当前股价。

Action: get_stock_price

Observation: 特斯拉股价 $248.50

Thought: 现在计算 100 * 248.50

Action: calculate

Observation: 结果是 $24,850

Thought: 计算完成,可以回复用户了

Final Answer: 购买100股特斯拉需要约 $24,850

`

ReAct 的优点是推理过程透明、可审计;缺点是 token 开销大(每步都要输出 Thought/Observation)。

架构 B:Plan-and-Execute

不再一步一步来,而是先整体规划,再批量执行:

`

Plan:

1. get_stock_price("TSLA")

2. calculate.multiply(result_1, 100)

3. format_currency(result_2)

Execute Phase (parallel):

→ get_stock_price → $248.50

→ calculate.multiply($248.50, 100) → $24,850

→ format_currency → "$24,850.00"

`

Plan-and-Execute 的优势是可以并行执行独立工具,大幅降低延迟;挑战在于规划阶段就要把整个流程想清楚,一旦中间步骤失败,恢复成本高。

架构 C:Hugging Agent(Tool Loop)

这是开源社区常用的方案:一个 while 循环,持续调用工具直到 LLM 决定"任务完成"。

`python

def agent_loop(messages, max_iterations=10):

for i in range(max_iterations):

response = llm.chat(messages)

if not response.tool_calls:

# 没有更多工具调用,任务完成

return response.content

for tool_call in response.tool_calls:

result = execute_tool(tool_call)

messages.append({

"role": "tool",

"tool_call_id": tool_call.id,

"content": str(result)

})

return "达到最大迭代次数"

`

这个模式简单直接,但容易陷入循环调用(LLM 反复调用同一工具而不收敛)。

工具调用的核心挑战:幻觉与可靠性

工具调用看似美好,工程落地却有三大深坑:

坑 1:参数幻觉(Parameter Hallucination)

LLM 有时会输出符合 JSON Schema 但值完全错误的参数:

`json

// 模型生成了一个"合理但错误的"参数

{ "city": "北京", "date": "2024-15-99" } // 根本不存在的日期

`

解决思路:

  • **输出 Schema 验证层**:用 JSON Schema 库做运行时校验
  • **Few-shot Examples**:在 system prompt 里给模型看正确和错误的参数示例
  • **结构化输出(Structured Output)**:用严格的 BNF 语法替代 JSON Schema

坑 2:工具描述依赖(Tool Description Dependency)

模型调用什么工具、传什么参数,完全依赖工具描述(description)的质量。一个模糊的描述会导致模型选错工具。

`python

# 模糊描述 → 模型可能选错

{

"name": "search",

"description": "搜索信息"

}

# 精准描述 → 模型准确调用

{

"name": "search",

"description": "在 Google 上搜索实时网页信息,返回标题+摘要+链接。不适合精确数值查询。"

}

`

坑 3:状态一致性与工具幂等性

多步骤 Agent 中,前面工具的执行结果会影响后续决策。如果某个工具的状态在执行过程中发生变化(比如余额减少了),模型需要正确感知这个变化。

2026 年的 Tool Use 新趋势

MCP(Model Context Protocol):统一工具接口

Anthropic 在 2024 年末提出的 MCP,正在成为行业事实标准。它的核心思路是:把工具的发现、调用、结果返回都标准化,让同一个 Agent 可以无缝切换不同的工具后端。

`

Host (LLM) ←→ MCP Client ←→ MCP Server (工具实现)

`

不再需要为每个 LLM Provider 写不同的工具适配器,MCP Server 是一次编写、各处运行。

工具调用的安全边界

当 LLM 可以执行任意工具时,安全问题就变得尖锐:

  • 工具是否有权限检查?
  • 工具执行失败时如何优雅降级?
  • 恶意 prompt 能否诱导 LLM 执行危险操作?

行业正在形成工具权限分级模型:读取类工具(GET 请求、只读 API)开放,写入类工具(POST、DELETE、文件写入)需要二次确认。

写在最后

Function Calling 不是新概念,但 2025-2026 年的工程实践让它真正成熟。从 JSON Schema 约束到流式工具 delta,从单步调用到多工具编排,每一步都是对 LLM"推理"与"执行"边界的新探索。

工具调用的终极目标,是让 LLM 成为真正的 Agent——不只是给建议,而是真的能把事情做成。随着 MCP 等标准的普及,这个目标正在加速实现。

但别忘了:工具是放大器,用得好威力无边,用得差则是给自己埋雷。