# dsh-compaction-policy [English](README.md) | 中文 **让 DeepSeek Harness 别再把对话压得太早——把触发时机交还给你。** DSH 会在对话变长时自动把较早的历史压缩成一份摘要。不少模型上,它动手的时机远早于“窗口 用掉 80%”:经常刚过半就开始,而且压完没几步又来一次。这个插件把决定权交回给你——它不改 任何配置文件,只调整正在运行的压缩引擎。 ## 你需要它吗 下面任何一条对上,基本就需要: - 你用的模型上下文窗口小于约 **33 万 token**(大多数本地模型、不少云端模型都是)。 - 上下文环看着才用了一半,DSH 就开始压缩对话。 - 压完之后,环没几步又爬回同样的位置,于是反复压缩。 如果你只用超大窗口(比如 1M),DSH 原生行为本来就接近 80%,大概不需要它。 ## 为什么会这样 每一步之前,DSH 会估算下一次请求有多大,并与下面这个触发点比较: ``` 触发点 = min(窗口 × 0.8, 窗口 − 输出预留 − 65536) ``` - **窗口**:DSH 记录的模型上下文窗口。 - **输出预留**:这次请求要求服务商为回答保留的 token 数。 - **65536**:DSH 固定留出的安全余量。 问题出在公式后半段:不管窗口多大,它都固定减掉 65536。窗口一旦小于约 33 万,这个固定值 就比 80% 更紧,于是它成了真正的触发点: | 上下文窗口 | DSH 实际触发 | 80% 应该在 | |---|---|---| | 128k | 约 62k(49%) | 102k | | 150k | 约 84k(56%) | 120k | | 256k | 约 190k(74%) | 205k | | 1M | 约 678k(68%) | 800k | 窗口再小(大约 6.5 万以内),这个固定余量会把窗口整个吃掉:DSH 干脆放弃主动压缩,只在某次 请求因为过长被拒绝之后才补救——那时丢掉的历史比计划内的压缩多得多。 ## 为什么改配置文件没用 DSH 0.2 把压缩策略放在每个 **agent preset** 里,而 preset 是按“整份定义”寻址的:无论 profile 的配置文件,还是插件自带的配置层,都改不动它里面的某一个字段。唯一的落盘办法是整份 替换 preset 内容——那会把你的 preset 钉死,之后 DSH 升级也不再生效。 所以这个插件不碰任何文件,它改的是运行时压缩引擎的行为。 ## 它做什么 - 没到**你**设的触发点:它直接回答“这次不用压”,DSH 自己的检查根本不会执行。 - 到了或超过:决定原样交回 DSH,和装插件之前完全一样。 - 请求过长后的紧急恢复、以及手动 `/compact`,都不受影响。 - 插件内部一旦出错,它会自动让路,DSH 的表现与没装插件时完全一致。 ## 适配哪些 DSH 版本 DSH 迭代很快,所以这里把支持范围写明白,而不是让人猜。 | DSH 版本 | 状态 | |---|---| | `0.2.0-rc.2` | **已验证**——本次发布就是针对它开发和测试的 | | 之后的 `0.2.x` / `0.3.x` | 预期可用。`@deepseek-ai/*` 声明的是开区间,更新的 harness 仍能安装并加载本插件;万一它依赖的某个内部接口变了,插件会停止介入,而不是把你的会话弄坏 | | 早于 `0.2.0-rc.2` | 不支持——本插件包装的是「按 agent preset 挂载」的压缩引擎,那种结构只存在于 0.2 线 | 这张表的机器可读形式,就是 `package.json` 里的 `@deepseek-ai/*` 开区间;已验证的构建记录在同文件的 `dsh.verifiedWith` 字段。 想确认它在你的构建上真的在跑: 1. **设置**里能看到 **上下文压缩策略**——客户端部分已加载。 2. 压缩发生在接近你设定的比例处,而不是半满出头——服务端部分正在介入(见[怎么确认生效](#怎么确认生效))。 如果在你的版本上它什么都不做,那是设计好的降级行为(不会崩),请带上 `dsh --version` 的输出开 issue。 _最后验证:DSH `0.2.0-rc.2`,2026-10-01。_ ## 安装 ```powershell dsh plugin --profile <你的 profile> add github:zyd232/dsh-compaction-policy ``` profile 填你实际在跑的那个:桌面端是 `desktop`,`dsh web` 是 `web`,也可以是自定义名字。 装完**必须重启 DSH**——插件行只在启动时读取,不重启等于没装。 **不需要新开会话**:已存在的会话在下一步就会被接上。 卸载: ```powershell dsh plugin --profile <你的 profile> remove dsh-compaction-policy ``` ## 设置在哪 打开**设置**,看左侧边栏:在内置分区之间会多出一项 **上下文压缩策略**(英文界面下叫 Compaction policy)。面板跟随 DSH 的语言(**设置 → 通用 → 语言**),默认英语、已含中文。 里面的值会写进 DSH 正常的设置文档,改完立即生效、不用重启;每个字段还有「恢复默认」,用来 清掉你的覆盖值。 ## 设置项 | 字段 | 默认 | 含义 | |---|---|---| | 启用 | 开 | 关掉就完全回到 DSH 原生策略。 | | 生效路由 | `*` | 对哪些路由生效:`provider` 或 `provider/model`,逗号或空格分隔;`*` = 全部路由。 | | 触发比例 | `0.8` | 上下文用到窗口的百分之多少时压缩。`0.8` = 80%,与 DSH 原生默认一致。 | | 预留输出余量(token) | `24576` | 留给模型回答的余量。DSH 原生是 `65536`;把它调小,过早压缩的问题才会消失。 | ## 怎么选值 先说通则,再举例。 - **触发比例**:没有特别理由就用 `0.8`;窗口很小、求稳的话有人用 `0.7`。 - **预留输出余量**:设成你实际会遇到的最长回答再加一点余量。`16384`–`32768` 够大多数聊天 和写代码场景;经常让模型写超长文件的可以再大些。留得太小可能导致回答没有空间、请求被拒。 - **生效路由**:只想影响部分服务商时再收窄。例如 `llama-cpp`(只管 llama.cpp 起的本地 模型)、`ollama`、`openai`,或 `ollama/*` 这种写法。 按默认的 24576 余量,窗口大于约 12.3 万时触发点就是干净的 80%,更小的窗口则按比例下移。 ## 怎么确认生效 压缩事件会记在会话日志里。想要硬数字:取每次压缩之前那次请求的大小,除以该模型的窗口,应该 落在你设的比例附近,而不是原来的 50% 上下。 直观上看,上下文环应该能越过以前开始回落的那条线继续涨。 ## 已知边界 - **只改触发点**。一次压缩保留多少历史、摘要可以多长,仍由 DSH 的压缩后端决定。 - **极小窗口无解**。如果窗口连请求本身(固定的系统提示词加工具 schema)都装不下,任何策略都 没用;DSH 后端会拒绝对这类路由做主动压缩,本插件刻意不去反复重试。 - **依赖 DSH 内部接口**。它通过 DSH 的服务 API(`agentPresets.serviceFor(…, 'compaction')`) 找到正在运行的压缩引擎,并包装它的 `compactIfNeeded`。将来 DSH 若改名或改签名,插件需要 同步更新;在那之前它只会“什么都不做”,不会乱来。 - **语言**:设置页与本文档提供中文和英文,并跟随 DSH 的语言设置(默认英语);欢迎补其他语言。 - **兼容性**:`@deepseek-ai/*` 的 peer 范围是**故意写成开区间**(`>=0.2.0-rc.2`,不设上限), 这样将来任何一次 harness 升级都不会把本插件挡在安装或加载之外。