dsh-plugin-opencode-route:爲 OpenCode Go 會話自動挑選更快網關路由

前言

在 DeepSeek Harness(DSH)裏用 OpenCode Go 做模型推理時,同一會話會通過 x-opencode-session 請求頭固定到某條上游路徑。不同 id 相當於不同「抽籤」結果,快慢並不一致。遇到首輪流式輸出偏慢,常見做法是手動開新會話再試——費時,且對話裏會留下中斷痕跡。

dsh-plugin-opencode-route 把這一過程自動化:僅在會話的第一次模型請求上監測解碼速率,過慢則中止當前嘗試、換新的路由 id 重試;用戶只看到最終被接受的那一次流式輸出,後續輪次不再換路,以免破壞已積累的 prompt cache。

這是什麼

  • 定位:DSH 插件,面向 opencode-go 提供商的網關路由實驗與優化。
  • 維護者:neil-ji(GitHub 倉庫)。
  • 分類:模型推理;當前倉庫星標爲 0。
  • 許可證:MIT(package.json 標明版本 1.10.9,運行需 Node.js >= 20)。

插件不保管憑證,每次調用仍經 ctx.llm,由提供商自行解析密鑰。

核心機制

只動路由 id

OpenCode Go 用 x-opencode-session 把對話釘在某條後端鏈路上。本插件只改這個頭裏的 id,不碰模型名、prompt 內容或其他供應商邏輯。

首請求:緩衝、判速、重試

對處於處理組(treatment)的會話,第一次請求流程如下:

  1. 先按常規模型調用放行。
  2. 緩衝首輪流式輸出的前 windowMs(默認 2000 ms)token。
  3. 計算這段窗口內的運行速率;若低於 thresholdTps(默認 150 tok/s),丟棄本次嘗試,生成新的 x-opencode-session id 重發。
  4. 最多重試 maxRetries(默認 3)次。被中止的窗口不會展示給用戶;接受的流按原始節奏回放(約一個窗口滯後),以便 DSH 自身的 token 速率統計仍反映真實時間線,而不是 2 秒突發。

僅首請求會觸發上述邏輯:一旦會話已經調用過模型,後續輪次一律直連,以保護 prompt cache。若首條 prompt 超過 maxPromptTokens(默認 60 000),也不再重試——每次重試都要完整 prefill,代價過高。

默認參數來自對 323 次真實首請求的調參(倉庫內 research/tune_reroll.mjs):2000 ms / 150 tok/s / 3 次重試時,約 95% 會話達到 ≥150 tok/s,平均約 1.75 次嘗試,誤殺率約 7%。動態重調參已設計但未啓用,見 research/TODO-tuning.md。

A/B 實驗

會話按 sha256(salt:sessionId) 分桶:treatment 啓用重試,control 完全不動。雙方均記錄帶 arm 字段的 turn 事件,便於對比效果。分析腳本爲 research/analyze_ab.mjs,可用 --since <timestamp> 限定 cohort。

安裝與配置

安裝

倉庫隨附 cordis.patch.yml 默認配置。安裝命令如下(須使用資料原文,勿自行拼接 github:owner/repo 形式):

dsh plugin add dsh-plugin-opencode-route --profile <name>

將 <name> 換成你的 DSH profile 名。插件在當前 dsh 進程權限下運行;安裝前建議閱讀源碼與 MIT 許可證,確認符合你的安全策略。

配置項

下列字段均在 README 中列出,均可選覆蓋:

config:
  enabled: true
  dryRun: false              # true = 只觀測,不重試
  providers: [opencode-go]   # 精確白名單;其他提供商不受影響
  models: []                 # 空列表表示該提供商下全部模型
  reroll: { enabled: true, windowMs: 2000, thresholdTps: 150, maxRetries: 3, maxPromptTokens: 60000 }
  experiment: { enabled: true, armRatio: 0.5, salt: route-v1 }
  • dryRun: true 時只記錄行爲,不實際換 id。
  • 關閉 reroll.enabled 或頂層 enabled 可去掉所有重試副作用;A/B 中的對照組本就不走重試。

觀測與排錯

界面與命令

  • 會話標題欄徽標(Header capsule):只讀展示會話加權速率(總輸出 token / 總解碼時間,與 DSH Composer 頁腳定義一致);數據不足時回退爲最近三次可用請求的中位數。A/B 期間顯示 實驗組 或 對照組,懸停可見最近三次請求的時間、速度、首 token、cache 等信息。
  • /route:當前實驗臂、參數、計數器與近期 turn。
  • /route stats:重試相關計數。
  • /route test:受控檢查路由 id 是否影響速度(四個 id 交錯重複,報告組間與組內方差)。

事件與 HTTP

  • 事件日誌:%DSH_HOME%\opencode-route\events.jsonl,含 plugin、turn、reroll 等類型;約 8 MB 輪轉至 events.1.jsonl。
  • 只讀 HTTP:GET /opencode-route/status?session=<id>。

效果評估可配合 research/analyze_ab.mjs 讀取事件日誌;早期實驗曾測過舊的 probe/pin 方案(無顯著效果),當前 shipped 行爲以 README 所述 reroll 爲準。research/README.md 記錄的是更早的基線研究(446 sessions / 44k calls),屬歷史背景,不代表現行邏輯。

適用場景與副作用

適合誰

  • 主要通過 DSH 使用 OpenCode Go,且首輪流式解碼速度波動明顯、願意用首 token 延遲換穩定吞吐的開發者。
  • 需要做路由策略 A/B、並用事件日誌與 /route 工具鏈量化對比的團隊。

不適合指望「零成本加速」的場景:重試只針對處理組會話的第一次請求,且僅在判定過慢並實際中止時產生代價。

首請求重試的成本(README 明示)

僅 treatment 首請求、且發生中止時:

  • 首 token 更晚:每次嘗試各有 TTFT,外加 2 s 觀測窗;按調參後約 1.75 次嘗試,首個可見 token 可能約 10 s(相對單次約 4 s);四次均慢時可達約 25 s。接受後的流仍按原節奏回放,後續正文不慢於該次嘗試本身。
  • 額外輸入 token:每次中止會在新 id 下冷 prefill;約 1.75 次嘗試意味着約 0.75 次額外 prefill(例:15k 首 prompt 約多 11k input tokens)。maxPromptTokens 限制最壞情況。
  • 額外輸出 token:中止前最多已生成約一個窗口的輸出(約 200–300 token)。
  • 上游可能短暫繼續生成:插件停止消費流,未必取消提供商側任務。
  • DSH 原生 TTFB 含浪費的嘗試;插件 turn 事件中的 TTFB 僅來自被接受的那次。
  • 接受嘗試使用新 id:該次起 prompt cache 變冷;原 id 下已溫熱的 cache 在換路後需重建。

對照組與關閉 reroll 的會話無上述開銷。

結尾

dsh-plugin-opencode-route 在不動後續對話緩存的前提下,把「這條會話太慢,換個 session id 再試」收進 DSH 插件層:首請求測速、靜默重試、只展示接受的那條流,並配套 A/B 與觀測面方便驗證是否值得長期開啓。

DSH 生態強調「一切皆插件」;SkillHub 等目錄爲社區站點,與 DeepSeek / 幻方無官方從屬關係。是否安裝請結合本機權限與提供商策略自行判斷。

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

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

小夜