大模型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级别的调用。

但自建要考虑开源模型能力是否够用、团队是否有运维能力、延迟和吞吐是否满足需求。不是简单的经济账。


总结

  1. Token不等于字。中文比英文费Token。
  2. 输出比输入贵2-5倍。限制输出长度最直接。
  3. 对话历史每轮都重复计费。定期压缩。
  4. 选对模型比什么都重要。简单任务用小模型。
  5. 做好监控。别等月底才发现超了。

费用控制是持续优化的事。先跑起来,看数据,找优化空间,逐步迭代。


下一篇:AI推理会像CDN一样变成白菜价吗?一个IDC从业者的判断

觉得有用点个赞收藏,有问题评论区聊。

Logo

欢迎加入DeepSeek 技术社区。在这里,你可以找到志同道合的朋友,共同探索AI技术的奥秘。

更多推荐