前言¶
在 DeepSeek Harness(DSH)裏接大模型流式回答時,模型有時會以「抱歉,我不能…」「Sorry, I can’t…」一類話術直接拒答。若只在 HTTP 反向代理層處理,通常要把整段響應緩衝完再判斷,流式打字效果會斷掉。DSH 走客戶端插件與結構化 chunk,可以在只預讀開頭若干字符後做決定,被拒那次不向用戶展示,再靜默重發,正常回復的流式體驗基本保留。下面介紹社區插件 dsh-policy(維護者 hbx111,分類:模型推理)的實現思路與配置方式。
這是什麼¶
dsh-policy 是掛載在 DSH 上的插件(當前包版本 1.1.0,MIT 許可證),承擔兩件彼此獨立的工作:
- 流內判拒與自動重試(README 中的 headline 能力):若模型正文以拒答模式開頭,丟棄該次嘗試並靜默重新發起請求。
- 策略文本注入(可選,默認關閉):在出站請求尾部追加一段 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,是否採用請結合自有合規要求與源碼審閱後決定。