OpenClaw 上下文压缩与Token优化
凌晨2点,我收到API账单:这个月花了$127。检查日志发现,每次对话塞了20KB的上下文——历史消息、工具描述、记忆片段、系统提示词...像搬家一样把所有东西都带上。Token优化的本质不是省钱,而是学会"断舍离"——只带真正有用的。
为什么需要上下文压缩
LLM的上下文窗口有限,而Agent运行时需要:
- System Prompt:角色定义、工具描述、安全规则
- 对话历史:用户消息、Agent回复、工具调用记录
- 记忆内容:长期记忆、场景块、用户偏好
- 工具输出:文件内容、搜索结果、API响应
如果全部塞进去,128K上下文也不够用。优化目标:用最少的Token传递最大的信息量。
上下文预算分配
典型预算分配
总预算:128,000 tokens
├── System Prompt: 8,000 (6.3%) - 角色和规则
├── 工具描述: 12,000 (9.4%) - 可用工具列表
├── 记忆/场景: 10,000 (7.8%) - 用户上下文
├── 对话历史: 48,000 (37.5%) - 最近对话
├── 工具输出: 20,000 (15.6%) - 当前任务相关
├── 预留空间: 30,000 (23.4%) - Agent回复生成
└── 安全余量: 0 (0%) - 严格控制在预算内
关键原则
- System Prompt越精炼越好——删掉冗余描述
- 对话历史只保留最近的——过期的信息没用
- 工具输出要裁剪——只保留关键部分
- 记忆按需加载——不要预加载所有场景
压缩技术详解
1. 对话历史滚动窗口
// 对话历史管理
function manageConversationHistory(messages, tokenBudget) {
const systemTokens = countTokens(messages.filter(m => m.role === 'system'));
const availableTokens = tokenBudget - systemTokens;
// 保留最近的消息,但确保包含关键上下文
const recent = messages.slice(-20); // 最近20条
const recentTokens = countTokens(recent);
if (recentTokens > availableTokens) {
// Token超限,压缩历史
return compressHistory(recent, availableTokens);
}
return messages;
}
// 压缩历史:摘要旧消息,保留新消息
function compressHistory(messages, budget) {
const old = messages.slice(0, -10);
const recent = messages.slice(-10);
if (old.length > 0) {
// 将旧消息压缩为摘要
const summary = llm.summarize(old);
return [
{ role: 'system', content: `对话历史摘要:${summary}` },
...recent
];
}
return recent;
}
2. 工具输出裁剪
// 智能裁剪工具输出
function trimToolOutput(output, maxTokens = 4000) {
// 如果输出是HTML,只保留文本内容
if (output.includes(' maxTokens) {
output = extractKeySections(output, maxTokens);
}
// 移除代码注释和空行
output = output
.split('\n')
.filter(line => line.trim() && !line.trim().startsWith('//'))
.join('\n');
return output;
}
3. 按需记忆加载
// 记忆按需加载策略
async function loadRelevantMemory(query) {
// 不加载所有记忆,只加载相关的
const relevant = await memorySearch(query, {
limit: 3,
minRelevance: 0.6
});
// 压缩为简短摘要
return relevant.map(m =>
`[${m.type}] ${m.summary} (${m.date})`
).join('\n');
}
// 代码中按需调用
const userMemory = await loadRelevantMemory(currentQuery);
// 只注入相关的记忆,而不是全部
4. System Prompt精简
# ❌ 冗长的System Prompt(约2000 tokens)
你是妙趣AI,一个专业的AI营销运营官。你负责妙趣AI网站的日常运营
和内容生产。你的核心定位是:内容生产、SEO优化、社区运营、竞品
监控、数据报告。你的性格特征是:幽默有趣、专业但不端着...
# ✅ 精简后的System Prompt(约500 tokens)
你是妙趣AI,AI营销运营官。幽默专业,负责miaoquai.com的内容生产
和SEO运营。详见SOUL.md。核心规则:不处理招聘/知识整理/个人品牌。
风格:王家卫式时间感+周星驰式脑洞。工作目录:/root/.openclaw/agents/miaoquai/
# 节省:约75% tokens
轻量上下文模式(Light Context)
OpenClaw的轻量上下文模式专为子Agent优化:
// 启用轻量上下文
sessions_spawn({
task: "生成SEO页面",
runtime: "subagent",
lightContext: true // 关键配置
});
// lightContext 模式的效果:
// - 精简System Prompt(只包含核心规则)
// - 不加载完整记忆(只加载查询相关的片段)
// - 不加载完整工具列表(只加载任务需要的)
// - 不注入Scene Navigation(节省约3000 tokens)
// 典型节省:从20KB → 5KB(75%压缩)
Token使用监控
实时Token计数
// Token监控仪表盘
const tokenMetrics = {
sessionTokens: {
system: 4500,
history: 12000,
tools: 8000,
memory: 3000,
total: 27500
},
costEstimate: {
input: 27500 * 0.000005, // $0.1375
output: 2000 * 0.000015, // $0.03
total: '$0.1675'
},
savings: {
compressionRate: '72%',
tokensSaved: 71000,
costSaved: '$0.355'
}
};
成本告警
# 成本控制配置
cost_control:
daily_budget: 5.0 # 每日预算$5
session_limit: 0.50 # 单次对话上限$0.50
alert_threshold: 0.80 # 80%预算时告警
on_budget_exceeded:
action: downgrade # 切换到更便宜的模型
fallback_model: "claude-haiku"
notify: feishu
最佳实践清单
- 定期审计System Prompt——删除过时和重复的内容
- 对话历史设置上限——不要无限制累积
- 工具输出即时裁剪——不要把10KB的HTML全塞进去
- 记忆按需加载——用搜索代替全量注入
- 子Agent用lightContext——能省则省
- 监控Token用量——发现异常及时调整