LLM-07入门9 min

Token 计费与上下文长度:被忽视的成本杀手

Token 是 LLM 收费的基本单位,但大多数人只关注模型能力,忽略了成本优化。一个128K 上下文的模型跑满和不跑满,成本差 10 倍。本文从计费原理出发,详解跨境电商场景的成本控制实战技巧。

Token计费上下文窗口成本优化

Token 是怎么计费的

LLM API 的收费逻辑很简单:按 token 计费,输入和输出分开算。模型厂商有一个公开的定价表(price per 1M tokens),你的实际成本 = (输入 tokens + 输出 tokens) × 单价。

GPT-4o 的定价约 $2.5/1M 输入 tokens,$10/1M 输出 tokens。Claude Sonnet 4 是 $3/1M 输入,$15/1M 输出。看起来单价不贵,但当你的日均调用量达到百万级别时,成本就开始显著了。

token_cost_calc.py
#主流模型定价对比(单位:USD per 1M tokens)
models = {
    "GPT-4o (2024-05)": {"input": 2.5, "output": 10.0},
    "GPT-4o-mini":           {"input": 0.15, "output": 0.60},
    "Claude Sonnet 4":       {"input": 3.0, "output": 15.0},
    "Claude Haiku 3.5": {"input": 0.8, "output": 4.0},
    "Qwen2.5-72B (API)":     {"input": 0.5, "output": 1.5},
    "DeepSeek V3":           {"input": 0.27, "output": 1.1},
}

def calc_cost(model, input_tokens, output_tokens):
    return (input_tokens * models[model]["input"] + output_tokens * models[model]["output"]) / 1e6

print("单次调用成本估算(100 input + 500 output tokens):")
for model, prices in models.items():
    cost = calc_cost(model, 100, 500)
    print(f"  {model:<25}: ${cost:.4f}")

print("\n日均 10000 次调用的月成本:")
for model, prices in models.items():
    daily = calc_cost(model, 100_000, 5_000_000)
    monthly = daily * 30
    print(f"  {model:<25}: ${monthly:.2f} / 月")

上下文窗口:标称值 vs 实际可用

每个模型都有一个上下文窗口上限(如 GPT-4o 128K,Claude 3.5 200K),但"标称"和"实际可用"是两回事:

显存限制:KV Cache 需要把每个 token 的 Key 和 Value 矩阵存到显存里。13B 模型单 token 的 KV Cache 约 1MB,128K 上下文需要 128GB 显存——单卡放不下,需要 Tensor Parallelism,增加延迟。

计算成本 O(n2):Attention 的计算复杂度是序列长度的平方。128K token 的计算量是 32K 的 16 倍,延迟和费用都急剧上升。

质量稀释:超过一定长度后,模型对上下文中部信息的关注度下降("lost in the middle"问题)。实验表明,在 128K 上下文中,只有开头和结尾 10-20% 的信息能被可靠召回。

context_effective.py
import numpy as np

def effective_context_ratio(actual_tokens, max_tokens):
    usage_ratio = actual_tokens / max_tokens
    if usage_ratio < 0.3:
        return 0.95
    elif usage_ratio < 0.5:
        return 0.85
    else:
        middle_loss = (usage_ratio - 0.5) * 0.4
        return max(0.7, 0.85 - middle_loss)

print("有效上下文比例估算:")
for max_ctx in [32, 128, 200]:
    print(f"\n  {max_ctx}K 上下文窗口:")
    for actual in [8, 32, 64, 128]:
        if actual > max_ctx:
            continue
        ratio = effective_context_ratio(actual, max_ctx)
        print(f"    {actual}K实际使用:有效率约 {ratio*100:.0f}% (利用率 {actual/max_ctx*100:.0f}%)")

print("\n结论: 128K 窗口用到 64K 时,中间信息质量已显著下降")

中文用户的实际痛点:中文 tokenization 效率低于英文(一个字通常 1-2 tokens),同样的 128K token 窗口,中文承载的有效信息量约等于英文的 60-70%。这意味着中文用户应该把"有效上下文"按60-70% 折算,实际可用量比标称值短得多。

Token 计数的原理

