Skip to content

11. 什么是 ReAct?如何基于 ReAct 模式构建具备自主规划能力的 AI 智能体? ​

难度 P0 必背 · 岗位 应用 · 频率 ★★★ · 预计阅读 14 min

本题阅读地图 ​

  1. 💡 简要回答
  2. 📝 详细解析
  3. 🎯 面试总结

👔面试官:说说 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 ​

维度ReActPlan-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 → 循环

实现要点:

  1. Prompt 设计:明确定义 Thought/Action/Observation 格式
  2. 工具描述:精确描述每个工具的用途和参数
  3. 循环控制:最大步数限制、重复动作检测、无效动作检测
  4. Few-shot 示例:给模型看正确的执行轨迹

与 Plan-and-Execute 对比:

  • ReAct:灵活、适合探索性任务
  • Plan-and-Execute:稳定、适合确定性任务

面试时要能画出 ReAct 循环图 和说出 防止死循环的机制(最大步数、重复检测)。



章节首页 · ← Q10 · Q12 →

最后更新2026-05-01
难度P0
频率medium
阅读14 min
主题agent
觉得有帮助?把这个链接转给正在求职的朋友 · 用 Ctrl + K 全站搜索其它题