跳到主要内容

工具调用收敛:设计知道何时停止的智能体

· 阅读需 11 分钟
Tian Pan
Software Engineer

一对 LangChain 分析/验证智能体连续运行了 264 小时,产生了 47,000 美元的 API 费用,却没有任何有用的产出。验证智能体持续拒绝分析智能体的输出,但从未说明原因;分析智能体则默认再次尝试。没有人写过停止条件,循环一直运行,直到有人注意到账单。

这是架构图中从不出现的失败模式:知道如何调用工具,却不知道何时停止的智能体。经典的智能体循环是一个不断询问模型"我应该调用工具吗?"的 while True——但这个问题对"我已经看到足够的信息了"没有内置答案。没有收敛逻辑,你构建的不是智能体,而是一个昂贵的轮询函数。

问题的架构根源

每个智能体循环都有相同的形状:观察、决策、行动、重复。模型读取当前上下文,决定是否调用工具,执行工具,将结果追加到上下文,再重复一次。问题是结构性的:每次迭代都会在决定是否再次调用之前重新读取整个上下文。上下文呈二次方增长——原始提示词,然后是原始提示词加第一个响应,再然后是所有这些加上第二个响应。输入 token 主导成本,而非输出。到检索循环的第十次迭代时,你正在为重新读取大量已经处理过的上下文付费。

随机轨迹会加剧这一问题。同一智能体在同一任务上,不同运行之间的 token 消耗差异可达 30 倍。智能体的 P95 延迟是中位数的十倍,因为一小部分查询会螺旋式陷入检索抖动(retrieval thrash)——搜索查询在扩大和缩小之间交替,却没有新证据积累。如果你每次查询的检索迭代中位数是 2 次,但 P95 是 8 次,就说明存在抖动问题,只是你没有查看正确的直方图。

模型本身无法可靠地自我诊断是否拥有足够信息。它被训练成乐于助人,这意味着它默认会做更多事。问模型"你已经有足够信息了吗?"通常会得到"让我再查一件事"的答复。

哪些收敛信号真实存在

信息充足性不是单一指标——它是一系列信号,每种信号能捕捉不同的失败模式。

检索的边际收益递减。 最实用的启发式方法是边际洞见:在每次检索迭代后,询问获得了什么新证据。Microsoft 365 Researcher 智能体明确实现了这一点——它监控"这一步获得了什么新证据?",当边际收益低于阈值时就得出结论。这需要为你的任务定义"新证据"的含义,这是特定于任务的工作,但该模式可以推广。如果最新的检索结果与两次迭代前的结果在语义上高度重叠,你就是在从不同角度获取相同的知识。

覆盖阈值。 对于检索密集型智能体,生产团队已经收敛于三轮检索上限:对于大多数查询类型,超过三次检索循环后,找到真正新信息的概率趋近于零。正确的数字因领域而异,但关键是要选定一个数字并强制执行,而不是让循环保持开放。

置信度收敛。 自洽性(self-consistency)是一个实用的代理指标:如果模型在相同上下文下被多次提示给出相同答案,则置信度已经收敛。这很容易实现——用不同的随机种子运行最终综合步骤两次,并在语义上比较输出。如果它们一致,就完成了;如果它们差异显著,另一轮检索可能会有帮助。

无进展检测。 最简单也最不被充分利用的信号:如果智能体用相同(或语义相同)的参数调用同一工具并获得相同输出,它就卡住了。首次检测到时应触发自我纠正提示("你之前已经尝试过这个,没有新结果——换一种方法怎么样?");在同一会话中第二次检测时应强制停止。这能捕获反馈循环失败模式——那 47,000 美元的案例本质上就是一个没有人监控的无进展循环。

语义漂移。 最近的研究将智能体轨迹形式化为嵌入空间中的动力系统。收敛良好的智能体呈现出收缩模式:连续状态之间的高相似度,与原始意图的有界全局漂移。振荡的智能体在两种状态之间交替。发散的智能体每次迭代与上一次语义距离较远,没有聚类结构。你可以通过连续上下文快照之间的嵌入距离来测量这一点,尽管很少有团队这样做。

终止契约

每次工具调用都应满足一个终止契约:一个框架强制执行的机器可读退出条件,无论模型做出什么决定。各框架有不同的实现方式。

LangChain 的 max_iterations(默认 15)是底线,不是上限。它是防止失控循环的安全网,而不是收敛策略。当它触发时,early_stopping_method="generate" 给模型一次最终综合机会,附带"你到目前为止发现了什么?"的提示;early_stopping_method="force" 则立即停止。对于面向用户的应用,"generate"通常是正确选择,因为即使在硬性限制处也能产生连贯的内容。

AutoGen 有最丰富的终止词汇:MaxMessageTerminationTokenUsageTerminationTimeoutTerminationTextMentionTermination(当智能体说"TERMINATE"时停止)以及用于任意布尔表达式的 FunctionalTermination。这些可以用 AND/OR 逻辑组合。在实践中有效的模式是分层终止:token 预算(硬性成本限制)、消息计数(防止上下文爆炸)和文本信号(让智能体声明完成),三者组合,任何单一触发都会停止循环。

