Saltar al contenido principal
T

dsh-live-compact

tranquillitatis-lab/dsh-live-compact

Live Compact. Comprime el turno terminado en su lugar y conserva la caché de prefijo.

Instalar

dsh plugin --profile web add github:tranquillitatis-lab/dsh-live-compact

README

边做边压 Live Compact

Live Compact 就是边做边压。活着的时候就压,不等窗口堆满。

DSH 把压缩写死在大约 80%。不到这条线,上下文一直堆。到了才调一次模型,十几秒,还要计费。压完注意力会飘。更麻烦的是,压完没多久又满了。1M 的窗口根本不够用,再压一次更慢。

为什么非要等到 80%?边做边压不行吗?

云端和端侧

云端(公网地址,如 DeepSeek、GLM):装上即可。不要设置 SPINE_THUNDER。看题对不对,以及缓存命中。切点前面的原文不动。

端侧(本机、内网、27B):也可以装。不要设置 SPINE_THUNDER。不要拿云端缓存命中来要求它。看题对不对,以及切掉多少 token。本地服务没有云端那种前缀缓存,每次提问都会把当前上下文重新预填充。两万多是当前上下文的大小,不是插件没切。

SPINE_THUNDER 默认关闭。只有设为 1 才走雷霆。再设 SPINE_THUNDER_MODEL=27b 时,前缀超过 8 万会每次都少发,一次雷霆变成次次雷霆。端侧不要开。

超过 2 万 token 就切一刀。切的是刚结束的这一轮,不调用模型。切点前面的原文不动,缓存命中还是原来的水准。上下文因此一直被按在较低的位置。雷霆大压缩能拖就拖,拖到尽可能后面。就算哪天满了、真的触发了,掉下来之后小切还在,不会很快又堆回去。

headless:

dsh plugin --profile headless add dsh-live-compact@1.1.1

网页和桌面端(共用 web profile,装一次两边都生效):

dsh plugin --profile web add dsh-live-compact@1.1.1

想先装到本机看版本:

npm install -g dsh-live-compact
dsh-live-compact --version

1.1.1

  1. Windows 上取 SID 和写权限不再走 PATH。固定调用 %SystemRoot%\System32 下的 whoami.exe 和 icacls.exe。环境变量不是盘符绝对路径时,这次备份直接跳过,不退回裸命令名。
  2. 不再使用需要还原特权的 icacls /restore。目录用 /inheritance:r /grant:r,给当前用户、SYSTEM、Administrators 三条可继承的完全控制。文件只用 F,不带 (OI)(CI)。已收紧目录里的文件不再逐条跑 icacls。当前用户 SID 和目录权限每个进程只做一次。
  3. 权限失败不再把宿主打退出。这次备份不落盘,不退回 chmod,只提示一次。压缩照常进行。
  4. 进程重启后补抓工具结果,只补最近 3 轮。已经记下的位置还在,就从那里接着记。记下的位置比当前日志还大,按重启口径补最近 3 轮,不从 0 把整份日志再扫一遍。
  5. 一轮里有不少于 1000 token 的 read,这一刀只切这一轮,不把要留的后 3 轮短结果一起卷进去。这一轮里单个工具结果达到 3.2 万,只留指针。这一轮切不下来,才按原来的规则切更早的轮。
  6. 65 万、4.8 万、3.2 万、CHUNK_MIN 1000、云端默认 0.8 / 65536 / 8192、SPINE_THUNDER 默认关闭,都没改。没有加「省下的必须盖过重写」这种新门槛。备份目录快满时仍是先扫再判断,这版没改,留到 1.1.2。

