为什么 LLM 会产生幻觉?——token 级别的解释

LLM 之所以会产生幻觉,是因为它一次只写一个 token(一小块文本)------每次都挑一个"看起来接下来最可能出现"的 token。当它不知道正确的 token 是什么时,它也必须挑一个,于是一个看起来信心十足的猜测就这么出炉了。

在这篇博客里,我们将从 token 的层面理解 LLM 为什么会产生幻觉:token 是什么、LLM 怎么挑下一个 token、"尖锐猜测"和"平坦猜测"有什么区别、为什么模型既不能跳过 token 也不能收回 token、一个错误 token 如何演变成一整个错误答案,以及在真实世界里我们怎么减少幻觉。

我们将涵盖以下内容:

  • 什么是幻觉?
  • 什么是 token?
  • LLM 如何挑选下一个 token?
  • 简单 token 与事实 token
  • 模型知道时:尖锐猜测
  • 模型不知道时:平坦猜测
  • 用代码演示挑 token
  • 原因 1:没有"跳过"选项
  • 原因 2:随机性会从平坦猜测里挑出一个 token
  • 原因 3:token 一旦写出就无法收回
  • 原因 4:一个错误 token 引出更多错误 token
  • 原因 5:高概率 token 可以组合出根本不存在的东西
  • 原因 6:最终文本把不确定性藏起来了
  • 如何在 token 层面减少幻觉?

什么是幻觉?

幻觉(hallucination)是指 AI 给出了一个听起来正确且自信的答案,但它实际上是错的或者凭空编造的。

AI 不是在故意撒谎。它只是产出了一个"长得像真答案"的东西,而且带着十足的自信。

本文中,AI 指 LLM(大语言模型)。

假设我们问 AI:"作家 Meera Joshi 出生于哪一年?"

为了举例方便,假设 Meera Joshi 是一位没什么名气的作家,AI 从来没读过关于她的任何内容。一个谨慎的人类会说"我不知道"。但 AI 回答:"Meera Joshi 出生于 1962 年。"

这句话听起来很自信,但那个年份只是猜测。这就是幻觉。

我们会逐 token 地看清错误答案被生成的那个确切瞬间。为此,必须先理解 token 是什么。

什么是 token?

token 是 LLM 读取和书写的最小文本单元。

LLM 不像我们一样看到完整的单词。它把文本切成小块。一个 token 可以是一个完整的单词、单词的一部分、一个数字,甚至是"空格加单词"。

为了便于理解,看看我们那句话是怎么被切成 token 的:

复制代码
"Meera Joshi was born in 1962"

→ "Me" | "era" | " Joshi" | " was" | " born" | " in" | " 19" | "62"

可以看到:

  • "Meera" 被切成了两个 token:"Me" 和 "era"。
  • " was"、" born"、" in" 这种常见词各是一个 token。
  • 年份 "1962" 被切成了两个 token:" 19" 和 "62"。

具体怎么切取决于模型,但思路到处都一样:模型是一个 token 一个 token 地写出答案的。

补充:关于文本如何被一步步切分的机制,就是分词(Tokenization)。

注意:为了便于理解,本文余下部分把 "1962" 这样的完整年份当作一个 token 处理。核心思想完全不变。

现在,看看模型怎么决定下一个 token 是什么。

LLM 如何挑选下一个 token?

LLM 只反复做一件事:看着目前为止的所有文本,预测下一个 token。

但它不是只预测一个 token。它给自己认识的每一个 token 打分,这些分数会变成概率。也就是说,模型会生成一张猜测清单,每个猜测都带一个百分比。

拿个简单例子。假设目前的文本是:

复制代码
"The capital of France is"

模型为下一个 token 生成这样的猜测清单:

下一个 token 概率
" Paris" 92%
" a" 3%
" the" 2%
" located" 1%
其余所有 token 2%

然后,模型从清单里挑一个。这里它挑了 " Paris"。现在 " Paris" 被追加进文本,整个过程对下一个 token 再来一遍。

