tokenizer.json 结构化逐行说明先说明一件很重要的事:这个文件有 250325 行。它是自动生成的 tokenizer 总文件,里面包含:
vocabmerges如果机械地把 25 万行每一行都写一遍,学生只会被淹没,反而学不到重点。所以这份说明采用更适合教学的方式:
vocab 和 merges 用代表性片段说明规则这样你能真正读懂这个文件在做什么。
{
JSON 对象开始。说明整个 tokenizer 会被表示成一个大字典。
"version": "1.0",
这表示 tokenizer JSON 格式的版本号,不是模型版本号。
"truncation": null,
这里没有写死截断策略。也就是说,tokenizer 本身不强制规定“超过长度后怎么截断”,通常把这件事留给上层代码处理。
"padding": null,
这里也没有写死 padding 规则。和我们前面看到 pad_token 为 null 是一致的。
added_tokens:特殊 token"added_tokens": [
下面要开始列出“额外加入的特殊 token”。
{
"id": 50256,
"content": "<|endoftext|>",
"single_word": false,
"lstrip": false,
"rstrip": false,
"normalized": false,
"special": true
}这里定义了一个特殊 token:<|endoftext|>。
逐项理解:
id: 50256
content: "<|endoftext|>"
single_word: false
lstrip: false / rstrip: false
normalized: false
special: true
] , 的语义
这一行表示 added_tokens 数组结束,接下来进入下一个配置项。
normalizer:文本标准化"normalizer": null,
这里是 null,表示 GPT-2 tokenizer 不额外做一套复杂的 normalizer,比如统一大小写、去音标之类。
这说明 GPT-2 更偏向“保留原始文本细节,再用 byte-level 方式处理”。
pre_tokenizer:切词前预处理"pre_tokenizer": {
开始定义预处理规则。
"type": "ByteLevel",
这说明 tokenizer 采用 ByteLevel 预处理。它不是直接按自然语言中的“词”切,而是先把文本映射到字节层,再配合 BPE 做编码。
"add_prefix_space": false,
不会在句子最前面自动补空格。这个选项会影响第一个词怎么被编码。
"trim_offsets": true,
保留 offset 信息时,会修剪空白偏移,让位置信息更干净。
"use_regex": true
说明预处理时会使用正则规则来辅助划分文本模式。
},
pre_tokenizer 这一段结束。
post_processor:编码后的整理规则"post_processor": {
开始定义后处理。
"type": "TemplateProcessing",
说明后处理采用模板方式。也就是:对单句输入、双句输入分别按模板拼接。
这一段定义单句输入 single 的模板。
核心意思是: - 单句时,直接把序列 A 放进去 - type_id 为 0
这一段定义成对输入 pair 的模板。
核心意思是: - 第一段文本用序列 A - 第二段文本用序列 B - 两段分别标不同的 type_id
"special_tokens": {}
这里没有额外通过 post-processor 插入更多特殊 token。
post_processor 结束。
decoder:把 token 还原回文本"decoder": {
开始定义解码器。
"type": "ByteLevel",
解码器也是 ByteLevel 类型,和前面的预处理器对应。
"add_prefix_space": true,
解码回文本时,会按照 ByteLevel GPT-2 的规则处理前缀空格。
"trim_offsets": true,
继续保留对 offset 的修剪策略。
"use_regex": true
同样允许使用正则逻辑。
},
decoder 配置结束。
model:真正的 tokenizer 模型本体"model": {
这一行很关键。它告诉我们:前面只是辅助规则,现在开始进入“真正的分词模型内容”。
"type": "BPE",
说明这里使用的是 BPE: Byte Pair Encoding。
"dropout": null,
不对 BPE merge 过程使用 dropout。
"unk_token": null,
没有单独设置一个新的 unknown token。
"continuing_subword_prefix": "",
子词继续部分前面不加额外前缀。
"end_of_word_suffix": "",
词尾也不加额外后缀。
"fuse_unk": false,
不把未知 token 做额外融合处理。
"byte_fallback": false,
不启用额外的 byte fallback 机制。
"ignore_merges": false,
说明后面列出的 merges 规则是会真正参与工作的,不会被忽略。
vocab:词表"vocab": {
从这里开始进入词表。词表的作用是:
"!": 0,
"\"": 1,
"#": 2,
"$": 3,
"%": 4,
"&": 5,
"'": 6,
"(": 7,
")": 8,
"*": 9,
"+": 10,这说明最基础的标点符号都被收进词表,并且有自己的编号。
像:
"0": 15,
"1": 16,
"2": 17,这些行说明数字字符也都直接有自己的 token id。
像:
"a": 64,
"b": 65,
"c": 66,说明字母也被收入了词表。
搜索结果里有:
"model": 19849,
这说明完整字符串 "model" 已经作为一个高频子词或词,拥有独立 id 19849。这正是 BPE 的意义之一:高频组合不必每次都拆成单字符。
在 vocab 的尾部你会看到类似:
"Ġamplification": 50250,
"ominated": 50251,
"Ġregress": 50252,
"ĠCollider": 50253,
"Ġinformants": 50254,
"Ġgazed": 50255,
"<|endoftext|>": 50256这里要重点理解两个现象:
Ġ
Ġregress 可以粗略理解成“带前导空格的 regress”。<|endoftext|>: 50256
merges:BPE 合并规则"merges": [
这表示后面开始列出 BPE 的合并规则。
这些规则决定:哪些字符或子词会优先合并成更长的 token。
[
"Ġ",
"t"
],
[
"Ġ",
"a"
],
[
"h",
"e"
],
[
"i",
"n"
]这些规则的意思是:
Ġ 和 t 常常一起出现,于是可以合成 Ġth 和 e 常常一起出现,于是可以合成 hei 和 n 可以合成 in这就是 BPE 的核心:把高频共现的字符对不断合并,慢慢形成更大的子词单元。
结尾你会看到类似:
[
"Ġampl",
"ification"
],
[
"om",
"inated"
],
[
"Ġreg",
"ress"
]这说明 BPE 不只是合并单字符,也会继续把已经形成的子词再合并成更长的单位。
例如: - Ġampl + ification -> Ġamplification - Ġreg + ress -> Ġregress
]
说明 merges 数组结束。
}
说明整个 tokenizer 的 JSON 文件结束。
tokenizer.json 是 tokenizer 的总装说明书。added_tokensvocabmergesvocab 负责“有哪些 token 和 id”merges 负责“这些 token 是怎么逐步学出来的”Ġ 常常表示 token 前面带空格,这是 GPT-2 tokenizer 的重要阅读线索。