AI 输出了不存在的事实——怎么发现与减少幻觉

AI 自信地编出错误论文引用、不存在的 API 函数、差一个数量级的数字——幻觉集中在"要事实"和"没源头"的缺口处。本文用检索、源材料锚定、不确定标注三招堵上。

你让模型查一篇具体论文、一个函数签名、或者上季度的营收数字,它自信地给你一个答案,结果是错的——引用打不开、SDK 里没这个函数名、数字差了一个数量级。更糟的是你追问”确定吗”,它又造一条更像样的假引用。幻觉不是随机噪声——它集中在”需要事实”和”没有源头”之间的缺口处。本文梳理触发幻觉的 prompt 形状,以及用检索、源材料锚定、显式不确定标注三种方式把缺口堵上。

常见原因

按命中率排序。

1. 让模型给事实,但没喂源、也没开检索

如果你问 "Postgres GIN 索引查找的时间复杂度是多少?" 而模型没有 web 工具、没有粘贴文档、也没有 grounding,它只能从训练记忆里猜。猜常常接近但不完全对。模型不会主动说”我没文档”——它会编一个听起来合理的数字。

如何判断:你的 prompt 提到了具体实体(论文、函数、数字、日期),却没有给模型任何查验的途径。

2. 要”完整""全面”的列表

"列出所有 React hooks""给我每一种 Cloudflare Workers 绑定类型" 这种 prompt 触发”补全”行为。模型写 10 个真的、再编 2 个假的让列表看起来完备。训练集里真实清单很少正好是 N 项,模型会补。

如何判断:输出条数可疑地是整数(正好 10 条、正好 7 条),列表末尾几项看起来空泛。

3. 训练 cutoff vs 近期变化

你问的是某个库版本、API 变更、或定价层,而它发布在模型 cutoff 之后。模型会用 cutoff 之前的状态回答,并当成现状呈现。

如何判断:话题在过去 6-12 个月里有变化——版本、价格、模型名、deprecation。

4. 没命令模型标注不确定

chat 模型默认行为是产出流畅答案,而不是承认无知。没有 "不确定就说不知道" 的指令,模型会用听起来合理的字符串填空。

如何判断:回答里从未出现”我不确定”、“我无法验证”、“基于可能过时的训练数据”等字样。

5. 长上下文稀释 grounding

即使你粘了源材料,如果 prompt 有 8k tokens 而源在第 1 页,模型生成到第 4 页时可能输出与源相矛盾的内容。长上下文里 attention 不是均匀分布的。

如何判断:源材料在 prompt 里,回答里却出现源中没有的论断。

6. 追问反而触发更深的编造

当你说 "确定吗?",模型常会编一条听起来更确凿的引用,而不是退一步。RLHF 奖励的是”答得自信”。

如何判断:第二轮的引用比第一轮更具体(也更假)。

动手前先确认

  • 确认幻觉是稳定复现还是偶发;同一 prompt 跑两次。
  • 记录完整 prompt、模型、以及 system prompt 或源材料。
  • 把错误输出原样保存,与修正后版本对比。
  • 记下当时是否开了工具(web 搜索、代码执行、文件检索)。
  • 判断话题是否对时间敏感(版本、定价、新闻)。

需要收集的信息

  • 完整 prompt 文本和 system prompt。
  • 模型名称、版本、temperature、tool-use 设置。
  • 错误事实原文,以及来自一手源的正确答案。
  • 当时是否能用检索、web 搜索或文件上下文。
  • 模型 cutoff 时间与话题时效性的对比。

最短修复路径

按收益排序。

Step 1:粘贴源材料,不要依赖记忆

"Stripe API 在支付失败时返回什么?" 替换成”先粘文档、再加约束”:

源(Stripe 文档片段,下方):
<粘贴相关段落>

问题:Stripe 在支付失败时返回什么?
规则:
- 只用上方文本。
- 文本中没有就写 "NOT IN SOURCE"。
- 引用你用到的原话。

模型没有可以编造的空间了。

Step 2:开启检索/工具调用

ChatGPT 开 web 搜索。Claude 上传文件或挂 connector。API 调用启用 tool use 加搜索工具。没有检索时,冷门或新话题的事实题就是抛硬币。

Step 3:加显式不确定标签

事实密集的 prompt 都加上:

对每条非琐碎论点,附置信标签:
- [VERIFIED] 你能在本次对话中引用源材料。
- [LIKELY] 与训练记忆吻合但无法引用。
- [UNCERTAIN] 你在猜。
没有引用过的源就不许打 [VERIFIED]。

把”无声幻觉”变成”可见的不确定”。

Step 4:代码题,要可运行工件

"OpenAI Python SDK 怎么做流式响应?" 换成:

用 openai==1.40.0 写一段可运行的 Python 脚本。
含完整 import。
末尾列出你用到的所有方法、类、参数,并逐项标 VERIFIED-FROM-DOCS 或 UNCERTAIN。

然后实际跑一遍。AttributeError 报错说明模型编了方法名。

Step 5:每个具名实体都对照一手源

输出里每个论文标题、函数名、URL、数字,都要回到一手源核对:官方文档、论文页、GitHub repo、公司 changelog。把模型的自信度当成零信号。

Step 6:不要”争”——重置并加 grounding

模型给了假引用,你说”确定吗”,大概率拿到一个更精致的假引用。改成新开一轮:“我找不到 X。请贴出你看到的 URL 或章节号。如果给不出,标 UNCERTAIN 然后停下。“

怎么确认已经修好

  • 输出里每条非琐碎论点都有可引用源或 UNCERTAIN 标签。
  • 跑代码不报 AttributeErrorImportError、或 404。
  • 第二个模型或搜索引擎能交叉验证。
  • 同一 prompt 重跑两次,事实论断稳定一致。

如果还是没修好

  • 换有检索/grounding 的模型(Perplexity、开 web 的 ChatGPT、开 web 搜索的 Claude)。
  • 缩小问题——把”告诉我关于 X 的一切”拆成 5 个小事实题。
  • 法律 / 医疗 / 财务等领域,别用通用 chat 模型,用带引用的领域工具。
  • 话题晚于 cutoff,就接受”未验证答案都是猜”,必须外部查。

预防建议

  • 默认尾缀:"每条非琐碎论点标 [VERIFIED] / [LIKELY] / [UNCERTAIN]。"
  • 写代码的 prompt 一定钉死库 + 版本。
  • 事实密集任务用 grounded 模型,推理 / 写作用 chat 模型。
  • 不要无条件接受模型在追问后给的”新引用”,必须独立验证。
  • 养成”跑代码、点 URL、翻到引用页”再相信任何输出的习惯。

相关阅读

标签: #排查 #Prompt #Prompt 质量 #幻觉