ReAct范式实战:让Agent学会边想边做

说实话,我第一次看到ReAct这个论文标题的时候,内心是拒绝的。

"又是个学术界造的概念吧?"我当时想。

直到我真的在一个实际项目里试了一下,才发现------这玩意儿真的不是花架子。它是Agent从"傻傻地问一句答一句"到"能思考、能行动、能纠错"的关键一步。

这篇文章不讲虚的,直接聊ReAct怎么落地。

问题:单纯的Prompt + Tool Call为什么不够?

你可能会说:"给LLM配几个工具的Function Calling不就行了吗?"

行,但不完全行。

举个我踩过的坑。我让一个Agent帮忙分析用户反馈数据。它需要先查数据库拿到最近一周的反馈,然后做个情感分析,最后输出一个报表。

如果只用Function Calling,LLM会尝试一步到位------"好的,我来查数据、分析情感、生成报表"。但问题是:它不知道自己的查询结果质量如何,也不知道情感分析结果出来后有没有异常需要二次验证。

这就好比一个程序员写完代码不测试就直接上线。能跑是运气,崩了是常态。

核心思想:思考 → 行动 → 观察 → 再思考

ReAct的全称是 Reasoning + Acting。核心就四个字:边想边做

传统的LLM调用流程是:

复制代码
输入 → LLM → 输出

ReAct的流程是:

复制代码
输入 → LLM思考(我要做什么)→ 行动(调用工具)→ 观察(工具返回的结果)→ 再思考(结果是否合理?下一步做什么?)→ 再行动 → ... → 最终输出

这个循环让Agent有了"反馈回路"。每一步的结果都会影响下一步的决策。

一个完整的ReAct循环长什么样

我看过最清晰的解释,是论文里的一个例子。问Agent:"在加州哪里可以买到Xbox?"

  • 思考: 用户想知道Xbox的购买地点。我需要查一下加州的零售信息。
  • 行动: search("加州 Xbox 购买地点")
  • 观察: 搜索结果返回了GameStop、Best Buy、Target和微软官网的链接
  • 思考: 搜索结果包含了实体店和线上渠道。用户问的是"买",可能包括两者。让我进一步搜一下有没有具体的优惠信息。
  • 行动: search("Xbox Series X 加州的库存情况")
  • 观察: 有些店有现货,有些显示缺货
  • 思考: 我可以整理一下哪些店有现货,以及购买渠道。
  • 最终回答: 在加州,你可以去GameStop、Best Buy等实体店购买,或者上微软官网下单。目前GameStop和Best Buy部分店面有现货...

看到了吗?每一步都是"我想一下 → 我做一下 → 我看结果 → 我再想一下"。

工程实现:怎么落地ReAct?

理论说完了,聊点干的。我试过两种实现方式,各有千秋。

方式一:手动管理循环

这是最直接的方式。你手动维护一个"思考-行动-观察"的循环队列。

核心代码框架大概是这样:

python 复制代码
def react_loop(user_input, max_steps=10):
    messages = [
        {"role": "system", "content": REACT_SYSTEM_PROMPT},
        {"role": "user", "content": user_input}
    ]
    
    for step in range(max_steps):
        response = llm.call(messages)
        
        if response.has_final_answer:
            return response.final_answer
        
        action = parse_action(response.text)
        observation = execute_tool(action.name, action.args)
        
        messages.append({"role": "assistant", "content": response.text})
        messages.append({"role": "tool", "content": observation})
    
    return "Max steps reached"

关键点在于system prompt要写得够好。论文里推荐在System Prompt中给出明确的格式要求,让LLM知道每一步应该输出什么。

我用的System Prompt模板是这样的:

复制代码
你是一个智能Agent。你需要通过"思考→行动→观察"的循环来完成任务。

每轮你需要输出:
1. 思考(Thought):分析当前状态,决定下一步做什么
2. 行动(Action):调用一个工具函数
3. 观察(Observation):工具返回的结果(由系统填充)

当你认为任务已经完成时,输出最终答案(Final Answer)。

可用工具列表:
- search(query): 搜索网络信息
- calculate(expression): 执行数学计算
- ...

说实话,这种方式简单直接,但有一个问题------Token消耗大。每一步的思考和行动都会产生大量的Token输出。如果你的task需要5-6步,光是ReAct循环本身的Token消耗就够你心疼的。

方式二:用Agent框架

偷懒的方式是直接用现成的Agent框架。LangChain、LangGraph、CrewAI、AutoGen这些框架都内置了ReAct支持。

