【与我学 ClaudeCode】记忆管理篇 之 Context Compact :三层压缩实现「无限会话」
作者逆境不可逃技术永无止境希望我的内容可以帮助到你大家吼 ! 我是 逆境不可逃 今天给大家带来文章《【与我学 ClaudeCode】记忆管理篇 之 Context Compact 三层压缩实现「无限会话」》.Learn-Claude-Code 官方地址 :https://github.com/shareAI-lab/learn-claude-code上一篇文章https://blog.csdn.net/2401_87662859/article/details/161276600?spm1001.2014.3001.5502Context Compact 是迭代的第 6 个版本s06核心解决上下文窗口有限、长会话易溢出的问题。它通过「三层递进式压缩 磁盘归档」策略让 Agent 既能在内存中保持上下文精简又能完整保留所有对话历史实现理论上的「无限会话」。一、问题根源为什么长会话一定会被上下文窗口 “杀死”Agent 在处理大项目时上下文会以惊人的速度膨胀读一个 1000 行的文件吃掉4000 token读 30 个文件、跑 20 条命令轻松突破 100k token 窗口限制传统方案要么直接截断旧消息丢失关键上下文要么一直堆到溢出API 报错Agent 根本无法在大型项目中持续工作二、四大核心设计决策图片内容详解Context Compact 通过四个关键设计构建了低成本、高效率、可追溯的上下文管理体系。1. 三层压缩策略成本与收益的分层平衡核心设计上下文管理使用三个独立的层次成本激进程度递增微压缩Micro-compact每轮运行几乎零成本。截断旧消息中的tool_result块去除不再需要的冗长命令输出自动压缩Auto-compacttoken 超过阈值时触发。调用 LLM 生成对话摘要代价高但能大幅缩减上下文手动压缩Manual compact用户 / 模型主动触发用于明确的「重新开始」场景仅在真正需要时执行替代方案的致命缺陷单一压缩策略如总是在 80% 容量时摘要实现更简单但会浪费 token滑动窗口丢弃最旧 N 条消息成本低但会丢失重要上下文。三层方案实现了最佳 token 效率低成本清理持续运行昂贵的摘要极少触发。2. 最小节省量阈值20,000 Token 才触发压缩核心设计自动压缩仅在「估算节省量当前 token 数 - 预估摘要大小超过 20,000 token」时触发。压缩本身会消耗 token摘要文本和 API 调用成本20K 的阈值确保只有在节省量明显超过开销时才执行压缩。替代方案的致命缺陷基于百分比的阈值如上下文 80% 满时压缩能适配不同窗口大小但没考虑生成摘要的固定成本固定 10K 阈值压缩更激进但往往得不偿失。20K 是经验验证的平衡点压缩节省的 token 始终超过摘要带来的质量损失。3. 摘要替换全部消息而非保留部分历史核心设计自动压缩触发时生成摘要并替换全部消息历史不会保留最近的 N 条消息。这避免了「重复信息冲突」的问题如果同时保留近期消息和旧消息的摘要模型会看到同一内容的两种表示比如摘要说 “决定用方案 X”而近期消息还在讨论方案 Y产生矛盾信号。干净的摘要是一个连贯的单一叙述。替代方案的致命缺陷保留最近 5-10 条消息和摘要一起能保留近期细节但会创建重叠问题且总上下文大小不可预测。部分系统使用「滑动窗口 摘要」的方式虽然有效但需要仔细调整重叠区域。4. 完整对话以 JSONL 格式归档到磁盘核心设计尽管上下文在内存中被压缩完整的未压缩对话仍会追加到磁盘上的 JSONL 文件中。每条消息、每次工具调用、每个结果都不会丢失。对内存上下文的压缩是有损操作但对永久记录是无损的。事后分析、调试 Agent 行为、计算 token 用量、提取训练数据都可以基于完整记录进行。替代方案的致命缺陷不归档能节省磁盘空间但调试会变得极其困难 —— 当 Agent 出错时你无法看到 200 条消息之前的思考过程数据库存储如 SQLite提供了可查询性但会增加依赖。JSONL 是支持追加写入、易处理的最简单格式。三、系统整体架构与三层压缩流程1. 核心架构图Every turn: ------------------ | Tool call result | ------------------ | v [Layer 1: micro_compact] (silent, every turn) Replace tool_result 3 turns old with [Previous: used {tool_name}] | v [Check: tokens 50000?] | | no yes | | v v continue [Layer 2: auto_compact] Save transcript to .transcripts/ LLM summarizes conversation. Replace all messages with [summary]. | v [Layer 3: compact tool] Model calls compact explicitly. Same summarization as auto_compact.2. 关键组件与实现细节(1) 第一层Micro-compact微压缩这是零成本的每轮清理核心逻辑是替换旧的tool_result为占位符仅保留最近 3 次的工具输出def micro_compact(messages: list) - list: # 收集所有 tool_result 的位置 tool_results [] for msg_idx, msg in enumerate(messages): if msg[role] user and isinstance(msg.get(content), list): for part_idx, part in enumerate(msg[content]): if isinstance(part, dict) and part.get(type) tool_result: tool_results.append((msg_idx, part_idx, part)) # 如果工具结果数量少于等于保留数直接返回 if len(tool_results) KEEP_RECENT: return messages # 构建工具ID到工具名称的映射 tool_name_map {} for msg in messages: if msg[role] assistant: for block in msg.get(content, []): if hasattr(block, type) and block.type tool_use: tool_name_map[block.id] block.name # 替换旧的工具结果保留最近 KEEP_RECENT 个 to_clear tool_results[:-KEEP_RECENT] for _, _, result in to_clear: # 跳过短结果和需要保留的工具如 read_file if len(result.get(content, )) 100: continue tool_id result.get(tool_use_id, ) tool_name tool_name_map.get(tool_id, unknown) if tool_name in PRESERVE_RESULT_TOOLS: continue # 替换为占位符 result[content] f[Previous: used {tool_name}] return messages关键优化保留read_file的结果属于PRESERVE_RESULT_TOOLS因为这些是参考材料压缩后会迫使 Agent 重新读取文件浪费 token成本收益几乎零成本每轮都执行能有效控制上下文的 “日常膨胀”(2) 第二层Auto-compact自动压缩当 token 数超过阈值默认 50,000时触发核心逻辑是「先归档再摘要」def auto_compact(messages: list) - list: # 1. 保存完整对话到 JSONL 文件 TRANSCRIPT_DIR.mkdir(exist_okTrue) transcript_path TRANSCRIPT_DIR / ftranscript_{int(time.time())}.jsonl with open(transcript_path, w) as f: for msg in messages: f.write(json.dumps(msg, defaultstr) \n) print(f[transcript saved: {transcript_path}]) # 2. 调用 LLM 生成对话摘要 conversation_text json.dumps(messages, defaultstr)[-80000:] # 取最近 80k token 做摘要 response client.messages.create( modelMODEL, messages[{role: user, content: Summarize this conversation for continuity. Include: 1) What was accomplished, 2) Current state, 3) Key decisions made. Be concise but preserve critical details.\n\n conversation_text}], max_tokens2000, ) summary next((block.text for block in response.content if hasattr(block, text)), ) # 3. 用摘要替换所有消息 return [ {role: user, content: f[Conversation compressed. Transcript: {transcript_path}]\n\n{summary}}, ]关键设计摘要会包含「已完成的工作、当前状态、关键决策」确保 Agent 不会丢失上下文连贯性成本收益高成本API 调用 摘要 token但能一次性将上下文压缩到 2000 token 左右节省数万 token(3) 第三层Manual compact手动压缩通过新增的compact工具实现由模型或用户主动触发逻辑与auto_compact完全相同TOOL_HANDLERS { # 其他工具略 compact: lambda **kw: Manual compression requested., } # 在 agent_loop 中处理 if block.name compact: manual_compact True output Compressing... # 工具调用后执行压缩 if manual_compact: print([manual compact]) messages[:] auto_compact(messages) return使用场景模型判断任务进入新阶段如完成了需求分析准备开始编码或用户明确要求 “重置上下文” 时触发成本收益与自动压缩相同但由用户 / 模型主动控制更灵活3. Agent 主循环三层压缩的整合def agent_loop(messages: list): while True: # 第一层每轮微压缩 micro_compact(messages) # 第二层token 超过阈值时自动压缩 if estimate_tokens(messages) THRESHOLD: print([auto_compact triggered]) messages[:] auto_compact(messages) # 调用 LLM response client.messages.create( modelMODEL, systemSYSTEM, messagesmessages, toolsTOOLS, max_tokens8000, ) messages.append({role: assistant, content: response.content}) if response.stop_reason ! tool_use: return results [] manual_compact False for block in response.content: if block.type tool_use: if block.name compact: manual_compact True output Compressing... else: handler TOOL_HANDLERS.get(block.name) output handler(**block.input) if handler else fUnknown tool: {block.name} results.append({type: tool_result, tool_use_id: block.id, content: str(output)}) messages.append({role: user, content: results}) # 第三层手动压缩触发 if manual_compact: print([manual compact]) messages[:] auto_compact(messages) return4.执行流程四、与 Skillss05的关键变更对比组件之前s05 Skills之后s06 Context Compact工具集5 个工具基础 load_skill5 个工具基础 compact上下文管理无自然膨胀三层压缩策略Micro-compact无旧工具结果替换为占位符Auto-compact无token 阈值触发的 LLM 摘要归档机制无对话保存到.transcripts/目录的 JSONL 文件核心优化按需知识加载上下文压缩与永久归档五、核心优势与创新点无限会话能力通过三层压缩让上下文始终保持在窗口限制内理论上支持无限长的对话极致的 token 效率日常膨胀由零成本微压缩控制昂贵的摘要仅在真正划算时触发token 浪费率极低无损调试能力完整对话以 JSONL 格式归档事后调试、问题复现、训练数据提取都能基于完整记录进行避免摘要矛盾用单一摘要替换全部消息消除了 “摘要 近期消息” 的重复信息冲突问题灵活的手动控制compact工具让模型和用户都能主动触发压缩适配任务阶段切换等场景六、运行示例假设 Agent 正在处理一个大型项目重构任务会话流程如下前几轮对话中Agent 执行read_file、bash ls等工具micro_compact每轮都会将超过 3 轮的旧tool_result替换为占位符控制上下文膨胀当对话 token 数超过 50,000 时auto_compact自动触发将完整对话保存到.transcripts/transcript_xxx.jsonl调用 LLM 生成摘要「已完成项目结构分析确定了重构的核心模块当前准备开始修改认证逻辑」用摘要替换所有消息上下文 token 数骤降到 2000 左右Agent 继续基于摘要进行工作后续对话中可以随时调用compact工具手动触发压缩如果后续调试时发现问题可以直接读取 JSONL 文件查看完整的对话历史和工具输出七、可扩展方向分层摘要实现多级摘要会话级、阶段级让 Agent 可以快速回顾关键阶段的进展智能阈值调整根据当前任务类型如编码 / 调试 / 文档动态调整压缩阈值和保留工具列表摘要质量优化在摘要提示词中加入项目特定的关键信息如技术栈、架构约束提升摘要的实用性归档索引为 JSONL 归档文件添加简单索引支持按任务、工具调用、关键词快速检索