1.1.0

  1. Issue #19 里下一轮输入回到 21 万到 24 万、前缀被打掉的那一刀,是切点走到了已有卡片左边。1.1.0 把最新一张卡片当成地板。往左走到卡片就停。切点右边还有更新的卡片,这一刀不切。已进缓存的前缀不再被后面的刀改写。
  2. 同一次收尾可以连切,这是现有设计,没有改。改的是记账。以前每一刀都把尾巴算进重写,四刀就把同一段尾巴乘了四次。现在一次收尾只记一次:第一刀之后的前缀,减去后面几刀省下的。dsh-live-compact stats 的 rewrite 用这个数。逐刀明细在 shadow 目录的 spine-cuts.jsonl,只有序号、token 和切点,没有消息原文。
  3. 没有加「省下的必须盖过重写」这种新门槛。加了会把同一次收尾里后面的刀切掉。65 万停切线、收尾停在 3.2 万、CHUNK_MIN 默认 1000、云端默认 0.8 / 65536 / 8192,都没改。SPINE_THUNDER 仍是默认关闭。
  4. 今天桌面端长时间卡住,是每回合、每个工具结果都在拷贝整份会话日志,并反复计量。1.1.0 一个空闲回合只拷贝一次日志。工具结果到达时用已经记下的调用编号,不再为了查一次调用而拷贝整份日志。收尾循环复用这一次的任务和调用表。token 计量是开头一次,每真正切下一刀再测一次。没切的回合只测一次。切哪一段没改。

门禁和复测

npm run test:gate 已过。Windows 取权限、宿主不退出、重启只补最近 3 轮、长 read 只切自己那一轮,都在这道门禁里。65 万、3.2 万、CHUNK_MIN 1000、云端默认值没改。

这轮连的是插件版。10 组同一套 31 轮填日志,组内串行,两个模型同时开。原版 DSH 压缩对比留到 1.1.2。Coder 390 27B 这轮没跑,后补。测评图在下面,也在 v1.1.1。

云端看题对不对,以及每轮第一个 step_end 的缓存命中。这个命中是这些首步的 cacheRead / (cacheRead + input) 加总。切掉的 token 是 spine-cuts.jsonl 里 saved 的合计。含切刀的轮是这些轮的墙钟合计,刀本身是毫秒。任务墙钟从第 1 轮文件生成算到第 31 轮写完。结束上下文是最后一轮的 totalTokens,已经包含前面各轮,不是每轮增量。

DS V4.1 Flash,10 组,填日志 230/230,跳过 0。首步缓存 98.64%。切掉 65180。10 组墙钟合计 36 分 18 秒。多数组结束在 3.5 万到 4.6 万。第 1 组 read 全文 25 次,正文留在上下文里,四刀只省 21493,结束 282871。第 2 组几乎只用 bash,只 read 一次,没切,结束 37781。

GLM 5.3 Flash,同一插件、同一套题。第 1、2、3、4、8、9、10 组填日志 23/23。第 5、6 组全程连接失败,不计入。第 7 组前段连接失败,填日志 14/23,不算通过。不要写成 230/230。有用量的轮首步缓存 98.97%。第 1、2 组主要是 grep,没切,结束 39511 和 29987。插件没有把 GLM 切得更多。第 4、9 组也反复 read 全文,结束 285535 和 281515,和第 1 组 DS 是同一种形状。可比的 7 组里,DS 每组都更快。

插件版对比

DS V4.1 Flash

GLM 5.3 Flash

1.0.9

  1. 云端和本地按当前配置里这一家的地址区分。请求头通常只有 provider 名。配置里的 baseURL 优先,没有再看官方 DeepSeek 和内置目录。公网地址按云端切,回环和内网按本地。读不到地址仍按本地。SPINE_ENGINE=local 或 cloud 可以强制指定。这不改官方大门的 headroom。
  2. 官方大压缩的三项可以在启动前用环境变量覆盖:SPINE_THRESHOLD_RATIO、SPINE_HEADROOM_TOKENS、SPINE_RETAIN_TOKENS。云端默认仍是 0.8、65536、8192,不按地址改小。TUI 的 /settings 没有这一项。要改当前配置,直接改 cordis.patch.yml 里的对应字段。
  3. 发版门禁是 npm run test:gate,不连模型。8 组 31 轮在 test/live-fill,要连模型。这两部分都在 GitHub 测试集里。
  4. 测评分两个口径。云端看题对不对,以及每轮第一个 step_end 的缓存命中。本地看题对不对和切掉的 token。DS V4.1 Flash,8 组,184/184,跳过 0,缓存 98.22%,题末最高 35334,切掉 97306,估算费用 $0.208。GLM 5.3 Flash,同一套 8 组,184/184,同一公式缓存 74.66%。Coder 390 27B,3 组 31 轮,填日志 69/69,切掉 20635。费用是离峰用量估算,不是账单。
  5. 安装用 npm 的 dsh-live-compact@1.0.9。上不了 npm 时用镜像包 https://download.merkyorlynn.com/downloads/plugins/dsh-live-compact-1.0.9.tgz 。页面在 https://download.merkyorlynn.com/live-compact.html 。测评图在当时的 v1.0.9。

