你有没有想过,为什么 GPT-4 坚持说 9.11 大于 9.9?为什么 LLM 数不清 “strawberry” 里有几个 r?为什么有一个叫 “SolidGoldMagikarp” 的词能让模型精神崩溃?答案都指向同一个地方:tokenization。

Tokenization 不只是预处理

前三篇我们讲了 tokenization 的基础:BPE 怎么切词、不同算法的取舍、词表大小的影响。听起来像是一个「设置好就忘掉」的预处理步骤。

但事实远非如此。Tokenization 是 LLM 的视网膜——它决定了模型能「看到」什么。 如果视网膜有盲区,模型就会在这些盲区上犯系统性的错误。更危险的是,攻击者可以利用这些盲区来绕过安全防线。

这一篇,我们来看 tokenization 的阴暗面。

第一幕:数学灾难——为什么 LLM 算不对数

9.11 > 9.9?模型的数字困惑

2024 年初,一个看似简单的问题在社交媒体上引发热议:GPT-4 声称 9.11 大于 9.9。

这不是模型「不聪明」——而是它根本看不到你看到的东西

当你写 9.11 时,你看到的是数字 9.11(九点一一)。但模型看到的是三个 token:9 + . + 11。而 9.9 被切成 9 + . + 9

模型的「推理」变成了:小数点后面,119 哪个大?11 > 9,所以 9.11 > 9.9。

这不是推理错误,是感知错误。 模型从未接收到「9.11 是一个数值」这个信息——它收到的是三个独立的符号碎片。

大数的崩溃

问题在小数字上还不明显。但一旦数字超过 4-5 位,灾难性的切分就开始了:

你写的 模型看到的 token 后果
42 [42] ✓ 单 token,没问题
127 [127] ✓ 还行
1287 [12][87] ⚠ 数值结构丧失
31415 [31][415] ⚠ 不是按位切的!
1000000 [100][0000] ⚠ 百万 = 100 + 0000?
你看到的 31415926 一个完整的数字 (π×10⁷) BPE 切分 模型看到的 314 159 26 三个毫无数学关联的碎片 后果:模型无法进行进位、对齐、位值运算 加法 31415926 + 1 可能得到完全错误的结果

DeepMind 的研究证实:token 边界与数位边界的不对齐,是 LLM 数学推理失败的主要驱动力。 不是模型笨——是它看不见数字的结构。

“strawberry” 里有几个 r?

这是 2024 年最广为人知的 LLM 失败案例。ChatGPT 反复声称 “strawberry” 里有 2 个 r。

原因很简单:模型看到的不是 s-t-r-a-w-b-e-r-r-y 这 10 个字母,而是:

["str", "aw", "berry"]

三个不透明的 token。模型需要「知道」str 里面包含一个 r、berry 里面包含两个 r——但这种子 token 内部结构的知识,在训练中并不总能被可靠地学到。

这揭示了一个根本性限制:LLM 在 token 级别操作,而字符级别的任务(数字母、反转字符串、回文检测)需要比 token 更细的粒度。

↑ 点击标签切换演示 | "下一步"逐步观察 | 注意数字如何被错误切分

第二幕:Glitch Token——词表里的幽灵

SolidGoldMagikarp 事件

2023 年 2 月,研究者发现了一个惊人的现象:GPT 的词表中存在一些「幽灵 token」——它们在训练数据中出现过(所以被 BPE 加入了词表),但在后续微调阶段几乎没有被见到过。

这些 token 包括:SolidGoldMagikarpattRotTheNitromeFanStreamerBot 等看起来莫名其妙的字符串。

当你强制模型处理这些 token 时,会发生以下诡异行为:

  • 模型拒绝重复这些词(”I cannot say that word”)
  • 模型陷入循环,反复输出相同内容
  • 模型声称自己不是 AI
  • 模型产生完全不连贯的胡言乱语
  • 模型表现出「存在恐惧」(”I’m afraid”)

为什么会这样?

想象一下:你的大脑中有一个「概念槽位」,但这个槽位从未被真正训练过。当信号被路由到这个未初始化的区域时,输出就是随机的、不可预测的。

正常 Token "hello" 训练充分的嵌入 有意义的输出 Glitch Token "SolidGoldMagikarp" 未训练的嵌入 ⚠️ 🔥 不可预测行为 循环/拒绝/乱码 根因:Tokenizer 在数据 A 上训练(包含该词),模型在数据 B 上微调(不包含该词)→ embedding 区域未初始化

