Appearance
11. 什么是 ReAct?如何基于 ReAct 模式构建具备自主规划能力的 AI 智能体?
难度 P0 必背 · 岗位 应用 · 频率 ★★★ · 预计阅读 14 min
本题阅读地图
- 💡 简要回答
- 📝 详细解析
- 🎯 面试总结
👔面试官:说说 ReAct 是什么?怎么用它来构建智能体?
🙋♂️我:ReAct 就是推理加行动,让模型一边思考一边做事情。
👔面试官:ReAct 的循环具体是怎样的?Observation 有什么用?怎么防止 ReAct 无限循环?实际代码怎么实现?
🙋♂️我:……大概就是 Thought → Action → Observation 这样循环,具体代码没写过。
ReAct 是最经典的智能体架构模式,下面把原理和实现讲清楚。
TL;DR 速记
- 是什么:ReAct 是让 LLM 在 Thought、Action、Observation 之间循环,边推理边调用工具。
- 关键点:Observation 会把工具结果反馈给模型,模型据此调整下一步,而不是一次性生成完整答案。
- 怎么答:实现时要定义响应格式、工具描述和循环控制,尤其要有最大步数、重复动作检测和无进展终止。
图解
图 1:ReAct 执行闭环
💡 简要回答
ReAct(Reasoning + Acting) 是一种让 LLM 交替进行「推理」和「行动」的范式,通过观察行动结果来调整下一步策略。
核心循环:
Thought(思考当前状态和目标)
↓
Action(选择并执行工具)
↓
Observation(观察行动结果)
↓
[循环直到完成任务或达到最大步数]📝 详细解析
ReAct 的核心思想
传统方式是「一次性生成答案」,ReAct 是「边做边想、边想边做」:
- Thought:分析当前情况,规划下一步
- Action:调用工具(搜索、计算、查数据库)
- Observation:获取工具返回的结果
- 循环:基于新的观察,重新思考
ReAct 示例流程
用户提问:「杭州今天天气怎么样?适合穿什么衣服?」
Step 1 - Thought:
用户想知道杭州的天气和穿衣建议。我需要先查询天气信息。
Step 1 - Action:
调用 get_weather 工具,city="杭州"
Step 1 - Observation:
{"city": "杭州", "temperature": 15, "condition": "多云", "wind": "东北风3级"}
Step 2 - Thought:
杭州今天15度多云,温度适中但有风。需要建议穿薄外套。
Step 2 - Action:
不需要调用工具,可以直接回答。
Step 3 - Final Answer:
杭州今天多云,15°C,东北风3级。建议穿薄外套+长裤,可以带件薄毛衣备用。Spring AI 实现 ReAct
java
@Component
public class ReActAgent {
private final ChatClient chatClient;
private final List<Tool> tools;
private static final int MAX_STEPS = 10; // 防止无限循环
public String execute(String userInput) {
StringBuilder conversation = new StringBuilder();
conversation.append("用户:").append(userInput).append("\n\n");
for (int step = 0; step < MAX_STEPS; step++) {
// 构建 ReAct Prompt
String prompt = buildReActPrompt(conversation.toString());
// 调用模型
String response = chatClient.prompt(prompt).call().content();
// 解析响应
if (response.contains("Final Answer:")) {
return extractFinalAnswer(response);
}
// 提取 Thought 和 Action
String thought = extractThought(response);
String action = extractAction(response);
conversation.append("Thought: ").append(thought).append("\n");
conversation.append("Action: ").append(action).append("\n");
// 执行工具
String observation = executeAction(action);
conversation.append("Observation: ").append(observation).append("\n\n");
}
return "达到最大步数限制,任务未完成";
}
private String buildReActPrompt(String context) {
return """
你是一个智能助手,可以通过思考和使用工具来解决问题。
可用工具:
%s
请按以下格式响应:
Thought: 你的思考过程
Action: 工具名称[参数]
或当任务完成时:
Final Answer: 最终答案
历史:
%s
""".formatted(formatTools(), context);
}
private String executeAction(String action) {
// 解析工具调用,执行并返回结果
// get_weather[杭州] → 调用 weatherTool.query("杭州")
}
}防止无限循环的机制
java
public class ReActAgent {
private static final int MAX_STEPS = 10;
private static final Set<String> executedActions = new HashSet<>();
private String executeWithSafety(String userInput) {
for (int step = 0; step < MAX_STEPS; step++) {
String action = getActionFromModel();
// 1. 检测重复动作
if (executedActions.contains(action)) {
return "检测到重复动作,终止执行";
}
executedActions.add(action);
// 2. 检测无效动作
if (isInvalidAction(action)) {
return "无效动作:" + action;
}
// 3. 执行动作
String observation = executeAction(action);
// 4. 检测是否有进展(Observation 是否有新信息)
if (isNoProgress(observation)) {
return "执行无进展,可能需要调整策略";
}
}
return "达到最大步数限制";
}
}ReAct vs Plan-and-Execute
| 维度 | ReAct | Plan-and-Execute |
|---|---|---|
| 规划方式 | 边执行边规划 | 先完整规划,再执行 |
| 灵活性 | 高,能根据观察调整 | 低,计划一旦定好不易改 |
| 可解释性 | 每一步都有 Thought | 整体计划清晰 |
| 适用场景 | 探索性任务、信息收集 | 确定性任务、流程固定 |
| 风险控制 | 可能陷入循环 | 计划可控,执行稳定 |
实际项目往往两者结合:先用 Plan-and-Execute 制定大纲,再用 ReAct 处理每个步骤的细节。
工程优化技巧
java
// 1. 工具描述要精确,帮助模型选对工具
@Tool(description = "查询天气。当用户询问任何城市的天气、气温、是否下雨时使用。")
// 2. Prompt 中给出 Few-shot 示例
String fewShotExample = """
示例1:
用户:北京天气怎么样?
Thought: 用户想知道北京的天气,我需要查询天气工具。
Action: get_weather[city="北京"]
Observation: {"temperature": 20, "condition": "晴"}
Thought: 已经拿到天气信息,可以直接回答。
Final Answer: 北京今天晴天,20°C。
""";
// 3. Observation 格式标准化
// 所有工具返回 JSON,方便模型解析常见踩坑与反例
- 踩坑 1:把 ReAct 等同于工具调用 · 错误说法:只要 LLM 能调工具就是 ReAct。· 正确做法:强调 ReAct 是 Thought → Action → Observation 的多步闭环。
- 踩坑 2:Observation 不结构化 · 错误说法:工具返回一大段自然语言即可。· 正确做法:工具结果尽量用 JSON 或固定字段,方便模型判断下一步。
- 踩坑 3:没有循环终止条件 · 错误说法:让模型自己判断什么时候结束。· 正确做法:设置最大步数、重复动作检测、无效动作检测和无进展终止。
- 踩坑 4:工具描述太模糊 · 错误说法:搜索工具描述成「能查东西」。· 正确做法:写清工具用途、参数、返回格式和不该调用的场景。
面试官可能继续追问
- 追问 1:Observation 的作用是什么? 答题要点:它把外部工具执行结果反馈给 LLM,让下一轮 Thought 基于真实状态调整。
- 追问 2:怎么解析 Action? 答题要点:最好用结构化格式或函数调用协议,服务端校验工具名和参数,不能直接执行任意文本。
- 追问 3:ReAct 如何防止死循环? 答题要点:最大步数、重复动作集合、无进展检测、错误次数阈值,必要时降级或转人工。
- 追问 4:ReAct 和 Plan-and-Execute 怎么选? 答题要点:探索性、依赖反馈的任务选 ReAct;步骤明确、需要效率的任务选 Plan-and-Execute,也可混合使用。
🎯 面试总结
ReAct 是最基础的智能体架构模式。
核心循环:Thought → Action → Observation → 循环
实现要点:
- Prompt 设计:明确定义 Thought/Action/Observation 格式
- 工具描述:精确描述每个工具的用途和参数
- 循环控制:最大步数限制、重复动作检测、无效动作检测
- Few-shot 示例:给模型看正确的执行轨迹
与 Plan-and-Execute 对比:
- ReAct:灵活、适合探索性任务
- Plan-and-Execute:稳定、适合确定性任务
面试时要能画出 ReAct 循环图 和说出 防止死循环的机制(最大步数、重复检测)。