【Agentic RL 专题】深入浅出了解ReAct

? 前言:从 cot 到 react

在只有基础对话能力的阶段,大模型更多像一个“一次性回答机”:

User: 问题 LLM : 一次性生成答案

即便我们加上了 Memory、RAG,智能体也只是多了“能记”和“会查”:

Memory:记住过去发生了什么(多轮对话、历史任务状态) RAG:在回答前去查一查知识库或互联网

但这仍然是“问一答一”的模式,缺少真正的多步决策与行动能力。

ReAct(Reasoning + Acting) 正是为了解决这个问题提出的:

在推理过程中,显式地交替输出“思考内容(Thought)”和“行动指令(Action)”,再利用环境反馈(Observation)更新后续推理。

一、ReAct 范式长什么样?

原论文《ReAct: Synergizing Reasoning and Acting in Language Models》采用的典型轨迹格式如下:

Question: (用户问题)Thought 1: 我需要先查一下 X 的相关背景。Action 1: search["X 的维基百科页面"]Observation 1: (搜索工具返回的摘要文本)Thought 2: 现在我知道了 X 的定义,还需要确认 Y。Action 2: lookup["Y 相关条目"]Observation 2: (查具体条目返回的信息)Thought 3: 根据 Observation 1 和 2,可以得出结论……Final Answer: (给用户的最终回答)

可以发现,在思考的过程中的关键元素如表所示:

元素

是否改变环境

主要作用

示例

Thought

❌ 不改变环境

作为“内心独白”,用于规划下一步、整理当前已知信息、解释为什么要调用某个工具

“我需要先查一下 2024 年奥运会的举办城市。”

Action

✅ 通过调用工具/环境间接改变环境

发出结构化“命令”,触发具体操作(检索、查表、移动等)

search["query"]lookup["entity"]move["north"](如 ALFWorld 中的移动)

Observation

✅ 环境产生的结果

记录环境或工具对 Action 的反馈,为下一步 Thought 提供依据

搜索结果文本、API 返回的 JSON、环境状态描述

Final Answer

❌ 自身不再行动(但对用户是最终输出)

标志推理/行动序列结束,给出最终对用户的回答

Final Answer: 2024 年奥运会举办城市是巴黎…

☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 免费无限量使用 DeepSeek R1 模型☜☜☜

【Agentic RL 专题】深入浅出了解ReAct

LLM 的工作就变成了:

二、从 CoT 到 ReAct

先来看一下CoT(Chain-of-Thought) 的流程形式:

Q: 2 + 3 * 4 = ?

A:

Step 1: 先算乘法 3*4 = 12

Step 2: 再算加法 2 + 12 = 14

所以答案是 14

Type Type

生成草稿,转换文本,获得写作帮助-等等。

Type 83 查看详情 Type

链式思考的出现大大提升了大模型的数学推理能力,他并不是重新训练大模型来得到这种能力的,而是通过prompting来挖掘大模型本就有的推理能力。

CoT的基础上,ReAct 的核心变化就是:在 “思考链(Thought)” 中间插入 “动作(Action)” 和 “环境反馈(Observation)”, 然后多轮循环。具体流程如下:

step 1. 在 Prompt 里定义协议

你是一个可以一边思考一边操作工具的助手。

你必须严格按下面格式输出(非常重要):

Question: {用户问题}

Thought: …

Action: 工具名”参数”

Observation: …

当你已经可以回答用户问题时,输出:

Final Answer: …

step 2. 循环控制伪代码

while True:    llm_output = call_llm(prompt)    if "Final Answer:" in llm_output:        提取最终答案,结束    action = parse_action(llm_output)         # 找 Action: xxx["..."]    obs = run_tool(action)                    # 真正调用工具    prompt += llm_output + f"Observation: {obs}"
【Agentic RL 专题】深入浅出了解ReAct

学到这里,我们可以说,ReAct其实本质就是一种更加“高级 prompting + 外层控制逻辑”

三、手撕“迷你 ReAct 循环”

为了帮助读者更好的理解ReAct·,我们先手撕简化版 ReAct 循环(伪代码,逻辑关键):

step 0. 工具自定义

import refrom typing import Dict, Callable# 假设这是一个Chat LLM 接口def call_llm(prompt: str) -> str:    passTOOLS: Dict[str, Callable[[str], str]] = {}def register_tool(name: str):    def decorator(fn):        TOOLS[name] = fn        return fn    return decorator@register_tool("calculator")def calculator(expr: str) -> str:    """计算简单数学表达式"""    try:        return str(eval(expr))    except Exception as e:        return f"计算错误: {e}"