边做边压

为什么非要等到 80%

两场测评

两场不混在一张表里。150 道是编程短题,串在同一次对话里。20 题是 WebUniverse 长链路。

150 题和 20 题

适用范围与不足

短题 150 道,Aider polyglot-benchmark 7e0611e。Python、Go、JavaScript、Rust、Java 各 30 题,没有 C++,按字母序穿插。从 python-affine-cipher、go-alphametics、javascript-affine-cipher、rust-accumulate、java-affine-cipher 往下走。

原版Live Compact
通过150/150150/150
全程命中率99.55%99.56%
缓存命中335.0M244.3M
缓存未命中1.498M1.088M
费用$1.50$1.15,预热 0
上下文峰值679K589K
压缩1 次,12.8 秒145 刀,2.2 秒
墙钟8,531 秒6,105 秒

便宜约 23%。145 刀切掉约 474K token。峰值 589,414,结束 589,554,没到 65 万。墙钟 6,105 秒这轮只跑了插件一边,快出来的时间不能全算在插件上。

上面两场是 1.0.2 之前测的。1.0.2 没有重跑 150 题,也没有在真实超过 2 万 token 的会话里切过一刀。

失忆对比

1.0.5 对过一次失忆。同一会话、同样任务,真实 DeepSeek。先埋 13 条约束和 1 条报错,再灌 6 轮日志,然后不许读文件,凭记忆答题。每组 2 次,只说明方向。

原版Live Compact
15 道回忆题15/15,15/1515/15,15/15
违反约束1 次轻微,00,0
日志中段 3 个细节1/3;另一次 3/3,靠解压会话日志,多 10 次工具3/3,3/3,查自己的备份
每次请求上下文约 15K约 29K

用户说过的约束两边都没忘。差别在工具输出里的细节。总花费在同一个量级。原版这次把摘要阈值调低,保证回忆前做过摘要。

长链路 20 题是另一场。原版第 15 题才做模型摘要,14.552 秒,切掉 520,460。压完上下文掉到 15.5 万,结束时又回到 433,844。插件 20 刀,74 毫秒,切掉 486,193。题末平均上下文 217,276,比原版 366,942 低 40.8%。结束上下文 323,726,比原版低 25.4%。题末采样命中率原版 99.87%,插件 99.90%。第 20 题那一跳原版 99.84%,插件 99.95%。采样命中率按每题末次请求的 token 加权,平均上下文取 20 个题末快照。

长填日志

1.0.6 跑了 8 组。每组 31 轮,其中 23 轮读一份 520 行日志,报告 WARN 条数和 NOTICE 原文。没有 NOTICE 就写 NONE。真实 DeepSeek。

长填日志

结果
填日志回合184
跳过工具直接报数字0
WARN184/184
NOTICE184/184
假 NOTICE0
切过的会话8/8,共 17 刀

8 组都切过,不是没压缩才碰巧对。这次提示没有「没有工具结果就不要给数字」。和早先一次 54/184 跳过工具的记录不是同一份日志重放。65 万停切线这版没动。

同一套题又跑了原版官方压缩。分数一样,费用一样,上下文更低。跳过工具两边都是 0,WARN 和 NOTICE 都是 184/184。费用按离峰用量估算,插件 $0.211,原版 $0.229,不是账单。题末上下文插件平均 2.6 万、最高 3.5 万;原版平均 4.4 万、最高 12.6 万。插件 8 组都在 3.5 万以内,原版有两组到了 8.0 万和 12.6 万。

原版对比

cordis.patch.yml 是静态整块替换,不读这三个环境变量。要在这里改 headroomTokens,需直接改配置块,例如:

- id: compaction-spine
  name: dsh-live-compact
  config:
    auto: true
    thresholdRatio: 0.8
    headroomTokens: 16384
    retainTokens: 8192
    compactionRetries: 0

1.0.8