所以,写出一个答案的流程长这样:

  • 第 1 步:模型看着目前的文本。
  • 第 2 步:它为下一个 token 生成带概率的猜测清单。
  • 第 3 步:它从清单里挑一个 token。
  • 第 4 步:它把这个 token 加进文本。
  • 第 5 步:回到第 1 步。

这个循环一直跑到答案写完为止。

非常关键的一点:整个循环里没有任何一步叫"检查这是不是真的"。只有"挑一个可能出现的下一个 token"。这就是问题的根源。

简单 token 与事实 token

现在,回头仔细看那句幻觉句子:

复制代码
"Meera Joshi was born in 1962."

这句话里不是每个 token 都同样难。

" was"、" born"、" in" 是简单 token(easy token)。它们遵循语言规则,任何关于出生年份的句子都会有它们,模型几乎不会错。

" 1962" 是事实 token(fact token)。它承载真正的信息。要写对它,模型必须真的知道这个事实。

任何答案里,大多数 token 都是简单 token,事实 token 只有少数几个。但这少数几个 token 决定了答案的真假。

模型对两类 token 用的是完全相同的循环。它不会为事实 token 放慢速度,也不会切换到什么"谨慎模式"。它照样生成猜测清单、照样挑一个------跟挑 " was" 一模一样。

于是,事实周围那些自信的语法,让错误的事实看起来也自信了起来。

模型知道时:尖锐猜测

当模型在训练中见过某个事实很多次,它的猜测清单会变得尖锐(sharp guess):一个 token 几乎拿走全部概率。

假设目前的文本是:

复制代码
"Albert Einstein was born in the year"

下一个 token 的猜测清单长这样:

下一个 token 概率
" 1879" 95%
" 1878" 2%
" 1880" 1%
其余所有 token 2%

可以看到,一个 token 远远领先于其他所有 token。模型读过爱因斯坦成千上万次,这个事实被牢牢存在了它里面。

猜测尖锐时,模型几乎每次都能挑对 token。

模型不知道时:平坦猜测

现在回到我们那位没什么名气的作家。目前的文本是:

复制代码
"Meera Joshi was born in the year"

模型从来没读过关于她的内容,所以它的猜测清单长这样:

下一个 token 概率
" 1962" 14%
" 1958" 13%
" 1971" 13%
" 1965" 12%
" 1960" 12%
" 1968" 12%
" 1955" 12%
" 1974" 12%

可以注意到,概率几乎均匀摊开,没有任何一个 token 遥遥领先。这就叫平坦猜测(flat guess)。

平坦猜测是模型表达"我不确定"的方式。模型知道下一个 token 肯定是个年份------因为这类句子就该这样------但它完全不知道是哪一年。

用一个简单的类比理解:假设一个班 100 个学生都读过很多次爱因斯坦的资料。我们问:"爱因斯坦哪一年出生?"几乎所有人会齐声喊"1879"。这就是尖锐猜测。再问同一个班:"Meera Joshi 哪一年出生?"没人知道,于是每人喊一个不同的年份。这就是平坦猜测。

所以在 token 层面:

  • 尖锐猜测 = 模型知道。
  • 平坦猜测 = 模型不知道。

模型对自己的不确定性是有某种感知的,它就藏在这些概率里。但现在的问题是:模型拿到一个平坦猜测后会干什么?

答案是:它照样挑一个 token。我们用代码看它怎么做的。

用代码演示挑 token

学这个的最好方式就是上手。我们写一段 Python 代码,像 LLM 一样从猜测清单里挑 token:

python 复制代码
import random

sharp_guess = {"1879": 0.95, "1878": 0.02, "1880": 0.01, "other": 0.02}

flat_guess = {"1962": 0.14, "1958": 0.13, "1971": 0.13, "1965": 0.12,
              "1960": 0.12, "1968": 0.12, "1955": 0.12, "1974": 0.12}

def pick_next_token(guesses):
    tokens = list(guesses.keys())
    chances = list(guesses.values())
    # 挑一个 token,概率越高被挑中的次数越多
    return random.choices(tokens, weights=chances)[0]

print(pick_next_token(sharp_guess))
print(pick_next_token(flat_guess))

