引言“你的 prompt 到底用了多少 token”这是每日一个开源项目系列的第121篇文章。今天的主角是tiktoken——OpenAI 开源的官方分词器。在调用 OpenAI API 之前几乎每个开发者都会遇到同一个问题这段文本会消耗多少 token超出上下文限制了吗费用怎么估算这些问题的答案都藏在 tokenization 这一步里。tiktoken 不只是一个数 token 的工具它是 GPT 系列模型在训练和推理时真实使用的分词器。理解它就是理解模型真正看到的输入形态。你将学到什么BPE字节对编码算法的核心原理和4个关键特性tiktoken 支持哪些编码如何选择正确的编码如何精确计算 Token 数量避免 API 调用超限如何添加自定义特殊 tokentiktoken 的 Rust Python 架构为何能比同类工具快 3-6 倍前置知识基础 Python 使用经验了解 OpenAI API知道 token 是计费单位即可对 NLP/分词有基本概念可选项目背景项目简介tiktoken 是 OpenAI 发布的开源 BPEByte Pair Encoding字节对编码分词器库。它的核心职责是将文本字符串转化为 token 序列整数列表供语言模型消费也可以将 token 序列还原为原始文本。这不是一个实验性工具——它是 GPT-3.5、GPT-4、GPT-4o 等模型真实使用的分词器。当你通过 API 发送一段文字时模型看到的其实是 tiktoken 生成的 token 序列。作者/团队介绍作者: OpenAI项目创建: 2022年伴随 GPT-3 API 开放逐渐公开核心贡献: 由 OpenAI 工程团队维护Rust 核心部分提供高性能支撑知名度: 被 184,000 个 GitHub 项目依赖是 LLM 应用开发的基础设施项目数据⭐ GitHub Stars:18,400 Forks: 1,500 版本: 0.13.02026-05-15 License: MIT 语言组成: Python 64.9% Rust 35.1%主要功能核心作用tiktoken 做三件事Encode将文本转化为 token ID 列表整数数组Decode将 token ID 列表还原为原始文本可逆无损Count精确计算一段文本对应的 token 数量这三件事看起来简单但在 LLM 应用开发中至关重要上下文管理确保 prompt 历史消息不超过模型上下文限制成本估算在调用 API 前预估费用OpenAI 按 token 计费Prompt 工程了解模型实际接收到的文字单元优化分词边界使用场景API 调用前的 Token 预算控制在发送请求前检查是否超出max_tokens限制避免截断或报错长文档的智能分块Chunking将文档切割成不超过指定 token 数的块用于 RAG 检索增强生成多轮对话的上下文窗口管理动态裁剪历史消息确保对话历史始终在模型窗口内精确成本估算与监控构建 token 用量统计面板优化 prompt 的 token 效率Fine-tuning 数据预处理在准备训练数据时按 token 数量控制样本长度快速开始pipinstalltiktokenimporttiktoken# 方式一按编码名获取推荐用于新项目enctiktoken.get_encoding(o200k_base)# 方式二按模型名获取自动匹配模型对应的编码enctiktoken.encoding_for_model(gpt-4o)# 编码文本 → token ID 列表tokensenc.encode(Hello, tiktoken!)print(tokens)# [13225, 11, 384, 4963, 0]print(len(tokens))# 5 ← 这就是 token 数# 解码token ID 列表 → 文本textenc.decode(tokens)print(text)# Hello, tiktoken!# 可逆性验证assertenc.decode(enc.encode(任意文本都可以还原))任意文本都可以还原核心特性高性能 Rust 核心核心分词逻辑用 Rust 实现比同类 Python 分词器快 3-6 倍1GB 文本基准测试对比GPT2TokenizerFast可逆无损编码decode(encode(text)) text始终成立token 序列可完整还原原始文本通用性覆盖任意文本不依赖训练词表任意 Unicode 文本包括训练集外的内容都能正确分词高压缩率平均每个 token 对应约 4 字节文本英文约 4 字符中文约 1-2 字显著减少序列长度子词感知能识别英文常见子词如ing、tion、pre-帮助模型理解词法规律多编码支持内置o200k_baseGPT-4o、cl100k_baseGPT-4/3.5-turbo等主流编码特殊 Token 扩展支持自定义添加|im_start|等特殊控制 token适配 Chat 格式教育模块内置_educational模块可视化 BPE 合并过程适合学习算法原理项目优势对比对比维度tiktokenHuggingFace TokenizersSentencePiece速度⚡ 最快Rust核心快Rust核心中等C与 OpenAI 模型对齐✅ 官方一致❌ 近似❌ 不支持Python 接口简洁度✅ 极简中等中等支持模型范围OpenAI 系列通用通用自定义编码✅ 支持✅ 支持✅ 支持依赖包大小小中中为什么选择 tiktoken调用 OpenAI API 时只有 tiktoken 的计算结果与服务端完全一致极简 API两行代码即可完成 token 计数MIT 协议商业项目无障碍使用项目详细剖析BPE 算法4个关键特性BPEByte Pair Encoding字节对编码是 tiktoken 的核心算法。理解 BPE 的 4 个特性就能理解 tiktoken 的能力边界① 可逆无损Lossless Reversibilitytoken 序列可以 100% 还原为原始文本没有任何信息丢失。这是 BPE 的基础承诺originalGPT-4o 使用 o200k_base 编码assertenc.decode(enc.encode(original))original# 永远成立② 通用性Open Vocabularytiktoken 基于字节级 BPE词表从单个字节256个开始通过统计频率逐步合并最终覆盖高频子词。任何 Unicode 字符都能被分词——即使是模型从未见过的词# 训练集之外的新词、表情符号、代码全部可以正常分词enc.encode( tiktoken-v99 新词)# 不会报错③ 高压缩率High Compression平均每个 token 约对应 4 字节这意味着序列长度大幅缩短降低计算开销textThe quick brown fox jumps over the lazy dogtokensenc.encode(text)print(f字符数:{len(text)}, token数:{len(tokens)})# 字符数: 43, token数: 9 → 压缩率约 4.8:1④ 子词感知Subword AwarenessBPE 能识别词根、词缀等语言规律帮助模型泛化到未见过的组合# encoding → [encod, ing] 模型可以理解 encod- 的含义# tokenization → [token, ization]print(enc.decode([b])forbinenc.encode(encoding))编码选择指南选错编码会导致 token 计数与实际 API 调用不符。以下是完整对照表编码名称适用模型词表大小o200k_baseGPT-4o, GPT-4o-mini200,000cl100k_baseGPT-4, GPT-3.5-turbo, text-embedding-3-*100,000p50k_basetext-davinci-003 等旧版模型50,000r50k_baseGPT-3 (davinci) 等50,000importtiktokendefcount_tokens(text:str,model:strgpt-4o)-int:精确计算指定模型的 token 消耗enctiktoken.encoding_for_model(model)returnlen(enc.encode(text))# 测试print(count_tokens(Hello, world!))# 4print(count_tokens(你好世界))# 6自定义特殊 TokenChat 模型如 gpt-3.5-turbo使用特殊 token 来界定角色边界。你可以扩展现有编码来支持这些控制符importtiktoken cl100k_basetiktoken.get_encoding(cl100k_base)# 创建带 Chat 格式特殊 token 的扩展编码enctiktoken.Encoding(namecl100k_im,# 自定义名称pat_strcl100k_base._pat_str,mergeable_rankscl100k_base._mergeable_ranks,special_tokens{**cl100k_base._special_tokens,|im_start|:100264,# 角色开始|im_end|:100265,# 角色结束})# 现在可以编码包含特殊 token 的 Chat 格式文本text|im_start|user\nWhat is BPE?|im_end|tokensenc.encode(text,allowed_special{|im_start|,|im_end|})print(ftoken 数:{len(tokens)})实际应用精确的 Token 预算控制这是 tiktoken 最高频的使用场景——在发送 API 请求前检查并裁剪消息列表importtiktokendeftrim_messages_to_budget(messages:list[dict],model:strgpt-4o,max_tokens:int8000,)-list[dict]: 裁剪消息历史确保 token 总数不超过预算。 保留 system prompt从最旧的 user/assistant 消息开始删除。 enctiktoken.encoding_for_model(model)defcount(msgs):# 每条消息有 4 token 的固定开销角色、分隔符等totalsum(4len(enc.encode(m.get(content,)))forminmsgs)returntotal2# 回复前置的 2 tokensystem[mforminmessagesifm[role]system]others[mforminmessagesifm[role]!system]whilecount(systemothers)max_tokensandothers:others.pop(0)# 删除最旧的消息returnsystemothers# 使用示例messages[{role:system,content:你是一个助手。},{role:user,content:第一个问题},{role:assistant,content:第一个回答},# ... 更多历史消息]trimmedtrim_messages_to_budget(messages,max_tokens4096)教育模块可视化 BPE 过程tiktoken 内置了一个教育用的简化版 BPE 实现适合学习算法原理fromtiktoken._educationalimportSimpleBytePairEncoding# 使用真实的 cl100k_base 合并规则训练一个简化编码encSimpleBytePairEncoding.from_tiktoken(cl100k_base)# 可视化分词过程resultenc.encode(hello world aaaaaaaaaaaa)# 输出会显示每一步合并的过程架构解析为什么这么快tiktoken 之所以比同类工具快 3-6 倍关键在于其Python Rust 混合架构tiktoken/ ├── tiktoken/ │ ├── __init__.py ← Python 接口层 │ ├── core.py ← 主 APIEncoding 类 │ ├── model.py ← 模型名 → 编码名的映射表 │ ├── registry.py ← 编码注册与缓存 │ └── _educational.py ← 教育用纯 Python BPE 实现 │ └── src/ (Rust) └── lib.rs ← 高性能 BPE 核心逻辑通过 PyO3 暴露给 Python性能关键点Rust 核心BPE 的合并循环用 Rust 实现避免了 Python 的 GIL 和解释器开销PyO3 绑定Rust 函数通过 PyO3 直接暴露为 Python 对象调用开销极低词表缓存编码词表在首次加载后缓存到内存避免重复 I/O正则预分割在 BPE 之前用高效正则表达式预先切分文本处理空格、标点边界项目地址与资源官方资源GitHub: openai/tiktoken使用教程: OpenAI Cookbook - How to count tokensIssue Tracker: github.com/openai/tiktoken/issues相关资源OpenAI Tokenizer 可视化工具在线查看文本的分词结果OpenAI API Token 计费说明Hugging Face Tokenizers 文档对比参考总结tiktoken 的价值不只在于数 token它是连接开发者与 GPT 模型之间的翻译层。掌握 tiktoken意味着你真正理解了模型的输入形态能够精确控制上下文、估算成本、构建健壮的 LLM 应用。Rust 核心 Python 接口的设计选择也是一个值得借鉴的工程范式把性能关键路径交给系统语言把易用性和灵活性留给动态语言。欢迎来我的个人主页找到更多有用的知识和有趣的产品