Token是大模型计费的基本单位,一次请求消耗的Token数直接决定了账单金额。很多团队接入大模型后发现成本远超预期,回头看日志才发现,大部分Token其实花在了重复发送的历史对话、冗长的系统提示词和啰嗦的输出上。本文整理几类经过实战验证的Token节省技巧,覆盖输入和输出两端,帮助你在保持回答质量的同时把成本压下来。

为什么同样的任务Token消耗差好几倍
先理解计费规则才能对症下药。主流API的计费分为输入Token(prompt tokens)和输出Token(completion tokens),输出部分的单价通常是输入的3到5倍。一次请求的总Token由四部分组成:系统提示词、历史对话、当前用户输入、模型输出。很多应用的系统提示词动辄两三千Token,每轮对话都原样重发一遍,十轮对话下来,仅系统提示词就要重复消耗两三万Token。
中文场景还有一个额外问题:同一个意思,中文表达的Token数大约是英文的1.3到1.5倍,啰嗦的敬语、重复的解释、无意义的客套话都会被切分成实打实的Token。所以省Token的第一步不是调参数,而是审视你发给模型的内容里有多少是废话。
可以用OpenAI提供的tiktoken库在本地预计算Token数,在发送前就知道这次请求的成本,避免上线后才发现失控。
import tiktoken
enc = tiktoken.get_encoding("cl100k_base")
text = "请帮我总结一下这段会议纪要的主要内容"
print(len(enc.encode(text))) # 提前知道这段话要花多少Token提示词压缩与历史对话管理
系统提示词是最大的隐性消耗源。优化方法有几个:第一,删掉对模型没有约束效果的废话,比如各种礼貌用语和背景铺垫;第二,用简洁的指令式表达替代段落式描述,把规则改成要点列表;第三,把固定不变的参考文档从提示词里挪走,改用检索的方式只在需要时注入相关片段(RAG),只送进模型真正用得上的几百Token,而不是整本文档。
历史对话的管理更关键。多轮对话如果每次都把全部历史发给模型,Token消耗会随轮数线性甚至平方级增长。常见做法是滑动窗口:只保留最近N轮对话;更进一步可以做摘要压缩,把较早的对话让模型先总结成一段简短摘要,之后每轮只携带摘要加最近两三轮原文。这样既保住了上下文连续性,又把历史部分控制在固定范围内。
def build_messages(history, current_input, max_rounds=3):
# 只保留最近三轮原文,更早的用摘要代替
recent = history[-max_rounds * 2:]
summary = summarize_history(history[:-max_rounds * 2]) if len(history) > max_rounds * 2 else ""
messages = [{"role": "system", "content": SYSTEM_PROMPT}]
if summary:
messages.append({"role": "system", "content": "此前对话摘要:" + summary})
messages.extend(recent)
messages.append({"role": "user", "content": current_input})
return messages如果使用OpenAI或Anthropic的接口,还可以利用prompt caching特性。系统提示词和对话前缀如果保持完全一致,缓存命中部分的输入费用会大幅打折,因此把固定内容放在消息列表最前面、动态内容放后面,不只是好习惯,还能直接省钱。
控制输出长度与结构化取舍
由于输出Token单价更高,控制输出长度往往收益更大。最直接的手段是设置max_tokens上限兜底,同时配合提示词明确要求简洁回答,比如加上只输出结论、不要重复问题、控制在两百字以内这样的约束。如果只需要结构化结果,明确要求输出JSON并只包含必要字段,不要让模型输出解释性文字。
思维链是另一个容易被忽视的消耗点。让模型一步步推理确实能提升准确率,但中间推理过程可能消耗数千Token。可以在提示词中要求模型把推理过程写进特定标签,再配合流式读取做过滤,只在最终结果中截取答案部分;或者直接使用提供隐藏思维链功能的模型版本,费用只按可见输出计算。
response = client.chat.completions.create(
model="gpt-4o",
messages=messages,
max_tokens=300, # 输出兜底上限
temperature=0.3,
# 提示词中已要求:直接输出JSON,不要解释
)
print(response.usage) # 关注prompt_tokens和completion_tokens最后建立监控习惯:把每次请求的usage数据落到日志,按功能模块统计Token分布,你会很快发现钱具体花在了哪里,再针对性优化,比盲目猜测有效得多。