dsh-reasoning-efforts
给第三方 provider 的模型自动挂上思考强度档位(off / low / medium / high / max), 让 DSH Next 聊天界面右下角的模型选择器里能直接选思考强度,并随时切换。
装上之后,在界面里加模型不需要任何额外操作 —— 插件会自动补档位。
为什么需要它
DSH 的 @deepseek-ai/dsh-llm-pi-ai 适配器支持给每个模型声明 reasoningEfforts,
一旦声明,模型选择器就出现档位。但:
- 官方 DeepSeek 卡片自带档位;
- 手工声明的第三方路由默认没有,必须逐个模型声明。
这个插件按规则表自动补,不靠逐个手写。
实测依据
档位最终作为 reasoning_effort 字段发给网关(thinkingFormat: openai 分支)。
对一个自建的 OpenAI 兼容网关(new-api 类)实测:
| 模型 | off (none) |
low | medium | high | max |
|---|---|---|---|---|---|
| 反代-deepseek-v4.1-flash | 思考 0 tok | 265 | — | 338 | 599 |
| wy-gemini-3.8-flash | 0 | 0 | 128 | 713 | — |
| 反代-hy3 | 0 | — | — | 25 | — |
结论:off 用 none 能真正把思考降为 0;Gemini 系要 medium 起才真正思考。
off: none 对 DeepSeek / Gemini / hy3 都接受,不会 400。
DSH 会话日志里的 request/header 可复核:切到 off 后 reasoningEffort: "off",
且该轮及之后的回复 reasoning 字符数均为 0。
工作原理
auto-efforts.json(规则表)
↓ 按模型 id 关键字匹配
auto-efforts.cjs(判定:挂哪些档位、线上发什么值)
↓
sync-core.mjs(只重写 cordis.patch.yml 的 models 段,写前回读校验)
↓
host.mjs(DSH 启动时 + 配置变化时自动触发)
sync-efforts.mjs 是同一个核心的命令行入口,用于排查或插件未启用时兜底。
用法
日常:什么都不用做
界面里加/删模型后,插件监听到配置变化会自动补档位。
改规则
编辑 auto-efforts.json:
{
"rules": [
{ "on": ["gemini"], "off": ["embedding", "reranker", "imagine"] }
]
}
on:模型 id 含任一关键字(大小写不敏感子串)就挂档位off:含任一关键字就跳过(排除优先,防止 embedding 之类被误挂)wire:可选,覆盖某档位实际发送的值
支持 // 注释和尾逗号。改完下次配置变化或重启时自动生效。
手动同步(排查用)
node sync-efforts.mjs # 写入 profile 的 cordis.patch.yml
node sync-efforts.mjs --dry-run # 只看会改什么
node sync-efforts.mjs --patch <路径> --rules <路径>
设计取舍
没有用 patch 里的 !!js 表达式,虽然技术上可行。原因:
DSH 的 HMR 走"轻量配置更新"路径,不执行 !!js 求值,会报
$.providers.mine.models expected array but got [object Object] 并保留旧配置。
只有冷启动才求值。结果是改完配置热重载就坏,非常脆。
所以把档位算成字面量写进 YAML —— 热重载、冷启动都正常。
手写优先:已经写了 reasoningEfforts 的模型永远不被覆盖,规则只填空缺。
坏文件不落盘:写之前用 DSH 同款解析方言回读校验,条目数不一致就放弃写入。
规则没命中就不管:不认识的模型名(如 gpt-4o、embedding)不挂档位,
宁可没有选项,也不给不支持推理的模型发 reasoning_effort 导致 400。
想全覆盖,在 auto-efforts.json 里加一条 { "on": ["-"] } 之类够宽的关键字即可。
文件
| 文件 | 作用 |
|---|---|
auto-efforts.json |
规则表,日常主要动这个 |
auto-efforts.cjs |
规则判定逻辑(纯函数) |
sync-core.mjs |
同步核心(解析、重写、校验) |
sync-efforts.mjs |
命令行入口 |
host.mjs |
插件宿主端:启动同步 + 监听配置变化 |
vendor/js-yaml.cjs |
js-yaml 4.3.1 的兜底副本(MIT,见 vendor/README.md) |
依赖说明:优先用宿主环境里的 js-yaml;DSH 把依赖打进 app.asar,profile 里通常没有,
所以 vendor/ 里带了一份副本兜底。能自己装 js-yaml 的话可以删掉 vendor/。
排查
模型选择器里没有档位?
- 确认 patch 里该模型有
reasoningEfforts(node sync-efforts.mjs --dry-run) - 看
~/.dsh/logs/desktop-next.log有没有[reasoning-efforts]日志或ValidationError - 模型名没命中任何规则时会故意不挂档位——在
auto-efforts.json里加对应关键字
请求报 400 / UNSUPPORTED_REASONING_EFFORT?
说明该网关不认这个档位。在规则表里给该模型加 off,或减少档位。
安装
# 1. 把包放进任意目录,然后在你的 DSH profile 里装它(profile 目录通常 ~/.dsh/profiles/desktop)
cd ~/.dsh/profiles/desktop
pnpm add <本包的绝对路径或 npm 包名>
# 2. 在 package.json 的 dsh.profile.bundles 里登记(pnpm add 不会自动加)
# "bundles": [ ..., "dsh-reasoning-efforts" ]
# 3. 重启 DSH Next
装好后打开 ~/.dsh/logs/desktop-next.log,能看到:
[reasoning-efforts] 目标配置: <你的 DSH 目录>/profiles/desktop/cordis.patch.yml
[reasoning-efforts] 档位已是最新(启动)
就说明插件在工作。
路径零配置:
host.mjs按DSH_HOME/DSH_PROFILE环境变量推导 profile, 推导不到就挑profiles/下最近修改的那个。要强制指定,在cordis.patch.yml里给插件加config.patchPath。
版本历史
1.3.0(2026-10-24 12:54)
js-yaml依赖解析改为优先用宿主环境已装的包,vendor/副本退为兜底,缺失时给出可操作的报错- 插件入口
cordis.patch.yml与host.mjs去除对特定机器的路径依赖,可跨机器/跨 profile 运行
1.2.0(2026-10-24 12:45)
cordis.patch.yml改用相对路径./host.mjs,不再写死绝对路径host.mjs自动推导 profile 路径(DSH_HOME/DSH_PROFILE→ 最近修改的 profile)
1.1.0(2026-10-24 10:00)
- 新增
host.mjs自动同步:DSH 启动时与配置变化时自动补档位,界面加模型后无需手动跑脚本 - 抽出
sync-core.mjs,命令行与插件共用同一份同步逻辑
1.0.0(2026-10-23 22:00)
- 首版:规则表 +
sync-efforts.mjs手动同步 - 实测 off/low/medium/high/max 五档在 DeepSeek / Gemini / hy3 上生效
- 档位以字面量写入配置,避免
!!js表达式在热重载路径下不求值的问题
No comments yet. Be the first to write one.