以LangGraph为例,它把ReAct封装成了一个Node + Edge的图结构:

python 复制代码
from langgraph.graph import StateGraph, END
from langgraph.prebuilt import ToolExecutor

# 定义Agent节点
def agent_node(state):
    messages = state["messages"]
    response = llm_with_tools.invoke(messages)
    return {"messages": [response]}

# 定义工具节点
def tool_node(state):
    messages = state["messages"]
    last_message = messages[-1]
    tool_calls = last_message.tool_calls
    results = tool_executor.batch(tool_calls)
    return {"messages": results}

# 构建图
graph = StateGraph(AgentState)
graph.add_node("agent", agent_node)
graph.add_node("tools", tool_node)
graph.add_conditional_edges("agent", should_continue, {"continue": "tools", "end": END})
graph.add_edge("tools", "agent")

框架的好处是帮你处理了循环逻辑、上下文管理、错误重试这些脏活。但代价是------你失去了对每一步的精细控制。如果你的场景需要非常定制化的ReAct逻辑,手撸可能更灵活。

踩坑记录

这东西看着简单,但真正用起来有几个坑。

坑1:LLM喜欢"跳过思考"

我遇到过一个奇怪的问题:LLM在某个轮次突然不输出了Thinking,直接给出了Final Answer。

排查后发现,是模型觉得"结果已经够好了"。但这往往是因为它忽略了某些细节。

解决办法:在System Prompt里加上"除非任务明确完成,否则每一步都必须包含思考步骤"的约束。

坑2:循环不终止

有些问题没有明确的"完成"条件,Agent会在工具调用和观察之间来回跳跃,永远不停。

解决方案:设置最大步数限制(我一般设5-8步),超时后返回当前最好的结果。

坑3:观察结果太长

工具返回的数据可能非常长(比如一次搜索返回10条结果),这些内容全部塞进上下文,Token爆炸。

方案:对观察结果进行摘要。只保留关键信息,丢掉冗余内容。这招能省至少30%的Token。

什么时候用ReAct?什么时候不用?

我个人觉得,ReAct最适合的场景是:

  • 多步骤推理任务:需要多次查询/计算才能得出结论的
  • 需要纠错的任务:第一次行动的结果可能不准确,需要二次验证
  • 决策路径不确定的任务:Agent需要根据中间结果动态调整策略

不适合的场景:

  • 简单的QA:用户问"今天天气怎么样?",直接查天气API返回结果就行,不需要思考循环
  • 高实时性场景:ReAct的每一次循环都需要一次LLM调用,延迟不可控
  • Token敏感场景:ReAct的Token消耗比普通问答高一个数量级

写在最后

ReAct不是什么黑魔法。它的核心思想很简单:让LLM的推理过程和实际行动交替进行,互相验证。

这个思路不仅在Agent领域有用,在日常编码中也有启发------别写一段超长的代码再debug,而是一小段一小段地写,每写完一段就跑一下看看结果。高效多了。

如果你也想在项目中引入Agent能力,建议从ReAct开始。它是最基础、最可控的Agent范式,也是理解和实现更复杂Agent架构(比如Tree-of-Thought、Multi-Agent)的基石。

下一篇我打算聊聊Tree-of-Thought,让Agent做更深层次的规划。感兴趣的可以关注一波。

相关推荐
朝阳391 小时前
react【实战】首页 -- 白天/黑夜主题切换(含组件封装)
前端·react.js·前端框架
吴声子夜歌1 小时前
Vue3——UI组件库Element Plus(二)
javascript·vue.js·ui·elementplus
卷Java1 小时前
Multi-Agent系统实战:如何让多个Agent握手协作
大模型·llm·multi-agent·agent协作
zhensherlock2 小时前
Protocol Launcher 系列:Beorg 高效任务管理的协议支持
前端·javascript·typescript·node.js·自动化·github·js
ppandss12 小时前
JavaWeb从0到1-DAY3.1- Vue(ii)
前端·javascript·vue.js
M ? A2 小时前
Vue 转 React | VuReact编译工具快速入门
前端·javascript·vue.js·后端·react.js·面试·vureact
qq_427539832 小时前
iframe 嵌入预览 PDF ,禁用右键菜单、打印下载按钮不展示
前端·javascript·vue.js·pdf
ZC跨境爬虫2 小时前
跟着 MDN 学 HTML day_3:(表单CSS美化实战与盒子模型三大核心属性详解)
前端·javascript·css·html