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

从一次点餐说起

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

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

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

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

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

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


什么是ReAct?

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

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

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

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

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


和传统 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 上找到。