你有没有遇到过这种情况:在OpenAI的API里输入一段中文,Token数比你预想的多出一大截;换成英文,同样意思的内容Token却少了很多。或者用DeepSeek和Claude处理同一段文本,算出来的Token数居然不一样。
这不是错觉,而是Token计算本身的复杂性造成的。
Token可以理解为大模型处理文本时的最小“积木块”。它既不是字也不是词,而是介于两者之间的“子词(subword)”或“字节序列”。大模型看不懂原始文字,只能看懂数字。所以每一段文字输入模型之前,都要先被切分成Token,再映射成数字ID。
一、Token是怎么“切”出来的?——Tokenization的核心流程
把文本变成Token的过程叫Tokenization(分词),整个过程可以分为三步:
1.1 为什么不用“字”或“词”做最小单位?
如果用词做单位(比如英文单词),会遇到生僻词问题——模型不可能认识所有单词,遇到不认识的词就不知道怎么办了。
如果用字/字符做单位,又会导致序列太长——一个英文句子平均5个字符才等于1个词,序列长度直接膨胀5倍,计算量暴涨。
所以主流方案取了个折中:用子词(Subword)做单位。高频词保留为完整Token,低频词拆分成共享子词单元。这样既控制了词表大小,又能覆盖几乎所有文本。
举个直观的例子:英文单词"unhappiness"可能被拆成"un" + "happiness"两个Token,而不是一个完整的词,也不是一个一个字母。
二、三大主流分词算法:BPE、WordPiece、SentencePiece
不同模型用不同的分词算法,这是导致同样文本在不同模型里Token数不一样的根本原因。
2.1 BPE(Byte-Pair Encoding)——最主流
代表模型:GPT系列、Llama、Qwen2等
核心思想:从字母开始,不断合并出现频率最高的相邻字符对。
训练过程(简化):
初始词表:a, b, c, d, e, ...
第1步:发现 "ab" 出现次数最多 → 合并成 "ab"
第2步:发现 "ab" + "c" 出现最多 → 合并成 "abc"
第3步:继续合并,直到词表达到预定大小
特点:
纯数据驱动,只看统计频率
可逆且无损,Token可以完美还原回原文
OpenAI的tiktoken就是基于BPE的快速实现
2.2 WordPiece——BERT的选择
代表模型:BERT
与BPE的区别:BPE选频率最高的合并,WordPiece选能最大提升似然概率的合并——简单说,BPE看“谁出现最多”,WordPiece看“谁合并后效果最好”。
2.3 SentencePiece——语言无关的解决方案
代表模型:LLaMA、T5、ALBERT等
最大特点:把空格也当成普通字符处理,不需要预先按空格分词。这让它天然支持中文、日文等没有空格的语言。
三种算法对比总结:
| 算法 | 代表模型 | 核心逻辑 | 中文支持 |
|---|---|---|---|
| BPE | GPT、Llama、Qwen2 | 合并频率最高的相邻对 | 一般 |
| WordPiece | BERT | 合并后似然提升最大的对 | 一般 |
| SentencePiece | LLaMA、T5 | 把空格当字符,不依赖预分词 | 优秀 |
三、Token计算框架:模型是怎么算Token的?
3.1 OpenAI:tiktoken
OpenAI官方提供了一个叫tiktoken的Python库,专门用来计算OpenAI模型的Token数。
import tiktoken # 根据模型名称获取对应的编码器 encoding = tiktoken.encoding_for_model("gpt-4o") # 计算Token数 text = "Hello, how are you?" tokens = encoding.encode(text) print(f"Token数量: {len(tokens)}") print(f"Token列表: {tokens}")tiktoken的编码规则:不同模型用不同的编码(encoding)。比如cl100k_base是GPT-4系列用的编码,词汇表有10万个Token。
英文的估算规则:
1个Token ≈ 4个字符
1个Token ≈ 0.75个单词
100个Token ≈ 75个单词
3.2 DeepSeek:基于BPE的自研分词器
DeepSeek同样采用BPE算法,但词汇表和具体切分规则与OpenAI不同。这就是为什么同样一段中文,在DeepSeek和OpenAI里算出来的Token数不一样。
一个有意思的发现:在DeepSeek-V3和Qwen 3.6上,中文比英文更省Token——同样的内容,中文版的Token数只有英文版的0.65倍。这与OpenAI的情况正好相反(OpenAI里中文通常比英文更费Token)。
3.3 Hugging Face Tokenizers:统一框架
Hugging Face提供了tokenizers库,统一实现了BPE、WordPiece、Unigram等多种算法。
from transformers import AutoTokenizer # 加载任何Hugging Face模型的tokenizer tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased") # 分词并计算Token数 tokens = tokenizer.tokenize("Hello, how are you?") print(f"Token列表: {tokens}") print(f"Token数量: {len(tokens)}")Tokenizer的完整流水线:
Normalizer:标准化(转小写、去重音等)
Pre-tokenizer:预切分(按空格等规则初步拆分)
Model:核心分词算法(BPE/WordPiece/Unigram)
Post-processor:后处理(添加特殊标记如
[CLS]、[SEP]等)
四、模型之间Token计算的差异:为什么同样文本在不同模型里不一样?
4.1 差异来源一:词表大小不同
每个模型训练时都会构建自己的词表。词表越大,一个Token能覆盖的文本就越多。
| 模型 | 词表大小(约) |
|---|---|
| GPT-2 | 50,257 |
| GPT-4 (cl100k_base) | 100,000 |
| Llama 2 | 32,000 |
| DeepSeek-V3 | 129,000 |
词表越大,生僻词越可能被保留为完整Token而不是拆成多个,Token数就越少。
4.2 差异来源二:分词粒度不同
同样是中文"人工智能":
| 模型 | 可能的切分方式 | Token数 |
|---|---|---|
| 模型A | ["人工智能"] | 1 |
| 模型B | ["人工", "智能"] | 2 |
| 模型C | ["人", "工", "智", "能"] | 4 |
没有一个“标准答案”,全看模型训练时的分词策略。
4.3 差异来源三:特殊Token的添加
很多模型会在输入前后自动添加特殊Token:
[CLS](分类标记)—— BERT系列[SEP](分隔标记)—— BERT系列<|im_start|>、<|im_end|>(消息起止)—— 部分开源模型<|endoftext|>(文本结束)—— GPT系列
这些特殊Token也会计入总数,而且不同模型加的数量不一样。
五、多模态Token计算:图像、音频是怎么变成Token的?
多模态模型的Token计算比纯文本复杂得多——不同模态的Token是分开计算的,而且计算方式完全不同。
5.1 图像转Token:视觉编码器
多模态模型处理图像时,不是直接把图片“当作”Token,而是通过视觉编码器把图片转换成Token序列。
典型的转换流程:
以ViT-L/14为例,处理224×224分辨率图像时,默认生成196个Patch Token。分辨率越高,Token越多。
不同平台的图像Token计算规则:
| 平台/模型 | 图像Token计算方式 |
|---|---|
| StepFun | 默认每张图169 Token,开启detail模式后根据图片大小计算 |
| 通义千问VL | 最小28×28像素=1 Token,每张图最少4 Token,最多1280 Token |
| Qwen3-Omni | 图片/视频输入单独计价,与文本输入价格不同 |
5.2 音频转Token:声学特征提取
音频的处理方式又不一样——通过声学特征提取把声音信号转成Token序列。
不同模态的Token价格完全不同。以阿里云Qwen3-Omni-Flash为例:
| 模态 | 输入价格(元/百万Token) |
|---|---|
| 文本 | 3.156 |
| 图片/视频 | 5.725 |
| 音频 | 27.962 |
音频Token的价格是文本的将近9倍。
5.3 多模态Token是“相互”还是“分开”计算的?
答案是:分开计算,但合并计费。
计算上分开:文本走文本分词器,图像走视觉编码器,音频走声学编码器——各自独立转换成Token
计费上合并:最终把所有模态的Token数加在一起,按各自的价格分别计费
计费公式:
总费用 = (图像Token数 × 图像单价) + (音频Token数 × 音频单价) + (文本Token数 × 文本单价) + (输出Token数 × 输出单价)
5.4 多模态模型的“隐藏成本”
多模态调用有一个容易被忽略的成本:即使你只问了一个简单问题,模型也要先把整张图片转成几百个Token才能处理。
比如你发一张高清图问“这是什么?”,模型可能先消耗了500个图像Token“读图”,再用10个文本Token生成回答。读图的成本远高于回答本身。
六、VSCode实战:Token计算的完整代码示例
6.1 使用tiktoken计算OpenAI模型的Token
import tiktoken def count_tokens_openai(text, model="gpt-4o"): """ 使用tiktoken计算OpenAI模型的Token数 """ try: encoding = tiktoken.encoding_for_model(model) except KeyError: # 如果模型名不存在,使用默认编码 encoding = tiktoken.get_encoding("cl100k_base") tokens = encoding.encode(text) return len(tokens), tokens # 测试不同文本 test_texts = [ "Hello, how are you?", # 英文 "你好,最近怎么样?", # 中文 "Artificial Intelligence", # 英文单词 "人工智能", # 中文词汇 ] for text in test_texts: count, tokens = count_tokens_openai(text) print(f"文本: {text}") print(f" Token数: {count}") print(f" Token IDs: {tokens[:5]}...") # 只显示前5个 print()运行结果示例(实际数字可能因模型版本而异):
文本: Hello, how are you? Token数: 6 Token IDs: [9906, 11, 703, 527, 499, 30]... 文本: 你好,最近怎么样? Token数: 7 Token IDs: [44300, 106395, 16, 38412, 102, 450, 116]... 文本: Artificial Intelligence Token数: 3 Token IDs: [21646, 12518]... 文本: 人工智能 Token数: 2 Token IDs: [44300, 106395]...6.2 使用Hugging Face Tokenizer计算任意模型
from transformers import AutoTokenizer def count_tokens_hf(text, model_name="Qwen/Qwen2.5-7B"): """ 使用Hugging Face加载指定模型的tokenizer并计算Token """ tokenizer = AutoTokenizer.from_pretrained(model_name) tokens = tokenizer.tokenize(text) token_ids = tokenizer.encode(text) return len(tokens), tokens, token_ids # 测试 text = "人工智能正在改变世界" count, tokens, ids = count_tokens_hf(text) print(f"文本: {text}") print(f"Token数: {count}") print(f"Token列表: {tokens}") print(f"Token IDs: {ids}")6.3 对比不同模型的Token计算差异
import tiktoken from transformers import AutoTokenizer def compare_tokenizers(text, models): """ 对比不同模型对同一段文本的Token切分 """ results = {} # OpenAI模型 for model in models.get("openai", []): try: enc = tiktoken.encoding_for_model(model) tokens = enc.encode(text) results[f"OpenAI-{model}"] = { "count": len(tokens), "tokens": tokens[:10] # 只显示前10个 } except: pass # Hugging Face模型 for model in models.get("hf", []): try: tokenizer = AutoTokenizer.from_pretrained(model) tokens = tokenizer.tokenize(text) ids = tokenizer.encode(text) results[f"HF-{model}"] = { "count": len(tokens), "tokens": tokens[:10] } except: pass return results # 测试文本 text = "大语言模型的Token计算方式因模型而异" # 要对比的模型 models = { "openai": ["gpt-4o", "gpt-3.5-turbo"], "hf": ["Qwen/Qwen2.5-7B", "meta-llama/Llama-2-7b"] } results = compare_tokenizers(text, models) for model_name, data in results.items(): print(f"{model_name}: {data['count']} 个Token") print(f" 前10个Token: {data['tokens']}") print()6.4 多模态Token估算(模拟)
def estimate_multimodal_tokens(image_resolution=(224, 224), text="", audio_seconds=0): """ 估算多模态请求的Token消耗(模拟) """ total = 0 details = {} # 图像Token估算(基于ViT风格) if image_resolution: patch_size = 16 h, w = image_resolution image_tokens = (h // patch_size) * (w // patch_size) details["图像Token"] = image_tokens total += image_tokens # 文本Token估算(粗略) if text: # 粗略估算:中文约1.5 Token/字,英文约0.25 Token/字符 chinese_chars = sum(1 for c in text if '\u4e00' <= c <= '\u9fff') other_chars = len(text) - chinese_chars text_tokens = int(chinese_chars * 1.5 + other_chars * 0.25) details["文本Token"] = text_tokens total += text_tokens # 音频Token估算(粗略:1秒≈50 Token) if audio_seconds > 0: audio_tokens = int(audio_seconds * 50) details["音频Token"] = audio_tokens total += audio_tokens details["总计"] = total return details # 示例:一张图 + 一段文字 + 10秒音频 result = estimate_multimodal_tokens( image_resolution=(224, 224), text="请分析这张图片的内容", audio_seconds=10 ) print("多模态Token估算:") for key, value in result.items(): print(f" {key}: {value}")输出示例:
多模态Token估算: 图像Token: 196 文本Token: 7 音频Token: 500 总计: 703| 维度 | 核心要点 |
|---|---|
| Token是什么 | 大模型处理文本的最小单元,介于字和词之间的“子词” |
| 怎么计算 | 预处理 → 分词(BPE/WordPiece/SentencePiece)→ 映射为ID |
| 三大算法 | BPE(最主流)、WordPiece(BERT用)、SentencePiece(支持中文好) |
| 为什么不同模型不一样 | 词表大小不同、分词粒度不同、特殊Token不同 |
| 多模态怎么算 | 图像→视觉编码器转Token,音频→声学编码器转Token,分开计算、合并计费 |
| 主要框架 | OpenAI tiktoken、Hugging Face Tokenizers、Google SentencePiece |
小编建议
不要用字符数估算Token数:中文1个字≈1.5-2 Token,英文1个词≈1-1.5 Token
不同模型用不同的计算工具:OpenAI用tiktoken,Hugging Face用AutoTokenizer
多模态调用前先估算图像Token:一张高清图可能消耗几百个Token,成本远超你的想象
中文场景优先选中文优化好的模型:DeepSeek和Qwen的中文Token效率优于OpenAI
生产环境务必在代码里精确计算Token:不要靠猜,用官方工具算
小编团自动研发 大型文件翻译、文本润色链接
[免费]翻译全文网页,你是否为翻译烦恼?-CSDN博客