前言¶
在 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)的會話,第一次請求流程如下:
- 先按常規模型調用放行。
- 緩衝首輪流式輸出的前
windowMs(默認 2000 ms)token。 - 計算這段窗口內的運行速率;若低於
thresholdTps(默認 150 tok/s),丟棄本次嘗試,生成新的x-opencode-sessionid 重發。 - 最多重試
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 與觀測面方便驗證是否值得長期開啓。
- 社區目錄頁:https://www.skillhub.cn/plugins/neil-ji/dsh-plugin-opencode-route
- 源碼與說明:https://github.com/neil-ji/dsh-plugin-opencode-route
DSH 生態強調「一切皆插件」;SkillHub 等目錄爲社區站點,與 DeepSeek / 幻方無官方從屬關係。是否安裝請結合本機權限與提供商策略自行判斷。