OpenClaw 上下文压缩与Token优化

更新时间:2026-04-24 | 预计阅读:11分钟

凌晨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

最佳实践清单

  1. 定期审计System Prompt——删除过时和重复的内容
  2. 对话历史设置上限——不要无限制累积
  3. 工具输出即时裁剪——不要把10KB的HTML全塞进去
  4. 记忆按需加载——用搜索代替全量注入
  5. 子Agent用lightContext——能省则省
  6. 监控Token用量——发现异常及时调整

相关资源