Aa728848/dsh-llm-verifier ↗★ 15
dsh-llm-verifier
Configurable DSH-native LLM verifier with a Web settings page 适合需要对大模型输出进行自动验收、裁判评分和预算控制的用户。
同名パッケージの別リポジトリ
インストール
$
npx -p @deepseek-ai/dsh dsh plugin --profile web add github:Aa728848/dsh-llm-verifierドキュメント
README 全文を読む ↗安装与启用 (Installation & Usage)
1. 使用 dsh plugin 安装
DeepSeek Harness(DSH)通过 profile 独立管理各个运行环境的插件依赖。请使用 dsh plugin 命令将插件安装至目标 profile(如 web):
### 1. 使用 `dsh plugin` 安装
DeepSeek Harness(DSH)通过 profile 独立管理各个运行环境的插件依赖。请使用 `dsh plugin` 命令将插件安装至目标 profile(如 `web`):
```bash
### 2. 启动与配置
启动 DSH Web 客户端:
```bash
dsh web
## 配置项说明
在 DSH 中打开:`设置 → LLM Verifier`。
> [!NOTE]
> **设置页导航**:设置项按 8 个可折叠分区组织——工具 / 自动验收 / 自动路由 / 裁判模型 / 预算与限额 / 存储与观测 / 执行 / 费用估算,其中后四类默认收起(标题栏上有「高级」标记与当前取值摘要),另有「展开全部 / 收起全部」。左上角的「快速配置」下拉**显示当前生效的预设**(逐项改过任何策略类字段后显示「自定义」),选中即写入一组自洽的取值:「默认平衡」把策略类字段恢复为插件默认值并按当前裁判数写入安全的任务/会话调用预算,「严格验收」「省额度」「仅工具」各有取舍。预设只调整策略类字段,**不会**改动裁判模型、判据、存储与执行参数。逐项改动过的字段会标「已改」并出现「恢复默认」。数字项在输入时即时校验(越界、非整数、缓存目录越出话题目录、证据总预算放不下两个单项等),有问题的字段就地标红、保存按钮禁用,页脚常驻显示未保存状态与「跳到第一处问题」。
| 配置项 | 说明 |
|---|---|
| **启用工具 (Enabled)** | 是否允许显式工具与自动验收向裁判模型发起请求;关闭后显式调用立即报错且自动门控不运行 |
| **调用策略** | `manual` 仅显式调用;`smart` 结构化优先,并只在有候选/检查点线索时做高置信语义路由,达到工具证据门槛后最终验收;`strict` 每个结束边界都尝试语义路由,并对任一已完成关键操作最终验收,路由或验收异常时 fail closed(预算耗尽时只注入一次阻断提示,随后放行并在宿主日志告警,避免无出口的 steering 活锁) |
| **混合语义路由** | 结构化证据不足时,是否允许裁判模型保守分类 `compare/select/track/none`;不会生成新候选或编造检查点 |
| **语义路由置信度** | 语义识别达到该值才执行对应工具,默认 `0.9` |
| **最多候选数** | 自动 `select` 一次最多纳入的候选数,默认 `8` |
| **每任务/每会话最多路由** | 限制自动路由**周期**的次数:`compare/select/track`、语义分类、团队任务闸、计划预审与 P06 的过程选优周期(过程周期同样消耗本项额度,因此它受既有路由额度约束,另有自己的每任务 1 次上限)。**一次周期只消耗一次**——语义分类成立时会在同一个预约上直接提升为它解析出的 `compare/select/track`(分类+执行=1 次),因此默认 2 次足以完成「计划预审 → 分类+compare」;解析为 `none`、低置信、非法引用,或分类成功但执行预算不足时同样消费该周期(后者记录为 `classification-only-budget`,不会伪装成"未路由"或"已评审")。它与最终验收**各自独立计数**(路由用本项,最终验收用「每任务/每会话最多验收」,互不占用),因此被路由要求过的最终验收一定有额度可用;旧版共享一个计数器时,路由可以把最终验收的额度花光,导致 turn 在从未验收的情况下静默关闭。预算按真实对局数估算(8 候选约需 108 次调用);被拒绝时写入宿主日志并区分「预算不足 / 已有 verifier 在跑 / 同一证据已路由」,strict 下额外注入一次提示。每个周期还会在统计里留下一条 `route` 观测:周期 id、触发点、去向、预约调用数、证据保留/省略数与取消标记——它是诊断口径,**不是**模型调用数。分类去重按**渲染后的证据(提示词)**而非最后事件序号,追加纯叙述不会再次付费分类;周期 id 取 epoch+实例+序号,跨插件重载唯一,重载前后两个不同周期不会在看板与离线汇总里合并;没有预约的诊断行(预算丢弃、交付阶段跳过、证据读取失败 evidence-unreadable)共用同一套 epoch 命名空间 |
| **同时验收子 Agent** | 默认关闭;开启后 `subagent` / fork 子会话也会执行自动路由与最终验收 |
| **过程选优(受控)** | 默认**关闭**。开启后**仅 smart 模式**生效,且仅当同一任务最近两次已完成的验证运行**都失败**(「失败」从运行自己的判决读:`[exit code: N≠0]`、`N failed`、`error TS…`、`test result: FAILED`、`FAIL` 都算,工具级报错也算;`0 failed` 不算失败)时,为**下一次主模型请求**额外生成备选回复(默认 N=2:原回复=候选 0,新增一份=候选 1;`autoProcessCandidates` 可提到 3 或 4,那时按锦标赛判定;采样温度不低于生成档位,避免低温会话买到原回复的副本),按 **process 判据**(失败靶向 / 与已失败尝试不同 / 可验证的一步)比较后**只回放胜者**。每任务最多 1 个周期、**没有**独立的每会话过程上限——该周期与其它路由一样消耗「每任务/每会话最多路由」额度(因此同一会话的第二个任务仍可购买自己的周期),并受任务/会话模型调用预算与最终验收保留额度共同限制;生成与比较共用一个 `timeoutMs` 阶段截止时间。裁判视图里的任务、约束、最近失败证据与两份候选(含工具名与参数)**先脱敏再限长**,并按实际渲染文本计量总量,工具动作无法完整容纳时回退原回复。选优**不是**验收:胜者交给宿主后,最终验收照常覆盖随后产生的实际工作。关闭时完全不进入该路径(不生成候选、不调用裁判、不缓冲响应);manual/strict 不进入该路径 |
| **备选带上失败证据** | 默认**开启**,仅在过程选优启用时生效。把触发本周期的那两次失败验证运行(先 `sanitizeVerifierText` 脱敏,再按单项/总量双层限长,总量 4000 字符)作为一条插件 user 消息附在备选请求之后,让额外生成的候选是针对真实失败的一次不同尝试,而不是同一提示词的再抽样;关闭即对照组(两份候选掌握的信息完全相同,周期照买)。裁判**不被告知**哪份候选带了证据,避免按来源而不是按内容打分;统计行的 `route.alternativeAugmented` 记录该差异,供真实任务对照读取。 |
| **备选用另一个模型** | 默认留空:备选由当前会话模型再采样一份。填入 `provider/model`(例如 `deepseek-official/deepseek-v4-flash`)则改用该模型生成备选,候选之间因此是真正的不同假设;跨 provider 时**不继承**原请求的推理强度(适配器可能不认识该 id),`maxTokens` 与生成温度下限照旧,实际使用的路由记进 `route.alternativeModel`。代价是这次比较同时也在比「哪个模型更好」,与任务本身的质量不可分——所以它是实验臂,不是推荐配置。 |
| **过程选优候选数** | 默认 **2**(原回复 + 1 份备选,判一对)。设为 3 或 4 时按 `[原回复, 备选 1, …]` 跑锦标赛,判官调用随之上升(N=3 约 5 对,约为单对的 5 倍),预算从同一份任务/会话模型调用额度里出——预约用引擎自己的 `estimateRoutedCalls()` 估算对局数,不会和实际跑的对数脱节。完全相同的候选不会送给判官:引擎先去重,全部相同则 0 调用并回放原回复。**不采纳**上游「多数票直接返回未评判候选」的语义。 |
| **进度完成阈值** | `track` **最新**检查点低于该值时 steering 要求继续执行,否则改为"准备最终交付证据;最终会话验收是强制的"。默认 `0.684` = 判官标尺上 **N("偏成功")的起点**(进度分 = 字母序号 ÷ 19,N = 13/19 ≈ 68.4%),与提示词里"N–S = leans YES"的档位描述自洽;旧的 0.8 要求 Q 以上,等于"说得再肯定也不算过"。更早的检查点只随消息展示:每个任务的第一个检查点都是"刚写完计划",用"任一检查点低于阈值"判定会让继续分支恒真(实测 5/5)。**最新检查点达到阈值时还会置一个"下个边界直接进最终验收"的偏好**:steering 文案不变,但下一停止边界会跳过新的自动路由(不再为同一句提示重复购买 `track`);偏好由最终验收的预约消耗,验收失败后路由自动恢复 |
| **单项/总证据字符上限** | 自动候选与检查点脱敏后的单项、整次路由输入硬上限,默认 `20000 / 60000`;同时约束语义路由提示词的总长度(只保留预算内最新证据)。截断标记本身也计入上限,因此截断后的条目不会被判定为超限。候选与检查点都按**数量分摊**总字符预算(单项仍受 2 万字符上限),自动 `track` 还最多渲染**最近 6 个**检查点(更早的在首个检查点中注明已省略),因此 8 个长候选或几十个检查点都不会让整条决策被上限整条丢弃。语义路由提示词同样把候选/检查点先脱敏再按同一预算限长,并改用确定性分隔块;分类器只能引用本次实际渲染出的 ID,引用被预算省略的 ID 视为非法引用(strict 下按失败处理且不无限重试) |
| **任务/会话模型调用预算** | 分类、compare/select/track 与最终验收共享的估算请求预算,默认 `96 / 240`(按真实对局数估算:8 候选的完整锦标赛约 18 场对决 × 3 标准 = 54 次调用,再加最终验收 3 标准 × 2 轮 = 6 次;默认值因此给最终验收留出余量)。路由预约时还会为至少一次最终验收预留额度(判据数 × 最终轮次 × 裁判数):扣掉该额度后放不下的一条路由会被直接拒绝,避免"先承诺强制验收、再无钱执行"。统计看板另报告**可观测用量**:请求在返回 usage 前失败时该次调用标记 `usageIncomplete`(尝试次数仍计入 `attempts`,token 记为未知而不是 0),直接 logprob 通道被 provider 拒绝后回退到显式标签时计入 `channelFallbacks`;失败行还保留**失败前已成功与已在途的用量**:引擎在 job/repeat 的 worker 里累计、首个失败后停止发起新调用但等待在途请求落地,再连同"已计费但不可用"的响应(截断、解析失败、空文本——compare 与 track 同样处理)与取消请求的尝试数、重试数、已知 token 的费用一并记账,因此"2 次成功 + 1 次失败"记的是 2 次调用与已知 token,而不是 1 次、0 token。用量载体在读取入口统一补成完整 `RunStats`(缺失计数补 0,绝不出 `NaN`/`null`);每个被取消的请求抛**自己的**错误对象(不再注解共享的 `signal.reason`),并发取消不会重复合并累计;重试成功后会把此前失败尝试**已返回的 token** 加回去、只在 token 未知时标 `usageIncomplete`;`verifier_best_of_n` 的生成、排序与基线三个阶段共用一个累计,任一阶段失败都带走此前用量。失败行读到的 partial **已写回计价结果**(`partialStats` 返回副本,`mapLimited` 会 `attachUsage` 回去),因此已知费用的行不再回退为 0;重试链在**成功、最终失败与取消**三种出口都携带此前已返回的 token 与整条链的 attempts/retries,只在有尝试的 token 未知时才标 `usageIncomplete`;best-of-n 的失败草稿保留 `requestAttempts`,幸存草稿用 `mergeRunStats` 传播 `usageIncomplete` |
| **通过阈值** | 自动会话验收要求证据分数达到阈值、胜过“未执行有效工作”基线,**且每一项标准各自也达到阈值**(均值会把某一项彻底失败平均掉:3 项中 1 项 0 分、2 项满分时均分 0.67 仍会越过 0.65) |
| **验收判据 (Rubric)** | 自动门控(最终验收、自动 compare/select/track)与未显式传 `criteria` 的工具使用的评分标准。内置 5 套:`coding`(默认,与历史内置判据**逐字相同**)、`debug`、`research`、`ops`、`writing`,每套 2–4 条窄判据。切换会同时改变验收松紧与提示词(缓存键随之失效,属预期);设置页可展开**预览**判官实际收到的提示词 |
| **判据文件 (Criteria file)** | `criteriaPreset = custom` 时读取的 Markdown 判据文件路径。格式:`## Ground Truth Note`(可选)+ `## Criteria` 下每个 `### 判据名`(可用 `{#id}` 锚定 id,否则由名称 slug 化)。文件缺失或解析失败时**退回 `coding` 判据**并在日志告警,不会让门控失效;判据文件在每次解析边界重新读取,编辑后立即生效 |
| **路由评估轮次** | 自动路由每个标准的重复轮次;默认 1。`compare` 只判一对,会被**向上取整到偶数**(引擎只在奇数轮交换 A/B 位置,奇数轮等于让第一个候选固定坐在 A 位);`select` 的 ring 天然对称、pivot 轮的 A/B 槽位由引擎逐对平衡,两者都保留配置值——不对症的偏差不付双倍调用 |
| **进度跟踪轮次** | 自动 `track` 单独的重复轮次并**取平均**,默认 `3`。判官模型不返回 logprobs 时,进度分来自显式标签通道——每次调用只采到**一个字母**(A–T 每档 5.3%),单次采样足以在相邻档位之间抖动;重复取平均即上游 `n_evaluations` 的做法。`track` 是最便宜的一类调用(一次请求、无锦标赛),因此默认值比路由轮次高 |
| **保存决策快照** | 默认开启:把每次裁判调用的**脱敏提示词 + 原始回答**限量写入本话题的 `verifier/decisions-v1.json`(每次调用最多 12 次模型调用;单条记录 ≤ 3 万字符,且**按调用数平均分配**——6 次调用的会话验收会把 6 条全部留下并各自缩窗,而不是只留下最先返回的 3 条;每话题保留最近 40 条),统计看板的「最近调用」里可逐条展开查看。它只回答"裁判为什么这么判",不参与任何判定;命中评分缓存或复用 in-flight 调用时不会伪造快照 |
| **最终验收轮次** | 最终会话验收每个标准的重复轮次,默认 `2`:奇数轮不交换、偶数轮交换 A/B 位置,因此默认配置下位置偏好被抵消。调低到 1 会省一次调用,但会失去这层保护 |
| **智能模式最少工具调用** | `smart` 策略需要的最少非 Verifier 工具调用数 |
| **最大证据字符** | 自动发送给裁判的最近会话轨迹字符上限 |
| **每任务/每会话最多验收** | 防止低分反馈形成无限修复循环并限制成本 |
| **供应商 (Provider)** | 从 DSH 当前已配置且可路由的 Provider 列表中选择 |
| **模型 (Model)** | 从所选 Provider 的模型目录中指定具体裁判模型 |
| **裁判标签 (Label)** | 主裁判在工具返回的 `judges[].label` 中显示的名称,留空则使用模型名 |
| **附加裁判 (Extra judges)** | 在主裁判之外追加最多 4 个裁判模型(各自可指定 Provider / Model / 推理强度 / 显示名),同一 Provider + Model 不允许重复;留空即为单裁判模式,行为与旧版本逐位一致 |
| **推理强度 (Reasoning Effort)** | 使用 Adapter 为该模型声明的思考强度,或保留模型默认值 |
| **最大输出 Token** | 单次裁判请求的输出 Token 上限 |
| **判官温度 (Temperature)** | 判官采样的温度,范围 0–2,默认 **0.2**(旧版固定为 1)。自动路由默认只跑 1 轮、最终验收默认 2 轮(偶数轮交换 A/B 位置),温度越低判决越可复现;部分推理模型只接受默认温度,遇到适配器报错时改回 1 |
| **最大并发数** | 所有 Verifier 调用共享的全局并发请求限制 |
| **最大重试次数** | 遇到偶发网络或服务短暂故障时的额外重试次数 |
| **请求超时 (ms)** | 单次模型调用的毫秒级超时时间 |
| **缓存条目上限** | 成功评分持久化缓存的最大容量条目数 |
| **重试基础延迟 (ms)** | 重试时指数退避的基数,默认 500 |
| **缓存目录 (Cache directory)** | 评分缓存 / 能力记忆 / 统计文件在话题目录下的相对子目录,默认 `verifier`;留空保存时保留原值 |
| **输入 / 输出价格** | 手填的 USD/百万 token 单价。**留 0 即交给自动定价**;一旦填了任意一个,整组就以手填为准 |
| **缓存读取价格** | 缓存命中输入 token 的单价;留 0 时退回按输入价计算(旧口径,会把缓存密集的调用算贵)。真实的 cache-read 单价常是输入价的 1/50 |
| **本机模型目录自动定价** | 默认开。本机安装的 pi-ai 模型目录(models.dev 快照,`@earendil-works/pi-ai/dist/providers/data`,约 1350 条)里有这条 provider+模型时自动取单价,**纯离线、零配置** |
| **在线价格库兜底** | 默认开。本机目录查不到时向 models.dev 查一次(4.6 MB 快照,进程内缓存 24 小时),手填或目录命中时**完全不联网** |
| **价格来源 Provider** | 转售路由(例如 command-code)两张表都没有时的显式出路:填一个 provider id(例如 openrouter),按它的挂牌价折算。**留空=不猜**,未定价路由的成本记为 0 |
> [!NOTE]
> **显式证据的总量上限**:一次显式工具调用的全部证据(脱敏并单项截断后)合计不得超过 **「自动路由证据总字符上限」的 2 倍**,且绝不突破 **24 万字符** 的硬上限——默认即 12 万字符(约 3 万 token),超出会直接报错并给出实际字符数。这是为了在判官请求顶爆模型上下文之前就把问题挡住。单项上限仍为 2 万字符,`verifier_select` 最多 16 个候选(16 × 2 万已超过默认预算,需要精简候选)。
> [!NOTE]
> **多模态与图片支持**:若选定的裁判模型不支持图像输入,传入图片时将由对应 DSH Adapter 明确报错拦截,插件绝不会静默丢弃图片证据。