Vercel AI SDK 的 stopWhen 搭配 stepCountIs(20) 虽然简单粗暴,但至少默认设置了限制而非没有。

基于成本的终止在开源框架中未被充分利用,但在生产中至关重要。该模式有两个阈值:软限制(触发工程团队警报)和硬限制(强制进入"最终答案"模式,综合现有上下文)。生产团队发现每会话 0.5 美元和 2 美元是可行的数字,但你的阈值取决于你的利润率模型。

所有框架的关键缺口:没有内置的"边际洞见"启发式方法。你必须自己实现边际收益递减检测。它需要一个特定于任务的效用函数——客户支持智能体中的"新证据"与代码审查智能体中的"新证据"含义不同。

为生产可见性进行监控

没有正确的指标,循环问题是不可见的。标准 APM 追踪告诉你发生了什么;智能体可观测性告诉你发生的事是否有用。

最小可行监控集:

  • 工具调用重复:统计每个会话对每个工具的调用次数,并标记用高参数相似度多次调用同一工具的会话。余弦相似度或参数哈希均可。
  • 上下文增长速率:每次迭代添加的 token 数。如果上下文增长速度快于智能体在推理中引用检索内容的速率,你就在积累臃肿。
  • 每次查询的检索迭代次数:追踪分布,而非均值。均值会掩盖尾部延迟螺旋。你需要 P50、P95 和 P99。
  • 每步成本:在每次操作后计算模型输入加输出成本。当某个会话的每步成本超过阈值时,路由到"最终答案"中断。
  • 步骤与完成率比:对于存在真实答案的智能体任务(例如,"检索这个特定问题的答案"),追踪每个会话需要多少步骤,与理论最小步骤相比。高比率表明收敛效率低下。

每次工具调用都应该发出结构化遥测数据:工具名称、延迟、输入参数(脱敏后)、输出数据、重试次数,以及输出相对于之前调用是否新颖。将工具跨度嵌套在父 LLM 跨度下,这样你就可以为任何会话重建完整的决策链。

目标不是调试个别故障,而是检测系统性模式。一个循环的智能体是一个 Bug;十个有共同工具的循环智能体是一个设计问题。P95 直方图能使这一点可见;单个追踪无法做到。

三层防御

没有任何单一机制是足够的。生产系统需要深度防御。

第一层:策略门控。 在智能体运行之前,定义预算、权限和风险规则:最大 token 预算、最大成本、可访问的工具、哪些操作需要人工确认。这一层不需要任何模型智能——它是纯策略执行。

第二层:有界规划。 与其使用开放式的 while 循环,不如在执行之前生成一个具有固定最大步骤数和预期迭代次数的计划。一个能产生"检索信息(最多 3 次)→ 综合 → 输出"的规划步骤在结构上是有界的,而"搜索直到有信心"则不是。规划者仍然可以使用模型进行规划;约束在于规划输出是有界结构,而非递归意图。

第三层:带收敛检查的执行循环。 在每个检索步骤中,应用上述启发式方法——无进展检测、边际洞见阈值化、成本追踪。这一层进行运行时监控,并在收敛信号触发时应用中断。

各层之间的相互作用至关重要。第一层防止成本失控。第二层防止架构无界性。第三层检测有界计划内的执行是否仍在低效收敛。

"足够信息"实际上意味着什么

根本困难在于信息充足性不是一个普遍概念——它是特定于任务的。对于回答账单问题的客户支持智能体,"足够"可能意味着拥有账户记录和相关政策文本。对于研究综合智能体,"足够"可能意味着拥有三个相互一致的独立来源。对于代码审查智能体,"足够"可能意味着已分析所有更改的文件。

这种特殊性正是没有框架附带收敛启发式方法的原因。在一个领域有效的启发式方法在另一个领域会失效。工程纪律是使充足性显式化:为每种智能体类型定义它,将其编码为终止条件,并在部署前用代表性查询测试它以衡量步骤至收敛的分布。

看起来智能的智能体往往在好的最终答案背后隐藏了糟糕的收敛行为。模型最终得到了正确的输出,所以循环问题没有被注意到。你只会在账单上发现它。那些早期发现这一问题的团队是那些关注步骤计数分布而非仅关注输出质量的人。

实践起点

如果你正在部署检索智能体且目前没有收敛逻辑,最小可行改进是三项变更:

  1. 将检索迭代限制在三次。对于有数据表明三次不够的智能体,可以覆盖此设置。
  2. 添加无进展检测:同一工具加同一参数在一个会话中出现触发自我纠正提示;出现两次触发强制停止。
  3. 对步骤计数分布进行监控。运行一周生产流量,查看 P95。如果 P95 超过 P50 的四倍,你就有一个值得解决的收敛问题。

其他所有内容——边际洞见启发式方法、语义漂移分析、置信度收敛——都是你在获得基线可见性后可以添加的优化。那个 47,000 美元的循环运行了十一天。有了一个硬性步骤计数限制和一个成本警报,两小时内就会被发现。

收敛不是模型能力问题。模型无法告诉你它何时拥有足够信息,就像初级分析师无法可靠地告诉你一个项目何时"完成"一样。这是一个系统问题:你必须构建模型所没有的停止标准。

References:Let's stay in touch and Follow me for more thoughts and updates