前言¶
在 DeepSeek Harness(DSH)里跑长会话智能体时,成本往往不来自「轮数多」,而是每一轮都会把同一段材料再次塞进请求:模型自己的 thinking 会随轮次单调增长;同一文件或页面被反复 read,内容在上下文里出现多次;终端工具每次回传完整命令参数,而决策通常只看输出;更早的轮次仍占窗口,却未必影响当前一步。
常见做法是手动删历史或换会话,本地 trajectory 与导出会丢信息。下面介绍维护者 DaVinci-2nd 的 dsh-context-saver:只在向模型提交的那一刻裁剪 outbound 副本,本地 session log、聊天记录与 trajectory 视图保持完整;插件关闭或所有选项关闭时,请求与未裁剪版本字节一致。
这是什么¶
dsh-context-saver 是 DSH 的 send-time 上下文裁剪插件,归类为模型推理相关能力。它解决的是长 agent 会话里 prompt token 膨胀、重复 payload 与 KV cache 前缀稳定性之间的平衡——裁剪仅作用于即将提交的 messages,不写入 session event,不改动本地深冻结的原始请求。
工作原理¶
DSH 中每次模型请求会经过 llm/stream waterfall,携带即将提交的完整 messages。插件在此拦截,按已启用规则构造新的 message 数组,再通过 ctx.llm.stream() 重新派发。原始请求不被修改。
因此:
- 本地 session log、
session/event、trajectory 与导出始终是全量历史; - 每一轮裁剪都从完整本地记录重新计算;
- 裁剪是确定性的,相同输入得到相同输出,连续两次请求的公共前缀保持字节一致,KV cache 命中率基本不受影响。
Compaction 与 session-title 类请求(带 purpose)不会被裁剪,避免其输入在提交时被悄悄改掉。
插件发出的 message 形状围绕 DeepSeek Messages 适配器的结构约束设计并做过线上校验:例如 tool-call 块不会被移除,仅将 arguments 置为 {};tool 角色消息不会被移除,仅清空 content;reasoning 块不会被移除,仅清空 text 并保留 signature。
核心功能与界面¶
控制入口在 composer 工具栏,与模型、沙箱选择器同一行。点击后打开浮动面板(随 DSH 语言设置显示中文或英文)。设置保存在本机,对所有 session 生效:
$DSH_HOME/dsh-context-saver/settings.json
面板选项(与 README 默认一致):
| 选项 | 默认 | 作用 |
|---|---|---|
| 总开关 | 开 | 关闭后 outbound 与未裁剪一致 |
| Strip thinking content | 开 | 保留 think 块结构,清空 text,模型仍收到签名 |
| Strip repeated reads | 开 | 相同文件/页面 read 只保留第一份完整内容,后续保留标识与空结构 |
| Strip terminal inputs and process | 关 | 终端工具保留输出,去掉模型传入的参数 |
| Strip the middle of the context | 关 | 开启时会警告:可能去掉长对话中间仍重要的内容 |
| Leading turns kept | 5 | 仅在中部裁剪开启时生效 |
| Trailing turns kept | 5 | 仅在中部裁剪开启时生效 |
中部裁剪规则:一轮 = 一条 user 消息及其后的模型输出,边界以 user 消息为准。总轮数 N,保留开头 H 轮、末尾 T 轮;当 N ≤ H + T 时不裁剪;否则仅落在两窗口之外的轮次被清空内容但保留结构(tool 配对、reasoning 位置与 signature 等)。配置的 0 会被抬升为 1,保证首尾至少各保留一轮。
重复 read 的占位符使用固定序数描述(如第 N 次 tool result),短于 200 字符的 read 不处理,避免标记比原文更贵。
实测效果(README 披露)¶
README 在真实 deepseek-flash 端点上给出两组测量,供评估默认配置时使用,非第三方独立审计。
本机一段 65 轮真实 session(按适配器序列化规则回放,含该 session 的 34 个 tool 声明):
| Prompt tokens | 回复 | |
|---|---|---|
| 未裁剪 | 867,787 | accepted |
| 默认裁剪 | 574,347 | accepted |
约少 33.8% prompt tokens。
60 轮合成 session(大量重复 read),比较第 N 轮与第 N+1 轮请求的前缀复用:
| 配置 | Prompt tokens | Cache hit rate |
|---|---|---|
| 裁剪关闭 | 21,102 | 98.9% |
| 默认(thinking + repeated reads) | 3,242 | 94.8% |
| 默认 + terminal | 3,242 | 94.8% |
| 默认 + terminal + middle | 1,847 | 90.1% |
默认配置在该合成场景下 prompt tokens 约为关闭时的 1/6.5,cache hit rate 94.8%;开启中部裁剪时命中率会下降,README 将其归因于任何中部裁剪方案在轮次滑出保留窗口时的固有代价。
安装与启用¶
插件为纯 JavaScript,无构建步骤、无 prepare script,从 GitHub 安装时 README 说明不需要 allowBuilds 权限。package.json 要求 DSH 版本 >=0.2.0-0 <0.3.0-0,许可证 MIT,当前包版本 0.1.0。
从 GitHub 安装:
dsh plugin add github:DaVinci-2nd/dsh-context-saver
需要可复现安装时,可固定 commit:
dsh plugin add github:DaVinci-2nd/dsh-context-saver#<sha>
也可在插件管理器中选择本地 checkout 目录,或将 install_bundle 指向该目录。安装后 bundle 中典型插入项为 id: dsh-context-saver。卸载时删除对应行或在插件管理器中卸载 bundle;settings.json 可手动删除。
典型用法¶
1、安装插件并确认 composer 工具栏出现 context saver 控件。
2、长会话中保持默认(thinking + 重复 read 裁剪)即可在 outbound 侧减 token,本地仍可在 trajectory 中查看完整 thinking 与 read 内容。
3、若终端命令参数在上下文中占比大,可在面板中打开 Strip terminal inputs and process(默认关闭)。
4、仅在明确接受「中间轮次内容不进入模型请求」的风险时,再开启中部裁剪,并按任务调整 Leading / Trailing turns kept;面板会给出英文警告文案。
5、调试对比时关闭总开关或全部子选项,请求应与未装插件时字节一致,便于确认问题是否来自裁剪逻辑。
核心裁剪逻辑在 src/trim.js(纯函数、单测覆盖),宿主拦截在 index.js。
适用场景与注意¶
适合:长时间 DSH agent 会话、频繁 read 同一文件、thinking 块随轮次累积、希望降低 prompt token 又要在本地保留完整审计轨迹的开发者。
注意:
- 插件以当前 DSH 进程的权限运行;安装前请自行查看 GitHub 源码 与 MIT 许可证,确认符合你的安全策略。
- 中部裁剪会结构性清空部分轮次内容,可能丢失对当前决策仍有用的中间信息;默认关闭是刻意设计。
- 社区目录 SkillHub 插件页 与 GitHub 仓库由社区维护,与 DeepSeek / 幻方无官方从属关系;DSH 生态强调「一切皆插件」,目录站点是独立索引,不是官方应用商店。
结尾¶
dsh-context-saver 把裁剪限制在「提交给模型的那一刻」,本地记录与导出不受影响,并在 README 中给出了 token 与 KV cache 命中率的实测表格。若你在 DSH 里做长链路 agent 开发,可以从默认配置试起,再按需打开终端或中部裁剪。