这里:

  • sharp_guess:爱因斯坦的猜测清单。一个 token 拿 95% 概率,"other" 代表其余所有 token 加在一起。
  • flat_guess:Meera Joshi 的猜测清单。概率摊得很开。
  • pick_next_token:挑一个 token 的函数,概率高的 token 被挑中的机会更多。

它会打印出类似这样的结果:

复制代码
1879
1971

如果把这段代码跑很多次:第一个 print 几乎每次都输出 "1879";第二个 print 却每次都在变------这次 "1962",下次 "1971",再下次 "1955"。

可以看到,这个函数永远会返回一个 token。它从不返回"我不知道"。哪怕面对平坦猜测,它也照样给我们一个年份。而当这个年份被写进句子后,它看起来跟 "1879" 一样自信。

这就是幻觉在单个 token 层面被生成的过程。

现在,逐个原因细看。

原因 1:没有"跳过"选项

在每一步,模型都必须从清单里挑一个 token。清单里是 " 1962"、" 1958" 这些 token,却没有任何一个特殊按钮写着"停,这个我不会"。

好比让学生做填空题,规则是每个空都必须填上字。哪怕完全不会,也得写一个词进去。他们的很多答案会看起来正确,实际上是错的。

LLM 在每一个 token 上都处在这种境地。

那么问题来了:"我不知道"这几个字本身也是 token,模型为什么不去挑它们呢?

模型只有在"我不知道"恰好是下一个高概率 token 时才会写它们。但这里有两个问题:

  1. 训练时,模型见过的"问题后面跟答案"的文本,远远多于"问题后面跟'我不知道'"的文本。
  2. 很多训练和评测方法,往往给自信的猜测打分更高,而不是给诚实的"我不知道"。

所以"我不知道"这些 token 通常只拿到很小的概率。

于是,当事实 token 的猜测是平坦的,模型还是会挑一个年份、一个名字或一个数字。它把空填上了。

原因 2:随机性会从平坦猜测里挑出一个 token

LLM 挑下一个 token 时通常带一些随机性,它并不总挑概率最高的那个。一个叫温度(temperature)的参数控制随机性的大小:

  • 低温度 = 模型几乎总挑最高概率的 token。
  • 高温度 = 模型更常挑其他 token。

面对尖锐猜测,随机性无关紧要:" 1879" 有 95% 概率,几乎每次都赢。

但面对平坦猜测,随机性就决定了答案。每个年份都只有约 12%~14% 的概率。所以同一个问题问五遍,可能每次得到不同的年份:

复制代码
Run 1: Meera Joshi was born in 1962.
Run 2: Meera Joshi was born in 1971.
Run 3: Meera Joshi was born in 1955.
Run 4: Meera Joshi was born in 1962.
Run 5: Meera Joshi was born in 1968.

可以看到,每个答案都写得信心十足,但答案之间互相打架。这种不一致是模型在瞎猜的强烈信号。

这时有人会说:"那把温度设成零不就行了?模型就永远挑最高概率的 token。"

没错,它现在永远挑 " 1962"。可 " 1962" 本来就只有 14% 的概率,它仍然是个猜测------只是变成了每次都一样的同一个猜测。

所以,低温度让答案每次相同,但不会让答案变正确。

原因 3:token 一旦写出就无法收回

我们手写东西发现错了,会用橡皮擦。

LLM 没有橡皮。一个 token 一旦被挑中并加进文本,就永远留在那里。模型只能往前走、继续加下一个 token。

举个例子。假设我们问模型:

复制代码
"Is 3,827 a prime number?"

答案的第一个 token 就是个重大决定。为了举例,假设猜测清单长这样:

下一个 token 概率
"Yes" 52%
"No" 48%

两个概率几乎持平。假设模型挑了 "Yes"。

但 3,827 不是质数------它是 43 × 89。

模型无法回头把 "Yes" 改成 "No"。错误的 token 已经写下了,之后的一切都建立在这个 "Yes" 之上。

原因 4:一个错误 token 引出更多错误 token

记住:每一步,模型看的都是目前为止的全部文本------包括它自己写的 token。它不会回头怀疑自己的 token,只是把它们当作必须接着往下写的文本的一部分。

