上下文预算分配深入分析

分析 OpenClaw 的 200k 令牌上下文预算如何在每次 LLM 调用中分配给不同组件。

总预算

// 来自 src/agents/defaults.ts
export const DEFAULT_CONTEXT_TOKENS = 200_000;

// 来自 src/agents/pi-settings.ts
export const DEFAULT_PI_COMPACTION_RESERVE_TOKENS_FLOOR = 20_000;

预算细分

1. 系统提示(2,000-8,000 令牌)

src/agents/system-prompt.tsbuildAgentSystemPrompt() 构建:

条件部分(~20 个组件):

  • 基本身份和能力
  • 工作区感知
  • 工具使用指南
  • 特定于频道的说明(Telegram、Discord、Slack 等)
  • 会话管理说明
  • 错误处理协议
  • 多轮对话指南
  • 所有者显示密钥说明(如果配置)
  • 自定义系统提示添加

令牌范围: 2,000-8,000 令牌,取决于活动功能

2. 技能目录(1,500-3,000 令牌)

来自 src/agents/skills/workspace.ts

const DEFAULT_MAX_SKILLS_IN_PROMPT = 150;
const DEFAULT_MAX_SKILLS_PROMPT_CHARS = 30_000;

计算

  • 最多 150 个技能
  • 最多 30,000 字符
  • 最坏情况下 ~7-8k 令牌(字符/4 启发式)
  • 典型: 1,500-3,000 令牌

3. 工具定义(2,400-3,600 令牌)

来自 Pi Agent SDK 的 24 个核心工具

  • 每个工具定义:~100-150 令牌
  • 总计:24 × ~100-150 = 2,400-3,600 令牌

核心工具包括:

  • Bash、Read、Write、Edit
  • Glob、Grep
  • WebFetch
  • NotebookEdit
  • TodoWrite
  • Skill
  • 以及 14+ 其他

4. 记忆(RAG)注入(500-2,000 令牌)

来自 src/memory/manager.ts

const SNIPPET_MAX_CHARS = 700;

每个片段

  • 最多 700 字符
  • 每个片段 ~175 令牌(字符/4)

典型注入

  • 3-10 个片段
  • 总计:500-2,000 令牌

5. 压缩保留(20,000 令牌)

// 来自 src/agents/pi-settings.ts
export const DEFAULT_PI_COMPACTION_RESERVE_TOKENS_FLOOR = 20_000;

目的

  • 压缩操作的缓冲
  • 确保摘要提示有足够空间
  • 包括 SUMMARIZATION_OVERHEAD_TOKENS = 4,096

触发点: 当上下文达到 ~180k(200k - 20k)时开始压缩

6. 会话历史(剩余:~163,000-174,000 令牌)

计算

200,000(总计)
  - 8,000(系统提示,高估)
  - 3,000(技能目录,高估)
  - 3,600(工具定义,高估)
  - 2,000(记忆注入,高估)
  - 20,000(压缩保留)
  - 1,000(其他开销)
---------
= 162,400 令牌可用于会话历史

典型范围: 163,000-174,000 令牌(总预算的 60-80%)

这是上下文预算的最大消费者

按用例划分的预算分配

最小会话(空历史)

系统提示:      2,000 令牌   (1.0%)
技能:          1,500 令牌   (0.75%)
工具:          2,400 令牌   (1.2%)
记忆:            500 令牌   (0.25%)
保留:         20,000 令牌   (10%)
历史:              0 令牌   (0%)
可用:        173,600 令牌   (86.8%)

典型活跃会话

系统提示:      5,000 令牌   (2.5%)
技能:          2,500 令牌   (1.25%)
工具:          3,000 令牌   (1.5%)
记忆:          1,500 令牌   (0.75%)
保留:         20,000 令牌   (10%)
历史:        120,000 令牌   (60%)
已用:        152,000 令牌   (76%)
可用:         48,000 令牌   (24%)

接近压缩会话

系统提示:      6,000 令牌   (3%)
技能:          3,000 令牌   (1.5%)
工具:          3,600 令牌   (1.8%)
记忆:          2,000 令牌   (1%)
保留:         20,000 令牌   (10%)
历史:        165,400 令牌   (82.7%)
已用:        200,000 令牌   (100%)
触发压缩!

压缩触发逻辑

// 接近保留下限时开始压缩
const effectiveLimit = DEFAULT_CONTEXT_TOKENS - DEFAULT_PI_COMPACTION_RESERVE_TOKENS_FLOOR;
// effectiveLimit = 200,000 - 20,000 = 180,000

if (estimatedTokens > effectiveLimit) {
  // 触发压缩
}

优化策略

1. 减少系统提示大小

  • 删除不必要的特定于频道的说明
  • 使用条件提示
  • 节省: 1,000-2,000 令牌

2. 限制技能目录

  • MAX_SKILLS_IN_PROMPT 减少到 100
  • 按会话过滤无关技能
  • 节省: 500-1,000 令牌

3. 延迟加载记忆片段

  • 仅在明确需要时注入记忆
  • 使用相关性评分
  • 节省: 500-1,500 令牌

4. 激进的历史修剪

  • maxHistoryShare 从 0.5 降低到 0.4
  • 更早触发压缩
  • 权衡: 上下文保留较少

交叉引用