dsh-baipiao-shigege
把白嫖渠道的模型按价格自动分成三条 1M 降级链,另加一条自己挑的 Custom 链;四条链都按实测吞吐从大到小排序,慢于门槛的模型直接出局。
DeepSeek Harness (DSH) 插件 · 版本 0.2.2 · MIT
它解决什么问题
白嫖渠道动辄上百个模型,倍率、上下文、速度各不相同。手动挑模型有三个麻烦:
- 不知道现在能用什么 —— 哪个渠道还有额度、哪个模型 1 块钱能用多久;
- 挑出来的模型会挂 —— 单个模型限流或宕机,整个会话就卡住;
- 快的不一定排前面 —— 首字快的模型可能吐字极慢,整体反而更慢。
这个插件把「能用什么」和「该先用谁」都自动化了:
- 从你的本地渠道网关拉全部模型,带倍率、上下文、图片能力;
- 按倍率分成 免费 / 低积分 / 高积分 三条链,每条都只收够 1M 上下文的模型;
- 每条链是一个 fallback 链,作为一个模型出现在选择器里:链首失败自动换下一个;
- 四条链统一按实测吞吐降序,每次启动自动重测一轮,低于 50 tok/s 的模型直接不进链;
- 调用在吞吐最高的前 N 个里轮流,既用快的、又不把用量压在同一个模型上;
- 账号层也一样:积分快过期的账号先用,其余轮流,避免集中使用触发风控;
- 定时重新拉取,倍率一变自动重新分层,不用重启、不用改配置。
四条链
| 链 | 选择器里的名字 | 说明 |
|---|---|---|
| 免费 | shigege-Free points |
倍率 ≤ 免费判定线 |
| 低积分 | shigege-Low points |
倍率 ≤ 低积分倍率上界 |
| 高积分 | shigege-Premium points |
其余(超过 排除倍率高于 的不参与) |
| 自定义 | shigege-Custom |
你自己勾选的模型 |
三条价格链都要求 上下文 ≥ 1M;达不到的模型不进入任何一条。
排序规则:吞吐第一
四条链统一按实测吞吐(tokens/s)从大到小排序,调用时先试快的。
排序不是一个数字的降序,而是「吞吐分档 + 档内省钱」两层:
| 层 | 键 | 为什么 |
|---|---|---|
| 第一层 | 吞吐分档(档宽 吞吐分档档宽,默认 25 tok/s) |
快慢是用户第一体感,跨档时快的整档优先 |
| 第二层 | 到期优先 → 倍率 | 同档内快慢差不多,此时省钱、先用会作废的才是对的 |
| 兜底 | 模型 id | 保证比较器是全序,排序结果稳定可复现 |
没测过速度的模型不会被当成慢:它们排在「实测够快」之后、「实测偏慢」之前。把「没数据」当成「慢」会让新上架或刚重置的模型永远垫底,那是另一种不公平。
吞吐淘汰:低于线的不进组合
设置里的 吞吐淘汰线(默认 70 tok/s)是一道分层期的筛子:
- 实测吞吐低于它的模型,直接不出现在任何链里——等价于「取消选择」,但不改你的勾选清单;
- 没测过的模型不受影响(否则启动瞬间所有模型都会被清空);
- 它只淘汰确知慢的:探测超时、空响应、只思考不作答 —— 而 HTTP 4xx/5xx 这类「请求形状不对」不算慢,不会被淘汰(那是最危险的一类误伤);
- 已被请求期判慢的模型,只有
tps = 0且仍在慢记忆窗口内才会被淘汰。
被淘汰的名单在设置页「已淘汰(实测低于吞吐线)」里逐条列出,写明多少 tok/s。想找回它:调低淘汰线,或点「清除慢模型记忆」重测。
与「最低速度」的区别:「最低速度」是请求期判定(这一轮流得慢就换下一个);「吞吐淘汰线」是分层期判定(测出来慢就不许进链)。两项都要,缺一不可。
重测全部之后:自动收敛勾选
淘汰线只让慢模型不进链,不会改你的勾选清单。所以重测之后设置页仍可能显示 「勾了 60 个、实际只用 12 个」。从 0.2.3 起,一次完整的重测全部跑完之后会 顺手把四条链的勾选收敛到通过门槛的那批——勾选清单与实际在用的模型保持一致。
三条不变式:
- 没测出的模型一律保留。测速失败(超时、样本太短、HTTP 错误)不等于「它慢」, 只是这次没测到。把它们一起取消,一次网络抖动就能清空大半条链。
- 你手动改过的链不覆盖。只有当前是「跟随自动分层」的链会被收敛;你显式勾过 的清单是你的意图,不会被一次重测悄悄改掉。
- 门槛为 0 时什么都不做(等于关掉淘汰)。
被取消的模型不会从候选列表消失,随时可以手动勾回来;下次重测若它达标,也会自动回来。
为什么淘汰线是 70 而不是 85
85 曾是凭体感定的值。用真实数据模拟后发现它过度收缩候选池:95 个池内 模型只剩 14 个,free 链只有 2 个——没有冗余。
关键观察:被 85 砍掉的 45 个「速度中游」模型,错误率其实很低:
| 模型 | 吞吐 | 错误率 |
|---|---|---|
| trae/glm-5.2 | 84 | 24% |
| zcode/GLM-5.3-Flash | 82 | 21% |
| trae/glm-5.3-flash | 72 | 12% |
而保留名单里有 trae/Doubao-Seed-2.0-Code(95 tps / 错误率 45%)。
84 与 85 的差别几乎没有,12% 与 45% 的错误率差别巨大——用一条硬线卡速度,
反而把更可靠的模型挡在外面。
放宽到 70 之后候选池 14 → 25 个,free 链恢复冗余,而链首仍是 438 tps 的
lobsterai/deepseek-flash——因为「谁先上」由排序决定,淘汰线只负责
「谁根本不配进池」。
同时保留 最低速度 = 85(请求期门槛):进池宽、换人严是刻意的,
70–85 的模型可以当兜底,但不该抢在链首。
错误率淘汰(与速度并列的第二道筛子)
只看速度会漏掉一类模型:快,但一半以上的请求直接失败。本机 9 天账本里:
| 吞吐区间 | 模型数 | 错误率 |
|---|---|---|
| 0–85 tok/s | 52 | 54.4% |
| 85–200 tok/s | 34 | 53.7% |
| 200–400 tok/s | 10 | 2.5% |
| 400+ tok/s | 7 | 12.0% |
85 tok/s 的淘汰线在第二档上完全失效。所以新增按真实请求错误率淘汰:
- 数据来自渠道包的
token-ledger.json(真实流量,不是我们的探测); - 默认阈值 50%,最少 20 次请求才下判断(样本太少不判,防误伤新模型);
- 回看最近 7 天,避免很久以前的故障永久压着一个模型;
- 与速度门槛互相独立:把速度淘汰关成 0,错误率淘汰仍然生效。
读不到账本时这项自动跳过——它不会让插件依赖渠道包的文件。
快速档:快 + 不集中
如果永远从链首开始,用量全压在第一名上;如果整条链轮流,偶尔会轮到一个 8 tok/s 的模型,用户为「分散」付十几秒代价。
快速档大小(默认 3)把轮换限制在吞吐最高的前 N 个里:
- 档内轮流当链首 → 用量分散到几个模型上,但每个都是快的;
- 档外原样接在后面 → 档内全部失败时仍能降级,可用性不降;
1= 永远只用最快的那一个(最激进);大于候选数时按候选数截断。
设置页「快速档(参与轮换的模型)」把四条链各自的前 N 个连同吞吐列出来,可以核对「这次会轮到哪几个」。
账号:先用快到期的,再轮流
模型层的分散解决「不要总用一个模型」;账号层的分散解决「不要总用一个账号」——后者才是风控真正盯的东西。
渠道包选号用的是「账号数组里第一个可用账号」,所以要让规则生效只能改那个数组:
- 读出每个账号的积分包与扣费截止时间(
credits.balances); - 积分最快作废、且还有余额的账号排最前(越早作废越前)——不用就废了;
- 其余账号轮流当第一顺位(
accountRotation)——避免用量集中在最初那一个; - 用
account.reorder写回渠道包,此后每次请求(含它自己的换号重试)都按新顺序走。
几个刻意的取舍:
- 余额为 0 的账号不占「快到期」首位:它没有可浪费的额度,排前面只会让请求先失败一次;
- 查不到余额的账号夹在中间:既不当第一顺位,也不被永远压到最后;
- 重排是节流的(默认 10 分钟):
account.reorder要写渠道包的设置文件,每轮都写既无必要也让顺序不可观察; - 顺序没变就不写:避免日志被同一种顺序灌满。
失败(渠道包没装、RPC 不通、账号列表在读取期间变了)只记日志,不影响分层与调用——这是可选增强,不是依赖。
启动自动重测
每次启动软件后,等首次分层成功,5 秒后自动跑一次「重测全部」,这样吞吐排序与淘汰线当天就是新鲜的。
两道闸避免它变成风控流量:
- 跳过窗口(
启动重测的跳过窗口,默认 10 分钟):上一轮探测在窗口内完成过就不再测——反复开关软件不会反复全量探测,那才是会被看出规律的形态; - 只在分层成功之后启动,避免网关还没就绪时白测一堆超时。
探测本身已是「按渠道分组、单账号串行、200–500ms 抖动」,同一账号同时只有一个请求在飞。它还在后台跑,不影响任何一次对话的延迟。
安装
方式一:作为本地链接(推荐,改代码即时生效)
# 1) 把仓库放到任意位置,例如 ~/.dsh/local-plugins/
git clone <repo-url> ~/.dsh/local-plugins/dsh-baipiao-shigege
# 2) 在 profile 的 package.json 里加一条 link: 依赖
# 文件:~/.dsh/profiles/desktop/package.json
# "dependencies": { "dsh-baipiao-shigege": "link:../../local-plugins/dsh-baipiao-shigege" }
# 3) 把包名加进 bundles 列表(同一个 package.json)
# "dsh": { "profile": { "bundles": [ ..., "dsh-baipiao-shigege" ] } }
# 4) 让 pnpm 建好 node_modules 联接
cd ~/.dsh/profiles/desktop && pnpm install
# 5) 重启 DeepSeek Harness
方式二:直接放进 node_modules
git clone <repo-url> ~/.dsh/profiles/desktop/node_modules/dsh-baipiao-shigege
然后在 profile 的 package.json 里把 dsh-baipiao-shigege 加进 dsh.profile.bundles,重启 DSH。
⚠️ 不要写成
"dsh-baipiao-shigege": "file:./node_modules/dsh-baipiao-shigege"—— 这种自引用依赖在node_modules被清空后无法重新安装。
前置条件
需要一个兼容 OpenAI 协议的本地网关,能提供:
GET /v1/models:模型清单,展示名里带倍率(形如DeepSeek-V4.1-Flash · x0.11);POST /v1/chat/completions:流式对话。
默认指向 http://127.0.0.1:8326(渠道包自带的本地网关)。这不是硬依赖——把它改成任何兼容网关,插件照样工作。网关 Key 会依次从以下位置读取:
- 插件设置里的「网关 Key」;
~/.dsh/openai-gateway/api-key。
配置项
在 设置 → 白嫖-石哥哥,或左侧导航同名入口里调整,改完立即生效:
分层
| 项 | 默认 | 说明 |
|---|---|---|
| 渠道网关地址 | http://127.0.0.1:8326 |
不含 /v1 |
| 重新分层间隔 | 30 | 分钟;0 = 只在启动时拉一次 |
| 低积分倍率上界 | 0.3 | 超过此倍率归入「高积分」 |
| 1M 链上下文门槛 | 1000000 | 达不到的模型不进任何链 |
| 每条链候选上限 | 40 | |
| 单渠道候选上限 | 10 | trae 有 23 个 1M 候选,6 太紧;10 仍能限制单渠道占比 |
| 排除倍率高于 | 2 | 池内倍率 P50 0.51 / P90 1.4;5 相当于没设 |
速度与吞吐
| 项 | 默认 | 说明 |
|---|---|---|
| 按实测速度重排候选 | 开 | 关掉则回到按倍率排,链不会自我优化 |
| 按整轮吞吐排序 | 开 | 同档内的次要键 = 首字 + 生成量/吞吐 |
| 吞吐淘汰线 | 70 | tokens/s;实测低于它的模型不进任何链;「重测全部」跑完后四条链的勾选会自动收紧;没测过的不受影响,0 = 不淘汰 |
| 快速档大小 | 3 | 只有吞吐最高的前 N 个参与轮流调用;档外只兜底,1 = 永远只用最快的 |
| 吞吐分档档宽 | 25 | tokens/s;跨档按吞吐排、同档内按到期→倍率排;0 = 严格按吞吐降序 |
| 估算用的输出量 | 200 | token;真实输出 P50 只有 90、P75 是 159,800 会过度偏向高吞吐 |
| 首字等待上限 | 10000 | 毫秒;第一个字等超过就换下一个,0 = 一直等 |
| 首字慢于多少毫秒算「启动慢」 | 10000 | 首字慢的模型下轮排到链尾;与等待上限一致 |
| 最低速度 | 85 | tokens/s;请求期低于它就换下一个并沉到链尾。刻意高于淘汰线:进池宽、换人严 |
| 单次最多放弃几个慢模型 | 1 | 放弃一个要付一个完整的首字超时;1 = 只换一次,之后老实等 |
为什么按吞吐而不是只看首字:首字 1 秒但每秒 8 个 token 的模型,与首字 3 秒但每秒 120 个 token 的模型,后者在长回答里反而先写完。排序键用 首字 + 预期输出/吞吐,才对应你真实感知的「问完到写完」。
为什么淘汰线与最低速度要分开:前者决定「谁进链」,后者决定「这一轮要不要换人」。合成一项会让「只想排序、不删模型」没法表达。
测速与账号
| 项 | 默认 | 说明 |
|---|---|---|
| 重新分层时自动测速 | 关 | 开启后每点一次「立即重新分层」都会在后台补测全部模型 |
| 启动时自动重测全部 | 开 | 每次打开软件后跑一轮重测,让排序与淘汰线当天就是新鲜的 |
| 启动重测的跳过窗口 | 10 | 分钟;上一轮在此窗口内完成过就不重复测,0 = 每次都测 |
| 优先用快到期的账号 | 开 | 把积分最快作废的账号排到渠道包选号第一位 |
| 其余账号轮流使用 | 开 | 除到期账号外,其余账号轮流当第一顺位 |
| 账号顺序重排间隔 | 10 | 分钟;重排会写渠道包的设置文件,0 = 每轮都重排 |
「重新分层时自动测速」为什么默认关闭:一轮全量探测是对近百个模型各发一个请求。对上游平台来说,那是一串密集且规律的后台流量,是账号风控里最容易被判异常的类型。关掉不影响任何功能——链仍按已有画像排序,想测时点设置页的「测速」或「重测全部」即可。
「启动自动重测」为什么可以默认开着:它有跳过窗口兜底(反复开关软件不会反复全量探测),且探测本身是按渠道分组、单账号串行的(见下节)。这两条合起来才是「敢默认开」的理由。
调度方式:探测按渠道分组,同渠道串行、不同渠道并行。
风控真正在意的是「同一账号的并发突发」。如果让多个工人从全局队列随便取,相邻的往往是同一渠道的模型,同一个账号就会同时挨好几个请求。分组之后:
- 单账号同时只有 1 个探测请求在飞;
- 并行的渠道数不受影响,整体探测速度不降反升(实测耗时约为原来的 0.93×)。
此外每次探测请求之间加 200–500ms 随机抖动,避免精确等间隔这种机器人特征;连续触发还有 60 秒冷却,但「重测全部」按钮仍可立即执行。
账号维度:按到期优先 + 其余轮流 这两项会通过 credits.balances 读出每个账号的积分到期时间,再用 account.reorder 写回渠道包的选号顺序。细节见上文「账号:先用快到期的,再轮流」。任何一步失败都只降级,不影响分层与调用。
这些调整不影响任何一次对话的延迟:探测是独立的后台任务,与请求路径完全分离。它只决定「速度画像多久能测完」,不参与任何一次回答。
自定义链
| 项 | 默认 | 说明 |
|---|---|---|
| Custom 严格按勾选 | 关(跟随候选池) | 开启后链严格等于勾选清单;关闭则整个候选池都进链。你在 Custom 里动过任何复选框后会自动切到「严格」 |
勾选与取消立即保存,没有「保存」按钮。取消某个模型后它仍然留在候选列表里(只是复选框没勾),随时可以再勾回来。
链内搜索
四条链的候选加起来近百个,滚动找人很累。每个链卡片内都有一个搜索框:
- 输入任意片段即时筛选,匹配完整 id(含渠道前缀),所以
glm、trae/glm、trae都能命中; - 右侧
×清除搜索,恢复完整列表; - 有搜索词时,链首全选复选框的计数变成
已选/匹配数; - 搜索时的「全选 / 全不选」只作用于筛选结果——搜到 3 个点全选,只把这 3 个加入链,不会误伤其余模型;
- 没有匹配时给出明确提示,而不是留一片空白。
这条设计很关键:如果搜索时全选仍作用于整条链,用户搜到几个再点一下,会把整条链近百个全部选中——搜索反而变成事故。所以后端
/chain/all支持可选的ids参数,前端在搜索状态下只传筛选出的那几个。
全选 / 全不选
全选 = 下面列出的每一个都勾上;全不选 = 一个都不勾,没有任何例外。
这条看起来是废话,但实现里踩过两次坑,都是「显式勾选又被自动分层的筛子二次处理」:
| 筛子 | 默认行为 | 曾经的后果 |
|---|---|---|
每条链候选上限 / 单渠道候选上限 |
每条链 40、单渠道 10 | low 有 35 个候选,全选后链里只有 12 个 |
吞吐淘汰线 |
85 tok/s | custom 有 96 个候选,全选后链里只有 33 个 |
现在这两道筛子只作用于「你还没动过这条链」的自动分层。一旦你在复选框里勾过任何一项,本条链就严格按你的清单来:勾了就在,没勾就不在——只是排序仍按吞吐降序(先试哪个与要不要用它是两件事)。
对应的 viewState().members[key] 也改成了三态,页面因此能准确画出勾选状态:
| mode | 含义 | 勾选显示 |
|---|---|---|
all |
你还没动过这条链 | 全部候选都勾上 |
none |
你点了全不选 | 一个都不勾 |
explicit |
你勾过(含全选) | ids 里的那些 |
auto |
仅 Custom:跟随候选池 | 全部候选都勾上 |
Custom 的「全选」现在写显式全集(
explicit),不再切回auto。切回 auto 时customModels是空的,页面读出来是「勾选 0 个」——点了全选却显示一个都没勾。
数据与持久化
| 路径 | 内容 |
|---|---|
~/.dsh/dsh-baipiao-stone/settings.json |
你的设置与勾选 |
~/.dsh/dsh-baipiao-stone/speed-memory.json |
实测速度画像(重启不丢) |
~/.dsh/dsh-baipiao-stone/last-request.json |
上游 400/422 时的请求体转储,便于排查 |
目录名用的是插件早期名字
dsh-baipiao-stone。这是有意的:改名零功能收益,却有一次丢gatewayKey、自定义选择与速度画像的风险。
常见问题
设置页空白 / 表单项全没了?
插件 import('@deepseek-ai/schemastery') 失败时会静默降级为 Config = undefined,设置页表单随之消失,其余功能正常。若用 link: 方式安装,需保证权威副本能解析到 schemastery:
cd <插件目录> && node relink.mjs # 内置 fixPeerResolution 会建好联接
点了「立即重新分层」,顶部积分没变? 积分查询是异步的(逐个渠道串行,10–20 秒)。分层立即完成,积分随后回填,期间顶部显示「可用积分(更新中…)」。若长时间不消失,检查网关与渠道登录状态。
某个模型取消勾选后又回来了? 确认「Custom 严格按勾选」为开启状态。关闭时链会跟随整个候选池,取消动作不生效。
勾了的模型却不在链里? 看设置页「已淘汰(实测低于吞吐线)」。如果它在里面,说明实测吞吐低于淘汰线——把「吞吐淘汰线」调低,或点「清除慢模型记忆」让它重新测一次。这是设计如此,不是 bug。
链里只有几个模型在动,其他从没被用过?
这是「快速档」在起作用:快速档大小 默认 3,只有吞吐最高的前 3 个轮流当链首,其余只在前 3 个全失败时兜底。想覆盖更多模型就把它调大;想更极致地只用最快的就调成 1。
启动就自动测速,会不会被风控? 探测按渠道分组、单账号串行(同一账号同时只有 1 个请求在飞),带 200–500ms 抖动,且有「跳过窗口」——上一轮 10 分钟内测过就不再测。反复开关软件不会反复全量探测。真要更保守:把「启动时自动重测全部」关掉,改用设置页的手动按钮。
账号顺序自己在变?
其余账号轮流使用 每轮会把轮换起点前移一位,所以顺序会变——但快到期的那几个永远在最前面,变化只发生在「其余账号」内部。想固定顺序就把这项关掉。
链里的模型总是不回我的渠道? 检查「渠道网关地址」与 Key;插件只跟网关说话,不直接连各渠道。
开发
node --check index.js && node --check client.js # 语法门禁
node selftest.mjs # 自检
node tiercheck.mjs # 分层逻辑
node speedcheck.mjs # 速度门槛与慢模型降级
node rankcheck.mjs # 吞吐排序 / 淘汰 / 快速档 / 账号排序
node selectallcheck.mjs # 全选/全不选(需要网关在线)
node hostcheck.mjs # 宿主接口(需要网关在线)
测试不会碰你的真实数据:speedcheck.mjs 与 rankcheck.mjs 通过 testenv.mjs
把 DSH_HOME 指向一个临时目录,跑完即删。这一点是必须的——它们会调用
clearSlowModels(),而那个函数默认会落盘;早先没有隔离时,跑一次
node speedcheck.mjs 就会把你积累的速度画像与慢模型记忆整份清空。
tiercheck.mjs / selftest.mjs / hostcheck.mjs 需要连真实网关(读
~/.dsh/openai-gateway/api-key 与 127.0.0.1:8326),所以它们不加隔离。
结构:
| 文件 | 作用 |
|---|---|
index.js |
宿主半身:注册 llm provider、拉取分层、HTTP 设置接口、速度探测 |
client.js |
浏览器半身:设置页 + 左侧导航入口(手写 ModuleLoader bundle,无构建步骤) |
sse.js |
SSE 解码 |
cordis.patch.yml |
挂载行 |
许可
MIT
No comments yet. Be the first to write one.