【Reflextion论文总结】

Reflextion论文总结


论文作者:

在这里插入图片描述

1、简介

Reflexion框架通过语言反馈来强化LLM Agent,而不是通过更新权重的方法进行学习。传统的强化学习方法需要大量的训练样本和昂贵的模型微调,这对于把大型语言模型(LLMs)与外部环境进行交互作为目标驱动的 智能体Agent 来说仍然是具有挑战性的。 Reflexion 通过将任务反馈信号转化为反思,并将其保存在循环记忆缓冲区中以诱导更好的决策,在后续试验中提高决策能力。

Reflexion框架灵活地集成了各种类型和来源的反馈信号,并在多种任务上取得了显著的改进,包括序列决策、编码和语言推理等。例如,在HumanEval编程基准测试中,Reflexion实现了91%的准确率,超过了之前的GPT-4(其准确率为80%)。此外,作者还进行了不同反馈信号、反馈集成方法和Agent类型的分析和实验,提供了对性能影响的解析思路。

2、创新点

该论文的主要贡献在于提出了Reflexion这一框架,并在实验中证明了其有效性。具体来说,该方法有以下几个创新点:

  • 提出了“反思”这一全新的“口头”强化学习范式,它将策略参数化为Agent的记忆,并与LLM参数的选择相结合。
  • 探索了LLM中自我反思的这一新特性,并经过实证验证表明,自我反思对于在少数尝试中学习复杂任务非常有用。
  • 引入了LeetcodeHardGym,这是一个包含40个具有挑战性的Leetcode问题(“困难级别”),覆盖19种编程语言的代码生成强化学习环境。
  • 进行了“反思”在多个任务上相对于基线方法的比较,证明了Reflexion在决策制定、推理和编程任务上的有效性。

3、主要内容

整体框架

Reflexion 由三个不同的模型组成:Actor、Evaluator和Self-Reflection。Actor模型使用大型语言模型(LLM)来生成文本和动作,并在环境中接收观察结果。Evaluator模型负责评估Actor产生的轨迹的质量,并计算一个奖励分数以反映其性能。Self-Reflection 模型则对反馈内容进行反思,为后续流程提供有价值的反馈信息。这三个模型共同协作,在任务中不断迭代优化,从而提高决策能力。

在这里插入图片描述

如上图所示,自我反思的三个主要模块功能为:

  • 参与者(Actor):根据状态观测量生成文本和动作。参与者在环境中采取行动并接受观察结果,从而形成轨迹。链式思考(CoT) 和 ReAct 被用作参与者模型。此外,还添加了记忆组件为智能体提供额外的上下文信息。
  • 评估者(Evaluator):对参与者的输出进行评价。具体来说,它将生成的轨迹(也被称作短期记忆)作为输入并输出奖励分数。根据人物的不同,使用不同的奖励函数(决策任务使用LLM和基于规则的启发式奖励)。
  • 自我反思(Self-Reflection):生成语言强化线索来帮助参与者实现自我完善。这个角色由大语言模型承担,能够为未来的试验提供宝贵的反馈。自我反思模型利用奖励信号、当前轨迹和其持久记忆生成具体且相关的反馈,并存储在记忆组件中。智能体利用这些经验(存储在长期记忆中)来快速改进决策。

记忆组件

自我反思过程的核心组成部分是短期记忆和长期记忆的概念。在推理时,Actor根据短期和长期的记忆做出决定,类似于人类在记住近期细节的同时,也会回忆起从长期记忆中提炼出来的重要经历。在RL设置中,轨迹历史作为短期记忆,而自我反思模型的输出存储在长期记忆中,具体存储的形式为上下文。这两个记忆组件一起工作,提供特定的上下文,但也受到几次试验的经验教训的影响,这是自我反思Agent相对于其他LLM Actor选择工作的一个关键优势。

流程

自我反思模型也是LLM的一个实例,在Reflexion框架中扮演着至关重要的角色,它通过生成口头自我反思来为未来的交互提供有价值的反馈。在稀疏的奖励信号的情况下,比如二元成功状态(成功/失败)、当前轨迹以及其持久记忆mem的情况下,自我反思模型会生成具体的反馈。这种反馈比标量奖励更有信息量,然后被存储在Agent的记忆(mem)中。具体算法如下:
在这里插入图片描述

