跳到内容

第 13 卷 / 第 11 章 / 第 1 课

11.1 Tokenizer、特殊符号与长文切片:模型读到的是 Token ID,不是原始文字 ​

Checkpoint 约定了 tokenizer 协议:Vocabulary ID、归一化、边界符号和 chat format。只换 tokenizer 而不换权重,同一句话就可能被模型读成另一组输入。

本课目标 ​

  • 拆开 normalization、pre-tokenization、subword model 与 post-processing;
  • 区分 BPE、WordPiece、Unigram 和 byte-level 设计;
  • 正确处理 special tokens、padding、truncation 与 loss mask;
  • 为长文设计 document-aware chunking;
  • 评估多语言/领域 token 效率与字符对齐。

1. Tokenization 是一条 Pipeline ​

常见阶段:

text
raw text
  -> Unicode / case / whitespace normalization
  -> pre-tokenization(空白、标点、byte 边界等)
  -> subword segmentation
  -> vocabulary IDs
  -> BOS/EOS/SEP/role 等 special tokens
  -> padding / truncation / attention mask

不同 tokenizer 可能保留大小写,也可能 lower-case;可能使用 Unicode normalization,也可能保留原 byte。不可假设 decode 后逐字符等于原文:规范化、未知字符、空白清理都会影响 round trip。

做 span labeling 或引用定位时,保留原文并核对 backend 的 offset 约定。例如开启小写和去重音的 tokenizer 可把 Café 编成 cafe,offset 仍指向原文片段。归一化不一定可逆;special tokens 还可能使用 (0, 0) 这类空区间。

2. 为什么不用“一个词一个 ID” ​

Word vocabulary 对形态变化、拼写、代码标识符和开放词表很脆弱;character/byte vocabulary 小,但序列更长。Subword 在 vocabulary size 与 sequence length 间折中。

BPE ​

从小单元开始,迭代合并频繁相邻 pair。实际实现还受 pre-tokenizer、byte-level mapping 和 merge tie rule 影响。

WordPiece ​

也构建 subwords,但 vocabulary 学习准则和编码细节与 BPE 不同。## 只是某些 BERT tokenizer 的 continuation 表示,不是 WordPiece 的普遍外观。

Unigram LM ​

从候选 vocabulary 出发,按 probabilistic segmentation likelihood 剪除/选择 pieces;同一文本可存在多种分段候选。

Byte-level ​

完整覆盖 256 个 byte 值,或提供相应 byte fallback,才能把有效 Unicode 文本按 UTF-8 字节表示而不丢未知字符。仅有“byte-level”名称不能证明覆盖完整;一个字符仍可能消耗多个 bytes/tokens。

“GPT 都用一种 BPE、BERT 都用同一种 WordPiece”过于笼统。必须检查具体 checkpoint 的 tokenizer files。

3. Vocabulary ID 没有数值顺序 ​

ID 50257 不比 ID 100 “语义更大”。Embedding table 以 ID 索引 learned vector;重排 vocabulary 却不同时重排 embedding/output head,就彻底改变模型。

很多 causal LM tie input embedding 与 output projection weights。新增 tokens 后要:

  1. 更新 tokenizer;
  2. resize model embeddings/output head;
  3. 初始化并训练新增 rows;
  4. 保存 tokenizer 与 model 同一版本;
  5. 检查 serving engine 是否加载新 vocabulary。

仅调用 add_tokens 不会让新 token 自动获得语义。

4. Special Tokens 是协议控制符 ​

常见:

  • BOS/EOS:序列开始/结束;
  • PAD:批量补齐;
  • MASK:masked objective corruption;
  • SEP/CLS:特定 encoder 输入组织;
  • role/control tokens:system/user/assistant/tool 边界;
  • sentinel tokens:span corruption 或 infilling。

未注册为 special token 的可见字符串可能被拆成普通 pieces。重复 BOS/EOS 或遗漏 assistant-start token 都会改变序列。有些 causal model 有意共用 PAD 与 EOS ID,此时必须按位置区分补齐与真正的结束监督。

不要把 user 可输入的普通字符串直接当不可伪造权限边界;控制 token 解析和消息角色应由应用层构造。

5. Padding Mask 与 Loss Mask 不是一回事 ​

Tokenizer 的 attention_mask 通常说明哪些 input positions 是有效 token;模型/架构再转换为实际 attention mask。Training labels 还需单独决定哪些 positions 计算 loss。

Instruction tuning 中可能:

text
system/user tokens: 可被 assistant attend,labels = -100(不计 loss)
assistant tokens:   可被 attend,labels = token IDs(计 loss)
padding tokens:     不应被 attend,labels = -100

是否只训练 assistant response 由 objective 决定。这里的 -100 是 loss 实现约定的 ignore index,不是 tokenizer ID,也不是通用 mask 协议。Attention 可见性与 loss 监督仍要分别设置。

Left/right padding 影响 position IDs、cache 和 generation batching,必须遵循 checkpoint/serving implementation。

6. Truncation 可能删除问题或答案 ​

