4.5 Compaction:上下文窗口管理
模型: claude-opus-4-6 (anthropic/claude-opus-4-6) 生成日期: 2025-02-17
Compaction(上下文压缩)是 OpenCode 中解决 LLM 上下文窗口限制的关键机制。当对话历史过长时,Compaction 会自动清理旧内容,确保对话可以持续进行。
4.5.1 为什么需要 Compaction?
衍生概念:LLM 的上下文窗口(Context Window)
每个 LLM 都有一个上下文窗口限制——它在一次请求中能处理的最大 token 数。例如:
Claude Sonnet
200,000 tokens
GPT-4o
128,000 tokens
Gemini Pro
2,000,000 tokens
在 Agentic Coding 场景中,上下文很容易被填满:
System Prompt:~2,000 tokens
AGENTS.md 指令:~1,000-5,000 tokens
每轮对话的消息:~500-2,000 tokens
每次工具调用的输出:~500-50,000 tokens(读取大文件时可能很大)
一次 10 轮的 Agent 对话,可能就消耗 50,000+ tokens。当累计 token 超过上下文窗口时,LLM 会拒绝请求或产生错误。
Compaction 的目标就是:在不丢失关键信息的前提下,压缩对话历史以腾出上下文空间。
4.5.2 溢出检测算法:isOverflow()
isOverflow()SessionCompaction.isOverflow() 判断当前对话是否即将超出上下文窗口:
关键参数:
COMPACTION_BUFFER = 20,000:在上下文窗口末尾预留 20K tokens 的缓冲区。这确保即使检测到溢出,也还有足够的空间让 LLM 生成最后的回复和压缩摘要。reserved:实际预留空间。取COMPACTION_BUFFER和模型最大输出 token 的较小值。
4.5.3 Prune 策略:工具输出的渐进式清理
在触发完整的 Compaction 之前,OpenCode 会先尝试 Prune(修剪)——一种更轻量的清理方式:
Prune 算法的核心思想:
从后往前遍历消息历史
保护最近 2 轮对话的所有内容
保护最近 40K tokens 的工具输出
超过保护区的旧工具输出 → 替换为
"[output truncated by compaction]"skill工具的输出永不清理(因为 Skill 内容对后续行为至关重要)
这种策略的直觉是:旧的工具输出(比如 10 轮前读取的文件内容)很可能已经不再相关,可以安全丢弃;而最近的工具输出仍然是当前推理的依据,必须保留。
4.5.4 Compaction 执行流程
如果 Prune 后空间仍不够,就会触发完整的 Compaction——用 LLM 生成一段摘要来替代旧的消息历史:
Compaction 使用的 Prompt 模板在 agent/prompt/compaction.txt 中定义。
4.5.5 Token 估算工具
由于精确的 token 计数需要使用模型的 tokenizer(分词器),OpenCode 在某些场景下使用快速估算:
这个估算值不需要精确——它只用于 Prune 策略中判断"大约"清理了多少 token。而精确的 token 数来自 LLM Provider 的响应元数据(usage 字段)。
Last updated
