最近不少朋友问我零基础到底怎么上手AI大模型。我的答案一直很固定别急着啃论文也别一上来就装各种复杂框架找一个能快速跑起来的小场景亲手做一个Demo。我最近刚完成的一个小项目就是标题里这个旅游规划智能体核心玩法是用react_agent模式让大模型自动完成一次旅行规划。这篇文章就把我从原理到代码、从踩坑到排错的完整过程复盘一遍适合没有任何Agent开发经验的读者直接对照复现。先解释一下react_agent这个名字懂前端的同学别误会它跟React框架没有任何关系。它指的是ReAct模式即Reasoning推理 Acting行动是当前构建智能体最基础也最实用的一种范式。我的做法很简单给大模型配上几个旅游相关的查询工具让它在生成答案前先想清楚再通过工具查到真实信息最终输出一份可落地的旅行计划。整个项目不依赖任何Agent框架纯粹用大模型API加几百行Python代码实现。1. 项目从哪来旅游规划智能体到底解决了什么问题1.1 这个Demo的边界与目标项目一开始我给自己定了一个非常明确的目标做一个能用、能演示、能继续扩展的旅游规划智能体而不是做一个生产级的商业应用。用户只需要输入一句大概的需求比如带5岁孩子去海滨城市玩3天预算6000块不想太赶智能体就应该自动完成下面这些事分析出行需求确定目的地和大致日期查询目的地的基础信息比如最佳旅游季节、消费水平查询天气预报判断适不适合出行筛选适合亲子的景点过滤掉刺激性强或者路程过远的项目查找合适的亲子餐厅避开辣、生冷等不适合儿童的选项查询城际和市内交通方案计算通勤时间把上面所有信息综合成一份包含每日安排、预算参考的行程表这个边界很重要。我没有要求它能实时预订酒店、购买门票也没有要求它接入真实地图。先把大模型能够理解需求、调用工具、反思结果、输出结构化工件这条链路跑通后续再加什么功能都简单。很多初学者做Agent项目容易犯一个错误一上来就想做一个万能助理结果工具堆了二三十个提示词写了上千字最后模型频繁用错工具项目烂尾。我这次刻意收敛范围只有5个工具每个工具职责单一这样模型调用的准确率会高很多。1.2 纯对话式大模型为什么搞不定旅行规划我在设计这个项目前先用普通的对话方式测试过大模型。直接把需求丢给它让它生成一份旅行计划效果看起来很唬人景点列表、餐厅推荐、预算估算都有但只要认真核对就会发现不少问题。最重要的问题是信息陈旧。大模型的训练数据有截止时间它不知道某个景点是不是正在维修、某条地铁线是不是已经开通、某个餐厅是不是已经停业。它甚至会一本正经地编造一个不存在的景点配上看起来完全合理的位置和开放时间。这就是所谓的大模型幻觉。其次纯对话方式缺乏数据来源。旅行规划本质上是一个需要大量实时信息的任务天气、交通、营业时间、票价、适合年龄……这些信息模型在训练时见过一些但都是片段化的大概率是过时的。用户问明天该穿什么模型需要知道明天真实的天气。ReAct模式恰恰解决了这个问题。它把推理和信息获取拆成了两个动作模型负责推理——现在需要知道什么信息下一步该做什么工具负责获取——查询真实数据把结果喂给模型。模型不再需要凭记忆编造只需要基于事实做规划和判断。1.3 这个项目涉及哪些关键技术点零基础的人看到智能体Agent这个词容易发怵觉得这是很高级的东西。拆开来看这个项目其实只有四个核心部分组成大模型API调用模型负责理解需求、推理决策、生成文本工具定义把外部能力包装成模型可以调用的函数提示词设计告诉模型它有哪些工具、按什么格式调用、什么情况下结束ReAct循环一个简单的while循环让模型反复思考→调用工具→观察结果→再思考直到给出最终答案我用最朴素的Python代码把这四部分串起来不借助任何Agent框架。这样做的好处是每一步都透明可见出了问题你能清楚知道是哪一环的锅。等到你理解了ReAct的精髓再去用那些封装好的框架也不迟。而且这个模式不止能做旅游规划。给模型配上文件读写工具就是文档助手配上数据库查询工具就是数据分析师配上代码执行工具就是编程助理。学会ReAct等于掌握了一套通用的Agent构造方法。2. 核心原理ReAct循环到底在做什么2.1 一个循环、三个关键字段ReAct的核心可以概括为三句话先想再做看结果再想。这完全模拟人类处理复杂任务的方式。比如我自己规划一次旅行不会直接打开某个App下单而是先想我需要知道目的地最近天气怎么样孩子适不适合去有什么景点适合亲子。这是Thought思考。接着我打开天气App查一下未来几天的气温这是Action行动。App弹出降水概率和温度曲线我发现第二天下雨这是Observation观察。于是我调整计划把室外景点安排在第一天再查一下室内儿童乐园这是新一轮Thinking。Agent里的ReAct循环就是把这个过程代码化。模型每一轮输出两个关键字段Thought模型用自然语言描述自己当前的想法比如用户带5岁孩子出行我需要先确认目的地天气Action模型输出一个结构化的JSON声明要调用哪个工具、传入什么参数程序解析出Action之后执行对应的工具函数拿到结果回来作为Observation拼进对话历史再交给模型继续推理。如此反复直到模型输出一个特殊动作Final Answer。这里有个容易忽略的细节Thought不是给用户看的装饰它是模型推理链的一部分。大模型在生成Thought时相当于把当前状态评估和下一步计划显式表达了出来这能显著降低它在复杂任务中出错的比例。你可以做个对比实验不要求模型输出思考过程直接让它给出最终答案效果通常会差很多尤其是在需要多步工具调用的场景。2.2 为什么推理加行动能减少幻觉我刚开始接触这套模式时有一个疑问大模型本来就会编造让它在思考之后调用工具它不还是可能编造工具结果吗实验做下来你会发现答案是否定的。大部分情况下不会原因是设计上就把编造空间堵死了。程序执行Action后工具返回的是程序代码生成的真实结果这段结果被明确标注为Tool Observation拼接到对话里。模型在最终回答时必须引用这些观察结果而不能凭空捏造。我在系统提示词里写得很清楚所有景点、天气、价格信息必须来自工具返回结果不得编造。模型遵循这个约束的概率很高因为整个对话的上下文已经给了它充分的事实材料它只需要组织语言即可。当然工具返回的实时信息来自模拟数据源真实度取决于你接入的数据源。但至少从机制上ReAct割断了模型直接凭记忆编造实时信息的通道。你要做的是让后面的工具执行环节返回高质量数据。2.3 可观测性与灵活扩展的优势ReAct还有一个很容易被忽略的优点是全程可观测。普通的大模型对话是一个黑盒输入问题输出答案中间发生了什么你完全不知道。ReAct不同每一轮Thought、Action、Observation都会打印出来你可以清楚看到模型是经过怎样的路径得到最终结论的。这个特性在调试时救了我很多次。有一次Agent反复调用同一个景点查询工具却不进入下一步我查看轨迹后发现是工具描述写得有歧义模型误以为还需要继续查。改了一句话之后问题立刻消失。如果没有轨迹日志这种问题基本没法定位。灵活性方面新增工具非常容易。我只需要在工具注册表里加一个函数再在系统提示词的工具列表里加一行描述Agent立刻就会多出一项能力。这就跟人一样你多学一个技能以后做事时就多一种手段。我后来给Agent加过一个餐厅查询工具改动不到20行代码它马上能在规划行程时主动把吃这个维度考虑进去。2.4 ReAct与其他Agent范式的对比零基础学习阶段只做ReAct是完全够用的。但搞清楚它和其他范式的区别能帮你建立完整认知。业界常听到的Plan-and-Execute模式会让模型先制定一个多步计划再逐步执行适合目标非常明确的任务Reflexion模式则在ReAct基础上增加自我反思机制失败后总结经验重新尝试适合高难度推理。ReAct的特点是灵活、简单、路径动态。它不需要预先规划所有步骤模型每一步根据当前观察结果动态决定下一步。这个特性让它特别适合旅游规划这类开放度高的任务——用户需求可能随时变化中途发现天气不好需要临时改行程ReAct天然支持这种动态调整。3. 动手准备工具选型与大模型API封装3.1 技术栈为什么这样选整个项目我只依赖两样东西一个可用的大模型API以及Python标准库。没有引入任何第三方Agent框架。我刻意这样选。零基础学习者最容易被各种框架搞得晕头转向框架里有Agent、Tool、Memory、Callback一堆抽象概念还没开始写业务逻辑就先陷进概念海洋。用最简单的技术栈你可以把注意力全部放在ReAct模式本身。大模型API我用的是一个统一的封装函数llm_chat它的功能只有一个传入消息列表返回模型生成的文本。这个函数内部的实现方式对Agent逻辑完全不重要只要你手上有一个能对话的大模型API套进这个函数就能跑。环境方面只需要Python 3.9以上装一个requests库就够。代码我组织成四个文件结构非常清晰tools.py放工具定义prompts.py放提示词agent.py放ReAct主循环config.py放配置参数。travel_agent_demo/ ├── agent.py # ReAct主循环 ├── tools.py # 工具函数定义 ├── prompts.py # 系统提示词模板 └── config.py # API配置与参数3.2 旅游场景工具清单一览我给智能体设计了5个工具每个对应旅行规划中的一个关键信息维度。get_destination_info查询目的地城市的基本情况包括城市特点、建议游玩天数、消费水平get_weather查询指定城市在指定日期的天气包括气温、降水概率、风力search_attractions查询一个城市的景点列表返回每个景点的名称、类型、建议游玩时长、适合人群、门票参考价search_restaurants查询指定区域的餐厅返回菜系、人均消费、亲子友好程度get_transport查询两个地点之间的交通方式和大致耗时也支持查询市内通勤工具数量的选择我斟酌过。最初想加一个酒店查询工具但考虑到行程规划阶段不需要精确到具体酒店只要给出住宿的区域建议即可所以砍掉了。少一个工具模型就少一分用错的概率。每个工具在注册表里都有三个关键信息真实的可调用函数、自然语言描述、参数说明。模型看到的是描述和参数说明程序执行的是真实函数。描述写得好不好直接决定模型能不能正确使用工具。3.3 定义工具的标准格式与参数规范工具函数本身很简单核心是把返回结果处理成JSON字符串。我举一个天气查询的例子# tools.py import json import datetime def get_weather(city: str, date: str) - str: 查询城市天气。这是模拟实现 实际使用时可以替换为真实天气API。 # 模拟数据实际项目在这里请求外部天气服务 weather_db { (阳海市, 2025-06-01): {weather: 多云, high: 28, low: 22, rain_prob: 10}, (阳海市, 2025-06-02): {weather: 小雨, high: 25, low: 21, rain_prob: 70}, } key (city, date) data weather_db.get(key, {weather: 晴, high: 26, low: 20, rain_prob: 20}) return json.dumps({city: city, date: date, **data}, ensure_asciiFalse)这个函数的特点是入参简单清晰返回结果用JSON格式。模型在拿到JSON字符串后可以直接提取关键数据进行后续推理。工具注册表则长这样# tools.py TOOL_REGISTRY { get_weather: { function: get_weather, description: 查询指定城市、指定日期的天气情况返回气温、降水概率、风力等级。, parameters: { type: object, properties: { city: {type: string, description: 城市名称}, date: {type: string, description: 日期格式YYYY-MM-DD} }, required: [city, date] } }, # 其余工具类似这里省略 }一开始我犯过一个错误工具描述写得太简略比如只写查询天气结果模型经常把参数传错。后来我把描述改成更详细的说明不仅说明功能还说明使用场景比如在合适的地方提示当需要判断某天是否适合户外活动时使用。这之后模型的调用准确率明显上升。工具返回的数据也需要考虑模型友好的问题。纯文本描述返回值对模型理解没问题但JSON结构化的返回值能让模型更快定位关键字段。我在每个工具返回里都保证字段名语义明确比如rain_prob比precipitation_probability好理解得多。4. 核心实现手写一个react_agent旅游规划智能体4.1 大模型API的统一封装在写主循环之前先搞定大模型API封装。我在config.py里放好配置项在agent.py里写封装函数# config.py MODEL_NAME your-model-name # 换成你实际可用的模型名 API_BASE https://your-api-endpoint # 换成你实际使用的API地址 API_KEY your-api-key # 换成你的API密钥 MAX_STEPS 8 TEMPERATURE 0.2# agent.py import json import requests def llm_chat(messages, temperatureTEMPERATURE, max_tokens2048): 调用大模型API。这里是通用封装请按你的API要求调整请求体。 headers { Authorization: fBearer {API_KEY}, Content-Type: application/json } payload { model: MODEL_NAME, messages: messages, temperature: temperature, max_tokens: max_tokens, stop: None } # 注意不同大模型API的请求格式有差异这里以最常见的结构示例 try: resp requests.post(API_BASE, headersheaders, jsonpayload, timeout30) resp.raise_for_status() data resp.json() return data[choices][0][message][content] except Exception as e: print(f[LLM调用失败] {e}) return 为什么要单独封装这一层因为后续所有代码都只调用llm_chat这个函数如果哪天你想换一个模型API只需要改这一个函数ReAct主循环完全不用动。4.2 编写ReAct主循环这是整个项目的核心逻辑用一个while循环就能说清楚# agent.py from tools import TOOL_REGISTRY from prompts import SYSTEM_PROMPT def parse_action(text): 从模型输出中解析动作JSON start text.find(json) if start ! -1: text text[start 7:].split()[0].strip() else: # 去掉常见的自然语言前缀和多余字符 start text.find({) end text.rfind(}) 1 if start -1 or end 0: return None text text[start:end] try: return json.loads(text) except json.JSONDecodeError: return None def execute_tool(name, arguments): 执行工具函数返回观察结果 if name not in TOOL_REGISTRY: return json.dumps({error: f未知工具: {name}}, ensure_asciiFalse) tool_func TOOL_REGISTRY[name][function] try: result tool_func(**arguments) return result except Exception as e: return json.dumps({error: f工具执行异常: {e}}, ensure_asciiFalse) def run_agent(user_query, max_stepsMAX_STEPS): messages [ {role: system, content: SYSTEM_PROMPT}, {role: user, content: user_query} ] for step in range(1, max_steps 1): print(f\n Step {step} ) response llm_chat(messages) print(模型输出:, response) action parse_action(response) if action is None: # 解析失败给模型一个纠错机会 messages.append({role: assistant, content: response}) messages.append({role: user, content: 请严格按照JSON格式输出你的动作。}) continue if action.get(type) final: return action.get(content, ) # 否则当作工具调用处理 tool_name action.get(name, ) tool_args action.get(arguments, {}) print(f调用工具: {tool_name}, 参数: {tool_args}) observation execute_tool(tool_name, tool_args) print(工具返回:, observation) messages.append({role: assistant, content: response}) messages.append({role: tool, content: observation}) return Agent执行超过最大步数未能生成最终计划。 if __name__ __main__: query 帮我规划阳海市3日亲子游孩子5岁预算6000元不想太赶 result run_agent(query) print(\n 最终输出 ) print(result)这段代码里隐藏了几个关键设计点新手容易忽略。第一我把模型的原始输出完整追加到消息列表里再紧跟一条tool角色的消息。这个顺序对模型理解很重要它先看到自己说了什么再看到工具返回了什么形成完整的因果链。第二parse_action函数做了容错。真实场景中模型经常不会老老实实只输出一个JSON它可能会先说一句好的我来查询天气然后才输出JSON。如果解析失败我让模型重新输出而不是直接崩溃这大大提升了稳定性。第三execute_tool内部做了异常捕获。即使工具函数抛了异常也会被转换成一条error信息返回给模型模型会发现工具调用出错了进而选择重试或换一种方式。这比让整个程序崩溃要友好得多。4.3 关键的系统提示词设计提示词是ReAct Agent的灵魂它的作用是让模型理解自己的身份、拥有的工具、输出格式和结束条件。我贴出实际使用的提示词并标出关键设计点# prompts.py SYSTEM_PROMPT 你是一个专业的旅游规划智能体。你的任务是根据用户需求利用提供的工具查询实时信息制定出合理、可执行的旅行计划。 你可以使用以下工具每次只能调用一个 1. get_destination_info: 查询目的地的基础信息包括城市特点、建议游玩天数、消费水平。当需要了解目的地整体情况时使用。 2. get_weather: 查询指定城市、指定日期的天气情况。当需要判断某天是否适合户外活动、需要携带哪些衣物时使用。 3. search_attractions: 查询一个城市的景点列表返回景点类型、建议游玩时长、适合人群、门票价格。当需要筛选景点时使用注意结合用户的亲子、老人等特殊需求。 4. search_restaurants: 查询指定地点附近的餐厅返回菜系、人均消费、亲子友好程度。当需要安排餐饮时使用。 5. get_transport: 查询两个地点之间的交通方式和大致耗时也支持查询同一城市内的通勤。当需要安排行程衔接时使用。 你的工作流程 1. 先理解用户需求拆解出关键约束人数、年龄、预算、天数、偏好、城市。 2. 每次行动前用一句话说明你的思考过程。 3. 需要信息时输出一个JSON动作格式为{type: tool, name: 工具名, arguments: {参数1: 值1}} 4. 收到工具结果后立刻根据结果继续思考决定下一步行动。 5. 当信息收集完成时输出最终规划{type: final, content: 完整的旅行计划} 硬性约束 - 所有景点、天气、餐厅、交通信息必须来自工具返回结果绝对不允许编造。 - 如果某工具调用失败检查参数后重试最多两次仍失败则更换策略。 - 不要重复调用同一个工具查询同样的内容。 - 用户预算有限时优先推荐门票价格合理、性价比高的景点。 - 亲子游场景不推荐刺激性强、路程过远、不适合低龄儿童的景点。 - 最终计划必须包含每日行程安排、备选方案、预算参考。 提示词有几个细节值得单独讲。每次只能调用一个工具这句话很重要。很多大模型API虽然支持并行工具调用但在零基础项目里串行调用更容易排查问题。每走一步你都能确认这一步的结果再决定下一步。工作流程部分相当于给模型一个操作手册。模型其实是一个人在回路的模仿者你写清楚流程它就会按流程执行。你希望它先理解需求再动手就把先理解需求拆解约束放在流程第一步。硬性约束部分是防幻觉的关键。我明确告诉模型必须来自工具返回结果、不要重复调用同一个工具、重试最多两次。这些规则模型大体上会遵守偶尔会有偏差但在后面配合解析逻辑兜底基本不会失控。4.4 工具执行细节模拟数据也能跑通全流程由于是Demo项目我没有真的去申请各种天气、景点API而是直接写了模拟数据源。每个工具内部都维护着一个字典存储了阳海市这个虚构城市的完整旅游数据。模拟数据这个做法看起来朴素但对零基础学习反而是优点。真实API有访问频率限制、有付费限额调试一次要等很久还可能在演示现场掉链子。模拟数据让整个项目随时随地能跑等学会了整套逻辑再替换数据源就行。景点工具我做得稍微复杂一些。景点信息里包含一个适合人群字段主要目的是测试模型能否结合用户需求筛选。比如用户带5岁孩子模型看到某个景点标注适合成人惊险刺激类就应该把它排除掉。这个测试点在完整演示中确实触发了效果很好。5. 实战演示让Agent规划一次亲子海滨3日游5.1 启动智能体输入用户需求我输入的需求是帮我规划阳海市3日亲子游孩子5岁预算6000元不想太赶最好6月1日出发。这个需求包含了几个约束条件目的地是阳海市时长3天有5岁孩子预算6000节奏慢出发日期明确。理想情况下Agent应该逐一提炼这些信息并在后续决策中时刻回扣。5.2 完整的运行轨迹拆解我把运行轨迹一步步拆开看。第一步模型输出Thought用户带孩子出行孩子只有5岁需要重点关注亲子友好项目。我先查询阳海市的基础信息了解这个城市的整体特点和推荐游玩方向。对应Action是调用get_destination_info。工具返回了城市概况海滨城市沙滩平缓适合亲子消费中等。这个环节的作用是让模型先建立对目的地的基本认知。如果模型连目的地是什么类型都不清楚后面筛选景点就容易瞎猜。第二步模型看到目的地是海滨城市决定查看6月1日和6月2日的天气海边活动对天气依赖很大如果有雨就需要调整室内外项目顺序。于是调用get_weather查询两天天气。工具返回6月1日多云、气温适宜6月2日有小雨。这时候模型做了一个关键决策6月2日有雨我应该在1日安排主要的户外海边活动2日转为室内项目。这一步充分体现了ReAct的价值它会根据观察结果动态调整策略而不是机械地按固定模板排行程。第三步模型查询阳海市的景点列表。search_attractions返回了8个景点模型从中筛选出3个海滨公园、海洋馆、儿童科技馆并排除了刺激水上项目和远郊景区。它的思考过程完全扣住了5岁孩子这个约束。第四步模型觉得餐饮信息还不够调用search_restaurants查询了景区附近适合亲子的餐厅重点关注是否有儿童餐、口味是否清淡。第五步模型调用get_transport查询了主要景点之间的交通耗时判断每天的路程安排是否会在1小时内确保不赶。至此模型认为信息收集完毕输出final类型的最终规划。这个运行轨迹看似自然其实每一步都经过了思考。换成一个纯对话模型它不会主动去查天气不会因为下雨调整项目顺序可能直接给你一个模板化行程表。我拿同一需求测试过差距非常明显。5.3 最终输出的旅行计划长什么样最终输出我用一个结构化文本返回这里节选核心部分【阳海市3日亲子游规划6月1日-6月3日】 出行信息 - 人数2大1小孩子5岁 - 预算6000元 - 节奏轻松休闲每日最多2个核心项目 Day16月1日多云26-28摄氏度 - 上午海滨公园沙滩游玩海边散步让孩子玩沙 - 午餐海滨公园附近亲子餐厅 - 下午海洋馆观看海洋动物表演 - 晚餐市区海鲜餐厅清淡口味 - 住宿建议住在海滨公园附近区域方便第二天出行 Day26月2日小雨21-25摄氏度 - 上午儿童科技馆室内为主不受雨天影响 - 午餐科技馆附近商场亲子餐厅 - 下午返回酒店休息傍晚在室内儿童游乐区活动 - 晚餐酒店周边粤菜馆 - 提示降雨天气注意携带雨具和薄外套 Day36月3日多云26摄氏度 - 上午海滨栈道散步逛本地老街 - 午餐老街特色小吃 - 下午根据回程交通时间灵活安排海滩短时停留 预算参考 - 住宿2晚约1800元 - 餐饮3天约1500元 - 门票约400元 - 交通约800元 - 其他及备用约1500元这个输出的质量超出了我最初的预期。模型不仅排了行程还根据天气预报把室内外项目做了适配甚至在餐饮和住宿安排上都有呼应。它能做到这一步核心原因是整个流程中每一步都基于工具返回的真实数据而不是凭空想象。6. 常见问题与排查技巧实录6.1 模型不按格式输出工具调用怎么办我在开发过程中遇到最多的一个问题就是模型有时候不输出JSON动作而是直接输出一大段自然语言。比如模型可能会说好的让我先看看阳海市的天气情况然后就没有然后了。排查之后发现原因主要有三个一是提示词里的JSON示例不够醒目模型没有理解输出格式要求二是模型能力较弱对复杂指令遵循度不高三是温度参数设置太高导致输出随机性过大。解决思路是多管齐下。第一优化提示词在格式说明处用json代码块强调并给出一个完整示例。第二把温度降到0.2左右让输出更稳定。第三在代码里做容错调用parse_action解析不成功时返回None触发系统提醒请严格按照JSON格式输出并给模型一次纠错机会。6.2 Agent进入死循环反复调用同一个工具另一个高频问题是模型卡在某一步反复调用同一个工具比如连续三次查询同样的景点信息就是不肯进入下一步。我排查后发现这通常是因为模型觉得信息还不够但它又不知道具体缺什么。我采取的措施有两条。第一在提示词里明确写不要重复调用同一个工具查询同样的内容。第二在执行层做限制execute_tool里维护一个调用记录如果同一个工具对同样的参数调用了两次就直接返回一个警告信息提示模型换一种方式。还有一个策略是控制max_steps。我的主循环设置最大8步如果超过步数就直接退出返回提示。这个机制是兜底保证Agent不会无限循环烧API费用。零基础同学务必加上这个限制。6.3 幻觉数据混入最终输出即使有工具提供实时数据模型偶尔还是会把记忆里的信息混进来。比如它可能会在行程里推荐一个工具结果中完全没有的景点或者把某家餐厅的评分凭空提高。针对这个问题我在提示词里加了非常硬的约束所有景点、天气、餐厅、交通信息必须来自工具返回结果绝对不允许编造。同时我让工具返回的数据足够丰富让模型觉得不需要编造也有足够信息可用。另外我在运行逻辑里加了输出校验最终计划文本生成后简单检查一遍如果出现工具返回数据里不存在的地点名称就提示模型修正。虽然这个检查做不到完全自动但作为辅助手段能显著减少幻觉输出。6.4 上下文越来越长怎么办ReAct每执行一轮就会往消息列表里追加一条模型输出和一条工具返回多轮之后上下文会越来越长。我在测试时跑过12步的对话token消耗明显增加而且模型对早期信息的关注度会下降。最直接的控制方法是减少max_steps一般8步足够完成旅游规划。如果需要更多轮次可以考虑只保留最近几轮的消息或者让工具返回精简数据而不是长文本。在我的场景里工具返回的JSON被刻意设计得短小精悍这本身就在控制上下文膨胀。6.5 大模型API调用出错的排查思路API调用失败是新手最常碰见的拦路虎。常见的报错类型包括鉴权失败、请求超时、模型名错误、请求格式不对。我给llm_chat函数包了一层异常捕获打印出错误信息这样在终端里能直接看到失败原因。这里分享一个排查技巧先用一个最简单的消息列表hello测试API连通性通了之后再跑完整Agent。别等到Agent跑了好几步才报错那样你都不知道是API问题还是Agent逻辑问题。6.6 问题排查速查表现象可能原因排查方向模型输出自然语言而非JSON提示词不明确增加JSON格式示例降低temperature反复调用同一工具工具描述误导检查description是否有歧义输出出现幻觉信息约束不足或数据不足强化硬性约束丰富工具返回数据上下文越来越长步数过多或返回数据冗长控制max_steps、精简工具返回API频繁报错密钥、模型名、格式错误先用单条消息测试连通性7. 我的实操体会与后续扩展方向这个项目做下来我最大的体会是零基础学AI大模型最忌讳的是追求一步到位。你先用模拟数据把一个ReAct Agent跑通看到模型真的会调用工具、会根据结果调整计划那种感觉和纯粹读理论完全不一样。这个正反馈很重要它会支撑你继续学下去。如果后续想继续扩展这个项目我建议按以下顺序逐个做把模拟数据换成真实天气API让天气信息真正实时化给Agent增加酒店预订和门票预订工具把规划落地接入语音输入让用户说话就能完成规划再加一层多Agent协作比如一个Agent负责目的地研究另一个负责预算控制最后统一合并成计划。但扩展之前请先确保你真正吃透了这四件事工具定义为什么用JSON格式、提示词里哪些约束是必要的、parse_action的容错是怎么运作的、执行工具的异常如何返回给模型。这四个点想明白ReAct对你就不再是黑盒而是可以随意改造的基础能力。
阅读完成 · 觉得有帮助?