前言¶
在 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 / 幻方无官方从属关系。是否安装请结合本机权限与提供商策略自行判断。