Files
deepseek-harness/docs/core-data-structures/compaction.zh.md
2026-07-23 18:45:56 +08:00

7.5 KiB
Raw Blame History

上下文压缩context compaction

English | 中文

压缩 seam 是一个能力 seam,与 bash 一样分为接口(dsh-compactctx.compact)、实现(例如 dsh-compact-basic 后端)和消费方(延期实现的 /compact 工具)。压缩是一项可选能力,不属于 agent loop智能体循环主干因此其词汇定义在此而非 core.md 中。基于 tokenizer 或模板的后端是实现同一接口的兄弟包package。与 bash 不同,该接口必然依赖 dsh-sessiondsh-llm:其动词作用于 agent 所有的 Session,而其持久摘要事件使用 ContentBlock 词汇(见压缩能力 seam Agent Noteagent 决策记录))。

源码:packages/compact/compact/src/types.ts

compact/* 会话事件

压缩通过声明合并为 SessionEventMap 扩展三种事件类型。三者都仅写入日志——记录压缩锁及其 provenance绝不进入 surface。这里有意不扩展 SurfaceEventType(只有产生消息的事件才到达模型),因此摘要本身承载在另一条带有 surfaceOp: { op: 'replace', start, end }user/message 上——这是摘要压缩执行的唯一 surface 变更。关于复用 user/message 为何是如实建模而非权宜之计,见对应 Agent Note。

事件 载荷 作用
compact/start { turn } 获取日志记录的锁
compact/summary { summary, shadowedRange, shadowedSeqs, shadowedTokenCount, provider, model, maxTokens? } provenance摘要块、被遮蔽的 surface 边界对(start/end seq——位置跨度而非数值区间、按 surface 顺序排列的被遮蔽 seq、估算 token 数,以及摘要调用的 envelopeprovidermodel,若有生成上限则还包括该上限)——写入日志后,该一次性请求可由日志 + 代码重建(见可重建性 Agent Note
compact/end { turn, error? } 释放锁(摘要调用抛出异常时设置 error

锁括住整个操作:先追加 compact/start,然后执行摘要生成、写入 compact/summary 来源记录与 user/message 替换,最后才追加 compact/end。最后释放锁意味着操作中途崩溃会表现为可检测的遗留锁(有 compact/start 而无匹配的 compact/end),而非一个虚假声称压缩已完成的 compact/end

这些变体在 declare module '@deepseek-ai/dsh-session' 块内合并,因此——与其他子页面上的顶层类型不同——它们不以漂移检查的 ```ts type-equiv 块粘贴(verify-type-equiv 提取器只按名称匹配顶层声明)。上方的载荷表即为目录条目;权威形状请循源码链接查看。

CompactionResult

成功压缩向调用方返回:记账事件 seq、原始摘要、被遮蔽的范围与 seq以及估算 token 数。

/** Result of a successful compaction operation. */
interface CompactionResult {
  /** The seq of the appended `compact/start` event. */
  startSeq: number
  /** The seq of the appended `compact/summary` event. */
  summarySeq: number
  /** The seq of the appended `compact/end` event. */
  endSeq: number
  /** The summary content blocks produced by the backend. */
  summary: ContentBlock[]
  /**
   * The surface-boundary pair that was shadowed: the seqs of the first
   * (`start`) and last (`end`) surface nodes of the replaced range. A
   * surface-POSITION span, not a numeric seq interval — after a prior replace
   * lands a fresh high-seq summary node at an older range's position, `start`
   * can be GREATER than `end`. {@link CompactionResult.shadowedSeqs} is the
   * authoritative set of shadowed nodes, in surface order.
   */
  shadowedRange: { start: number; end: number }
  /** The seqs of all shadowed surface nodes, in surface order. */
  shadowedSeqs: number[]
  /** Estimated token count of the shadowed content. */
  shadowedTokenCount: number
}

服务

自动调用方会说明策略为何运行;实现可以比普通压力更激进地处理已确认的溢出。

/** Why automatic policy is asking a backend to consider compaction. */
type CompactionTrigger = 'pressure' | 'context-overflow'

CompactService 暴露 compactIfNeeded(agent, trigger, signal) 以执行自动 pressurecontext-overflow 策略;没有可安全执行的工作时返回 null。它还针对显式、两端均包含的 surface 范围暴露 compactRegion(...)。每个后端都使用包导出的 COMPACT_CHECKPOINT_SOURCE 标记其替换用的 user/message;消费方调用 isCompactCheckpointSource(),而不是把检查点识别逻辑耦合到某一个后端。实现必须把传入的 signal 转发给摘要流程。该 seam 不拥有计价 API单例 ctx.tokenMeter 直接拥有估算与回放,而 dsh-compact-basic 拥有保留策略、事件排序、按路由执行的摘要调用及其配置。

压力压缩在串行 agent/post-step 中运行:此时成功的 assistant 输出、工具结果、缓冲上下文和 steering中途引导已持久化step/end 尚未发生。一旦压力或规范化溢出满足条件compact-basic 会在选择范围前调用可选的 ctx.toolResultPrune,再通过 ctx.tokenMeter 重新测量,并且可以在不生成摘要的情况下推进 surface。失败请求的恢复在失败的步骤关闭后通过 agent/request-error 运行;仅当 surface replacement generation 前进时才批准一个带新编号的步骤重试,即便后续摘要工作在剪枝后抛异常亦如此;取消仍然优先。区域边界保持工具调用/结果配对,但不保持整个轮次,因此一个过大轮次中较早关闭的步骤可以被压缩。dsh-compact-basic 拥有阈值、保留尾部策略、溢出上限与失败处理。

该 seam 导出 toolPairingBalancedBefore(session, seq)toolPairingBalancedAfter(session, seq),用于这些边缘检查。两者都会验证当前 surface 成员关系,并拒绝缺失的 seq 与孤立结果;其缓存语义由包契约规定。

工具结果剪枝产出

可选的工具结果剪枝服务会报告每次持久内容替换以及 Unicode code point 的总减少量。其公开结果类型位于 compact-tool-result-prune/src/types.ts

/** Provenance and size accounting for one landed surface replacement. */
interface PrunedEntry {
  /** Full-fidelity tool-result event shadowed by the replacement. */
  readonly originalSeq: number
  /** Newly appended pruned tool-result event. */
  readonly replacementSeq: number
  /** Tool call shared by the original and replacement. */
  readonly callId: CallId
  /** Original text size in Unicode code points. */
  readonly charsBefore: number
  /** Replacement text size in Unicode code points. */
  readonly charsAfter: number
}
/** Aggregate outcome of one stable-surface pruning pass. */
interface PruneResult {
  /** Replacements in the snapshotted surface order. */
  readonly pruned: readonly PrunedEntry[]
  /** Total Unicode code points removed across replacements. */
  readonly charsRemoved: number
}