)
第 18 篇推理引擎里文字怎么变成数字——分词与位置零门槛入门系列上一篇第 17 篇《把预训练模型翻译成能跑的文件》 下一篇第 19 篇《图片怎么进模型》一句话导读推理引擎里的模型只认数字。文字要先按能整词就整词切成子词、查表变成 id 序列再给每个 id 挂上一个位置坐标模型才知道谁在前、谁在后。关键词推理引擎入门、大模型推理、分词tokenization、词表vocabulary、字节对编码BPE、位置编码positional encoding、id 序列第 17 篇把权重翻译成了能跑的文件可模型还是不认识文字。要让它开口第一步就是把文字变成它能处理的数字——这一步决定了后面所有计算拿到的输入长什么样。这一篇只讲这个入口。① 一句话概念文字先切词查表变数字再给每个加位置。② 起点一本暗号词典假设你和朋友有一套暗号词典。这本词典不按单个字编号而是把常一起出现的词组也算一个号一个号代表你一个号代表好另外还专门有一个号代表你好。发消息的时候你就按能整个词对上就整个词用来切看到你好直接用它那一个号不必拆成两个字分别报号。这样词数更少、传得更省若每个字都单独编号长句子就会拉出一长串号码。可光有号还不够。你想一想同一批号排列顺序不一样意思就完全不同。于是每报一个号你还得说清楚这是第几号位置——第一个号挂上第 0 位第二个号挂上第 1 位依次往下。有了是哪个号再加上排在第几位听的人才能准确还原出原话。一句话总结先切词查表把字变成号再给每个号标上位置文字到这里才算真正变成了一套机器能处理的数字。③ 伪代码先建词表再按最长匹配查表分词分两步走先建词表把常见的相邻词粘成更长的词编码时再用最长匹配去查。这套做法的名字叫字节对编码BPE它的思路很朴素不看语法、不管词性只数哪两个单位总挨在一起谁挨得最勤就先粘谁。函数 建词表(语料) - 词表: 词表 所有单个字 重复 直到 不再合并: 对 语料里出现最多的相邻两词 # 数哪种组合最常见 词表.加入(两词拼成的词) # 例如 你好 - 你好 返回 词表 函数 编码(句子, 词表) - id序列: id序列 [] 当 句子 还没切完: 词 从当前起点 找 词表里最长的匹配 # 能整词就不拆 id序列.追加(词表[词]) # 查表得到编号 句子 句子[词的长度 : ] # 挪到这个词的后面 返回 给每个 id 附上位置编号(id序列) # 第 0、1、2 … 位逐行要点重复 直到 不再合并反复把最常相邻出现的两个词粘成一个这就是建词表的过程。越早被合进词表的组合拿到的编号越小。从当前起点 找 词表里最长的匹配编码时能整词就不拆——从当前位置出发在词表里找能对上的最长词。这样切出的序列最短、最省词表里的条目越长一句话切出来的词数越少。给每个 id 附上位置编号光有 id 只能说明是哪个词说明不了在哪给第 i 个 id 挂上第 i 位的坐标模型才分得清顺序。位置坐标不一定只是一个整数可以是一组数多个维度——那是为了将来给图片这类形状不同的输入留出位置。入门阶段先把它当成第几号位置就够了。词表必须和训练时用的完全一致换一份词表同一个句子切出的 id 就全变了模型等于听不懂你说话输出会变成乱码。从文字到 id、再到位置坐标的过程如图 1 所示。图 1文字 → 子词 → id并给每个 id 一个位置坐标自上而下三层——原始文字先切成若干子词① 切法来自训练时的词表不能自己改② 每个子词查表得到一个 id③ 每个 id 再挂一个位置坐标位置 0、位置 1、……底部红框提醒词表必须和训练时完全一致。④ 纸笔实验必做任务给定词表{你:1, 好:2, 你好:3}分别按单字和整词两种方式编码你好比较得到的 id 序列长度。按单字只用 1、2 两项切出你好两个词 → id 序列[1, 2]长度2。按整词允许用 3整个词你好能对上 → id 序列[3]长度1。预期结果[1, 2]与[3]—— 整词编码的长度更短1 比 2。再用同一份词表编码好你整词项对不上只能切成[2, 1]。可见词的粒度决定了序列长短而位置编号[0, 1]、[0]让模型分得清你好和好你——同样两个 id顺序反了就不是一个意思。可选 REPL 版词表{你:1,好:2,你好:3}def编码(句子,词表):ids[]i0whileilen(句子):词句子[i]# 先试单字ifi1len(句子)and句子[i:i2]in词表:词句子[i:i2]# 能整词就整词ids.append(词表[词])ilen(词)returnids,list(range(len(ids)))# id 序列 位置编号print(编码(你好,词表))# ([3], [0])print(编码(好你,词表))# ([2, 1], [0, 1])⑤ 进阶锚点进阶锚点本篇概念在《30 天手搓推理引擎》Day 18里被真正实现——18-1 BPE 入门与 tokenizer.json为什么引擎不直接跑 BPE/18-2 tokenizer.json → vocab.binbuild_vocab_bin.py 在干嘛/18-3 MRoPE3D 位置编码给视觉留的席位。入门版到这里就够了进阶版会多出引擎为什么用字节流最长前缀 空格标记的工程近似替代逐条合并规则、词表如何被打包成二进制文件以及三维位置编码mrope的实测分歧分析引自进阶系列源码与文档口径。想动手 → 仓库https://gitee.com/pei-xiaoguang/kestrel-llm从 Day 1 开始。下篇预告文字能进模型了那图片呢下一篇看图片怎么进模型先切成小块、每块编码成一个向量再当成一组词和文字拼在一起。