step 1. 在 Prompt 里定义协议

REACT_SYSTEM_PROMPT = """你是一个可以一边思考一边使用工具的助手。交互格式如下:Thought: 先解释你在想什么Action: 工具名["参数"]Observation: 我会用工具返回的结果填在这里...最后当你可以回答用户问题时,请输出:Final Answer: 给出最终回答当前可用工具:- calculator: 计算数学表达式,格式如 calculator["1+2*3"]"""

step 2. 循环控制

def react_loop(question: str, max_steps: int = 5):    scratchpad = ""    for step in range(1, max_steps + 1):        prompt = (            REACT_SYSTEM_PROMPT            + f"Question: {question}"            + scratchpad            + "请给出下一步 Thought / Action 或 Final Answer:"        )        llm_output = call_llm(prompt)        # 1. 先看是否已经给出 Final Answer        if "Final Answer:" in llm_output:            answer = llm_output.split("Final Answer:")[1].strip()            print("✅ Final Answer:", answer)            return answer        # 2. 解析 Action        action_match = re.search(r"Action:s*(w+)["(.*)"]", llm_output)        if action_match:            tool_name, tool_input = action_match.groups()            if tool_name not in TOOLS:                observation = f"工具 {tool_name} 不存在。"            else:                observation = TOOLS[tool_name](tool_input)            # 把这一步的 Thought / Action / Observation 追加到 scratchpad            scratchpad += (                f"{llm_output.strip()}"                f"Observation: {observation}"            )        else:            # 如果没解析出 Action,只把 Thought 拼进去,继续下一轮            scratchpad += f"{llm_output.strip()}"    print("⚠️ 达到最大步数仍未得到 Final Answer")    return None

拼 prompt:系统提示 + 问题 + 之前的 Thought/Action/Observation 轨迹;让 LLM 输出下一步:要么继续 Thought + Action;要么直接给出 Final Answer;解析 Action,调用对应工具,补上 Observation;循环直到终止。

LangChain 做的事情,本质上就是把这个“循环 + 解析 + 工具调用”封装成一个可复用的 LCEL 运行图,并提供不少内置工具和 Prompt 模板。

四、 LangChain 框架实现ReAct Agent

⚙️ 依赖安装(示例环境)