同一套 8 组、184 个填日志回合。真实 DeepSeek。跳过工具 0,WARN 184/184,NOTICE 184/184。缓存命中 98.23%,1.0.6 是 97.88%,原版是 98.51%。题末平均 2.6 万,最高 3.6 万,最低 1.6 万。1.0.6 最高 3.5 万。原版最高 12.6 万。费用按离峰用量估算,1.0.8 是 $0.209,1.0.6 是 $0.211,原版是 $0.229,不是账单。切掉的原文 11.4 万 token。原版没有压缩,8 组题末加起来积累了 34.9 万。

1.0.8 和 1.0.6、原版

卡片不再使用官方的 <compacted-summary> 和 compact-checkpoint。官方压缩会把那种节点当成上一版摘要再摘一次,切片摘要会越压越短。新卡片用 spine-checkpoint。已经写过的旧卡片仍会停住,不会再切一遍。

遇到已有卡片就停止往前扩。这是故意的。卡片已经换过一次,再穿过去会改掉已经进缓存的前缀。最新一段不够 1000,就跳过,不回头凑。

单个工具结果超过 3.2 万 token 才只留指针。默认不改。要自己调,启动前设 SPINE_POINTER_TOKENS,例如 8000。不按占比算。

1.0.7 长填日志

1.0.7 跑了同一套 8 组。真实 DeepSeek。184 个填日志回合都调用了工具。WARN 183/184,NOTICE 184/184,假 NOTICE 是 0。8 组都切过,一共 43 刀。卡片 43 张都有会话序号,没有备份路径。

差的 1 题是第 7 组第 4 轮。文件读了,模型把 NOTICE 那一行也算进 WARN,报了 8,日志里是 7。

1.0.7 长填日志

和已发布的 1.0.6、以及上次同一套题的官方压缩比。跳过工具都是 0。费用按离峰用量估算,1.0.7 是 $0.249,1.0.6 是 $0.211,原版是 $0.229,不是账单。缓存命中 1.0.7 是 96.10%,1.0.6 是 97.88%,原版是 98.51%。题末上下文 1.0.7 平均 2.3 万、最高 3.1 万、最低 1.9 万,8 组都在 3.2 万以内。1.0.6 平均 2.6 万、最高 3.5 万。原版平均 4.4 万、最高 12.6 万,有两组到了 8.0 万和 12.6 万。切掉的原文,1.0.7 是 21.5 万 token,1.0.6 是 9.0 万。原版这一轮没有压缩,8 组题末上下文加起来积累了 34.9 万,最高一组 12.6 万。65 万停切线没动。

和 1.0.6 比

1.0.7 改了什么

1.0.7 安装地址是新的。1.0.2 到 1.0.6 的旧包还在原来的链接上。

  • 云端和本地分开切。官方 DeepSeek 按公网地址切。服务商名含 strata,或地址是本机、私网、读不到,按本地切,不越过最后一条用户消息。
  • 最后一条用户消息不进切段。较早的用户原文写成单行 JSON,留在卡片里。
  • 卡片指针是会话日志的事件号,不写备份文件路径。最近 3 个已结束的工具轮仍留原文。
  • 单个超过 3.2 万 token 的工具结果只留序号指针,并连同对应调用一起换掉。
  • 备份默认上限 256MB。快满时仍删最老的。SPINE_SHADOW_MAX_BYTES 和 SPINE_SHADOW_MAX_MB 还能改。
  • 切完可看累计:dsh-live-compact stats。估算按未命中输入 $0.15/M,不扣重写成本。
  • 当前会话备份可以另查:import { searchShadow } from "dsh-live-compact/shadow-search"。插件自己不会去搜。
  • 65 万停切线没改。

1.0.6 改了什么

1.0.6 安装地址是新的。1.0.2、1.0.3、1.0.4、1.0.5 的旧包还在原来的链接上。

  • 配置报错不再被盖成「服务已被注册」。装不上时能看见原来的原因。
  • 备份按会话分目录。卡片只指向这一份文件所在的目录。
  • 报错优先进卡片。最近 3 个已经结束的工具轮留在原来的调用和结果里,结果不截短。更早的轮才收成卡片。
  • 助手说的「已提交 / 已发布」不进硬行。卡片只记有调用编号的工具事件,不靠词表。
  • 后台任务照常切。没结束的登记在卡片上,之后的文件以磁盘为准。失败的 kill 不会被记成已结束。
  • 工具原文在官方修剪前按调用编号落盘。卡片给路径、哈希和字节数。写失败就写无完整备份,不留悬空路径。
  • 65 万停切线没改。窗口更大时,过了 65 万仍会停掉小切。

