dsh-policy:流式輸出下的判拒檢測與靜默重試

前言

在 DeepSeek Harness(DSH)裏接大模型流式回答時,模型有時會以「抱歉,我不能…」「Sorry, I can’t…」一類話術直接拒答。若只在 HTTP 反向代理層處理,通常要把整段響應緩衝完再判斷,流式打字效果會斷掉。DSH 走客戶端插件與結構化 chunk,可以在只預讀開頭若干字符後做決定,被拒那次不向用戶展示,再靜默重發,正常回復的流式體驗基本保留。下面介紹社區插件 dsh-policy(維護者 hbx111,分類:模型推理)的實現思路與配置方式。

這是什麼

dsh-policy 是掛載在 DSH 上的插件(當前包版本 1.1.0,MIT 許可證),承擔兩件彼此獨立的工作:

  1. 流內判拒與自動重試(README 中的 headline 能力):若模型正文以拒答模式開頭,丟棄該次嘗試並靜默重新發起請求。
  2. 策略文本注入(可選,默認關閉):在出站請求尾部追加一段 policy 文本,作爲 user 消息發給模型。

中文 README 概括爲:在 dsh 客戶端側對模型響應做流內判拒並自動重發;只預讀開頭一兩句,被拒那次不吐給上層,正常回復的流式打字幾乎不受影響。插件零外部依賴,僅使用 Node 內置模塊;要求 Node >=18,DSH >=0.2.0-rc.1。

與「純代理」的差異可以概括爲:

plugin:  llm/stream (waterfall)  →  peek first N chars  →  refusal?  →  re-issue & swallow
proxy:   full response buffered  →  judge at the end    →  no streaming at all

核心功能

判拒與重試

  • 廉價預讀:默認只緩衝開頭 peekChars(默認 200)個字符再判定;普通長回答幾乎直通,延遲很小。
  • 推理塊感知:reasoning-delta 不計爲「正文已開始」;模型先長段推理再拒答仍可識別。
  • 工具調用感知:若第一個塊是 tool call,不按拒答處理,不重試。
  • 上游過濾感知:content_filter / guardrail_intervened / risk control 等終止視爲終態,不再重試,避免燒 token,並在失敗信息上附註。
  • 中英拒答模式:覆蓋如 Sorry, I can't…、抱歉,我不能提供…、我無法寫這類…,以及中文後置否定(例如「繼母與繼子這類家庭親屬關係的性內容我不寫」一類句式)。
  • 降低誤判:技術表述如「這個函數我不寫註釋」不應觸發重試;規則用窄模式與對象詞白名單約束。

判拒邏輯 looksRefusalHead(text) 對前 200 字符分四類:開頭道歉+不能、開頭不能+動作、指示詞+不能、後置否定等。後置否定用於補全僅以句首「抱歉」「我不能」錨定會漏掉的中文拒答。

策略注入(可選)

通過 ~/.dsh/policy/config.json 的 mode 控制注入位置:off | user | system | both;文檔說明 user 是較可靠送達模型的位置。重試與 mode 無關,mode 爲 off 時仍可單獨開啓重試。

onlyAgentLoop 默認爲 true:僅對攜帶 tool definitions 的請求注入策略,標題生成等內部調用不注入。

配置熱更新與日誌

  • 配置目錄:~/.dsh/policy/,含 config.json、policy-sys.txt(mode != off 時注入的文本)、policy.log(決策日誌,上限 256 KiB)。
  • 修改 config.json 的 mtime 後插件會重讀,無需重啓 dsh;修改 index.js 需重啓 dsh。
  • log: true 時向 policy.log 追加決策記錄。

默認配置示例(README 原文):

{
  "mode": "off",
  "onlyAgentLoop": true,
  "log": true,
  "retry": {
    "enabled": true,
    "maxRetries": 2,
    "peekChars": 200,
    "peekMs": 1200,
    "minTextChars": 24,
    "textStallMs": 1500,
    "maxWaitMs": 10000,
    "backoffMs": 350
  }
}

各鍵含義與默認值見下表(摘自 README;retry.enabled 文檔表內默認值爲 false,示例 JSON 中爲 true,以你實際寫入的配置爲準):

Key Default Meaning
mode off 策略注入:off | user | system | both
onlyAgentLoop true 僅在帶 tool 定義的請求上注入
log true 寫 policy.log
retry.enabled false 拒答重試總開關
retry.maxRetries 2 拒答後最多重發次數
retry.peekChars 200 判定前緩衝字符數
retry.peekMs 1200 等待首段文字的最長時間
retry.minTextChars 24 低於此長度繼續等待
retry.textStallMs 1500 文字停止增長多久後放行
retry.maxWaitMs 10000 預讀窗口硬上限
retry.backoffMs 350 重發前等待

安裝與啓用

README 給出兩種方式,未提供 dsh plugin add github:… 一類一鍵命令,安裝前請自行閱讀倉庫源碼與許可證(插件以當前 dsh 進程權限運行)。

方式一:將插件目錄放在 dsh profile 旁並註冊。

方式二(推薦):作爲 profile bundle 安裝;包內已含 cordis.patch.yml,不必在 profile 裏重複寫入。

若不以 bundle 安裝,需在 profile 的 cordis.patch.yml 中插入:

# profile/cordis.patch.yml — only needed if you are NOT installing as a bundle
- insert:
    - id: dsh-policy
      name: "dsh-policy"

以 bundle 安裝時,包內 cordis.patch.yml 已包含上述條目,不要在 profile 中重複。

啓用重試時,將 ~/.dsh/policy/config.json 中 retry.enabled 設爲 true,並按需調整 peekChars、maxRetries 等。需要策略注入時編輯 policy-sys.txt 並設置 mode。

本地測試

倉庫提供無網絡、無需啓動 dsh 進程的測試,驅動僞造 chunk 流經真實 listener:

node test-retry.mjs

README 記載 16 個用例,覆蓋拒答命中、正常內容不誤判、重發後用戶只見第二次、長推理後拒答、工具調用不重試、上游 content_filter 不重試等場景。

適用場景與限制

適合:在 DSH 智能體/對話鏈路中希望保留流式 UX,又對「開口就拒」做有限次自動重試的開發者;可與可選 policy 注入配合約束模型行爲。

限制(README 原文要點):

  • 重試是統計意義上的緩解;若同一輸入每次都被拒,重試只會多耗 token,最後一次原樣返回。
  • 檢測基於前綴;拒答出現在多段正常正文之後則抓不到。
  • 預讀窗口會在首 token 慢時增加延遲,可通過降低 peekMs 權衡首字延遲與檢出率。

參考鏈接

DSH 生態強調「一切皆插件」;SkillHub 等目錄爲社區站點,與 DeepSeek / 幻方無官方從屬關係。dsh-policy 當前 GitHub 星標爲 0,是否採用請結合自有合規要求與源碼審閱後決定。

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

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

小夜