理解 tokenization 才能优化 token 用量。不同模型用不同的分词器:

GPT 系列(Tiktoken):用 BPE(字节对编码),英文效率高。一个常见英语单词 = 1 个 token,标点 = 1 个 token。

中文模型(Qwen、GLM):用 SentencePiece/Unigram,中文效率较低。中文一个字通常 1-2 个 token。

tokenize_demo.py
# 使用 tiktoken 计算 token 数(GPT 同款分词器)
import tiktoken

enc = tiktoken.get_encoding("cl100k_base")

texts = [
    "Running shoes for men breathable lightweight",
    "男士轻便透气跑步运动鞋",
    "Nike Air Max 270, the best-selling sneaker with Air Max cushioning",
    "Nike Air Max 270 超轻缓震跑步鞋男款黑武士透气网面",
    "USD 299.99",
    "$299.99",
]

print("Token 数对比(Tiktoken cl100k_base):")
for text in texts:
    tokens = enc.encode(text)
    print(f"  {len(tokens):>3} tokens | {text[:50]}")

# 关键观察:
# - 英文品牌名 "Nike" = 1 token
# - 中文字符串 token 数普遍较高
# - 数字+货币符号两种写法 token 数相近

数字的特殊性:数字在 LLM 中是按 digit 逐个 token 化的。"299.99" 会被分解成 "2"、"9"、"9"、"."、"9"、"9" = 6 个 tokens,而 "$" 是另一个 token。如果你的场景涉及大量价格,数字本身的 token 消耗不可忽视。

成本控制的5 个实战技巧

技巧一:模型分流(大模型干重活,小模型干轻活)

不同的任务用不同的模型:简单分类、标签提取用小模型(GPT-4o-mini / Claude Haiku),复杂分析、翻译用大模型(GPT-4o / Claude Sonnet)。研究表明,80% 的电商 LLM 调用是简单任务,完全可以用小模型处理。

model_routing.py
def route_task(task, model_pool):
    if task["complexity"] == "low":
        return min(model_pool, key=lambda m: m["cost_factor"])
    elif task["complexity"] == "medium":
        return sorted(model_pool, key=lambda m: m["cost_factor"])[1]
    else:
        return max(model_pool, key=lambda m: m["capability"])

model_pool = [
    {"name": "GPT-4o-mini", "capability": 0.6, "cost_factor": 0.1},
    {"name": "Claude Haiku", "capability": 0.65, "cost_factor": 0.12},
    {"name": "GPT-4o", "capability": 0.95, "cost_factor": 1.0},
    {"name": "Claude Sonnet 4", "capability": 1.0, "cost_factor": 1.2},
]

tasks = [
    {"task": "产品标题分类", "complexity": "low"},
    {"task": "竞品分析报告生成", "complexity": "high"},
    {"task": "多语言翻译", "complexity": "medium"},
]

for task in tasks:
    best = route_task(task, model_pool)
    print(f"  {task['task']} ({task['complexity']}) -> {best['name']}")

技巧二:System Prompt 精简

System Prompt 每次调用都计入 input tokens。如果你的 System Prompt 长达 2000 tokens,每次调用光系统提示就消耗 $0.005(GPT-4o)。日均 1 万次调用,光 System Prompt 的月成本就是 $1500。

prompt_trimming.py
# 精简 System Prompt 的前后对比
original_system = """
你是一个专业的跨境电商产品经理助手。

你的专长:
- 分析亚马逊、Temu、SHEIN 等平台的产品标题和描述
- 提炼产品的核心卖点、目标人群、适用场景
- 识别标题中的关键属性(品牌、型号、颜色、尺码、材质)
- 提供多语言产品本地化建议(英语、西班牙语、德语、法语)

输出格式要求:
- 输出必须严格遵循用户指定的格式,不额外发挥
- 如果信息不足,明确说"信息不足,无法判断"
- 涉及价格、销量等数据时,标注"未提供"而不是编造

语言风格:专业、简洁、直接,关键结论放在最前面
"""

