Skip to content

从 Token 到 Tokenizer:大模型如何把文本变成计算 ​

使用大模型时,经常会看到几个词:token、tokenizer、embedding、Q/K/V、attention。它们看起来像是分散的概念,但其实处在同一条处理链路上。

一段文本进入模型,大致会经历下面的过程:

text
原始文本
  ↓
Tokenizer 切分
  ↓
Token ID
  ↓
Embedding 向量
  ↓
Q / K / V
  ↓
Attention
  ↓
预测下一个 token

模型不是直接“阅读”字符串,而是把文本先拆成 token,再把 token 转成数字和向量,最后在 Transformer 里做矩阵计算。理解这条链路,是理解大模型上下文长度、推理成本、生成过程和缓存机制的基础。

本文从 token 开始,逐步拆解文本是如何变成模型可以计算的内容。

一、什么是 Token ​

Token 是大模型处理文本的基本单位。

它不一定是一个字,也不一定是一个完整的词,而是 tokenizer 根据词表和切分规则得到的文本片段。

例如中文句子:

text
我喜欢机器学习

可能被切成:

text
["我", "喜欢", "机器", "学习"]

英文句子:

text
I love machine learning

可能被切成:

text
["I", " love", " machine", " learning"]

有些词还会被拆成更小的子词:

text
unbelievable

可能变成:

text
["un", "believ", "able"]

所以,token 更准确的定义是:模型词表中的一个文本片段。

不同模型使用的 tokenizer 不同,同一句话切出来的 token 也可能不同。这也是为什么不同模型对同一段文本的 token 数统计不一定完全一致。

二、Token 有什么用 ​

Token 的作用不是为了符合人类的分词习惯,而是为了让文本进入神经网络计算。

2.1 把文本变成数字 ​

神经网络不能直接处理字符串。模型真正接收的是数字。

例如:

text
["我", "喜欢", "猫"]

会被映射成:

text
[1024, 5832, 901]

这里的每个数字就是 token ID。模型内部有一张词表,记录了 token 和 ID 的对应关系。

2.2 决定上下文长度 ​

大模型的上下文窗口通常按 token 计算,而不是按字数、字符数或单词数计算。

例如一个模型支持:

text
128k tokens

意思是输入和输出加起来最多可以容纳大约 128k 个 token。

这也是为什么有时一段中文、英文、代码、JSON 在模型里占用的 token 数差异很大。它们经过 tokenizer 后的切分密度不同。

2.3 影响推理成本和速度 ​

token 越多,模型需要处理的序列越长,推理成本也越高。

在 Transformer 中,attention 需要计算 token 之间的关系。序列越长,计算量和显存压力越明显。实际使用大模型 API 时,费用通常也和输入 token、输出 token 数量直接相关。

2.4 作为生成的基本单位 ​

大模型生成文本时,本质上是在不断预测下一个 token。

例如当前上下文是:

text
我 喜欢

模型可能预测下一个 token 是:

text
猫

然后上下文变成:

text
我 喜欢 猫

模型继续预测下一个 token。最终,我们看到的是一段完整文本,但模型内部是一个 token 一个 token 地生成。

三、什么是 Tokenizer ​

Tokenizer 是分词器,也可以理解为文本编码器。

它负责两件事:

text
文本 -> token -> token ID
token ID -> 文本

前者叫编码,后者叫解码。

例如:

text
我喜欢 AI

经过 tokenizer 后,可能得到:

text
tokens: ["我", "喜欢", " AI"]
ids:    [1024, 3881, 9274]

模型真正接收的不是 "我喜欢 AI" 这个字符串,而是 [1024, 3881, 9274] 这样的数字序列。

Tokenizer 的设计要解决一个平衡问题:

text
切得太细:序列很长,计算成本高。
切得太粗:词表很大,遇到新词和罕见词很难处理。

现代大模型通常使用子词级 tokenizer。常见词可以作为完整 token,罕见词可以拆成更小片段,从而兼顾词表规模和泛化能力。

四、一个输入是怎么变成 Token 的 ​

以这句话为例:

text
我喜欢猫

第一步,tokenizer 根据自己的规则切分文本:

text
["我", "喜欢", "猫"]

第二步,查词表,把 token 转成 ID:

text
[1024, 5832, 901]

第三步,模型通过 embedding 表把 ID 转成向量:

text
1024 -> [0.12, -0.31, 0.88, ...]
5832 -> [0.45, 0.09, -0.20, ...]
901  -> [-0.11, 0.73, 0.34, ...]

这些向量才是 Transformer 真正处理的输入。

可以把 embedding 理解成 token 的语义坐标。相似 token 在向量空间中可能更接近,但这个“语义”不是人工指定的,而是在大规模训练中学出来的。

五、Tokenizer 怎么用 ​

以 Hugging Face Transformers 为例,可以这样加载 tokenizer:

python
from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("bert-base-chinese")

text = "我喜欢机器学习"
encoded = tokenizer(text)

print(encoded)

输出可能类似:

