核心误区与架构概览

在智能体(Agent)开发中,上下文管理是决定模型表现的关键环节。许多开发者误以为上下文压缩(Compaction)仅仅是调用一个总结函数或插入某个 /compact 插件,但 DeepSeek Harness 的做法截然不同。它并非将聊天记录简单追加给模型,而是主动管理模型真正可见的上下文窗口。上下文压缩是整套工程体系中至关重要的一环,其设计初衷是为了让产品具备如 Codex 和 DeepSeek Harness 般优秀的上下文管理能力。

“Codex和DeepSeek Harness的做法有什么不同呢?为什么它们看起来都叫compaction,底层走的却不是同一条路径呢?”

DeepSeek Harness 的上下文压缩不是单一模块,而是一条由多个插件和服务组合而成的能力链。其核心组件包括: 1. dsh-compaction:仅定义 ctx.compaction 能力接口,规定压缩服务应做什么。 2. compaction-basic:实现默认算法,负责决定何时压缩、保留哪些内容、生成摘要及提交新的 checkpoint。 3. Token Meter:独立服务,负责测量上下文压力。 4. Tool Result Pruner(可选):裁剪超大的工具输出结果。 5. Command-compact:提供 /compact 命令作为人工入口,本身不包含摘要算法。

这种模块化设计意味着压缩功能是默认可用且可替换的。通过 Web 或 Headless Profile,用户可以选择 Standard Code、Cordis 等 Agent Preset(预设),这些预设自动组合了 Basic Pruner 和 /compact 命令,对开发者透明。

反直觉的压缩策略:先裁剪后摘要

理解 DeepSeek Harness 的关键在于一个反直觉的例子。假设 Coding Agent 连续工作很久,突然返回几万字的测试日志,将上下文窗口推向红线附近。常规思维是立即调用模型总结历史,但在 DeepSeek Harness 中:第一步很可能根本不需要模型介入。

系统会先调用 tool result pruner 裁掉超大工具结果中间的部分,然后重新测量上下文压力。如果裁剪后上下文回到安全范围,Agent 继续工作,此过程不生成任何摘要。这是该架构最值得讲的地方:它不是简单的总结函数,而是通过确定性且低成本的预处理来缓解压力。

“在DeepSeek Harness里面,第一步很可能根本不需要模型。它会先裁掉超大工具结果的中间部分,再重新测量。”

这种策略的优势在于确定性和便宜。它不需要调用大模型进行语义理解,而是基于规则处理。对于测试日志、报错堆栈等内容,开头和结尾通常比中间大量重复行更重要。因此,系统优先保留关键信息头尾,剔除冗余中间部分。只有当工具结果裁剪后仍然超限,系统才会进入真正的会话摘要阶段。

触发机制与压力测量

DeepSeek Harness 提供了三种主要的上下文压缩入口,确保在不同场景下都能有效管理资源:

  1. 自动压力检查(默认):在上一轮 AI 回复和工具结果写入日志后、下一次请求模型前,系统会检查上下文是否接近上限。默认阈值为模型上下文窗口的 80%。该比例可根据具体的 Provider 和 Model 进行修改。
  2. 模型服务报错触发:当模型明确返回 context window exceeded 错误时,Harness 会尝试压缩。此时无需预先知道窗口大小,因为 Provider 已证明当前请求无法容纳。只有当模型可见的历史真正发生替换后,才会重新提交请求。
  3. 用户命令触发:用户输入 /compact。这要求 Agent 处于空闲状态,即使未达到 80% 阈值也会尝试压缩。该操作不会额外创建一轮模型对话,仅对已有历史进行整理。

无论通过何种入口进入,系统首先需回答“当前上下文到底有多满”,这由独立的 Token Meter 完成。它优先使用 Provider 返回的 token usage 信息,但前提是请求结构一致;对于新增或替换内容,则使用启发式规则估算:大致 4 个字符算一个 token,加上角色内容块和请求结构的开销。

“在这里我们看到的占用率也应该理解成参考数字,而不是一个精确的计费账单。”

这种估算方式对中文和 JSON Schema 可能偏低,因此 Token Meter更像是一个压力计而非精确的 tokenizer。开发者需理解其估算性质,避免将其视为绝对准确的计费依据。

第一层裁剪:基于 Unicode Code Point 的规则

在压力确认后,官方 CLI 默认安装的 Pruner 会执行第一层裁剪。其配置针对三个主要 Preset 设定了统一标准:一条工具结果超过 8,192 个 Unicode code point,则保留开头的 4096 个和结尾的 1024 个,中间替换为固定的裁剪标记。

这里有两个关键细节需要注意: 1. 单位是 Unicode Code Point,而非 Token。这意味着系统不保证沿着人眼理解的完整字符组合(如 Emoji 或复杂汉字)来切分,可能产生断裂。 2. 目的非语言质量:裁剪是为了降低上下文体积,而非优化阅读体验。对于测试日志等结构化数据,保留调用栈的开头和结尾足以定位问题。

