Compaction 对话压缩(长对话历史压缩的 OpenClaw 策略详解)

当对话历史实在太长、会话修剪(Pruning)也不够用时,Compaction 是 OpenClaw 的核心应对手段。它将较早的对话轮次汇总为一个精简摘要条目,保存到会话转录中,近期消息保持完整。完整历史始终保留在磁盘上,压缩只改变模型在下一轮看到的内容。OpenClaw 的 Compaction 默认启用自动触发,采用 safeguard 质量守护模式,支持可插拔压缩提供商,并在压缩前自动刷新记忆以防止信息丢失。

一、为什么需要 Compaction

会话修剪只能裁剪旧工具结果,不改写对话文本。当对话本身很长——几百轮交互、大量来回讨论——修剪工具输出释放的空间杯水车薪,模型上下文窗口仍然不够用。

场景 修剪是否够用 是否需要 Compaction
工具结果累积过大 够用 不需要
对话轮次过多 不够 需要
接近上下文窗口上限 视情况 通常需要
模型返回溢出错误 不够 需要(自动触发)
想保留关键讨论、丢弃冗余 不适用 需要

Compaction 解决的是”对话本身太长”的问题,而非”单条工具结果太大”的问题。两者的分工明确:修剪裁工具输出,压缩摘要对话文本。

二、Compaction 的工作原理

2.1 核心流程

Compaction 的执行分为四步:

  1. 选择压缩拆分点(split point),确定哪些轮次被摘要、哪些保留;
  2. 将较早的对话轮次交给模型生成摘要,保存为 compaction 类型的转录条目;
  3. 近期消息保持完整,后续轮次看到的是”摘要 + 近期消息”;
  4. 完整对话历史仍保留在磁盘上的 SQLite 会话存储中。
# Compaction 核心伪代码
def compact(session, keep_recent_tokens=20000):
    # 1. 估算各轮次 Token,找到拆分点
    split_point = find_split_point(session, keep_recent_tokens)
    
    # 2. 确保工具调用与 toolResult 配对不被打断
    split_point = adjust_for_tool_pairs(session, split_point)
    
    # 3. 将拆分点之前的轮次交给模型生成摘要
    older_turns = session[:split_point]
    summary = model.summarize(older_turns, 
                               preserve_identifiers=True)
    
    # 4. 写入 compaction 条目,保留近期消息
    session.insert_compaction_entry(
        summary=summary,
        firstKeptEntryId=split_point,
        tokensBefore=session.total_tokens
    )
    # 完整历史仍在磁盘上,不删除

2.2 工具调用配对保留

这是 Compaction 最关键的细节。OpenClaw 选择拆分点时,会让助手的工具调用与其对应的 toolResult 条目保持配对。如果拆分点恰好落在工具块内部——比如助手发了工具调用但结果还没返回的位置——OpenClaw 会自动移动边界,让配对保持在一起。

这一设计避免了”模型看到了工具调用但看不到结果”的断裂状态,否则模型可能在下一轮重复发起相同的工具调用,浪费 Token 和时间。

2.3 摘要的存储与可见性

层面 说明
摘要存储位置 会话转录(SQLite),类型为 compaction
摘要包含字段 firstKeptEntryId、tokensBefore
磁盘完整历史 始终保留,不删除
模型下一轮看到的内容 摘要 + firstKeptEntryId 之后的消息
历史查看器 仍可渲染原始消息条目

OpenClaw 不再为新压缩写入单独的 .checkpoint.*.jsonl 副本,现有旧版检查点文件在被引用时仍可使用,并由正常会话清理机制修剪。

三、自动压缩与手动压缩

3.1 自动压缩(Auto-compaction)

自动压缩默认启用,在两种情况下触发:

  1. 阈值触发:会话接近上下文窗口上限时(如总窗口 20 万、预留 2 万缓冲,Token 用量超过 18 万时);
  2. 溢出恢复:模型返回上下文溢出错误时,OpenClaw 先压缩历史再重试该轮请求。
{
  "agents": {
    "defaults": {
      "compaction": {
        "enabled": true,
        "mode": "safeguard"
      }
    }
  }
}

设置 enabled: false 可禁用嵌入式运行时的主动阈值压缩,但 OpenClaw 的预检和溢出恢复压缩路径仍然可用,手动 /compact 也不受影响。

3.2 手动压缩

在任何聊天中输入 /compact 可强制执行压缩,还能附加指令引导摘要重点:

/compact 请特别保留关于项目架构的讨论内容

手动压缩使用 keepRecentTokens(默认 20,000)作为截断点预算,在重建的上下文中保留该近尾部内容。如果未明确设置保留预算,手动压缩的行为类似硬性检查点,只从新摘要继续。

四、safeguard 质量守护模式

新配置默认将 agents.defaults.compaction.mode 设为 "safeguard",提供更严格的守护措施和摘要质量审计。

