ARTICLE DETAIL

资讯详情

深耕网站SEO优化与搜索引擎排名提升的一线实战洞察。

不用正则与 Trie 树,如何用 600 行纯 C 写一个零拷贝 GGUF BPE 分词器?

不用正则与 Trie 树,如何用 600 行纯 C 写一个零拷贝 GGUF BPE 分词器? 图书馆的索书号有个好处:你不需要读完一本书就能确定它该放在哪一格。分词器干的是同一件事——把一串字节安放到词表的某个格子里,然后交给后面的矩阵乘法。区别在于,索书号放错了顶多让人多找十分钟,token 切错了,后面几百层注意力全都在读一段并不存在的文本。去年帮人排查过一次这样的事故。一个跑在本地的 agent,把工程里的 C 源码贴进 prompt 让模型改一处 bug,改出来的补丁八成对、两成完全离题,离题的那两成都集中在带缩进的代码块上。日志、采样参数、KV cache 全查过一遍,没有异常。直到把同一段文本喂给--dump-tokens,才看明白:四个空格开头的那一行,切出来的第一个片段是三个空格,第二个片段是一个空格加上后面的标识符。也就是说,模型看到的缩进结构和我在编辑器里看到的并不是一回事。这个切法本身是对的——它精确复刻了官方 pre-tokenizer 的行为——错的是我以为“文本进去、token 出来”是一层薄薄的转换。这一层一点都不薄。它是整条推理链路上唯一一处能在完全不报错、不崩溃、不留任何痕迹的情况下把语义悄悄改掉的地方。我打算把 ds4 这个项目里的那一层从头到尾拆开。它是纯 C 写的,没有任何第三方依赖,词表直接从 mmap 的 GGUF 文件里读,BPE 合并、special token 切分、chat 模板拼装总共不到六百行,全部塞在ds4.c的一个段落里(ds4.c:21685那个Tokenizer and Chat Prompt Encoding区块,一直到ds4.c:22555),对外接口是ds4.h:197-219
返回列表