python
{
    "input_ids": [101, 2769, 1599, 3614, 3322, 2110, 739, 102],
    "token_type_ids": [0, 0, 0, 0, 0, 0, 0, 0],
    "attention_mask": [1, 1, 1, 1, 1, 1, 1, 1]
}

其中:

text
input_ids:token 对应的数字 ID
attention_mask:哪些位置是真实 token,哪些位置是 padding
token_type_ids:区分句子 A / 句子 B,BERT 中常见

也可以把 ID 转回 token:

python
tokens = tokenizer.convert_ids_to_tokens(encoded["input_ids"])
print(tokens)

可能得到:

text
["[CLS]", "我", "喜", "欢", "机", "器", "学", "习", "[SEP]"]

再把 token ID 解码回文本:

python
decoded = tokenizer.decode(encoded["input_ids"])
print(decoded)

这里的 [CLS] 和 [SEP] 是 BERT 使用的特殊 token。不同模型会有不同的特殊 token,例如表示句子开始、句子结束、填充、未知字符等。

六、常见 Tokenizer 类型 ​

Tokenizer 有很多实现方式。它们的目标类似:把文本切成适合模型学习和计算的单位。

6.1 Character Tokenizer ​

Character Tokenizer 按字符切分。

例如:

text
我喜欢AI

切成:

text
["我", "喜", "欢", "A", "I"]

优点是简单,并且基本不会遇到未知词。缺点是序列容易变长,尤其是英文会被切得过碎。

6.2 Word Tokenizer ​

Word Tokenizer 按词切分。

英文示例:

text
I love machine learning

切成:

text
["I", "love", "machine", "learning"]

中文需要先分词:

text
我喜欢机器学习

可能切成:

text
["我", "喜欢", "机器学习"]

这种方式符合人类直觉,但词表会非常大。遇到新词、罕见词、拼写错误或代码标识符时,处理起来也比较困难。

6.3 BPE ​

BPE,全称 Byte Pair Encoding,是常见的子词切分方法。

它的核心思想是:

text
先从较小单位开始,例如字符或 byte。
统计相邻片段出现频率。
反复合并最常见的相邻片段。
最终得到固定大小的词表。

例如训练过程中发现:

text
l + o 经常一起出现 -> 合并成 lo
lo + w 经常一起出现 -> 合并成 low

最终:

text
lowest -> ["low", "est"]
unhappy -> ["un", "happy"]

BPE 的优势是词表大小可控,同时能处理未见过的新词。GPT 系列模型常使用 BPE 或其变体。

6.4 WordPiece ​

WordPiece 和 BPE 类似,也是一种子词 tokenizer。BERT 常用 WordPiece。

例如:

text
unaffable

可能切成:

text
["un", "##aff", "##able"]

其中 ## 表示这个 token 是接在前一个 token 后面的子词。

WordPiece 的优势是可以把罕见词拆成常见子词,减少未知词问题。它在 BERT 及其相关模型中非常常见。

6.5 SentencePiece ​

SentencePiece 是 Google 提出的 tokenizer 工具,常用于 T5、ALBERT、XLNet、LLaMA 等模型。

它的特点是直接从原始文本训练,不依赖外部分词器,并且会把空格也当成普通符号处理。

例如:

text
Hello world

可能被切成:

text
["▁Hello", "▁world"]

这里的 ▁ 表示空格位置。

SentencePiece 对多语言场景比较友好,适合中文、英文、日文以及混合文本。

6.6 Unigram Tokenizer ​

Unigram 通常和 SentencePiece 一起出现。

它不是从小单位不断合并,而是先准备一个较大的候选词表,再用概率模型保留最合适的一批 token。

同一句话可能有多种切分方式:

text
machinelearning

可能被切成:

text
["machine", "learning"]
["mach", "ine", "learning"]
["machine", "learn", "ing"]

Unigram 会选择概率更合理的切分方式。

6.7 Byte-level BPE ​

Byte-level BPE 以字节为基础单位,而不是以 Unicode 字符为基础单位。

这意味着它几乎可以处理任意文本:

text
中文
英文
emoji
特殊符号
代码
乱码

它的优点是鲁棒性强,几乎不会出现 unknown token。缺点是某些非英文文本可能会产生更多 token,切分结果也更不直观。

GPT-2、RoBERTa 等模型使用过 Byte-level BPE。

6.8 常见模型和 Tokenizer 对应关系 ​

常见对应关系如下:

text
BERT      -> WordPiece
GPT-2     -> Byte-level BPE
RoBERTa   -> Byte-level BPE
T5        -> SentencePiece
ALBERT    -> SentencePiece
XLNet     -> SentencePiece
LLaMA     -> SentencePiece / BPE 变体
GPT 系列  -> BPE / Byte-level BPE 变体

但具体到某个模型,仍然要看它发布时附带的 tokenizer 文件,不能只根据模型名字推断。

七、Token 进入模型后发生了什么 ​

Tokenizer 只负责把文本变成 token ID。真正的神经网络计算从 embedding 开始。

