ReAct模式详解:当你的AI开始“边想边干”

张开发
2026/6/1 10:04:42 15 分钟阅读
ReAct模式详解:当你的AI开始“边想边干”
昨天深夜调试一个智能客服场景遇到个典型问题用户问“上个月订单金额最高的客户是谁”AI直接回了一句“根据系统记录是张三”。但实际数据库里根本没有“张三”这个客户。查看日志才发现AI根本没去查数据库纯粹是根据训练数据里的常见人名瞎猜的。这种“想当然”的推理在真实业务场景里就是灾难。一、ReAct到底解决了什么痛点传统AI回答问题的路径很直接接收问题 → 内部推理 → 输出答案。问题在于这个“内部推理”完全依赖模型已有的知识遇到需要实时数据、需要操作外部系统、需要分步骤计算的情况模型要么胡编乱造要么直接摆烂。ReActReasoning Acting模式的核心思想很简单让AI学会“先动脑子再动手动手之后继续动脑子”。具体来说就是让模型在思考过程中能够主动调用工具、查询数据、执行操作然后基于执行结果继续思考直到得出可靠结论。二、拆解ReAct的工作循环看个实际代码片段就明白了。下面是个简化版的ReAct循环实现classReActAgent:defrun(self,query:str):# 初始化思考上下文contextf用户问题{query}\n# 最多循环5轮防止死循环forstepinrange(5):# 第一步让模型思考当前该做什么promptf{context}请分析当前情况你需要 1. 思考下一步应该做什么推理 2. 如果需要外部信息说明要调用什么工具 格式必须严格按 Thought: 你的思考过程 Action: tool_name[输入参数] 或 FINAL_ANSWER responsellm(prompt)# 解析模型的输出thought,actionself._parse_response(response)contextf\nStep{step}Thought:{thought}ifFINAL_ANSWERinaction:# 模型认为可以给出最终答案了returnself._extract_answer(action)# 执行动作tool_name,paramsself._parse_action(action)resultself.tools[tool_name].execute(params)# 把执行结果加入上下文contextf\nAction:{action}\nObservation:{result}# 这里有个关键点观察结果要简洁但完整# 太长会浪费token太短会丢失信息iflen(result)500:resultresult[:500]...截断# 循环结束还没答案return经过多轮尝试仍无法确定答案几个关键设计点强制格式输出必须要求模型按“Thought: … Action: …”格式输出。早期版本没做强制模型经常自由发挥解析起来简直噩梦。观察结果管理工具返回的结果要适当截断。有次调试时数据库返回了2万字的JSON直接塞进上下文后面token爆炸了。循环退出机制必须设置最大步数。实测中遇到过模型陷入“查数据→发现不完整→再查其他数据”的死循环。三、真实场景的坑与解决方案坑1模型“想太多”就是不行动在测试阶段经常看到这样的输出Thought: 用户需要查询订单数据我需要先确定时间范围。“上个月”可能指自然月也可能指最近30天我需要先确认具体定义... 思考了300字还在纠结概念解决方案在prompt里明确约束请保持思考简洁聚焦于确定下一步具体行动。如果信息不足优先通过工具获取实际数据而非猜测。坑2工具调用参数格式错误模型可能输出Action: query_database[SELECT * FROM orders WHERE time last_month]但你的工具实际只接受JSON格式参数。解决方案两个方法在示例中明确展示正确格式或者更稳妥的在解析层做格式转换defsafe_parse_params(param_str):# 先尝试解析为JSONtry:returnjson.loads(param_str)except:# 如果不是JSON按简单字符串处理return{query:param_str}坑3模型过早给出最终答案有时模型刚查了一次数据就自信满满地输出FINAL_ANSWER实际上数据并不完整。解决方案在评估阶段加入验证机制defshould_continue(answer,confidence):ifconfidence0.8:returnTrueif不确定inansweror可能inanswer:returnTrue# 还可以检查答案是否包含具体数据而不是模糊描述returnFalse四、进阶让ReAct更稳定技巧1给模型“记忆摘要”多轮交互后上下文会很长可以每3轮做一次摘要ifstep%30:summary_promptf请用100字总结当前已获取的信息和待解决的问题\n{context}contextllm(summary_prompt)\n以上为摘要技巧2工具描述要具体不要只写“查询数据库”要写清楚工具名query_order_data 描述查询订单表支持参数customer_id客户ID、start_date开始日期格式YYYY-MM-DD、max_results最大返回条数默认10 示例query_order_data[{start_date: 2024-01-01, max_results: 5}]技巧3设置推理超时有些问题确实需要多步推理但生产环境不能无限等待importsignalclassTimeoutException(Exception):passdefrun_with_timeout(agent,query,timeout30):defhandler(signum,frame):raiseTimeoutException()signal.signal(signal.SIGALRM,handler)signal.alarm(timeout)try:returnagent.run(query)finally:signal.alarm(0)五、个人经验谈ReAct模式不是银弹它最适合的是那些需要混合常识推理和实时数据查询的场景。纯计算类问题用代码工具更直接纯知识类问题用RAG可能更合适。实际部署时我建议从简单工具集开始先实现2-3个核心工具确保模型能正确调用再慢慢扩展。一开始就提供20个工具模型反而会困惑。日志要详细记录保存完整的Thought-Action-Observation链条。出问题时这是最好的调试依据。我们团队现在要求所有生产请求必须保存至少7天的完整推理链。设置人工接管点对于关键业务比如涉及金额、法律条款当模型confidence低于阈值时自动转人工。这个设计避免了很多麻烦。定期评估工具使用频率有些工具模型从来不用可能是描述不清楚也可能是根本不需要。每季度清理一次工具集。最后说个实际数据在我们客服系统上线ReAct后对于需要查数据的复杂问题准确率从38%提升到76%但平均响应时间从1.2秒增加到3.5秒。这就是典型的trade-off用时间换准确率。业务是否接受需要提前沟通清楚。ReAct让AI从“答题机器”变成了“会查资料的分析员”这个转变很微小但在实际业务中就是“不能用”和“勉强能用”的区别。下次遇到模型胡说八道时不妨想想是不是该让它先动手查查数据再说话

更多文章