从 Token 到 Tokenizer:大模型如何把文本变成计算
使用大模型时,经常会看到几个词:token、tokenizer、embedding、Q/K/V、attention。它们看起来像是分散的概念,但其实处在同一条处理链路上。
一段文本进入模型,大致会经历下面的过程:
原始文本
↓
Tokenizer 切分
↓
Token ID
↓
Embedding 向量
↓
Q / K / V
↓
Attention
↓
预测下一个 token模型不是直接“阅读”字符串,而是把文本先拆成 token,再把 token 转成数字和向量,最后在 Transformer 里做矩阵计算。理解这条链路,是理解大模型上下文长度、推理成本、生成过程和缓存机制的基础。
本文从 token 开始,逐步拆解文本是如何变成模型可以计算的内容。
一、什么是 Token
Token 是大模型处理文本的基本单位。
它不一定是一个字,也不一定是一个完整的词,而是 tokenizer 根据词表和切分规则得到的文本片段。
例如中文句子:
我喜欢机器学习可能被切成:
["我", "喜欢", "机器", "学习"]英文句子:
I love machine learning可能被切成:
["I", " love", " machine", " learning"]有些词还会被拆成更小的子词:
unbelievable可能变成:
["un", "believ", "able"]所以,token 更准确的定义是:模型词表中的一个文本片段。
不同模型使用的 tokenizer 不同,同一句话切出来的 token 也可能不同。这也是为什么不同模型对同一段文本的 token 数统计不一定完全一致。
二、Token 有什么用
Token 的作用不是为了符合人类的分词习惯,而是为了让文本进入神经网络计算。
2.1 把文本变成数字
神经网络不能直接处理字符串。模型真正接收的是数字。
例如:
["我", "喜欢", "猫"]会被映射成:
[1024, 5832, 901]这里的每个数字就是 token ID。模型内部有一张词表,记录了 token 和 ID 的对应关系。
2.2 决定上下文长度
大模型的上下文窗口通常按 token 计算,而不是按字数、字符数或单词数计算。
例如一个模型支持:
128k tokens意思是输入和输出加起来最多可以容纳大约 128k 个 token。
这也是为什么有时一段中文、英文、代码、JSON 在模型里占用的 token 数差异很大。它们经过 tokenizer 后的切分密度不同。
2.3 影响推理成本和速度
token 越多,模型需要处理的序列越长,推理成本也越高。
在 Transformer 中,attention 需要计算 token 之间的关系。序列越长,计算量和显存压力越明显。实际使用大模型 API 时,费用通常也和输入 token、输出 token 数量直接相关。
2.4 作为生成的基本单位
大模型生成文本时,本质上是在不断预测下一个 token。
例如当前上下文是:
我 喜欢模型可能预测下一个 token 是:
猫然后上下文变成:
我 喜欢 猫模型继续预测下一个 token。最终,我们看到的是一段完整文本,但模型内部是一个 token 一个 token 地生成。
三、什么是 Tokenizer
Tokenizer 是分词器,也可以理解为文本编码器。
它负责两件事:
文本 -> token -> token ID
token ID -> 文本前者叫编码,后者叫解码。
例如:
我喜欢 AI经过 tokenizer 后,可能得到:
tokens: ["我", "喜欢", " AI"]
ids: [1024, 3881, 9274]模型真正接收的不是 "我喜欢 AI" 这个字符串,而是 [1024, 3881, 9274] 这样的数字序列。
Tokenizer 的设计要解决一个平衡问题:
切得太细:序列很长,计算成本高。
切得太粗:词表很大,遇到新词和罕见词很难处理。现代大模型通常使用子词级 tokenizer。常见词可以作为完整 token,罕见词可以拆成更小片段,从而兼顾词表规模和泛化能力。
四、一个输入是怎么变成 Token 的
以这句话为例:
我喜欢猫第一步,tokenizer 根据自己的规则切分文本:
["我", "喜欢", "猫"]第二步,查词表,把 token 转成 ID:
[1024, 5832, 901]第三步,模型通过 embedding 表把 ID 转成向量:
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:
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("bert-base-chinese")
text = "我喜欢机器学习"
encoded = tokenizer(text)
print(encoded)输出可能类似:
{
"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]
}其中:
input_ids:token 对应的数字 ID
attention_mask:哪些位置是真实 token,哪些位置是 padding
token_type_ids:区分句子 A / 句子 B,BERT 中常见也可以把 ID 转回 token:
tokens = tokenizer.convert_ids_to_tokens(encoded["input_ids"])
print(tokens)可能得到:
["[CLS]", "我", "喜", "欢", "机", "器", "学", "习", "[SEP]"]再把 token ID 解码回文本:
decoded = tokenizer.decode(encoded["input_ids"])
print(decoded)这里的 [CLS] 和 [SEP] 是 BERT 使用的特殊 token。不同模型会有不同的特殊 token,例如表示句子开始、句子结束、填充、未知字符等。
六、常见 Tokenizer 类型
Tokenizer 有很多实现方式。它们的目标类似:把文本切成适合模型学习和计算的单位。
6.1 Character Tokenizer
Character Tokenizer 按字符切分。
例如:
我喜欢AI切成:
["我", "喜", "欢", "A", "I"]优点是简单,并且基本不会遇到未知词。缺点是序列容易变长,尤其是英文会被切得过碎。
6.2 Word Tokenizer
Word Tokenizer 按词切分。
英文示例:
I love machine learning切成:
["I", "love", "machine", "learning"]中文需要先分词:
我喜欢机器学习可能切成:
["我", "喜欢", "机器学习"]这种方式符合人类直觉,但词表会非常大。遇到新词、罕见词、拼写错误或代码标识符时,处理起来也比较困难。
6.3 BPE
BPE,全称 Byte Pair Encoding,是常见的子词切分方法。
它的核心思想是:
先从较小单位开始,例如字符或 byte。
统计相邻片段出现频率。
反复合并最常见的相邻片段。
最终得到固定大小的词表。例如训练过程中发现:
l + o 经常一起出现 -> 合并成 lo
lo + w 经常一起出现 -> 合并成 low最终:
lowest -> ["low", "est"]
unhappy -> ["un", "happy"]BPE 的优势是词表大小可控,同时能处理未见过的新词。GPT 系列模型常使用 BPE 或其变体。
6.4 WordPiece
WordPiece 和 BPE 类似,也是一种子词 tokenizer。BERT 常用 WordPiece。
例如:
unaffable可能切成:
["un", "##aff", "##able"]其中 ## 表示这个 token 是接在前一个 token 后面的子词。
WordPiece 的优势是可以把罕见词拆成常见子词,减少未知词问题。它在 BERT 及其相关模型中非常常见。
6.5 SentencePiece
SentencePiece 是 Google 提出的 tokenizer 工具,常用于 T5、ALBERT、XLNet、LLaMA 等模型。
它的特点是直接从原始文本训练,不依赖外部分词器,并且会把空格也当成普通符号处理。
例如:
Hello world可能被切成:
["▁Hello", "▁world"]这里的 ▁ 表示空格位置。
SentencePiece 对多语言场景比较友好,适合中文、英文、日文以及混合文本。
6.6 Unigram Tokenizer
Unigram 通常和 SentencePiece 一起出现。
它不是从小单位不断合并,而是先准备一个较大的候选词表,再用概率模型保留最合适的一批 token。
同一句话可能有多种切分方式:
machinelearning可能被切成:
["machine", "learning"]
["mach", "ine", "learning"]
["machine", "learn", "ing"]Unigram 会选择概率更合理的切分方式。
6.7 Byte-level BPE
Byte-level BPE 以字节为基础单位,而不是以 Unicode 字符为基础单位。
这意味着它几乎可以处理任意文本:
中文
英文
emoji
特殊符号
代码
乱码它的优点是鲁棒性强,几乎不会出现 unknown token。缺点是某些非英文文本可能会产生更多 token,切分结果也更不直观。
GPT-2、RoBERTa 等模型使用过 Byte-level BPE。
6.8 常见模型和 Tokenizer 对应关系
常见对应关系如下:
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 是:
[1024, 5832, 901]模型会从 embedding 表里取出对应向量:
1024 -> x1
5832 -> x2
901 -> x3每个 x 都是一个高维向量。随后这些向量进入 Transformer 层。
在 Transformer 中,最核心的机制是 attention。attention 的关键就是 Q、K、V。
八、Q、K、V 是怎么计算出来的
对于每个 token 的向量 x,模型内部有三组可训练参数矩阵:
Wq, Wk, Wv通过矩阵乘法得到:
Q = x * Wq
K = x * Wk
V = x * Wv其中:
Q = Query,查询
K = Key,键
V = Value,值可以这样理解:
Q:当前 token 想找什么信息
K:每个 token 可以被怎样匹配
V:每个 token 真正提供什么内容这三个向量不是 tokenizer 生成的,而是 token embedding 进入模型后,由模型参数计算出来的。训练时,Wq、Wk、Wv 会随着任务目标不断更新。
九、Q、K、V 是怎么用的
Attention 的标准公式是:
Attention(Q, K, V) = softmax(QK^T / sqrt(d_k)) V拆开来看:
- 当前 token 的 Q 和所有 token 的 K 计算相似度。
- 相似度越高,说明当前 token 越应该关注那个 token。
- 通过 softmax 把相似度转成权重。
- 用这些权重对所有 token 的 V 做加权求和。
- 得到当前 token 融合上下文后的新表示。
例如:
小明把书放进书包,因为它很重。这里的“它”到底指“书”还是“书包”?模型会通过 attention 让“它”关注前面的相关 token。不同层、不同 head 可能学习不同关系,例如指代关系、语法关系、位置关系或语义关系。
这就是 Transformer 能够理解上下文的关键:任意 token 都可以通过 attention 直接和其他 token 建立联系。
十、从输入到输出的完整链路
把前面的内容串起来,一段文本从输入到输出大致是这样的:
原始文本
↓
Tokenizer 切成 token
↓
Token 映射成 token ID
↓
Token ID 查 embedding 表,变成向量
↓
向量进入 Transformer
↓
每个 token 向量计算 Q、K、V
↓
通过 attention 聚合上下文信息
↓
模型预测下一个 token ID
↓
Tokenizer 把 token ID 解码成人类可读文本例如:
输入:
我喜欢 machine learningtokenizer 可能得到:
["我", "喜欢", " machine", " learning"]转成 ID:
[1024, 5832, 4321, 8765]模型根据这些 ID 生成新的 ID:
[9012, 3456]再由 tokenizer 解码成:
很有趣最终得到:
我喜欢 machine learning 很有趣十一、工程实践里为什么要关心 Token
理解 token 不只是为了看懂模型结构,它在工程实践中也很重要。
11.1 控制上下文窗口
提示词、历史对话、代码文件、工具返回结果都会占用 token。上下文窗口再大,也不是无限的。
如果把大量无关内容塞进 prompt,不仅成本更高,还可能稀释真正重要的信息。
11.2 估算 API 成本
很多大模型 API 按 token 计费。一次请求的成本通常取决于:
输入 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:
Q 决定当前 token 想找什么。
K 决定每个 token 可以如何被匹配。
V 提供真正被聚合的信息。Attention 通过 Q 和 K 计算关注权重,再用这些权重加权 V,从而让每个 token 获得上下文信息。
一句话概括:
token 是文本进入大模型后的基本计算单位,tokenizer 负责文本和 token ID 的转换,Q/K/V 与 attention 负责在 token 之间建立上下文关系。