dsh-llm-verifier 0.1.16 → 0.1.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +62 -9
- package/lib/{caller-BWwSVNZf.js → caller-DJd_FlrQ.js} +118 -60
- package/lib/caller-DJd_FlrQ.js.map +1 -0
- package/lib/caller.js +1 -1
- package/lib/client.js +738 -82
- package/lib/client.js.map +1 -1
- package/lib/core.js +51 -7
- package/lib/core.js.map +1 -1
- package/lib/index.js +1258 -425
- package/lib/index.js.map +1 -1
- package/lib/types/auto.d.ts +23 -0
- package/lib/types/auto.d.ts.map +1 -1
- package/lib/types/auto.js +105 -22
- package/lib/types/auto.js.map +1 -1
- package/lib/types/cache.d.ts +1 -0
- package/lib/types/cache.d.ts.map +1 -1
- package/lib/types/cache.js +20 -10
- package/lib/types/cache.js.map +1 -1
- package/lib/types/caller.d.ts +3 -0
- package/lib/types/caller.d.ts.map +1 -1
- package/lib/types/caller.js +79 -36
- package/lib/types/caller.js.map +1 -1
- package/lib/types/client-i18n.d.ts +159 -0
- package/lib/types/client-i18n.d.ts.map +1 -1
- package/lib/types/client-i18n.js +151 -1
- package/lib/types/client-i18n.js.map +1 -1
- package/lib/types/client-judges.d.ts +20 -0
- package/lib/types/client-judges.d.ts.map +1 -0
- package/lib/types/client-judges.js +109 -0
- package/lib/types/client-judges.js.map +1 -0
- package/lib/types/client.d.ts +76 -2
- package/lib/types/client.d.ts.map +1 -1
- package/lib/types/client.js +128 -25
- package/lib/types/client.js.map +1 -1
- package/lib/types/config.d.ts +23 -0
- package/lib/types/config.d.ts.map +1 -1
- package/lib/types/config.js +119 -5
- package/lib/types/config.js.map +1 -1
- package/lib/types/core.d.ts +25 -0
- package/lib/types/core.d.ts.map +1 -1
- package/lib/types/core.js +65 -6
- package/lib/types/core.js.map +1 -1
- package/lib/types/engine.d.ts +19 -1
- package/lib/types/engine.d.ts.map +1 -1
- package/lib/types/engine.js +315 -29
- package/lib/types/engine.js.map +1 -1
- package/lib/types/images.d.ts +13 -0
- package/lib/types/images.d.ts.map +1 -1
- package/lib/types/images.js +48 -1
- package/lib/types/images.js.map +1 -1
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/index.js +185 -50
- package/lib/types/index.js.map +1 -1
- package/lib/types/plan-gate.d.ts.map +1 -1
- package/lib/types/plan-gate.js +8 -2
- package/lib/types/plan-gate.js.map +1 -1
- package/lib/types/router.d.ts +42 -3
- package/lib/types/router.d.ts.map +1 -1
- package/lib/types/router.js +158 -13
- package/lib/types/router.js.map +1 -1
- package/lib/types/session.d.ts.map +1 -1
- package/lib/types/session.js +19 -2
- package/lib/types/session.js.map +1 -1
- package/lib/types/statistics.d.ts +19 -1
- package/lib/types/statistics.d.ts.map +1 -1
- package/lib/types/statistics.js +85 -10
- package/lib/types/statistics.js.map +1 -1
- package/lib/types/team-gate.d.ts +1 -0
- package/lib/types/team-gate.d.ts.map +1 -1
- package/lib/types/team-gate.js +15 -4
- package/lib/types/team-gate.js.map +1 -1
- package/lib/types/top-logprobs.d.ts +11 -1
- package/lib/types/top-logprobs.d.ts.map +1 -1
- package/lib/types/top-logprobs.js +35 -6
- package/lib/types/top-logprobs.js.map +1 -1
- package/package.json +1 -1
- package/src/auto.test.ts +55 -8
- package/src/auto.ts +101 -21
- package/src/cache.test.ts +133 -0
- package/src/cache.ts +19 -8
- package/src/caller.test.ts +214 -3
- package/src/caller.ts +81 -33
- package/src/client-i18n.ts +193 -1
- package/src/client-judges.ts +121 -0
- package/src/client.test.ts +433 -0
- package/src/client.tsx +206 -36
- package/src/config.test.ts +410 -0
- package/src/config.ts +158 -5
- package/src/core.test.ts +76 -0
- package/src/core.ts +68 -6
- package/src/engine.test.ts +427 -1
- package/src/engine.ts +419 -34
- package/src/images.test.ts +40 -0
- package/src/images.ts +44 -1
- package/src/index.test.ts +74 -0
- package/src/index.ts +172 -50
- package/src/parity.test.ts +9 -1
- package/src/plan-gate.test.ts +28 -0
- package/src/plan-gate.ts +8 -2
- package/src/router.test.ts +98 -1
- package/src/router.ts +147 -14
- package/src/session.test.ts +38 -0
- package/src/session.ts +16 -2
- package/src/statistics.test.ts +314 -3
- package/src/statistics.ts +93 -9
- package/src/team-gate.test.ts +70 -1
- package/src/team-gate.ts +17 -4
- package/src/top-logprobs.test.ts +63 -2
- package/src/top-logprobs.ts +23 -6
- package/lib/caller-BWwSVNZf.js.map +0 -1
package/README.md
CHANGED
|
@@ -106,7 +106,24 @@ pnpm run typecheck:local # 依据 tsconfig.local.json,把 @deepseek-ai/dsh-*
|
|
|
106
106
|
|
|
107
107
|
- **上游项目**:[llm-as-a-verifier/llm-as-a-verifier](https://github.com/llm-as-a-verifier/llm-as-a-verifier)
|
|
108
108
|
|
|
109
|
-
本插件将上游算法完整移植为 TypeScript 实现,并深度集成了 DSH 的模型路由、设置面板、附件管理、会话日志与工具生态。上游实现作为本插件的算法基准;本仓库内置了 Python / TypeScript 一致性测试(Parity Tests),确保核心评分与锦标赛赛制(Tournament Fixture
|
|
109
|
+
本插件将上游算法完整移植为 TypeScript 实现,并深度集成了 DSH 的模型路由、设置面板、附件管理、会话日志与工具生态。上游实现作为本插件的算法基准;本仓库内置了 Python / TypeScript 一致性测试(Parity Tests),确保核心评分与锦标赛赛制(Tournament Fixture)的跨语言逻辑一致——**唯一的例外见下节**。
|
|
110
|
+
|
|
111
|
+
## 与上游的一处已知差异
|
|
112
|
+
|
|
113
|
+
概率期望评分中,同一字母可能对应多个 token 表面形式(受约束解码同时提供 `"A"` 与 `" A"`,二者都表示字母 A)。它们是同一次采样的互斥结果,因此本插件把它们**相加**得到该字母的概率;上游 Python 参考实现则保留其中较大的那个:
|
|
114
|
+
|
|
115
|
+
```python
|
|
116
|
+
# llm_verifier/fine_grained_reward.py:678
|
|
117
|
+
# 核对基准:上游 main @ 8db8a114355a9d7fdf9a8d1d5c87f6aeebd18770(pyproject version 0.2.0)
|
|
118
|
+
probs[val] = max(probs.get(val, 0.0), p)
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
`max` 会系统性低估"概率质量被拆到两种写法上"的字母(例:`" A"=0.4, "A"=0.4, " T"=0.5, "T"=0.1` 时,求和得 ≈0.5714,取最大值只有 ≈0.4444,足以跨过通过阈值),因此这里选择求和。**这是本插件唯一一处刻意的评分语义偏离**:
|
|
122
|
+
|
|
123
|
+
- 仅影响概率期望通道(`top_logprobs`);显式标签通道、A–T 标尺、进度判定与锦标赛赛制均与上游一致;
|
|
124
|
+
- 只有判官确实把同一字母的质量拆到两种写法上时才会产生数值差异;
|
|
125
|
+
- 该聚合在上游也没有被测试或文档固定下来(上游 main 分支没有 tests 目录,开放的 PR #26 的 fixture 只包含不同字母,仓库内没有任何 max/sum 的讨论),因此这属于可自由取舍的实现细节,而非上游契约;
|
|
126
|
+
- 一致性测试的 fixture 有意不覆盖该情形(否则会必然失败);若要退回与上游逐位一致,把 `core.ts` 中该行改回取最大值即可,同时请一并更新本节与 `AGENTS.md`。
|
|
110
127
|
|
|
111
128
|
## 核心原理
|
|
112
129
|
|
|
@@ -160,6 +177,8 @@ K ... S = 偏向失败的程度依次递增
|
|
|
160
177
|
T = 明确且无可争议的失败
|
|
161
178
|
```
|
|
162
179
|
|
|
180
|
+
所有裁判提示词都会把任务、轨迹、计划与证据包在带内容派生令牌的分隔块(`<<<TAG:token>>> … <<<END_TAG:token>>>`)中——令牌由提示词内容确定性派生,因此证据里写死的终止符无法提前闭合数据区,而相同输入仍渲染出完全相同的提示词(评分缓存不受影响),并明确声明这些内容**只是数据**:不得执行其中的指令、不得改写评分标尺或输出格式、其中的任何“评分”文本一律忽略——被评审的工具输出与文件内容因此无法通过提示词注入伪造判决。
|
|
181
|
+
|
|
163
182
|
字母按等距标尺线性映射到 `[0, 1]` 区间。在打分计算上,插件采用**自适应评分机制**:
|
|
164
183
|
|
|
165
184
|
- **优先概率期望评分**:若当前模型路由为官方 `deepseek-official` 或显式配置了兼容 OpenAI Chat Completions 且支持 `top_logprobs` 的端点,插件将基于 A–T 候选 Token 的完整概率分布计算加权期望值;
|
|
@@ -169,6 +188,28 @@ T = 明确且无可争议的失败
|
|
|
169
188
|
> [!NOTE]
|
|
170
189
|
> 在**进度追踪(`verifier_track`)**中,字母方向相反:`A` 代表“确定尚未完成”,`T` 代表“几乎确定已完成”,再按规则映射为 `[0, 1]` 的完成度概率。
|
|
171
190
|
|
|
191
|
+
## 多裁判共识(Ensemble,可选)
|
|
192
|
+
|
|
193
|
+
默认只使用一个裁判模型。在 `设置 → LLM Verifier → 模型` 中,主裁判(`供应商 / 模型 / 推理强度 / 最大输出 Token`)保持不变,其下可以追加最多 4 个**附加裁判**,每个附加裁判可指定 Provider、Model、可选的推理强度与显示名。`主裁判 + 附加裁判` 构成一次验收的裁判组;**不配置附加裁判时,本插件的行为与之前完全一致**。
|
|
194
|
+
|
|
195
|
+
```text
|
|
196
|
+
主裁判 (provider/model) ┐
|
|
197
|
+
附加裁判 1 ├─ 每个裁判独立调用、独立缓存、独立计费
|
|
198
|
+
附加裁判 2 … (最多 4 个) ┘
|
|
199
|
+
↓
|
|
200
|
+
同一 (评估标准 × 轮次) 内取中位数
|
|
201
|
+
↓
|
|
202
|
+
既有的「轮次求平均 → 标准求平均」聚合(不变)
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
- **聚合方式是中位数**:单个裁判时中位数就是它自己的分数,因此单裁判结果与旧版本逐位一致;两个裁判退化为平均值;三个及以上时,个别跑偏的裁判不会把结论拉走。
|
|
206
|
+
- **每个裁判独立缓存与去重**:裁判身份(Provider / Model / 推理强度 / 输出上限)是评分缓存键的一部分,不同裁判既不会读到对方的缓存,也不会被合并成一次调用。
|
|
207
|
+
- **判决透明**:四个工具(`verifier_compare` / `verifier_select` / `verifier_track` / `verifier_current_session`)的返回都新增 `judges` 数组,逐裁判给出 Provider、Model、显示名、是否成功、实际调用次数,以及该裁判自己的分数 / 排名 / 检查点分数;`verifier_compare` 与 `verifier_current_session` 还返回 `agreement`(与最终胜负一致的裁判比例,单裁判恒为 1)。
|
|
208
|
+
- **降级而不是整体失败**:个别裁判偶发失败(网络、限流、解析不出判决)时会被排除在该次聚合之外,并在 `judges[].ok=false` 与 `judges[].error` 中如实报告;只有当**整组裁判**都给不出判决时,这次验收才失败。
|
|
209
|
+
- **预算按裁判数放大**:自动路由的模型调用预算按 `对局数 × 裁判数` 预留,多裁判场景请相应调大「任务/会话模型调用预算」(默认 64 / 240)。
|
|
210
|
+
- **分类只走主裁判**:混合语义路由的分类请求是轻量路由动作而非判决,只使用主裁判,不随裁判数放大。
|
|
211
|
+
- **统计归属**:统计与费用按「一次验收」记账,多裁判的 token 与费用合计计入该次调用,模型维度归属主裁判;单个裁判的实际调用次数见工具返回中的 `judges[].calls`。
|
|
212
|
+
|
|
172
213
|
## 多候选方案:为什么不采用全量两两比对?
|
|
173
214
|
|
|
174
215
|
对 $N$ 个候选方案进行全量比对(All-Pairs Tournament)需要进行约 $\frac{N(N - 1)}{2}$ 场对决,API 调用量呈二次方($O(N^2)$)爆炸式增长。
|
|
@@ -194,14 +235,15 @@ flowchart LR
|
|
|
194
235
|
| 配置项 | 说明 |
|
|
195
236
|
|---|---|
|
|
196
237
|
| **启用工具 (Enabled)** | 是否允许显式工具与自动验收向裁判模型发起请求;关闭后显式调用立即报错且自动门控不运行 |
|
|
197
|
-
| **调用策略** | `manual` 仅显式调用;`smart` 结构化优先,并只在有候选/检查点线索时做高置信语义路由,达到工具证据门槛后最终验收;`strict` 每个结束边界都尝试语义路由,并对任一已完成关键操作最终验收,路由或验收异常时 fail closed |
|
|
238
|
+
| **调用策略** | `manual` 仅显式调用;`smart` 结构化优先,并只在有候选/检查点线索时做高置信语义路由,达到工具证据门槛后最终验收;`strict` 每个结束边界都尝试语义路由,并对任一已完成关键操作最终验收,路由或验收异常时 fail closed(预算耗尽时只注入一次阻断提示,随后放行并在宿主日志告警,避免无出口的 steering 活锁) |
|
|
198
239
|
| **混合语义路由** | 结构化证据不足时,是否允许裁判模型保守分类 `compare/select/track/none`;不会生成新候选或编造检查点 |
|
|
199
240
|
| **语义路由置信度** | 语义识别达到该值才执行对应工具,默认 `0.9` |
|
|
200
241
|
| **最多候选数** | 自动 `select` 一次最多纳入的候选数,默认 `8` |
|
|
201
|
-
| **每任务/每会话最多路由** | 独立于最终验收预算,限制 `compare/select/track`
|
|
242
|
+
| **每任务/每会话最多路由** | 独立于最终验收预算,限制 `compare/select/track` 及语义分类的自动次数;预算按真实对局数估算(8 候选约需 54 次调用),被拒绝时写入宿主日志,strict 下额外注入一次提示 |
|
|
243
|
+
| **同时验收子 Agent** | 默认关闭;开启后 `subagent` / fork 子会话也会执行自动路由与最终验收 |
|
|
202
244
|
| **进度完成阈值** | `track` 任一检查点低于该值时 steering 要求继续工作,默认 `0.8` |
|
|
203
|
-
| **单项/总证据字符上限** | 自动候选与检查点脱敏后的单项、整次路由输入硬上限,默认 `20000 / 60000
|
|
204
|
-
| **任务/会话模型调用预算** | 分类、compare/select/track 与最终验收共享的估算请求预算,默认 `
|
|
245
|
+
| **单项/总证据字符上限** | 自动候选与检查点脱敏后的单项、整次路由输入硬上限,默认 `20000 / 60000`;同时约束语义路由提示词的总长度(只保留预算内最新证据)。截断标记本身也计入上限,因此截断后的条目不会被判定为超限 |
|
|
246
|
+
| **任务/会话模型调用预算** | 分类、compare/select/track 与最终验收共享的估算请求预算,默认 `64 / 240`(按真实对局数估算:8 候选的完整锦标赛约 18 场对决 × 3 标准 = 54 次调用) |
|
|
205
247
|
| **通过阈值** | 自动会话验收要求证据分数达到阈值且胜过“未执行有效工作”基线 |
|
|
206
248
|
| **自动评估轮次** | 自动验收每个标准的重复轮次;默认 1,作为低成本初筛 |
|
|
207
249
|
| **智能模式最少工具调用** | `smart` 策略需要的最少非 Verifier 工具调用数 |
|
|
@@ -209,14 +251,22 @@ flowchart LR
|
|
|
209
251
|
| **每任务/每会话最多验收** | 防止低分反馈形成无限修复循环并限制成本 |
|
|
210
252
|
| **供应商 (Provider)** | 从 DSH 当前已配置且可路由的 Provider 列表中选择 |
|
|
211
253
|
| **模型 (Model)** | 从所选 Provider 的模型目录中指定具体裁判模型 |
|
|
254
|
+
| **裁判标签 (Label)** | 主裁判在工具返回的 `judges[].label` 中显示的名称,留空则使用模型名 |
|
|
255
|
+
| **附加裁判 (Extra judges)** | 在主裁判之外追加最多 4 个裁判模型(各自可指定 Provider / Model / 推理强度 / 显示名),同一 Provider + Model 不允许重复;留空即为单裁判模式,行为与旧版本逐位一致 |
|
|
212
256
|
| **推理强度 (Reasoning Effort)** | 使用 Adapter 为该模型声明的思考强度,或保留模型默认值 |
|
|
213
257
|
| **最大输出 Token** | 单次裁判请求的输出 Token 上限 |
|
|
258
|
+
| **判官温度 (Temperature)** | 判官采样的温度,范围 0–2,默认 **0.2**(旧版固定为 1)。自动验收默认只跑 1 轮,温度越低判决越可复现;部分推理模型只接受默认温度,遇到适配器报错时改回 1 |
|
|
214
259
|
| **最大并发数** | 所有 Verifier 调用共享的全局并发请求限制 |
|
|
215
260
|
| **最大重试次数** | 遇到偶发网络或服务短暂故障时的额外重试次数 |
|
|
216
261
|
| **请求超时 (ms)** | 单次模型调用的毫秒级超时时间 |
|
|
217
262
|
| **缓存条目上限** | 成功评分持久化缓存的最大容量条目数 |
|
|
263
|
+
| **重试基础延迟 (ms)** | 重试时指数退避的基数,默认 500 |
|
|
264
|
+
| **缓存目录 (Cache directory)** | 评分缓存 / 能力记忆 / 统计文件在话题目录下的相对子目录,默认 `verifier`;留空保存时保留原值 |
|
|
218
265
|
| **输入/输出价格** | 仅用于本地估算单次裁判产生的费用(`estimatedCostUsd`) |
|
|
219
266
|
|
|
267
|
+
> [!NOTE]
|
|
268
|
+
> **显式证据的总量上限**:一次显式工具调用的全部证据(脱敏并单项截断后)合计不得超过 **「自动路由证据总字符上限」的 2 倍**,且绝不突破 **24 万字符** 的硬上限——默认即 12 万字符(约 3 万 token),超出会直接报错并给出实际字符数。这是为了在判官请求顶爆模型上下文之前就把问题挡住。单项上限仍为 2 万字符,`verifier_select` 最多 16 个候选(16 × 2 万已超过默认预算,需要精简候选)。
|
|
269
|
+
|
|
220
270
|
> [!NOTE]
|
|
221
271
|
> **多模态与图片支持**:若选定的裁判模型不支持图像输入,传入图片时将由对应 DSH Adapter 明确报错拦截,插件绝不会静默丢弃图片证据。
|
|
222
272
|
|
|
@@ -250,7 +300,8 @@ flowchart LR
|
|
|
250
300
|
}
|
|
251
301
|
```
|
|
252
302
|
|
|
253
|
-
- 同一任务内至少两个内容或状态发生真实变化的 `todo/write`
|
|
303
|
+
- 同一任务内至少两个内容或状态发生真实变化的 `todo/write` 快照形成进度检查点;完全相同的重复快照会被折叠;
|
|
304
|
+
- 每个进度检查点都会附带**该时刻之前最近一次成功工具输出**(`tool/result` / `tool/ptc-dispatch` 原文,脱敏并限长)。只有 todo 文本的检查点无法证明"已完成",裁判提示词明确拒绝给无实测输出的状态打高分,因此证据随检查点一同送入——否则一个真正完成的任务也会稳定被打回继续工作。
|
|
254
305
|
|
|
255
306
|
显式调用过对应的 `verifier_compare`、`verifier_select` 或 `verifier_track` 后,自动 Router 不会再对同类结构化对象重复执行。每个输入还会计算稳定指纹,同一证据不会重复消费预算。
|
|
256
307
|
|
|
@@ -262,7 +313,9 @@ flowchart LR
|
|
|
262
313
|
- `strict`:每个准备结束边界都分类,无法确认时返回 `none`;路由调用失败时注入 steering,阻止静默跳过;
|
|
263
314
|
- `manual`:结构化与语义自动路由、最终自动验收都关闭,四个工具仍可显式调用。
|
|
264
315
|
|
|
265
|
-
候选选择产生 steering 后,Agent 必须实施胜出候选;进度未达阈值也会 steering 继续。任何自动 `compare/select/track` 成功都会设置 `finalVerificationRequired`,下一停止边界即使没有传统写入类工具也必须执行 `verifier_current_session
|
|
316
|
+
候选选择产生 steering 后,Agent 必须实施胜出候选;进度未达阈值也会 steering 继续。任何自动 `compare/select/track` 成功都会设置 `finalVerificationRequired`,下一停止边界即使没有传统写入类工具也必须执行 `verifier_current_session`;只有针对最新快照且达到阈值的最终验收才能清除要求(计划预审通过**不会**设置该标记:批准计划不等于完成工作)。路由采用 reservation/commit/fail 状态,取消、过期或失败不会被误记为成功;strict 会维持阻断并 fail closed。
|
|
317
|
+
|
|
318
|
+
显式调用 `verifier_current_session` **不会**无条件关闭自动门控:只有该次复核真的达到通过阈值(`winner === 'A'` 且分数不低于阈值),并且之后没有再产生实质工作(写文件、执行命令等)时,才会被当作"已完成验收"而放行。判决失败、低于阈值、结果无法解析、或通过之后又继续改动的复核,都不会解除门控——下一停止边界仍会照常验收。此外,Agent Teams 的队友会话以 `team-message` 作为任务边界,因此队友会话同样可以触发(并遵守)任务级门控。
|
|
266
319
|
|
|
267
320
|
所有自动阶段共享任务/会话级模型调用预算;分类请求以 `verifier_route_classify` 单独记录到统计。候选、步骤和标签在发送前统一执行默认脱敏、单项字符上限和总字符上限,图片证据按与显式工具相同的路径传入。
|
|
268
321
|
|
|
@@ -271,7 +324,7 @@ flowchart LR
|
|
|
271
324
|
- **按话题持久化**:成功评分缓存与调用统计写入当前 DSH 话题的持久化目录(`~/.dsh/sessions/<workspace>/<session-id>/verifier/`)。不同话题相互隔离;永久删除话题时,该目录会随会话日志一并删除,不再在桌面或项目工作目录生成 `.dsh-verifier-cache`。
|
|
272
325
|
- **持久化缓存**:成功的评分结果将基于 SHA-256 哈希值进行持久化缓存。Key 的计算维度包含:完整渲染后的裁判提示词(涵盖任务描述、候选内容、评审标准与提示词模板本身)、评分通道(概率期望 / 显式标签)、Provider、Model、推理强度、输出上限、轮次编号及图片摘要。缓存按调用前预测的通道查询,但**始终按响应的实际评分通道写入**:首次调用发生中途降级(无可用路由或供应商拒绝 logprobs)时,结果会落在显式标签键下供后续调用复用,而不会被误当作概率期望评分;提示词模板变更或 logprobs 能力状态翻转都会自然失效。失败或被取消的请求不会写入缓存。
|
|
273
326
|
- **并发请求合并**:相同的并发比对请求会自动共用在途 Promise(In-flight Deduplication),避免重复调用。
|
|
274
|
-
- **运行统计与监控**:每次调用返回完整的统计信息,涵盖实际请求次数、重试次数(Retries)、各类 Token 消耗(输入/缓存命中/输出/推理 Token)、缓存命中与未命中次数(Cache Hits/Misses
|
|
327
|
+
- **运行统计与监控**:每次调用返回完整的统计信息,涵盖实际请求次数、重试次数(Retries)、各类 Token 消耗(输入/缓存命中/输出/推理 Token)、缓存命中与未命中次数(Cache Hits/Misses)以及费用估算;统计记录还会保存一条 `verdict` 摘要(阶段、结果、分数、基线、胜负、阈值),看板的「最近调用」因此能直接显示每次判决与阈值的关系,回答"这次为什么没通过",而不是只显示"调用成功/失败"(注意:`success` 表示**模型调用没有抛错**,不等于任务通过验收);其中:
|
|
275
328
|
- `topLogprobScores`:采用概率分布期望计算的评分次数;
|
|
276
329
|
- `explicitTagScores`:降级采用模型显式输出标签的评分次数。
|
|
277
330
|
- **能力记忆**:当某个 Provider/Model 明确拒绝 `logprobs` 参数后,插件会记住该能力探测结果,避免后续每次调用重复报错。探测结果按话题持久化到 verifier 目录的 `capabilities-v1.json`(24 小时 TTL 后自动重新探测),随话题一并删除;跨进程与会话恢复不再重复探测,首次降级并发窗口内的相同请求也会合并在途调用、不重复计费。
|
|
@@ -283,7 +336,7 @@ flowchart LR
|
|
|
283
336
|
- **提取范围**:仅提取直接的用户消息、Assistant 回复、工具调用(Tool Call)及实际工具执行结果(Tool Result);自动排除插件和系统内置指令(Plugin/System Instructions);
|
|
284
337
|
- **敏感信息脱敏**:默认对常见 Bearer Token、API Key、通用 Token、Password 及 Secret 进行脱敏替换;
|
|
285
338
|
- **灵活控制**:支持指定提取的消息序号范围、字符长度截断上限以及自定义正则表达式脱敏规则;
|
|
286
|
-
-
|
|
339
|
+
- **数据流向**:提取并脱敏后的上下文仅会发送给你在设置面板中指定的裁判模型;启用多裁判时,同一份脱敏后的证据会分别发送给裁判组中的每一个模型。
|
|
287
340
|
|
|
288
341
|
> [!IMPORTANT]
|
|
289
342
|
> 默认脱敏规则不能替代全面的数据防泄漏(DLP)策略。在处理高度敏感的任务时,建议主动限制提取范围并补充自定义脱敏正则表达式。
|
|
@@ -10,6 +10,19 @@ var TopLogprobsUnsupportedError = class extends Error {
|
|
|
10
10
|
this.name = "TopLogprobsUnsupportedError";
|
|
11
11
|
}
|
|
12
12
|
};
|
|
13
|
+
/**
|
|
14
|
+
* A provider-level rejection of the direct transport that is not a logprobs
|
|
15
|
+
* capability answer (bad request, auth, quota, malformed body). It downgrades
|
|
16
|
+
* this topic to the DSH stream instead of failing the whole verification.
|
|
17
|
+
*/
|
|
18
|
+
var TopLogprobsRouteError = class extends TopLogprobsUnsupportedError {
|
|
19
|
+
status;
|
|
20
|
+
constructor(message, status) {
|
|
21
|
+
super(message);
|
|
22
|
+
this.status = status;
|
|
23
|
+
this.name = "TopLogprobsRouteError";
|
|
24
|
+
}
|
|
25
|
+
};
|
|
13
26
|
function object(value) {
|
|
14
27
|
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
|
|
15
28
|
}
|
|
@@ -53,7 +66,7 @@ async function resolveTopLogprobRoute(ctx, provider) {
|
|
|
53
66
|
deepSeekThinking: false
|
|
54
67
|
};
|
|
55
68
|
}
|
|
56
|
-
async function callTopLogprobs(route, model, prompt, maxTokens, reasoningEffort, signal, images) {
|
|
69
|
+
async function callTopLogprobs(route, model, prompt, maxTokens, reasoningEffort, signal, images, attempt = 1, temperature = .2) {
|
|
57
70
|
const content = images?.length ? [{
|
|
58
71
|
type: "text",
|
|
59
72
|
text: prompt
|
|
@@ -81,7 +94,7 @@ async function callTopLogprobs(route, model, prompt, maxTokens, reasoningEffort,
|
|
|
81
94
|
content
|
|
82
95
|
}],
|
|
83
96
|
max_tokens: maxTokens,
|
|
84
|
-
temperature
|
|
97
|
+
temperature,
|
|
85
98
|
logprobs: true,
|
|
86
99
|
top_logprobs: 20,
|
|
87
100
|
...thinking
|
|
@@ -90,6 +103,7 @@ async function callTopLogprobs(route, model, prompt, maxTokens, reasoningEffort,
|
|
|
90
103
|
const raw = await response.text();
|
|
91
104
|
if (!response.ok) {
|
|
92
105
|
const excerpt = raw.slice(0, 1e3);
|
|
106
|
+
const message = "llm-verifier: top_logprobs request failed with HTTP " + response.status + ": " + excerpt;
|
|
93
107
|
if ([
|
|
94
108
|
400,
|
|
95
109
|
404,
|
|
@@ -97,13 +111,14 @@ async function callTopLogprobs(route, model, prompt, maxTokens, reasoningEffort,
|
|
|
97
111
|
415,
|
|
98
112
|
422
|
|
99
113
|
].includes(response.status) && /logprob|top_logprobs|unsupported|unknown (?:field|parameter)|unrecognized (?:field|parameter)|not support/i.test(excerpt)) throw new TopLogprobsUnsupportedError("provider rejected top_logprobs: HTTP " + response.status + " " + excerpt);
|
|
100
|
-
|
|
114
|
+
if (response.status === 408 || response.status === 409 || response.status === 429 || response.status >= 500) throw new Error(message);
|
|
115
|
+
throw new TopLogprobsRouteError(message, response.status);
|
|
101
116
|
}
|
|
102
117
|
let body;
|
|
103
118
|
try {
|
|
104
119
|
body = object(JSON.parse(raw)) ?? {};
|
|
105
120
|
} catch {
|
|
106
|
-
throw new
|
|
121
|
+
throw new TopLogprobsRouteError("llm-verifier: top_logprobs endpoint returned invalid JSON", response.status);
|
|
107
122
|
}
|
|
108
123
|
const choice = object((Array.isArray(body.choices) ? body.choices : [])[0]);
|
|
109
124
|
const message = object(choice?.message);
|
|
@@ -142,8 +157,8 @@ async function callTopLogprobs(route, model, prompt, maxTokens, reasoningEffort,
|
|
|
142
157
|
scoringMode: "top-logprobs",
|
|
143
158
|
usage: {
|
|
144
159
|
calls: 1,
|
|
145
|
-
attempts:
|
|
146
|
-
retries:
|
|
160
|
+
attempts: attempt,
|
|
161
|
+
retries: attempt - 1,
|
|
147
162
|
inputTokens: Math.max(0, input - cached),
|
|
148
163
|
cachedInputTokens: cached,
|
|
149
164
|
outputTokens: Number(rawUsage.completion_tokens ?? 0) || 0,
|
|
@@ -166,8 +181,16 @@ var TopLogprobCapabilityCache = class {
|
|
|
166
181
|
this.file = file;
|
|
167
182
|
this.now = now;
|
|
168
183
|
}
|
|
184
|
+
/** Expired marks are dropped so a provider that later gains logprobs support is re-probed. */
|
|
169
185
|
isUnsupported(provider, model) {
|
|
170
|
-
|
|
186
|
+
const key = provider + "\0" + model;
|
|
187
|
+
const markedAt = this.unsupported.get(key);
|
|
188
|
+
if (markedAt === void 0) return false;
|
|
189
|
+
if (this.now() - markedAt > 864e5) {
|
|
190
|
+
this.unsupported.delete(key);
|
|
191
|
+
return false;
|
|
192
|
+
}
|
|
193
|
+
return true;
|
|
171
194
|
}
|
|
172
195
|
/** Hydrates persisted marks once; in-process marks always win over file contents. */
|
|
173
196
|
async ensureLoaded() {
|
|
@@ -248,61 +271,38 @@ function usage(attempts, value = {}) {
|
|
|
248
271
|
reasoningTokens: value.reasoningTokens ?? 0
|
|
249
272
|
};
|
|
250
273
|
}
|
|
251
|
-
|
|
274
|
+
/** Transient failures worth another attempt; anything else fails fast. */
|
|
275
|
+
const RETRYABLE_MESSAGE = /rate|quota|timeout|timed out|temporar|network|fetch|socket|5\d\d/i;
|
|
276
|
+
/**
|
|
277
|
+
* Run one logical verifier request under the configured timeout, retrying
|
|
278
|
+
* transient failures with exponential backoff.
|
|
279
|
+
*
|
|
280
|
+
* Every channel goes through this wrapper — including the direct top_logprobs
|
|
281
|
+
* transport, which used to bypass both the timeout and the retry budget.
|
|
282
|
+
* @param config - resolved verifier client configuration.
|
|
283
|
+
* @param signal - caller's abort signal (tool call or turn boundary).
|
|
284
|
+
* @param run - one attempt; receives its own deadline signal and 1-based attempt number.
|
|
285
|
+
* @returns The first successful completion.
|
|
286
|
+
*/
|
|
287
|
+
async function retrying(config, signal, run) {
|
|
252
288
|
let attempt = 0;
|
|
253
289
|
while (true) {
|
|
290
|
+
if (signal?.aborted) throw signal.reason;
|
|
254
291
|
attempt += 1;
|
|
255
292
|
const controller = new AbortController();
|
|
256
|
-
|
|
293
|
+
let timedOut = false;
|
|
294
|
+
const timeout = setTimeout(() => {
|
|
295
|
+
timedOut = true;
|
|
296
|
+
controller.abort(/* @__PURE__ */ new Error("llm-verifier: request timed out"));
|
|
297
|
+
}, config.timeoutMs);
|
|
257
298
|
const abort = () => controller.abort(signal?.reason);
|
|
258
299
|
signal?.addEventListener("abort", abort, { once: true });
|
|
259
300
|
try {
|
|
260
|
-
|
|
261
|
-
type: "text",
|
|
262
|
-
text: prompt
|
|
263
|
-
}];
|
|
264
|
-
for (const image of images ?? []) {
|
|
265
|
-
const ref = await config.attachments.saveImage({
|
|
266
|
-
data: image.data,
|
|
267
|
-
mediaType: image.mediaType
|
|
268
|
-
});
|
|
269
|
-
content.push({
|
|
270
|
-
type: "image",
|
|
271
|
-
attachment: ref
|
|
272
|
-
});
|
|
273
|
-
}
|
|
274
|
-
const messages = [createUserMessage({
|
|
275
|
-
content,
|
|
276
|
-
source: {
|
|
277
|
-
kind: "plugin",
|
|
278
|
-
plugin: "dsh-llm-verifier"
|
|
279
|
-
}
|
|
280
|
-
})];
|
|
281
|
-
const assembler = new BlockAssembler();
|
|
282
|
-
const options = deepFreeze({
|
|
283
|
-
provider: config.provider,
|
|
284
|
-
model: config.model,
|
|
285
|
-
...config.reasoningEffort ? { reasoningEffort: ReasoningEffortId(config.reasoningEffort) } : {},
|
|
286
|
-
messages,
|
|
287
|
-
maxTokens: config.maxTokens,
|
|
288
|
-
temperature: 1,
|
|
289
|
-
signal: controller.signal
|
|
290
|
-
});
|
|
291
|
-
for await (const chunk of config.llm.stream(options)) assembler.push(chunk);
|
|
292
|
-
const failed = failureMessage(assembler.finish);
|
|
293
|
-
if (failed !== void 0) throw new Error("llm-verifier: model call failed: " + failed);
|
|
294
|
-
const text = assembler.blocks().filter((block) => block.type === "text").map((block) => block.text).join("");
|
|
295
|
-
if (!text.trim()) throw new Error("llm-verifier: selected DSH model produced no text");
|
|
296
|
-
return {
|
|
297
|
-
text,
|
|
298
|
-
tokens: [],
|
|
299
|
-
positions: [],
|
|
300
|
-
scoringMode: "explicit-tag",
|
|
301
|
-
usage: usage(attempt, assembler.usage)
|
|
302
|
-
};
|
|
301
|
+
return await run(controller.signal, attempt);
|
|
303
302
|
} catch (error) {
|
|
304
303
|
if (signal?.aborted) throw signal.reason;
|
|
305
|
-
|
|
304
|
+
const retryable = timedOut || error instanceof Error && RETRYABLE_MESSAGE.test(error.message);
|
|
305
|
+
if (attempt > config.maxRetries || !retryable) throw error;
|
|
306
306
|
await delay(Math.min(3e4, config.retryBaseDelayMs * 2 ** (attempt - 1) * (.8 + Math.random() * .4)), signal);
|
|
307
307
|
} finally {
|
|
308
308
|
clearTimeout(timeout);
|
|
@@ -310,6 +310,60 @@ async function callExplicitTag(config, prompt, signal, images) {
|
|
|
310
310
|
}
|
|
311
311
|
}
|
|
312
312
|
}
|
|
313
|
+
/** One attachment per image object per process: retries must not duplicate attachments. */
|
|
314
|
+
const imageRefs = /* @__PURE__ */ new WeakMap();
|
|
315
|
+
async function callExplicitTag(config, prompt, signal, images, attempt) {
|
|
316
|
+
const content = [{
|
|
317
|
+
type: "text",
|
|
318
|
+
text: prompt
|
|
319
|
+
}];
|
|
320
|
+
for (const image of images ?? []) {
|
|
321
|
+
let pending = imageRefs.get(image);
|
|
322
|
+
if (pending === void 0) {
|
|
323
|
+
pending = Promise.resolve().then(() => config.attachments.saveImage({
|
|
324
|
+
data: image.data,
|
|
325
|
+
mediaType: image.mediaType
|
|
326
|
+
})).catch((error) => {
|
|
327
|
+
if (imageRefs.get(image) === pending) imageRefs.delete(image);
|
|
328
|
+
throw error;
|
|
329
|
+
});
|
|
330
|
+
imageRefs.set(image, pending);
|
|
331
|
+
}
|
|
332
|
+
content.push({
|
|
333
|
+
type: "image",
|
|
334
|
+
attachment: await pending
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
const messages = [createUserMessage({
|
|
338
|
+
content,
|
|
339
|
+
source: {
|
|
340
|
+
kind: "plugin",
|
|
341
|
+
plugin: "dsh-llm-verifier"
|
|
342
|
+
}
|
|
343
|
+
})];
|
|
344
|
+
const assembler = new BlockAssembler();
|
|
345
|
+
const options = deepFreeze({
|
|
346
|
+
provider: config.provider,
|
|
347
|
+
model: config.model,
|
|
348
|
+
...config.reasoningEffort ? { reasoningEffort: ReasoningEffortId(config.reasoningEffort) } : {},
|
|
349
|
+
messages,
|
|
350
|
+
maxTokens: config.maxTokens,
|
|
351
|
+
temperature: config.temperature,
|
|
352
|
+
signal
|
|
353
|
+
});
|
|
354
|
+
for await (const chunk of config.llm.stream(options)) assembler.push(chunk);
|
|
355
|
+
const failed = failureMessage(assembler.finish);
|
|
356
|
+
if (failed !== void 0) throw new Error("llm-verifier: model call failed: " + failed);
|
|
357
|
+
const text = assembler.blocks().filter((block) => block.type === "text").map((block) => block.text).join("");
|
|
358
|
+
if (!text.trim()) throw new Error("llm-verifier: selected DSH model produced no text");
|
|
359
|
+
return {
|
|
360
|
+
text,
|
|
361
|
+
tokens: [],
|
|
362
|
+
positions: [],
|
|
363
|
+
scoringMode: "explicit-tag",
|
|
364
|
+
usage: usage(attempt, assembler.usage)
|
|
365
|
+
};
|
|
366
|
+
}
|
|
313
367
|
var RequestLimiter = class {
|
|
314
368
|
limit;
|
|
315
369
|
active = 0;
|
|
@@ -319,6 +373,7 @@ var RequestLimiter = class {
|
|
|
319
373
|
if (!Number.isSafeInteger(limit) || limit < 1) throw new Error("llm-verifier: request concurrency limit must be a positive integer");
|
|
320
374
|
}
|
|
321
375
|
async run(operation, signal) {
|
|
376
|
+
if (signal?.aborted) throw signal.reason;
|
|
322
377
|
if (this.active >= this.limit) await new Promise((resolve, reject) => {
|
|
323
378
|
const enter = () => {
|
|
324
379
|
signal?.removeEventListener("abort", abort);
|
|
@@ -332,7 +387,10 @@ var RequestLimiter = class {
|
|
|
332
387
|
this.queue.push(enter);
|
|
333
388
|
signal?.addEventListener("abort", abort, { once: true });
|
|
334
389
|
});
|
|
335
|
-
if (signal?.aborted)
|
|
390
|
+
if (signal?.aborted) {
|
|
391
|
+
this.queue.shift()?.();
|
|
392
|
+
throw signal.reason;
|
|
393
|
+
}
|
|
336
394
|
this.active += 1;
|
|
337
395
|
try {
|
|
338
396
|
return await operation();
|
|
@@ -347,27 +405,27 @@ async function predictScoringChannel(config) {
|
|
|
347
405
|
await config.topLogprobCapabilities.ensureLoaded();
|
|
348
406
|
return config.topLogprobCapabilities.isUnsupported(config.provider, config.model) ? "explicit-tag" : "top-logprobs";
|
|
349
407
|
}
|
|
350
|
-
async function callAutomatic(config, prompt, signal, images) {
|
|
408
|
+
async function callAutomatic(config, prompt, signal, images, attempt) {
|
|
351
409
|
await config.topLogprobCapabilities.ensureLoaded();
|
|
352
410
|
if (!config.topLogprobCapabilities.isUnsupported(config.provider, config.model)) {
|
|
353
411
|
const route = await resolveTopLogprobRoute(config.ctx, config.provider);
|
|
354
412
|
if (route !== void 0) try {
|
|
355
|
-
return await callTopLogprobs(route, config.model, prompt, config.maxTokens, config.reasoningEffort, signal, images);
|
|
413
|
+
return await callTopLogprobs(route, config.model, prompt, config.maxTokens, config.reasoningEffort, signal, images, attempt, config.temperature);
|
|
356
414
|
} catch (error) {
|
|
357
415
|
if (!(error instanceof TopLogprobsUnsupportedError)) throw error;
|
|
358
416
|
config.topLogprobCapabilities.markUnsupported(config.provider, config.model);
|
|
359
417
|
}
|
|
360
418
|
else config.topLogprobCapabilities.markUnsupported(config.provider, config.model);
|
|
361
419
|
}
|
|
362
|
-
return callExplicitTag(config, prompt, signal, images);
|
|
420
|
+
return callExplicitTag(config, prompt, signal, images, attempt);
|
|
363
421
|
}
|
|
364
422
|
async function callVerifier(config, prompt, signal, images) {
|
|
365
|
-
const invoke = () => callAutomatic(config, prompt,
|
|
423
|
+
const invoke = () => retrying(config, signal, (attemptSignal, attempt) => callAutomatic(config, prompt, attemptSignal, images, attempt));
|
|
366
424
|
return config.limiter === void 0 ? invoke() : config.limiter.run(invoke, signal);
|
|
367
425
|
}
|
|
368
426
|
/** Plain-text verifier call for conservative JSON routing; probability labels are intentionally bypassed. */
|
|
369
427
|
async function callVerifierText(config, prompt, signal) {
|
|
370
|
-
const invoke = () => callExplicitTag(config, prompt,
|
|
428
|
+
const invoke = () => retrying(config, signal, (attemptSignal, attempt) => callExplicitTag(config, prompt, attemptSignal, void 0, attempt));
|
|
371
429
|
return config.limiter === void 0 ? invoke() : config.limiter.run(invoke, signal);
|
|
372
430
|
}
|
|
373
431
|
function addUsage(target, source) {
|
|
@@ -395,4 +453,4 @@ function emptyUsage() {
|
|
|
395
453
|
//#endregion
|
|
396
454
|
export { emptyUsage as a, resolveCapabilityFile as c, callVerifierText as i, addUsage as n, predictScoringChannel as o, callVerifier as r, TopLogprobCapabilityCache as s, RequestLimiter as t };
|
|
397
455
|
|
|
398
|
-
//# sourceMappingURL=caller-
|
|
456
|
+
//# sourceMappingURL=caller-DJd_FlrQ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"caller-DJd_FlrQ.js","names":[],"sources":["../src/top-logprobs.ts","../src/caller.ts"],"sourcesContent":["import type { Context } from '@deepseek-ai/cordis'\nimport { credentialRef } from '@deepseek-ai/dsh-credentials'\nimport { mkdir, readFile, rename, unlink, writeFile } from 'node:fs/promises'\nimport { dirname, isAbsolute, join, resolve } from 'node:path'\nimport type { CompletionLogprobs, TokenAlternative } from './core.ts'\nimport type { UsageStats, VerifierImage } from './caller.ts'\n\nexport interface TopLogprobRoute {\n baseURL: string\n apiKey?: string\n headers?: Record<string, string>\n deepSeekThinking: boolean\n}\nexport interface TopLogprobCompletion extends CompletionLogprobs { usage: UsageStats; scoringMode: 'top-logprobs' }\nexport class TopLogprobsUnsupportedError extends Error { constructor(message: string) { super(message); this.name = 'TopLogprobsUnsupportedError' } }\n/**\n * A provider-level rejection of the direct transport that is not a logprobs\n * capability answer (bad request, auth, quota, malformed body). It downgrades\n * this topic to the DSH stream instead of failing the whole verification.\n */\nexport class TopLogprobsRouteError extends TopLogprobsUnsupportedError { constructor(message: string, readonly status?: number) { super(message); this.name = 'TopLogprobsRouteError' } }\n\nfunction object(value: unknown): Record<string, unknown> | undefined { return typeof value === 'object' && value !== null && !Array.isArray(value) ? value as Record<string, unknown> : undefined }\nfunction text(value: unknown): string | undefined { return typeof value === 'string' && value.trim() ? value.trim() : undefined }\nfunction endpoint(baseURL: string): string { return baseURL.replace(/\\/+$/, '') + '/chat/completions' }\nfunction dataUrl(image: VerifierImage): string { return 'data:' + image.mediaType + ';base64,' + Buffer.from(image.data.buffer, image.data.byteOffset, image.data.byteLength).toString('base64') }\n\nasync function credential(ctx: Context, name: string | undefined): Promise<string | undefined> {\n if (!name) return undefined\n const provider = ctx.get('credentials')\n return (await provider?.resolve(credentialRef(name)))?.value\n}\n\nexport async function resolveTopLogprobRoute(ctx: Context, provider: string): Promise<TopLogprobRoute | undefined> {\n const settings = ctx.get('settings')\n if (provider === 'deepseek-official') {\n const value = settings ? object(settings.get('llm-deepseek' as never)) ?? {} : {}\n const apiKeyEnv = text(value.apiKeyEnv) ?? 'DEEPSEEK_API_KEY'\n const apiKey = await credential(ctx, apiKeyEnv)\n if (!apiKey) return undefined\n return { baseURL: text(value.baseURL) ?? 'https://api.deepseek.com', apiKey, deepSeekThinking: true }\n }\n if (!settings) return undefined\n const root = object(settings.get('llm-pi-ai' as never))\n const profiles = object(root?.providers)\n const profile = object(profiles?.[provider])\n // Only explicitly OpenAI-compatible profiles are safe to serialize directly.\n // Other DSH adapters keep their private protocol and use the explicit-tag fallback.\n if (!profile || profile.api !== 'openai-completions') return undefined\n const baseURL = text(profile.baseURL)\n if (!baseURL || !/^https:\\/\\//i.test(baseURL)) return undefined\n const apiKey = await credential(ctx, text(profile.apiKeyEnv))\n const rawHeaders = object(profile.headers)\n const headers = rawHeaders === undefined ? undefined : Object.fromEntries(Object.entries(rawHeaders).filter((entry): entry is [string, string] => typeof entry[1] === 'string'))\n return { baseURL, ...(apiKey ? { apiKey } : {}), ...(headers ? { headers } : {}), deepSeekThinking: false }\n}\n\nexport async function callTopLogprobs(route: TopLogprobRoute, model: string, prompt: string, maxTokens: number, reasoningEffort: string | undefined, signal?: AbortSignal, images?: readonly VerifierImage[], attempt = 1, temperature = 0.2): Promise<TopLogprobCompletion> {\n const content: string | Record<string, unknown>[] = images?.length ? [{ type: 'text', text: prompt }, ...images.map(image => ({ type: 'image_url', image_url: { url: dataUrl(image) } }))] : prompt\n const thinking = route.deepSeekThinking && reasoningEffort ? reasoningEffort === 'off' ? { thinking: { type: 'disabled' } } : { thinking: { type: 'enabled' }, reasoning_effort: reasoningEffort } : {}\n const response = await fetch(endpoint(route.baseURL), {\n method: 'POST', redirect: 'error', signal,\n headers: { 'content-type': 'application/json', ...(route.apiKey ? { authorization: 'Bearer ' + route.apiKey } : {}), ...route.headers },\n body: JSON.stringify({ model, messages: [{ role: 'user', content }], max_tokens: maxTokens, temperature, logprobs: true, top_logprobs: 20, ...thinking }),\n })\n const raw = await response.text()\n if (!response.ok) {\n const excerpt = raw.slice(0, 1000)\n const message = 'llm-verifier: top_logprobs request failed with HTTP ' + response.status + ': ' + excerpt\n if ([400, 404, 405, 415, 422].includes(response.status) && /logprob|top_logprobs|unsupported|unknown (?:field|parameter)|unrecognized (?:field|parameter)|not support/i.test(excerpt)) throw new TopLogprobsUnsupportedError('provider rejected top_logprobs: HTTP ' + response.status + ' ' + excerpt)\n // Throttling and server faults stay generic so the shared retry wrapper can\n // attempt again; every other rejection downgrades to the DSH stream.\n if (response.status === 408 || response.status === 409 || response.status === 429 || response.status >= 500) throw new Error(message)\n throw new TopLogprobsRouteError(message, response.status)\n }\n let body: Record<string, unknown>\n try { body = object(JSON.parse(raw)) ?? {} } catch { throw new TopLogprobsRouteError('llm-verifier: top_logprobs endpoint returned invalid JSON', response.status) }\n const choices = Array.isArray(body.choices) ? body.choices : []\n const choice = object(choices[0])\n const message = object(choice?.message)\n const answer = typeof message?.content === 'string' ? message.content : ''\n const logprobs = object(choice?.logprobs)\n const rows = Array.isArray(logprobs?.content) ? logprobs.content : []\n if (!rows.length) throw new TopLogprobsUnsupportedError('provider returned no token logprobs')\n const tokens: string[] = []\n const positions: TokenAlternative[][] = []\n for (const rawRow of rows) {\n const row = object(rawRow) ?? {}\n const token = typeof row.token === 'string' ? row.token : ''\n tokens.push(token)\n const top = Array.isArray(row.top_logprobs) ? row.top_logprobs : []\n const alternatives = top.flatMap(value => { const item = object(value); return item && typeof item.token === 'string' && typeof item.logprob === 'number' ? [{ token: item.token, logprob: item.logprob }] : [] })\n if (!alternatives.length && typeof row.logprob === 'number') alternatives.push({ token, logprob: row.logprob })\n positions.push(alternatives)\n }\n const rawUsage = object(body.usage) ?? {}\n const promptDetails = object(rawUsage.prompt_tokens_details) ?? {}\n const completionDetails = object(rawUsage.completion_tokens_details) ?? {}\n const cached = Number(rawUsage.prompt_cache_hit_tokens ?? promptDetails.cached_tokens ?? 0) || 0\n const input = Number(rawUsage.prompt_tokens ?? 0) || 0\n return { text: answer, tokens, positions, scoringMode: 'top-logprobs', usage: { calls: 1, attempts: attempt, retries: attempt - 1, inputTokens: Math.max(0, input - cached), cachedInputTokens: cached, outputTokens: Number(rawUsage.completion_tokens ?? 0) || 0, reasoningTokens: Number(completionDetails.reasoning_tokens ?? 0) || 0 } }\n}\n\n/** Marks older than this are dropped on hydration so a provider that later gains logprobs support is re-probed. */\nexport const CAPABILITY_TTL_MS = 24 * 60 * 60 * 1000\n\ninterface CapabilityDocument { version: 1; entries: Record<string, number> }\n\n/** Resolves the capability memory file beside the score cache inside the topic verifier directory. */\nexport function resolveCapabilityFile(cacheDir: string, cwd = process.cwd()): string {\n const root = isAbsolute(cacheDir) ? cacheDir : resolve(cwd, cacheDir)\n return join(root, 'capabilities-v1.json')\n}\n\nexport class TopLogprobCapabilityCache {\n private readonly unsupported = new Map<string, number>()\n private loaded = false\n private hydrating: Promise<void> | undefined\n private writing: Promise<void> = Promise.resolve()\n\n constructor(private readonly file?: string, private readonly now: () => number = Date.now) {}\n\n /** Expired marks are dropped so a provider that later gains logprobs support is re-probed. */\n isUnsupported(provider: string, model: string): boolean {\n const key = provider + '\\0' + model\n const markedAt = this.unsupported.get(key)\n if (markedAt === undefined) return false\n if (this.now() - markedAt > CAPABILITY_TTL_MS) { this.unsupported.delete(key); return false }\n return true\n }\n\n /** Hydrates persisted marks once; in-process marks always win over file contents. */\n async ensureLoaded(): Promise<void> {\n if (this.loaded || this.file === undefined) return\n this.hydrating ??= (async () => {\n try {\n const document = JSON.parse(await readFile(this.file!, 'utf8')) as CapabilityDocument\n const entries = document !== null && typeof document === 'object' && document.version === 1 && typeof document.entries === 'object' && document.entries !== null ? document.entries : {}\n const now = this.now()\n for (const [key, markedAt] of Object.entries(entries)) {\n if (typeof markedAt !== 'number' || !Number.isFinite(markedAt) || markedAt < 0 || now - markedAt > CAPABILITY_TTL_MS) continue\n // Max-merge: never let an older persisted stamp clobber a fresher in-process probe.\n const existing = this.unsupported.get(key)\n if (existing === undefined || existing < markedAt) this.unsupported.set(key, markedAt)\n }\n } catch { /* a missing or unreadable file simply starts empty */ }\n this.loaded = true\n })()\n await this.hydrating\n }\n\n markUnsupported(provider: string, model: string): void {\n this.unsupported.set(provider + '\\0' + model, this.now())\n if (this.file === undefined) return\n // Serialize behind hydration so an early mark never clobbers not-yet-loaded entries.\n this.writing = this.writing\n .then(() => this.ensureLoaded())\n .then(async () => {\n const snapshot: CapabilityDocument = { version: 1, entries: Object.fromEntries(this.unsupported) }\n await mkdir(dirname(this.file!), { recursive: true })\n const temporary = this.file! + '.tmp-' + process.pid\n await writeFile(temporary, JSON.stringify(snapshot), 'utf8')\n try { await rename(temporary, this.file!) } catch (error) { await unlink(temporary).catch(() => {}); throw error }\n })\n .catch(() => { /* capability memory is best-effort; the next mark rewrites the file */ })\n }\n\n /** Resolves once the trailing persistence attempt settles; exposed for tests. */\n flush(): Promise<void> { return this.writing }\n}\n","import { BlockAssembler, ReasoningEffortId, createUserMessage, type ContentBlock, type FinishReason, type LlmRuntime } from '@deepseek-ai/dsh-llm'\nimport * as LlmModule from '@deepseek-ai/dsh-llm'\n\nfunction deepFreeze<T>(value: T): T {\n const mod = LlmModule as unknown as Record<string, unknown>\n if (typeof mod.deepFreeze === 'function') {\n return (mod.deepFreeze as Function)(value)\n }\n if (value && typeof value === 'object' && !Object.isFrozen(value)) {\n Object.freeze(value)\n for (const key of Object.keys(value)) {\n deepFreeze((value as Record<string, unknown>)[key])\n }\n }\n return value\n}\nimport type { AttachmentStore } from '@deepseek-ai/dsh-attachment'\nimport type { CompletionLogprobs } from './core.ts'\nimport { TopLogprobCapabilityCache, TopLogprobsUnsupportedError, callTopLogprobs, resolveTopLogprobRoute } from './top-logprobs.ts'\nimport type { Context } from '@deepseek-ai/cordis'\n\nexport interface VerifierClientConfig {\n ctx: Context\n llm: LlmRuntime\n attachments: AttachmentStore\n topLogprobCapabilities: TopLogprobCapabilityCache\n provider: string\n model: string\n /** User-facing judge name for tool output; cosmetic only, never part of the scoring cache identity. */\n label?: string\n reasoningEffort?: string\n maxTokens: number\n temperature: number\n timeoutMs: number\n maxRetries: number\n retryBaseDelayMs: number\n limiter?: RequestLimiter\n}\n\nexport interface VerifierImage {\n data: Uint8Array\n mediaType: 'image/png' | 'image/jpeg' | 'image/webp' | 'image/gif'\n}\n\nexport interface UsageStats {\n calls: number\n attempts: number\n retries: number\n inputTokens: number\n cachedInputTokens: number\n outputTokens: number\n reasoningTokens: number\n}\n\nexport type ScoringMode = 'top-logprobs' | 'explicit-tag'\nexport interface VerifierCompletion extends CompletionLogprobs { usage: UsageStats; scoringMode: ScoringMode }\n\nfunction failureMessage(finish: FinishReason): string | undefined {\n if (finish.kind === 'error' || finish.kind === 'aborted') return finish.failure.message\n if (finish.kind === 'max-tokens') return 'verifier response reached max tokens before completing its answer'\n return undefined\n}\n\nasync function delay(ms: number, signal?: AbortSignal): Promise<void> {\n if (signal?.aborted) throw signal.reason\n await new Promise<void>((resolve, reject) => {\n const timer = setTimeout(resolve, ms)\n const abort = () => { clearTimeout(timer); reject(signal?.reason) }\n signal?.addEventListener('abort', abort, { once: true })\n })\n}\n\nfunction usage(attempts: number, value = {} as { inputTokens?: number; outputTokens?: number; cacheReadTokens?: number; cacheWriteTokens?: number; reasoningTokens?: number }): UsageStats {\n return { calls: 1, attempts, retries: attempts - 1, inputTokens: value.inputTokens ?? 0, cachedInputTokens: (value.cacheReadTokens ?? 0) + (value.cacheWriteTokens ?? 0), outputTokens: value.outputTokens ?? 0, reasoningTokens: value.reasoningTokens ?? 0 }\n}\n\n/** Transient failures worth another attempt; anything else fails fast. */\nconst RETRYABLE_MESSAGE = /rate|quota|timeout|timed out|temporar|network|fetch|socket|5\\d\\d/i\n\n/**\n * Run one logical verifier request under the configured timeout, retrying\n * transient failures with exponential backoff.\n *\n * Every channel goes through this wrapper — including the direct top_logprobs\n * transport, which used to bypass both the timeout and the retry budget.\n * @param config - resolved verifier client configuration.\n * @param signal - caller's abort signal (tool call or turn boundary).\n * @param run - one attempt; receives its own deadline signal and 1-based attempt number.\n * @returns The first successful completion.\n */\nasync function retrying<T>(config: VerifierClientConfig, signal: AbortSignal | undefined, run: (signal: AbortSignal, attempt: number) => Promise<T>): Promise<T> {\n let attempt = 0\n while (true) {\n if (signal?.aborted) throw signal.reason\n attempt += 1\n const controller = new AbortController()\n let timedOut = false\n const timeout = setTimeout(() => { timedOut = true; controller.abort(new Error('llm-verifier: request timed out')) }, config.timeoutMs)\n const abort = () => controller.abort(signal?.reason)\n signal?.addEventListener('abort', abort, { once: true })\n try {\n return await run(controller.signal, attempt)\n } catch (error) {\n if (signal?.aborted) throw signal.reason\n // A deadline abort is retryable even when the adapter wraps the reason in\n // its own error type with an unrelated message.\n const retryable = timedOut || (error instanceof Error && RETRYABLE_MESSAGE.test(error.message))\n if (attempt > config.maxRetries || !retryable) throw error\n await delay(Math.min(30000, config.retryBaseDelayMs * 2 ** (attempt - 1) * (0.8 + Math.random() * 0.4)), signal)\n } finally {\n clearTimeout(timeout)\n signal?.removeEventListener('abort', abort)\n }\n }\n}\n\n/** One attachment per image object per process: retries must not duplicate attachments. */\nconst imageRefs = new WeakMap<VerifierImage, Promise<unknown>>()\n\nasync function callExplicitTag(config: VerifierClientConfig, prompt: string, signal: AbortSignal | undefined, images: readonly VerifierImage[] | undefined, attempt: number): Promise<VerifierCompletion> {\n const content: ContentBlock[] = [{ type: 'text', text: prompt }]\n for (const image of images ?? []) {\n let pending = imageRefs.get(image)\n if (pending === undefined) {\n const promise = Promise.resolve()\n .then(() => config.attachments.saveImage({ data: image.data, mediaType: image.mediaType }))\n .catch(error => {\n if (imageRefs.get(image) === pending) {\n imageRefs.delete(image)\n }\n throw error\n })\n pending = promise\n imageRefs.set(image, pending)\n }\n content.push({ type: 'image', attachment: await pending as never })\n }\n const messages = [createUserMessage({ content, source: { kind: 'plugin', plugin: 'dsh-llm-verifier' } })]\n const assembler = new BlockAssembler()\n const options = deepFreeze({\n provider: config.provider,\n model: config.model,\n ...(config.reasoningEffort ? { reasoningEffort: ReasoningEffortId(config.reasoningEffort) } : {}),\n messages,\n maxTokens: config.maxTokens,\n temperature: config.temperature,\n signal,\n })\n for await (const chunk of config.llm.stream(options)) assembler.push(chunk)\n const failed = failureMessage(assembler.finish)\n if (failed !== undefined) throw new Error('llm-verifier: model call failed: ' + failed)\n const text = assembler.blocks().filter((block): block is Extract<ContentBlock, { type: 'text' }> => block.type === 'text').map(block => block.text).join('')\n if (!text.trim()) throw new Error('llm-verifier: selected DSH model produced no text')\n // DSH adapters expose provider-neutral text/usage but not top-logprob candidates.\n // extractScore() therefore uses the model's explicit final A–T tags.\n return { text, tokens: [], positions: [], scoringMode: 'explicit-tag', usage: usage(attempt, assembler.usage) }\n}\n\nexport class RequestLimiter {\n private active = 0\n private readonly queue: Array<() => void> = []\n constructor(readonly limit: number) { if (!Number.isSafeInteger(limit) || limit < 1) throw new Error('llm-verifier: request concurrency limit must be a positive integer') }\n async run<T>(operation: () => Promise<T>, signal?: AbortSignal): Promise<T> {\n if (signal?.aborted) throw signal.reason\n if (this.active >= this.limit) await new Promise<void>((resolve, reject) => {\n const enter = () => { signal?.removeEventListener('abort', abort); resolve() }\n const abort = () => { const index = this.queue.indexOf(enter); if (index >= 0) this.queue.splice(index, 1); reject(signal?.reason) }\n this.queue.push(enter); signal?.addEventListener('abort', abort, { once: true })\n })\n if (signal?.aborted) {\n this.queue.shift()?.()\n throw signal.reason\n }\n this.active += 1\n try { return await operation() } finally { this.active -= 1; this.queue.shift()?.() }\n }\n}\n\n/** Best-effort pre-call channel prediction for cache identity only; callAutomatic() stays the runtime source of truth. */\nexport async function predictScoringChannel(config: VerifierClientConfig): Promise<ScoringMode> {\n await config.topLogprobCapabilities.ensureLoaded()\n return config.topLogprobCapabilities.isUnsupported(config.provider, config.model) ? 'explicit-tag' : 'top-logprobs'\n}\n\nasync function callAutomatic(config: VerifierClientConfig, prompt: string, signal: AbortSignal | undefined, images: readonly VerifierImage[] | undefined, attempt: number): Promise<VerifierCompletion> {\n await config.topLogprobCapabilities.ensureLoaded()\n if (!config.topLogprobCapabilities.isUnsupported(config.provider, config.model)) {\n const route = await resolveTopLogprobRoute(config.ctx, config.provider)\n if (route !== undefined) {\n try { return await callTopLogprobs(route, config.model, prompt, config.maxTokens, config.reasoningEffort, signal, images, attempt, config.temperature) }\n catch (error) {\n // Both a capability rejection and a non-retryable provider rejection of\n // the direct transport fall back to the DSH stream instead of failing\n // the whole verification.\n if (!(error instanceof TopLogprobsUnsupportedError)) throw error\n config.topLogprobCapabilities.markUnsupported(config.provider, config.model)\n }\n } else config.topLogprobCapabilities.markUnsupported(config.provider, config.model)\n }\n return callExplicitTag(config, prompt, signal, images, attempt)\n}\n\nexport async function callVerifier(config: VerifierClientConfig, prompt: string, signal?: AbortSignal, images?: readonly VerifierImage[]): Promise<VerifierCompletion> {\n const invoke = () => retrying(config, signal, (attemptSignal, attempt) => callAutomatic(config, prompt, attemptSignal, images, attempt))\n return config.limiter === undefined ? invoke() : config.limiter.run(invoke, signal)\n}\n\n/** Plain-text verifier call for conservative JSON routing; probability labels are intentionally bypassed. */\nexport async function callVerifierText(config: VerifierClientConfig, prompt: string, signal?: AbortSignal): Promise<VerifierCompletion> {\n const invoke = () => retrying(config, signal, (attemptSignal, attempt) => callExplicitTag(config, prompt, attemptSignal, undefined, attempt))\n return config.limiter === undefined ? invoke() : config.limiter.run(invoke, signal)\n}\nexport function addUsage(target: UsageStats, source: UsageStats): void { for (const key of ['calls', 'attempts', 'retries', 'inputTokens', 'cachedInputTokens', 'outputTokens', 'reasoningTokens'] as const) target[key] += source[key] }\nexport function emptyUsage(): UsageStats { return { calls: 0, attempts: 0, retries: 0, inputTokens: 0, cachedInputTokens: 0, outputTokens: 0, reasoningTokens: 0 } }\n"],"mappings":"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"}
|
package/lib/caller.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as emptyUsage, i as callVerifierText, n as addUsage, o as predictScoringChannel, r as callVerifier, t as RequestLimiter } from "./caller-
|
|
1
|
+
import { a as emptyUsage, i as callVerifierText, n as addUsage, o as predictScoringChannel, r as callVerifier, t as RequestLimiter } from "./caller-DJd_FlrQ.js";
|
|
2
2
|
export { RequestLimiter, addUsage, callVerifier, callVerifierText, emptyUsage, predictScoringChannel };
|