pip install -U langchain langchain-openai langchain-community duckduckgo-search`

3.1 定义 LLM 与工具

# 带搜索 + 计算器的 ReAct Agent 示例import osfrom langchain_openai import ChatOpenAIfrom langchain_community.tools import DuckDuckGoSearchRunfrom langchain_core.tools import tool# 远程调用,需要KEYos.environ["OPENAI_API_KEY"] = "你的 key"# 1️⃣ LLM:底层使用 Chat 接口(如 GPT-4 / DeepSeek 等)llm = ChatOpenAI(    model="gpt-4o-mini",   # 或者 deepseek/chat 等    temperature=0)# 本地定义llm#from langchain_community.chat_models import ChatOllama#llm = ChatOllama(#    model="qwen2.5:7b-instruct",  # 本地 ollama 已经拉好的模型#    temperature=0#)# 2️⃣ 定义一个自定义工具:计算器@tooldef calculator(expression: str) -> str:    """计算一个数学表达式,例如 '1+2*3'。"""  #docstring    try:        return str(eval(expression))    except Exception as e:        return f"计算出错: {e}"#内置的 DuckDuckGo 搜索工具,简单的网页搜索工具,无需keysearch = DuckDuckGoSearchRun()tools = [calculator, search]

@tool 装饰器会自动把 Python 函数包装成 LangChain 的 BaseTool 对象;

3.2 ReAct Prompt

在第三章我们提过,需要在 Prompt 里定义协议;

而在LangChain Hub 中这些事已经不需要我们做了, 因为已经有现成的 ReAct Prompt(hwchase17/react)以直接拿来用:[

from langchain import hub# 从 LangChain Hub 拉取 ReAct Promptprompt = hub.pull("hwchase17/react")print(prompt.template[:400], "...")

你打印一下会看到类似结构(英文),明确告诉 LLM 要循环输出 Thought / Action / Observation,直到给出 Final Answer。

Answer the following questions as best you can. You have access to the following tools:{tools}Use the following format:Question: the input question you must answerThought: you should always think about what to doAction: the action to take, should be one of [{tool_names}]Action Input: the input to the actionObservation: the result of the action.. (this Thought/Action/Action Input/Observation can repeat N times)Thought: I now know the final answerFinal Answer: the final answer to the original input questionBegin!Question: {input}Thought:

3.3 使用 create_react_agent 构建 Agent + Executor

LangChain 提供了一个封装好的工厂函数:create_react_agent,专门用来构造 ReAct 风格的 Agent。

from langchain.agents import create_react_agent, AgentExecutor# 5️⃣ 构建 ReAct Agent(本质是一个 LCEL runnable)agent = create_react_agent(    llm=llm,    tools=tools,    prompt=prompt,)# 6️⃣ 用 AgentExecutor 包一层循环执行逻辑agent_executor = AgentExecutor(    agent=agent,    tools=tools,    verbose=True,        # 打印中间 Thought / Action / Observation 轨迹    max_iterations=5,    # 最多迭代 5 轮    handle_parsing_errors=True,)

3.4 测试

query = "请查一下 2024 年奥运会举办城市,然后算一下这个城市名称的长度平方是多少?"result = agent_executor.invoke({"input": query})print("? 最终回答:", result["output"])

verbose=True 的情况下,你会在控制台看到类似这样的轨迹(示意):

Thought: 我需要先查一下 2024 年奥运会的举办城市。Action: duckduckgo_searchAction Input: "2024 Summer Olympics host city"Observation: The 2024 Summer Olympics were held in Paris, France. ...Thought: 我知道了举办城市是 Paris。现在需要计算城市名称长度的平方。Action: calculatorAction Input: "len('Paris')**2"Observation: 25Thought: 我已经知道了最终答案。Final Answer: 2024 年奥运会举办城市是巴黎(Paris),城市名 "Paris" 的长度为 5,5 的平方为 25,因此答案是 25。

分析一下:

1. 第一步 Thought:说明“先查办奥运会城市”;2. 第一步 Action:调用 `duckduckgo_search`;    3. Observation 包含了搜索结果(告诉你是 Paris);    4. 第二步 Thought:决定用 calculator 计算长度平方;    5. 第二步 Action:调用 `calculator`;    6. Observation 给出 25;    7. 最后 Thought + Final Answer:给出解释 + 最终结论。

可以发现,这个过程和我们上面手写的 ReAct loop 是一一对应的,只不过 LangChain 帮我们封装了细节。

四、ReAct的发展

? 4.1 在 ReAct 之上叠“反思(Reflexion)”

在 ReAct 的基础循环上,再叠一层“学习自己的经验”的外环。比如 Reflexion 让 Agent 在失败后,用自然语言总结“刚才哪一步错了,下次应该怎么改”,再写入 Memory,下一轮参考。Reflexion: Language Agents with Verbal Reinforcement Learning

? 4.2 与「规划(Planning)」结合

原生 ReAct 偏“短视”——每一步都是 “想一点 → 做一步”,对需要长远规划、多阶段子任务的场景不够强。比如 2025 的 Pre-Act 工作就直接点名:ReAct 通常是“即时思考 + 即时动作”,对复杂任务效果有限,于是提出“先做多步规划,再结合 ReAct 执行”的框架

【Agentic RL 专题】深入浅出了解ReAct

五、总结

到这一章,我们已经让智能体具备了三种“能力模块”:

Memory 让它记住发生过什么,RAG 让它查询外部世界的知识,而 Planner 则让它从“一问一答”升级为“多步决策的任务执行者”。

但目前这一切,仍然是“静态策略”:

规划规则、检索策略、记忆使用方式,都是我们人为写在 prompt 里或硬编码在逻辑中的。 在未来的学习中,我们希望让这些策略自己学会变好,自然就得进一步引出 Agentic RL:

以上就是【Agentic RL 专题】深入浅出了解ReAct的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/983484.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
如何用css实现按钮hover颜色变化
上一篇 2025年12月1日 21:06:50
Git工作流:从主分支克隆后创建独立开发分支的最佳实践
下一篇 2025年12月1日 21:06:53

相关推荐

  • VSCode怎么新建ipynb文件_VSCode创建和编辑Jupyter笔记本文件教程

    答案:在VSCode中运行Jupyter笔记本需准备Python环境、安装Python扩展并确保安装ipykernel;通过命令面板或文件菜单新建笔记本,编辑时可添加代码或Markdown单元格,运行代码后结果实时显示;通过右上角内核选择器切换Python环境,推荐为不同项目配置独立虚拟环境以避免依…

    2026年9月21日
    000
  • Windows 10功能更新1909版错误0xc19001e1怎么解决?

    0xc19001e1错误可通过禁用第三方安全软件、清理磁盘空间、运行Windows更新疑难解答及重置更新组件解决。首先卸载非微软安全软件并重启;确保C盘有20GB以上可用空间,通过设置清理临时文件;使用内置疑难解答工具修复更新问题;最后以管理员身份运行命令提示符,停止wuauserv、cryptSv…

    2026年9月21日
    000
  • windows怎么格式化硬盘_windows硬盘格式化方法

    格式化硬盘可通过四种方法完成:1. 使用磁盘管理工具,进入“此电脑”→“管理”→“磁盘管理”,右键目标分区选择“格式化”,设置文件系统及是否快速格式化;2. 通过文件资源管理器,在“此电脑”中右键驱动器选择“格式化”,选择NTFS等文件系统并开始操作;3. 使用命令提示符运行diskpart工具,依…

    2026年9月21日
    100
  • 夸克Ai搜索如何设置默认_夸克Ai搜索默认引擎更改

    首先在夸克APP中将默认搜索引擎设为AI引擎,再开启相关AI功能开关以启用AI搜索服务。具体步骤:1、打开夸克APP,点击右下角菜单进入设置;2、选择“通用”选项,点击“搜索引擎”;3、选择“AI引擎”或“夸克AI搜索”作为默认服务;4、返回主界面测试搜索关键词,确认AI结果是否展示;5、进入“AI…

    2026年9月21日
    400
  • Laravel中的Blade模板引擎基础用法

    blade模板引擎在laravel中用于简化视图开发。具体使用方法如下:1.输出变量:{{ $variable }}。2.条件判断:@if、@else、@elseif。3.循环:@foreach。4.模板继承:@extends、@section、@yield。blade让视图代码更简洁易读,但需注意…

    2026年9月21日
    000
  • Windows10重置此电脑卡住不动了怎么办_Windows10重置电脑卡住修复方法

    重置电脑卡住时,先等待2-4小时观察硬盘灯是否闪烁,确认系统是否仍在运行;若无响应,可尝试断开网络避免更新下载、调整BIOS关闭Secure Boot并启用Legacy模式;或使用Windows安装U盘启动,进入修复模式执行启动修复、chkdsk磁盘检查,以及通过三次强制关机触发恢复环境重试重置。 …

    2026年9月21日
    000
  • Linux查看系统日志的常用命令

    答案是查看Linux日志需综合使用journalctl、dmesg、tail、grep等工具。journalctl用于systemd系统集中查询服务及内核日志,支持时间、优先级、字段等多维度过滤;dmesg专注内核启动与硬件问题;tail -f实时监控日志动态;cat、grep、less结合正则和管…

    用户投稿 2026年9月21日
    000
  • mysql如何实现后台管理系统

    答案:基于MySQL的%ignore_a_1%需设计用户、权限、日志等表结构,通过后端语言实现安全的CRUD接口与JWT认证,前端展示数据并控制权限,确保系统安全稳定。 实现一个基于 MySQL 的后台管理系统,核心是构建一个安全、稳定、可扩展的系统架构,将数据库作为数据存储层,配合后端语言和前端界…

    2026年9月21日
    000
  • Workerman服务启动失败的排查步骤

    workerman服务启动失败的排查步骤如下:1. 检查配置文件,确保无语法错误;2. 查看系统日志,寻找错误线索;3. 检查端口占用情况,确保端口未被占用;4. 调整文件权限,确保workerman有足够权限;5. 检查php环境,确保版本兼容且扩展已安装。 关于Workerman服务启动失败的排…

    2026年9月21日
    200
  • 如何为VSCode设置自定义的代码高亮颜色?

    答案:通过settings.json中的editor.tokenColorCustomizations可自定义VSCode代码高亮颜色,支持全局或特定主题下修改关键字、字符串等元素颜色,结合textMateRules和作用域精确控制,提升代码可读性。 为 VSCode 设置自定义的代码高亮颜色,可以…

    2026年9月21日
    000
  • 百度浏览器自动跳转怎么办 百度浏览器页面跳转广告拦截方法

    百度浏览器自动跳转通常由恶意软件或设置被篡改引起,需检查浏览器设置、清除异常插件、修复快捷方式与注册表,并使用安全软件扫描清理,同时启用广告拦截与隐私保护功能以彻底解决问题。 百度浏览器出现自动跳转,通常不是浏览器本身的问题,而是由恶意软件、插件或设置被篡改导致的。解决这个问题需要从多个方面入手,检…

    2026年9月21日
    100
  • 115网盘资源查找入口_115网盘资源快速链接通道

    115网盘资源查找入口为http://www.115.com/,支持多平台访问、高效媒体管理及安全存储,提供网页端与客户端多种使用方式。 115网盘资源查找入口在哪里?这是不少网友都关注的,接下来由PHP小编为大家带来115网盘资源快速链接通道,感兴趣的网友一起随小编来瞧瞧吧! http://www…

    2026年9月21日
    000
  • 压力测试(Benchmark)Swoole服务的工具与方法

    进行swoole服务的压力测试是为了确保服务在高负载下稳定运行。1. 选择工具:apache jmeter、wrk、locust。2. 使用方法:jmeter通过脚本配置,wrk通过命令行,locust通过python脚本。3. 注意事项:环境隔离、数据监控、脚本设计。4. 优化点:内存泄漏、连接池…

    2026年9月21日
    000
  • Windows11内存占用率过高怎么解决_Windows11内存占用过高修复方法

    1、通过任务管理器结束高内存占用进程;2、禁用Superfetch(SysMain)服务以降低内存负担;3、优化启动项减少后台负载;4、升级物理内存条提升系统性能。 如果您发现Windows 11系统运行缓慢,并且任务管理器显示内存占用率持续处于高位,这可能是由于后台进程过多、系统服务占用资源或硬件…

    2026年9月21日
    100
  • mysql常用存储引擎有哪些

    InnoDB是现代MySQL应用的首选存储引擎,因其支持事务(ACID)、行级锁、外键约束、崩溃恢复和MVCC,适用于高并发、数据完整性要求高的OLTP场景;MyISAM虽读取快但仅支持表级锁且无事务和外键,适用于读多写少的简单场景,已逐渐被淘汰;Memory引擎将数据存于内存,速度快但易失,适合临…

    2026年9月21日
    000
  • Linux目录结构与Windows目录结构对比

    Linux采用单一树状结构,所有文件系统挂载于根目录/下,如/home、/etc;Windows以C:\、D:\等独立盘符划分,无统一根节点。2. Linux将配置集中于/etc,用户数据存于/home,系统文件在/bin、/usr等,配置明文可编辑;Windows程序装在Program Files…

    用户投稿 2026年9月21日
    100
  • 谷歌浏览器图片无法显示怎么办 谷歌浏览器图片加载失败修复方法

    首先检查浏览器图片显示设置是否允许,确认无误后清除缓存和Cookie数据,接着排查扩展程序干扰,最后更新浏览器并检查硬件加速设置。 谷歌浏览器图片加载不出来,通常不是大问题,多数情况通过几个简单操作就能解决。下面列出几种常见且有效的排查方法。 检查图片显示设置 最直接的原因可能是浏览器被设置为阻止图…

    2026年9月21日
    000
  • 如何配置VSCode来完美支持Vue.js开发?

    安装Volar、TypeScript Vue Plugin、ESLint和Prettier扩展,禁用Vetur,在settings.json中配置vetur.enabled为false,设置ESLint保存时自动修复并指定Prettier为默认格式化工具,关联.vue文件语言,启用TypeScrip…

    2026年9月21日
    000
  • Potplayer如何修复卡顿问题_Potplayer解决播放卡顿的实用方案

    更换视频渲染器、更新显卡驱动、调整色彩格式、关闭叠加层特效及修复视频文件可解决PotPlayer播放卡顿问题。 如果您在使用PotPlayer播放视频时遇到画面卡顿、播放不流畅的情况,这可能是由于渲染器设置不当、硬件加速冲突或系统资源占用过高导致的。以下是解决此问题的具体步骤: 本文运行环境:Del…

    2026年9月21日
    100
  • 利用蝴蝶号搭建多账号无人直播系统的完整方案

    利用蝴蝶号搭建多账号无人直播系统的完整方案利用蝴蝶号搭建多账号无人直播系统的完整方案利用蝴蝶号搭建多账号无人直播系统的完整方案利用蝴蝶号搭建多账号无人直播系统的完整方案

    搭建多账号无人直播系统并非一键操作,而是通过“蝴蝶号”实现自动化流程。首先,“蝴蝶号”负责多账号的生命周期管理,包括登录、状态维护、ip代理分配和设备指纹模拟;其次,内容调度系统决定直播内容及播放时间,可为预录视频或动态生成流;再次,推流引擎将内容实时推送至平台,推荐使用ffmpeg结合python…

    2026年9月21日 用户投稿
    100

发表回复

登录后才能评论
关注微信