Context Window Auto-Compaction
Clawdbot Contributors· validated-in-production
问题
上下文(Context)溢出是侵蚀Agent可靠性的隐形杀手。当累积的对话历史超出模型的上下文窗口(context window)时,会引发以下问题:
- API错误:请求因
context_length_exceeded或类似错误而失败 - 人工干预需求:运维人员必须截断对话记录,导致宝贵的Context丢失
- 重试复杂性:检测溢出并通过压缩方式重试的过程极易出错
Agent需具备自动压缩功能,在令牌(token)限额内保留核心信息,同时结合模型专属校验机制与预留令牌下限,以防止溢出问题立即再次发生。
方案
由上下文溢出错误触发的自动会话压缩机制,具备智能预留令牌和队列感知重试能力。系统会自动检测溢出、压缩会话记录、验证结果并重试请求——所有操作对用户完全透明。
核心概念:
- 溢出检测:捕获表明上下文长度超出的API错误(如
context_length_exceeded、prompt过长等)。 - 带压缩的自动重试:发生溢出时,系统会自动压缩会话并重试请求。
- 预留令牌下限:压缩后确保剩余令牌不低于最小数量(默认20k),避免立即再次出现溢出。
- 队列感知压缩:采用分层队列(会话→全局)机制,防止压缩过程中出现死锁。
- 压缩后验证:估算压缩后的令牌数量,确认其小于压缩前的令牌数。
- 模型专属验证:Anthropic模型要求严格的轮次顺序;Gemini模型则有不同的会话记录格式要求。
实现草图:
async function compactEmbeddedPiSession(params: {
sessionFile: string;
config?: Config;
}): Promise<CompactResult> {
// 1. 加载会话并配置预留令牌
const sessionManager = SessionManager.open(params.sessionFile);
const settingsManager = SettingsManager.create(workspaceDir, agentDir);
// 确保满足最低预留令牌要求(默认20k)
ensurePiCompactionReserveTokens({
settingsManager,
minReserveTokens: resolveCompactionReserveTokensFloor(params.config),
});
// 2. 针对模型API清理会话历史
const prior = sanitizeSessionHistory({
messages: session.messages,
modelApi: model.api,
modelId,
provider,
sessionManager,
});
// 3. 执行模型专属验证
const validated = provider === "anthropic"
? validateAnthropicTurns(prior)
: validateGeminiTurns(prior);
// 4. 压缩会话
const result = await session.compact(customInstructions);
// 5. 估算压缩后的令牌数量
let tokensAfter: number | undefined;
try {
tokensAfter = 0;
for (const message of session.messages) {
tokensAfter += estimateTokens(message);
}
// 合理性检查:压缩后令牌数必须小于压缩前
if (tokensAfter > result.tokensBefore) {
tokensAfter = undefined; // 不采信该估算结果
}
} catch {
tokensAfter = undefined;
}
return {
ok: true,
compacted: true,
result: {
summary: result.summary,
tokensBefore: result.tokensBefore,
tokensAfter,
},
};
}
预留令牌强制机制:
const DEFAULT_PI_COMPACTION_RESERVE_TOKENS_FLOOR = 20_000;
function ensurePiCompactionReserveTokens(params: {
settingsManager: SettingsManager;
minReserveTokens?: number;
}): { didOverride: boolean; reserveTokens: number } {
const minReserveTokens = params.minReserveTokens ?? DEFAULT_PI_COMPACTION_RESERVE_TOKENS_FLOOR;
const current = params.settingsManager.getCompactionReserveTokens();
if (current >= minReserveTokens) {
return { didOverride: false, reserveTokens: current };
}
// 覆盖配置以确保满足最低令牌下限
params.settingsManager.applyOverrides({
compaction: { reserveTokens: minReserveTokens },
});
return { didOverride: true, reserveTokens: minReserveTokens };
}
基于API的压缩(OpenAI Responses API): 部分服务商提供了专用的压缩端点,效率优于手动摘要:
// OpenAI的/responses/compact端点
const compacted = await responsesAPI.compact({
messages: currentMessages,
});
// 返回结果包含以下类型的条目:
// - 特殊type=compaction的条目,带有encrypted_content字段
// 用于保留模型对原始对话的潜在理解
// - 精简后的对话条目
currentMessages = compacted.items;
该方案具备以下优势:
- 保留潜在理解:
encrypted_content字段会保存模型对原始对话的压缩表示 - 效率更高:服务端压缩速度快于客户端本地摘要
- 自动触发压缩:当超出
auto_compact_limit阈值时可自动触发压缩
队列感知重试(防止死锁):
// 压缩流程先经过会话队列,再进入全局队列
async function compactEmbeddedPiSession(params: CompactParams): Promise<CompactResult> {
const sessionLane = resolveSessionLane(params.sessionKey);
const globalLane = resolveGlobalLane(params.lane);
return enqueueCommandInLane(sessionLane, () =>
enqueueCommandInLane(globalLane, () =>
compactEmbeddedPiSessionDirect(params) // 核心压缩逻辑
)
);
}
如何使用
操作步骤
- 配置预留下限:设置
compaction.reserveTokensFloor参数,确保上下文压缩后留有足够缓冲空间(默认值为20000)。 - 处理溢出错误:捕获API错误,通过匹配错误信息检测令牌溢出,随后触发上下文压缩。
- 验证会话记录:在重试前执行模型专属校验(如Anthropic的轮次校验、Gemini的顺序校验)。
- 估算压缩后令牌数:在重试前确认上下文压缩确实降低了令牌总量。
- 使用通道排队机制:通过分层通道执行上下文压缩,避免与并发操作产生死锁。
需规避的误区
- 预留下限设置过于激进:预留令牌阈值过高可能导致实际会话内容的可用空间不足。
- 遗漏模型专属校验:跳过会话记录的模型专属校验,会导致重试时出现API错误。
- 令牌估算偏差:估算启发式算法可能与实际令牌数存在偏差,仅需将估算结果作为合理性校验依据。
- 无限压缩循环:若上下文压缩无法减少令牌数量,需避免无限重试循环,最多执行1-2次尝试。
(注:compaction为LLM领域通用术语,此处译为“上下文压缩”,也可保留原英文表述)
权衡
优点:
- 透明恢复:溢出错误会自动处理,无需用户干预。
- 保留关键上下文:压缩操作生成摘要,而非进行任意截断。
- 防止二次溢出:预留令牌下限确保短期内不太可能立即再次发生溢出。
- 模型感知适配:针对不同供应商采用专属验证规则,保障API兼容性。
缺点/注意事项:
- 摘要质量:自动生成的摘要可能会丢失人工整理所能保留的细微细节。
- 延迟损耗:压缩与重试操作会带来额外开销,耗时从几秒到几分钟不等,具体取决于上下文规模。
- 令牌估算误差:启发式算法可能会误判实际令牌数量,进而导致重试失败。
- 实现复杂度:通道感知队列与模型专属验证逻辑增加了实现难度。
参考文献
关键词:
涵盖Clawdbot项目中负责压缩编排、预留令牌配置、上下文评估的功能实现文件,Pi编码代理的核心压缩逻辑,OpenAI Codex代理循环的API端点方案,以及上下文窗口主动管理、提示词缓存的相关技术模式。
直译:
- Clawdbot compact.ts - 压缩编排
- Clawdbot pi-settings.ts - 预留令牌配置
- Clawdbot context-window-guard.ts - 上下文评估
- Pi编码代理 SessionManager - 核心压缩逻辑
- 拆解Codex代理循环 | OpenAI博客 - 基于API的
/responses/compact端点方案 - 相关内容:上下文窗口焦虑管理(用于主动式管理)
- 相关内容:通过精确前缀保留实现提示词缓存
来源摘要
正在获取来源并生成中文摘要…
来源: https://github.com/clawdbot/clawdbot/blob/main/src/agents/pi-embedded-runner/compact.ts