理解AI Agent的大脑:ReAct模式从入门到实战

系列文章

本篇是 AI Agent 深度解析系列的第 3 篇。以下是系列完整目录,建议收藏作为学习索引。

🏗️ 基础理论篇

  1. 从零理解 RAG:检索增强生成完整指南
  2. Embedding 向量化的魔法:从文本到向量的数学之旅与 Java 实战
  3. 理解 AI Agent 的大脑:ReAct 模式从入门到实战
  4. Spring AI 核心架构全解析:从 ChatModel 到 Advisor Chain 的设计哲学

🧩 核心组件篇

  1. AI Agent 的记忆系统:从 ChatMemory 到持久化记忆的 Java 实战
  2. AI Agent 的记忆力是怎么实现的——LangChain4j Memory 机制深度解析
  3. AI Agent 的工具箱:深入理解 Tool Use 与 Spring AI Function Calling 实战
  4. 让 AI 学会”说人话”——Spring AI 结构化输出实战
  5. AI Agent 的灵魂对话:Prompt Engineering 系统提示词设计的艺术与工程

🏛️ 架构设计篇

  1. AI Agent 的规划大脑:从任务分解到自适应执行策略
  2. AI Agent 的工作流编排:从顺序链到自适应 DAG 的 Java 实战
  3. AI Agent 团队协作:多 Agent 系统架构设计与 Java 实战
  4. Agent 间如何对话:A2A 协议深度解析与 Java 实战

🔍 知识检索篇

  1. AI Agent 的知识检索引擎:从向量搜索到智能检索策略的 Java 实战
  2. 当 RAG 遇上知识图谱:GraphRAG 原理与 Java 实战
  3. 当 RAG 遇到 Agent:Agentic RAG 的架构设计与 Java 实战
  4. MCP 模型上下文协议:AI 的万能接口与 MCP Server 实战

🚀 进阶能力篇

  1. AI Agent 的推理引擎:从 Chain-of-Thought 到推理模型的深度解析与 Java 实战
  2. AI Agent 的多模态感知:从图片理解到语音交互的 Java 实战
  3. AI Agent 的自我反思与经验学习:从错误中进化的 Java 实战
  4. AI Agent 的上下文工程与 Token 预算管理:从窗口压缩到成本优化的 Java 实战
  5. AI Agent 的人机协作:从 Human-in-the-Loop 到渐进式自治的 Java 实战

🛡️ 生产保障篇

  1. AI Agent 的安全防线:Prompt 注入防御与生产级安全防护实战
  2. AI Agent 的可观测性:从链路追踪到成本监控的 Java 实战
  3. AI Agent 的流式响应与实时交互:从 SSE 到 WebSocket 的 Java 实战
  4. AI Agent 的容错与韧性:从错误处理到生产级可靠性保障的 Java 实战
  5. AI Agent 评估与优化:从基准测试到生产环境的质量守护实战
  6. AI Agent 的成本优化:从模型路由到缓存策略的 Java 实战

🧭 全景总结

  1. 从理论到生产:AI Agent 全景知识图谱与 Java 开发者成长路线

从一次点餐说起

周末你想去吃个饭,打开微信问朋友:”帮我推荐一家餐厅呗。”

你的朋友大概不会直接甩一个店名给你。他会先想:你喜欢什么口味?川菜还是日料?预算多少?离你家远不远?现在几点了,附近还在营业的有什么?

思考一圈之后,他打开大众点评搜了一下,发现附近有几家评分不错的川菜馆,但有一家离你家太远了。他再想想,你上次说最近在减肥,于是排除了那家以大盘菜出名的。

最后他说:”去那家’蜀香小馆’吧,走路十分钟,评分4.8,分量不大适合你。”

这个过程其实就是一个ReAct的缩影:想一想→做一做→看看结果→再想想→再做做→直到得到满意的答案

今天我们就来聊聊,AI Agent 是怎么像你朋友一样”边想边做”的。


什么是ReAct?

ReAct 这个名字来自论文《ReAct: Synergizing Reasoning and Acting in Language Models》,它是两个单词的组合:

  • Reasoning(推理)—— LLM 天生就会的事,分析、思考、推理
  • Acting(行动)—— 调用工具、查询数据、执行操作

传统的 LLM 只能”想”——你问它一个问题,它根据训练数据生成一段回答。但它不能”做”,它不知道今天北京的天气是几度,因为它没有访问实时数据的能力。

