Back to home@Aclypea

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/stream waterfall 上,所有 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 条目(和别的插件一样),或看下表:

配置项默认说明
enabledtrue总开关
checkEveryChars96每累计多少字符检测一次
minRun / minCoveredChars12 / 96循环最少重复次数 / 最少覆盖字符
maxChars16384滚动窗口上限
detectStalledActionfalse停滞动作检测(通用默认关)
vision.enabledtrueP2 局部防护开关
vision.providerPrefixes["vision-toolkit-"]命中即启用局部防护的前缀
vision.densityRatio0.5P2 的密度比,比通用值(0.58)更激进
vision.lowDiversityChars2048P2 的低多样性窗口,比通用值(3072)更小
vision.detectStalledActiontrueP2 开启停滞动作检测

使用

  • 熔断命中后: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