精简_system = """你是跨境电商产品分析助手。
专长:产品卖点提炼、属性识别、多语言本地化。
规则:严格按指定格式输出;信息不足说"未提供";不编造数据。
风格:专业简洁,结论先行。"""

def estimate_tokens(text):
    return len(text.split()) * 1.3

orig_tokens = estimate_tokens(original_system)
mini_tokens = estimate_tokens(精简_system)
saving_pct = (orig_tokens - mini_tokens) / orig_tokens * 100

print(f"原始 System Prompt: ~{orig_tokens:.0f} tokens")
print(f"精简后: ~{mini_tokens:.0f} tokens")
print(f"节省: {saving_pct:.0f}% tokens")
print(f"月均万次调用节省: ${(orig_tokens - mini_tokens) * 10000 * 2.5 / 1e6:.0f}")

技巧三:RAG 检索优化,减少输入 token

如果你用 RAG,但每次检索出来的 chunks 塞满了大量不相关信息,就是在浪费 token。优化检索精度(提高 reranker 质量、控制 chunk 长度)直接降低 input token 消耗。

rag_token_optimize.py
def rag_cost(num_chunks, chunk_avg_tokens, model="GPT-4o"):
    input_tokens = 50
    retrieved_tokens = num_chunks * chunk_avg_tokens
    system_tokens = 200
    total_input = input_tokens + retrieved_tokens + system_tokens
    output_tokens = 300
    return (total_input * 2.5 + output_tokens * 10) / 1e6

print("RAG 成本对比(GPT-4o):")
configs = [
    (1, 500, "只召回 top-1,chunk 长"),
    (3, 300, "top-3 中等 chunk"),
    (5, 200, "top-5 短 chunk"),
    (10, 100, "top-10 极短 chunk"),
]

for num, avg, desc in configs:
    cost = rag_cost(num, avg)
    print(f"  {desc}: ${cost:.4f}/次 = ${cost*10000:.2f}/万次")

技巧四:缓存(Cache)

OpenAI 有 Cache(gpt-4o-cache)、Claude 有 Cache,都是对 input tokens 的成本减免(通常 50-90% off)。原理是你在短时间内重复发送相同的 System Prompt 或相同的文档内容,模型厂商缓存重复部分,只对变化的部分计费。

跨境电商的固定场景(产品分析模板、物流政策查询模板)天然适合缓存。设计 prompt 时,把固定部分放在开头,变化部分放在末尾,可以最大化缓存命中率。

技巧五:批量处理

把多条任务合并成一次 API 调用(在模型支持的情况下)。例如同时分析 10 个产品标题而不是10 次调用,每次调用共享相同的 System Prompt tokens。成本从 10 × (200+50) = 2500 input tokens 降低到 (200 + 10×50) = 700 input tokens,节省 72%。

batch_processing.py
def batch_cost(num_items, system_tokens=200, per_item_tokens=50, output_per_item=100):
    single_total = num_items * (system_tokens + per_item_tokens + output_per_item)
    batch_total = system_tokens + num_items * (per_item_tokens + output_per_item)
    return single_total, batch_total

for n in [5, 10, 20, 50]:
    single, batch = batch_cost(n)
    saving = (single - batch) / single * 100
    print(f"  {n} 条任务: 逐条 {single} tokens -> 批量 {batch} tokens, 节省 {saving:.0f}%")

成本优化的优先级:第一优先级是模型选型(换小模型省 80-90%),第二是 prompt 精简(省 20-30%),第三是 RAG 检索优化(省 30-50%),第四是缓存(省 50-90%),第五是批量处理(省 50-70%)。前两项不需要改代码,只需要选型和 prompt 重写,立竿见影。

关键结论

· Token 计数是成本的根本:理解 tokenization 才能优化。中文 token效率低,实际上下文比标称短30-40%
· 模型分流是成本控制的第一杠杆:80% 的简单任务用小模型处理,成本差 10-20 倍
· System Prompt 每次都计费:精简到必要内容,2000 tokens vs 200 tokens 的月成本差 10 倍
· RAG 检索优化直接降成本:控制 chunk 数和长度,成本可差 5 倍
· 缓存和批量处理是进阶技巧:固定场景天然适合缓存,批量处理适合离线场景