Agent开发实战-ReAct 工作流
AI Agent 的灵魂 —— ReAct 工作流全解析一、 引言为什么我们需要 ReAct痛点引入传统的大模型LLM就像在做“闭卷考试”遇到不懂的只能靠幻觉瞎编或者像传统的 RAG只能被动接受人类喂给它的资料。概念提出ReAct (Reasoning Acting)范式打破了这个僵局。它让大模型长出了“手脚”不仅能思考Reason还能主动决定去调用工具Act真正从一个“聊天机器人”进化成了“智能体Agent”。核心比喻ReAct 就像是给大模型安排了一场“开卷考试”。大模型是考生Python 代码是监考老师。遇到不会的题考生大模型会在草稿纸上写“我要查某某书”老师Python看到后把书找来翻到那一页递给考生考生看完后再写出最终答案。二、 ReAct 的“三步走”魔法T-A-O 循环ReAct 的底层逻辑非常优雅它是一个不断循环的状态机由三个核心基石组成Thought思考作用大模型的“内心独白”。它分析当前的用户目标评估自己已有的知识并决定下一步该干什么。例子Thought: 用户问紫微星在命宫代表什么这属于专业命理知识我不确定需要调用搜索引擎工具。Action行动指令作用大模型向外部系统Python 代码下达的指令通常包含“工具名称”和“JSON格式的参数”。例子Action: search_ziwei\nAction Input: {query: 紫微星在命宫}Observation观察反馈作用外部系统如你的 RAG 检索器、计算器、天气 API执行完任务后将结果以文本形式返回给大模型。例子Observation: 检索到以下资料紫微星入命宫主人气质高雅有领导欲...三、 完整工作流程图解以一次查询为例[第 0 步] 设定规则 (System Prompt)我们通过极其严格的 Prompt 告诉模型“你拥有工具 A 和 B。你必须按照 Thought - Action - Observation 的格式输出。”[第 1 步] 用户提问用户“廉贞化忌会怎样”[第 2 步] 模型初次生成 (Thought Action)模型输出思考过程并下达 JSON 格式的查询指令。此时神奇的事情发生了——模型停止了生成。[第 3 步] 代码拦截与执行 (Observation)Python 代码监听到了Action拦截了模型的输出。Python 在后台运行 RAG 数据库查询拿到资料。[第 4 步] 结果回传 (Second Thought)Python 把拿到的资料拼接成Observation: [资料内容]重新发给大模型。[第 5 步] 输出结论 (Final Answer)大模型结合拿到的Observation进行二次思考Thought: 我已经拿到充足资料可以回答了。然后输出最终的Final Answer。四、 藏在代码深处的工程秘密硬核加分项怎么让大模型“停下来”Stop Words 的妙用很多人以为是 Python 在实时打断大模型其实不然。核心技巧是在调用 LLM 的 API 时传入stop[Observation:]参数。这样大模型一旦企图自己编造观察结果底层推理引擎就会自动切断生成乖乖把控制权交还给 Python。如何防止系统崩溃JSON 幻觉与自愈机制大模型输出 Action Input 时经常会少写一个括号或多写一个逗号导致json.loads()报错。工业级的做法不是直接报错退出而是捕获异常try...except把错误日志包装成Observation: JSON格式错误...扔回给大模型让大模型自己意识到语法错误并重新生成。防止死循环熔断机制如果工具一直查不到数据大模型可能会陷入“思考-查询-查不到-再思考-再查询”的死循环。必须在外层加一个for step in range(MAX_ITER)的循环器达到最大次数强制结束保护系统资源。以下是关键代码importreimportjsondefrun_react_agent_with_healing(question,llm_client,rag_system,max_iterations5): 带有异常捕获与自愈机制的工业级 ReAct Agent 循环 print(f 用户提问:{question}\n)# 1. 初始 System Prompt 与用户问题messages[{role:system,content:REACT_SYSTEM_PROMPT},# 假设已定义工具列表{role:user,content:question}]# 2. 状态机主循环 (防止大模型无限发散的熔断机制)forstepinrange(max_iterations):print(f--- [ Agent 思考轮次:{step1}/{max_iterations}] ---)# 第一阶段思考与动作下发 # 核心技巧 1传入 stop 参数一旦模型企图伪造观察结果立刻硬中断responsellm_client.chat.completions.create(modelqwen2.5-7b,messagesmessages,temperature0.1,# 降低温度保证 JSON 格式输出的稳定性stop[Observation:,观察结果:]).choices[0].message.contentprint(f 模型输出:\n{response})messages.append({role:assistant,content:response})# 解析模型意图 (利用正则抠出 Action 和 JSON)action_matchre.search(rAction:\s*(.*?)\n,response)actionaction_match.group(1).strip()ifaction_matchelseNone# 如果大模型决定回答直接退出循环ifactionNoneorFinal Answerinresponse:print(\n✅ 任务圆满结束)returnresponse# 第二阶段拦截、执行与自愈 # 提取 Action Input 中的 JSON 字符串input_matchre.search(rAction Input:\s*(\{.*?\}),response,re.DOTALL)action_input_strinput_match.group(1).strip()ifinput_matchelse{}ifsearch_ziweiinaction:try:# 尝试将字符串解析为 JSON 对象argsjson.loads(action_input_str)queryargs.get(query,question)print(f️ [工具触发] 正在检索知识库:{query})# 调用 RAG 获取真实数据_,docsrag_system.query(query)observation\n.join([d.page_contentfordindocs])print(f️ [工具返回] 成功获取{len(docs)}条相关资料。\n)# 将真实的观察结果喂回给大模型messages.append({role:user,content:fObservation:{observation}\n请根据以上资料继续思考如果资料足够请给出 Final Answer。})exceptjson.JSONDecodeErrorase:# 核心技巧 2JSON 幻觉自愈机制 (Self-Healing)print(f⚠️ [系统警告] 模型输出了损坏的 JSON正在触发自愈机制...)# 将详细的 Python 报错信息包装成提示词强迫模型自我反思并重写error_feedback(fObservation: Action Input 解析失败fPython 报错日志{str(e)}。f请检查你的 JSON 语法是否遗漏了逗号或双引号修正后重新输出 Thought 和 Action。)messages.append({role:user,content:error_feedback})continue# 直接进入下一轮循环让大模型重新生成exceptExceptionase:print(f❌ [系统异常] 未知错误:{e})messages.append({role:user,content:Observation: 工具调用发生内部错误请直接根据你的常识回答。})else:# 核心技巧 3防范“幻觉工具”print(f⚠️ [系统警告] 模型调用了不存在的工具 [{action}])messages.append({role:user,content:fObservation: 工具 {action} 不存在你只能使用 search_ziwei或者输出 Action: None。})continue# 如果走完了 for 循环还没得到答案触发熔断return抱歉由于问题过于复杂Agent 思考超时已强行熔断。五、 结语从手写 ReAct 到工业化编排纯手写 ReAct 循环能让我们深刻理解 Agent 的底层原理。但在真实的复杂业务中比如引入人工审批、多 Agent 协作手写的while循环极其难以维护。这就引出了目前工业界的最优解——将线性循环升级为图结构的状态机如 LangGraph。