欢迎拜访:雾里看山-CSDN博客
本篇主题:认识 Token:为什么大模型按 Token 计费
发布时间:2026.8.27
隶属专栏:AI进化之路
目录
- 先算一笔账
- 一句话理解 Token
- 为什么大模型不直接按"字"处理
- 1. 词表大小爆炸
- 2. 语义信息丢失
- 3. 跨语言支持差
- 三种主流分词方式
- 1. BPE(Byte Pair Encoding)
- 2. WordPiece
- 3. SentencePiece
- 动手看 Token 是怎么切的
- 安装分词器
- 用 Hugging Face 的 tokenizer
- 用 OpenAI 的 tiktoken
- 上下文长度到底在限制什么
- 一次调用到底花多少钱
- Token 相关的常见坑
- 坑 1:以为中文字符数和 Token 数是 1:1
- 坑 2:以为 Token 数就是字数
- 坑 3:忽略"看不见的"Token
- 坑 4:以为长上下文一定好
- 坑 5:不同模型的 Token 不能直接比较
- 实战:做一个简易成本计算器
- 这一篇到底要记住什么
- 给后续几篇打个底
先算一笔账
打开任何一家大模型平台的计费页面,几乎都会看到一句话:
按
Token计费。
刚开始学 AI 的人经常会问两个问题:
Token到底是个什么东西?为什么不是按"字"算钱?- 我写的一句中文,到底被算成了多少个
Token?
这一篇就把这两个问题讲清楚,同时把"上下文长度限制"和"成本控制"一起带出来。
一句话理解 Token
可以这样记:
Token是大模型在处理文本时使用的最小语义单元。它不是字,也不是词,而是模型自己定义的"切分粒度"。
对中文来说,常见的情况是:
- 一个汉字 ≈
1 ~ 2个Token。 - 一个英文单词 ≈
1 ~ 3个Token。 - 一个标点、空格、换行也算
Token,但通常按"半个左右"计入。
不同模型的Tokenizer(分词器)不同,但同一句话在不同模型上得到的 Token 数会有差异。
为什么大模型不直接按"字"处理
表面上看,按字处理最简单也最直观。但工程上不行,原因有三:
1. 词表大小爆炸
中文常用字有几万个。如果每个字都作为一个独立单元:
- 词表会非常大,Embedding 层参数会爆。
- 稀有字训练数据少,模型学不好。
2. 语义信息丢失
单字没有"词"的语义。比如"苹果公司"和"吃苹果",如果按字切分,模型很难直接学到"苹果"在不同语境下是不同含义。
3. 跨语言支持差
大模型要同时处理中、英、代码、公式等多语言。如果按字处理,跨语言一致性和对齐会非常麻烦。
所以最终主流大模型都选择了子词(Subword)切分方案,本质上是把"高频词"、“低频词”、"生僻字"统一拆成固定大小的基础单元。
三种主流分词方式
下面三种是学习大模型时绕不开的,理解它们的差异就够用了。
1. BPE(Byte Pair Encoding)
核心思路:从字符开始,不断合并出现频率最高的相邻字符对。
例如原始语料里有:
low low low newer newer newer wider wider wider- 第一轮:合并频率最高的
r+r→rr,得到lowe r这种组合。 - 第二轮:合并
e r→er。 - 反复迭代,直到词表大小达到设定值。
GPT系列、LLaMA系列基本都基于BPE或其变体。
2. WordPiece
和BPE类似,但合并的判断标准从"出现频率"换成"对语言模型概率提升的贡献"。BERT系列就是用WordPiece。
3. SentencePiece
可以理解为"语言无关版的BPE"。它直接以原始字节流(Unicode字符)为输入,不需要预分词。中文、日文等多语言模型大量采用SentencePiece。
把三者放在一起对比:
| 方案 | 训练粒度 | 典型用户 | 优点 | 缺点 |
|---|---|---|---|---|
BPE | 子词 | GPT/LLaMA | 简单、易实现 | 词表稳定性一般 |
WordPiece | 子词 | BERT | 概率驱动的合并 | 训练稍慢 |
SentencePiece | 字节级 | Qwen/ChatGLM | 语言无关、无需预分词 | 词表可能略大 |
动手看 Token 是怎么切的
光看概念太抽象。下面用一个最小的Python例子,把一段中文拆成Token。
安装分词器
pipinstalltransformers tiktoken用 Hugging Face 的 tokenizer
fromtransformersimportAutoTokenizer# 这里以 Qwen 的分词器为例,中文表现稳定tokenizer=AutoTokenizer.from_pretrained("Qwen/Qwen2.5-0.5B-Instruct",trust_remote_code=True)text="今天天气真不错,我想去爬个山。"tokens=tokenizer.tokenize(text)ids=tokenizer.encode(text)print("原文:",text)print("Token:",tokens)print("Token 数:",len(tokens))print("Token IDs:",ids)一次典型输出可能类似:
原文: 今天天气真不错,我想去爬个山。 Token: ['今天', '天气', '真', '不错', ',', '我', '想', '去', '爬', '个', '山', '。'] Token 数:12 Token IDs: [107340, 116882, 5971, 98288, 3837, 108540, 7291, 5391, 40854, 104728, 130309, 37011]可以看到:
- 高频词(
今天、天气)被合并成一个Token。 - 单字(
真)单独成为一个Token。 - 标点(
,、。)也算Token。
用 OpenAI 的 tiktoken
如果想直接看GPT系列的切分方式:
importtiktoken enc=tiktoken.encoding_for_model("gpt-4o-mini")text="今天天气真不错,我想去爬个山。"tokens=enc.encode(text)print("Token 数:",len(tokens))print("Tokens:",tokens)# 反向解码回文本print("反解码:",enc.decode(tokens))题外话:
tiktoken是OpenAI开源的纯Python实现,专门用来精确计算Token数,便于预算成本。
上下文长度到底在限制什么
很多同学把"上下文长度"理解成"最多能输入多少字"。更准确的说法是:
上下文长度限制的是一次请求中输入 Token + 输出 Token的总和。
常见上下文长度:
| 模型 | 上下文长度(Token) | 适合场景 |
|---|---|---|
GPT-3.5早期版本 | 4K | 短对话 |
GPT-4o | 128K | 长文档总结 |
Claude 3.5 Sonnet | 200K | 长代码、长文档 |
Gemini 1.5 Pro | 1M ~ 2M | 整本书、视频 |
Qwen2.5-72B | 128K | 长文本 |
DeepSeek-V3 | 64K ~ 128K | 长文本 |
需要注意:
- 上下文越长,推理延迟和成本都会显著上升,不是越长越好。
- 上下文长到一定程度,模型对中间位置的信息会出现"中间遗忘"现象。
一次调用到底花多少钱
假设使用GPT-4o-mini这种常见的小尺寸旗舰模型,假设输入0.15美元 / 百万Token,输出0.6美元 / 百万Token(价格会变动,以官方为准)。来算一笔账:
输入:5000 Token 输出:2000 Token 总费用: 输入费用 = 5000 / 1_000_000 * 0.15 = 0.00075 美元 输出费用 = 2000 / 1_000_000 * 0.60 = 0.00120 美元 合计 ≈ 0.00195 美元 ≈ 1.4 分钱如果每天调用 1 万次:
每日费用 ≈ 1.4 分 * 10000 = 140 元 每月费用 ≈ 140 * 30 = 4200 元这就是为什么在工程上必须做:
- 控制上下文长度:不必要的 Prompt 全部删掉。
- 控制输出长度:用
max_tokens限制最大输出。 - 分级使用模型:简单任务用便宜模型,复杂任务才用旗舰模型。
- 缓存重复 Prompt:相同的系统提示可以缓存。
Token 相关的常见坑
坑 1:以为中文字符数和 Token 数是 1:1
实际上中文 1 个字 ≈1 ~ 2个Token。把 1 万字的小说塞进 Prompt,可能要预留2 ~ 3万 Token 的预算。
坑 2:以为 Token 数就是字数
英文里1 Token大约对应4个字符。中文里要按"字符 / 0.75"粗略估算。
坑 3:忽略"看不见的"Token
在聊天接口里,每次请求其实包含三类内容:
system(系统提示)- 之前几轮
user / assistant对话 - 当前
user问题
所有这些全部计入 Token 总量。
坑 4:以为长上下文一定好
Gemini 1.5 Pro这种1M Token模型不是"万能"。把 50 万字的废话塞进去,模型依然会抓不住重点。质量比长度更重要。
坑 5:不同模型的 Token 不能直接比较
Qwen的 1000 个Token和GPT-4o的 1000 个Token,背后的语义粒度并不完全一样。迁移模型时要重新测一遍。
实战:做一个简易成本计算器
下面是一段可以直接拷贝运行的最小Python代码,用来估算一次调用的大致成本:
importtiktokendefestimate_cost(prompt:str,output_tokens:int=0,model:str="gpt-4o-mini"):enc=tiktoken.encoding_for_model(model)input_tokens=len(enc.encode(prompt))# 假设价格:单位是美元 / 1M Token,按官方最新价替换prices={"gpt-4o-mini":{"input":0.15,"output":0.60},"gpt-4o":{"input":5.00,"output":15.00},}p=prices[model]cost_in=input_tokens/1_000_000*p["input"]cost_out=output_tokens/1_000_000*p["output"]return{"input_tokens":input_tokens,"output_tokens":output_tokens,"cost_usd":cost_in+cost_out}if__name__=="__main__":prompt="请帮我把下面这段话翻译成英文,并保持原意。"print(estimate_cost(prompt,output_tokens=200))这段代码虽然简单,但已经是很多团队的"成本估算原型"。
这一篇到底要记住什么
Token是大模型处理的最小语义单元,不是字也不是词。- 主流分词方式有
BPE、WordPiece、SentencePiece,理解思路即可。 - 上下文长度限制的是"输入 + 输出 Token 总和"。
- 中文 1 字 ≈
1~2个Token,英文1 Token≈4个字符。 - 工程上必须做 Token 控制:精简 Prompt、限制
max_tokens、分级模型、缓存重复内容。
给后续几篇打个底
- 第 05 篇会带大家真正调一次大模型 API,把这一篇的
Token概念落到一段可运行的curl/Python示例上。 - 第 06 篇开始走"本地化"路线:用
Ollama/LM Studio在自己电脑上跑一个小模型,彻底绕开 Token 成本。
⚠️ 写在最后:以上内容是我整理 Token 概念时的一份学习笔记,本质上是把"为什么按 Token 收费"这件事从直觉层面拉到工程层面。如果你在实际项目里遇到"账单突然爆了"这种问题,可以从这一篇的四条控制手段逐条排查。