陆 · 校验
Jev 判断
ctx.jev
调用 TypeSafe Jev 或本地部署的 Laya(二选一),返回 Choice / Noul / Score 的类型化判断和概率;一次 judge() 有严格的总时长。
接口
import { choice, noul, score } from '@mc/dsh-agent-kit'
const { answers } = await ctx.jev.judge({
state: { input, candidate },
questions: {
wrong: noul('候选结果与输入证据不符', { true: '不符', false: '相符' }),
pick: choice('输入最符合哪个类别', { bug: '缺陷', feature: '需求', question: '咨询' }),
severity: score('严重程度', ['无影响', '轻微', '严重', '致命']),
},
signal,
traceId,
})
if (answers.wrong.noul >= 0.7) escalate()
if (answers.pick.confidence < 0.6) askHuman()judge() 返回 { model, answers, usage? }。answers 的类型按问题推断:
| 问题 | 答案 | 说明 |
|---|---|---|
noul(instructions, { true, false }) | { type: 'noul', noul } | noul 是回答”是”的概率,范围 [0, 1] |
choice(instructions, { A: 描述, B: 描述 }) | { type: 'choice', choice, confidence, probabilities } | choice 是选中的标签,probabilities 按标签给出 |
score(instructions, [档位0, 档位1, …]) | { type: 'score', score, confidence, legend, probabilities } | score 是期望分数,可能介于整数档位之间 |
问题构造函数由本包导出,与 SDK 的线上格式一致;没有启用 jev 的项目不需要安装 SDK。
Provider:Jev 与本地 Laya 二选一
provider 决定请求发往哪里,业务代码里的 ctx.jev.judge() 与返回类型不变:
| provider | 服务 | 需要 |
|---|---|---|
typesafe(默认) | TypeSafe 托管的 Jev | TypeSafe API Key |
laya | 本地部署的 Laya,接口与 Jev 相同(POST /v1/systemone) | baseURL;Key 可选 |
- id: agent-kit-jev
disabled: false
config:
provider: laya
baseURL: http://127.0.0.1:8000 # laya-serve 默认端口
apiKeyRef: LAYA_API_KEY # 可选,默认即 LAYA_API_KEYprovider: laya时baseURL必填;Key 按apiKeyRef从环境变量或 dsh 凭据文件读取,取不到则不带鉴权发送。此时不读取、也不会发送 TypeSafe Key。provider: typesafe时baseURL被忽略并记一条警告,避免 TypeSafe Key 被发往其他地址。model仍会随请求发送。Laya 只认english/multilingual/typed-decisions,其余名字(包括默认的jev-latest)按输入语言自动路由。- Laya 的上下文窗口很小(多语言模型 1024 token,英文模型 512),超出的 state 会被静默截断、不报错;
usage.input_tokens等于窗口上限即说明被截断。把要判断的内容放在 state 前面,并控制 state 长度。 - Laya 在证据就在文本里的短判断上可用,但需要常识的判断(例如由域名判断业务)明显弱于 Jev;切换前请用同一批问题对比结果与阈值。
依赖与 Key
- 需要安装可选依赖
@typesafe-ai/sdk,只有启用 jev 时才需要;两种 provider 都用它发送请求。 provider: typesafe时,TypeSafe API Key 按以下顺序读取,三处都取不到时 Service 启动失败:- 环境变量
TYPESAFE_API_KEY。 - macOS 钥匙串(仅 macOS):未配置
keychainService时默认读取共享服务名ai.typesafe.api-key,可与 gitflow-cli 共用;配置时按列表顺序尝试,空列表表示不读钥匙串。 - dsh 凭据文件
$DSH_HOME/.credentials.yaml,Linux 与 Windows 上保存 Key 的默认位置。
- 环境变量
- 读到的 Key 只在本进程内存中使用,登记为脱敏密钥,不会传给任何子进程。
超时与重试
timeoutMs是一次judge()的总时长,包含 SDK 内部的重试;超时或signal中止时取消请求。- SDK 默认对 408、429、5xx 与连接错误最多重试 2 次,但它的超时只约束单次尝试,所以本包用自己的定时器保证总时长。
- 创建 SDK 客户端时关闭其日志,避免在调试日志中输出请求体。
- 返回 401 / 403 时
health()置为failed并触发agent-kit/service-failed,之后请求成功会自动恢复;两种 provider 相同。
配置
在 Profile 的 cordis.patch.yml 中按 id agent-kit-jev 启用并给出配置。按 id 修改 config 时整段替换,未给出的字段使用默认值。下表由本包源码中的配置 schema 生成。
- id: agent-kit-jev
disabled: false
config:
# 只写需要改的字段,其余使用下表的默认值 | 字段 | 默认值 | 取值范围 | 说明 |
|---|---|---|---|
provider | typesafe | typesafe | laya | typesafe:TypeSafe 托管的 Jev;laya:本地部署的 Laya |
baseURL | — | 匹配 /^https?:\/\/\S+$/ | Laya 服务地址,provider 为 laya 时必填 |
apiKeyRef | — | 匹配 /^[A-Za-z_][A-Za-z0-9_]*$/ | Laya Key 的 ref(环境变量名 / dsh 凭据键),默认 LAYA_API_KEY |
model | jev-latest | — | SDK 支持的模型名 |
timeoutMs | 30000 | [1000, 300000] | 一次 judge() 的总时长,包含 SDK 内部重试 |
keychainService | — | 见说明 | macOS 钥匙串服务名,推荐共享名 ai.typesafe.api-key;可给列表按顺序尝试 |
keychainAccount | — | 匹配 /^[\w.@:-]{1,128}$/ | 钥匙串账户名,默认 $USER |
约束与说明
- provider 为 typesafe(默认)时,TypeSafe Key 读取顺序:环境变量 TYPESAFE_API_KEY → macOS 钥匙串(默认 ai.typesafe.api-key)→ dsh 凭据文件 $DSH_HOME/.credentials.yaml。
- provider 为 laya 时必须配置 baseURL;Key 按 apiKeyRef(默认 LAYA_API_KEY)从环境变量或 dsh 凭据读取,取不到则不带鉴权;不会读取或发送 TypeSafe Key。
- 两种 provider 都需要安装可选依赖 @typesafe-ai/sdk(Laya 与 Jev 接口相同,由 SDK 改 baseURL 发送)。
错误码
所有错误都是 KitError:用 isKitError(e) 判断,按 code 与 retryable 决定是否重试。
| code | 可重试 | 含义 |
|---|---|---|
unavailable | 是 | 网络错误、5xx、408 或超过总时长。 |
rate_limited | 是 | TypeSafe / Laya API 返回 429。 |
unauthorized | 否 | TypeSafe / Laya API 返回 401 / 403;health() 同时置为 failed。 |
bad_request | 否 | 其余 4xx 与参数错误。 |
aborted | 否 | 调用方 signal 中止或 Service 卸载。 |
invalid_config | 否 | 配置或环境变量非法,Service 启动失败。 |