十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

大模型Agent核心范式ReAct:从原理到Python实战

大模型Agent核心范式ReAct:从原理到Python实战 之前在业务里做 AI Agent 落地时被问得最多的一个问题不是“大模型选哪个”而是“大模型怎么才能真的去干活”。很多资料把 Agent 讲得很玄一会儿扯规划一会儿扯记忆一会儿扯工具调用初学者很容易被绕晕。实际上Agent 最核心的一种工作范式就是本文要讲的 ReAct。这篇文章不堆概念先花两分钟把 ReAct 的思路讲透再给一个可以本地运行的最小 Python 实现最后聊聊生产落地时容易踩的坑。如果你刚接触大模型应用开发或者想在现有项目中引入 Agent这篇内容可以直接作为入门起点。1. 什么是 ReAct让大模型既会思考又会行动1.1 从一个需求说起为什么纯问答不够用在理解 ReAct 之前我们先看一个最简单的需求用户问“北京现在天气怎么样”。如果你直接把这个问题抛给一个纯文本大模型它通常会回答“我无法获取实时天气数据请打开天气应用查询”。原因很简单大模型的训练数据有截止时间它不会实时访问外部世界。再换一个需求“帮我计算一下项目里三个接口的平均响应时间并把结果写到 report.md 里”。这个问题更难因为模型不仅要理解需求还要读取日志文件、做数学计算、调用文件写入接口。对于传统的 Prompt 问答模式模型只能输出一段建议而不能真正操作系统。这些问题暴露了同一个短板大模型擅长“思考”但不擅长“行动”。它缺少一个闭环机制让生成的内容能够触发真实操作再把操作结果拿回来继续推理。ReAct 正是为了解决这个问题而提出的。1.2 ReAct 的核心思想推理和行动交替进行ReAct 这个词来自论文 《ReAct: Synergizing Reasoning and Acting in Language Models》的缩写由 Reason推理和 Act行动组合而成。论文的核心思想并不复杂让大模型在回答问题的过程中交替生成“思考过程”和“执行动作”。具体来说ReAct 的每一轮循环包含三步Thought模型用自然语言描述当前子问题是什么下一步打算怎么做。Action模型从预设的工具列表中选择一个动作并给出对应的输入参数。Observation程序执行这个动作把结果以文本形式返回给模型。整个流程可以表示为Thought: 我需要先查询北京的实时天气。 Action: search_weather(北京) Observation: 晴气温 25℃东南风 3 级模型看到 Observation 之后会根据新信息继续生成下一轮 Thought直到收集到足够的信息最终输出一个 Final Answer。1.3 ReAct、CoT、Function Calling 有什么区别很多读者容易把 ReAct 和另外两个概念搞混这里做一个简单对比。方法是否思考是否行动典型场景普通 Prompt否否简单问答、文本改写CoT思维链是否数学推理、逻辑题ReAct是是需要调用外部工具的多步任务Function Calling部分是工具调用但缺少显式推理轨迹CoT 的思路是引导模型先输出推理步骤再给出答案。但它不会连接外部系统模型如果不知道某个事实很可能直接“一本正经地胡说八道”。Function Calling 解决了“模型可以调用函数”的问题但函数调用的流程通常由框架控制模型本身没有显式的“思考下一步怎么做”的过程。ReAct 的独特价值在于它把“思考”和“行动”统一在一个循环里让模型可以根据观察结果动态调整计划。这种设计更接近人类解决问题的过程也更容易调试和追踪。1.4 注意ReAct 不是前端框架 React.js搜索相关资料时很多人会搜到 React.js。这里需要澄清一下两者没有任何关系。ReAct大模型 Agent 的一种提示词组织方式属于 AI 应用开发领域。React.js一个用于构建用户界面的 JavaScript 库属于前端开发领域。如果后端同学在讨论 Agent 时说 ReAct大概率是指推理与行动循环如果前端同学在讨论 React通常是指组件库和虚拟 DOM。本文讨论的是前者。2. 两分钟理解 ReAct 的运作流程2.1 一个贴近业务的例子让 Agent 查天气并给建议为了便于理解我们模拟一个完整的 ReAct 调用过程。假设系统里有两个工具search_weather(city)查询城市天气search_poi(city, category)查询某城市的推荐游玩地点用户输入“北京天气怎么样适不适合户外跑步”模型生成的完整轨迹可能如下Thought: 用户想知道北京天气是否适合户外跑步我需要先获取北京的实时天气。 Action: search_weather(北京) Observation: 北京今天多云气温 32℃空气质量良微风。 Thought: 气温 32℃ 偏高紫外线可能较强如果户外跑步需要注意补水和防晒。 Action: search_poi(北京, 公园) Observation: 推荐奥森公园、朝阳公园、颐和园适合晨跑或夜跑。 Thought: 综合天气和公园信息我可以给出一个相对完整的建议。 Action: finish(北京今天适合户外跑步但 32℃ 气温偏高建议选择清晨或傍晚注意补水和防晒。奥森公园是推荐路线。)在这个示例中Agent 不只是简单返回一句话而是经历了“查天气 → 评估适合度 → 查公园 → 给建议”的完整过程。每一步都有依据而不是凭空生成。2.2 两分钟速记口诀如果你想快速记住 ReAct可以用下面这个口诀思考行动看结果再思考。具体来说就是遇到一个复杂问题先不要急着回答。把问题拆成子任务决定用哪个工具。调用工具拿到真实结果。根据结果更新认知继续下一步。信息足够后输出最终答案。这套流程可以用在很多场景中查数据库、调 API、读文件、跑脚本、检索文档等等。只要外部工具能够被封装成一个“输入文本、输出文本”的函数ReAct 就能使用它。3. 搭建一个最小 ReAct AgentPython 实战这一节我们实现一个可以运行的最小 ReAct Agent。整体代码量不大重点在于理解“模型输出解析”和“循环控制”两个环节。3.1 环境准备本文示例使用以下环境操作系统Windows / macOS / Linux 均可Python 版本3.9 及以上LLM 接口兼容 OpenAI 协议的 SDK需要提前安装依赖库openai、python-dotenv可选版本需要根据你的项目实际情况调整。如果你的网络环境或模型服务不是标准 OpenAI 接口请把base_url和api_key替换成你自己的网关地址。创建项目目录mkdir react-demo cd react-demo初始化虚拟环境并安装依赖python -m venv venv source venv/bin/activate # Windows 请使用 venv\Scripts\activate pip install openai python-dotenv项目结构如下react-demo/ ├── react_agent.py ├── .env └── requirements.txtrequirements.txt内容openai1.0.0 python-dotenv1.0.0.env文件内容OPENAI_API_KEY你的密钥 LLM_MODELgpt-4o-mini注意.env文件不要提交到 Git 仓库建议加入.gitignore。3.2 定义工具集为了让代码在没有外部服务的情况下也能演示我们实现两个工具get_current_time返回当前系统时间search_weather返回一个模拟天气结果这里的关键设计是工具函数统一接收字符串参数返回字符串结果。这样方便模型理解和调用。# 文件路径react_agent.py import datetime import json import os import random TOOLS_DESC 你可以使用以下工具 1. get_current_time - 功能获取当前系统时间 - 参数无 - 示例get_current_time() 2. search_weather(city) - 功能查询指定城市的天气 - 参数city城市名称例如 北京 - 示例search_weather(北京) .strip()然后实现工具执行函数def get_current_time(): now datetime.datetime.now() return f当前时间是 {now.strftime(%Y-%m-%d %H:%M:%S)} def search_weather(city: str): # 演示用函数实际项目中请接入真实天气服务 weather_list [晴, 多云, 小雨, 阴] temp random.randint(18, 33) weather random.choice(weather_list) return f{city} 天气{weather}气温 {temp}℃湿度 60% def execute_tool(action: str, action_input: str): if action get_current_time: return get_current_time() elif action search_weather: return search_weather(action_input) else: return f未知工具: {action}这里有一个重点工具输入参数如何从字符串中提取。实际项目中我们通常让模型输出 JSON然后用json.loads解析。为了降低初学者的理解成本上面的代码里直接使用了函数参数后续我们会给出更规范的做法。3.3 定义 LLM 调用函数下面封装一个call_llm函数from openai import OpenAI client OpenAI( api_keyos.getenv(OPENAI_API_KEY), ) def call_llm(messages): response client.chat.completions.create( modelos.getenv(LLM_MODEL, gpt-4o-mini), messagesmessages, temperature0, ) return response.choices[0].message.content如果你使用的是其他兼容 OpenAI 协议的模型服务比如本地部署的 vLLM、Ollama 网关或者国内云厂商的 OpenAI 兼容接口可以这样修改client OpenAI( api_key你的密钥, base_urlhttps://你的网关地址/v1, )这里需要提醒你的是不同版本 SDK 的参数可能存在细微差异具体以你的openai库文档为准。3.4 完整 ReAct 主循环ReAct 主循环是整个 Agent 的核心。它要做的事情包括将用户问题、系统提示、历史轨迹拼成 messages。让模型生成文本。判断模型输出是否包含 Final Answer。如果包含则结束循环。如果不包含则解析 Action 和 Action Input执行工具把 Observation 重新拼回对话。设置最大循环次数防止死循环。完整代码如下# 文件路径react_agent.py import re SYSTEM_PROMPT f 你是一个智能助手需要逐步完成任务。 你只能使用以下工具 {TOOLS_DESC} 请严格按照以下格式输出 Thought: 你的思考过程 Action: 工具名称 Action Input: 工具参数 当信息足够时使用下面的格式结束 Thought: 我现在可以回答问题了 Final Answer: 最终答案 MAX_STEPS 5 def react_agent(question: str): messages [ {role: system, content: SYSTEM_PROMPT}, {role: user, content: f问题{question}}, ] step 0 while step MAX_STEPS: step 1 print(f\n Step {step} ) result call_llm(messages) print(result) messages.append({role: assistant, content: result}) # 判断是否输出最终答案 if Final Answer: in result: final_answer result.split(Final Answer:)[-1].strip() print(f\n最终答案{final_answer}) return final_answer # 解析 Action 与 Action Input action_match re.search(rAction:\s*(.), result) input_match re.search(rAction Input:\s*(.), result) if not action_match or not input_match: error_msg 格式错误请用 Action 和 Action Input 指定工具调用。 print(error_msg) messages.append({role: user, content: error_msg}) continue action action_match.group(1).strip() action_input input_match.group(1).strip().strip() print(f执行工具{action}({action_input})) observation execute_tool(action, action_input) print(f观察结果{observation}) messages.append({role: user, content: fObservation: {observation}}) print(\n已达到最大步数停止循环。) return None if __name__ __main__: question 现在几点了北京天气怎么样 answer react_agent(question) if answer: print(回答完成。)3.5 运行与验证在终端运行python react_agent.py这里需要注意如果你使用的是.env文件保存密钥需要提前加载。可以在文件顶部加入from dotenv import load_dotenv load_dotenv()运行后模型可能会输出如下类似的轨迹 Step 1 Thought: 用户想知道当前时间和北京天气我首先需要获取当前时间。 Action: get_current_time Action Input: 执行工具get_current_time() 观察结果当前时间是 2025-06-01 14:30:22 Step 2 Thought: 当前时间已经获取现在我需要查询北京天气。 Action: search_weather Action Input: 北京 执行工具search_weather(北京) 观察结果北京 天气多云气温 26℃湿度 60% Step 3 Thought: 我已经获取了当前时间和北京天气现在可以回答用户。 Final Answer: 现在是 2025-06-01 14:30:22北京今天多云气温 26℃。3.6 结果说明从上面的运行结果可以看到ReAct 的价值在于模型没有直接编造时间而是先调用get_current_time获取真实时间。模型没有直接编造天气而是调用了search_weather。每一步都有依据每一步都可见。这就是 Agent 和大模型普通问答的本质区别Agent 通过工具连接了现实世界。4. 从玩具到生产ReAct 的真实工程实践上面的示例能帮助你理解原理但离生产还有一定距离。这一节我们讨论几个关键改造点。4.1 工具注册与参数解析规范化在真实项目中工具数量会很多不能再靠 if-else 来分发。推荐的做法是维护一个工具注册表TOOL_REGISTRY { get_current_time: get_current_time, search_weather: search_weather, } def execute_tool(action: str, action_input: str): if action not in TOOL_REGISTRY: return f错误未知工具 {action} tool_func TOOL_REGISTRY[action] try: return tool_func(action_input) except Exception as e: return f工具执行异常{e}同时为了让模型更容易输出结构化参数可以让模型直接生成 JSON而不是自由文本。例如Action: search_weather Action Input: {city: 北京}解析时就更加可靠action_input json.loads(input_str) city action_input[city]4.2 增加最大步数和熔断机制生产环境中最容易出现的问题就是 Agent 陷入死循环。比如模型反复调用同一个工具或者在同一问题上绕圈。为了防止资源浪费至少要做三件事设置最大步数例如 5 步或 10 步。对同一个工具连续调用次数做限制。当观察结果没有带来新信息时强制终止。在代码中实现一个简单的重复检测last_observation None for step in range(MAX_STEPS): observation execute_tool(action, action_input) if observation last_observation: break last_observation observation4.3 多轮会话与记忆管理ReAct 示例中只有一个用户问题。真实业务中用户往往会连续提问例如用户帮我查一下上海的天气。 用户那苏州呢如果每次都是全新会话Agent 就会丢失“上一条在查天气”的上下文。处理方法通常有两种把历史对话完整拼入 messages让模型拥有短期记忆。使用向量数据库做长期记忆把关键结论存入知识库。生产项目中建议先用第一种简单直接。当上下文长度超过模型限制时再考虑摘要压缩或向量检索。5. 常见问题与排查思路ReAct 在开发过程中会遇到很多细节问题这里列出高频问题并给出排查方向。问题现象常见原因解决思路模型一直输出 Final Answer不调用工具系统提示词对工具描述不够清晰或者模型能力不够强化工具描述要求“先调用工具再回答”模型输出 Action 但没有 Action Input提示词示例不足在提示词中增加更完整的调用示例工具调用进入死循环缺少步数限制或工具结果没有更新增加最大步数检测重复观察解析 Action 时失败模型输出格式不固定换用 JSON 输出模式或使用更强模型API 调用超时模型服务响应慢增加超时时间添加重试机制工具执行报错被模型掩盖异常信息没有反馈给模型把异常信息写入 Observation让模型调整方案对结果不信任出现幻觉缺少来源引用要求模型在 Final Answer 中注明工具来源6. 最佳实践与工程建议6.1 工具描述要像“接口文档”一样清晰模型只能通过文本描述来理解工具。好的工具描述应该包含功能的边界能做什么不能做什么。参数的格式类型、取值范围、示例。返回结果的含义字段说明。不要写“这个工具很强大”这种抽象描述而是写“search_weather(city)city 为城市名例如北京返回天气和气温”。6.2 严格限制工具的权限边界生产环境的 Agent 通常会操作数据库、服务器、支付系统。这里必须遵循最小权限原则Agent 使用的数据库账号只能访问必要的表。涉及删除、更新的操作必须先经过人工审批。高危命令放在隔离的沙箱环境中执行。即使模型“以为”它在执行安全操作也无法绕过操作系统和账号的权限限制。安全边界应该由基础设施保障而不是依赖模型自我约束。6.3 完整记录 ReAct 轨迹线上排查 Agent 问题最怕看不到中间过程。建议把每一步的 Thought、Action、Observation 全部写入日志或埋点系统。这样如果 Agent 给出了错误答案我们可以复盘是哪一步推理出了问题哪一个工具返回了异常数据。6.4 用 Evals 评估 Agent 效果ReAct 不是写出来就能用的它需要持续评测。你可以在发布前准备一组典型的测试用例覆盖以下类型单工具简单调用。多工具连续调用。工具返回异常数据。用户问题存在歧义。需要模型判断“不应调用工具”的场景。每次修改提示词或工具描述后都跑一遍测试集对比通过率。这种基于评测集的回归验证比人工手工点几个问题要可靠得多。6.5 选择合适的模型ReAct 的效果受模型本身影响较大。能力较弱的模型可能无法理解 Action 格式或者无法根据 Observation 调整计划。如果你的业务场景不复杂可以先从当前可用的中大型模型开始跑通后再考虑蒸馏到更小更便宜的模型上。7. 总结与下一步学习建议到这里我们已经完成了 ReAct 的入门到最小落地理解了 ReAct Reasoning Acting 的核心思想。知道 Thought、Action、Observation 的循环是如何工作的。用 Python 实现了一个可运行的 ReAct Agent。了解了生产落地时的工程改造点与常见排查思路。接下来你可以做三个实验帮助自己加深理解把search_weather替换成真实天气 API看看实际返回结果对模型推理有什么影响。给 Agent 增加一个“计算器”工具观察模型是否能在多步推理中正确使用它。准备 10 个业务测试问题写一个eval.py脚本统计 ReAct Agent 的成功率。ReAct 只是 Agent 的一种基础范式。在此基础上你还会接触到 Plan-and-Execute、Self-Refine、多 Agent 协作等更复杂的设计。如果你能把 ReAct 理解透彻后续学这些内容都会顺畅很多。动手把代码跑起来比读十篇文章更有用。
返回列表