ReAct 的核心思想很简单:让 LLM 在推理的同时,可以调用外部工具,然后根据工具返回的结果继续推理,如此循环,直到得出最终答案。

换句话说,ReAct 赋予了 LLM “手和脚”——它不仅能思考,还能行动。

下图展示了 ReAct 的完整循环过程,以及与传统 Chain 模式的对比:

ReAct推理-行动循环:思考→行动→观察→循环

如图左侧所示,ReAct 的核心是一个三步循环:Thought(想一想,分析下一步该做什么)→ Action(做一做,调用外部工具)→ Observation(看看结果,获取工具返回)。循环持续到 LLM 判断信息足够,才生成最终回答。右侧对比了传统 Chain 模式——Chain 一步到位,容易编造数据;ReAct 通过工具调用获取真实数据,代价是需要多轮循环。

接下来我们详细对比一下 Chain 和 ReAct 的区别。


和传统 Chain 的区别

如果你用过 LangChain,你一定知道 Chain 的概念。Chain 是线性的:输入 → 处理 → 输出,一条路走到底。

1
2
传统 Chain:
用户问题 → LLM思考 → 回答

但现实世界的问题往往没那么简单。比如:

“帮我查一下北京今天的最高气温,然后算一下如果每天省下3度电,一周能省多少?”

这个问题需要两步:先查天气,再计算。普通 Chain 做不到,因为它只会一口气生成回答,很可能”瞎编”一个温度数字。

ReAct 的做法不同,它是一个循环

1
2
ReAct 流程:
用户问题 → LLM思考 → 决定调用工具 → 获取结果 → LLM再思考 → 再调用工具 → ... → 最终回答

区别一目了然:Chain 是一条直线,ReAct 是一个圆圈,可以转很多圈。


ReAct 的工作流程

ReAct 的执行循环可以用四个词概括:

1. Think(思考)

LLM 分析当前的情况,决定下一步该做什么。它可能会想:”用户问我北京的天气,我需要调用天气查询工具。”

2. Act(行动)

LLM 调用一个外部工具,比如搜索 API、数据库查询、计算器等。

3. Observe(观察)

LLM 收到工具返回的结果,比如”北京今天最高气温32℃”。

4. 判断是否需要继续

如果已经有了足够的信息,就直接生成最终答案。如果还不够,回到第1步继续。

用一个更直观的流程图:

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
┌─────────────────────────────────┐
│ 用户提问 │
└──────────┬──────────────────────┘

┌─────────────────────────────────┐
│ Think:我需要先查北京天气 │
└──────────┬──────────────────────┘

┌─────────────────────────────────┐
│ Act:调用天气工具查北京 │
└──────────┬──────────────────────┘

┌─────────────────────────────────┐
│ Observe:返回 32℃ │
└──────────┬──────────────────────┘

┌─────────────────────────────────┐
│ Think:现在我需要计算一周省电 │
└──────────┬──────────────────────┘

┌─────────────────────────────────┐
│ Act:调用计算器 3×7=21 │
└──────────┬──────────────────────┘

┌─────────────────────────────────┐
│ Observe:结果是21度电 │
└──────────┬──────────────────────┘

┌─────────────────────────────────┐
│ 最终回答:北京今天32℃, │
│ 每天省3度电一周能省21度 │
└─────────────────────────────────┘

代码实战:用 LangChain 实现 ReAct Agent

光说不练假把式,我们来写一个真实的例子。场景很简单:一个能查天气、做计算的 AI 助手。

安装依赖

1
pip install langchain langchain-community langchain-openai duckduckgo-search

完整代码

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
import os
from langchain_openai import ChatOpenAI
from langchain.agents import AgentExecutor, create_react_agent
from langchain_core.tools import tool
from langchain_core.prompts import PromptTemplate

# 设置 API Key(也可以通过环境变量设置)
os.environ["OPENAI_API_KEY"] = "your-api-key-here"

# ========== 定义工具 ==========

@tool
def get_weather(city: str) -> str:
"""查询指定城市的当前天气信息。输入城市名称,返回天气描述。"""
# 这里用模拟数据,实际项目中可以接入真实天气 API
weather_data = {
"北京": "晴天,最高气温32℃,最低气温22℃,东南风3级",
"上海": "多云,最高气温28℃,最低气温20℃,微风",
"深圳": "阵雨,最高气温30℃,最低气温25℃,南风2级",
}
return weather_data.get(city, f"未找到{city}的天气信息")

