DIY LLM 第 2 章 · 带读页之二
分词器也有它的 2012
一个旧工具、一批够大的语料、一个丢人的痛点凑到一起 —— 外加两个「我能不能自己改」的问题。
一句话:这条线不是被谁设计出来的,是捡漏捡出来的。救场的算法在一份 21 年前的程序员杂志里躺着,发明它的人压根不知道 AI 是什么。赢了之后,大家才回头发现地基是歪的。
先对一下你给的那个讲法
ImageNet 2012:被冷落二十多年的老思路 + 够大的数据集 + 原本打游戏的显卡 + 三个不信邪的人 → 一夜改写整个领域。
分词器 2015:21 年前的压缩小算法 + 够大的双语语料 + 「翻译撞见生词就废」这个丢人的痛点 + 三个做翻译的人 → 从此成了所有大模型开工前的第一道工序。
同款结构,只是更冷门:主角不是一块显卡,是一张躺在旧杂志里的「先粘哪一对」的顺序表。
三幕
人物很少,记住五个人就够。出现的都是人名,不是机构、不是术语。
第一幕 · 1994
一个跟 AI 毫无关系的小发明
Philip Gage —— 人名,一个写程序的工程师。
他在一份程序员杂志上发了篇小文章,讲怎么把文件压小一点、解压快一点。办法特别土:数一数哪两个字节最常挨着,就给它俩发一个新编号,反复做几千次。文件里越常见的组合,就越会被粘成一整块。
当年这只在「压缩」那个小圈子里流传。没有人觉得它跟语言、跟智能有什么关系,作者本人更没往那儿想。
留下的东西:一张「先粘哪对、后粘哪对」的顺序表。
第二幕 · 2015 · 这一幕就是它的 2012
三个做翻译的人,去旧纸堆里捡回了它
Sennrich、Haddow、Birch —— 三个人名,爱丁堡大学做机器翻译的。
那几年的翻译系统有个特别丢人的毛病:碰到没见过的词,直接吐一个「不认识」,整句话就废了。词表再大也装不下人名、新词、专业术语。
他们把 21 年前那篇压缩文章翻出来,换了个用法 —— 不压文件了,压词。让语料自己决定哪些字该粘成一块:常见的整块留着,没见过的还能拆回单字拼出来。一试,翻译质量明显往上跳。
你的产线语料里「温」「度」总挨着 → 粘成 温度;「烘」「箱」也粘成 烘箱;哪天冒出新词「虚拟调试」,拆开照样能拼出来,不再丢。
从此这套做法成了标配。你教材末尾参考资料里那篇 1508.07909(一篇论文的编号),就是这次捡漏的现场记录;附录 6 让你手写的那张表,就是 Gage 当年那张压缩表,一个字没改。
留下的东西:今天所有大模型开工前的第一道工序。
第三幕 · 2018 · 所有人涌进来
成了地基,也分了家
这一年像 2012 之后大家都涌进深度学习:Google 给自家的 BERT 配了一套「挑最划算的一对来粘」;另一个人 Taku Kudo(人名)同一年一口气给了两样东西(一个反向删的做法 + 一个装做法的工具包);OpenAI 更干脆,把起点降到字节 —— 任何文字在电脑里都是字节,从此没有「没见过的字」。
「先切块、再训练」从此再没人质疑。
留下的东西:字节打底 + 粘合 + 固定词表,到 2026 年生产里跑的仍基本是这一代。
翻车名场面:冠军在小水沟里翻了车
好几年后,最强的模型被一个小学拼写题问倒:strawberry 里有几个 r?它不是笨,是它从来没看见过字母,只看得见切好的整块 —— 等于让只看得见包装箱的人猜箱里有几颗糖。
同一套地基还有个不响的坑:同样一段意思,中文常常被切得更碎,按块计费就多付钱、更占窗口。还有极少数几乎没学好的编号,一碰就让模型突然胡言乱语。
所以这故事的下半句是:赢了不等于地基对。今天所有「想干脆拿掉分词器」的研究,都是在补这一幕的账。
你问的两件事
都是「我能不能自己动手改」的问题。两个答案都是:能做,但你想省的那件事,恰恰不在这一层。
① 专有名词直接做成独立 token?
能做,真有人做。「块数会少」这半句对;「便于理解」这半句不成立,而且只加不练会变差。
- 省的是钱,不是懂。把「虚拟调试」从几块变成一块,占的窗口小了、账单少了。像把一个长名字缩成一个工号,登记快了,不代表这人更懂业务。
- 新编号是一张空白工牌。词表里多了个号,模型从没在这个号上学过任何东西。直接拿去微调,可能输出乱码,连原来会的都受影响。得先拿大量行业文本让它把这个号重新学一遍 —— 这已经不是微调了。
- 反而少了猜的线索。切成几块时,模型还能借着「调试」两个字猜个大概;粘成一整块,这点线索就没了。懂不懂来自训练,不来自切法。
- 今天的起点已经保证「不认识的字不会丢」,生僻词只是切得碎。所以现在加专有 token 只剩一个理由:省钱省窗口。行业里一句很直白的判断是:「你的领域有行话」远不够格动词表。
真要做:先按原样跑一版;只挑最高频、切得最碎的一小批(百来个到几百个);新号的起点别随机发,拿原来那几块的平均当起点;做完必须检查老文本的切法跟以前完全一致。
② 能不能把 ontology 一起做进 token?
你说「这是两个维度」—— 这句话本身就是答案,而且比很多做工程的人先想到。方向对,位置不对:垂直模型确实该带本体,但不该塞进编号里。
- 编号是死的,身份是活的。「温度」在「烘箱温度偏高」里是被观察的量,在「把设定值拧到 78 度」里是我能动的旋钮,在「温度属于工艺参数」里是一类东西。一个固定编号装不下三种身份。token 只回答「这是哪块字」,本体回答「这块字此刻是什么、跟谁有关系」。
- 类比:token 像快递单上印的字,本体像仓库里的货架关系图。想让仓库变整齐,改快递单没用,得另立一套架子。
- 行业知识偏偏是会变的。产品族换了、工艺改了、类别合并了。把关系焊死在编号里,改一次就得重训一遍模型;挂在外面,只改那层就行。
- 业界真在做,而且做了很多年(那些 K 开头、E 开头的都是论文或做法的名字,不是机构)。做法一律是旁边另开一路:输入时把关系额外喂进去、训练时多一个目标、回答前先去查一层。还有个专门的词叫「知识噪声」—— 硬塞进句子会跟原句互相污染,得再加隔离。会被反弹,本身就说明不该硬塞。
「自带」的正确形态:不是把本体编进 token,是让模型查得到本体、输出受它约束。这正落在你 FDE 路线图的语义 / 数据治理层,也接 klgwiki 的本体工作。
一句话带走:词怎么切,是「记账」的事;词是什么、跟谁有关系,是「仓库」的事。
垂直模型的专业度 = 语料里术语用法一致 + 有一层可查可改的概念关系 + 输出被这层校验 —— 跟切法基本无关。