🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

输出循环看门狗 ADistanceThereIs/dsh-output-loop-guard

DeepSeek Harness
ADistanceThereIs15 天前有提交已提供中文文档扫描:未发现敏感能力

检测模型流式输出自我重复,自动中止失控轮次并唤醒继续

29.9/100
综合分
0
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/10/17 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add ADistanceThereIs/dsh-output-loop-guard
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:待复验
是什么
dsh 原生插件 · security
装得上吗
曾在 dsh 0.2.0-rc.2 下真实安装成功,但当前 dsh 已更新至 0.2.1-rc.5,本站尚未在新版下复验
L4 · 真实安装等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 15 天前
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码
v2.7.0
🟢 扫描:未发现敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描未发现敏感能力:最多只发网络请求、读取自身元数据或只读文件,未发现执行命令、文件写入或敏感信息读取。

扫描于 2026/10/31(1 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

依赖的 DSH / Cordis 模块
@deepseek-ai/dsh-llm
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

DSH 防止流式模型输出自我重复:检测推理或可见文本中的退化循环,中止失控轮次并唤醒智能体,附上纠正提示。

README

由 DeepSeek 最新模型翻译生成
dsh-output-loop-guard DSH 的输出自我重复看门狗:模型流式输出出现退化循环时中止该轮,并唤醒 agent 带着纠正提示继续任务——不需要人按停止键,也不需要人再打一句"继续"。 - 适用于 DSH >= 0.2.0-rc.2,ESM,零运行时依赖。 - 21 项自包含回归测试(npm test)。 - 在 27 个真实会话 / 1,783 个 assistant 步骤上标定:24 次触发,0 次假阳性。 它补的是哪个洞 框架自带的 @deepseek-ai/dsh-repeat-tool-reminder 只能看见重复的工具调用(同一工具、同一参数连续 3/5/8 次)。发生在推理通道里的退化循环它结构上看不到。在促成这个插件的那次会话里: - 模型在推理通道里反复吐 好。→(执行)→好。→Write.→…
展开完整文档(README 剩余 1 节)
dsh-output-loop-guard

DSH 的输出自我重复看门狗:模型流式输出出现退化循环时中止该轮,并唤醒 agent 带着纠正提示继续任务——不需要人按停止键,也不需要人再打一句"继续"。

- 适用于 DSH >= 0.2.0-rc.2,ESM,零运行时依赖。
- 21 项自包含回归测试(npm test)。
- 在 27 个真实会话 / 1,783 个 assistant 步骤上标定:24 次触发,0 次假阳性。

它补的是哪个洞

框架自带的 @deepseek-ai/dsh-repeat-tool-reminder 只能看见重复的工具调用(同一工具、同一参数连续 3/5/8 次)。发生在推理通道里的退化循环它结构上看不到。在促成这个插件的那次会话里:

- 模型在推理通道里反复吐 好。→(执行)→好。→Write.→… 达 112,109 字符,以 50,196 个流式块、126 秒连续解码产出,工具调用数为 0 —— repeat-tool-reminder 不可能触发;
- 自动压缩也没能兜住:其触发阈值是 floor(min(W × 0.8, W − O − B)),对 1M 窗口 + 256k 输出上限约为 678k token,而该会话峰值约 508k token;
- 循环最终靠用户手动停止结束,而退化文本留在会话里,反而让后续更容易复发(自我模仿)。

output-loop-guard 挂在实时流事件 agent/assistant-stream 上,直接看文本本身。

工作方式

对每一段流式输出维护滑动窗口(默认 1200 字符,每新增 64 字符检查一次),四个信号:

| 信号 | 判据 | 抓什么 |
| repeated-block | 最短周期块(≥2 个换行、≥2 个不同非空白字符)连续重复 ≥6 次 | 多行周期循环,如周期 106 字符的 好。→(执行)→Write. 循环 |
| dominant-gram | 某个 n-gram 覆盖窗口 ≥55% 且出现 ≥24 次,且跨 ≥2 行 | 尾部不整齐、但重复已主导窗口的循环 |
| repeated-line | 单行重复:推理通道 ≥40 次,可见正文 ≥60 次(singleLineTextMinRepeats,设 0 可关) | 推理里的单行空转、正文里失控的整行复制 |
| flat-tic | 无空白短 gram 覆盖窗口 ≥25% 且出现 ≥48 次,仅推理通道 | 没有换行的纯口癖(好。好。好。…) |

两条设计约束保证精度:

- 只用最短周期判定。 同一行重复时,行长的 2×、3× 也是"周期";标定中按任意周期看,会把正常 bullet 列表误判成多行循环。因此只看最短周期,并要求该周期块本身跨 ≥2 个换行。
- 通道感知。 可见正文里重复整行通常是合法内容(生成的夹具、配置文件、列表),所以正文单行门槛(60)高于推理通道(40);无换行的纯口癖只在推理通道判定。缩进、==== / ---- 分隔线、连续空行永不触发。

触发后:

1. agent.cancel({ kind: 'hook', reason: 'output-loop-guard: …' }) —— 中止正在跑的生成(记录为 interrupted,退化文本不再增长);
2. agent.steer(<notice>) —— 信号已被 abort,steer 会升级为新一轮并唤醒 driver,agent 立即带纠正提示继续(提示明确要求停止复述、直接产出动作或结束);
3. 同一轮内触发超过 maxTripsPerTurn 次后不再自动继续,只 inject 提示并停下。

安装

本包是 DSH 的组合包(bundle):加载器只读 package.json 里的 dsh.bundle.patch (dsh.plugin.json 是可选元数据,供部分本地插件索引使用,官方运行时不读取它),由 cordis.patch.yml 插入 output-loop-guard 行。

A. 从 git 托管安装并固定 commit(需要 DSH 进程的 PATH 里有 git)
dsh plugin --profile <profile> add "github:ADistanceThereIs/dsh-output-loop-guard#<commit>"

B. 从 Release tarball 安装 —— 不需要 git 先从 Releases 页下载 dsh-output-loop-guard-0.1.0.tgz,然后:
dsh plugin --profile <profile> add ./dsh-output-loop-guard-0.1.0.tgz

C. 直接用 Release 资产 URL(需要 Node 信任系统 CA 库)
dsh plugin --profile <profile> add \
https://github.com/ADistanceThereIs/dsh-output-loop-guard/releases/download/v0.1.0/dsh-output-loop-guard-0.1.0.tgz

三种方式都会把包追加进 dsh.profile.bundles 并合成 bundle 的 patch 层。重启 DSH 后该行才会激活。

卸载:

dsh plugin --profile <profile> remove dsh-output-loop-guard

配置

在 profile 的 cordis.patch.yml 里覆盖该行(patch 会替换整行的 config,要保留的键都要重述):

- id: output-loop-guard
name: dsh-output-loop-guard
config:
dryRun: false # true = 只检测记录,绝不中止 autoContinue: true # 中止后唤醒 agent 并给出纠正提示 maxTripsPerTurn: 2 # 每轮自动继续预算 windowChars: 1200 checkEveryChars: 64 minPeriodRepeats: 6 # 多行周期重复次数门槛 singleLineMinRepeats: 40 # 推理通道单行门槛 singleLineTextMinRepeats: 60 # 正文通道单行门槛(0 = 关闭) useDominantGram: true dominantGramCoverage: 0.55 dominantGramMinCount: 24 useFlatTic: true ticMinCount: 48 ticMinCoverage: 0.25 verbose: false

想先观察自己会话里的触发情况,可先用 dryRun: true。

实测证据

语料回放

在 27 个真实会话 / 1,783 个 assistant 步骤上回放(语料同时含健康文本与退化文本):

- 24 次触发,0 次假阳性;
- 覆盖促成该插件的会话的全部循环步骤,并跨会话命中另一个工作区里同类的 (好。) 循环;
- 检出延迟:112,109 字符的失控在 2,944 字符(2.6%)处被抓住;其余循环在 1,152–7,808 字符内抓住——从 20–126 秒的空转变成数百毫秒结束。

真实运行时验证

在活的 DSH 运行时里跑一条"把两行重复输出 300 遍"的诱导任务,会话日志包含:

{"type":"turn/end","data":{"turn":1,"reason":{"kind":"aborted","reason":{"kind":"hook","reason":"output-loop-guard: repeated output (repeated-block)"}}}}
{"type":"assistant/message","interrupted":true} // 只输出 9 遍即被切断,而非 300 遍
{"type":"user/message","source":{"kind":"output-loop-guard","form":"notice"}}

随后 agent 把同样的内容改为写文件交付,而不是继续复述——这正是预期行为:护栏掐掉失控输出,而不是让任务失败。

回归测试

npm test 跑 21 项自包含检查(不需要语料):真实退化必须被中止(24,180 字符的流在 576 字符处抓住)、健康长文档不受影响、真实形态的正文(列表/代码块/表格/分隔线/夹具)不得触发、失控的正文整行必须触发、dryRun 不得中止、禁用后不得注册监听、agent 句柄抛异常不得污染流。

已知边界

- 正文里的单行重复需 ≥60 个连续相同行才触发(保护合法夹具与列表);singleLineTextMinRepeats: 0 可关闭。
- 只做结构化判定(周期与密度),不做语义判断:改动过的近似重复可能漏过 repeated-block,通常由 dominant-gram / flat-tic 兜住。
- 每个 agent、每次 attempt 独立计数,子 agent 不共享。
- 触发会丢掉该步骤尚未发出的工具调用(代价是一次重试),这是换取"不再空转数分钟"的取舍;可先用 dryRun 观察。

用到的事件契约

- agent/assistant-stream,载荷 { agent, frame },frame = { type: 'start' | 'chunk' | 'end', attemptId, revision, …, chunk },chunk 为 StreamChunk(reasoning-delta / text-delta / …)。
- Agent.cancel(cause, options):封闭原因集合为 user | parent | disposed | hook,hook 会把 reason 记入 turn/end——本插件使用 hook。
- Agent.steer() 即 send(message, 'next-step', true);当活动信号已被 abort 时,send 会把目标升级为 next-turn 并唤醒 driver,因此 cancel(); steer(notice) 等于"中止这次生成,然后用新一轮继续"。

常见问题

dsh plugin add github:… 报 resolveGit / resolveRef 失败。
pnpm 解析 git 依赖要用 git 可执行文件,而 DSH 继承的是启动它的那个进程的环境变量。若你先启动 DSH、后安装 Git,新的 PATH 对已在运行的 DSH 不可见。把 Git 所在目录加进 shell 的 PATH(或重启 DSH)后重试:

$env:PATH = 'C:\Program Files\Git\cmd;' + $env:PATH
dsh plugin --profile <profile> add "github:ADistanceThereIs/dsh-output-loop-guard#<commit>"

建议固定到具体 commit(或 tag),这样后续推送无法悄悄改变本机实际运行的代码。

dsh plugin add https://… 报 fetch failed / unable to verify the first certificate。 Node 的 fetch 用的是内置 CA 列表,因此做 HTTPS 检查的安全软件(企业代理、部分杀软)会破坏它,而 curl 仍然正常。Node 22.15+/24 可改用系统信任库:

$env:NODE_OPTIONS = '--use-system-ca'
dsh plugin --profile <profile> add https://github.com/ADistanceThereIs/dsh-output-loop-guard/releases/download/v0.1.0/dsh-output-loop-guard-0.1.0.tgz

自己下载 tarball 再安装本地文件可完全绕开该问题。

护栏掐掉了你本来想要的内容。 设 dryRun: true(只检测不中止)、放宽阈值,或设 singleLineTextMinRepeats: 0 关闭正文单行判定。

感觉护栏没生效。 bundle 的行需要重启 DSH 后才激活;对于非应用托管的 profile,可用 dsh --profile <profile> --dump-config | Select-String output-loop-guard 确认该行已合成。

开发

node test/guard.test.mjs # 或 npm test

detector.mjs 无依赖、可单独导入(dsh-output-loop-guard/detector),因此检测逻辑可以脱离 DSH 复用或重新标定。

许可

MIT,见 LICENSE。
预览分享卡片长什么样 ↓ADistanceThereIs/dsh-output-loop-guard
分享 · DeepSeek Harness Hub
ADistanceThereIs/dsh-output-loop-guard

检测模型流式输出自我重复,自动中止失控轮次并唤醒继续

回到顶部