认识 Token:为什么大模型按 Token 计费
欢迎拜访:雾里看山-CSDN博客
本篇主题:认识 Token:为什么大模型按 Token 计费
发布时间:2026.8.27
隶属专栏:AI进化之路

目录
先算一笔账
打开任何一家大模型平台的计费页面,几乎都会看到一句话:
按
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。
安装分词器
pip install transformers tiktoken
用 Hugging Face 的 tokenizer
from transformers import AutoTokenizer
# 这里以 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 系列的切分方式:
import tiktoken
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 代码,用来估算一次调用的大致成本:
import tiktoken
def estimate_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 收费"这件事从直觉层面拉到工程层面。如果你在实际项目里遇到"账单突然爆了"这种问题,可以从这一篇的四条控制手段逐条排查。
更多推荐

所有评论(0)