Token成本控制-生产环境的省钱指南
Token 成本是 AI 应用商业化的关键变量。在不控制 token 消耗的情况下,多个消耗来源叠加在一起,会产生远超预期的 API 费用:system prompt 写得又臭又长、对话历史没有截断、RAG 每次塞了过多文档、批处理任务用实时 API 跑……每一项单独看都觉得"没多少",叠在一起就是巨额账单。
Token 成本控制:生产环境的省钱指南
Token 成本是 AI 应用商业化的关键变量。在不控制 token 消耗的情况下,多个消耗来源叠加在一起,会产生远超预期的 API 费用:system prompt 写得又臭又长、对话历史没有截断、RAG 每次塞了过多文档、批处理任务用实时 API 跑……每一项单独看都觉得"没多少",叠在一起就是巨额账单。
1.1 Token 消耗从哪里来
明确消耗来源,才知道从哪里下手优化。
System Prompt:每次 API 调用都要发送,哪怕用户只问了一句话。写了 800 token 的 system prompt,每天调用 1 万次,光这一项就是 800 万 input token。
对话历史:多轮对话的场景,每次调用都要把之前所有的消息一起发。用户和 AI 聊了 20 轮,第 21 轮的调用里包含了前 20 轮的全部内容。对话越长,成本曲线越陡。
RAG 检索结果:每次检索 top-5 个文档,每个文档 800 token,这一项就是 4000 token。每次调用都这样,成本可观。
工具调用结果:工具返回的内容可能很长。比如查询数据库返回了 50 行记录,直接塞进 context,可能是 2000 token。
输出 token:通常比 input 贵 2-4 倍(具体看模型定价)。如果没有限制输出长度,模型可能写出一篇小论文来回答一个简单问题。
1.2 七种降本策略
缓存/压缩/模型分级/批处理等七种 Token 成本控制策略的节省效果对比
1.2.1 选对模型
这是效果最显著的一招。
GPT-4o 的 input token 价格是 $2.5/百万,GPT-4o-mini 是 $0.15/百万,差了约 17 倍。DeepSeek-V3 目前定价更低,约 $0.27/百万 input token(缓存命中更便宜)。
绝大多数 AI 应用场景不需要最强的模型。情绪分类、意图识别、格式提取——GPT-4o-mini 和 DeepSeek-V3 完全够用。把复杂的推理任务(多步规划、代码生成、复杂分析)留给大模型,日常查询用小模型,成本能降到原来的 1/10 到 1/20。
1.2.2 压缩对话历史
对话历史不能无限增长。常见的处理方式有两种:
滑动窗口:只保留最近 N 轮对话。N 取多少根据业务场景决定,客服场景 10 轮通常够了。
摘要压缩:当对话超过一定长度,用 LLM 把早期的对话历史压缩成摘要,摘要替换原始历史。这样上下文不会完全丢失,但 token 消耗大幅减少。
1.2.3 精简 System Prompt
很多 system prompt 是这样写的:
你是一个专业的智能助手,拥有丰富的知识储备和专业能力,能够以友善、耐心、专业的态度回答用户的各种问题,始终保持诚实和客观,如果不确定答案请直接说不知道,不要编造信息……
这种 prompt 写了 300 token,有效信息大概 50 token。每次调用都白发 250 token。
精简原则:只保留模型真正需要知道的规则。角色定义 1 句话,核心约束 3-5 条,举例说明 1-2 个。精简后的 system prompt 不超过 200 token,每次节省 100-200 token,乘以百万次调用量级,是真金白银。
1.2.4 RAG 结果截断
RAG 的 top-k 参数和每个文档的长度都要控制。
不要检索 10 个文档,top-3 在绝大多数场景够用。每个文档最多取 500 token,超出的截断。这一项从 8000 token 压缩到 1500 token,减少了将近 80%。
1.2.5 Prompt Caching
Prompt Caching(提示词缓存):LLM 供应商提供的服务端缓存机制,当请求的开头部分(前缀)与之前的请求完全相同时,供应商可以复用已处理的计算结果,并给予大幅折扣(这部分 token 不需要重新计算)。
OpenAI 和 DeepSeek 都支持 Prompt Caching。如果 prompt 前缀(比如 system prompt 或一段固定的背景文档)在多次调用中完全一样,命中缓存的部分只收大幅折扣后的价格(各供应商比例不同,请查阅官方最新定价)。
使用条件:prefix 部分必须超过一定长度(OpenAI 要求 1024 token,DeepSeek 的具体要求请参考官方文档),且在短时间内重复使用。
如果有一个 2000 token 的 system prompt,每天调用 1 万次,开启缓存后这部分成本减少 50-90%。
1.2.6 批处理(Batch API)
非实时任务——比如批量处理文档、离线生成报告、后台数据分析——不需要用实时 API。
Batch API(批处理接口):LLM 供应商提供的异步批量处理接口,允许一次性提交大量请求,由供应商在非高峰时段处理,通常 24 小时内返回结果。因为不占用实时计算资源,价格比实时 API 便宜 50%。
OpenAI 的 Batch API 价格是实时 API 的 50%。DeepSeek 也有类似的批处理接口。提交任务后异步等待结果,通常 24 小时内完成。
这个优化对于有大量离线处理需求的场景非常值,直接对半砍。
1.2.7 控制输出长度
用 max_tokens 参数限制输出。同时在 prompt 里明确要求简洁:
请用 3 句话内回答,不要重复问题,直接给出结论。
这两招结合,能把平均输出长度从 400 token 压到 150 token。
1.3 Token 计算工具
发请求之前先算好 token 数,避免意外超支。
import tiktoken
def count_tokens(text: str, model: str = "gpt-4o") -> int:
encoding = tiktoken.encoding_for_model(model)
return len(encoding.encode(text))
# 检查 prompt 消耗
system_prompt = "你是一个客服助手,只回答关于产品使用的问题,不讨论其他话题。"
print(f"System prompt token 数:{count_tokens(system_prompt)}")
1.4 完整代码:带成本追踪的 LLM 调用封装
import os
import time
import tiktoken
from openai import OpenAI
from dataclasses import dataclass, field
from typing import List, Dict, Optional
client = OpenAI(base_url="https://api.deepseek.com", api_key=os.getenv("DEEPSEEK_API_KEY"))
# 各模型的定价(美元/百万 token,仅作参考,实际使用请查最新官网)
# ⚠️ 定价随时可能变化,使用前请核实:https://platform.deepseek.com/api-docs/pricing
MODEL_PRICING = {
# DeepSeek(课程主要使用)
"deepseek-chat": {"input": 0.27, "output": 1.10}, # DeepSeek-V3,截至2026年3月
"deepseek-reasoner": {"input": 0.55, "output": 2.19}, # DeepSeek-R1,截至2026年3月
# OpenAI(部分章节使用)
"gpt-4o": {"input": 2.5, "output": 10.0},
"gpt-4o-mini": {"input": 0.15, "output": 0.60},
}
@dataclass
class CostTracker:
"""成本追踪器,记录每次调用的 token 和费用"""
total_input_tokens: int = 0
total_output_tokens: int = 0
total_cost_usd: float = 0.0
call_count: int = 0
call_history: List[Dict] = field(default_factory=list)
def record(self, model: str, input_tokens: int, output_tokens: int):
pricing = MODEL_PRICING.get(model, {"input": 2.5, "output": 10.0})
cost = (input_tokens * pricing["input"] + output_tokens * pricing["output"]) / 1_000_000
self.total_input_tokens += input_tokens
self.total_output_tokens += output_tokens
self.total_cost_usd += cost
self.call_count += 1
self.call_history.append({
"model": model,
"input_tokens": input_tokens,
"output_tokens": output_tokens,
"cost_usd": cost,
"timestamp": time.time()
})
def summary(self) -> str:
return (
f"调用次数:{self.call_count}\n"
f"总 input token:{self.total_input_tokens:,}\n"
f"总 output token:{self.total_output_tokens:,}\n"
f"总费用:${self.total_cost_usd:.4f} USD(约 ¥{self.total_cost_usd * 7.2:.2f})"
)
# 全局追踪器
tracker = CostTracker()
def chat_with_history(
user_message: str,
history: List[Dict],
system_prompt: str,
model: str = "deepseek-chat",
max_history_turns: int = 10,
max_output_tokens: int = 500,
rag_context: Optional[str] = None,
) -> tuple[str, List[Dict]]:
"""
带成本控制的多轮对话函数
优化点:
1. 对话历史截断(max_history_turns)
2. 输出长度限制(max_output_tokens)
3. RAG 内容可选注入
4. 自动成本追踪
"""
# 截断对话历史,只保留最近 N 轮(每轮 = 用户 + 助手,共 2 条消息)
truncated_history = history[-(max_history_turns * 2):]
if len(history) > len(truncated_history):
print(f"[成本控制] 历史截断:{len(history)} 条 → {len(truncated_history)} 条")
# 构建 system prompt(如果有 RAG 内容,追加到 system prompt 末尾)
full_system = system_prompt
if rag_context:
# RAG 内容截断到 1500 token
encoding = tiktoken.encoding_for_model(model if model in tiktoken.list_encoding_names() else "gpt-4o")
rag_tokens = encoding.encode(rag_context)
if len(rag_tokens) > 1500:
rag_context = encoding.decode(rag_tokens[:1500])
print(f"[成本控制] RAG 内容截断至 1500 token")
full_system += f"\n\n参考资料:\n{rag_context}"
messages = [{"role": "system", "content": full_system}]
messages.extend(truncated_history)
messages.append({"role": "user", "content": user_message})
# 发送请求前预估 token(可选,用于监控)
encoding = tiktoken.get_encoding("cl100k_base")
estimated_input = sum(len(encoding.encode(m["content"])) for m in messages)
print(f"[成本预估] 预计 input token:{estimated_input}")
# 调用 API
response = client.chat.completions.create(
model=model,
messages=messages,
max_tokens=max_output_tokens,
temperature=0.7,
)
assistant_message = response.choices[0].message.content
usage = response.usage
# 记录实际费用
tracker.record(model, usage.prompt_tokens, usage.completion_tokens)
print(
f"[成本记录] 实际 input: {usage.prompt_tokens}, output: {usage.completion_tokens}, "
f"本次费用: ${tracker.call_history[-1]['cost_usd']:.6f}"
)
# 更新对话历史
new_history = truncated_history + [
{"role": "user", "content": user_message},
{"role": "assistant", "content": assistant_message},
]
return assistant_message, new_history
# 使用示例
if __name__ == "__main__":
system = "你是一个产品客服,只回答关于产品使用的问题,回答简洁不超过100字。"
history = []
questions = [
"这个产品怎么退款?",
"退款要多久到账?",
"如果超过7天还没到账怎么办?",
]
for q in questions:
print(f"\n用户:{q}")
answer, history = chat_with_history(
user_message=q,
history=history,
system_prompt=system,
model="deepseek-chat",
max_history_turns=5,
max_output_tokens=200,
)
print(f"助手:{answer}")
print(f"\n{'='*40}")
print("成本汇总:")
print(tracker.summary())
1.5 成本监控
代码里的 CostTracker 适合开发阶段的调试。生产环境推荐接入 LangSmith 或 Langfuse——它们会自动记录每次 LLM 调用的 token 消耗、费用、延迟,还能按用户、按功能模块聚合统计。
LangSmith 的使用方式很简单,设置两个环境变量就接入了:
import os
os.environ["LANGCHAIN_TRACING_V2"] = "true"
os.environ["LANGCHAIN_API_KEY"] = "your-langsmith-api-key"
# 之后所有通过 LangChain 的调用都会自动上报
每周查看一次 token 统计图表,能快速发现异常消耗——比如某个功能突然多了 10 倍调用量,或者某个用户在大量刷接口。
1.6 成本控制的优化潜力
各项优化组合叠加后,成本下降往往超出预期:模型切换到混合策略(简单任务用 mini),对话历史截断到 10 轮,system prompt 从 800 token 精简到 180 token,RAG 文档从 10 篇截到 3 篇,批处理任务全切 Batch API。每一步单独看都不起眼,叠加起来可以实现 5 倍甚至更大的成本差距。
AI 应用如果成本失控,会进入"越用越亏"的死循环。成本控制是让 AI 应用可持续运营的必要条件,越早建立成本意识越好。