【Agent】ReAct:最经典的Agent设计框架
文章目录
- 一、ReAct论文
- 二、ReAct工作原理
- 2.1 核心模块
- 2.2 步骤拆解
- 三、技术优势:为什么ReAct优于传统Agent?
- 四、案例分析
- 五、代码实现
- 参考资料
在早期的大语言模型(LLM)应用中,提示工程(Prompt Engineering)是连接用户意图与模型输出的核心手段。然而,纯提示驱动的方案在多步推理、工具调用和动态环境交互中常显不足。ReAct框架(Reasoning+Acting)应运而生,通过将链式推理(Reasoning) 与环境行动(Acting) 结合,构建出能主动思考、决策并执行复杂任务的智能体(Agent)。
一、ReAct论文
ReAct来自于ICLR 2023年发表的论文:REACT: SYNERGIZING REASONING AND ACTING INLANGUAGE MODELS。
论文解读参考博客: 《REACT: SYNERGIZING REASONING AND ACTING INLANGUAGE MODELS》论文阅读
该文献提出了一个名为ReAct的新方法,旨在将推理和行动在LLMs中结合起来,以解决复杂的语言理解和决策任务。传统的语言模型在处理推理任务时(如CoT)通常是静态的,依赖于模型内部的知识,容易产生幻觉和错误传播。而现有的行动生成模型(如WebGPT)则缺乏推理能力,无法动态调整计划或处理异常情况。ReAct通过交替生成推理轨迹和任务相关行动,使得模型能够在推理过程中动态调整计划,并通过与外部环境(如Wikipedia)交互获取额外信息,从而提升任务的解决能力和可解释性。
图1:(1)四种提示方法的比较,(a)标准提示,(b)链式思维(CoT,仅推理),(c)仅行动,(d)ReAct(推理+行动),用于解决HotpotQA问题。(2)(a)仅行动和(b)ReAct提示用于解决ALFWorld游戏的比较。在这两个领域中,我们在提示中省略了上下文示例,仅展示了模型生成的任务解决轨迹(行动、思维)和环境反馈(观察)。
在这项工作中,我们提出了ReAct,一种将推理和行动与语言模型结合以解决多样化语言推理和决策任务的通用范式(图1)。ReAct提示LLMs以交替的方式生成与任务相关的语言推理轨迹和行动,这使得模型能够进行动态推理,以创建、维护和调整高层次行动计划(推理以行动),同时与外部环境(如Wikipedia)交互,将额外信息纳入推理(行动以推理)。
二、ReAct工作原理
ReAct 智能体在一个思考→行动→观察的循环中运行,直到它找到解决方案或最终答案为止。
这类似于人类解决问题的方式:我们思考要做什么,执行一个行动(比如:查找某件事或进行计算), 观察结果,然后将其纳入我们的下一个思考中。
ReAct 框架使用提示词工程来强制执行这种结构化的方法,交替大模型的思考和行动/观察。
2.1 核心模块
(1)推理(Reasoning)模块
- 动态思考链(Chain-of-Thought):Agent在每一步生成自然语言推理逻辑,解释当前决策原因(如:“用户需要查天气,需先获取位置信息”)。
- 错误回溯机制:当行动失败时,Agent能分析原因并调整策略(如:“API返回错误,可能是参数格式问题,重试前需校验输入”)。
(2)行动(Acting)模块
- 工具集成(Tool Calling):调用外部API、数据库、计算器等(如:
search_weather(location="Beijing")
)。 - 环境状态感知:实时接收行动结果,作为下一步决策的输入(如:“获取到北京气温25°C,建议用户带薄外套”)。
(3)交互闭环:Reasoning与Acting的循环
ReAct的执行流程形成自迭代循环:
Thought → Act → Observation → Thought → ... → Final Answer
每一次循环都将环境反馈纳入推理,实现动态适应复杂场景的能力。
2.2 步骤拆解
下面是一个 AI 智能体中 ReAct 循环的逐步分解:
- Thought:AI 智能体(由 LLM 驱动)分析用户的查询和内部上下文,并以自然语言产生一个推理步骤。这通常不会显示给最终用户,但它是 AI 智能体规划的一部分。
例如:“问题要求一个国家的人口;Thought: 我应该使用网络搜索来找到最新数字。
”
- Action:根据思考,AI 智能体决定要执行的外部工具或操作。它输出一个规定的格式来表示行动。
例如:Action:WebSearch("2023年加拿大人口")
。AI 智能体本质上是通过名称“调用”一个函数(工具),通常带有一些输入参数。
-
Observation:AI 智能体的环境(我们的代码)执行请求的行动,并将结果(观察)返回给 AI 智能体。
例如,网络搜索工具可能会返回:“Observation:2023年加拿大人口为3800万。
”这个观察结果被输入到 AI 智能体的上下文中。
-
AI 智能体带着新信息回到第一步(另一个思考)。它将用新数据进行推理。在我们的例子中,它可能会想:“现在我有了人口数字;我可以回答问题了。”
这个思考/行动/观察循环重复进行,允许 AI 智能体在需要时链接多个工具使用(搜索,然后可能是一个计算,然后另一个搜索等)。最终,AI 智能体决定它可以回答用户。在这一点上,它不是输出一个行动,而是输出一个最终答案(有时在格式中标记为答案:或最终答案)。在整个过程中,AI 智能体保持对话和它自己的中间步骤,这就是记忆的功能。
每个思考和观察都可以被添加到对话上下文中,以便 LLM 记住到目前为止它已经做了什么。
三、技术优势:为什么ReAct优于传统Agent?
-
解决LLM的“幻觉”问题
传统Agent可能盲目执行错误指令,而ReAct的显式推理步骤让决策过程可追溯,减少无依据输出。 案例:当用户问“爱因斯坦最近的推特说了什么?”,ReAct会先推理:“爱因斯坦已去世,需搜索历史资料库而非实时社交媒体”。 -
支持长任务分解
复杂任务被拆解为原子化推理-行动对(ReAct Pair)执行:
用户请求:“分析特斯拉过去一年的股价趋势并总结原因”
Steps:
1. Thought: 需要特斯拉股票代码 → Action: search_stock_symbol("Tesla")
2. Observation: 获得代码TSLA
3. Thought: 查询过去一年股价 → Action: get_stock_data("TSLA", period="1y")
4. Observation: 接收时间序列数据
5. Thought: 调用数据分析模型 → Action: analyze_trend(data)
- 无缝集成领域工具
通过工具注册机制(如LangChain Tools),Agent可灵活扩展能力边界:
from langchain_community.tools import DuckDuckGoSearchResults
tools = [DuckDuckGoSearchResults(name="web_search"),PythonCalculatorTool() # 自定义Python计算器]
agent = ReActAgent(llm=GPT4, tools=tools)
四、案例分析
考虑在一个多智能体系统中构建的一个 AI 智能体的输出:
在上面的例子中,我们看到了一个使用 ReAct 范式执行任务的新闻报道 AI 智能体的实时追踪。该 AI 智能体被要求创建一个与“Agent2Agent协议”相关的新闻标题。然而,它并没有急于下结论,而是如其结构化的追踪所示,逐步推理。
接下来我们拆解一下:
- AI 智能体角色:新闻报道者–这个 AI 智能体专门负责策划和验证新闻内容。
- Task:该 AI 智能体被指示生成一个新闻标题,并确保它与Agent2Agent协议相关。
- Thought:该 AI 智能体首先内部推理,它应该通过快速搜索关于该协议的最新更新来验证信息。这是 ReAct 周期中的推理部分。
- Action:它接着使用一个标记为“搜索互联网”的工具,传递一个结构化的 JSON 输入,查询内容为:“Agent2Agent 协议新闻 2023年11月”。这是 AI 智能体利用外部工具收集现实世界数据的行动步骤。
- Tool Output:它包含了搜索工具检索到的结果–可能是新闻片段、文章摘要或相关网址。 这展示了将结构化思考和外部行动结合起来的力量:AI 智能体不仅仅依赖大模型的内部知识,而是通过工具进行事实核查。
这是一个例子,说明了 ReAct 模式是如何鼓励 AI 智能体行为的透明性、准确性和可验证性:对于那些需要处理真实世界信息的系统来说,这可是非常重要。
五、代码实现
Github项目代码:https://github.com/samwit/langchain-tutorials/blob/main/agents/YT_Exploring_ReAct_on_Langchain.ipynb
本质上所有的 Agent 设计模式都是将人类的思维、管理模式以结构化prompt的方式告诉大模型来进行规划,并调用工具执行,且不断迭代的方法。
接下来结合代码内容详细解读。
- 生成提示词。 首先,将代码中预设好 ReAct 的提示词模板(格式为Quesion->Thought->Action->Observation)和用户的问题进行合并。得到的提示词是这样的。
如果需要针对你自己的领域定制,需要将 fewshot 里的内容更换为更合适的内容,比如你的 Action 里可能会有"Send message to someone", 这里的 Action “Send message” 可能就对应一个外部工具的 API 接口。 - 调用大模型生成Thought+Action。 接下来将 few shot 提示词发给大模型。如果直接将上述提示词发给大模型,大模型生成将针对用户问题生成一堆 Thought,Action 和 Observation,但显然这里 Action 还没有展开,我们并不希望大模型输出 Observation。在代码里通过 Stop.Observation 来控制大模型遇到Observation后停止输出,于是大模型仅仅返回 Thought 和 Action,而不会把 Observation 给生成出来。
- 调用外部工具。 拿到 Action 之后,大模型就可以调用外部工具了。首先判断这里的 Action 是不是 Finish,如果不是我们就可以利用大模型把 Action 后面的自然语言转换为外部工具能识别的 API 接口,这个转换过程就是大模型的 function calling 功能,本质上是对大模型进行微调,专门用于语言格式转换的模型,但并非所有的大模型都支持 function calling。
- 生成Observation。 API 接口返回后,还会将接口返回内容转换为自然语言输出,生成 Observation,然后将 Observation 的内容,加上刚刚的 Thought, Action 内容输入给大模型,重复第 2,3 步,直至 Action 为Finish 为止。
- 完成输出。 将最后一步的 Observation 转化为自然语言输出给用户。
由此,我们可以看到 Agent 要落地一个场景,需要定制两项内容。
- Prompt 模板中 few shot 中的内容。
- function calling 中的外部工具定义。
而 Prompt 模板中 fewshot 本质上就是人类思维模式的结构化体现,通过查阅各个设计模式的 prompt 模板是很好的学习 Agent 设计模式的方法,习得这个方法,可以用同样的方法理解其他的设计模式,以下模式不再进行代码解读。
参考资料
- 智能体 | 基于ReAct框架:构建极简智能体实践的探索
- 智能体的开发-ReAct 框架
- AI 智能体 ReAct 架构设计模式剖析