dsh-opencode-go-router:在缓存失效前切换 OpenCode Go 路由

前言

在 DeepSeek Harness(DSH)里走 OpenCode Go 调用 DeepSeek 系列模型时,上游靠 x-opencode-session 把同一会话钉在后端上,靠重复提示词前缀做 prompt cache。上下文折叠(billion-context)、系统提示词改写、历史压缩都会改写前缀,缓存随之丢失;折叠后的重建请求往往是冷的,但紧跟着的那条请求又可能立刻变热。若在请求已经发出之后才换路由,往往会多打一条无意义的冷启动。下面介绍 TLEWA 维护的 DSH 宿主插件 dsh-opencode-go-router(Cordis 内部 id 为 opencode-router):在请求发出之前预测缓存命中率,并在「判冷且最近很慢」时替换路由 id,同时用两级热路由池让前缀相近的新会话接手已有缓存的 id。

这是什么

dsh-opencode-go-router 是发布在 npm 上的 DSH 插件包(当前资料中的版本为 0.6.2,许可证 MIT)。它只修改 OpenCode Go 相关请求的 x-opencode-session 请求头,不是模型适配器。billion-context 可选:有折叠账本时可做折叠诊断;没有会话状态文件时,实测缓存、TTFT/吞吐统计、池替换与轮换历史仍由插件自身采样维护。

维护者与仓库:TLEWA/dsh-opencode-go-router。社区目录页:skillhub.cn 插件页。

为什么需要预测式轮换

OpenCode Go 用会话头绑定后端与缓存。前缀一变,该后端上的缓存就对不上新前缀。billion-context 折叠重建时,重建请求本身冷,但重建会把新前缀写进该后端缓存,下一条往往又热。

本插件的切换时机是:在一条本来就会冷的请求发出之前。钩子在 llm/stream、请求头组装之前运行,预测 <= cacheHitThresholdPct(默认 25%)且最近样本很慢时换新的 ses_... 路由 id,使新 id 作用在同一条被判冷的请求上,避免「多打一条额外冷请求」。

系统提示词改写或消息历史被压缩时,预测命中率恒为 0%,但仅「判冷」不够,还须最近请求的平均 TTFT 或吞吐达到慢请求门槛(默认 TTFT ≥ 12000 ms 或吞吐 ≤ 60 tok/s)。连续切换后仍慢于基础目标时,插件会按步进放宽下一次判定(stepTtftGraceMs、stepThroughputGraceTps),而不是重复等价切换。

只处理已配置 provider(默认 opencode-go)且模型 id 以 deepseek 开头(大小写不敏感)的请求;其他模型忽略。

核心能力

实测缓存与性能样本

插件包装合格请求的 llm/stream,读取最后一个 usage 块。单次命中率定义为 cacheReadTokens / (inputTokens + cacheReadTokens),并记录 TTFT、吞吐、提示词 token 数等;每个 DSH 会话保留最近 sampleSize(默认 5)条有效样本参与判定。

折叠账本(可选诊断)

若存在 billion-context 会话状态文件(路径形如 sessions/openai/<host>_<sha256(conversationId).slice(0,24)>.json),可跟踪 metadata.cacheLedger.folds。conversationId 在 DSH 中通常来自优先级更高的 x-bili-plugin-conversation;轮换 x-opencode-session 不改变该文件名。最新折叠主要作为「刚发生过重建式大冷请求」的证据,不单独直接触发轮换。插件不修改 billion-context 以外的文件。

预测与轮换条件

合格请求发出前,按 README 描述的顺序预测下一条命中率(含系统提示词变化、历史变短、空闲 cacheTtlMs、上次命中、大前缀 prefill 等规则)。第一个合格请求没有样本,不会因预测而轮换。

仅在预测为冷、minRotationGapMs 已过、最近普通请求模型合格、且(默认)攒满 requireFullSamples 时轮换。dryRun: true 时只记录不改请求头。