总的来说,自我反思的关键步骤是a)定义任务,b)生成轨迹,c)评估,d)执行自我反思,e)生成下一条轨迹。下图展示了自我反思的智能体学习迭代优化其行为来解决决策、编程和推理等各种任务的例子。自我反思(Refelxion)通过引入自我评估、自我反思和记忆组件来拓展 ReAct 框架。

在这里插入图片描述

4、自我反思适用情形

自我反思最适合以下情况:

  • 智能体需要从尝试和错误中学习:自我反思旨在通过反思过去的错误并将这些知识纳入未来的决策来帮助智能体提高表现。这非常适合智能体需要通过反复试验来学习的任务,例如决策、推理和编程。
  • 传统的强化学习方法失效:传统的强化学习(RL)方法通常需要大量的训练数据和昂贵的模型微调。自我反思提供了一种轻量级替代方案,不需要微调底层语言模型,从而使其在数据和计算资源方面更加高效。
  • 需要细致入微的反馈:自我反思利用语言反馈,这比传统强化学习中使用的标量奖励更加细致和具体。这让智能体能够更好地了解自己的错误,并在后续的试验中做出更有针对性的改进。
  • 可解释性和直接记忆很重要:与传统的强化学习方法相比,自我反思提供了一种更可解释、更直接的情景记忆形式。智能体的自我反思存储在其记忆组件中,让分析和理解其学习过程变得更加简单。

自我反思主要适用于以下任务:

  • 序列决策:自我反思提高了智能体在 AlfWorld 任务中的表现,涉及在各种环境中导航并完成多步目标。
  • 推理:自我反思提高了 HotPotQA 上智能体的性能,HotPotQA 是一个需要对多个文档进行推理的问答数据集。
  • 编程:自我反思的智能体在 HumanEval 和 MBPP 等基准测试上编写出了更好的代码,在某些情况下实现 SOTA 结果。

5、实验结果

实验结果表明,自我反思能够显著提高 AlfWorld 上的决策任务、HotPotQA 中的问题推理以及在 HumanEval 上的 Python 编程任务性能。

在序列决策 (AlfWorld) 任务上进行评估时,ReAct + Reflexion 用启发式和 GPT 的自我评估进行二元分类,完成了 130/134 项任务,显着优于 ReAct。

在仅仅几个学习步骤中,自我反思显著优于所有基线方法。仅对于推理以及添加由最近轨迹组成的情景记忆时,Reflexion + CoT 的性能分别优于仅 CoT 和具有情景记忆的 CoT。

如下表所示,在 MBPP、HumanEval 和 Leetcode Hard 上编写 Python 和 Rust 代码时,Reflexion 通常优于之前的 SOTA 方法。

6、Langchain实现

在“反思”中,行为主体明确地批评每个响应,并将批评建立在外部数据的基础上。它直接生成引用,并明确列举生成响应中多余和缺失的方面。这使得反思的内容更加建设性,并更好地引导生成器响应反馈。在下面的示例中,我们在固定的步骤后停止,但其实也可以将此决定交给反思LLM调用。行为主体循环的概述如下:

在这里插入图片描述

论文中框架主要由三部分构成(上文已介绍过),下面主要可以看看关键代码:

  • Actor (agent) with self-reflection
  • External evaluator (task-specific, e.g. code compilation steps)
  • Episodic memory that stores the reflections.

AnswerQuestion

from langchain_core.messages import HumanMessage, ToolMessage
from langchain_core.output_parsers.openai_tools import PydanticToolsParser
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.pydantic_v1 import BaseModel, Field, ValidationError


class Reflection(BaseModel):
    missing: str = Field(description="Critique of what is missing.")
    superfluous: str = Field(description="Critique of what is superfluous")


class AnswerQuestion(BaseModel):
    """Answer the question. Provide an answer, reflection, and then follow up with search queries to improve the answer."""

    answer: str = Field(description="~250 word detailed answer to the question.")
    reflection: Reflection = Field(description="Your reflection on the initial answer.")
    search_queries: list[str] = Field(
        description="1-3 search queries for researching improvements to address the critique of your current answer."
    )


