dsh-loop-detector:DSH 智能体死循环与重复输出的硬中断检测

前言

在 DeepSeek Harness(dsh)上跑本地大模型时,量化或 RL 调过的推理模型有时会在流式输出里卡死:同一句话反复生成,或对着同一主题用不同措辞反复调用 web_search,却拿不到新信息。dsh 自带的 @deepseek-ai/dsh-repeat-tool-reminder 只是在上下文中注入提醒,模型可以忽略;本地模型(例如关闭 reasoning 的 Qwen / Ornith 35B MoE)在实践中仍会继续循环。

下面介绍社区插件 dsh-loop-detector(维护者 viego-qiin),它在运行时监听智能体流与工具调用,命中后硬中断当前生成,再引导重试;超过重试次数则取消整轮对话。插件归类为 admin-security,当前 GitHub 星标为 2。目录页:skillhub.cn/plugins/viego-qiin/dsh-loop-detector;源码与文档:github.com/viego-qiin/dsh-loop-detector。社区插件目录为独立站点,与 DeepSeek / 幻方无官方从属关系。

这是什么

dsh-loop-detector 是面向 dsh 0.2.x 的 Cordis 插件(v2.0.0,MIT 许可)。它做两类检测:正文/推理流上的文本级重复,以及指定工具(默认 web_search)上的「同任务换说法」意图级重复;命中后先 agent.cancel 中止当前生成,再 steer 引导,而不是只排队一条下一轮才生效的软提示。

若你在 dsh 0.2.x 上仍用 v1,插件可能从未触发:v1 监听的是已非实时会话事件的 assistant/chunk,中断用的是仅影响下一步的 steer(),且每次 steer 开新 turn 会把重试计数清掉。v2 改为监听 agent/assistant-stream,先 cancel 再引导,并在真实用户输入时重置计数(插件注入消息按 id 排除)。

核心功能

文本级重复检测

监听 agent/assistant-stream 的 text-delta,可选 reasoning-delta。缓冲区内分层检测:

  1. 周期扫描:尾部以固定周期(默认 8–256 字符)重复 ≥4 次。
  2. n-gram:最近 2048 字符内同一 64 字符块出现 ≥3 次。
  3. 大锚点:尾部 512 字符在更早位置再次出现并向后延伸(例如整段计划打印两遍)。

重复单元需至少 2 个不同字符且实质性字符(字母/数字/CJK)占比 ≥30%,避免把 markdown 分隔线、表格对齐符误判为循环。v2 对中文换词搜索循环使用「停词切分 + CJK 二元组 + Jaccard 相似度」,不再像 v1 那样按非字母数字切分把整句中文压成一个 token。

工具调用意图级重复

监听 tools/post-execute,从参数提取关键词,与最近 3 次调用的并集比较。新颖度低于阈值或 Jaccard 相似度高于阈值,且连续两次满足,则视为「同任务、换说法」。toolPatterns 支持通配符,可纳入 grep、shell 等工具;空数组可关闭该能力。

硬中断与重试

默认在打断后引导重试 1 次(maxRetries),用尽后取消整轮。可配置为首次命中即 cancel(action: 'cancel')。命中后有 cooldownMs,避免残留 chunk 再次触发。

安装与启用

前提:已有一个在跑的 dsh profile(dsh 0.2.x,Node ≥ 22.18,dsh 自带运行时满足即可)。

官方 README 给出两种方式,均未使用 dsh plugin add github:... 一类命令。

在 profile 目录下把插件链为本地依赖(路径换成你本机克隆或解压后的目录):

cd $env:USERPROFILE\.dsh\profiles\desktop
pnpm add link:"D:\path\to\dsh-loop-detector"

插件的运行时依赖(@deepseek-ai/cordis、dsh-agent、dsh-llm、dsh-tools、schemastery)必须留在 peerDependencies,不要挪到 dependencies,否则 Node 会在插件自己的 node_modules 里解析,缺失会导致插件加载失败;dsh 的 profile 解析器才会把裸 specifier 指到 dsh 已安装的副本。

方式二:复制到 node_modules

Copy-Item -Recurse -Force "D:\path\to\dsh-loop-detector" `
  "$env:USERPROFILE\.dsh\profiles\desktop\node_modules\dsh-loop-detector"

注册 bundle

仅 pnpm add link: 可能已能工作,但设置 → 插件 → 已安装列表来自 profile 的 bundles。在 package.json 中追加包名:

// $env:USERPROFILE\.dsh\profiles\desktop\package.json
"dsh": {
  "profile": {
    "bundles": [
      "@deepseek-ai/dsh-base",
      // …existing entries…
      "dsh-loop-detector"
    ]
  }
}

重启 dsh 后可在 GUI 中开关插件。覆盖默认配置可在 profile 的 cordis.patch.yml 末尾写 id 定向项(升级插件后仍保留):

- id: loop-detector
  config:
    minLen: 1024
    checkReasoning: false

临时关闭可用 GUI,或:

- id: loop-detector
  disabled: true

典型用法与日志

安装并启用后,可故意让模型进入重复输出或重复搜索,在日志中应看到类似:

[loop-detector] session xxx 正文本命中: periodic repeat: period=8 x4|片段 "abcdefgh"
[loop-detector] session xxx 检测到死循环(重试 1/1): periodic repeat: period=8 x4;已打断并引导重试
[loop-detector] session xxx 意图级重复: repeated web_search intent: novelty=0.29 similarity=0.71

常用配置项(完整表见仓库 README):

字段 默认 含义
minLen 512 累计多少字符后开始检测
maxRetries 1 打断并引导的次数,之后取消 turn
action 'steer' 'steer' 打断+引导;'cancel' 首次命中即取消
toolPatterns ['web_search'] 监视的工具名(通配符);[] 关闭意图检测
checkReasoning true 是否检测 reasoning 流

非法配置(未知 action、minLen < 1、比例不在 [0,1])会在挂载时报错,不会静默回退。

适用场景与注意

适合在 dsh 0.2.x 上跑本地或易陷入文本复读、工具空转的智能体场景;需要比官方 repeat-tool-reminder 更强制的止损时可以考虑启用。

插件与当前 dsh 进程同权限运行,安装前请阅读 源码 与 MIT 许可证,自行评估是否纳入 profile。调参项(周期范围、n-gram、锚点窗口等)多数有合理默认,仅在误报/漏报时再动 README 中的 Detector tuning 一节。

结尾

dsh-loop-detector 针对 dsh 0.2.x 会话事件与中断语义做了对齐,用文本三层检测加工具意图检测,在循环发生时 cancel 硬中断并有限次引导重试。更多信息见 SkillHub 目录页 与 GitHub 仓库(含 README.zh.md)。

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

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

Xiaoye