4.1 质量校验流程

启用 safeguard 后,OpenClaw 在验证前应用最终摘要预算,执行以下检查:

  1. 必需标题检查:必须保留的标题必须出现在保留的生成正文中;
  2. 待处理请求检查:待处理的用户请求必须出现在将存储的确切文本中;
  3. 标识符保留检查:默认 identifierPolicy: "strict",不透明标识符(如文件路径、ID、配置值)必须原样保留。

4.2 校验失败的处理

校验结果 处理方式
通过 写入 compaction 条目,压缩完成
不通过 给予配置次数的纠正重试
所有重试均不通过 中止压缩,保留原始历史,暴露现有恢复结果

这一机制防止低质量摘要污染会话上下文。如果压缩无法通过质量门禁,宁可不做也不做错——保留原始历史比写入一个丢信息的摘要更安全。

五、配置项与高级用法

5.1 核心配置项

配置项 默认值 说明
enabled true 是否启用自动压缩
mode "safeguard" 压缩模式(safeguard / default)
keepRecentTokens 20000 手动压缩的近尾部保留预算
model 继承会话模型 执行摘要的模型
identifierPolicy "strict" 标识符保留策略
maxActiveTranscriptBytes 未设置 活跃转录字节守护阈值
notifyUser false 是否向用户显示压缩状态消息

5.2 指定压缩模型

默认情况下压缩使用 Agent 的主模型。可以指定一个更擅长摘要或更便宜的模型来做压缩:

{
  "agents": {
    "defaults": {
      "compaction": {
        "model": "ollama/llama3.1:8b"
      }
    }
  }
}

如果摘要因模型级回退 eligible 的提供商错误而失败,OpenClaw 会通过会话现有的模型回退链重试该次压缩。但显式指定的 compaction.model 覆盖是精确的,不继承会话回退链。

5.3 记忆刷新(Memory Flush)

压缩前,OpenClaw 可以运行一轮静默的记忆刷新,将持久笔记保存到磁盘:

{
  "agents": {
    "defaults": {
      "compaction": {
        "memoryFlush": {
          "model": "ollama/qwen3:8b"
        }
      }
    }
  }
}

这防止了”压缩丢信息”的担忧:重要事实在压缩前已落盘到记忆文件,即使摘要遗漏了某些细节,Agent 仍可通过记忆检索找回。

5.4 活跃转录字节守护

maxActiveTranscriptBytes 针对长期运行的会话,在转录历史达到指定大小时触发压缩:

{
  agents: {
    defaults: {
      compaction: {
        maxActiveTranscriptBytes: "20mb"
      }
    }
  }
}

这在提供商侧上下文管理可能保持模型上下文健康、但持久化转录历史持续膨胀的场景下尤其有用。它不拆分原始字节,而是请求正常压缩管线创建语义摘要。

六、可插拔压缩提供商

插件可通过 registerCompactionProvider 注册自定义压缩提供商。当提供商注册并配置后,OpenClaw 将摘要工作委托给它,而非使用内置 LLM 管线。

{
  "agents": {
    "defaults": {
      "compaction": {
        "provider": "my-provider"
      }
    }
  }
}

设置 provider 会自动强制 mode: "safeguard"。提供商接收与内置路径相同的压缩指令和标识符保留策略,OpenClaw 仍在提供商输出后保留近期轮次和拆分轮次的后缀上下文。如果提供商失败或返回空结果,OpenClaw 回退到内置 LLM 摘要。

七、Compaction 与 Pruning 的对比

维度 Compaction(压缩) Pruning(修剪)
作用对象 整段对话历史 旧工具结果
信息处理方式 摘要化 截断或清除
是否持久化 是(保存到会话转录) 否(仅内存,按请求执行)
触发时机 接近窗口上限或溢出错误 缓存 TTL 过期 + 上下文占比
信息损失程度 中(摘要压缩) 低(只清工具输出)
配置位置 agents.defaults.compaction agents.defaults.contextPruning

两者相辅相成:修剪在各次压缩周期之间保持工具输出精简,减少压缩频率;压缩在修剪不够用时做更深度的瘦身。如果两者都不够,就该用 /new 开新会话了。

常见问题(FAQ)

Q1:Compaction 会删除原始对话历史吗?

不会。完整历史保留在磁盘上,压缩只改变模型下一轮看到的内容。

Q2:压缩后 Agent 会忘记之前的讨论吗?

摘要保留关键信息,压缩前还会提醒 Agent 保存重要笔记到记忆文件。

Q3:能指定不同的模型做压缩吗?

能。设置 compaction.model 即可委托更擅长摘要的模型执行压缩。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 qiqicto@qq.com 举报,一经查实,本站将立刻删除。
赞 (0)
套餐观察官的头像套餐观察官普通用户

相关推荐

返回顶部