假设输入 ID 是:

text
[1024, 5832, 901]

模型会从 embedding 表里取出对应向量:

text
1024 -> x1
5832 -> x2
901  -> x3

每个 x 都是一个高维向量。随后这些向量进入 Transformer 层。

在 Transformer 中,最核心的机制是 attention。attention 的关键就是 Q、K、V。

八、Q、K、V 是怎么计算出来的 ​

对于每个 token 的向量 x,模型内部有三组可训练参数矩阵:

text
Wq, Wk, Wv

通过矩阵乘法得到:

text
Q = x * Wq
K = x * Wk
V = x * Wv

其中:

text
Q = Query,查询
K = Key,键
V = Value,值

可以这样理解:

text
Q:当前 token 想找什么信息
K:每个 token 可以被怎样匹配
V:每个 token 真正提供什么内容

这三个向量不是 tokenizer 生成的,而是 token embedding 进入模型后,由模型参数计算出来的。训练时,Wq、Wk、Wv 会随着任务目标不断更新。

九、Q、K、V 是怎么用的 ​

Attention 的标准公式是:

text
Attention(Q, K, V) = softmax(QK^T / sqrt(d_k)) V

拆开来看:

  1. 当前 token 的 Q 和所有 token 的 K 计算相似度。
  2. 相似度越高,说明当前 token 越应该关注那个 token。
  3. 通过 softmax 把相似度转成权重。
  4. 用这些权重对所有 token 的 V 做加权求和。
  5. 得到当前 token 融合上下文后的新表示。

例如:

text
小明把书放进书包,因为它很重。

这里的“它”到底指“书”还是“书包”?模型会通过 attention 让“它”关注前面的相关 token。不同层、不同 head 可能学习不同关系,例如指代关系、语法关系、位置关系或语义关系。

这就是 Transformer 能够理解上下文的关键:任意 token 都可以通过 attention 直接和其他 token 建立联系。

十、从输入到输出的完整链路 ​

把前面的内容串起来,一段文本从输入到输出大致是这样的:

text
原始文本
  ↓
Tokenizer 切成 token
  ↓
Token 映射成 token ID
  ↓
Token ID 查 embedding 表,变成向量
  ↓
向量进入 Transformer
  ↓
每个 token 向量计算 Q、K、V
  ↓
通过 attention 聚合上下文信息
  ↓
模型预测下一个 token ID
  ↓
Tokenizer 把 token ID 解码成人类可读文本

例如:

text
输入:
我喜欢 machine learning

tokenizer 可能得到:

text
["我", "喜欢", " machine", " learning"]

转成 ID:

text
[1024, 5832, 4321, 8765]

模型根据这些 ID 生成新的 ID:

text
[9012, 3456]

再由 tokenizer 解码成:

text
很有趣

最终得到:

text
我喜欢 machine learning 很有趣

十一、工程实践里为什么要关心 Token ​

理解 token 不只是为了看懂模型结构,它在工程实践中也很重要。

11.1 控制上下文窗口 ​

提示词、历史对话、代码文件、工具返回结果都会占用 token。上下文窗口再大,也不是无限的。

如果把大量无关内容塞进 prompt,不仅成本更高,还可能稀释真正重要的信息。

11.2 估算 API 成本 ​

很多大模型 API 按 token 计费。一次请求的成本通常取决于:

text
输入 token 数
输出 token 数
是否命中缓存
模型单价

所以压缩 prompt、减少重复上下文、控制输出长度,都会影响实际成本。

11.3 优化检索增强生成 ​

在 RAG 系统中,召回多少文档、每个文档截取多长、如何拼接上下文,本质上都要受 token 预算约束。

检索结果不是越多越好。更合理的做法是把 token 留给真正相关、可引用、信息密度高的内容。

11.4 理解 KV Cache 和 Prompt Cache ​

Transformer 推理中,已经计算过的 token 可以复用部分中间结果。KV Cache 复用的是解码阶段的 Key、Value,Prompt Cache 复用的是相同前缀 prompt 的计算结果。

这些缓存机制的基础仍然是 token。缓存能不能命中,取决于模型看到的 token 序列是否满足复用条件。

十二、总结 ​

Token 是大模型处理文本的基本单位,tokenizer 是文本和 token ID 之间的转换器。

一段文本进入模型后,并不是直接被模型理解,而是先经过 tokenizer 切分成 token,再映射成 token ID,随后通过 embedding 表变成向量。每个 token 向量进入 Transformer 后,会计算出 Q、K、V:

text
Q 决定当前 token 想找什么。
K 决定每个 token 可以如何被匹配。
V 提供真正被聚合的信息。

Attention 通过 Q 和 K 计算关注权重,再用这些权重加权 V,从而让每个 token 获得上下文信息。

一句话概括:

token 是文本进入大模型后的基本计算单位,tokenizer 负责文本和 token ID 的转换,Q/K/V 与 attention 负责在 token 之间建立上下文关系。

Last updated: