从“被动问答”到“主动自治”:大模型 Agent 架构设计深度剖析

引言

自从 ChatGPT 横空出世,大语言模型(LLM)经历了从“段子手”到“百科全书”的进化。然而,纯文本交互的边界终究有限。如果说大模型是一个拥有海量知识的“超级大脑”,那么 Agent(智能体) 就是赋予了这位大脑“感知”、“记忆”和“行动”能力的“数字员工”。

吴恩达教授在 2024 年初曾提出一个深刻的洞察:基于 Agent 的工作流将在今年推动 AI 取得巨大进步,甚至可能超过下一代基础模型本身。

从单一的对话机器人,到能够自主规划任务、调用外部工具(API)、甚至多智能体协作完成复杂系统,Agent 的架构设计已经成为当前 AI 工程界最核心的命题。本文将从理论到工程实践,深度剖析 Agent 架构设计的三大核心支柱:ReAct(推理与行动)、Tool Use(工具调用)与 Multi-Agent(多智能体协同)


一、 破局:从 CoT 到 ReAct 的范式跃迁

在早期的 LLM 应用中,我们遇到了一个瓶颈:模型很容易产生“幻觉”。当遇到复杂问题时,模型往往会在缺乏中间推导的情况下给出看似合理但实则错误的答案。

1. CoT (Chain of Thought) 的局限

为了解决这个问题,学术界提出了 CoT(思维链)。通过在 Prompt 中加入 “Let’s think step by step”,引导模型逐步推理。然而,CoT 的致命弱点在于:它完全依赖于模型的内部知识,是一个“闭门造车”的过程。 如果模型本身不知道今天的天气,或者不知道某只股票的实时价格,思维链再长也无济于事。

2. ReAct (Reason + Act) 的诞生

2022 年,谷歌的研究人员提出了 ReAct 范式。ReAct 的核心思想是:将大模型的推理能力与行动能力结合起来,通过与外部环境的交互来获取信息并更新认知。

在 ReAct 框架下,Agent 的运行被拆解为一个不断循环的迭代过程:

  1. Thought(思考):分析当前的任务和观察到的信息,决定下一步该做什么。
  2. Action(行动):根据思考结果,调用外部工具或 API。
  3. Observation(观察):获取工具返回的结果。

举个例子:当你问 Agent “苹果公司今天的市值是多少?”

  • Thought: 我需要查询苹果公司(AAPL)今天的实时股价,然后再计算市值。
  • Action: 调用 get_stock_price(ticker="AAPL")
  • Observation: 股价为 180.5 美元。
  • Thought: 我已经获得了股价,接下来我需要查询苹果公司的总股本。
  • Action: 调用 get_outstanding_shares(ticker="AAPL")
  • Observation: 总股本为 15.5 亿股。
  • Thought: 我现在可以计算市值了(180.5 * 15.5亿),并回答用户的问题。

通过这种“边想边做”的模式,Agent 的可靠性得到了质的飞跃,这也是目前市面上几乎所有主流 Agent 框架(如 LangChain, AutoGen)的底层基石。


二、 触碰真实世界:Tool Use 的工程实现

ReAct 提供了理论框架,而 Tool Use(工具调用) 则是 Agent 触碰真实世界的双手。

让大模型使用工具,本质上是将自然语言转化为结构化的 API 调用。现代 LLM(如 GPT-4, Claude 3.5, GLM-5 等)原生支持了 Function Calling 功能,极大地降低了 Tool Use 的工程门槛。

Tool Use 的核心机制

  1. 工具定义:开发者使用 JSON Schema 描述工具的名称、描述和所需参数。
  2. 意图识别与参数提取:模型根据用户的 Prompt 和提供的工具列表,判断是否需要使用工具,并提取出 JSON 格式的参数。
  3. 代码执行与结果注入:应用程序接管模型返回的 JSON,执行对应代码,将结果追加到上下文中,再次交由模型总结。

实战代码:构建一个基于 OpenAI API 的 Tool Use Agent

下面我们用一段不到 100 行的 Python 代码,手动从零实现一个具备 Tool Use 和 ReAct 循环的最小化 Agent。这比直接使用 LangChain 更能让你理解底层机制。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
import json
from openai import OpenAI

# 初始化客户端
client = OpenAI(api_key="your-api-key", base_url="your-base-url")
MODEL_NAME = "gpt-4o-mini"

# 1. 定义本地工具函数
def get_weather(location: str) -> str:
"""模拟获取天气的API"""
# 实际工程中这里是一个真实的 HTTP 请求
weather_data = {
"北京": "晴天,气温 15 摄氏度,空气质量优",
"上海": "小雨,气温 18 摄氏度"
}
return weather_data.get(location, f"未找到{location}的天气数据")

# 2. 为 LLM 提供工具的 JSON Schema 描述
tools_schema = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "获取指定城市的实时天气情况",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "城市名称,例如:北京、上海",
}
},
"required": ["location"],
},
}
}
]

# 将工具函数映射到字典中,方便动态调用
available_functions = {
"get_weather": get_weather,
}

def run_agent(user_query: str, max_steps: int = 5):
messages = [{"role": "user", "content": user_query}]

for step in range(max_steps):
print(f"--- Step {step + 1} ---")

# 调用大模型
response = client.chat.completions.create(
model=MODEL_NAME,
messages=messages,
tools=tools_schema,
tool_choice="auto", # 让模型自行决定是否调用工具
)
response_message = response.choices[0].message

# 将大模型的回复加入上下文历史
messages.append(response_message)

# 检查模型是否决定调用工具
if not response_message.tool_calls:
print("Agent 最终回复:", response_message.content)
break

# 遍历所有工具调用
for tool_call in response_message.tool_calls:
function_name = tool_call.function.name
function_to_call = available_functions[function_name]

# 解析模型提取的参数
function_args = json.loads(tool_call.function.arguments)
print(f" [Thought] 需要调用工具获取信息...")
print(f" [Action] 调用函数: {function_name}({function_args})")

# 执行本地工具函数
function_response = function_to_call(**function_args)
print(f" [Observation] 获取到结果: {function_response}")

# 将工具执行结果追加到上下文中
messages.append(
{
"tool_call_id": tool_call.id,
"role": "tool",
"name": function_name,
"content": str(function_response),
}
)

# 运行测试
if __name__ == "__main__":
run_agent("我今天要去上海出差,请问需要带伞吗?")

代码解析:
在这段代码中,我们放弃了死板的 Prompt 控制,转而使用现代 LLM 的原生能力。当大模型发现仅靠自身知识无法回答问题时,它会返回一个特殊的 tool_calls 对象。我们的代码截获这个对象,执行对应函数,并将结果(Observation)塞回上下文,大模型即可根据最新获取的信息给出准确回答。


三、 涌现的力量:Multi-Agent 架构设计

随着业务复杂度的指数级上升,单一 Agent 开始显得力不从心。就像一家初创公司,起初老板(单个 Agent)身兼数职,但随着业务扩大,必须雇佣专业的财务、销售和工程师。

Multi-Agent System (MAS) 应运而生。在 MAS 中,多个具备不同角色、不同工具集、甚至不同系统提示词的 Agent 协同工作。

常见的 Multi-Agent 编排架构

1. 主从架构

这是目前最主流、最容易落地的架构。由一个 Supervisor(主控 Agent) 负责理解用户意图、拆解任务和分配工作,其他 Worker Agents 负责具体执行。

  • 优点:控制力强,流程清晰,不容易出现死循环。
  • 适用场景:复杂的单线任务,如自动化软件开发、深度行业调研。

2. 辩论式架构

让多个拥有相同级别权限但初始设定(偏见)不同的 Agent 针对同一问题进行辩论。

  • 优点:极大地提升结果的鲁棒性和逻辑严密性,减少幻觉。
  • 适用场景:代码 Review、投资决策分析、高风险领域的逻辑推演。

3. 流水线架构

任务像工厂流水线一样,被拆分为多个串行的阶段,上一个 Agent 的输出作为下一个 Agent 的输入。

  • 适用场景:内容创作(Writer Agent 起草 -> Reviewer Agent 审核 -> Editor Agent 润色)。

实战设计:构建基于“主从架构”的自动化研发团队