所以,写下 "Yes" 之后,目前的文本变成了:

复制代码
"Is 3,827 a prime number? Yes"

模型基于这个文本预测下一个 token。而 "Yes" 之后最可能的延续,是一个支持 "Yes" 的理由。于是它写出:

复制代码
"Yes, 3,827 is a prime number because it cannot be divided by any number other than 1 and itself."

(是的,3,827 是质数,因为它除了 1 和自身没有其他因数。)

每个新 token 相对于前面的文本来说都是合理的高概率 token。语法正确,解释听起来有逻辑。但整个答案建立在开头那一个错误 token 上。

我们的作家也是同样情况:

复制代码
"Meera Joshi was born in 1962. She grew up in the 1970s and published her first book in the late 1980s."

模型没有在一个错误年份上停下,而是用 " 1962" 盖出更多细节:她在 1970 年代长大、在 1980 年代末出了第一本书。这些全都顺着 1962 推得顺理成章,也全是编的。

一个错误的事实 token 成了后续 token 的地基,一个小小的猜测长成了一整个虚构的故事。

原因 5:高概率 token 可以组合出根本不存在的东西

再看一类特殊的幻觉:假名字、假标题、假参考文献。

假设我们让模型推荐一篇某主题的论文。模型写出:

复制代码
"Sharma, A. and Patel, R. (2019). Using AI to Detect Crop Diseases. Journal of Agricultural AI."

逐 token 地看:

  • "Sharma" 是常见的作者姓氏,高概率 token。
  • "Patel" 也是常见的作者姓氏,高概率 token。
  • "2019" 是这类论文常见的年份,高概率 token。
  • "Using AI to Detect Crop Diseases" 作为这个主题的标题很自然,其中每个 token 都高概率。
  • "Journal of Agricultural AI" 听起来像个真实期刊名,高概率 token。

每个 token 单独看都挑得有道理。但假设这篇论文------正是这两位作者、正是这一年、正是这本期刊------在世界上根本不存在。

模型在乎的唯一一件事是:每个 token 和前面的 token 搭配得好不好。循环里没有任何环节检查"这个完整组合在真实世界里是否存在"。于是它把一堆高概率 token 组合成了一条不存在的参考文献。

这就是为什么 LLM 特别擅长产出"看起来很真、其实不存在"的参考文献。

原因 6:最终文本把不确定性藏起来了

我们已经知道,模型对自己的不确定性是有感知的:平坦猜测就意味着"我不确定"。

但模型挑完 token 之后,文本里留下的只有 token 本身,它背后的概率被丢掉了。

所以当我们读最终答案时,下面这两个看起来一模一样:

  • " 1879"------它有 95% 的概率。
  • " 1962"------它只有 14% 的概率。

它们都只是句子里的一个数字,都用同样自信的语气写出,第二个旁边并没有标一个小小的"14%"。

也就是说,模型内心不确定,但它的字面上看起来确定。而我们读者只能看到字面。所以光靠读,我们没有任何办法区分哪些部分是确知的、哪些部分是猜的。

如何在 token 层面减少幻觉?

现在看怎么减少幻觉。每个修复手段对应我们学过的一个原因。

修复 1:把事实喂给模型。

如果把正确信息直接放进问题里(比如贴一份文档),事实就成了"目前文本"的一部分,模型看得见。于是平坦猜测变成了尖锐猜测。

这正是 RAG(检索增强生成,Retrieval-Augmented Generation)登场的时刻。一句话概括:先找到正确的信息,再连同问题一起交给模型。

修复 2:让"我不知道"变成高概率 token。

构建模型的公司可以训练模型在不确定时说"我不知道",并给诚实的"我不知道"打比自信的错误猜测更高的分。这样当事实 token 的猜测变平时,"我不知道"这些 token 能拿到更大的概率。这对应原因 1。

修复 3:看 token 背后的概率。

很多 AI 工具能显示每个 token 背后的概率。如果一个事实 token(年份、名字)是以低概率被挑中的,我们就能标记它"很可能是猜的"。这把最终文本藏起来的不确定性找了回来。