class ResponderWithRetries:
    def __init__(self, runnable, validator):
        self.runnable = runnable
        self.validator = validator

    def respond(self, state: list):
        response = []
        for attempt in range(3):
            response = self.runnable.invoke(
                {"messages": state}, {"tags": [f"attempt:{attempt}"]}
            )
            try:
                self.validator.invoke(response)
                return response
            except ValidationError as e:
                state = state + [
                    response,
                    ToolMessage(
                        content=f"{repr(e)}\n\nPay close attention to the function schema.\n\n"
                        + self.validator.schema_json()
                        + " Respond by fixing all validation errors.",
                        tool_call_id=response.tool_calls[0]["id"],
                    ),
                ]
        return response

Initial responder

import datetime

actor_prompt_template = ChatPromptTemplate.from_messages(
    [
        (
            "system",
            """You are expert researcher.
Current time: {time}

1. {first_instruction}
2. Reflect and critique your answer. Be severe to maximize improvement.
3. Recommend search queries to research information and improve your answer.""",
        ),
        MessagesPlaceholder(variable_name="messages"),
        (
            "user",
            "\n\nReflect on the user's original question and the"
            " actions taken thus far. Respond using the {function_name} function.",
        ),
    ]
).partial(
    time=lambda: datetime.datetime.now().isoformat(),
)
initial_answer_chain = actor_prompt_template.partial(
    first_instruction="Provide a detailed ~250 word answer.",
    function_name=AnswerQuestion.__name__,
) | llm.bind_tools(tools=[AnswerQuestion])
validator = PydanticToolsParser(tools=[AnswerQuestion])

first_responder = ResponderWithRetries(
    runnable=initial_answer_chain, validator=validator
)

Revision

revise_instructions = """Revise your previous answer using the new information.
    - You should use the previous critique to add important information to your answer.
        - You MUST include numerical citations in your revised answer to ensure it can be verified.
        - Add a "References" section to the bottom of your answer (which does not count towards the word limit). In form of:
            - [1] https://example.com
            - [2] https://example.com
    - You should use the previous critique to remove superfluous information from your answer and make SURE it is not more than 250 words.
"""


# Extend the initial answer schema to include references.
# Forcing citation in the model encourages grounded responses
class ReviseAnswer(AnswerQuestion):
    """Revise your original answer to your question. Provide an answer, reflection,

    cite your reflection with references, and finally
    add search queries to improve the answer."""

    references: list[str] = Field(
        description="Citations motivating your updated answer."
    )


revision_chain = actor_prompt_template.partial(
    first_instruction=revise_instructions,
    function_name=ReviseAnswer.__name__,
) | llm.bind_tools(tools=[ReviseAnswer])
revision_validator = PydanticToolsParser(tools=[ReviseAnswer])

revisor = ResponderWithRetries(runnable=revision_chain, validator=revision_validator)

7、一点思考

通过反思与长短期记忆可以提升生成内容的质量,但整体步骤可能比较耗时,文章也没有具体说明其迭代的具体轮数与时间。LangChain中给的例子没有突出说明长短期记忆部分,仅对Actor部分做了展示,所以对于memory部分的实现方式还是存疑。

人类智慧以其从错误中吸取教训的能力而著称。我们通常不会在第一次尝试时解决问题,但是当我们犯错误时,我们会产生新的想法,通过自我反省,通过分析我们的失误来完善我们的方法。因此,站在告警诊断的角度来看,LLM想要使用自我反思需要着重注意的是它的评估能力和反思能力,而与这很息息相关的一点就是测试集的完善程度。

实际上,论文无论使用的HumanEval数据集还是LeetcodeHardGym数据集,都有明确的评估指标和测试数据,从而供给大模型进行反思和测试。这个思路是类似于测试驱动开发(TDD)的思想,他让大模型能够快速验证当前的策略或代码能否满足条件,然后来迭代完善它的实现。我们需要满足这篇论文的原始假设“测试生成应该比策略生成更容易完成”,基于这个假设,如果一个智能体可以设计多样化和准确的测试,那么自然他们就可以使用内部测试来迭代地完善他们的实现。当前的大模型可能还远不具备这个能力,而现在基于能力不健全的大模型(LLM)我们所做的设计与尝试,还有很长的路要走。

参考链接

论文:https://arxiv.org/pdf/2303.11366

代码:https://github.com/noahshinn024/reflexion

  • 22
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值