LLM Token 优化实战:七大策略让成本砍半
Token 即成本
在 LLM 应用中,Token 是最直接的成本单元。一个中等复杂度的 Agent 对话可能消耗 5K-20K tokens,按 GPT-4 定价算就是 $0.15-$0.60 一次。日活 1000 用户,月成本轻松过万。优化 Token 不是"锦上添花",是"生存必需"。
七大优化策略
1. 工具结果截断
工具调用可能返回海量数据(网页全文、数据库导出等)。直接塞进上下文窗口既浪费 Token 又稀释关键信息。
MAX_RESULT_CHARS = 2000 # 约 500 tokens
def smart_truncate(text: str) -> str:
if len(text) <= MAX_RESULT_CHARS:
return text
# 在语义边界截断:找最后一个完整句子
truncated = text[:MAX_RESULT_CHARS]
last_period = max(truncated.rfind('。'), truncated.rfind('. '))
if last_period > MAX_RESULT_CHARS * 0.5:
truncated = truncated[:last_period + 1]
return f"{truncated}\n\n(结果已截断,原始 {len(text)} 字符。缩小查询范围可获完整结果)"
避坑:截断不能在 JSON 或代码块中间。如果截断位置在 ``` 或 { } 中间,需要向前回溯到边界。
2. 意图分类精简工具
20 个工具每个占用约 300-500 tokens。如果只注入 5 个相关工具,节省 4500-7500 tokens/轮。
# 用便宜模型先做意图分类(一次约 200 tokens)
intent = cheap_model.classify(query) # → "database_query"
# 只注入对应分组的 5 个工具(vs 全部 20 个)
tools = TOOL_GROUPS[intent] # 节省 ~4500 tokens
3. 按需展开历史上下文
使用 LCM(Lossless Context Management)机制:长对话不直接截断,而是压缩为摘要并保留引用。Agent 需要细节时再按需展开。
# 不是这样(全量注入):
messages = all_history # 可能 50K+ tokens
# 而是这样(摘要 + 按需展开):
summary = compress_history(all_history) # 约 2K tokens
messages = [system_prompt, summary, current_question]
# 当 Agent 需要某个历史细节时,通过 tool_call 获取
4. 流式输出(SSE)
流式输出不减少 Token,但改善用户体验——用户不必等待所有 Token 生成完毕才能看到内容。Server-Sent Events 是标准做法:
# 后端 SSE 响应
event: start
data: {"session_id": "abc123"}
event: token
data: {"content": "Agent"}
event: token
data: {"content": " 的核心是"}
event: tool
data: {"name": "search", "status": "running"}
event: done
data: {"total_tokens": 4521}
5. 结构化输出约束
用 JSON Schema 约束输出格式,让 LLM 跳过"解释性废话":
# 不用自然语言描述结果(Token 多)
"我找到了 3 个相关文档,分别是:第一个文档讲的是..."
# 用结构化输出(Token 少且可解析)
{"results": [{"title": "RAG优化", "score": 0.92}, ...]}
6. Prompt 压缩
把角色扮演式的冗长描述替换为精炼指令:
# ❌ 冗余(~200 tokens)
"你是一个专业的、经验丰富的 AI 助手。你的任务是帮助用户解决技术问题。
你总是仔细思考后再回答,你的回答准确、全面、有条理..."
# ✅ 精炼(~30 tokens)
"技术专家。回答准确、结构化。不确定时明确说明。"
7. 结果去重合并
并行工具调用可能返回高度重叠的结果。在提交给 LLM 之前先做语义去重:
# 用 ROUGE-L 或简单的 Jaccard 相似度去重
unique_results = deduplicate(parallel_results, threshold=0.85)
# 去重后可能从 3000 tokens 降到 1200 tokens
实际效果
| 优化措施 | 预估节省 | 实现难度 |
|---|---|---|
| 工具结果截断 | 20-40% | 低 |
| 意图分类精简工具 | 30-50% | 中 |
| 按需展开历史 | 30-60% | 高 |
| Prompt 压缩 | 10-20% | 低 |
| 结构化输出 | 15-30% | 低 |
组合使用以上策略,通常可以将每轮对话的 Token 消耗降低 40-60%。