dsh-output-loop-guard:在流式输出中拦截模型自重复退化环

前言

在 DeepSeek Harness(DSH)里跑智能体时,模型有时会卡在「同一段短文本」上反复解码:推理通道里不断重复「好。→(执行)→好。→Write.→…」,却迟迟不发出工具调用。官方自带的 @deepseek-ai/dsh-repeat-tool-reminder 只盯连续重复的工具调用(同一工具、同一参数,连续 3/5/8 次),对推理通道里的文本循环无能为力;自动 compaction 也未必能及时触发。结果是输出越滚越长、会话记录被污染,人工点停止往往成了唯一出路。

下面介绍社区插件 dsh-output-loop-guard(维护者 ADistanceThereIs):它监听实时 agent/assistant-stream 帧,从文本结构判断是否进入退化环,中止失控回合,并用纠正性通知唤醒智能体继续工作。

这是什么

dsh-output-loop-guard 是面向 DSH 的 bundle 插件,定位是「输出自重复看门狗」:在推理或可见文本里检测退化循环,中止该轮生成,并向 agent 注入纠正说明,无需人工按停止或手动输入「继续」。

  • 要求 DSH >= 0.2.0-rc.2,ESM 打包,运行时零依赖。
  • 在 SkillHub 社区目录中归类为 admin-security。
  • 源码与说明见 GitHub 仓库,当前发布版本 0.1.0(MIT)。

与 repeat-tool-reminder 的差异

能力 repeat-tool-reminder output-loop-guard
观测对象 重复工具调用 流式文本本身
推理通道循环 不可见 可检测
长时间无 tool call 的刷屏 不触发 可中止并 steer

README 中记载的动机会话里,模型在推理中重复约 112,109 字符、50,196 个流式分片、持续解码约 126 秒且零次工具调用——repeat-tool-reminder 无法介入;在该语料回放校准中,本插件对该类模式有检测记录(见下文「校准数据」)。

核心功能:如何检测与如何处置

滑动窗口与四条信号

默认在流式输出上维护 1,200 字符滑动窗口,每新增 64 字符检查一次。四条规则如下:

信号 规则概要 主要覆盖
repeated-block 最短周期块(≥2 换行、≥2 个不同非空白字符)重复 ≥6 次 多行短周期循环
dominant-gram 某一 n-gram 占窗口 ≥55%、出现 ≥24 次且跨 ≥2 行 尾部参差但重复已占主导
repeated-line 单行连续重复:推理通道 ≥40、可见文本 ≥60(singleLineTextMinRepeats,设为 0 可关闭) 单行空转或答案里行级刷屏
flat-tic 无空白短 gram 占窗口 ≥25%、出现 ≥48 次,仅推理通道 无换行的口吃式重复(如「好。好。好。」)

设计上有两点刻意收紧误报:只认最短周期的多行块(避免把普通列表判成循环);对通道区分对待——可见文本单行阈值更高,缩进块、====/---- 分隔线、空行运行等不触发。

触发后的动作

  1. 调用 agent.cancel({ kind: 'hook', reason: 'output-loop-guard: …' }),中止进行中的生成并记为中断,退化文本不再增长。
  2. 调用 agent.steer(<notice>);因生成已中止,steer 会升级为新回合,驱动智能体按通知纠正(停止复述、发出下一步动作或结束)。
  3. 同一回合内超过 maxTripsPerTurn 次触发后,不再自动继续,仅 inject 通知,避免坏模型无限自旋。

安装与启用

插件以 DSH bundle 形式安装:loader 读取 package.json 中的 dsh.bundle.patch,cordis.patch.yml 会插入 output-loop-guard 行。任选一种方式(将 <profile> 换成你的 profile 名;方式 A 需将 <commit> 换成具体 commit):

# A. 从 git 主机安装,钉在某一 commit(DSH 进程 PATH 上需有 git)
dsh plugin --profile <profile> add "github:ADistanceThereIs/dsh-output-loop-guard#<commit>"

# B. 从 Release 压缩包安装(无需 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 层。修改 bundle 后需重启 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 = 仅检测并打日志,不 cancel
    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。

典型用法与验证思路

  1. 安装 bundle 并重启 DSH,确认 cordis.patch.yml 中出现 output-loop-guard 行。
  2. 生产环境前用 dryRun: true 跑若干真实任务,看日志里是否有合理检测。
  3. 关闭 dryRun 后,当模型进入结构化的自重复循环时,会话里应出现 turn/end 的 reason.kind 为 hook、reason.reason 含 output-loop-guard,以及来源为 output-loop-guard 的用户向通知。

README 给出的端到端示例日志片段(任务被设计成重复两行 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}
{"type":"user/message","source":{"kind":"output-loop-guard","form":"notice"}}

意图是:止住失控输出,而不是放弃任务——示例中 agent 随后把同样内容写进文件,而非继续重复刷屏。

仓库内 npm test 运行 21 项自包含回归(不依赖语料文件),覆盖真实退化必须被中止、健康长文档不受影响、列表/代码块/表格等正常输出不误报、dryRun 不 cancel、禁用插件不挂载等行为。

校准数据与局限

作者在 README 中公布的语料回放(27 个真实会话 / 1,783 个 assistant 步)结果:24 次检测,0 次误报;动机会话的每一步循环均被命中;112,109 字符失控在约 2,944 字符(2.6%) 处被截断,其他循环多在 1,152–7,808 字符内触发。

使用时需注意:

  • 可见文本要触发单行重复需 ≥60 行连续相同;合法 fixture、列表可能被保护,若不需要可设 singleLineTextMinRepeats: 0。
  • 检测基于周期与密度等结构特征,语义上「近重复」可能漏过 repeated-block,但 dominant-gram / flat-tic 常能补上。
  • 插件在 当前 DSH 进程权限下运行,安装前请自行审阅源码与 MIT 许可证;社区目录 SkillHub 插件页 与 GitHub 为独立信息源,与 DeepSeek / 幻方无官方从属关系。

结尾

DSH 生态强调「一切皆插件」;当工具调用重复提醒覆盖不到推理通道刷屏时,dsh-output-loop-guard 用流式文本上的四条结构信号自动 cancel 并 steer,把「人工点停止」换成可配置的看门狗。需要进一步了解分类与条目信息可打开 SkillHub 目录页,安装与配置细节以 GitHub README 为准。

羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

小夜