tiktoken 实战:5 分钟搞定 o200k_base 文本编码
【免费下载链接】tiktokentiktoken is a fast BPE tokeniser for use with OpenAI's models.项目地址: https://gitcode.com/GitHub_Trending/ti/tiktoken
当你把一段中英混排的需求文档丢给 GPT-4o 之前,最该先搞清楚的是:这段文字到底会被切成多少 token?tiktoken 就是干这件事的——它是 OpenAI 官方出品的 BPE 分词器,一行get_encoding("o200k_base")就能拿到和新模型完全一致的编码规则,本地算出的 token 数和线上账单对得上。
一句话讲清:tiktoken 是模型的"切词刀"
语言模型读不懂文字,它读的是一串数字(token)。BPE(Byte Pair Encoding,字节对编码)负责把任意文本压缩成这串数字,并且可无损还原。
tiktoken 就是 OpenAI 这套 BPE 分词器的 Python 实现,核心是用 Rust 写的,比同类开源分词器快 3~6 倍(README 里用 1GB 文本实测的数据)。它内置了 gpt2、cl100k_base、o200k_base 等 7 套编码,o200k_base是最新一代:词表 200,000 个 token,比上一代 cl100k_base 的 100,000 整整翻倍,gpt-4o、gpt-5、o1、o3 这些新模型用的都是它。
核心机制拆解
内部到底做了什么:词表 + 一条"切分规则"
每套编码其实是两样东西:一张词表(哪些字符串片段对应哪个编号),加一条正则表达式(决定先按什么规则把文本切成小块,再去词表里配对合并)。
以 o200k_base 为例,它的正则拆成 7 段规则:大小写混合的词、全大写的词、不超过 3 位数字的连续数字、成片的符号、换行、空格、普通空白。用 Unicode 字符类别(比如\p{L}表示任意语言的字母,不分中文英文)判断,所以中英文都能被正确识别成"词"而不是逐字硬拆。词表从 100,000 扩到 200,000 意味着:常见词组有更大概率作为一个整体存在,编码时少拆、解码时更省空间。想看内部细节可以翻 tiktoken_ext/openai_public.py,每套编码的词表地址、特殊 token、正则都写在那里;分词性能则来自 Rust 侧的 src/lib.rs。
同一段文本,cl100k 和 o200k 切出来不一样
拿一段带代码的中英混排文本(比如def hello(): print("你好")加几句中文说明),分别用 cl100k_base 和 o200k_base 编码,token 序列和数量都对不上——这不是 bug,是两把不同的刀。
import tiktoken old = tiktoken.get_encoding("cl100k_base") new = tiktoken.get_encoding("o200k_base") text = 'def hi():\n print("你好, world")' print(len(old.encode(text)), len(new.encode(text)))同一段文本在 cl100k 下切出的 token 数,和 o200k 下通常差 10% 上下,具体多少取决于文本里符号、换行、中文的占比。切词方式不同,连 token ID 都没法互相换算。
从零跑起来:pip install tiktoken
环境要求 Python 3.9 及以上。装好直接跑:
import tiktoken enc = tiktoken.get_encoding("o200k_base") text = "你好,世界!hello o200k_base" tokens = enc.encode(text) print(tokens, len(tokens)) assert enc.decode(tokens) == text跑完你应看到一串 token ID 列表、token 总数,以及 assert 静默通过(说明编解码无损往返)。注意首次运行会从 OpenAI 的 CDN 下载几 MB 的词表文件并缓存到本地,需要联网,之后就走缓存了。
真实场景下的表现
场景一:中英混排文档。输入用户侧的 API 调用超时后请 retry 3 次,输出为若干 token。中文部分按词切("用户"、"调用"各自成块),夹带的英文和数字也整块处理,o200k 的词表更大,这类文本切出来的 token 数普遍比 cl100k 少 10%~20%——直接反映在 API 的 input 计费上。
场景二:代码块。输入上面那段 Python 代码,{、}、"、换行都被正则的符号/空白规则单独成组,而不是和字母黏在一起切碎;o200k 的正则比 cl100k 多了对大小写形态的区分(全大写词和混合大小写词分别走不同分支),标识符切分更整齐。
场景三:长文档批量计数。用encode_batch处理几千行文本时,Rust 内核让它比 Python 版分词器快 3~6 倍,这也是 tiktoken 相比 HF tokenizers 的主要卖点;只关心数量不关心内容时,直接拿 token 列表长度即可。
踩坑与避坑
首次运行卡住或报错。现象是get_encoding一直不返回或直接失败。原因是它要联网下载 o200k_base.tiktoken 词表,离线环境会挂。解法:先在能联网的机器上跑一次生成缓存,把缓存目录拷过去再部署。
换了编码后 token 数突然变了。现象是同一句话从 cl100k 换成 o200k,数字对不上。原因是两套词表和正则完全不同,token 数本来就不该一致。解法:token 统计永远锁定一个编码,别混着算。
用错了编码,token 数和模型对不上。现象是本地数 320 个 token,API 却报 350。原因是 gpt-4、gpt-3.5-turbo 用 cl100k_base,而 gpt-4o、gpt-4.1、gpt-5、o1、o3 用 o200k_base。解法:tiktoken.encoding_for_model("gpt-4o")让库替你查表,别手写。
解码回来"缺字"或多了奇怪符号。现象是 round-trip 结果和原文不一样。原因是文本里有特殊 token(如 `
【免费下载链接】tiktokentiktoken is a fast BPE tokeniser for use with OpenAI's models.项目地址: https://gitcode.com/GitHub_Trending/ti/tiktoken
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考