dsh-empty-turn-guard:避免模型只输出协议标记的空回合

前言

在使用 DSH(DeepSeek-Harness)进行智能体开发时,一种隐蔽的失败模式值得注意:模型返回的内容只剩下协议标记(如 </||DSML|| calls>、<thinking> </thinking> 等),既没有正文也没有工具调用,而 Harness 把它当作一次正常的回合结束。这会导致对话静默中断,很难排查。

dsh-empty-turn-guard 插件针对这种场景,把只有协议标记的回合改判为可重试的 EMPTY_RESPONSE 错误,让 Harness 重新调用模型,而不是默默结束。

是什么

这是一个 DSH bundle(自带 cordis.patch.yml 的插件包),由维护者 FYTXY 开发,分类为「工作流」。它通过拦截 llm/stream 链路,在接收到模型返回的 finish 事件时检查三个条件:reason 为 stop、未观察到工具调用、去除标记后文本为空。满足时将结果重写为 EMPTY_RESPONSE,触发重试机制。

插件没有依赖,不修改 DSH 原有文件,通过 DSH 的 bundle 机制安装。

核心功能

  • 拦截只有协议标记的回合。当模型返回以 </||DSML|| calls>、<thinking> </thinking> 或剩余标点结尾的内容,且没有工具调用时,将其转为 EMPTY_RESPONSE。
  • 提供两处开关。在「Settings → Built-in plugins → Empty-turn guard」和「Plugins」侧边栏各有一处开关,控制同一个配置。
  • 避免误判。插件要求同时满足 finish 为 stop、无工具调用、去标记后文本为空三个条件才触发。一个词的回答、单独的 ? 或提及标记的正文都会正常通过。
  • 不影响截断。max-tokens 限制导致的截断已经是可见结果,插件不介入。
  • 日志安全。诊断日志只记录字符长度(如 text=24ch),不记录模型输出文本。

安装与启用

从 GitHub 安装:

dsh plugin --profile <your-profile> add github:FYTXY/dsh-empty-turn-guard

安装后重启 DSH,在「Settings → Built-in plugins → Empty-turn guard」打开开关即可生效。

若从本地 checkout 开发,可使用:

dsh plugin --profile <your-profile> add link:/absolute/path/to/dsh-empty-turn-guard

典型用法

启用后,当模型只返回协议标记时,日志会出现类似信息:

[dsh-empty-turn-guard] empty-turn-guard: mounted (markup-only stops become EMPTY_RESPONSE retries)

实际拦截时:

[dsh-empty-turn-guard] rewriting an empty stop (text=24ch) into EMPTY_RESPONSE

随后会触发 llm/retry 或 llm/retry-started 事件,由 DSH 的重试机制处理,默认重试 5 次,初始间隔 500ms,最大间隔 10s,带有 10% 随机抖动。

若需保持安装但暂时禁用,可在 profile 的 cordis.patch.yml 中为该行添加配置:

- id: dsh-empty-turn-guard
  name: 'dsh-empty-turn-guard'
  config:
    enabled: false

enabled 是易失字段,无需重启即可生效。

适用场景与注意

适合需要稳定对话流程的场景,特别是对工具调用和回合完整性要求较高的工作流。

插件以当前 DSH 进程权限运行,安装前建议检查源码与许可证(MIT)。

小结

dsh-empty-turn-guard 通过在 llm/stream 链路前置拦截,把只有协议标记的空回合转为可重试的错误,减少静默失败。其实现不依赖额外运行时库,仅使用 DSH 现有的 llm/stream 和 EMPTY_RESPONSE 接口。

  • 插件目录:https://www.skillhub.cn/plugins/FYTXY/dsh-empty-turn-guard
  • GitHub:https://github.com/FYTXY/dsh-empty-turn-guard
羽毛球分组比赛记分
小程序二维码

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

Xiaoye