大模型API的Token到底怎么算的?拆解各家计费逻辑
大模型API的Token到底怎么算的?拆解各家计费逻辑
摘要:用大模型API的时候,账单上的Token到底怎么算的?为什么输入和输出价格不一样?为什么换个问法费用就不同?本文从Token的本质讲起,拆解主流大模型的计费逻辑,附带费用估算和省钱技巧。
关键词:大模型API、Token计费、BPE分词、API成本优化
Token不等于字
调大模型API,每家都按Token计费。但Token不是字,也不是词。
大模型用BPE算法把文本切成小片段,每个片段就是一个Token。
"Hello" → 1个Token
"unhappiness" → "un" + "happi" + "ness" → 3个Token
"今天天气怎么样" → "今天" + "天气" + "怎么样" → 3个Token
验证一下:
import tiktoken
enc = tiktoken.encoding_for_model("gpt-4o")
print(len(enc.encode("Hello, how are you?"))) # 6
print(len(enc.encode("你好,最近怎么样?"))) # 7-8
同样一句话,中文Token数通常比英文多20-50%。所以用中文调API,费用会稍高一些。
不同模型的分词器不一样,同一个文本在不同模型里Token数可能不同。
计费公式
所有大模型API的计费都是一个公式:
总费用 = 输入Token数 × 输入单价 + 输出Token数 × 输出单价
输入和输出分开计价,输出通常比输入贵2-5倍。
因为大模型生成输出是逐Token生成的,每生成一个Token都要把之前的全部过一遍模型。输出的计算量比输入大,所以更贵。
一次API调用中,输入包括系统提示词、对话历史、用户当前输入。输出就是模型生成的回答。
response = client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": "你是一个技术顾问"}, # 输入
{"role": "user", "content": "什么是BGP"} # 输入
]
)
usage = response.usage
print(f"输入: {usage.prompt_tokens}") # 输入Token数
print(f"输出: {usage.completion_tokens}") # 输出Token数
各家定价对比
国际模型(每百万Token)
| 模型 | 输入 | 输出 | 输出/输入 |
|---|---|---|---|
| GPT-4o | $2.50 | $10.00 | 4倍 |
| GPT-4o-mini | $0.15 | $0.60 | 4倍 |
| Claude 3.5 Sonnet | $3.00 | $15.00 | 5倍 |
| Claude 3 Haiku | $0.25 | $1.25 | 5倍 |
国内模型(每百万Token,人民币)
| 模型 | 输入 | 输出 | 输出/输入 |
|---|---|---|---|
| 通义千问-Plus | ¥0.80 | ¥2.00 | 2.5倍 |
| DeepSeek-V3 | ¥1.00 | ¥2.00 | 2倍 |
| 豆包-Pro | ¥0.80 | ¥2.00 | 2.5倍 |
| 文心一言4.0 | ¥12.00 | ¥12.00 | 1倍 |
国内模型经过2024年几轮价格战,已经比2023年降了一个数量级。
一次调用到底花多少钱
写个函数算一下:
def estimate_cost(input_tokens, output_tokens, input_price, output_price):
"""input_price和output_price是每百万Token的价格"""
return (input_tokens / 1_000_000) * input_price + \
(output_tokens / 1_000_000) * output_price
# 一次典型的技术问答:输入300 tokens + 输出500 tokens
print(f"GPT-4o: ${estimate_cost(300, 500, 2.50, 10.00):.6f}") # $0.00575
print(f"GPT-4o-mini: ${estimate_cost(300, 500, 0.15, 0.60):.6f}") # $0.000345
print(f"DeepSeek-V3: ¥{estimate_cost(300, 500, 1.00, 2.00):.6f}") # ¥0.0013
单次调用看着便宜,但一天几千上万次调用累计起来就很可观了:
场景:每天5000次调用,每次输入500 tokens + 输出300 tokens
GPT-4o月费: 约$637(¥4,600)
GPT-4o-mini月费: 约$38(¥275)
同一个场景,选错模型差16倍。
藏在细节里的隐性成本
对话历史会重复计费
多轮对话中,之前的每一轮都会作为输入Token重复发送:
第1轮输入:300 tokens(系统提示 + 用户问题)
第3轮输入:1200 tokens(系统提示 + 两轮历史 + 新问题)
第10轮输入:4000 tokens(历史已经很长了)
对话轮次越多,每次调用的输入Token越多。这是多轮对话最大的隐性成本。
系统提示词每次都算
系统提示词不管你问什么都要发送,每次调用都算Token。
# 看起来不长,但一天5000次调用就重复5000次
system_prompt = "你是一个专业的Python技术顾问,拥有10年开发经验..."
# 假设100个Token,一天就是50万Token
流式输出不省钱
有些同学觉得stream=True会便宜。不会。流式只是返回方式不同,Token数和费用完全一样。
省钱的几个实用技巧
1. 选对模型
这比任何优化都有效。简单任务用小模型:
def select_model(task_type):
return {
"classify": "gpt-4o-mini",
"extract": "gpt-4o-mini",
"summarize": "gpt-4o",
"reasoning": "gpt-4o",
}.get(task_type, "gpt-4o-mini")
分类、提取、格式化这类任务,小模型够用,能省十几倍。
2. 压缩系统提示词
# 优化前:约100 tokens
system = "你是一个非常专业的Python技术顾问,拥有10年以上的开发经验。请用准确简洁的中文回答。如果不确定请说明。"
# 优化后:约30 tokens
system = "Python技术顾问。简洁中文回答。不确定时说明。"
效果差别不大,但一天5000次调用,光系统提示词每月就能省下几十美元。
3. 管理对话历史
def trim_history(messages, max_turns=5):
"""只保留最近N轮对话"""
system = [m for m in messages if m["role"] == "system"]
history = [m for m in messages if m["role"] != "system"]
return system + history[-(max_turns * 2):]
更进一步,把早期对话压缩成摘要:
def summarize_old_history(messages, client, max_turns=5):
system = [m for m in messages if m["role"] == "system"]
history = [m for m in messages if m["role"] != "system"]
if len(history) <= max_turns * 2:
return messages
old = history[:-(max_turns * 2)]
recent = history[-(max_turns * 2):]
# 用便宜的小模型生成摘要
summary = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": "用50字总结以下对话要点"},
{"role": "user", "content": str(old)}
]
).choices[0].message.content
return system + [
{"role": "system", "content": f"对话摘要:{summary}"}
] + recent
4. 限制输出长度
输出比输入贵好几倍。很多场景300 Token就够了:
response = client.chat.completions.create(
model="gpt-4o",
messages=messages,
max_tokens=300
)
# 提示词里也加上长度要求
{"role": "user", "content": "用100字以内解释BGP"}
不设max_tokens的话,模型可能生成很长的回答,白白多花钱。
5. 批量任务用Batch API
OpenAI的Batch API价格是实时API的50%。如果你有大批量数据要处理,不要一个一个调。
做好费用监控
上线之后一定要埋Token用量监控,不能等月底账单才发现超了。
class TokenTracker:
PRICING = {
"gpt-4o": {"input": 2.50, "output": 10.00},
"gpt-4o-mini": {"input": 0.15, "output": 0.60},
}
def __init__(self):
self.total_cost = 0
self.total_input = 0
self.total_output = 0
def record(self, model, input_tokens, output_tokens):
p = self.PRICING.get(model, {"input": 2.0, "output": 8.0})
cost = (input_tokens / 1_000_000) * p["input"] + \
(output_tokens / 1_000_000) * p["output"]
self.total_cost += cost
self.total_input += input_tokens
self.total_output += output_tokens
return cost
def report(self):
print(f"累计输入: {self.total_input:,} tokens")
print(f"累计输出: {self.total_output:,} tokens")
print(f"累计费用: ${self.total_cost:.4f}")
配合告警,超过预算就切换到便宜模型或者触发降级:
DAILY_BUDGET = 50.0
if tracker.total_cost > DAILY_BUDGET * 0.8:
# 切换到便宜模型
model = "gpt-4o-mini"
什么时候该自建推理
API费用高到一定程度,自建推理可能更划算。
粗略算法:
自建成本(2×A100 80GB):约12,000元/月(折旧+托管+运维)
GPT-4o API成本:
每天10,000次调用 × 每次800 tokens → 月费约18,000元
API月费超过12,000元时,可以考虑自建。 对应大约每天6,000-7,000次GPT-4o级别的调用。
但自建要考虑开源模型能力是否够用、团队是否有运维能力、延迟和吞吐是否满足需求。不是简单的经济账。
总结
- Token不等于字。中文比英文费Token。
- 输出比输入贵2-5倍。限制输出长度最直接。
- 对话历史每轮都重复计费。定期压缩。
- 选对模型比什么都重要。简单任务用小模型。
- 做好监控。别等月底才发现超了。
费用控制是持续优化的事。先跑起来,看数据,找优化空间,逐步迭代。
下一篇:AI推理会像CDN一样变成白菜价吗?一个IDC从业者的判断
觉得有用点个赞收藏,有问题评论区聊。
更多推荐



所有评论(0)