首页 / 课程 / S05: Context Compression

S05: Context Compression 上下文压缩

"Context is finite, but conversation is infinite" -- 压缩是长对话的生存之道。

Harness 层: Compact -- 让对话突破上下文限制。

本章导图:压缩:对话历史过长时在保留语义下收缩上下文。

🎯 问题

Agent Loop 持续累积消息:

  • 模型有上下文窗口限制 (200K tokens)
  • 消息累积会超出限制
  • 重要信息可能被截断
  • API 成本随 token 增长

💡 解决方案

Claude Code 实现了多层压缩策略:

Token Usage
    │
    ├── < Warning ──────── 提醒用户
    │
    ├── < AutoCompact ──── 自动压缩
    │
    └── < Error ────────── 强制压缩
                        

📐 阈值计算

// 源码位置: src/services/compact/autoCompact.ts

const MAX_OUTPUT_TOKENS_FOR_SUMMARY = 20_000
const AUTOCOMPACT_BUFFER_TOKENS = 13_000

function getAutoCompactThreshold(model: string): number {
  const contextWindow = getContextWindowForModel(model)
  const effectiveWindow = contextWindow - MAX_OUTPUT_TOKENS_FOR_SUMMARY
  return effectiveWindow - AUTOCOMPACT_BUFFER_TOKENS
}

🔑 压缩类型

🤖

Auto Compact

自动触发压缩

Manual /compact

用户手动触发

🔬

Micro Compact

特定消息压缩

💾

Memory Compact

会话记忆压缩

📊 压缩流程

// 源码位置: src/services/compact/compact.ts

async function compact(
  messages: Message[],
  config: CompactConfig
): Promise {

  // 1. 执行预压缩 hooks
  await executePreCompactHooks(messages)

  // 2. 分析上下文
  const analysis = analyzeContext(messages)

  // 3. 生成摘要
  const summary = await generateSummary(messages, analysis)

  // 4. 创建压缩边界消息
  const boundaryMessage = {
    role: 'system',
    type: 'compact_boundary',
    content: summary,
    originalMessages: messages,
    tokenStats: { before, after, saved }
  }

  // 5. 替换历史
  const newMessages = [boundaryMessage, ...messages.slice(-keepRecent)]

  return { messages: newMessages, stats }
}