@tool
def calculator(expression: str) -> str:
"""计算数学表达式。输入一个数学表达式字符串,返回计算结果。"""
try:
result = eval(expression) # 注意:生产环境请用更安全的计算库
return str(result)
except Exception as e:
return f"计算出错:{str(e)}"

# ========== 设置 LLM ==========

llm = ChatOpenAI(model="gpt-4", temperature=0)

# ========== ReAct Prompt 模板 ==========

react_prompt = PromptTemplate.from_template("""
Answer the following questions as best you can. You have access to the following tools:

{tools}

Use the following format:

Question: the input question you must answer
Thought: you should always think about what to do
Action: the action to take, should be one of [{tool_names}]
Action Input: the input to the action
Observation: the result of the action
... (this Thought/Action/Action Input/Observation can repeat N times)
Thought: I now know the final answer
Final Answer: the final answer to the original input question

Begin!

Question: {input}
Thought:{agent_scratchpad}
""")

# ========== 创建 ReAct Agent ==========

tools = [get_weather, calculator]
agent = create_react_agent(llm, tools, react_prompt)
agent_executor = AgentExecutor(
agent=agent,
tools=tools,
verbose=True, # 打印每一步的思考过程
max_iterations=10 # 防止无限循环
)

# ========== 运行示例 ==========

if __name__ == "__main__":
# 示例1:单步查询
print("=" * 50)
result = agent_executor.invoke({"input": "北京今天天气怎么样?"})
print(f"最终回答:{result['output']}")

# 示例2:多步推理(需要先查天气,再计算)
print("=" * 50)
result = agent_executor.invoke({
"input": "北京今天最高气温是多少?如果每天省下3度电,一周能省多少度?"
})
print(f"最终回答:{result['output']}")

运行效果

当你运行上面的代码,你会看到 Agent 的思考过程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
> Entering new AgentExecutor chain...
Thought: 用户问了两个问题,我需要先查北京的天气,获取最高气温
Action: get_weather
Action Input: 北京
Observation: 晴天,最高气温32℃,最低气温22℃,东南风3级
Thought: 我现在知道北京最高气温是32℃,接下来需要计算每天省3度电一周能省多少
Action: calculator
Action Input: 3 * 7
Observation: 21
Thought: I now know the final answer
Final Answer: 北京今天最高气温是32℃。如果每天省下3度电,一周能省21度电。

> Finished chain.
最终回答:北京今天最高气温是32℃。如果每天省下3度电,一周能省21度电。

看到了吗?Agent 先思考需要查天气,然后行动调用了天气工具,观察结果后继续思考需要做计算,再行动调用计算器,最终得出完整答案。

这就是 ReAct 的魅力——它不是一次性把答案吐出来,而是一步一步地解决问题。


什么时候该用 ReAct?

不是所有场景都需要 ReAct,用对了才高效:

适合用 ReAct 的场景:

  • 需要多步推理的问题(比如”先查A,再根据A算B”)
  • 需要调用外部工具的场景(查数据库、调API、搜索网页)
  • 问题比较复杂,一次推理搞不定的任务
  • 需要根据中间结果动态调整策略的场景

不需要 ReAct 的场景:

  • 简单的问答、翻译、总结,直接调 LLM 就行
  • 答案就在输入里,不需要外部数据
  • 对延迟要求极高的实时场景(ReAct 多轮交互会增加延迟)

一个简单的判断标准:如果你的问题能一步到位,就用普通 Chain;如果需要”想一想、做一做、再想想”,那就该上 ReAct。


写在最后

ReAct 不是什么高深莫测的技术,它的核心思想就是模仿人类解决问题的方式:边想边做,根据反馈调整策略。

这其实和你平时的工作方式很像——你写代码的时候,不是一次写完就跑通了,而是写着写着发现不对,改一改,跑一下看看,再改改,直到程序正确运行。

ReAct 之所以重要,是因为它是 AI Agent 的基础思维模式。你后面会看到的各种 Agent 框架、各种复杂的 Agent 架构,底层几乎都离不开 ReAct 这个核心思想。

理解了 ReAct,你就理解了 AI Agent 为什么能”做事”,而不只是”说话”。

下一次你让 AI 助手帮你完成一个复杂任务的时候,不妨想想:它此刻可能正在 Think → Act → Observe 的循环中,一步一步帮你找到答案。


参考论文:Yao, S. et al. “ReAct: Synergizing Reasoning and Acting in Language Models” (ICLR 2023)

本文代码:基于 LangChain 0.2+ 版本,完整示例可在 GitHub 上找到。