truncation=True 让输入不超过上限,却未说明删哪一端/哪一段。Pair input 的 longest_first、only_first、only_second 语义不同;对聊天若从右侧截断,可能恰好删掉最新用户问题。

记录:

  • 原 token count 与截断后 count;
  • 被截断样本比例;
  • 各字段保留策略;
  • BOS/EOS/role tokens 是否仍完整;
  • label 是否被截掉;
  • train/serve 的 truncation_side 是否一致。

模型 context limit、tokenizer model_max_length 与 serving 配置可能不一致;配置中的极大占位数也不应当作真实可用窗口。

7. 长文先按 Document Split,再切 Chunks ​

正确顺序:

text
documents -> train/valid/test by source/time/entity -> tokenize/chunk within each split

若先切 chunk 再随机分,重叠窗口或同文相邻段会跨 train/test,产生近重复泄漏。

Chunk 设计包括:

  • boundary:句子、段落、代码单元还是固定 token;
  • max tokens 与 special-token 预算;
  • overlap/stride;
  • document ID、offset、timestamp、license metadata;
  • 短文 packing 是否跨 document;
  • causal LM 的 EOS/document boundary。

Overlap 提高边界召回,也增加重复 compute 与评估相关性。Metric/bootstrap 应按 document/source,而非把 overlapping chunks 当独立样本。

EOS 标记边界,却不会阻止 packed 文档之间的 attention。若要求文档独立,应使用框架支持的分块对角 attention mask 或分开序列;允许跨文档上下文则是另一种明确的训练选择。

8. 一个可审计的编码示例 ​

片段需要先把 tokenizer_dir 设为已固定版本的本地 tokenizer 目录。接口已用 Transformers 5.16.1 和本地小词表核对;输出随词表而变。

python
from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained(
    tokenizer_dir, local_files_only=True, use_fast=True,
)
if not tokenizer.is_fast:
    raise ValueError("this example requires a fast tokenizer with offsets")

encoded = tokenizer(
    "第一段任务日志。第二段包含告警。",
    add_special_tokens=True,
    truncation=True,
    max_length=32,
    return_attention_mask=True,
    return_offsets_mapping=True,
    return_special_tokens_mask=True,
)

print({
    "tokens": tokenizer.convert_ids_to_tokens(encoded["input_ids"]),
    "ids": encoded["input_ids"],
    "attention_mask": encoded["attention_mask"],
    "special_mask": encoded["special_tokens_mask"],
    "offsets": encoded["offset_mapping"],
})

Fast tokenizer 常支持 offset mapping,具体 backend/checkpoint 要验证。Production 不应运行时用浮动 model ID 下载最新文件;固定 revision、hash、license 和本地 artifact。

9. Token 效率要实测 ​

同一句话在不同 tokenizer 下的 tokens/character、tokens/byte 差异会影响:

  • 可放入 context 的信息量;
  • pretraining/fine-tuning compute;
  • API/serving token cost;
  • 跨语言响应长度与 latency;
  • code、数字、URL、罕见术语的碎片化。

不存在“英文每词 1–2 token、中文每字 1 token”的稳定规律。用真实语言、领域和混合文本 corpus 统计 length quantiles、unknown/byte fallback、compression ratio 和 truncation rate。

10. Tokenizer Training 也是数据治理 ​

Vocabulary 频率会编码训练 mixture。若数据含 PII、secret、恶意控制字符串或大量某语言,token pieces 与效率会受影响。

训练/选择 tokenizer 时记录:

  • normalization/pre-tokenizer/config;
  • corpus source、license、consent 与时间;
  • per-language/domain sampling weights;
  • dedup/filter;
  • vocabulary size 与 reserved tokens;
  • stability/compatibility policy。

Tokenizer vocabulary 中出现字符串不等于模型记住事实;但 artifact 本身也可能泄露敏感片段,需要审计。

常见误区 ​

  • Tokenizer 只是部署前处理:它是 checkpoint 输入协议的一部分。
  • Subword 能无损还原任何原文:normalization/unknown/cleanup 可改变文本。
  • PAD mask 自动屏蔽 training loss:attention 与 label mask 分开。
  • 开启 truncation 就安全:可能删掉最新问题或监督答案。
  • 中文一字一个 token:效率取决于具体 vocabulary 与文本。

练习 ​

  1. 比较两个 pinned tokenizers 在中文、英文、代码、URL 上的长度分布。
  2. 检查 encode→decode 与 offsets 在空白/Unicode normalization 下的变化。
  3. 为 pair/chat 输入设计不会删掉问题与答案的截断策略。
  4. 先 chunk 后 split,观察重叠泄漏;再改为 document-first split。
  5. 新增 domain token 后检查 embedding resize、保存与 serving compatibility。

小结 ​

Tokenizer 把原始文本变成模型真正接收的 IDs,并通过 special tokens、mask、padding 和 truncation 定义输入协议。它决定序列长度、字符对齐和部署兼容性,也会继承训练 corpus 的治理问题。

下一课讨论这些 token sequences 怎样产生监督信号:causal、masked 与 denoising objectives 从同一批原始文本构造出不同的信息流和模型能力。

Built with VitePress | Software Systems Atlas