LLM Token 优化实战:七大策略让成本砍半

2026-06-11LLMToken优化成本控制生产实践

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%

未标记