裁剪完成后,Basic 模块会重新测量压力。如果此时上下文已降至安全范围,流程直接结束;只有工具结果裁剪后仍然超限,才会进入真正的会话摘要。这一步骤确保了只有在必要时才消耗昂贵的模型资源进行语义压缩。

第二层摘要:保留近期历史与生成 Checkpoint

当必须进入会话摘要时,compaction-basic 模块决定哪些内容被压缩。其策略是从当前模型可见历史的尾部向前积累,默认目标是逐字保留大约 16% 窗口的近期内容。较老的连续区间则成为准备被压缩的部分。

这里需要澄清一个概念:不是压缩后只剩 16%,而是最近的 16% 被逐字保留。最终送给模型的是“旧内容的 Checkpoint”加上“近期的原文”。切分位置的选择有严格约束: * 工具调用配对:如果 AI 发起 Tool Call,对应的结果必须完整保留在摘要范围内或近期原文中。 * 不可分割单元:若最近存在未闭合的工具单元,或某条非工具消息本身过大无法处理,压缩可能被拒绝。

确定范围后,系统调用模型生成摘要。这并非简单的“请总结”,而是重放会话上下文:重新发送系统提示词、工具定义及待压缩消息,最后追加固定的 Compaction Instruction(压缩指令)。

“这条指令要求摘要保留8类信息,包括用户的主要目标、关键技术概念、修改过的文件和代码错误与修复……”

该指令要求摘要保留八类关键信息,目的是让另一个模型拿到 Checkpoint 后能继续当前工作。这种重放方式还能复用现有的 KV Cache,尽管摘要写回后从第一个变化 Token 开始缓存仍会失效。

Checkpoint 生成与失败条件

摘要生成的输出有严格的失败条件。只有纯文本会进入 Checkpoint,以下情况会导致压缩失败: * Reasoning 和工具调用被排除。 * 图片输出失败(当前版本不支持)。 * 因达到 Max Tokens 被截断的摘要也会失败。

此外,系统会进行大小比较:如果处理后的摘要并没有比原来的区间更小,则不会提交此次替换。这意味着压缩必须带来实质性的空间节省。

真正改变模型上下文的是随后的 Surface Replacement(表层替换)。一次成功操作会在会话日志中依次追加四组事实: 1. compaction/start:作为持久锁。 2. compaction/summary:记录摘要来源范围、Token 估值、Provider 和 Model。 3. Checkpoint 消息:带有属性 surfaceOp = replace,这是唯一改变模型可见历史的消息。 4. compaction/end:结束事务。

“原来的事件没有从磁盘日志里消失或删除,只是不再出现在当前这个会话surface里面。”

这种设计被称为 Event Sourced(事件溯源)。开发者不仅能看到摘要,还能追溯它替换了哪段历史、引用了哪些事件。这种设计强调了 Provenance(来源可追溯性),确保压缩过程的透明性和安全性。

架构总结与局限性

回到最初的问题:DeepSeek Harness 的上下文压缩是独立插件还是融合在其他组件中?答案是:它是一项独立能力,但由多个插件组合实现完整功能。

  • Agent Loop:提供触发机制。
  • Token Meter:提供压力测量。
  • Pruner:负责低成本的第一层裁剪。
  • Compaction-Basic:负责摘要生成和表层替换。
  • /Compact 命令独立的人工入口,通常用于用户主动干预。

这种拆分允许开发者替换另一套 Compaction Backend 或不安装 Pruner,而无需修改 Agent Loop。然而,该设计并非万能: 1. 估算误差:Token Meter 的启发式计算存在偏差。 2. 巨大单元压力:不可分割的巨大消息块仍可能导致压缩失败或效率低下。 3. 版本迭代:当前分析基于预发布版本,默认参数和持久化协议未来可能变化。

“DeepSeek Harness的上下文压缩,表面上是把旧会话变短,底层呢真正做的是通过插件的组合维护一份能够继续工作的模型状态。”

结论

DeepSeek Harness 的上下文压缩机制展示了一种模块化、事件溯源且成本敏感的工程实践。它摒弃了单一的“总结即压缩”思维,转而采用分层处理策略:先通过基于 Unicode 规则的 Pruner 低成本裁剪冗余工具输出,仅在必要时才调用模型生成保留近期历史(16%)和关键上下文(8类信息)的 Checkpoint。通过 Surface Replacement 机制,系统在保留完整事件日志的同时更新模型可见视图,实现了压缩过程的可追溯性(Provenance)。尽管存在 Token 估算误差和处理巨大不可分割单元时的局限性,这种由独立插件组合而成的能力链为开发者提供了灵活、透明且高效的上下文管理方案。