一文搞懂 AI 大模型 API 的 Token 计费机制
你有没有遇到过这种情况:调了一个月大模型 API,账单出来吓一跳,却完全不知道钱花在哪里了?这篇文章带你把 Token 计费机制彻底搞清楚,顺带分享几个实用的省钱技巧。
什么是 Token?
Token 是大模型处理文本的最小单位。模型并不是逐字读取文字,而是把文本切分成一个个 token 再处理。
中英文的 token 密度差异很大:
| 语言 | 大致换算 |
|---|---|
| 英文 | ~0.75 token / 词(“hello world” ≈ 2 tokens) |
| 中文 | ~1.5–2 token / 字(“你好世界” ≈ 6–8 tokens) |
| 代码 | 介于两者之间,标点和缩进单独占 token |
举个具体例子:
"今天天气不错,适合出门走走。"
→ 大约 20-24 tokens(包括标点)
"The weather is nice today, great for a walk."
→ 大约 10-11 tokens
所以中文应用的 token 消耗通常比同等英文内容高 2 倍左右,这在估算成本时非常重要。
Tokenizer 可视化工具
想直观感受 token 切分?可以用 TikToken 的在线工具,或者用代码自己跑:
# 安装:pip install tiktoken
import tiktoken
enc = tiktoken.get_encoding("cl100k_base") # GPT 系列使用的编码
text = "今天天气不错,适合出门走走。"
tokens = enc.encode(text)
print(f"文本: {text}")
print(f"Token 数: {len(tokens)}")
print(f"Token IDs: {tokens}")
注意:不同模型用不同的 tokenizer,上面这个是通用参考,各家模型的实际切分可能略有差异,但数量级差不多。
计费模型:input + output 分开算
大模型 API 的计费公式很简单:
费用 = input_tokens × 输入单价 + output_tokens × 输出单价
为什么 input 和 output 分开定价?因为两者的计算开销不同——生成 token(output)比处理 token(input)更耗算力,所以输出通常比输入贵。
国产主流模型定价对比(2025年参考)
价格以人民币每百万 tokens(元/M tokens)计,来源为各官方文档,实际以官网最新价格为准。
| 模型 | 输入价格(元/MT) | 输出价格(元/MT) | 上下文窗口 |
|---|---|---|---|
| DeepSeek-V3 | 0.27 | 1.10 | 64K |
| DeepSeek-R1 | 0.55 | 2.19 | 64K |
| Qwen-Max | 40 | 120 | 32K |
| Qwen-Plus | 4 | 12 | 131K |
| Qwen-Turbo | 0.3 | 0.6 | 1M |
| GLM-4-Flash | 0.1 | 0.1 | 128K |
| GLM-4 | 100 | 100 | 128K |
| Moonshot-v1-8k | 12 | 12 | 8K |
| Moonshot-v1-128k | 60 | 60 | 128K |
几个观察:
- DeepSeek-V3 性价比极高,效果媲美旗舰但价格接近零
- Qwen-Turbo 轻量任务首选,长上下文支持好
- GLM-4-Flash 超低价,适合高并发简单任务
- Moonshot 按上下文窗口分档计费,用多少上下文就选对应档位
推理模型的特殊计费:Thinking Tokens
DeepSeek-R1 这类推理模型在回答前会进行"思考",这个思考过程也会产生 tokens,计入计费。
import openai
client = openai.OpenAI(
api_key="your-api-key",
base_url="https://api.deepseek.com"
)
response = client.chat.completions.create(
model="deepseek-reasoner",
messages=[{"role": "user", "content": "证明根号2是无理数"}]
)
usage = response.usage
print(f"输入 tokens: {usage.prompt_tokens}")
print(f"输出 tokens: {usage.completion_tokens}")
# R1 的 usage 里有额外字段
if hasattr(usage, 'completion_tokens_details'):
details = usage.completion_tokens_details
print(f" 其中思考 tokens: {details.reasoning_tokens}")
print(f" 其中实际输出 tokens: {details.completion_tokens - details.reasoning_tokens}")
实际影响:R1 解一道复杂数学题可能产生 2000–5000 个 thinking tokens,加上实际答案。如果你的场景不需要深度推理,用 V3 就够了,便宜 4 倍。
影响 Token 消耗的关键因素
1. System Prompt
很多人忽略 system prompt 的 token 开销。如果你的 system prompt 有 500 字,每次请求都要带上,日均 1 万次调用就是 500 × 1万 = 500万 input tokens/天。
2. Few-shot 示例
给模型提供几个例子(few-shot)确实能提升效果,但代价是输入 token 暴增。每加一个示例对,通常增加 100–500 tokens。权衡效果和成本再决定用几个。
3. 对话历史(多轮对话)
多轮对话每次都要把历史记录全部发送:
第1轮:100 tokens
第2轮:100 + 150 = 250 tokens(带上第1轮)
第3轮:100 + 150 + 200 = 450 tokens(带上前两轮)
...
第N轮:累积增长
长对话的 token 消耗呈二次方增长,是成本失控的常见原因。
4. 输出长度
max_tokens 设置决定了模型最多能输出多少,但不代表一定会用完。不过对于生成任务(写文章、写代码),输出 tokens 往往占大头。
成本估算实战
场景:一个智能客服应用,日均 1 万次对话
假设:
- System prompt:300 tokens
- 平均用户输入:80 tokens
- 平均对话 3 轮(历史累积后平均约 600 tokens 输入)
- 平均输出:200 tokens
- 选用模型:Qwen-Plus(输入 4元/MT,输出 12元/MT)
计算:
每次请求输入 tokens ≈ 300(system)+ 600(历史+当前输入)= 900 tokens
每次请求输出 tokens ≈ 200 tokens
日消耗:
输入:900 × 10,000 = 9,000,000 tokens = 9 MT
输出:200 × 10,000 = 2,000,000 tokens = 2 MT
日费用:
输入:9 × 4 = 36 元
输出:2 × 12 = 24 元
合计:60 元/天
月费用 ≈ 1,800 元
如果换 DeepSeek-V3(输入 0.27元/MT,输出 1.10元/MT):
日费用:
输入:9 × 0.27 = 2.43 元
输出:2 × 1.10 = 2.20 元
合计:4.63 元/天
月费用 ≈ 139 元
选对模型,成本差 13 倍。
省钱技巧
技巧1:精简 System Prompt
把 system prompt 做极简化处理,只保留真正影响输出的指令。把 500 字的 system prompt 压缩到 100 字,每月省 80% 的 system prompt 成本。
技巧2:设置合理的 max_tokens
response = client.chat.completions.create(
model="deepseek-chat",
messages=messages,
max_tokens=500, # 根据实际需求设置上限,别让模型无限输出
temperature=0.7
)
技巧3:对话历史做截断
def trim_history(history: list, max_tokens: int = 2000) -> list:
"""保留最新的对话,总 token 不超过限制"""
# 简单实现:按字数估算,1 token ≈ 1.5 中文字
total_chars = 0
trimmed = []
for msg in reversed(history):
chars = len(msg["content"])
if total_chars + chars > max_tokens * 1.5:
break
trimmed.insert(0, msg)
total_chars += chars
return trimmed
技巧4:按任务选模型
- 简单分类/抽取 → GLM-4-Flash(便宜 100 倍)
- 通用问答/摘要 → DeepSeek-V3 或 Qwen-Turbo
- 复杂推理/代码 → DeepSeek-R1 或 Qwen-Max
- 超长文档处理 → Qwen-Turbo(100万 token 上下文)
技巧5:缓存高频相同请求
如果你的应用有大量重复问题(FAQ 类),在应用层做语义缓存,命中缓存的请求零 token 消耗。
Python 实战:记录和统计 Token 消耗
在生产环境中,必须把每次请求的 token 使用情况记录下来,方便对账和优化。
import openai
import json
from datetime import datetime
from dataclasses import dataclass, asdict
from typing import Optional
@dataclass
class TokenUsageRecord:
timestamp: str
model: str
prompt_tokens: int
completion_tokens: int
total_tokens: int
reasoning_tokens: Optional[int] # 推理模型专用
estimated_cost_cny: float # 估算费用(元)
# 各模型单价配置(元/百万tokens)
MODEL_PRICING = {
"deepseek-chat": {"input": 0.27, "output": 1.10},
"deepseek-reasoner": {"input": 0.55, "output": 2.19},
"qwen-max": {"input": 40.0, "output": 120.0},
"qwen-plus": {"input": 4.0, "output": 12.0},
"qwen-turbo": {"input": 0.3, "output": 0.6},
"glm-4-flash": {"input": 0.1, "output": 0.1},
}
def calculate_cost(model: str, prompt_tokens: int, completion_tokens: int) -> float:
pricing = MODEL_PRICING.get(model, {"input": 0, "output": 0})
input_cost = prompt_tokens / 1_000_000 * pricing["input"]
output_cost = completion_tokens / 1_000_000 * pricing["output"]
return round(input_cost + output_cost, 6)
def chat_with_tracking(
client: openai.OpenAI,
model: str,
messages: list,
usage_log: list,
**kwargs
) -> str:
"""发送请求并自动记录 token 使用"""
response = client.chat.completions.create(
model=model,
messages=messages,
**kwargs
)
usage = response.usage
reasoning_tokens = None
# 提取推理模型的 thinking tokens
if hasattr(usage, 'completion_tokens_details') and usage.completion_tokens_details:
reasoning_tokens = getattr(usage.completion_tokens_details, 'reasoning_tokens', None)
cost = calculate_cost(model, usage.prompt_tokens, usage.completion_tokens)
record = TokenUsageRecord(
timestamp=datetime.now().isoformat(),
model=model,
prompt_tokens=usage.prompt_tokens,
completion_tokens=usage.completion_tokens,
total_tokens=usage.total_tokens,
reasoning_tokens=reasoning_tokens,
estimated_cost_cny=cost
)
usage_log.append(asdict(record))
return response.choices[0].message.content
def print_usage_summary(usage_log: list):
"""打印 token 消耗汇总"""
if not usage_log:
print("暂无记录")
return
total_prompt = sum(r["prompt_tokens"] for r in usage_log)
total_completion = sum(r["completion_tokens"] for r in usage_log)
total_cost = sum(r["estimated_cost_cny"] for r in usage_log)
print(f"\n{'='*40}")
print(f"请求次数: {len(usage_log)}")
print(f"输入 tokens 合计: {total_prompt:,}")
print(f"输出 tokens 合计: {total_completion:,}")
print(f"估算总费用: ¥{total_cost:.4f}")
print(f"平均每次费用: ¥{total_cost/len(usage_log):.6f}")
print(f"{'='*40}\n")
# 使用示例
if __name__ == "__main__":
client = openai.OpenAI(
api_key="your-deepseek-api-key",
base_url="https://api.deepseek.com"
)
usage_log = []
questions = [
"用 Python 写一个快速排序",
"什么是 CAP 定理?",
"解释一下 Transformer 的注意力机制"
]
for q in questions:
answer = chat_with_tracking(
client=client,
model="deepseek-chat",
messages=[{"role": "user", "content": q}],
usage_log=usage_log,
max_tokens=500
)
print(f"Q: {q[:20]}...")
print(f"A: {answer[:100]}...\n")
print_usage_summary(usage_log)
# 保存详细日志
with open("token_usage.jsonl", "a") as f:
for record in usage_log:
f.write(json.dumps(record, ensure_ascii=False) + "\n")
运行后你会看到类似输出:
========================================
请求次数: 3
输入 tokens 合计: 487
输出 tokens 合计: 1,243
估算总费用: ¥0.001503
平均每次费用: ¥0.000501
========================================
总结
Token 计费的核心逻辑很简单,但魔鬼在细节里:
- 中文比英文贵 2 倍,估算时别用英文标准
- 推理模型有 thinking tokens,复杂问题成本可能超出预期
- 多轮对话是隐形成本,历史 token 线性累积
- 选对模型是最大的省钱手段,相同任务成本差距可达百倍
- 必须做 token 监控,否则成本失控时你根本不知道问题在哪
把 token 使用记录接入你的 metrics 系统,设置费用告警,比什么技巧都管用。
笔者在 TheRouter 中内置了用量统计面板,每次请求的 token 消耗、模型分布、费用明细都会自动汇总,不需要自己搭日志管道,对多模型场景下的成本归因非常有帮助。
作者:TheRouter 开发者,专注 AI 模型路由网关。项目主页:therouter.ai
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)