乐于分享
好东西不私藏

AI 基础-1 Tokenizer 不是预处理:它决定大模型如何看见世界

AI 基础-1 Tokenizer 不是预处理:它决定大模型如何看见世界


很多人第一次学大模型,会从 Transformer 开始:注意力、层数、参数量、显卡。讨论到后面,还会继续追问 MoE、推理加速、RLHF。

这些当然都重要。但如果回到模型真正开始工作的第一秒,会发现它根本没有看到“文字”。它看到的是一串离散的整数:`[15496, 995, ...]`。用户输入、企业文档、代码、表格、表情符号,都会先被切成 token,再进入模型。

这就是 Tokenizer 容易被低估的原因:它看起来只是预处理,实际上却在定义模型的输入语言。你可以把它理解成镜头、分词器,甚至是大模型世界里的计量单位。镜头失焦,后面的再大模型也只能在失焦的世界里学习;计量单位不统一,成本、长度和效果的讨论也会跟着失真。

## 一、模型不是读文字,而是在预测编号

一句“今天天气不错”,人看到的是自然语言、语气和场景;模型看到的是若干编号。Tokenizer 负责两件事:把文本编码成 token ID,以及把模型生成的 token ID 解码回文本。

这件事之所以不简单,是因为自然语言不是一个封闭集合。新产品名、新人名、地址、拼写错误、代码变量、日期、货号,会不断出现。

如果按“一个完整词一个编号”,词表很快爆炸。中文没有天然空格,英语还会不断遇到复数、时态、组合词;如果把每个罕见词都塞进词表,模型参数和长尾维护都会失控。

反过来,如果按“一个字节一个编号”,任何内容都能表示,但同一句话会被拆得很长。模型每增加一个 token,都要多一次位置计算、多一次注意力交互,还要占用更多上下文窗口。看起来什么都支持,实际上把计算账单推给了训练和推理系统。

主流子词方案做的就是折中:把常见片段保留成较大的 token,把罕见词拆成更小、可复用的片段。BPE 的直觉很朴素:频繁一起出现的字符或片段,值得合并;很少见的词则允许由更小单元拼出来。它解决的不是“把词切得漂亮”,而是开放词表问题——模型即使没见过一个完整新词,也不必只剩下 `UNK` 这一条死路。

## 二、Tokenizer 决定模型看见世界的颗粒度

同样是“订单号 SO-2026-0812-001”,一种 tokenizer 可能把它切成少量稳定片段,另一种则可能拆成很多零散字符。两者都能把文本送进模型,但模型要学习的难度不同。

前一种情况,模型更容易识别“这是订单号”“这一段像日期”“这一段是流水号”;后一种情况,模型得先在大量碎片中重新学会这些结构。对通用聊天,差异可能不明显;对合同、报表、代码、医学缩写、物流单号这类高密度场景,差异会被放大。

这也是为什么我更倾向于把 Tokenizer 看成能力边界的一部分,而不是一个不可触碰的默认配置。它决定了模型的基本颗粒度:模型到底是按词、子词、字节,还是按某些高频符号组合去组织经验。

这里有一个常见误区:认为词表越大越好。词表更大,某些常见词确实可以被压缩成更少 token;但 embedding 和输出层也会膨胀,尾部 token 的训练样本又可能不足。词表更小,覆盖更稳,却可能让序列变长、计算更贵。不存在脱离任务的最优答案,只有围绕数据分布、语言覆盖、上下文和硬件预算的取舍。

## 三、它为什么直接影响成本

大模型的很多成本,本质上按 token 发生。

训练时,token 数进入序列长度和训练预算;推理时,输入 token 越多,prefill 越慢,KV Cache 占用越大;产品计费时,用户看到的是一段文字,平台实际承担的却是输入与输出 token 的消耗。

所以同一份 20 页文档,不能只问“有多少字”,还要问“对当前 tokenizer 来说有多少 token”。同一套 Prompt,不能只看文字写得是否优雅,还要看它是否重复、是否夹带冗长表格、是否把每次都不会变的系统信息反复发送。

一个很现实的案例是企业知识问答。团队常常把完整制度、历史工单、几十列 CSV 直接塞进上下文,模型偶尔能答对,就以为 RAG 做成了。但过一段时间会发现:延迟越来越高,成本越来越高,答案还越来越不稳定。很多时候问题不是模型“记不住”,而是信息被送入时已经被切成过多碎片,关键规则埋在长上下文里,模型很难稳定地给出正确权重。

Tokenizer 当然不是这个问题的唯一解,但它提醒我们:文本进入模型之前并不是无损的。任何输入设计,都是在为后续的成本、注意力分配和错误模式埋伏笔。

## 四、多语言、代码和业务字段,最容易暴露问题

英文世界里表现良好的 tokenization,不一定天然适合中文、日文、阿拉伯文或混杂文本。不同语言的平均 token 长度、标点使用、形态变化都不一样;代码还会混入缩进、路径、版本号和专有符号。若某类数据被异常切碎,它会在相同上下文窗口里损失表达空间,也会在训练中占用更多预算。

业务系统则更复杂。客户名、车牌号、合同编号、币种、计量单位、业务缩写,经常既关键又长尾。它们不是因为“切得不好”就一定答错,而是因为模型未必知道这些片段之间的关系。此时只换 tokenizer 也解决不了全部问题,仍然需要结构化字段、检索过滤、工具调用和评测;但不理解 token 边界,就很容易把问题误诊成“模型不够大”。

因此,Tokenization 还带来一个更大的工程提醒:不要把所有业务语义都寄托在纯文本里。对身份、金额、日期、状态、权限等关键对象,能结构化就结构化;让模型解释、归纳和对话,而不是让它从一长串字符里猜数据库主键。

## 五、今天怎么做:把 Tokenizer 放进你的检查清单

如果你做 LLM 应用或领域模型,可以从下面四步开始。

第一,抽取 100 条真实输入做 token 审计。不要只看干净英文样例,要覆盖中文、数字、表格、代码、混合语言、长文档和最常见的异常输入。记录每条文本的字符数、token 数和异常切分案例。

第二,单独检查高价值字段。产品型号、人名、订单号、日期、单位、币种、法律条款、SQL、公式,到底被切成什么?它们在模型回答失败的样本里出现频率多高?这比泛泛讨论“tokenizer 好不好”更有用。

第三,把 token 数写进评测面板。每次改 Prompt、改检索 chunk、改模型或改系统消息时,同时看回答质量、上下文长度、首 token 延迟和单位任务成本。效果提高 1%,成本翻倍,未必是好优化。

第四,为长期演进保留边界。Tokenizer 一旦更换,历史向量、缓存、训练数据、微调权重和线上指标都可能受到影响。它不是一个可以随手替换的小库,而是一项需要版本化、灰度和回归验证的基础设施决策。

真正成熟的团队不会把 Tokenizer 当成透明空气。它会持续问:我们的用户到底在说什么?这些内容被模型切成了什么?这种切法让模型学到了什么,又让我们付出了什么?

从“会调模型”走向“理解模型”,这就是非常扎实的第一步。