热路由 id 池

会话空闲入池后,前缀摘要(分块 SHA-256,不存原文)相近的新会话可借入一级或二级池中的老 ses_... id,减少冷启动。一级池要求前缀块命中率至少 poolMatchPct(默认 60%);二级借入还须满足相对会话基线的 poolSpeedGainRatio(默认 1.1)等条件。poolEnabled: false 可关闭池逻辑,行为更接近 0.6 之前「仅轮换时才创建路由」的模式。

Web 状态页

安装后可在 DSH Web 端口访问状态路径(README 示例:http://127.0.0.1:<DSH Web 端口>/opencode-router/status)查看实时统计与池对比信息。

环境要求

  1. DSH 版本 ≥ 0.2.1-rc.5 且 < 0.3.0(与 package.json 中 engines.dsh 一致)。
  2. Node.js 20 或更新。
  3. 使用带 llm-pi-ai 适配器的 DSH,并配置 OpenCode Go provider(默认名 opencode-go),且至少有一个模型 id 以 deepseek 开头的 DeepSeek 系列模型。

安装与启用

从 npm 安装(命令须与仓库 README 一致):

dsh plugin add dsh-opencode-go-router --profile <profile>

也可在 DSH 插件管理器的「添加插件」中填写包名 dsh-opencode-go-router。包内声明了 dsh.bundle.patch,正常安装会自动创建 opencode-router 行;不要在 profile 里为它再手动加一条独立 Cordis 行,也不要在 cordis.patch.yml 里重复 insert 同一插件。

安装后若 bundle 已在宿主运行期声明,需在插件管理器中重新加载或重启 DSH。与 dsh-opencode-ip-guard 等配套注入器联用时,路由存在时本插件会替换基线 x-opencode-session;overrideExistingHeader 控制是否覆盖已有头。

典型配置

在 profile 的 cordis.patch.yml 中按行 id 覆盖默认值,例如调高或调低缓存命中轮换门槛:

- id: opencode-router
  config:
    cacheHitThresholdPct: 25

常用项(完整表格见 GitHub README)包括:

键 默认值 作用摘要
enabled true 总开关
predictiveRotation true 关闭则不做预测式切换
cacheHitThresholdPct 25 预测命中率低于等于此值才可能轮换
ttftThresholdMs 12000 慢请求 TTFT 基础门槛
throughputThresholdTps 60 慢请求吞吐基础门槛
poolEnabled (见 README) 是否启用热路由池

修改实现后,触碰一次插件配置或开关 profile bundle 通常即可重新加载;版本号长期不变时可重启 DSH。

适用场景与注意

适合谁: 已在 DSH 中通过 OpenCode Go 稳定使用 DeepSeek 系列模型,且关心 prompt cache 丢失后 TTFT/吞吐变差、希望自动换路由或跨会话复用热 session id 的开发者。

权限与安全: 插件以当前 DSH 进程权限运行,会在本地写入 statePath(默认 $DSH_HOME/storages/opencode-router/state.json)并改写出站请求头。安装前建议阅读 仓库源码 与 MIT 许可证,确认 profile 与 provider 配置符合预期。

边界: 不压缩上下文、不改系统提示词或会话日志;失败判定始终按基础 TTFT/吞吐目标,不按已放宽后的目标。声明了 purpose 的辅助请求不改变「最近一次普通会话模型」的轮换判定状态。

结尾

dsh-opencode-go-router 把 OpenCode Go 的路由头管理与缓存命中率预测绑在 DSH 请求链路上:在缓存注定丢失且实测变慢时,于请求发出前替换 x-opencode-session,并用两级池让相似前缀会话继承仍热的后端绑定。DeepSeek Harness 生态奉行「一切皆插件」;SkillHub 目录 与 GitHub 仓库 为独立社区信息与源码归属处,与 DeepSeek / 幻方无官方应用商店从属关系。

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

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

小夜