跳到主要内容

工具幻觉率:你的智能体团队尚未运行的探测工具集

· 阅读需 11 分钟
Tian Pan
Software Engineer

询问一个 Agent 团队他们的工具调用成功率是多少,你会得到一个答案。但如果你问他们的工具幻觉率(tool-hallucination rate)是多少,全场就会陷入沉默。大多数团队并不追踪这一指标,而那些追踪的团队通常也只计算最灾难性的版本——即目录中不存在的函数名——而那些更隐蔽、代价更高的变体则在生产环境中未受监控地运行。

幻觉化的工具调用不仅仅是指模型凭空捏造了 delete_orphaned_users(older_than="30d") 导致你的分发器(dispatcher)抛出 ToolNotFoundError。这是简单的情况。更复杂的情况是,虚假的调用通过模糊匹配隐匿地指向了一个相邻的真实工具,或者工具名称正确,但 Agent 捏造了一个参数,而你的 Schema 因为将其标记为可选而愉快地接受了它。这两种情况都能通过你的“工具调用是否成功”仪表盘,但都不是用户真正想要的。

本文的核心观点是将工具幻觉视为一个可衡量的量,而不是一种传说中的故障类别。这意味着三个指标、一个每个 Agent 团队都应该运行(但几乎没人运行)的探测套件,以及一套关于提示词(prompt)、工具目录(catalog)和分发器(dispatcher)各自对幻觉率贡献的准则。

三种率,而不仅仅是一种

“工具幻觉率”是一个笼统的概念(suitcase term)。如果你唯一的指标是每千次对话中 UnknownToolError 异常的数量,那么你测量的是分发器的严格程度,而不是模型的行为。请将其拆分为以下三个指标:

未知工具率 (Unknown-tool rate) —— 模型输出一个在当前对话注册的工具集中不存在的函数名的频率。这是经典的幻觉调用。它的下限由分发器的错误日志决定,上限则由模糊匹配层静默吸收的任何内容决定。

影子调用率 (Shadow-call rate) —— 模型输出的名称与真实工具足够接近,以至于分发器(或框架的模糊匹配器)将其路由到了模型并非本意的工具。例如,update_user_profile 因为匹配器过于“慷慨”而被路由到 update_user。这是最糟糕的情况:你产生了幻觉,它却“成功”了,结果你向真实记录写入了错误的字段。除非你专门进行埋点监控,否则这个指标是不可见的。

参数幻觉率 (Hallucinated-argument rate) —— 工具名称正确,但参数是捏造的。例如,在 search_documents(query=..., tenant_id="enterprise_tier") 中,tenant_id 应该是请求者的字面 UUID,而不是对他们的描述。调用在 Schema 层面是成功的,但在语义层面是失败的。在可靠性对齐(Reliability Alignment)文献中,这被称为“工具内容幻觉”,是最微妙的失败模式之一:JSON 解析成功,类型验证通过,但副作用却是错误的。

最近一份关于 Agent 幻觉调查文献的分类法将执行幻觉分解为工具类型(tool-type)、工具时机(tool-timing)、工具格式(tool-format)和工具内容(tool-content)类别。对于暴露大量目录的生产级 Agent,后两类(格式和内容)的比例占据主导地位。行业讨论往往偏向于未知工具率,因为它易于统计。你的指标卡应该将这三者全部分开。

为什么幻觉率比你想象的要高

目录大小会非线性地推高幻觉率。每轮对话暴露 5-10 个工具的团队,其工具幻觉率往往低到可以忽略不计。而每轮暴露 50 多个工具的团队会发现幻觉率激增,这种增长仅凭模式匹配是无法解释的——模型开始在工具族之间进行虚构,因为上下文本身暗示了一个比实际注册的更大的动作空间。目录中的工具越新,附近出现幻觉“近亲”的可能性就越大,因为训练分布中有熟悉的邻居,模型会进行插值。

命名是一种泄露。如果你的目录中有 create_invoicelist_invoicesget_invoice,那么当用户第一次要求取消发票时,模型会非常自信地调用 delete_invoice。目录的形态暗示了完整性。再配合一个过度承诺的系统提示词(system prompt)——“你可以访问全套计费工具”——你就等于告诉模型,缺失的工具一定存在,因为提示词是这么说的。

训练分布会从另一个方向泄露。模型在成千上万的代码库中见过 send_emailsend_messagesend_notification 的实现。如果你只注册其中一个,另外两个就会存在于先验知识中。ToolTweak 系列研究表明,表面层级的工具元数据极易受到对抗性操纵,正是因为工具名称在选择中具有极大的权重——在正常情况下,正是这种权重将幻觉引向了那些看似合理但实际上并不存在的“邻居”工具。

提示词也有所影响。那些被指令要求“机智灵活”或“当工具失败时尝试其他方法”的 Agent,在首轮调用失败后,幻觉调用的比例会有显著上升。这种指令赋予了模型即兴发挥的权限,而代价最低的即兴发挥就是捏造一个新的工具名称。

你应该运行的探测套件

针对工具幻觉的探测套件(probe suite)是一个独立于生产环境追踪记录之外的留存评估集。有效的构建形式如下:

  • 诱饵目录(Decoy catalogs)。 针对每个真实任务,组装一个故意忽略该任务所需工具的目录。目的不是测试任务完成情况,而是衡量在缺少正确工具时模型的行为。对输出进行评分:它是拒绝了,还是提出了澄清问题,或者是伪造了一个工具,抑或是误用了现有工具?“伪造(Invented)”即为该探测项下的未知工具率(unknown-tool rate)。这四种结果的分布情况就是关键信号。

  • 仿冒陷阱(Lookalike traps)。 针对每个真实工具,添加一个目录变体,在真实工具旁边放一个名称相似的诱饵。例如 search_docs 放在 search_documents 旁边,user_info 放在 user_profile 旁边。衡量当任务明确需要真实工具时,模型调用诱饵的频率。这就是你的影子调用率(shadow-call rate)。如果你的框架使用了模糊匹配(fuzzy matching),请在评估时将其关闭——你需要看到的是模型的原生输出,而不是被匹配器强制修正后的结果。

  • 可选参数伪造(Optional-argument fabrications)。 针对带有可选参数的每个真实工具,运行那些并不需要这些参数的任务,并衡量模型仍用伪造值填充这些参数的频率。这就是幻觉参数率(hallucinated-argument rate)。

  • 过度承诺提示词探测(Overclaimed-prompt probes)。 在系统提示词中故意夸大智能体(agent)的能力(例如“你拥有用于 X 的工具”),但在目录中却不包含 X。匹配提示词与过度承诺提示词之间幻觉率的差值,量化了提示词本身在多大程度上导致了问题。

在每次提示词变更、目录变更和模型升级时运行此套件。它是工具调用领域的回归测试。探测套件中 3% 的未知工具率并不是及格分数——它是你需要努力压低的底线。类似 DeepEval 的框架提供了工具正确性(tool-correctness)作为指标,但工具正确性仅代表“它是否调用了正确的工具”——它本身无法告诉你具体是哪种幻觉率导致了失败。

预防措施,按效果降序排列

杠杆率最高的防御手段是模式强制生成(schema-enforced generation),而非模式强制分发(schema-enforced dispatch)。OpenAI 函数调用的严格模式(Strict mode)和 Anthropic 的结构化输出(structured-outputs)测试版将工具模式编译为受限的解码语法(constrained decoding grammar),这意味着模型在字面上无法输出违反模式的 token——未知工具名称在生成过程中就变得不可触达,而不是在生成后被拒绝。这能让未知工具率趋近于零。但对于架构允许范围内的影子调用或伪造参数,它无能为力。

第二道防线是分发器严格性(dispatcher strictness)。关闭模糊匹配。如果工具名称不完全匹配,则判定该轮对话失败,并将模型原本意图调用的名称作为错误消息反馈给模型,同时列出实际的目录。大多数框架默认采用宽松设置,因为这看起来有所帮助;但在生产环境中,它会掩盖影子调用,并导致你的可观测性数据失真。

第三道防线是针对每个任务界面(task surface)使用窄目录。无论是在幻觉率还是延迟方面,拥有 50 个工具的单一智能体总是会输给五个各拥有 10 个工具的智能体。在编排层(orchestration layer)进行路由,而不是在模型内部进行。如果模型只看到与当前工作阶段相关的工具子集,那么“这个同类工具可能存在”的先验概率就没有滋生的土壤。

第四道防线是负向少样本示例(negative few-shot examples)。包含明确“禁止调用”模式的提示词——例如“如果任务是 X,请不要调用 cancel_subscription;先要求用户确认”——能显著降低相关真实工具的幻觉参数率。LangChain 关于工具调用的少样本提示(few-shot prompting)工作是一个常被忽视的参考。仅靠正向示例只能教会模式,而负向示例能教会边界。

第五道防线是带有语义检查的参数校验,而不只是类型检查。一个符合 UUID 格式但并不属于请求主体的 tenant_id 就是典型的幻觉参数失败模式。分发器需要在调用工具之前检查身份和范围,并将拒绝操作记录为幻觉信号,而不是通用的权限错误——在对话记录中它们看起来一样,但对于你的评估数据(eval feedstock)来说意义完全不同。

这对你的智能体审查有何改变

如果你已经有了每周的智能体质量审查机制,那么改动很小。在仪表盘上增加三个指标:未知工具率(unknown-tool rate)、影子调用率(shadow-call rate)和幻觉参数率(hallucinated-argument rate),每个指标都在固定的探测套件上进行测量,以便每周的数据具有可比性。按模型、按提示词版本、按目录版本进行追踪。当其中任何一个指标激增时,审查就变成了调查:是目录扩充了,是提示词开始过度承诺了,还是模型版本的更迭改变了先验概率?

探测套件就是你投入的核心资产。一个优秀的套件应该覆盖目录中的长尾部分,而不仅仅是热门工具。当工具废弃时,它也应随之更新,以确保诱饵目录探测能反映当前的注册表状态。它应该在提示词变更发布前的 CI 流程中运行,而不是在搞砸了生产环境之后。

这一切并不光鲜。它不会为你的发布演示稿产生一条持续上扬的曲线。它只会产生三个你可能并不想面对的数字,但它让这些问题变得足够显眼,以至于下次模型伪造了一个你从未写过的函数时,你会是在仪表盘上看到它,而不是在客户的投诉工单里。

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