根因分析:

  1. Tokenizer 在大规模语料(如 Reddit、GitHub)上训练 → 学到了这些用户名/特殊字符串
  2. 模型 在筛选后的微调数据上训练 → 这些 token 几乎从未被见到
  3. 结果:词表里有这个 token 的「位置」,但 embedding 空间中对应的区域几乎没有被优化过

这就像一栋大楼里有一间房间,门牌号存在,但里面从未装修——进去之后什么都可能发生。

后续发展

  • GlitchProber(2024):用 PCA 分析中间层激活,发现 glitch token 在 embedding 空间中远离正常聚类
  • 梯度方法挖掘(arXiv 2410.15052):用梯度优化系统性地发现未训练 token
  • 现代模型(GPT-4o、Claude 3)已经通过更好的训练覆盖修复了大部分 glitch token

第三幕:Token Smuggling——安全绕过攻击

安全过滤器的盲区

大多数 LLM 的安全系统在两个层面工作:

  1. 输入过滤:检查用户输入是否包含有害内容(关键词匹配、分类器)
  2. 输出过滤:检查模型输出是否包含有害内容

问题是:输入过滤通常在原始文本上操作,而模型在 token 上操作。 如果攻击者能让同一段文本在两个层面上有不同的「解读」,就可以绕过过滤。

攻击向量

1. Unicode 同形字攻击

用视觉上相同但编码不同的字符替换:

  • 拉丁字母 a(U+0061)→ 西里尔字母 а(U+0430)
  • 视觉上完全相同,但 tokenizer 会产生不同的切分
  • 安全过滤器的正则表达式匹配失败

2. 零宽字符注入

在关键词中插入零宽字符(U+200B、U+FEFF):

  • 人眼看不到任何区别
  • 但 tokenizer 会在零宽字符处断开,生成不同的 token 序列
  • 过滤器检测不到完整的违规词

3. 非标准切分利用(ACL 2025 论文 “Adversarial Tokenization”)

研究发现:即使文本被「异常」tokenize(不是标准 BPE 的贪婪切分),LLM 仍然能理解语义。攻击者利用这一点:

  • 用非标准的编码方式写出有害指令
  • 安全分类器无法识别(因为关键词被打散)
  • 但模型能「拼回来」理解意图
Token Smuggling 攻击流程 攻击者输入 ha​rm​ful(含零宽字符) 安全过滤器 ✓ 未检测到违规词 Tokenizer ["ha","rm","ful"] LLM 理解语义 → 执行 ⚠️ 对比:正常输入 正常输入 harmful 安全过滤器 🚫 拦截!检测到违规词 核心漏洞:安全过滤器和 LLM 对「同一输入」的理解不一致——过滤器看字符串,模型看语义

RAG 毒化与 Glitch Token DoS

OWASP 发现了另一种攻击路径:将 glitch token 注入 RAG(检索增强生成)的知识库。当模型检索到包含这些 token 的文档段落时,可能产生不连贯输出——实现拒绝服务攻击。

第四幕:Tokenization 意识——模型在「自我觉察」

模型知道自己被切词了吗?

2024 年的一项研究发现了一个令人惊讶的现象:LLM 在第一层就已经发展出了「tokenization 意识」——它学会了编码「输入是如何被切分的」这个元信息。

这意味着模型并非完全对自己的 tokenization 无知。它在某种程度上「知道」当前 token 是否是一个完整单词、是否是一个词的开头/中间/结尾。

但这种意识是有限的——它不足以可靠地完成字符级任务。就像你能感觉到自己在呼吸,但不能精确控制每一块肋间肌。

这意味着什么

Tokenization 的这些「阴暗面」揭示了几个深层问题:

  1. 感知瓶颈:模型的推理能力受限于它的「感知分辨率」——你不能在看不见的东西上做推理
  2. 安全的脆弱性:任何基于字符串匹配的安全措施,都可能被 tokenization 层面的操作绕过
  3. 训练与词表的不对称:词表来自数据集 A,模型训练在数据集 B,对不上的部分就是安全漏洞
  4. Tokenization ≠ 中性预处理:它主动塑造了模型的认知边界

下一篇预告

如果文本的 tokenization 已经这么复杂,那图像、音频、机器人动作、甚至 DNA 序列呢?下一篇我们将看到,「token」这个概念已经远远超越了文字——万物皆可 token,这正在催生 AI 的大统一时代。