ReAct范式实战:让Agent学会边想边做
说实话我第一次看到ReAct这个论文标题的时候内心是拒绝的。又是个学术界造的概念吧我当时想。直到我真的在一个实际项目里试了一下才发现——这玩意儿真的不是花架子。它是Agent从傻傻地问一句答一句到能思考、能行动、能纠错的关键一步。这篇文章不讲虚的直接聊ReAct怎么落地。问题单纯的Prompt Tool Call为什么不够你可能会说“给LLM配几个工具的Function Calling不就行了吗”行但不完全行。举个我踩过的坑。我让一个Agent帮忙分析用户反馈数据。它需要先查数据库拿到最近一周的反馈然后做个情感分析最后输出一个报表。如果只用Function CallingLLM会尝试一步到位——“好的我来查数据、分析情感、生成报表”。但问题是它不知道自己的查询结果质量如何也不知道情感分析结果出来后有没有异常需要二次验证。这就好比一个程序员写完代码不测试就直接上线。能跑是运气崩了是常态。核心思想思考 → 行动 → 观察 → 再思考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理论说完了聊点干的。我试过两种实现方式各有千秋。方式一手动管理循环这是最直接的方式。你手动维护一个思考-行动-观察的循环队列。核心代码框架大概是这样defreact_loop(user_input,max_steps10):messages[{role:system,content:REACT_SYSTEM_PROMPT},{role:user,content:user_input}]forstepinrange(max_steps):responsellm.call(messages)ifresponse.has_final_answer:returnresponse.final_answer actionparse_action(response.text)observationexecute_tool(action.name,action.args)messages.append({role:assistant,content:response.text})messages.append({role:tool,content:observation})returnMax 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的图结构fromlanggraph.graphimportStateGraph,ENDfromlanggraph.prebuiltimportToolExecutor# 定义Agent节点defagent_node(state):messagesstate[messages]responsellm_with_tools.invoke(messages)return{messages:[response]}# 定义工具节点deftool_node(state):messagesstate[messages]last_messagemessages[-1]tool_callslast_message.tool_calls resultstool_executor.batch(tool_calls)return{messages:results}# 构建图graphStateGraph(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逻辑手撸可能更灵活。踩坑记录这东西看着简单但真正用起来有几个坑。坑1LLM喜欢跳过思考我遇到过一个奇怪的问题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做更深层次的规划。感兴趣的可以关注一波。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2567344.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!