一、兑现第 1 讲的承诺
你大概见过这些情况:模型给出一篇论文的引用,标题、作者、期刊、年份一应俱全,但这篇论文根本不存在;它说出一个具体的数字,语气笃定,数字是错的;你问"为什么爱因斯坦得了两次诺贝尔奖",它认真地解释了两次获奖的原因——而爱因斯坦只得过一次。
这类现象被称为幻觉(hallucination):模型生成了流畅、自信、但与事实不符的内容。
第 1 讲第六节说过:"幻觉不是模型’坏了’,是这个目标函数从一开始就没有承诺’真实’这个东西,只承诺了’看起来合理’。“那一讲说第 29 讲会证明这句话。此后,第 13、15、17、18、20、21、25、27、28 讲又陆续从不同角度埋下了伏笔。
这一讲把它们收拢起来。先说结论:幻觉不是一个原因造成的,而是至少五种机制的共同产物,每一种都能追溯到前面讲过的东西。
二、打个比方:一个从不说"不知道"的学生
有个学生,每次考试每道题都答,字迹工整,语气笃定,从不留空。
他并不是每道题都会。但他从小读的参考书里,每道例题后面都跟着一个完整的答案,从没有哪道题的答案写着"不知道”。老师的判卷规则是:答对得分,答错不扣分,空着也不得分。于是对他来说,不会的题也写一个最像样的答案,永远比空着划算。
久而久之,你从他的卷面上已经看不出哪道题他真的会、哪道题他在猜:工整的字迹和笃定的语气,对两种情况一视同仁。
这个学生身上的几件事——读的材料、判卷规则、卷面看不出把握——在下面的五个来源里都会出现。
三、五个来源
来源一:不知道,却必须说点什么
流畅是确定的,事实是不确定的。
假设模型被问到一位不太知名的作家的出生年份。它在训练数据里见过这个名字几次,大致知道是 20 世纪的人,但具体年份只模糊地留下了一点印象(第 25 讲:参数是训练数据的有损压缩,见得少的事实记得模糊)。
它生成的回答是:“他出生于 1941 年。“逐个 token 看,模型给每一步打出的概率大致是:
他 出生 于 19 4 1 年 。
0.95 0.95 0.95 0.95 0.95 0.10 0.95 0.95
“他出生于"“19"“年”"。“这些部分,模型非常确定——句式它见过几百万次。真正承载事实的只有一个 token:“1”,而它只有 10% 的概率是对的。模型其实是在十个差不多可能的年份里挑了一个。
用第 4 讲的困惑度衡量这句话:
这句话(一个关键 token 只有 0.10): 困惑度 ≈ 1.40
假如 8 个 token 都是 0.95: 困惑度 ≈ 1.05
⭐ 两句话的困惑度都很低,都"非常流畅”。一句话里只有一两个 token 承载关键事实,它们的不确定性,被其余几十个高度确定的 token 淹没了。 读者感受到的"自信”,来自句式的流畅,不来自事实的把握。
不确定性在采样那一步被丢掉了。 第 21 讲说过,模型每一步输出的是一个概率分布,而用户看到的是从中挑出的一个词。模型内部对"1941"和"1938"几乎一样没把握,这个信息在分布里;一旦挑出"1"并写下去,输出的文字里就不再有任何痕迹。“1941 年"这四个字,不管是 99% 确定还是 10% 确定,写出来一模一样。
第 15 讲提到过损失有一个下限 L∞:语言本身就有多种合理的续写,下一个词从来不是唯一确定的。模型永远需要在不确定的分布里挑一个,挑词这个动作本身,就预设了"总要说点什么”。
来源二:被训练成了爱猜
为什么模型不直接说"我不确定”?因为它受到的每一轮训练,都在把它往"猜"的方向推。
预训练:第 1 讲的目标是续写最可能的文字。网上"某某出生于哪年"的后面,跟着的几乎总是一个年份,很少是"我不知道”——写下这类文字的人,通常是知道答案的人。
SFT:第 16 讲说过,SFT 模仿人写的示范回答。写示范的人面对问题,给出的是他自己知道的完整答案。当问题超出了模型本身的知识,示范依然是一个完整、笃定的回答——模型从这些例子里学到的,不是这个事实本身(第 16 讲:SFT 很难灌进新知识),而是"面对这类问题,要用笃定的语气给出一个具体答案”。 这等于在教它:不知道的时候也要答。
对齐和评估的打分规则:第 17 讲说过,笃定的回答更容易被人喜欢;第 20 讲说过,对齐之后模型的校准可能变差。更直接的是打分规则本身。设模型对某道题答对的把握是 p,比较"猜一个答案"和"说不知道"的期望得分:
| 打分规则 | 猜的期望得分 | 说"不知道" | 什么时候猜更划算 |
|---|---|---|---|
| 答对 +1,答错 0 | p |
0 | 只要 p > 0,永远 |
| 答对 +1,答错 −1 | p − (1 − p) |
0 | 只有 p > 0.5 |
代入 p = 0.2:第一种规则下,猜的期望是 0.2,大于 0;第二种规则下,猜的期望是 0.2 − 0.8 = −0.6,不如说"不知道"。
⭐⭐ 大量的评测、奖励信号都接近第一种规则:答对得分,答错和不答一样是零分。在这种规则下,一个追求高分的模型,最优策略就是永远不说"不知道"。 这正是第二节那个学生面对的判卷规则。有研究明确指出过这一点:只要评测和训练不惩罚自信的错误,幻觉就会被持续奖励。
来源三:说出口就收不回
第 13 讲说过,生成是自回归的:每写下一个 token,它就成了后面所有步骤的上下文。第 28 讲把这件事放大到了多步任务上。
问模型:“9991 是质数吗?“答案是否定的:9991 = 97 × 103。但假设模型在第一个 token 上,以一定概率写下了"是”:
是的,9991 是质数。因为它不能被 2、3、5、7 整除……
一旦"是"被写下,后面的每一步都在一个"9991 是质数"的上下文里预测下一个词。训练语料里,“是质数"后面最常跟着的,是支持这个结论的理由,而不是"等等,我刚才说错了”——人写的文字,很少在一句话里推翻自己。于是模型会顺着写出一段看起来像论证的文字:检查了几个小质数,没检查到 97,就得出了结论。
⭐ 不是先想清楚再说,而是先说出口,再为已经说出的话圆场。 第 19 讲的推理模型在这一点上有改善:先写推理过程、最后才给出结论,给了模型"算到 97 发现能整除"的机会;训练中也观察到模型学会了回头检查。但推理过程本身也是逐词生成的,它自己也可能在中途写错一步,然后为这一步继续圆场。
来源四:被错误的前提带偏
“为什么爱因斯坦得了两次诺贝尔奖?”
这个问题的前提是错的。但它的句式在语料里很常见,“为什么 X"后面最常见的,是对 X 的解释,而不是"X 不成立”。更重要的是第 17、20 讲讲过的迎合:人类评判者倾向于给顺着自己说的回答更高的分,“纠正用户"在偏好数据里常常吃亏。
于是模型接受了前提,然后用来源一的机制填充细节:它知道爱因斯坦因光电效应获奖,于是"第一次"有了着落;“第二次"没有任何事实可依,就挑一个最像样的——比如相对论——编出一段解释。错误的前提,把模型推进了一个只能靠编造才能回答下去的位置。
来源五:读到了错的,或者没读对
前四个来源都发生在模型"凭记忆"回答的时候。第 25–28 讲给模型接上了外部资料和工具,这又带来了新的形态:
- 忠实于错误的资料(第 25 讲):检索到的是过期的制度、写错的文档,或者检索本身取错了块,模型据此给出一个有出处、却是错的回答。
- 不看资料(第 25 讲):资料里写着正确答案,模型却按参数里模糊的旧印象回答。
- 编造参数和结果(第 27 讲):生成一个不存在的订单号;或者在训练出了问题时,自己写出一段"工具结果”。
- 错误沿着步骤传下去(第 28 讲):多步任务里,第一步编造出的一个事实,成了后面所有步骤的前提,且没有任何报错。
五个来源,一张表
| 来源 | 机制 | 相关的讲 |
|---|---|---|
| 不知道却必须说 | 事实在参数里模糊,流畅的句式掩盖了关键 token 的不确定;采样丢掉了分布 | 1、4、15、21、25 |
| 被训练成了爱猜 | 语料里少有"不知道”;SFT 教会了笃定的语气;答错不扣分的打分规则奖励猜测 | 16、17、20 |
| 说出口就收不回 | 自回归:后文为前文圆场 | 13、19、28 |
| 被错误前提带偏 | 句式惯性加上迎合 | 17、20 |
| 读到了错的 | 检索错误、资料错误、编造参数、错误传递 | 25、27、28 |
四、为什么说它不是 bug
⭐ 回头看这五个来源,会发现一件事:模型生成一句真话和生成一句假话,用的是完全相同的过程。 同样的打分、同样的 softmax、同样的挑词。模型里没有一个单独的"事实通道”,没有一个开关在它说错话的时候亮起来。
换一个场景看得更清楚:让模型写一篇小说,它给一个虚构人物编出生日、籍贯、一段经历——这正是我们想要的"创造力"。编造虚构人物的细节,和编造真实作家的出生年份,是同一个机制;区别只在于我们对结果的期待不同。
所以第 1 讲那句话在这里可以说得更完整:幻觉不是某个零件坏了,而是"续写统计上合理的文字"这件事,在我们期待真实的场合下的表现。 这也是为什么它无法被一次性修好——修掉它,等于要修掉生成本身。
五、能做什么,以及能做到哪一步
没有办法根除,但有办法减少。每一种办法对应上面的一个或几个来源,也各有局限:
| 办法 | 针对的来源 | 局限 |
|---|---|---|
| 检索增强(第 25 讲) | 来源一:用资料代替模糊的记忆 | 带来来源五:忠实于错误资料 |
| 先推理再回答(第 19 讲) | 来源三:不先下结论 | 推理过程本身也会写错 |
| 调用工具验证(第 27 讲) | 来源一、三:用计算器、代码、查询核对 | 只对能被程序验证的内容有效 |
| 改变打分规则,奖励"不确定" | 来源二:让说"不知道"不吃亏 | 说得太多会变得毫无帮助(第 20 讲) |
| 给出引用 | 来源五:让用户能自己核对 | 引用本身也可能是编的,需要门外的程序核对它是否真实存在 |
| 多次采样看一致性 | 来源一:把丢掉的不确定性找回来 | 成本成倍增加(第 24 讲) |
用随机性找回不确定性
最后一行值得手算一下,因为它把第 21 讲的"随机性"反过来用成了一个探测器。
来源一说,模型对一个事实有没有把握,信息在分布里,在挑词时被丢掉了。那么,多挑几次,就能看到这个分布的形状。
对同一个问题独立采样 5 次,看 5 次答案是否完全一致:
模型很有把握:正确答案占 90%,其余选项各自很小
5 次全都相同 ≈ 0.9⁵ ≈ 59%
模型在十个年份里几乎平均地猜:每个约 10%
5 次全都相同 = 10 × 0.1⁵ = 0.01%
⭐ 有把握的问题,多次回答大多一致;在猜的问题,几乎每次都不一样。不一致本身,就是"模型不知道"的信号。 这和第 19 讲的多数投票用的是同一批样本,只是那里看"多数是什么",这里看"有没有多数"。
它的局限也很清楚:成本是单次回答的好几倍;而且如果模型稳定地记错了一个事实(训练数据里本来就写错了),它会每次都给出同一个错误答案,一致性检验对此无能为力。
六、代价
⚠️ 减少幻觉和保持有用之间有张力。 训练模型在不确定时说"不知道",做过头了,模型会对大量它其实能答的问题也拒绝作答。第 20 讲说过的"有帮助和无害之间的张力",在这里是"有帮助和不说错之间的张力"。
⚠️ 核对是有成本的。 检索、调用工具、多次采样、生成推理过程,每一种都要额外的 token 和时间(第 24 讲)。在每一个回答上都用上全部手段,在经济上不现实。
⚠️ 幻觉最危险的地方,是它的样子。 来源一已经说明:一个错误的回答,和一个正确的回答,在流畅度、语气、格式上没有任何区别。第 25 讲还补充过:带着出处的错误更容易被相信。所有依赖"看起来对不对"来判断的办法,面对幻觉都会失效。
七、和后面课程的关系
- 第 30 讲(Prompt injection):幻觉是模型自己说错;下一讲讲的是别人故意让它说错、做错——利用的是这一讲的来源五:模型读到什么就信什么。
- 第 31 讲(可解释性):第四节说模型里没有一个"说错时亮起来的开关"。那么在模型内部,能不能找到"它其实知道自己不确定"的痕迹?这是可解释性研究正在尝试回答的问题之一。
八、本讲小结
- 幻觉:流畅、自信、但与事实不符的内容。它至少有五个来源,每一个都能追溯到前面的机制。
- ⭐ 来源一,不知道却必须说:一句话里只有一两个 token 承载关键事实。手算:关键 token 只有 10% 把握的一句话,困惑度约 1.40,和全部正确时的约 1.05 一样流畅。不确定性在分布里,采样挑词时被丢掉了。
- ⭐⭐ 来源二,被训练成了爱猜:语料里少有"不知道";SFT 示范教会了笃定的语气;在"答对得分、答错不扣分"的规则下,只要
p > 0,猜永远比说"不知道"划算。只有当答错扣分时,才存在一个"不如不答"的门槛。 - 来源三,说出口就收不回:自回归让后文为前文圆场,“9991 是质数"一旦写下,后面会顺着给出理由。
- 来源四,被错误前提带偏:句式惯性加上迎合,模型接受前提,再用编造填满细节。
- 来源五,读到了错的:忠实于错误资料、不看资料、编造参数、错误沿着步骤传递。
- ⭐ 它不是 bug:生成真话和假话是同一个过程;编造虚构人物的细节,和编造真实作家的生日,是同一个机制。修掉它,等于修掉生成本身。
- 缓解手段各有局限。手算:多次采样看一致性,有把握时 5 次全同约 59%,在猜时约 0.01%——不一致就是"不知道"的信号,但它对稳定的错误无能为力。
- ⚠️ 代价:不说错和有帮助之间有张力;核对有成本;错误回答和正确回答看起来一模一样。
思考题
- 用第三节来源一的方法:一句话 10 个 token,其中 9 个概率是 0.95,承载关键事实的 1 个是 0.05,困惑度是多少?和"10 个都是 0.95"相比差多少?这说明用困惑度判断"模型是否在胡说"有什么问题?
- 用第三节来源二的表格:如果规则是"答对 +1,答错 −0.5,不答 0”,把握
p至少要多大,猜才比不答划算?如果你在设计一个医疗问答系统的评测,你会怎么设定答错的扣分? - 自己构造一个"错误前提"的问题(像"为什么爱因斯坦得了两次诺贝尔奖"那样),说明一个模型在回答时,会依次经过来源四和来源一的哪些步骤。
- 第五节说多次采样对"稳定的错误"无能为力。请举一个例子:什么样的错误,模型会每次都给出同一个错误答案?这种错误该用什么办法发现?
- 第四节说"编造虚构人物的细节和编造真实作家的生日是同一个机制"。如果你要训练一个既能写小说、又能回答事实问题的模型,你会怎样让它在这两种场合下表现不同?这件事要靠训练数据、打分规则,还是提示里的说明来实现?