假设我们要构建一个自动化软件开发系统,我们可以这样设计架构:

  1. Product Manager Agent (产品经理)

    • 系统提示词:你是一个产品经理,擅长将用户需求转化为详细的 PRD 文档。
    • 工具:浏览器搜索、文档系统。
    • 任务:接收需求,输出 PRD。
  2. Engineer Agent (工程师)

    • 系统提示词:你是一个高级 Python 工程师,根据 PRD 编写高质量代码。
    • 工具:Terminal, IDE, 本地文件系统读写。
    • 任务:接收 PRD,输出代码文件。
  3. QA Agent (测试工程师)

    • 系统提示词:你是一个测试工程师,编写单元测试验证代码。
    • 工具:Terminal(执行 pytest)。
    • 任务:接收代码,执行测试,返回 Bug 报告。
  4. Supervisor Agent (架构师/主控)

    • 负责:统筹 PM、Eng、QA 之间的交互。如果 QA 发现 Bug,Supervisor 会将 Bug 报告打回给 Eng 修改,直到所有测试通过。

(注:微软的 AutoGen 和最近极其火爆的 Meta GPT 就是这种架构的典型工业级实现。)


四、 架构演进:从工作流到长短期记忆(RAG 与 Agent 的融合)

在构建高级 Agent 时,纯粹的无状态 ReAct 是不够的。Agent 必须具备记忆

  1. 短期记忆:通过对话上下文管理。在代码中体现为 messages 列表。但由于 LLM 的 Token 限制,早期对话会被截断。
  2. 长期记忆:结合向量数据库(如 Milvus, Pinecone, ChromaDB)。Agent 可以将重要的中间状态或过去的经验写入向量库,在未来遇到相似任务时先去数据库中“回忆”。这也是 Agent 能够实现“持续学习”的关键。
  3. 规划模块:面对庞大的任务,直接进入 ReAct 循环往往会导致“失焦”。现代 Agent 架构通常在循环前加入 Planner(规划器),将大目标拆解为 DAG(有向无环图)级别的子任务列表,再由 Agent 逐步执行。

五、 工程落地中的“坑”与最佳实践

在实际生产环境中部署大模型 Agent,往往会遇到比写 Demo 复杂得多的问题。以下是几个关键挑战及应对策略:

1. 幻觉与死循环

现象:Agent 反复调用同一个工具,或者编造不存在的工具名称,导致死循环或程序崩溃。
解决方案

  • 限制最大迭代次数:如同上面代码中的 max_steps,强制熔断。
  • 严格约束 System Prompt:明确告知 Agent “如果没有合适的工具,请直接回答‘我不知道’”。
  • 强化 Few-Shot Examples:在 Prompt 中给出正确的 ReAct 轨迹示例,让模型学会在“不确定”时主动放弃。

2. 上下文爆炸与成本飙升

现象:Agent 每次执行操作,都需要把之前所有的历史对话和工具返回结果发送给大模型,导致 Token 消耗呈指数级增长。
解决方案

  • 上下文压缩:使用较小的模型对历史 Observation 进行摘要总结,替换冗长的原始返回。
  • 任务剪枝:在 Multi-Agent 架构中,Supervisor 在分配任务给 Worker 时,应只传递必要的上下文,而不是全量信息。

3. 工具描述的“文艺复兴”

现象:模型找不到正确的工具,或者传错了参数类型。
解决方案

  • 高质量的 JSON Schema:工具的 description 字段极其重要。不要写人类才能意会的简短描述,要用详尽、准确的自然语言描述工具的“触发条件”和“参数格式”。
  • 兜底机制:在代码层对 LLM 提取的参数进行校验,如果类型错误,将错误信息作为 Observation 抛回给 LLM,它通常会自我纠正。

总结

大模型 Agent 的架构设计代表了人工智能走向通用人工智能(AGI)的关键一步。我们可以清晰地看到技术栈的演进路径:

  • 阶段一:纯粹的 LLM API 调用,一问一答。
  • 阶段二:LLM + RAG,扩充了模型的知识库。
  • 阶段三:LLM + ReAct + Tool Use,模型拥有了手和脚,开始与环境交互。
  • 阶段四(当前):LLM + Multi-Agent + 长期记忆,构建了具备社会协同能力的数字员工网络。

对于工程师而言,掌握 Agent 架构设计已经不再是一个加分项,而是 AI 时代的必备技能。无论是利用 LangGraph 构建复杂的状态机,还是手写原生的 ReAct 循环,理解底层逻辑,才能在这个快速迭代的技术浪潮中稳住阵脚。

未来属于能够设计、管理和协调这些“硅基生命”的人。准备好你的提示词和工具箱,Agent 的大航海时代才刚刚开始。