1.0.5 改了什么

1.0.5 安装地址是新的。1.0.2、1.0.3、1.0.4 的旧包还在原来的链接上。修的是 1.0.4 实测里的五处:

  • 预设不再硬等 gate。gate 加载失败时,网页预设不会卡在等待。换包前先试加载,失败就保留原版名字。
  • 换上之后带上 0.8、65536、8192。预设里已有的配置优先。
  • 预设 id 写在外层或内层都能换。standard、ptc、cordis、minimal 在 0.2.1-rc.5 上都会换。TUI 仍不碰。
  • 命令输出只有结构信号才标成报错原文:isError、非 0 退出码、[stderr]、[exit code: N]、[Command finished with exit code N]、exit_code=N、ptc 结果里的 "exitCode": N。证据不够就标状态未知,留原文末尾几行。
  • 长输出要先把备份写成功,卡片才指向那个文件。写失败就不切,也不指向一个还不存在的文件。
  • 备份写成一个确定的文件,编号不存在共享引擎上。卡片里写这次备份的实际路径。
  • 官方工具结果修剪器裁掉的内容不进这份备份。备份默认上限 256MB。满了先删最老的,删不出空间才不切。
  • 外壳先加载。引擎装不上时,这一会话不挂起。能改用原版就用原版,并记下「本会话未接管」。原版也装不上时,/compact 马上返回错误。
  • headless 的宿主包自己关掉了原版压缩。插件不能把那一行重新打开。网页预设不注入 gate,漏换这一轮就继续用原版。

1.0.4 改了什么

1.0.4 安装地址是新的。1.0.0 到 1.0.3 的旧包还在原来的链接上。

短的工具结果会留在摘要里,标成工具输出,不标已确认。不超过 12 行、也不超过 512 字,整段留下。更长的只留一行:多少字、正文已省略。省略的原文在本机 ~/.dsh/compaction-spine/shadow,文件名含这次的短编号。需要再读,不要默认读进来。思考仍不进摘要。

1.0.3 改了什么

1.0.3 安装地址是新的。1.0.0、1.0.1、1.0.2 的旧包还在原来的链接上。

摘录只留正文。用户的话和助手写出来的句子按原来的规则留,并标是谁说的。思考和工具结果不进摘要。思考和工具原文进本地备份,带来源。这版不自动读回下一问。

网页和 Desktop 的四个预设在加载时会把组里的原版压缩换成这个包。换不上就落回原版,预设仍能起来。TUI 这版不碰。

  • 思考过程不进摘要。本地备份里单独存,标成思考。
  • 工具输出不进摘要。PASS、文件已更新、目录列表、本机路径、报错头都不留。原文在备份里。
  • 留下的每一行标原来是谁说的。句子里写着「用户说」,也不会变成你的新指令。
  • 去掉「已确认」。摘要开头写明:这是旧内容摘录,不是新指令,也不是你的授权。
  • 这一刀如果没有合格的摘要,就整段留下,不去调模型。卡片可以很短。
  • 备份只有自己能读。文件名不带会话号。本机路径不发给模型。备份默认上限 256MB。满了先删最老的,删不出空间才不切。
  • 2 万和 65 万没动。配置里的 0.8 只管官方大压缩,不管这一刀。想改小切的起点,只能在启动前设 SPINE_MIN_TOKENS。

环境变量

