大模型本质上是一个巨大的数学函数,输入输出都是数字,它根本不理解人类文字。所以中间需要有一个"翻译官"——Tokenizer。
# Tokenizer 的工作流程
Tokenizer 负责两件事:
编码(文字 → 数字),分两步:
- 切分:把一句话切成最小单位,每个碎片就是一个 token
- 映射:把每个 token 对应到一个数字(token ID)
解码(数字 → 文字),只有一步:
- 把模型输出的 token ID 反向映射回文字
举个例子,用户问"小皮咖喜欢人工智能吗":
编码:文字 → 切分为 token → 映射为 token ID → 传给模型
模型计算后输出一个 token ID
解码:token ID → 映射回文字(如"喜欢")
模型每次只输出一个 token,所以解码不需要切分。
# Tokenizer 是怎么训练出来的
以常用的 BPE 算法为例,核心思路很简单:从大量文本中统计哪些字经常挨在一起,把它们合并成一个 token。
训练过程:
- 先把所有单字放入词表,每个字分配一个编号(token ID)
- 扫描训练材料,找出出现频率最高的相邻字对,合并成一个新词
- 把新词加入词表,记录合并规则
- 重复以上步骤,合并后的词还可以继续合并(如"人工"+"智能"→"人工智能")
最终得到两个核心组件:
- 词表:记录 token 和 token ID 的映射关系
- 合并规则:记录哪些字应该合并为一个 token
# 为什么不是"一个字 = 一个 token"
如果每个字都是一个 token,那"小皮咖喜欢人工智能吗"就是 9 个 token,效率太低。
通过合并规则,常见的词被压缩成单个 token:
小皮咖 + 喜欢 + 人工智能 + 吗 → 4 个 token
这样模型输入更少,训练和推理速度更快。
# Token 和字/词的换算关系
大致参考:
| 语言 | 1 个 token 约等于 |
|---|---|
| 中文 | 1.5 ~ 2 个汉字 |
| 英文 | 4 个字母,或 0.75 个单词 |
所以一个 40 万 token 的上下文窗口,大约相当于 60~80 万汉字 或 30 万英文单词。
# 几点补充
- token ID 只是个编号,没有语义含义。ID 为 35 和 36 的两个 token,含义不一定相近,和 embedding 向量不是一回事。
- 词表只有单字也能当 tokenizer 用,但效率低。加入常见词汇是为了提升效率。