询问你的智能体上季度的流失率,它会用一个简洁的句子回答 4.2%。这个数字看起来很合理。周围的文字描述也显得很有信心。然而,当有人最终检查仪表盘时,显示的却是 6.8%。智能体根本没有进行任何查询——它只是产生了一个符合“流失率”特征的 Token 序列,因为对于语言模型来说,口述一个数字和计算一个数字在输出过程中看起来是一模一样的。
这是一种能躲过所有 Demo 的隐形失败模式。一个虚构的工具名称会抛出你可以捕获的错误。一个格式错误的参数会通不过 Schema 校验。但是,一个表达流畅的虚构 数值,会穿透你的整个流水线,看起来与真实数值毫无二致。没有异常,没有日志记录,没有红字。唯一的错误信号是某个恰好知道正确答案的人——而使用智能体的初衷本就是为了让人们不必亲自去查。
之所以值得专门为此写一篇文章,而不是将其作为“幻觉”的一个脚注,是因为常规的针对幻觉的建议在这里并不适用。你无法通过 RAG 来解决它,因为模型明明拥有工具却选择不去使用。你无法通过提示词完全可靠地解决它,因为“始终使用分析工具获取数字”这种指令,模型大部分时间会遵守,但其余时间会悄悄忽略。修复方法必须是结构性的:你必须在关键环节让“复述数字”变得 不可能,并让它产生的每一个数字都带上它的“凭据”。
为什么流畅性掩盖了缺失的工具调用
语言模型通过对基于先前所有内容的概率分布进行采样来生成下一个 Token。当上下文询问“上季度的流失率”时,高概率的后续内容是一个个位数的百分比,因为训练数据中的流失率通常就是这个样子。模型并不是在查阅事实,而是在补全模式。输出的 4.2% 和实际 SQL 查询的结果属于相同的数据类型——字符串——而产生虚假数字的生成过程,与格式化真实数字的过程在机制上是一模一样的。
这就是为什么流畅性是最好的伪装。我们已经习惯于将迟疑、推托和格式错误的输出视为疑点。而一个虚构的数字完全没有这些征兆。它以与正确答案相同的节奏出现,因为从机制上讲,它 就是 同一种输出。关于 LLM 智能体幻觉的研究将其分为两类:忠实性错误 (faithfulness errors),即智能体违背了其检索到的证据;以及事实性错误 (factuality errors),即在没有任何证据的情况下妄言。复述的数字属于第二类,而且更难被发现,因为没有任何证据可以反驳——只有缺失,而缺失是无法被渲染出来的。
针对定量问题,情况会变得更糟,因为模型非常不擅长那些被它们跳过工具而直接进行的算术运算。最先进的模型在 7 位数除法上的得分低于 40%。一项针对 48 项医疗计算任务的研究发现,大约三分之一的测试结果是错误的。模型并不是以某种可以纠正的方式“偷懒”——Transformer 推理本质上是一个概率文本生成器,而不是计算器,无论你如何提示,它都无法可靠地执行确定性的算术运算。因此,复述的数字具有双重危险:模型既拒绝调用工具,又在结构上无法产生工具本该提供的答案。
答案不等于有出处的答案
你的系统需要明确区分的是 答案 (answer) 和 有出处的答案 (sourced answer)。它们不是同一种事物的两个等级,而是两种不同的对象。
“答案”是一个占据数字位置的字符串。而“有出处的答案”是一个字符串加上一个可验证的计算指向:哪个工具运行了、使用了哪些参数、针对哪些数据、在什么时间运行。前者是一个断言,后者是一个带有凭据的断言。
现今大多数智能体技术栈产生的都是前者,却表现得像是后者。用户看到 4.2%,理所当然地认为系统 知道 这个数字,因为系统连接到了分析数据库——它肯定查过了。但“连接到”和“查阅过”是不同的事实,而输出结果并没有区分它们。界面暗示了数据并不具备的出处 (provenance)。
将这些视为不同的对象会改变工程逻辑。有出处的答案是可以验证的:你可以检查追踪 (trace) 中是否存在工具调用,其结果是否与文中的数字一致,以及它触及的数据是否足够新鲜。而没有出处的答案只能被盲目信任。而信任,对于一个失败模式是“自信地编造”的系统来说,并不是一种保障,而是一个漏洞。
因此,设计规则是简单粗暴的:智能体输出中任何没有出处的数字都是缺陷 (defect)。这不是风格上的瑕疵,也不是可以接受的近似值——它就是一个缺陷,其严重程度等同于 500 错误。它应该导致校验失败,而不是被耸耸肩放过。
让“口述”数字变得不可能
提示词(Prompting)是最弱的约束手段,因为它设定的是一种“偏好”,而模型只是在统计学意义上满足这种偏好。“始终使用分析工具”这种指令在大多数情况下有效,直到问题表述变得异常、上下文过长,或者模型单纯表现得过于自信——这时它就会根据模式直接作答。你无法察觉到那 3% 被跳过的情况,因为跳过这一步不会留下任何痕迹。
最可靠的杠杆是 API。现代工具调用(tool-calling)接口允许你将 tool_choice 设置为 required,强制模型在特定轮次中发出工具调用而非生成自由文本。对于被分类为定量的问题——例如“是多少”、“有多少”、“增长率是多少”——你可以让模型完全脱离散文模式。它不被允许回答,只被允许调用。随后,数字作为工具调用的“结果”进入对话,而不是作为生成的 Token。根据构建逻辑,工具结果天然带有溯源路径。
让这一流程保持简洁的架构是“两阶段转场”。首先,一个轻量级的分类器——可以是一个小模型,甚至是一个规则——来判定问题是否涉及定量分析。如果是,下一轮模型运行将开启 tool_choice: required 并配置精简的工具集。模型的工作被简化为选择工具和填充参数;它无法使用散文描述,因为散文不在选项菜单内。只有在工具返回结果后,模型才会进入正常的轮次,用自然语言组织答案。此时,它所描述的数字是接收到的,而非凭空臆造的。
这与程序辅助语言模型(PAL)和代码解释器工具背后的思路一致:让模型处理它擅长的推理工作——分解问题、选择操作——并将“执行”路由到确定性的路径上。带来的提升非常显著。将算术运算委托给代码路径可将算术错误减少约 83%。临床计算研究发现,一旦引入工具,错误答案减少了 5 到 13 倍。模型从来都不是进行计算的正确场所,它是决定“运行哪种计算”的正确场所。
为每个数据附上“收据”
强制工具调用解决了你正确分类为定量问题的缺口。但它对漏掉的情况无能为力——比如在一段定性描述中突然出现的数字,或者像“营收增长了约 12%”这样由于没有被标记为“数字问题”而逃过拦截的情况。针对这些,你需要第二层防御:将溯源(Provenance)作为每个数字的追踪属性,并在事后进行检查。
具体来说,智能体输出中的每个数字都应携带元数据:生成它的工具调用、时间戳、数据范围。结构化输出是实现这一目标的机制——不要让模型输出一段嵌入数字的文字,而是让它输出一个结构化对象,其中每个声明都是一个字段,且每个数值字段都有一个必填的 source 兄弟字段。现在,一个没有来源的数字会导致 Schema 校验失败,而不再是一个静默的字符串。这种硬性约束实现了 Prompt 无法完成的强制执行。
这还为你提供了一个低成本的验证步骤。有了溯源信息,验证器可以将文字中的数字与引用的工具结果中的数字进行交叉比对。如果智能体说 4.2%,但引用的查询返回的是 6.8%,这就是一个可以在用户发现之前通过机械方式捕捉到的忠实度错误(Faithfulness Error)。对深度搜索智能体的研究发现,引用的存在与引用的准确性之间存在明显脱节——输出引用较多的系统往往事实准确性反而较低,因为引用变成了装饰。附加来源是必要的,但还不够;你还必须验证该来源是否真的支撑了句中的陈述。
UI 层面的一个有效原则是:展示“收据”。在渲染数字时,展示其数据新鲜度并提供底层查询的链接。这有两个作用:首先,它让用户可以进行校准——十秒钟前查询出的数字与一周前快照中的数字给人的感觉完全不同。其次,它让溯源的缺失变得“可见”。一个没有收据的数字在有收据的数字旁边显得格外突兀,这种突兀会引发一个系统本该自动回答的问题:这个数字是从哪儿来的?
把精力花在刀刃上
并不是每个数字都值得动用这套机制。成本是现实存在的——额外的分类轮次、更严格的输出 Schema、验证环节——如果无差别地应用,会让智能体在处理那些只需要粗略数字的问题时变得更慢、更脆弱。
要把精力花在“错误数字会导致错误决策”的地方。任何进入报告、账单计算、合规声明、医疗或财务数据的内容——这些必须强制进行工具调用并验证溯源,毫无例外。至于任何对话式的、低风险的内容——比如“这个数据集大概有多大”、“大概需要多长时间”——可以保留在散文描述中,理想情况下允许模型使用模糊词。
这种权衡决策(Judgment Call)应该是明确划定的界限,而不是任其随机发生。目前,在大多数系统中,界限取决于模型碰巧在何处调用了工具——也就是说,界限根本不存在,完全受采样随机性(Temperature)控制。请用明确的策略取代这种随机性:列出不允许出现无来源数字的问题类型和输出场景,并在输入端通过 tool_choice、输出端通过溯源 Schema 强制执行。
思维上的转变在于:不再将“口述数字”视为罕见的幻觉,而是将其视为你正在对抗的“默认行为”。模型总是倾向于口述,因为口述是一串廉价的 Token 序列,而计算是一段多步骤的迂回。如果不加干预,它会选择廉价的路径,而廉价路径产生的输出在外观上与正确答案别无二致。你的工作不是恳请它选择那条迂回路,你的工作是为那些至关重要的数字封死廉价路径,并让每一个存活下来的数字都带着它走过长路的证据。
会员专享
余下内容仅对会员开放。
会员可读完整内容 —— 每一个公开发布的观点背后,那些框架、决策与推理的全貌。
- —完整文章,包含未公开存档的部分
- —可落地的工作框架,附带权衡与决策依据
- —新文章抢先看,先于公开发布
随时取消 · 一次订阅,畅读全部