问题背景
在开发 AI 行程规划功能时,许多团队的第一反应是搭建一条流水线:提取目的地、查询机票、搜索酒店、排列每日行程、拼合成最终输出。这条流水线在 demo 阶段能够运行,但一旦面对真实用户,就会暴露出根本缺陷——真实的规划过程从来不是一条直线。用户可能中途改变主意,从高原改去海岛;可能某个地点没有直飞,需要重新调整路线;也可能发现某段路驾驶时间过长,需要拆成两天。流水线无法处理这些回头、换路、重来的需求,只能通过 if-else 堆砌状态机,最终变得难以维护。
野行 Y 采用了一个不同的思路:模型驱动的循环。这个循环没有“第几步”的概念,只有“当前状态”和“下一步决定”。当用户改变主意时,新消息进入上下文,模型自然按新意图行动;当驾驶时间过长需要拆分时,模型看到八小时返回结果,自己决定增加住宿点;当没有直飞时,工具返回无数据,模型看到后自动调整策略。规则从代码搬到了模型的判断中,维护的重点从庞大的状态机转变为“给模型什么工具、什么上下文、什么约束”。
核心概念
模型驱动的循环:每一轮模型只做一个决定——根据当前上下文,判断下一步该做什么。可能的行为包括搜索目的地、反问用户天数、估算驾驶时长、提交行程报告等。工具执行的结果回到上下文,模型看到结果后再决定下一步。
上下文:包含用户原始需求、历史对话、工具返回结果、系统约束指令等全部信息,是模型每轮决策的依据。
护栏:为防止模型不收敛、跑偏而设计的强制约束机制,是循环稳定运行的关键。
工作原理
循环的骨架是一个简单的 while 循环,代码位于 loop.py 的主循环中。它不关心“第几步该做什么”,反复执行以下流程:
- 将当前上下文喂给模型。
- 模型输出一个动作(如调用某个工具)。
- 执行该动作,获取结果。
- 将结果回填到上下文。
- 重复步骤1-4,直到模型调用
submit_plan提交行程。
这个循环的核心是“模型自己决定下一步”,系统只提供可用的工具和约束条件。
执行流程
一个典型的循环执行流程如下:
- 用户输入:例如“我想去高原自驾”。
- 模型判断需要更多信息,调用搜索工具查询高原自驾路线。
- 搜索结果返回上下文,模型看到信息后,可能反问用户“几天、几个人、开什么车”。
- 用户回答,上下文更新。
- 模型继续调用工具估算驾驶时长、查询住宿等。
- 当模型认为行程已经完整,调用
submit_plan提交最终行程。
如果用户中途改变主意,比如从高原改为海岛,新的输入进入上下文,模型在下一轮自然按新意图行动,不会因为之前已经规划了高原路线而卡住。
参数作用
循环本身并不复杂,真正复杂的是围绕它搭建的护栏系统。这些护栏在代码中通过强制检查、条件阻断、超时控制等方式实现,目的是防止模型犯浑。以下是野行 Y 中几个关键的护栏及其作用:
计数器:防止模型偷懒
模型可能试图用一大段文字糊弄过去,不调用工具。代码中有一个计数器,当模型尚未输出正式报告就吐出大量文字时,系统会回注一条指令:“别用纯文字,必须调 submit_plan 出正式报告”,强制模型走结构化输出流程。弱模型尤其容易犯这个错误。
撤除工具:防止模型过度搜索
模型可能查资料上瘾,连续搜索三四次游记,迟迟不进入排线阶段。此时系统直接将搜索工具从模型可用的工具列表中移除。模型看不见搜索工具,只能继续下一步操作。这种方式比单纯用文字提示更有效,因为工具不在手里,它无法绕开。
强制确认:确保人在环中
模型不能直接输出最终报告。在调用 submit_plan 之前,必须先将主线骨架摆给用户确认一次。代码强制检查:如果一次确认都没有走过,则打回,要求先展示给用户看。
子Agent核对:防止模型自我确认
模型刚排完主线时,上下文里充满了“为什么这么排”的理由,让它自查容易自我确认,觉得排得挺好。因此,在展示给用户之前,系统会另开一个干净的子 Agent,只拿着用户的原始要求和当前版本的主线,逐条核对硬伤:怕高反却上了高海拔?带着老人却单日暴走?三人中有的人的必去点被漏了?发现硬伤就要求重排。这个子 Agent 在用户看到主线之前执行,因此有问题的版本用户根本看不到。
驾时计算:防止模型忽略驾驶时长
自驾行程在出报告前,必须强制计算每天的驾驶时长。弱模型容易跳过这一步,排出一天开十二小时、一千多公里的路线。代码中设置强制检查:没有计算过驾驶时长就想提交,打回。
墙钟闸:防止超时
步数上限在慢模型下形同虚设,因为一步可能等待一百多秒,步数没用完,外部已经超时。因此系统增加一个计时器:跑满五分钟还没出报告,无论模型进行到哪一步,都强制它用已经核实过的真实地名收尾。宁可行程短一天,也不能让用户看到白屏。
示例说明
假设用户说“想去高原自驾,怕高反,带老人”。模型在循环中开始搜索,可能查到海拔四千七百米的垭口。子 Agent 核对时发现“怕高反”和“高海拔”冲突,立即打回要求重排。模型不得不调整,避开高海拔路线。如果模型绕圈子不提交,墙钟闸会在五分钟后强制收尾,用已经确认过的地名生成一个缩短版行程。
另一个例子:用户说“去稻城亚丁,从成都出发”。模型查询驾驶时长,发现单程八小时,一天开不完。它看到工具返回的数据,自己决定把这一天拆成两天,中间增加一个住宿点。如果模型不主动拆分,驾时计算护栏会强制检查并打回。
优势与限制
优势:循环能够自然处理回头、换路、重来,无需维护复杂的 if-else 状态机。模型可以根据实际返回的数据动态调整,灵活适应真实场景中的变化。
限制:循环本身依赖模型的能力,弱模型更容易犯偷懒、绕圈子、忽略细节等错误。因此需要大量护栏来兜底,这些护栏的开发和维护成本很高。一个裸的 while 循环会出两类事故:不收敛(一直搜索不提交)和跑偏(忽略用户约束)。
常见误区
误区一:认为 agentic loop 就是“让模型自由决定”,把重点放在模型本身。实际上,最花力气的地方在于设计护栏,防止模型自由过头。
误区二:认为循环可以完全替代规则。实际上,护栏本身就是规则,只是从代码逻辑转移到了系统约束。模型再聪明,也有犯浑的时候,系统必须在那时还能体面收场。
适用场景
模型驱动的循环适用于需要动态规划、用户意图可能频繁变化、需要根据实时数据调整的复杂任务。例如行程规划、多步骤研究、对话式决策等。不适用于线性、确定性、无需反馈的任务。
内容总结
野行 Y 的循环是一个模型驱动的主循环,加上一圈护栏兜着。护栏包括计数器、撤工具、强制确认、子Agent核对、驾时计算、墙钟闸。这些护栏是系统稳定运行的关键,也是整个引擎的核心。后续的工具设计将在此基础上展开。
