完整学习LLM(四):Token是什么
好家伙,
上一篇我们聊了:
text
为什么大模型是在预测下一个 token.
当时一直在说 token.
但其实还有一个问题没有拆:
text
Token 到底是什么?
这个词在大模型里出现得太频繁了.
比如:
text
上下文窗口是多少 token
输入 token 怎么计费
输出 token 怎么计费
这个模型最多支持多少 token
为什么一句中文和一句英文 token 数不一样
如果不理解 token,后面看上下文窗口、Embedding、Prompt、计费、RAG 切块都会有点虚.
所以这篇就单独聊它.
还是老规矩:
text
不先上复杂算法.
先用项目里能碰到的问题解释.
0.背景:为什么不能直接把一句话丢给模型
我们平时看到的是文字.
比如:
text
我想学习大模型和 RAG
但模型本身不能像人一样直接"看懂"这句话.
计算机最终处理的是数字.
所以文本进入模型之前,要先经历一个转换过程:
text
文本
-> 切成 token
-> token 转成编号
-> 编号转成向量
-> 进入模型计算
也就是说:
text
Token 是文本进入模型前的中间单位.
它不是最终的向量.
也不是我们看到的完整句子.
它更像是模型能处理文本之前,先把文本切成的一小块一小块.

1.Token不是简单等于一个字
很多人第一次理解 token,会直接想成:
text
一个 token = 一个字
这个理解不完全对.
有时候一个字可能是一个 token.
有时候一个词可能是一个 token.
有时候一个英文单词会被拆成多个 token.
有时候标点、空格也会影响 token.
比如英文:
text
unbelievable
它可能不是一个整体.
可能被拆成类似:
text
un
believ
able
再比如:
text
ChatGPT
也可能被拆成不同的小块.
中文也一样.
text
大模型
可能作为一个整体处理.
也可能被拆成:
text
大
模型
具体怎么拆,取决于模型使用的 tokenizer.
所以先记住一点:
text
Token 是模型的文本切分单位,但不一定等于一个字或一个词.
2.为什么要切成Token
原因很直接:
text
模型需要把文本变成可计算的数字.
如果不切,整篇文章就是一大坨字符串.
模型没法直接算.
切成 token 以后,每个 token 可以映射成一个 ID.
比如粗略想象:
text
我 -> 1024
想 -> 358
学习 -> 9012
大模型 -> 7718
RAG -> 64001
这些 ID 再进入下一步,变成向量.
向量才是模型真正能计算的东西.
所以 token 的作用有点像:
text
把人类文字拆成模型能查表、能编码、能计算的基本块.
如果没有 token 这一步,模型就不知道怎么把文本稳定地送进计算流程.
3.Token和预测下一个Token的关系
上一篇说过:
text
大模型是在预测下一个 token.
现在就更好理解了.
因为模型看到的不是:
text
我想学习大模型
而是一串 token:
text
[我] [想] [学习] [大模型]
它要做的是:
text
根据前面的 token,
预测后面最可能接哪个 token.
比如前面是:
text
我 想 学习
后面可能接:
text
大模型
Python
RAG
Docker
英语
模型会根据上下文算这些候选的可能性.
然后选择一个继续生成.
所以:
text
Token 是输入单位.
也是输出单位.
用户输入会被切成 token.
模型回答也是一个 token 一个 token 生成出来的.
4.Token为什么会影响上下文窗口
我们经常看到一个说法:
text
某个模型支持 128k 上下文.
这里的 128k,通常说的就是 token 数.
不是 128k 个汉字.
也不是 128k 个单词.
这点很重要.
因为模型的上下文窗口限制的是:
text
最多能放进去多少 token.
比如一个模型最多支持:
text
8192 tokens
那你输入的内容、系统提示词、历史对话、检索出来的资料、模型要输出的答案,都要挤在这个窗口里.
大概可以想成:
text
系统提示词
用户问题
历史对话
RAG 检索片段
工具返回结果
模型输出
这些加起来都占 token.
所以做 RAG 的时候,不是把文档全塞进去就完事.
因为文档太长,token 会爆.
这也是为什么 RAG 要做文档切块.
5.Token为什么会影响成本
大模型 API 通常会按 token 计费.
一般分成:
text
输入 token
输出 token
输入 token 是你发给模型的内容.
输出 token 是模型生成的内容.
比如:
text
Prompt 很长
历史对话很多
RAG 检索片段塞太多
模型回答很啰嗦
都会让 token 数上升.
token 数上升以后,通常会带来几个问题:
text
费用更高
响应更慢
上下文更容易塞满
模型更容易被无关信息干扰
所以工程上要控制 token.
不是越多越好.
尤其是 RAG.
如果每次检索都塞一大堆无关文档,看起来资料很多,实际可能让模型更乱.
6.为什么中文英文token数不一样
这个问题很多人会遇到.
同样一句意思,中文和英文的 token 数可能不一样.
原因是 tokenizer 的词表和切分方式不一样.
它不是按人类语言的"字数"或"单词数"简单统计.
比如英文里常见词可能会作为一个 token:
text
hello
world
function
但不常见的词可能会被拆开.
中文里有些常见组合也可能被合在一起,有些又会被拆开.
所以你看到:
text
字符数差不多,token 数不一样
这是正常的.
以后写 prompt 时,不要只看文字长度.
更重要的是:
text
最终被 tokenizer 切成了多少 token.
7.Token和RAG切块有什么关系
这个和前面几篇 RAG 文章能接起来.
RAG 里有一个步骤:
text
把长文档切成 chunk.
这里切块不能只按字数想.
更准确应该考虑 token.
因为最后塞进模型的是 token.
比如一个 chunk 太大:
text
一次塞进去占很多 token
上下文窗口很快满
检索出来的片段可能包含很多无关内容
模型抓重点更困难
chunk 太小也有问题:
text
语义可能被切碎
上下文不完整
检索结果看起来相关,但缺少前后解释
所以 RAG 切块本质上是在做一个平衡:
text
既要让片段足够完整,
又不能让 token 太多.
这就是 token 对工程落地的影响.
它不是一个纯理论概念.
它会直接影响知识库效果.
8.一个简单例子
假设我们有一段文档:
text
战斗监控接口用于查看战斗服运行状态.
部署时需要配置数据库连接、服务端口和 Nginx 反向代理.
如果直接作为文本看,我们觉得它只是两句话.
但进入模型前,它会被拆成一串 token.
大概可以理解成:
text
[战斗] [监控] [接口] [用于] [查看] [战斗服] [运行] [状态]
[部署] [时] [需要] [配置] [数据库] [连接] [服务] [端口] [Nginx] ...
注意这只是帮助理解的示意.
真实 tokenizer 不一定这么切.
但这个例子能说明:
text
模型不是拿整段中文直接算.
它拿的是 token 序列.
当你问:
text
战斗监控接口怎么部署?
RAG 检索到这段文档以后,也是把它作为 token 放进上下文.
然后模型根据这些 token 继续生成回答.
9.容易踩的几个坑
第一个坑:
text
以为 token 等于字数.
不等于.
字数只能粗略估计.
第二个坑:
text
以为上下文窗口越大越好.
窗口大当然有用,但塞太多无关内容,模型也会被干扰.
第三个坑:
text
RAG 检索片段越多越好.
不一定.
如果 TopK 太大,上下文会变长,噪声也会变多.
第四个坑:
text
忽略输出 token.
有时候输入不长,但模型回答很长,成本和延迟也会上来.
第五个坑:
text
Prompt 写得很啰嗦.
该清楚的地方要清楚.
但没必要每次都塞一堆重复废话.
10.总结
这篇主要想把 token 这个概念放稳.
我现在会这样理解:
text
Token 是文本进入模型前的切分单位.
模型通过 token 读入上下文,也通过 token 生成答案.
它会影响:
text
上下文窗口
API 计费
生成速度
RAG 切块
Prompt 长度
模型输出稳定性
所以以后看到:
text
这个模型支持多少 token
这次请求用了多少 token
RAG chunk 设置多少 token
输出限制 max_tokens
就不会觉得它只是一个计费单位.
它其实贯穿了大模型从输入到输出的整个流程.
最后一句话总结:
text
文字进入模型之前,要先变成 token;
模型生成答案时,也是一个 token 一个 token 往外接.
下一篇继续往下走:
text
Embedding 是什么?
为什么文本能变成向量?