同样,我们可以把同一个问题多问几遍(原因 2 里的做法):如果事实 token 在多个答案之间变来变去,说明模型在猜。这对应原因 6。

修复 4:让模型先思考再回答。

如果模型先把思考过程一步步写出来,关键决定就不依赖于开头那个孤零零的不确定 token 了。比如模型可以先把 3,827 除以各个小数试一遍,发现 43 × 89,然后才写 "No"。这不能完全解决问题,但给了模型更大的机会走到正确的 token 上。这对应原因 3 和原因 4。

修复 5:事实任务用低温度。

对于事实型任务,低温度减少了向低概率 token 的随机跳跃。但记住:它让答案每次相同,而不是正确。所以要和其他修复手段搭配用,不能单靠它。这对应原因 2。

修复 6:永远核查事实 token。

作为用户,我们现在知道了:名字、数字、日期、参考文献就是事实 token,幻觉最常出现在这些 token 上。所以这些地方是我们在相信一个答案之前必须反复核查的地方。

注意:这些修复手段没有一个是把幻觉彻底消灭的。只要模型还是靠"挑下一个高概率 token"来书写,就永远存在冒出自信猜测的可能。

到这里,我们应该已经理解了 LLM 为什么会在 token 层面产生幻觉:模型一次挑一个高概率 token,而当它不知道答案时,它也必须挑一个。

常见问题

幻觉发生时,LLM 是在撒谎吗?

不是。LLM 产生幻觉时并不是在故意撒谎。它每一步都在挑一个可能出现的下一个 token,当它不知道正确的 token 时,它也必须挑一个。结果就是一个听起来正确自信、实际错误或编造的猜测。

LLM 的答案里哪些部分最容易被幻觉?

事实 token------名字、数字、日期、参考文献------最容易被幻觉。而 " was"、" in" 这类简单 token 遵循语言规则,模型几乎不会错。事实 token 需要模型真的知道那个事实,所以这些是必须反复核查的地方。

怎么判断 LLM 正在瞎猜?

可以看每个 token 背后的概率,很多 AI 工具都能显示。如果一个事实 token(年份、名字)是以低概率挑中的,它很可能是猜的。也可以把同一个问题多问几遍,如果事实 token 在答案之间变来变去,说明模型在猜。

把温度设成零能杜绝幻觉吗?

不能。温度为零让模型永远挑最高概率的 token,于是答案每次相同。但如果最高概率的 token 本来概率就不高,它仍然是个猜测------只是每次都一样的同一个猜测。低温度让答案相同,不让答案正确。

幻觉能被彻底消除吗?

不能。RAG、训练模型说"我不知道"、检查 token 背后的概率等手段都能减少幻觉,但没有一个能彻底消除。只要模型还是靠挑下一个高概率 token 来书写,就永远存在冒出自信猜测的可能。

相关推荐
量化吞吐机1 小时前
最高最低都一样,价格就同样集中吗
人工智能·python
AI视频工具指南1 小时前
怎么用 AI 做一两分钟的小故事视频?从结尾倒推故事
人工智能·aigc·音视频
武子康1 小时前
ESP32-S3 分核后仍报 AFE 缓冲区满?先查输入合同
人工智能·后端·agent
Magician_liu1 小时前
认识感知机
人工智能·机器学习
xjxijd1 小时前
AI 安全进入爆发周期:智能体安全成下一阶段核心竞争高地
人工智能·安全·ai
江湖中的阿龙1 小时前
大模型应用怎么做评测?从样本集、自动评分到上线回归的完整实战
人工智能·python·回归·大模型评测
天天代码码天天2 小时前
让普通照片“动”起来:用 C# + Vulkan 做一个照片深度与景深小工具
人工智能
QYR-分析2 小时前
后置行车记录仪:8.6% 高增,车辆事故取证与全天候安防的后摄影像终端
人工智能
范中勤2 小时前
LangGraph Checkpointer 封装(下):with 的双层上下文与 MemorySaver 为什么不用 with
python·大模型·llm·agent·langgraph