Agent Paradigms —— ReAct & Plan-and-Solve & Reflection
引言:从“单次推理”到“闭环智能”
在上一篇文章中,我们拆解了AI Agent的四大核心模块——LLM、规划、工具与记忆。如果把这四个模块比作Agent的“器官”,那么范式(Paradigm) 就是让这些器官协同工作的“神经系统”——它决定了Agent如何思考、如何行动、如何从错误中学习。
早期的大语言模型应用遵循一种朴素的模式:用户输入问题 → 模型生成答案。这种“一次性推理”在面对复杂任务时往往力不从心——模型可能在推理中途出错却无法修正,可能缺乏关键信息却无法主动获取,可能生成错误答案却浑然不觉。
为了解决这些问题,研究者们先后提出了三种具有里程碑意义的Agent范式:
- ReAct(2022) :让Agent在“推理”与“行动”之间来回切换,边想边做
- Plan-and-Solve(2023) :让Agent先规划再执行,避免在复杂任务中“走一步看一步”导致的迷失
- Reflection / Reflexion(2023) :让Agent能够批评自己的输出并迭代改进,实现“自我优化”
这三种范式并非相互替代,而是层层递进、互为补充。理解它们的核心机制,是构建真正可用Agent系统的必修课。
一、ReAct——推理与行动的协同
1.1 从CoT到ReAct:打破“信息真空”
在ReAct提出之前,思维链(Chain-of-Thought, CoT) 已经证明了大语言模型通过“逐步思考”可以解决复杂的推理问题。然而,CoT存在一个根本性的缺陷:模型的推理过程完全在“信息真空”中进行,完全依赖其内部知识。这意味着:
- 模型无法获取外部信息来填补知识空白
- 模型无法验证自己推理步骤的正确性
- 模型容易产生“幻觉”(hallucination)
2022年,Shunyu Yao等人提出了ReAct(Reasoning + Acting) 范式。ReAct的核心思想极其简洁却极具革命性:让LLM交替生成推理轨迹(reasoning traces)和任务特定的行动(task-specific actions)。推理轨迹帮助模型诱导、跟踪和更新行动计划并处理异常,而行动则允许模型与外部知识库或环境交互以收集额外信息。
用更通俗的话说:CoT让模型“自己想”,ReAct让模型“边想边做” 。
1.2 Thought-Action-Observation:三拍循环
ReAct的运作遵循一个标准化的三拍循环:
Thought(思考) :Agent根据当前状态生成一段推理文本,分析“我现在知道什么”“我还需要什么”“下一步该做什么”。这段推理不会影响外部环境,但会更新模型的内部状态。
Action(行动) :Agent根据思考结果执行一个具体行动。这个行动可以是调用一个工具(如搜索、计算、API调用),也可以是输出最终答案。
Observation(观察) :Agent接收行动执行后从外部环境返回的反馈。这个观察结果成为下一轮循环的输入。
这三个步骤形成一个闭环,不断迭代直到任务完成。一个典型的ReAct轨迹如下:
1Thought 1: 我需要查一下2024年诺贝尔物理学奖得主是谁。2Action 1: 搜索“2024 诺贝尔物理学奖”3Observation 1: 搜索结果:John J. Hopfield和Geoffrey E. Hinton因在人工神经网络方面的基础性发现和发明获奖。4Thought 2: 好的,我已经知道了获奖者。现在我需要确认他们的国籍。5Action 2: 搜索“John J. Hopfield 国籍”6Observation 2: John J. Hopfield是美国物理学家。7Thought 3: 我已经收集了足够的信息,可以给出最终答案了。8Action 3: 完成1.3 数学建模:ReAct的条件概率框架
从数学角度看,ReAct可以形式化为一个条件概率生成过程。
设 ct=(o1,a1,o2,a2,...,ot) 为时刻 t 的上下文。在每一步,模型根据当前上下文生成下一个token:
P(at∣ct)=∏i=1∣at∣P(xi∣x<i,ct)
其中 at 可以是推理文本(Thought)、行动指令(Action)或最终答案。
ReAct的整个轨迹是一个概率链:
P(trajectory)=∏t=1TP(at∣ct)
其中状态更新是推理文本和观察结果的拼接:
ct+1=ct⊕Thoughtt⊕Observationt
这个数学框架揭示了ReAct的本质:它是一个在“推理空间”和“行动空间”之间交替采样的过程,通过外部观察来不断修正条件概率分布。
1.4 CoT与ReAct:互补而非替代
需要特别强调的是,ReAct并非要取代CoT,而是与之互补。
CoT擅长的是纯粹的推理任务——那些不需要外部信息、完全依赖内部知识就能解决的问题。而ReAct擅长的是需要与外部世界交互的任务——问答、事实核查、决策制定等。
实验数据清楚地展示了这种互补性:在事实核查任务(FEVER)上,ReAct显著优于CoT,因为它可以主动验证信息。而在某些纯推理任务上,CoT可能更加高效。
从工程角度看,两者的关系可以这样理解:CoT是ReAct的“推理引擎” ——ReAct中的Thought步骤本质上就是在执行CoT式的推理。ReAct在CoT的基础上增加了“行动”和“观察”两个维度,使推理不再局限于模型的内部知识。
1.5 ReAct的动态纠错:在歧义环境中导航
ReAct最令人印象深刻的能力之一,是它在面对歧义或错误时能够动态纠错。
传统的CoT推理是一条直线——模型一旦在某一步推理出错,整个答案就可能完全错误,而且没有任何机制可以纠正。ReAct则不同:当模型发现自己的推理与观察结果不一致时,它可以重新思考、调整策略。
这种纠错能力在数学上可以理解为:观察结果 ot 提供了新的证据,更新了模型对世界的信念:
P(goal∣ct+1)∝P(ot∣goal,ct)⋅P(goal∣ct)
当观察结果与当前假设矛盾时,后验概率 P(goal∣ct+1) 会重新分配,促使模型修正其推理方向。
LangChain团队通过分析200多个生产环境案例发现,87%的成功Agent实现最终收敛于ReAct模式。这一数据充分说明了ReAct在实际应用中的价值。
1.6 代码实现:从零构建ReAct Agent
以下是一个精简但完整的ReAct Agent实现:
1from typing import List, Dict, Any, Optional2import json3import re4
5class ReActAgent:6 """7 ReAct (Reasoning + Acting) Agent8
9 核心循环: Thought → Action → Observation10 """11
12 def __init__(self, llm, tools: Dict[str, callable], max_steps: int = 10):13 """14 初始化ReAct Agent15
16 Args:17 llm: 大语言模型接口(具有 generate(prompt) 方法)18 tools: 工具字典 {工具名: 可调用函数}19 max_steps: 最大迭代步数,防止无限循环20 """21 self.llm = llm22 self.tools = tools23 self.max_steps = max_steps24 self.trajectory = [] # 存储完整的 Thought-Action-Observation 轨迹25
26 def _build_system_prompt(self) -> str:27 """构建系统提示词,定义ReAct的格式规范"""28 tool_descriptions = "\n".join([29 f"- {name}: {tool.__doc__ or '无描述'}"30 for name, tool in self.tools.items()31 ])32
33 return f"""34 你是一个ReAct智能体。你可以通过“思考→行动→观察”的循环来解决问题。35
36 可用工具:37 {tool_descriptions}38
39 请严格按照以下格式输出你的每一步:40 Thought: 你的推理过程(自然语言)41 Action: 要调用的工具名称,或 "Finish" 表示结束42 Action Input: 工具的输入参数(JSON格式),或最终答案43
44 注意:Action Input 必须是有效的JSON字符串。45 """46
47 def _parse_response(self, response: str) -> Dict[str, str]:48 """49 解析LLM的输出,提取 Thought、Action 和 Action Input50
51 数学上,这是将非结构化的文本映射到结构化行动空间:52 parse: Text → {Thought, Action, Action Input}53 """54 thought_match = re.search(r"Thought:\s*(.+?)(?=\nAction:|\Z)", response, re.DOTALL)55 action_match = re.search(r"Action:\s*(.+?)(?=\nAction Input:|\Z)", response, re.DOTALL)56 action_input_match = re.search(r"Action Input:\s*(.+?)(?=\n\s*(?:Thought|Action)|\Z)", response, re.DOTALL)57
58 return {59 "thought": thought_match.group(1).strip() if thought_match else "",60 "action": action_match.group(1).strip() if action_match else "",61 "action_input": action_input_match.group(1).strip() if action_input_match else ""62 }63
64 def run(self, question: str) -> str:65 """66 运行ReAct主循环67
68 数学上,这等价于迭代执行:69 for t = 1 to T:70 Thought_t, Action_t = LLM(context_t)71 Observation_t = Environment(Action_t)72 context_{t+1} = context_t + Thought_t + Observation_t73 """74 context = f"问题: {question}\n"75
76 for step in range(self.max_steps):77 # 1. Thought + Action: 调用LLM进行推理和决策78 prompt = self._build_system_prompt() + "\n" + context79 response = self.llm.generate(prompt)80
81 # 2. 解析输出82 parsed = self._parse_response(response)83 self.trajectory.append(parsed)84
85 print(f"\n--- 第 {step + 1} 步 ---")86 print(f"Thought: {parsed['thought']}")87 print(f"Action: {parsed['action']}")88
89 # 3. 检查是否完成90 if parsed["action"] == "Finish":91 print(f"✅ 完成!答案: {parsed['action_input']}")92 return parsed["action_input"]93
94 # 4. Observation: 执行工具调用95 if parsed["action"] in self.tools:96 try:97 # 解析JSON参数98 args = json.loads(parsed["action_input"]) if parsed["action_input"] else {}99 result = self.tools[parsed["action"]](**args)100 observation = f"Observation: {result}"101 except Exception as e:102 observation = f"Observation: 错误 - {str(e)}"103 else:104 observation = f"Observation: 未知工具 '{parsed['action']}'"105
106 print(f"{observation}")107
108 # 5. 更新上下文,进入下一轮109 context += f"Thought: {parsed['thought']}\n"110 context += f"Action: {parsed['action']}\n"111 context += f"Action Input: {parsed['action_input']}\n"112 context += f"{observation}\n"113
114 return "达到最大步数,任务未完成"115
116
117# 使用示例118def search(query: str) -> str:119 """搜索互联网获取信息"""120 # 实际实现中调用真实的搜索API121 return f"关于 '{query}' 的搜索结果: ..."122
123def calculate(expression: str) -> str:124 """计算数学表达式"""125 try:126 return str(eval(expression))127 except:128 return "计算错误"129
130agent = ReActAgent(131 llm=your_llm,132 tools={"search": search, "calculate": calculate},133 max_steps=5134)135
136result = agent.run("2024年诺贝尔物理学奖得主是谁?")二、Plan-and-Solve——先规划,后执行
2.1 核心思想:解决CoT的“漏步”问题
2023年,Lei Wang等人提出了Plan-and-Solve(PS)Prompting。其核心动机是解决思维链在处理多步骤复杂问题时容易出现的 “漏步错误”(missing-step errors) 。
CoT和ReAct虽然强大,但它们都遵循一种 “边走边看” 的线性模式——每一步决策都基于上一步的结果。这种模式在简单任务上表现良好,但在复杂任务中容易导致“只见树木不见森林”——模型可能在一个细枝末节上浪费大量时间,或者遗漏了某个关键步骤。
Plan-and-Solve的解决思路非常直观:先将整个任务分解为一系列子任务(规划阶段),然后按计划逐个执行(求解阶段) 。
2.2 两阶段架构
Plan-and-Solve将任务处理明确地分为两个解耦的阶段:
第一阶段:规划(Planning)
在这一阶段,Agent不对具体问题进行求解,而是制定一个高层次的行动计划。这个计划将整个任务分解为若干逻辑连贯的子目标(subgoals)。
规划阶段的Prompt模板通常是:
“Let’s first understand the problem and devise a plan to solve the problem. Then, let’s carry out the plan to solve the problem step by step.”
第二阶段:求解(Solving)
在这一阶段,Agent严格按照第一阶段制定的计划逐步执行。每一步执行都聚焦于一个特定的子目标,避免了在无关方向上的探索。
为了进一步提高求解质量,研究者还提出了PS+ 变体,加入了更详细的指令:
“Let’s first understand the problem, extract relevant variables and their corresponding numerals, and devise a plan. Then…”
2.3 数学建模:任务分解为子目标
从数学角度看,Plan-and-Solve的核心是将一个复杂的目标函数分解为若干子目标的组合。
设原始任务为 G,规划阶段将其分解为子目标序列 (g1,g2,...,gn),使得:
G=g1∘g2∘...∘gn
其中 ∘ 表示任务的组合(顺序执行)。
每个子目标 gi 的求解可以形式化为:
gi=argmaxaP(a∣plan,contexti−1)
其中 contexti−1 包含了之前所有子任务的执行结果。
这种分解的关键优势在于降低了每一步的决策复杂度——Agent不需要在每一步都重新考虑全局目标,只需要专注于当前子任务。
2.4 成本控制:无细粒度反馈的高效策略
Plan-and-Solve的一个重要特点是成本效率。与ReAct每步都需要与环境交互不同,Plan-and-Solve的规划阶段完全不涉及外部交互,只在执行阶段才逐步求解。
实验数据显示,Plan-and-Solve在纯数值任务上提供了最佳的“准确率-成本”比——在FinQA数据集上比ReAct提高了2.8个百分点,而token消耗仅为思维树的七分之一左右。
这意味着Plan-and-Solve特别适合那些“步骤清晰、可预测”的任务——比如数学计算、结构化数据处理、标准操作流程等。对于这类任务,预先规划可以避免ReAct式的“试错”带来的额外token开销。
2.5 代码实现:Plan-and-Solve的核心逻辑
1from typing import List, Dict, Any2from dataclasses import dataclass3
4@dataclass5class SubTask:6 """子任务的数据结构"""7 id: int8 description: str9 status: str # "pending", "in_progress", "completed", "failed"10 result: Any = None11
12class PlanAndSolveAgent:13 """14 Plan-and-Solve Agent15
16 两阶段架构:17 1. 规划阶段:将复杂任务分解为子任务序列18 2. 求解阶段:按计划逐步执行每个子任务19 """20
21 def __init__(self, llm, tools: Dict[str, callable]):22 self.llm = llm23 self.tools = tools24 self.plan: List[SubTask] = []25
26 def _plan_phase(self, question: str) -> List[SubTask]:27 """28 规划阶段:将任务分解为子目标29
30 数学上,这等价于求解:31 plan = argmax_{p} P(p | question)32 其中p是任务分解方案33 """34 prompt = f"""35 请将以下复杂任务分解为3-5个逻辑连贯的子任务。36
37 任务: {question}38
39 请按以下格式输出计划:40 步骤1: [子任务描述]41 步骤2: [子任务描述]42 ...43
44 注意:每个子任务应该是独立、可执行的,且步骤之间应有明确的依赖关系。45 """46
47 response = self.llm.generate(prompt)48 return self._parse_plan(response)49
50 def _parse_plan(self, response: str) -> List[SubTask]:51 """解析LLM生成的计划"""52 tasks = []53 lines = response.strip().split('\n')54 for line in lines:55 if line.strip().startswith(('步骤', 'Step')):56 # 提取步骤编号和描述57 parts = line.split(':', 1) if ':' in line else line.split(')', 1)58 if len(parts) > 1:59 desc = parts[1].strip()60 tasks.append(SubTask(61 id=len(tasks) + 1,62 description=desc,63 status="pending"64 ))65 return tasks66
67 def _solve_phase(self, question: str) -> str:68 """69 求解阶段:按计划逐步执行70
71 数学上,这等价于:72 for each subgoal g_i in plan:73 result_i = Execute(g_i, context_{i-1})74 context_i = context_{i-1} + result_i75 """76 context = f"原始任务: {question}\n"77 context += "执行计划:\n"78 for task in self.plan:79 context += f"- {task.description}\n"80 context += "\n现在开始逐步执行:\n"81
82 for i, task in enumerate(self.plan):83 task.status = "in_progress"84
85 # 执行当前子任务86 prompt = f"""87 {context}88
89 当前正在执行步骤 {task.id}: {task.description}90 请完成这个子任务,并输出结果。91 """92
93 response = self.llm.generate(prompt)94 task.result = response95 task.status = "completed"96
97 context += f"\n步骤 {task.id} 结果: {response}\n"98
99 # 综合所有子任务的结果,生成最终答案100 final_prompt = f"""101 基于以下各步骤的执行结果,请给出最终答案。102
103 {context}104 """105 return self.llm.generate(final_prompt)106
107 def run(self, question: str) -> str:108 """运行Plan-and-Solve主流程"""109 # 阶段1: 规划110 print("📋 规划阶段: 分解任务...")111 self.plan = self._plan_phase(question)112 for task in self.plan:113 print(f" {task.id}. {task.description}")114
115 # 阶段2: 求解116 print("\n⚙️ 求解阶段: 逐步执行...")117 return self._solve_phase(question)三、Reflection / Reflexion——通过自我批评实现迭代优化
3.1 从“试错”到“反思”:Agent的学习机制
ReAct和Plan-and-Solve虽然强大,但它们都有一个共同的局限:每次任务都是“从零开始”,无法从过去的错误中学习。如果一个Agent在某个任务上失败了,下一次遇到类似任务时,它仍然会犯同样的错误。
人类解决复杂问题的方式则完全不同——我们通过试错和反思来学习。当我们失败时,我们会思考“我哪里做错了”“下次应该如何改进”,并将这些反思应用于未来的尝试。
2023年,Noah Shinn等人提出了Reflexion框架。其核心思想极具洞察力:不是通过更新模型权重来强化Agent,而是通过语言反馈(linguistic feedback) 。
Reflexion agents verbally reflect on task feedback signals, then maintain their own reflective text in an episodic memory buffer to induce better decision-making in subsequent trials.
用更通俗的话说:Reflexion让Agent把自己的失败经验写成“反思日记”,在下一次尝试前先读一遍。
3.2 批评-修正机制(Critic-Revise)
Reflection/Reflexion的核心机制可以概括为 “生成器-批评器-修正器” 的三元循环:
第一步:生成(Generate) ——生成器(Generator)根据用户请求生成初始输出。
第二步:批评(Critique) ——批评器(Critic)评估生成器的输出,指出其中的错误、遗漏或可改进之处。批评可以是:
- 自我批评:同一个模型既当生成器又当批评器
- 外部批评:使用另一个模型或规则系统进行评审
第三步:修正(Revise) ——生成器根据批评器的反馈,修订并生成改进后的输出。
这三个步骤可以反复迭代,直到输出质量达到满意标准。
3.3 数学建模:Reflexion作为语义梯度
Reflexion最精妙之处在于其对“学习”的重新定义。传统的强化学习通过策略梯度来更新模型参数:
∇θJ(θ)=Eτ∼πθ[∑t=0T∇θlogπθ(at∣st)R(τ)]
这需要大量的训练样本和昂贵的模型微调。
Reflexion则完全不同。它将“梯度”从参数空间转移到了语义空间。设:
- τ 为失败的轨迹
- f:τ→r 为反思生成函数(由LLM实现)
- r 为反思文本
Reflexion的“语义梯度”可以形式化为:
Δπ≈LLM(prompt⊕r)
即:反思文本 r 被追加到提示中,从而在不改变模型权重的情况下“调整”了策略。
从信息论角度看,Reflexion相当于在提示空间中执行优化:
promptt+1=promptt⊕Reflection(trajectoryt)
这种方法的美妙之处在于:它利用了LLM本身的语义理解能力来实现“学习”,而不需要任何参数更新。
3.4 实验数据:Reflexion的强大效果
Reflexion的实验结果令人印象深刻:
- 在HumanEval代码生成基准上,Reflexion达到了91%的pass@1准确率,超越了此前GPT-4的80%
- 在AlfWorld决策任务上,成功率达到了97%
- 在HotPotQA问答任务上,成功率为51%
这些数据证明了“语言反馈”这一范式的有效性。
3.5 迭代次数控制:何时停止反思
反思虽然强大,但无限迭代是不现实的——每次反思都会消耗token和时间。因此,迭代次数控制是一个关键的工程问题。
实践中常用的停止策略包括:
固定迭代次数:设置一个最大迭代次数(通常为3-5轮),达到后自动停止。这是最简单也最常用的策略。
置信度阈值:让Agent对自己的输出进行置信度评分(如1-10分),达到阈值(如8分)后停止。
外部验证:使用一个独立的验证Agent来评估输出质量,通过时停止。
边际收益递减检测:当连续两轮迭代的改进幅度低于某个阈值时停止。
在实际生产中,建议设置3-5次反思循环,以平衡质量提升与成本开销。
3.6 代码实现:Reflection Agent
1from typing import List, Dict, Any, Optional2
3class ReflectionAgent:4 """5 Reflection Agent: 通过自我批评和迭代修正来优化输出6
7 核心循环: Generate → Critique → Revise (重复直到满意)8 """9
10 def __init__(self, llm, max_iterations: int = 3, confidence_threshold: float = 8.0):11 """12 初始化Reflection Agent13
14 Args:15 llm: 大语言模型接口16 max_iterations: 最大迭代次数17 confidence_threshold: 置信度阈值(1-10),达到后停止18 """19 self.llm = llm20 self.max_iterations = max_iterations21 self.confidence_threshold = confidence_threshold22 self.reflection_history: List[str] = []23
24 def _generate(self, task: str, context: str = "") -> str:25 """生成阶段:产生初始输出"""26 prompt = f"""27 任务: {task}28
29 {context}30
31 请生成你的回答。32 """33 return self.llm.generate(prompt)34
35 def _critique(self, task: str, output: str) -> str:36 """37 批评阶段:评估输出质量,指出问题38
39 数学上,这等价于:40 critique = argmax_c P(c | task, output)41 其中c是批评文本42 """43 prompt = f"""44 任务: {task}45
46 生成的回答:47 {output}48
49 请以批评者的身份评估这个回答。指出:50 1. 回答中存在的错误或不准确之处51 2. 遗漏的重要信息52 3. 可以改进的地方53
54 批评:55 """56 return self.llm.generate(prompt)57
58 def _revise(self, task: str, output: str, critique: str) -> str:59 """60 修正阶段:根据批评改进输出61
62 数学上,这等价于:63 revised = argmax_r P(r | task, output, critique)64 """65 prompt = f"""66 任务: {task}67
68 原始回答:69 {output}70
71 批评意见:72 {critique}73
74 请根据上述批评意见,修订并生成改进后的回答。75 """76 return self.llm.generate(prompt)77
78 def _evaluate_confidence(self, task: str, output: str) -> float:79 """评估对当前输出的置信度"""80 prompt = f"""81 任务: {task}82
83 回答: {output}84
85 请对这个回答的质量进行评分(1-10分),只返回数字。86 """87 response = self.llm.generate(prompt)88 try:89 return float(response.strip())90 except:91 return 5.092
93 def run(self, task: str) -> str:94 """95 运行Reflection主循环96
97 迭代过程:98 for i in range(max_iterations):99 output = Generate(task, context)100 critique = Critique(task, output)101 if quality_sufficient(output):102 break103 output = Revise(task, output, critique)104 """105 print(f"📝 任务: {task}\n")106
107 # 初始生成108 current_output = self._generate(task)109 print(f"--- 初始生成 ---\n{current_output}\n")110
111 for iteration in range(self.max_iterations):112 # 1. 批评113 critique = self._critique(task, current_output)114 print(f"--- 第 {iteration + 1} 轮批评 ---\n{critique}\n")115 self.reflection_history.append(critique)116
117 # 2. 评估置信度118 confidence = self._evaluate_confidence(task, current_output)119 print(f"置信度评分: {confidence}/10")120
121 # 3. 检查是否应该停止122 if confidence >= self.confidence_threshold:123 print("✅ 置信度达标,停止迭代")124 break125
126 # 4. 修正127 current_output = self._revise(task, current_output, critique)128 print(f"--- 第 {iteration + 1} 轮修正后的输出 ---\n{current_output}\n")129
130 return current_output四、三种范式的对比与选择
4.1 核心差异
| 维度 | ReAct | Plan-and-Solve | Reflection |
|---|---|---|---|
| 核心机制 | 推理与行动交替 | 先规划后执行 | 生成-批评-修正循环 |
| 决策模式 | 在线、自适应 | 离线、结构化 | 迭代、自优化 |
| 外部交互 | 每步都可能 | 主要在执行阶段 | 可选(可纯内部) |
| 错误处理 | 动态纠错 | 规划避免 | 迭代修正 |
| 成本特征 | 中等 | 低(无细粒度反馈) | 较高(多轮) |
| 适用场景 | 开放域、不确定环境 | 结构化、可预测任务 | 内容生成、质量敏感任务 |
4.2 如何选择
选择ReAct:当任务环境不可预测、需要动态调整策略时。例如:网络搜索、多步问答、客户服务对话。
选择Plan-and-Solve:当任务步骤清晰、可预先规划时。例如:数学计算、数据处理、标准操作流程。
选择Reflection:当输出质量是关键、可以接受多轮迭代时。例如:代码生成、内容创作、报告撰写。
4.3 混合架构:取长补短
在实际生产系统中,这三种范式往往不是互斥的,而是可以组合使用。例如:
- Plan-and-Solve + ReAct:先用Plan-and-Solve制定整体计划,然后在每个子任务的执行中使用ReAct进行动态调整
- ReAct + Reflection:ReAct负责与环境交互收集信息,Reflection负责对收集到的信息进行批判性分析和整合
- 三者结合:规划 → 执行(ReAct式) → 反思优化
五、总结:从线性到循环,从单次到迭代
回顾这三种范式的演化,我们可以清晰地看到一条能力递增的路径:
ReAct让Agent从“一次性推理”进化到“闭环推理”——它可以在推理过程中获取外部信息并动态调整。
Plan-and-Solve让Agent从“边走边看”进化到“先看路再走”——它通过预先规划避免了在复杂任务中迷失方向。
Reflection让Agent从“每次从零开始”进化到“从错误中学习”——它通过自我批评和迭代修正实现了持续的自我优化。
这三种范式共同构成了当前AI Agent能力的基础框架。理解它们,就是理解了如何让AI从“会说话”进化到“会思考、会行动、会学习”。
正如ReAct论文中所说:“推理轨迹帮助模型诱导、跟踪和更新行动计划并处理异常,而行动允许它与外部来源交互以收集额外信息。”这三者——推理、行动、反思——正是智能的本质要素。
Some information may be outdated