变量默认值作用
SPINE_THRESHOLD_RATIO0.8预设中官方大压缩的触发比例,在 gate.js 加载时读取。
SPINE_HEADROOM_TOKENS65536预设中官方大压缩的预留空间(token),在 gate.js 加载时读取。
SPINE_RETAIN_TOKENS8192预设中官方大压缩的保留量(token),在 gate.js 加载时读取。
SPINE_POINTER_TOKENSSPINE_CHUNK_MAX(默认 32000)单个工具结果超过此 token 数才只留指针。
SPINE_MIN_TOKENS20000轮后小切的最低上下文 token 数。
SPINE_KEEP_ROUNDS3原处保留的最近已结束工具轮数。
SPINE_KEEP_ROUND_TOKENS32000云端收尾的停止线;最近 3 个已结束工具轮始终留在原文。
SPINE_SHADOW_DIR~/.dsh/compaction-spine/shadow备份目录;设了 DSH_HOME 时以它替代 ~/.dsh。
SPINE_SHADOW_MAX_BYTES268435456正数直接作为备份字节上限,优先于 SPINE_SHADOW_MAX_MB。
SPINE_SHADOW_MAX_MB256未设置正数字节上限时,按 MB 设置备份上限。
SPINE_ENGINE自动识别设为 cloud 或 local 可强制切法,其他值忽略。
SPINE_THUNDER关闭设为 1 才走雷霆。端侧不要开。
SPINE_THUNDER_MODELflash设为 27b 且前缀超过 8 万时,每次官方压缩都少发。端侧不要设。
SPINE_ENGINE_FAIL无仅供测试:用 import、construct、after-super 注入引擎故障。
SPINE_STOCK_FAIL无仅供测试:设为 1 时禁止回退原版引擎。
SPINE_CHUNK_MIN1000一刀至少包含的 token 数。
SPINE_CHUNK_MAX32000(RAIL_TOKENS)一刀最多包含的 token 数,也是指针阈值的默认值。
SPINE_COOLDOWN_MS0官方压缩后的额外时间窗口;仅正数开启,未设置、空串、非数字、0 或负数均关闭。

每个新的 compact-checkpoint 只让轮后小切跳过一次,spine-checkpoint 不触发这个跳过。

gate.js 的官方压缩预设默认使用 thresholdRatio: 0.8、headroomTokens: 65536、retainTokens: 8192,可在启动前用对应环境变量覆盖。这些数值只管官方大压缩,不改小切切点。

安装

从 npm 装。headless 和网页是两个 profile,要各装一次。桌面端是另一个 profile,普通 dsh plugin --profile desktop 会被拒绝。

dsh plugin --profile headless add dsh-live-compact@1.1.1
dsh plugin --profile web add dsh-live-compact@1.1.1

想先装到本机看版本:

npm install -g dsh-live-compact
dsh-live-compact --version

备用:上不了 npm 的,用国内镜像站的包。1.0.2 到 1.1.0 的旧链接仍在。

dsh plugin --profile headless add https://download.merkyorlynn.com/downloads/plugins/dsh-live-compact-1.1.1.tgz
dsh plugin --profile web add https://download.merkyorlynn.com/downloads/plugins/dsh-live-compact-1.1.1.tgz
npm install -g --force "https://download.merkyorlynn.com/downloads/plugins/dsh-live-compact-1.1.1.tgz"
dsh-live-compact --version

需要 DSH >=0.2.0-rc.2 <0.3.0。装上后跑长任务,日志里出现 spine cut …ms 才算这刀生效。页面:https://download.merkyorlynn.com/live-compact.html

DSH-TUI 同样换不掉预设里的原版压缩,先不要装。

被切掉的原文会写到 ~/.dsh/compaction-spine/shadow,只有自己能读。上限 256MB。快满时删最老的备份。卡片里的序号是会话日志的事件号。要在当前会话的备份里找一行,用 import { searchShadow } from "dsh-live-compact/shadow-search"。

dsh-live-compact stats 的 saved 是切完当下少掉的 token,rewrite 是同一次收尾实际要重写的尾巴,只记一次。同一步连切不会按刀数把尾巴乘上去。这两个数口径不同,比值不是盈亏。桌面端没有终端,rg "spine cut" 只在终端输出里找得到。逐刀明细在 shadow 目录的 spine-cuts.jsonl。

改上限:

export SPINE_SHADOW_MAX_BYTES=67108864

想自己清:

rm -f ~/.dsh/compaction-spine/shadow/*/*.txt ~/.dsh/compaction-spine/shadow/*.txt

设了 DSH_HOME 或 SPINE_SHADOW_DIR 时,目录在那边。删不掉旧文件时,这一刀不切,同一次会话只警告一次。

MIT,见 LICENSE。

Plugins relacionados