dsh-repetition-guard
DeepSeek Harness (DSH) 模型输出复读熔断插件 / Repetition guard plugin for DeepSeek Harness
- Stars
- 0
- Language
- JavaScript
- Created
- Aug 31, 2026
- Updated
- Aug 31, 2026
Introduction
dsh-repetition-guard
中文 | English
DSH(DeepSeek Harness)的模型输出复读熔断插件。模型流式输出陷入循环(单字刷屏、短句复读、低多样性长文本)时,在线终止流,抛结构化错误码 MODEL_REPETITION_LOOP,交给 DSH 现有的 agent/request-error → retry 流程处理,避免几万 output tokens 打水漂。
几个特点:
- 纯插件实现,不改 DSH 源码。卸载即移除,DSH 更新不丢补丁
- 挂在官方
llm/streamwaterfall 上,所有 provider 和包装路由都过它 - 对
vision-toolkit-*前缀路由启用更激进的局部防护(P2) - 自带静态加载 / 历史回放 / 误杀测试
背景
长会话、超大上下文下,上游模型会真实陷入语言循环。见过单字「课」重复几千次,也见过 执行 / send / Create 这种短句无限循环,单步浪费 10 万+ 字符、数万 output tokens。DSH 核心没有通用的在线复读熔断,只能等 max-tokens 或人工取消;流空闲超时也救不了——模型一直在吐 token,永远不算 idle。诊断细节在 docs/dsh-repetition-diagnosis.md。
两层防护:
- P1 通用熔断:包一层流的 text/reasoning delta,命中立即终止上游迭代,产出
MODEL_REPETITION_LOOP - P2 Vision Toolkit 局部防护:
vision-toolkit-*这类图片输入包装路由复读概率高,命中前缀时换成更积极的检测参数,熔断更早
隐私声明见 PRIVACY.md:本仓库是公开的,已移除所有真实会话、个人信息和机器路径,测试样本是匿名合成数据。
检测模式
核心在 lib/repetition-guard.js,零依赖、纯 ESM,node / 浏览器都能跑。5 种模式:
exact-suffix-loop:精确后缀循环,短窗口逐周期重复token-density:短 token 在窗口里占比异常,单字/短词刷屏repeated-lines:同一行/句反复出现stalled-action:一直在输出动作标记但没有新信息(默认关,P2 对 vision 路由开)low-diversity:N-gram shingle 多样性过低,长文本复读
防误杀方面:只看 text/reasoning delta,不碰工具参数流;滚动窗口有界(默认 16 KiB);阈值保守,代码、表格、PPT/XML 结构、长文、引用列表都不触发(见 test/misdetect.test.mjs)。
安装
本地安装(推荐)
# 在仓库根目录执行
powershell -ExecutionPolicy Bypass -File scripts/install-local.ps1
脚本做的事:把插件复制到 ~/.dsh/dsh-repetition-guard → 在 profile 的 node_modules 建 Junction → 改 profiles/desktop/package.json(dependencies 加 link: 依赖、bundles 加条目,改前自动备份)。之后重启 DSH 生效。
卸载:
powershell -ExecutionPolicy Bypass -File scripts/install-local.ps1 -Uninstall
手动注册
改 ~/.dsh/profiles/desktop/package.json:
"dependencies": {
"dsh-repetition-guard": "link:C:/Users/<用户名>/.dsh/dsh-repetition-guard"
},
"dsh": {
"profile": {
"bundles": [ "...", "dsh-repetition-guard" ]
}
}
再把插件目录放到 ~/.dsh/dsh-repetition-guard,profile 的 node_modules 下建 Junction 指向它。
配置
默认配置直接能用。想调的话,在 profile 的 cordis.patch.yml 里覆盖 repetition-guard 条目(和别的插件一样),或看下表:
| 配置项 | 默认 | 说明 |
|---|---|---|
enabled | true | 总开关 |
checkEveryChars | 96 | 每累计多少字符检测一次 |
minRun / minCoveredChars | 12 / 96 | 循环最少重复次数 / 最少覆盖字符 |
maxChars | 16384 | 滚动窗口上限 |
detectStalledAction | false | 停滞动作检测(通用默认关) |
vision.enabled | true | P2 局部防护开关 |
vision.providerPrefixes | ["vision-toolkit-"] | 命中即启用局部防护的前缀 |
vision.densityRatio | 0.5 | P2 的密度比,比通用值(0.58)更激进 |
vision.lowDiversityChars | 2048 | P2 的低多样性窗口,比通用值(3072)更小 |
vision.detectStalledAction | true | P2 开启停滞动作检测 |
使用
- 熔断命中后:DSH 显示结构化错误(模式、重复次数、覆盖字符数),重试策略决定 retry / 切模型 / 终止,retry 会清掉旧草稿
设置 → 复读熔断页面能看到累计统计(请求总数、熔断次数、按 provider 分布)- 只读接口
GET /api/repetition-guard/stats,插件卸载即消失
测试
# 静态加载 + 单元 + 误杀测试,纯 node 即可,不需要 DSH
node test/static-load.test.mjs
node test/misdetect.test.mjs
# 历史回放:把 DSH 会话存档(.jsonl.zstd)按步喂给 guard,看哪些步骤会熔断
# 需要 node 22+(node:zlib 原生 zstd)
node test/replay.test.mjs
目录结构
dsh-repetition-guard/
├── lib/
│ ├── index.js # 插件入口(llm/stream 挂载 + 统计 API)
│ ├── repetition-guard.js # P1 核心算法(零依赖 ESM)
│ └── vision-guard.js # P2 局部防护参数解析
├── client/index.js # 前端设置页(熔断统计)
├── test/ # 静态加载 / 回放 / 误杀测试
├── docs/dsh-repetition-diagnosis.md # 诊断报告(P0/P1/P2/P3)
├── examples/dsh-anomaly-samples.txt # 匿名测试样本
└── scripts/
└── install-local.ps1 # 本地安装/卸载
License
MIT