Reflexion论文和框架详解(附demo版)
摘要:本文提出Reflexion框架,一种基于语言反思的强化学习范式,通过语言反馈而非参数调整来优化大型语言模型(LLM)智能体的表现。该方法包含三个核心组件:执行任务的演员模型、评估质量的评估器模型和生成语言反馈的自我反思模型。Reflexion利用LLM的文本理解能力,将环境反馈转化为语义梯度指导后续决策,模拟人类通过内省学习的过程。实验表明该方法在编程等任务中表现优异,但也面临数据污染、局部
1. 研究背景:语言智能体的现状与瓶颈
大型语言模型(LLM)不仅在文本生成领域展现了惊人的能力,更逐渐演变为能够与外部环境交互 的决策智能体。近年来的研究,如 ReAct、SayCan、Toolformer、 HuggingGPT 和 WebGPT 等,展示了以 LLM 为核心构建自主系统的巨大潜力 。这些系统通过 生成文本和动作,调用 API、操作编译器或在虚拟环境中执行任务.
然而,这些方法的根本局限在于其学习方式。目前的语言智能体主要依赖于上下文学习( In-context Learning),即通过在提示词(Prompt)中提供静态的示例来指导模型行为。虽然这种方法在 Few-shot 场景下有效,但它缺乏一种机制让智能体从自身的错误中快速、高效地学习。
传统的优化路径——基于梯度下降的强化学习——虽然在游戏和控制领域取得了巨大成功(如 AlphaGo),但在 LLM 智能体场景下面临严峻挑战:
1. 样本效率低:传统强化学习需要数以万计甚至百万计的训练样本才能收敛,而与现实世界(如 API 或 编译器)交互的成本极高。
2. 微调成本高昂:对于拥有数十亿甚至上万亿参数的 LLM(如 GPT-4),进行参数微调需要庞大的计算资源,且容易导致模型能力的灾难性遗忘。
3. 奖励信号稀疏:在复杂的推理或编程任务中,环境通常只能提供二元的成功/失败反馈,难以通过标量奖励精确指导模型“哪一步做错了”。
2 Reflexion 范式转移的初步认知
针对上述痛点,Reflexion 提出了一种全新的视角:如果我们将“反思”本身视为一种强化信号,会 发生什么?
Reflexion 框架的核心假设是:智能体不需要修改神经网络的权重来学习,而是可以通过修改其 “记忆”(上下文)来优化策略 。这种方法利用了 LLM 强大的语言理解和生成能力,将环境的二元或标量反馈转化为语言形式的文本摘要。
这个文本摘要充当了一种语义梯度(Semantic Gradient)。在深度学习中,梯度向量指示了权重更新的方向;而在 Reflexion 中,语言反思指示了思维更新的方向。例如,当智能体在游戏中因为“找不到钥匙”而失败时,传统的 RL 可能会收到一个 -1 的奖励,而 Reflexion 智能体则会生成一段反思:“我在尝试打开门之前没有检查桌子上的盒子,下次我应该先检查盒子。” 。
这种机制模拟了人类的高级认知过程。人类在学习复杂任务时,并非通过调整神经突触的连接强度从一次失败中学习,而是通过内省和元认知来分析错误原因,并在短期记忆形成新的行动计划 。
3.方法论:ReAct是基于语言反思的强化框架
Reflexion 框架的设计高度模块化,通过三个核心组件的协同工作来实现自我进化:演员(Actor)、 评估器(Evaluator)和自我反思(Self-Reflection)。这一架构不仅是对 ReAct 等现有框架的扩展,更是引入了闭环控制系统中的“反馈控制”理念。
3.1 理论架构与组件定义
Reflexion 的工作流程可以被形式化为一个迭代优化过程。我们定义智能体为一组模型的集合: (演员)、
(评估器)和
(自我反思)。
3.1.1 演员模型 
演员是系统的执行引擎,基于 LLM 构建。它的任务是根据当前的状态观察生成文本和动作。
策略定义: 类似于传统 RL 中的策略 ,演员在时间
根据当前状态
采样动作
。
上下文增强: 与传统 RL 不同,Reflexion 中的状态 不仅包含当前的观察
,还包含来自记忆组件
的反思性上下文。这意味着演员的决策不仅受限于当前的感知,还受到过去经验指导 。
模型兼容性: 演员可以使用 Chain of Thought (CoT) 或 ReAct 等不同的提示策略。这表明 Reflexion 是一个通用的元框架,可以增强任何现有的生成模型。
3.1.2 评估器模型 
评估器是质量控制机制,负责评估演员生成的轨迹 的质量,并计算奖励分数
。
语义价值函数的挑战: 在自然语言任务中,定义一个能够精确衡量“好坏”的价值函数极其困难。Reflexion 通过针对不同任务设计特定的评估器来解决这个问题:
推理任务(HotPotQA): 使用精确匹配(Exact Match, EM)评分,直接对比预测答案与标准答案(在训练或验证阶段)。
决策任务(AlfWorld): 使用预定义的启发式函数(Heuristics)。例如,如果智能体陷入循环动作或在特定时间内未完成任务,评估器将返回失败信号。
编程任务(HumanEval): 这是最接近真实世界应用的场景。评估器通过执行单元测试来生成确定性的二元奖励(通过/失败)。更有趣的是,研究还探索了使用另一个 LLM 作为评估器,对生成的代码进行打分 。
3.1.3 自我反思模型 
也是一个 LLM,其作用是解决强化学习中著名的信用分配问题。
输入: 稀疏的奖励信号(如“失败”)、当前的行动轨迹、以及持久记忆 。
功能: 它将难以解释的标量奖励转化为具体的、有针对性的语言反馈。
机制: 当收到失败信号时, 会分析轨迹,推断是哪一步动作导致了后续的连锁反应。例如,它可能会指出:“我在第 3 步选择了错误的工具,导致第 5 步无法获取数据。下次我应该在第 3 步尝试使用搜索工具。”
语义梯度: 这种语言反馈为下一次试验提供了“梯度方向”,指导演员在提示空间中进行调整。
3.1.4 记忆系统 (Memory System)
Reflexion 引入了类人的记忆机制,分为短期记忆和长期记忆 。
短期记忆: 记录当前试验中的动作序列和环境观察。这对应于 ReAct 框架中的上下文。
长期记忆: 存储由 生成的反思摘要。在推理时,这些摘要被追加到提示词的上下文中。为了适应 LLM 的上下文窗口限制,系统通常采用滑动窗口机制,仅保留最近的
个(通常为 1-3 个)反思经验。这模拟了人类容易遗忘久远细节但能记住最近教训的特性。
class Memory:
"""
一个简单的短期记忆模块,用于存储智能体的行动与反思轨迹。
"""
def __init__(self):
"""
初始化一个空列表来存储所有记录。
"""
self.records: List[Dict[str, Any]] = []
def add_record(self, record_type: str, content: str):
"""
向记忆中添加一条新记录。
参数:
- record_type (str): 记录的类型 ('execution' 或 'reflection')。
- content (str): 记录的具体内容 (例如,生成的代码或反思的反馈)。
"""
record = {"type": record_type, "content": content}
self.records.append(record)
print(f"📝 记忆已更新,新增一条 '{record_type}' 记录。")
def get_trajectory(self) -> str:
"""
将所有记忆记录格式化为一个连贯的字符串文本,用于构建提示词。
"""
trajectory_parts = []
for record in self.records:
if record['type'] == 'execution':
trajectory_parts.append(f"--- 上一轮尝试 (代码) ---\n{record['content']}")
elif record['type'] == 'reflection':
trajectory_parts.append(f"--- 评审员反馈 ---\n{record['content']}")
return "\n\n".join(trajectory_parts)
def get_last_execution(self) -> Optional[str]:
"""
获取最近一次的执行结果 (例如,最新生成的代码)。
如果不存在,则返回 None。
"""
for record in reversed(self.records):
if record['type'] == 'execution':
return record['content']
return None
3.2 算法流程详解
第一步:初始化
初始化演员 、评估器
、自我反思模型
。清空记忆 ,设定最大试验次数 max_trials。
第二步:初始尝试
生成轨迹 (): 演员
基于初始策略与环境交互,生成第一个轨迹
。
第三步:评估
评分 (): 评估器
对
进行评 估。如果任务成功,直接返回结果;如果失败,进入反思循环。
第四步:反思生成
生成反思 ():
接收
作为输入,生成第一条反思摘要。
第五步:记忆存储
更新记忆: 将 追加到
中。
第六步:迭代循环
While (评估未通过且 max_trials):
上下文增强: 将 中的内容作为附加上下文输入给演员。
生成新轨迹 (): 演员利用包含反思的上下文, 生成新的动作序列。由于有了之前的教训,演员倾向于避开已知的错误路径。
再次评估: 评估器 对
评分。
递归反思: 如果仍未通过, 基于
和 历史
生成新的反思
,并追加到
。
第七步:中止
返回成功的轨迹或在达到最大次数后返回最终状态。
4. Reflexion与其他范式的联系和对比
| 特性 | ReAct | Self-Refine | Chain of Thought (CoT) | Reflexion |
|---|---|---|---|---|
| 核心机制 | 推理 + 行动交替 | 迭代式自我修正 | 逐步推理 | 语言反馈 + 情景记忆闭环 |
| 记忆类型 | 短期上下文 | 无显式长期记忆 | 无 | 长期情景记忆 |
| 反馈来源 | 外部观察 | 内部自我评估 | 无 | 外部环境 + 内部模拟 + 语言反思 |
| 适用场景 | 交互式决策 | 单轮生成优化 | 逻辑推理 | 复杂多步决策、 编程、推理 |
| 权重更新 | 无 | 无 | 无 | 无 (语义梯度更新) |
与 ReAct 的对比: ReAct 强调“行动”与“观察”的交织,适合探索环境。Reflexion 可以看作是 ReAct 的上层封装,为其添加了一个“事后诸葛亮”的机制,通过长期记忆修正 ReAct 的短期决策偏差。
与 Self-Refine 的对比: Self-Refine 主要关注单次生成的优化(如文本重写),通常缺乏与外部环境的深度交互和长期记忆的累积。Reflexion 更强调从多次试验的失败中学习,适用于需要试错的长程任务。
5. 局限性
5.1 数据污染的争议
Reflexion 在 HumanEval 上 91% 的准确率虽然惊人,但也引发了关于数据污染的强烈质疑 。
核心论点: 批评者认为,GPT-4 的预训练数据中极可能包含了 HumanEval 的题目和标准答。如果模型“见过”答案,Reflexion 的反思过程可能并不是真正的“推理修正”,而是通过提示词诱导模型“回忆”起训练数据中的正确答案。
后续验证: 在更晚发布的、确保未被 GPT-4 见过的基准测试(如 Leetcode 新题)中,Reflexion 的表现虽然仍优于基准,但绝对数值大幅下降(如 LeetcodeHard 上仅为 15%)。这表明 91% 的数值可能部分归功于记忆效应。
5.2 局部最优与探索能力的缺乏
Reflexion 本质上是一种贪婪的优化策略。它基于当前的错误进行修正,这在数学上类似于梯度下 降,因此也继承了梯度下降的缺点——容易陷入局部最优。
WebShop 案例: 在需要高度创造性和多样化探索的 WebShop 任务中,Reflexion 未能显著超越 ReAct。
后续演进: 为了解决这一问题,后续工作如 LATS (Language Agent Tree Search) 引入了蒙特卡洛树搜索,允许智能体在反思的同时回溯并探索其他分支,从而不仅能“修正”当前路径,还能“放弃”当前路径去寻找全局最优解。
5.3 对评估器质量的依赖
Reflexion 的有效性完全取决于 (评估器)的准确性。
这一点非常重要,一旦评估器的能力并没有演员好,会导致原地踏步甚至效果回退。gpt-4o-mini以上才有初步的代码评估和反馈能力,使用不同模型作为三个组件效果可能差距非常大。
误导性反馈: 如果评估器给出了错误的反馈(例如,错误的单元测试通过了错误的代码),智能体就会将错误的行为固化到记忆中。
能力悖论: 期望一个无法解决任务的模型能够准确评估该任务的解决方案,在逻辑上存在一 定的悖论。Reflexion 在编程任务上的成功部分得益于编译器这一客观、完美的“外部评估器”,而在开放式生成任务中,这一优势将不复存在。
6.Reflection的demo代码实现
如果有想实现一个ReAct智能体的demo,可以参考:datawhale的三种智能体经典范式构建
对于参考链接中的实现,Reflexion 机制的终止条件是"反馈中包含无需改进"或"达到最大迭代次数"。我优化了Reflexion 机制的终止条件,使其更加智能化。
首先,修改评估器的提示词逻辑(引入一个打分的json格式):
REFLECT_PROMPT_TEMPLATE = """
你是一位极其严格的代码评审专家和资深算法工程师,对代码的性能有极致的要求。
你的任务是审查以下Python代码,并专注于找出其在<strong>算法效率</strong>上的主要瓶颈。
# 原始任务:
{task}
# 待审查的代码:
```python
{code}
```
请分别分析该代码的时间复杂度与空间复杂度,并思考是否存在一种<strong>算法上更优</strong>的解决方案来显著提升性能或节省内存。
如果存在,请清晰地指出当前算法的不足,并提出具体的、可行的改进算法建议(例如,使用筛法替代试除法或采用更节省内存的结构)。
如果代码在算法层面已经达到最优,才能回答“无需改进”。
请严格输出以下 JSON(不要包含额外文本或代码块标记):
{{
"score": 0-100之间的整数分数,表示当前算法的整体质量,
"time_complexity": "时间复杂度分析",
"space_complexity": "空间复杂度分析",
"analysis": "核心瓶颈分析",
"recommendations": ["改进建议1", "改进建议2" ...]
}}
当确实无需改进时,将 "score" 设为 100,并在 "recommendations" 中写入 "无需改进"。
"""
以下是我优化后的ReflexionAgent类,基类和main函数参考上方链接。
class ReflexionAgent:
def __init__(self, llm_client, max_iterations=5, high_score_threshold: int = 90,
min_improvement: int = 2, stagnation_patience: int = 2):
self.llm_client = llm_client
self.memory = Memory()
self.max_iterations = max_iterations
# --- 智能化终止条件的配置参数 ---
self.high_score_threshold = high_score_threshold # 高分阈值:当分数超过此值,认为代码质量已很高
self.min_improvement = min_improvement # 最小改进幅度:用于判断迭代是否带来了实质性提升
self.stagnation_patience = stagnation_patience # 停滞容忍度:连续多少轮改进微小后,判定为陷入停滞
def run(self, task: str):
print(f"\n--- 开始处理任务 ---\n任务: {task}")
# --- 1. 初始执行 ---
print("\n--- 正在进行初始尝试 ---")
initial_prompt = INITIAL_PROMPT_TEMPLATE.format(task=task)
initial_code = self._get_llm_response(initial_prompt)
self.memory.add_record("execution", initial_code)
# --- 新增:初始化最佳记录 ---
best_code = initial_code
best_score = -1 # 初始分数设为负值
# --- 2. 迭代循环:反思与优化 ---
last_score = None
stagnant_rounds = 0 # 用于追踪连续未达到最小改进的轮数
last_feedback_text = None # 用于追踪上一轮的反馈文本,以检测重复
for i in range(self.max_iterations):
print(f"\n--- 第 {i + 1}/{self.max_iterations} 轮迭代 ---")
# 获取当前待评估的代码(上一轮执行的结果)
current_code_to_evaluate = self.memory.get_last_execution()
# a. 反思
print("\n-> 正在进行反思...")
reflect_prompt = REFLECT_PROMPT_TEMPLATE.format(task=task, code=current_code_to_evaluate)
feedback = self._get_llm_response(reflect_prompt)
self.memory.add_record("reflection", feedback)
parsed_feedback = self._parse_feedback_metadata(feedback)
current_score = parsed_feedback.get("score", 0) # 默认给0分防止None报错
# 如果当前分数有效且比历史最高分更高,则保存当前代码为最佳代码
if current_score is not None and current_score > best_score:
print(f"🌟 发现更好的版本!分数从 {best_score} 提升到 {current_score}")
best_score = current_score
best_code = current_code_to_evaluate
# --- 终止条件检查 ---
# --- 终止条件 1: 基于LLM的明确判断 ---
# 如果反思阶段LLM明确表示代码已无需改进,则直接终止。
# 这是最直接的智能化信号,尊重LLM的自我评估能力。
if "无需改进" in feedback or (current_score >= 100):
print("\n✅ 代码已达到最优状态,任务完成。")
break
# --- 终止条件 2: 基于分数的收敛判断 ---
# 调用辅助函数判断是否因分数足够高且改进微小而停止。
if self._should_stop_by_score(current_score, last_score):
print("\n✅ 评分显示已收敛且分数较高,停止迭代。")
break
# --- 终止条件 3: 检测改进停滞 ---
# 追踪连续改进幅度低于 `min_improvement` 的次数。
# 如果超过 `stagnation_patience`,说明可能已达到平台期,继续迭代收益不大,因此终止。
if last_score is not None:
if current_score - last_score < self.min_improvement:
stagnant_rounds += 1
else:
stagnant_rounds = 0
if stagnant_rounds >= self.stagnation_patience:
print("\n⚠️ 连续多轮改进幅度不足,停止迭代。")
break
# --- 终止条件 4: 检测反馈循环 ---
# 如果本轮的反馈文本与上一轮完全相同,说明LLM可能陷入了“反思-优化”的局部最优循环,
# 无法产生新的有效改进,因此终止。
current_feedback_text = feedback.strip()
if current_feedback_text and current_feedback_text == last_feedback_text:
print("\n⚠️ 反馈内容重复,停止迭代。")
break
last_score = current_score
last_feedback_text = current_feedback_text
# c. 优化
# 注意:如果这轮优化导致分数降低,下一轮循环开头评分时 best_score 不会更新,
# 从而保证了我们永远持有历史最好的那个版本。
print("\n-> 正在进行优化...")
refine_prompt = REFINE_PROMPT_TEMPLATE.format(
task=task,
last_code_attempt=current_code_to_evaluate,
feedback=feedback
)
refined_code = self._get_llm_response(refine_prompt)
self.memory.add_record("execution", refined_code)
print(f"\n--- 任务完成 ---\n最终保留的代码 (最高分: {best_score}):\n```python\n{best_code}\n```")
return best_code
def _get_llm_response(self, prompt: str) -> str:
"""一个辅助方法,用于调用LLM并获取完整的流式响应。"""
messages = [{"role": "user", "content": prompt}]
response_text = self.llm_client.think(messages=messages) or ""
return response_text
def _parse_feedback_metadata(self, feedback: str) -> Dict[str, Any]:
metadata = {
"score": None,
"analysis": None,
"recommendations": [],
"time_complexity": None,
"space_complexity": None,
}
if not feedback:
return metadata
json_str = self._extract_json_block(feedback)
if not json_str:
return metadata
try:
data = json.loads(json_str)
except json.JSONDecodeError:
return metadata
if isinstance(data, dict):
metadata["score"] = data.get("score")
metadata["analysis"] = data.get("analysis")
metadata["time_complexity"] = data.get("time_complexity")
metadata["space_complexity"] = data.get("space_complexity")
recs = data.get("recommendations") or []
metadata["recommendations"] = recs if isinstance(recs, list) else [recs]
return metadata
@staticmethod
def _extract_json_block(text: str) -> Optional[str]:
start = text.find("{")
end = text.rfind("}")
if start == -1 or end == -1 or end <= start:
return None
return text[start:end + 1]
def _should_stop_by_score(self, score: Optional[int], last_score: Optional[int]) -> bool:
"""
智能化终止条件的辅助函数
根据分数判断是否应该停止迭代。
停止的条件是:
1. 当前分数和上一轮分数都已超过高分阈值 (`high_score_threshold`)。
2. 分数变化非常小,未达到最小改进幅度 (`min_improvement`)。
当两者同时满足时,认为已经收敛,可以停止。
"""
if score is None or last_score is None:
return False
# 条件1: 分数足够高
high_enough = score >= self.high_score_threshold and last_score >= self.high_score_threshold
# 条件2: 改进幅度微小
minor_change = abs(score - last_score) < self.min_improvement
return high_enough and minor_change
更多推荐



所有评论(0)