跳到主要内容

上下文管理

你正在用 AI 重构一个大模块。Agent 已经读了十几个文件、执行了一堆 shell 命令、搜索了几十个符号引用。半小时之后,它开始变得“迟钝”——回答开始跑偏、重复犯之前的错误、忘了你早就告诉过它的关键信息。

模型并没有变笨。是上下文窗口不堪重负。

Helix 用两种互补的策略来解决这个问题:Cache(存储并按需召回)与 Compact(压缩为结构化摘要)。


为什么上下文管理至关重要

工具密集型的 AI 工程任务,token 消耗增长远比普通对话快得多:

  • 读一个 500 行的文件 → ~2,000 tokens
  • 执行一次 find 命令 → 可能输出几千行
  • 搜索代码引用 → 几十个文件中的匹配结果
  • 每次工具调用的参数和返回都计入上下文

10 次工具调用之后,你可能已经消耗了 50K+ tokens。而大多数模型对最近内容的注意力更集中——早期的重要决策与上下文正在被遗忘。

没有上下文管理,你只有两种选择:

  1. 开新对话——丢失所有进度
  2. 硬撑下去——输出质量持续下降,成本持续上升

Helix 提供了第三种方式。


Cache:存储大型输出,按需召回

Cache 解决的问题是:工具输出太大,但并不是每次都需要。

工作原理

  1. 当对话轮次超过阈值后,Helix 会自动用轻量的 cache 标记替换早期消息中的大型工具输出
  2. 原始内容存入本地 KV cache(Pebble 存储引擎,使用 SHA256 内容寻址去重)
  3. Cache 标记保留在对话历史里,形如 [CACHED] recall_cached_content("sha256hash")
  4. 当 Agent 需要重新查看历史的工具输出时,通过 recall_cached_content 工具按需召回原始内容

关键设计选择

  • 内容寻址去重 —— 相同内容只存储一次,SHA256 哈希保证唯一性
  • 高可逆性 —— 任意被缓存的内容都可以完整召回,没有信息损失
  • 自动触发 —— 无需用户介入,系统按对话轮次自行处理
  • Workspace 级隔离 —— 每个 Workspace 拥有独立的 cache 实例,由 builtin_context_cache MCP server 管理

实际效果

设想一个有 80 次工具调用的会话,前 60 次的工具输出已经不在“活跃工作区”里。Cache 用几十字节的标记替换它们,释放出大量上下文空间,而 Agent 任何时候都依然可以“回看”任意历史输出。


Compact:把旧对话压缩为结构化摘要

Compact 解决的问题是:对话历史太长,但又不能直接全部丢掉。

触发条件

当 token 使用量达到上下文窗口的 85% 时(默认窗口大小:128K tokens),Compact 自动触发。还需满足额外条件:

  • 当前没有正在进行的压缩操作
  • 距上次压缩至少经过 60 秒(冷却期)
  • 有足够多的历史消息可被压缩

压缩方式:“交接文档”格式

Compact 不是简单地截断或删除旧消息。它会调用 AI 生成结构化的交接文档摘要,包含六个章节:

摘要章节内容
项目背景项目类型、技术栈、关键架构信息
技术细节已发现的重要技术事实与约束
已完成工作至今完成的内容、关键决策与理由
当前问题阻塞点和未解决的问题
TODO 事项接下来要做什么,并按优先级排列
用户偏好用户表达过的风格、约束与特殊要求

这份摘要会作为一条 [Conversation History Summary] 消息注入对话历史,替换被压缩的旧消息。

三阶段加锁策略

为了避免压缩过程与正在进行的对话冲突,Compact 使用三阶段加锁策略:

  1. 加锁,读取数据 —— 获取锁,读取要压缩的消息
  2. 释放锁,调用 AI —— 释放锁,调用 AI 生成摘要(这一步耗时较长,不阻塞对话)
  3. 重新加锁,写回结果 —— 再次加锁,把摘要写入对话历史

这意味着用户在 Compact 生成摘要的同时可以继续正常对话——不会被阻塞。


Cache 与 Compact:何时用哪一个

维度CacheCompact
优化对象大型工具输出的重复传输过长的对话历史
可逆性✅ 高——任何时候都可恢复完整原文⚠️ 低——压缩为摘要后细节丢失
触发时机基于对话轮次阈值token 用量达到窗口 85%
存储方式本地 KV cache(Pebble + SHA256)替换为摘要消息
用户感知几乎不可见——Agent 自行决定何时召回可能可见——早期细节会被摘要化
适用对象文件内容、命令输出、搜索结果已完成的讨论段落、早期推理

双策略协同的完整生命周期

会话开始

▼ 正常对话(所有内容都在上下文中)

├─ 工具输出不断累积...

▼ 轮次超过阈值 → Cache 启动
│ 早期工具输出 → cache 标记
│ 需要时 → recall_cached_content 取回

├─ 对话继续增长...

▼ token 达到窗口 85% → Compact 触发
│ 旧对话 → “交接文档”摘要
│ 最近对话保持完整

├─ 工作继续...

▼ 再次接近上限 → Compact 再次触发(60s 冷却之后)

└─ 会话可运行数小时 / 跨天

真实场景

场景:跨天的大规模重构任务

  • 第 1 小时:理解代码结构,读了十几个文件 → Cache 开始存储早期工具输出
  • 第 2 小时:形成方案,开始改动代码 → 上下文接近 85% → Compact 生成第一份交接摘要
  • 第 3 小时:继续改动,遇到问题需要回看早期文件 → Agent 通过 Cache 召回
  • 第二天:再次 Compact → 摘要更新 → 工作继续,关键上下文不丢失

整个过程中,用户无需手动管理任何东西。系统自动平衡上下文容量、信息保留与成本。


与其他能力的协同

与 SubAgent

SubAgent 在隔离的上下文中运行,拥有独立的 Cache/Compact 策略。子任务的中间工具输出永远不会进入主会话上下文——主会话只接收提炼后的摘要结果。这是另一种形式的“上下文保护”。

与 Workspace

Cache 与 Compact 都在 Workspace 级别运行——每个 Workspace 拥有独立的缓存存储与压缩策略。不同项目之间的上下文管理互不干扰。


相关文档