热闻岛
返回全网热点

Tokenizer:大模型读懂文本的入口

1小时前8 阅读
Tokenizer:大模型读懂文本的入口配图
很多人第一次接触大模型时,会以为模型是直接“读字”的。其实不是。模型真正处理的是一串数字,这些数字来自 tokenizer 的切分结果。Tokenizer 的价值,就是把人类能读的文本,转换成模型能处理的 token id。 这篇文章用通俗
Tokenizer:大模型读懂文本的入口配图

很多人第一次接触大模型时,会以为模型是直接“读字”的。其实不是。模型真正处理的是一串数字,这些数字来自 tokenizer 的切分结果。Tokenizer 的价值,就是把人类能读的文本,转换成模型能处理的 token id。

这篇文章用通俗的方式讲清楚:token 是什么,为什么不能简单按字或按词切,BPE、WordPiece、Unigram、SentencePiece 分别解决什么问题,以及在工程落地中为什么 token 数会影响成本、速度和上下文窗口。

一句话总结:Tokenizer 不是普通分词器,而是模型和文本之间的“编码协议”。

1. 模型为什么需要 Tokenizer

神经网络不能直接处理“文字”本身。无论是中文、英文、代码还是符号,最终都要变成数字。Tokenizer 先把文本切成一个个 token,再把 token 查表变成整数 ID。模型拿到 ID 后,再去 embedding 表里取向量,后面的 Transformer 才能继续计算。

Tokenizer:大模型读懂文本的入口配图

文本先变成 token,再变成 token id,最后进入模型计算

所以 token 不等于汉字,也不一定等于单词。它可能是一个字、一个词、一段常见子串,也可能是标点、空格、代码片段或特殊标记。不同模型的 tokenizer 不一样,同一句话在不同模型里可能被切成不同数量的 token。

2. Tokenizer 的完整流程

真实项目里的 tokenizer 通常会经过一条流水线:先对输入做标准化,再做预分词,然后用 BPE、WordPiece、Unigram 等算法切成子词,最后查词表变成 token id。有些模型还会加入 BOS、EOS、PAD、MASK 等特殊 token。

Tokenizer:大模型读懂文本的入口配图

这里最容易忽略的是“词表绑定”。模型训练时用的是某个 tokenizer 和某份词表,推理时也必须保持一致。随便换 tokenizer,就像拿错字典翻译,轻则 token 数异常,重则模型输出质量明显下降。

3. 为什么不是直接按词或按字切

最直觉的方案是按词切,例如把英文句子切成一个个单词。但这样会遇到两个问题:词表会非常大,而且没见过的新词很容易变成 unknown。另一种方案是按字符切,词表确实小了,但序列会变得很长,模型要处理的 token 数暴涨。

Tokenizer:大模型读懂文本的入口配图

子词分词是折中方案。比如 unbelievable 可以切成 un、believe、able。模型既能复用常见片段,又能处理训练集中没出现过的新组合。大模型常用的 BPE、WordPiece、Unigram,本质上都在做这件事。

4. BPE:把高频片段合并成 token

BPE 的想法很像“压缩”。它先从字符开始,然后统计哪些相邻片段最常一起出现,把它们合并成新的 token。这个过程不断重复,直到词表达到设定大小。

Tokenizer:大模型读懂文本的入口配图

例如 low、lower、lowest 频繁出现时,l 和 o 可能先合成 lo,lo 和 w 再合成 low。以后模型遇到 lowest,就不必完全按字符处理,而可以使用 low、est 这类更有语义的片段。

# 一个极简 BPE 合并示意,不是完整生产实现
corpus = ["low", "lower", "lowest", "newer"]

# 初始状态:每个词拆成字符
# low -> l o w
# lower -> l o w e r

# 统计高频相邻片段后,逐步合并
# l + o -> lo
# lo + w -> low
# e + r -> er

5. WordPiece、Unigram、SentencePiece 怎么理解

BPE、WordPiece、Unigram 都属于子词分词,但选择 token 的方式不同。BPE 更像“频率合并器”;WordPiece 更关注合并后对语料概率的提升;Unigram 则先准备一个较大的候选词表,再逐步删掉贡献较小的片段。

Tokenizer:大模型读懂文本的入口配图

SentencePiece 更像是一套语言无关的 tokenizer 工具。它不要求输入文本先按空格切成词,而是把文本当成原始字符流来学习子词,这对中文、日文、多语言场景很有用。

Tokenizer:大模型读懂文本的入口配图
import sentencepiece as spm

sp = spm.SentencePieceProcessor(model_file="demo.model")
print(sp.encode("分词器不是简单按空格切词", out_type=str))

6. Token 数为什么很重要

在大模型应用里,token 数直接影响三个东西:上下文长度、响应速度和调用成本。用户输入、系统提示词、历史对话、RAG 检索内容、工具返回结果,全部都会占 token。

Tokenizer:大模型读懂文本的入口配图

很多线上问题不是模型“不会”,而是上下文被塞爆了:前面的关键信息被截断,后面的回答自然会跑偏。做 RAG 分块时也不能只按字符数切,最好按 token 数控制每块大小。

import tiktoken

enc = tiktoken.encoding_for_model("gpt-4o")
text = "Tokenizer 是大模型读文本的入口"

ids = enc.encode(text)
print(ids)
print("token 数:", len(ids))

7. 中文、英文、代码的 token 数并不一样

同样长度的文本,中文、英文、代码、JSON 的 token 数可能差很多。原因是词表学习自训练语料,高频片段更容易形成较长 token,低频组合则可能被拆得更碎。

Tokenizer:大模型读懂文本的入口配图

这也是为什么做提示词模板、长文档总结、代码生成和知识库问答时,都要提前统计 token 数。尤其是 JSON、Markdown 表格、代码块、长 URL,很容易让 token 数意外变高。

8. 工程落地最容易踩的坑

Tokenizer 看起来是底层组件,但在工程里很容易引发连锁问题。比如换模型时没有同步 tokenizer,RAG 按字符分块导致 token 溢出,训练时新增特殊 token 但没有扩展 embedding,或者线上没有记录 token 使用量,最后成本异常却不知道原因。

Tokenizer:大模型读懂文本的入口配图

比较稳妥的做法是:把 tokenizer 当成模型配置的一部分进行版本管理;每次模型切换都做 token 统计回归;上线前压测中文、英文、代码、表格、JSON、长 URL 等典型输入;RAG 分块和截断统一按 token 数处理。

from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("bert-base-chinese")
text = "大模型需要把文本切成 token"

tokens = tokenizer.tokenize(text)
ids = tokenizer.convert_tokens_to_ids(tokens)

print(tokens)
print(ids)

9. 最后怎么记

Tokenizer 可以理解成大模型的“文字编码器”。它不负责理解世界,也不负责生成答案,但它决定了文本进入模型之前的形态。切得好,模型更容易学习和泛化;切得差,序列会更长、成本会更高、上下文更容易被挤爆。

Tokenizer:大模型读懂文本的入口配图

真正落地时,记住三句话:模型看的是 token id;tokenizer 必须和模型配套;成本、速度、上下文窗口都和 token 数有关。

要点速读

很多人第一次接触大模型时,会以为模型是直接“读字”的。其实不是。模型真正处理的是一串数字,这些数字来自 tokenize

  • 很多人第一次接触大模型时,会以为模型是直接“读字”的
  • 其实不是
  • 模型真正处理的是一串数字,这些数字来自 tokenize