niceeval 0.11.1-canary.8 → 0.11.1
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/INDEX.md +1 -0
- package/dist/i18n/en.d.ts +0 -1
- package/dist/i18n/en.js +5 -5
- package/dist/i18n/index.d.ts +5 -0
- package/dist/i18n/index.js +14 -3
- package/dist/i18n/zh-CN.d.ts +1 -2
- package/dist/i18n/zh-CN.js +4 -5
- package/dist/runner/types.d.ts +7 -2
- package/docs-site/zh/examples/integrations/langgraph.mdx +3 -3
- package/docs-site/zh/explanation/judge.mdx +7 -5
- package/docs-site/zh/explanation/runner.mdx +1 -1
- package/docs-site/zh/reference/cli.mdx +11 -17
- package/docs-site/zh/reference/define-config.mdx +14 -1
- package/docs-site/zh/troubleshooting/recover-after-kill.mdx +1 -1
- package/docs-site/zh/tutorials/agent-feedback-loop.mdx +11 -10
- package/docs-site/zh/tutorials/ci-integration.mdx +2 -3
- package/docs-site/zh/tutorials/configuration.mdx +165 -0
- package/docs-site/zh/tutorials/connect-your-agent.mdx +3 -1
- package/docs-site/zh/tutorials/custom-reports.mdx +30 -3
- package/docs-site/zh/tutorials/quickstart.mdx +1 -1
- package/docs-site/zh/tutorials/viewing-results.mdx +2 -2
- package/docs-site/zh/tutorials/write-experiment.mdx +22 -24
- package/package.json +1 -1
- package/src/agents/bub.ts +5 -8
- package/src/cli.ts +22 -17
- package/src/i18n/en.ts +5 -5
- package/src/i18n/index.ts +16 -3
- package/src/i18n/locale.test.ts +41 -0
- package/src/i18n/zh-CN.ts +4 -5
- package/src/runner/feedback/io.ts +1 -1
- package/src/runner/types.ts +7 -2
- package/src/scoring/judge.test.ts +47 -6
- package/src/scoring/judge.ts +15 -22
- package/src/show/index.ts +1 -1
- package/src/show/json.test.ts +3 -5
- package/src/show/show.test.ts +3 -5
package/INDEX.md
CHANGED
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
- `docs-site/zh/tutorials/agent-onboarding.mdx` — Coding Agent 从零接入项目:给 Coding Agent 的完整接入流程:探索项目、与用户确认路径、配置 Judge、写出 Adapter / Experiment / 评估用例并跑通第一个实验。
|
|
21
21
|
- `docs-site/zh/tutorials/authoring.mdx` — 编写评估用例: 单轮、多轮和数据集模式:用 defineEval 编写评估用例,包括单轮对话、多轮对话、数据驱动测试、Sandbox Workspace 和评估的生命周期与 Fixture。
|
|
22
22
|
- `docs-site/zh/tutorials/ci-integration.mdx` — 在 GitHub Actions 和 CI 中运行 NiceEval:把 NiceEval 接入 GitHub Actions 或任意 CI。评估用例失败时非零退出,输出 JUnit XML,并通过缓存加速重复运行。
|
|
23
|
+
- `docs-site/zh/tutorials/configuration.mdx` — 把配置和密钥各放到该放的地方:跑几次、超时、并发、judge、语言这些值写进代码的哪一层,API key 和 provider token 用哪些环境变量。
|
|
23
24
|
- `docs-site/zh/tutorials/connect-otel.mdx` — OTel 接入:把应用已有的 OTel span 发送给 NiceEval,在 niceeval view 中查看每轮调用瀑布图;评估用例断言仍以 Send 返回的事件和用量为准。
|
|
24
25
|
- `docs-site/zh/tutorials/connect-your-agent.mdx` — 接入你的 Agent:写一个 Adapter、配置一个 Experiment,并运行第一条评估用例;再把配置和参数从 Experiment 传给 Adapter 与被测应用。
|
|
25
26
|
- `docs-site/zh/tutorials/custom-reports.mdx` — 编写自定义报告:用 defineReport、内置报告组件和双面组件编写一份同时用于 niceeval show 与 niceeval view 的自定义报告。
|
package/dist/i18n/en.d.ts
CHANGED
package/dist/i18n/en.js
CHANGED
|
@@ -65,11 +65,10 @@ export const en = {
|
|
|
65
65
|
"runner.gateLeaseWaiting": "waiting on another run for experiment {{experimentId}}'s concurrency slots: all {{effectiveN}} in use ({{holders}}). Concurrent runs share this experiment's slots, and the smallest maxConcurrency in play wins — this run declared {{declaredN}}. Nothing dispatches until a slot frees up; the other run's slots release when its attempts finish, or 30s after it dies.\n",
|
|
66
66
|
"runner.dispatchHaltedExperiment": "experiment halted (dispatch-halted): {{message}}\n",
|
|
67
67
|
"runner.dispatchHaltedEval": "eval halted: {{message}}\n",
|
|
68
|
-
"judge.modelMissing": "No judge model configured. Set it in defineConfig({ judge: { model: \"...\" } })
|
|
68
|
+
"judge.modelMissing": "No judge model configured. Set it in defineConfig({ judge: { model: \"...\" } }) or the eval's judge config (there is no built-in default model, and no environment variable for it).\n" +
|
|
69
69
|
" Docs: node_modules/niceeval/docs-site/zh/tutorials/scoring-guide.mdx",
|
|
70
70
|
"loaders.yamlMissing": "loadYaml(\"{{path}}\") needs a YAML parser: run `pnpm add yaml` first (or switch to loadJson with a JSON dataset).",
|
|
71
71
|
"cli.flag.parseError": "{{message}}\nRun `niceeval --help` for usage.\n",
|
|
72
|
-
"cli.envInvalidNumber": "Environment variable {{name}} is not a number: \"{{value}}\".\n",
|
|
73
72
|
"cli.help": "niceeval — agent-native evals\n\n" +
|
|
74
73
|
"Usage:\n" +
|
|
75
74
|
" niceeval exp [path|experiment] [eval-id-prefix…] run experiments\n" +
|
|
@@ -122,8 +121,9 @@ export const en = {
|
|
|
122
121
|
" --json (machine feed: NDJSON on stdout; default is human text)\n" +
|
|
123
122
|
" --junit path --out dir --port n --open / --no-open -h, --help -v, --version\n\n" +
|
|
124
123
|
"Positional args only select which evals to run (id prefixes); which agent and\n" +
|
|
125
|
-
"how to run come from experiments/ + flags.
|
|
126
|
-
"
|
|
124
|
+
"how to run come from experiments/ + flags. Resolution: flag > experiment >\n" +
|
|
125
|
+
"niceeval.config.ts > built-in default. Configuration has no environment layer;\n" +
|
|
126
|
+
"environment variables hold credentials such as API keys.\n",
|
|
127
127
|
"cli.show.noResults": "No results found under {{root}}. Run `niceeval exp` first, then `niceeval show`.\n",
|
|
128
128
|
"cli.show.runDirMissing": "Results directory not found: {{dir}}\n",
|
|
129
129
|
"cli.show.noEvalMatch": "No results matched: {{patterns}}. Evals with results: {{evals}}\n",
|
|
@@ -274,7 +274,7 @@ export const en = {
|
|
|
274
274
|
"hitl.respondAllEmpty": "There is no pending input.requested request; respond() / respondAll() cannot work. Confirm the turn parked with t.parked(), then answer via t.requireInputRequest() or t.respond().",
|
|
275
275
|
"hitl.respondEmpty": "t.respond(...) requires at least one answer.",
|
|
276
276
|
"hitl.stringAmbiguous": "There are {{count}} pending input requests; a plain-string answer cannot be matched to one. Use the { request, optionId } or { request, text } object form to name it explicitly.",
|
|
277
|
-
"judge.apiKeyMissing": "judge is missing an API key
|
|
277
|
+
"judge.apiKeyMissing": "judge is missing an API key: set NICEEVAL_JUDGE_KEY, or point judge.apiKeyEnv at another environment variable.",
|
|
278
278
|
"judge.httpError": "judge HTTP {{status}}: {{body}}",
|
|
279
279
|
"judge.probeFailed": "judge precheck failed ({{model}}): {{error}}",
|
|
280
280
|
"judge.probeTimeout": "judge precheck timed out after {{seconds}}s ({{model}}): the endpoint accepted the connection but never responded — check the judge baseUrl / gateway, or point NICEEVAL_JUDGE_BASE at a responsive one",
|
package/dist/i18n/index.d.ts
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { type MessageKey } from "./zh-CN.ts";
|
|
2
2
|
import { type Locale, type Vars } from "./core.ts";
|
|
3
3
|
export type { Locale, Vars } from "./core.ts";
|
|
4
|
+
/**
|
|
5
|
+
* 注入项目配置声明的界面语言。传 undefined(没配 / 没有配置文件)时清空,回到系统 locale 判定。
|
|
6
|
+
* 无法归一的值(如 "C")同样按未声明处理——不为一个装饰性设置让命令失败。
|
|
7
|
+
*/
|
|
8
|
+
export declare function setConfiguredLocale(raw: string | undefined): void;
|
|
4
9
|
export declare function detectLocale(env?: NodeJS.ProcessEnv): Locale;
|
|
5
10
|
export declare function t(key: MessageKey, vars?: Vars): string;
|
package/dist/i18n/index.js
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
// CLI 侧 i18n:内核(插值/归一)在 core.ts
|
|
1
|
+
// CLI 侧 i18n:内核(插值/归一)在 core.ts;这里只注入来源(config.locale + 系统 locale)与
|
|
2
|
+
// zh-CN 默认值。界面语言是配置,家在 `defineConfig({ locale })`;系统 locale 是「输出到哪个
|
|
3
|
+
// 终端」的环境事实,只作没配时的判定依据。niceeval 自己不发明 NICEEVAL_LANG 这类配置变量
|
|
4
|
+
// (边界见 docs/architecture.md「配置从代码来,凭据从环境来」)。
|
|
2
5
|
import { en } from "./en.js";
|
|
3
6
|
import { zhCN } from "./zh-CN.js";
|
|
4
7
|
import { interpolate, normalizeLocale } from "./core.js";
|
|
@@ -6,9 +9,17 @@ const dictionaries = {
|
|
|
6
9
|
"zh-CN": zhCN,
|
|
7
10
|
en,
|
|
8
11
|
};
|
|
12
|
+
/** `defineConfig({ locale })` 的归一结果;CLI 装载配置后调 setConfiguredLocale 注入一次。 */
|
|
13
|
+
let configuredLocale;
|
|
14
|
+
/**
|
|
15
|
+
* 注入项目配置声明的界面语言。传 undefined(没配 / 没有配置文件)时清空,回到系统 locale 判定。
|
|
16
|
+
* 无法归一的值(如 "C")同样按未声明处理——不为一个装饰性设置让命令失败。
|
|
17
|
+
*/
|
|
18
|
+
export function setConfiguredLocale(raw) {
|
|
19
|
+
configuredLocale = normalizeLocale(raw);
|
|
20
|
+
}
|
|
9
21
|
export function detectLocale(env = process.env) {
|
|
10
|
-
return (
|
|
11
|
-
normalizeLocale(env.NICEEVAL_LOCALE) ??
|
|
22
|
+
return (configuredLocale ??
|
|
12
23
|
normalizeLocale(env.LC_ALL) ??
|
|
13
24
|
normalizeLocale(env.LC_MESSAGES) ??
|
|
14
25
|
normalizeLocale(env.LANG) ??
|
package/dist/i18n/zh-CN.d.ts
CHANGED
|
@@ -63,7 +63,6 @@ export declare const zhCN: {
|
|
|
63
63
|
readonly "judge.modelMissing": string;
|
|
64
64
|
readonly "loaders.yamlMissing": "loadYaml(\"{{path}}\") 需要 YAML 解析器:请先 `pnpm add yaml`(或改用 loadJson + JSON 数据集)。";
|
|
65
65
|
readonly "cli.flag.parseError": "{{message}}\n运行 `niceeval --help` 查看用法。\n";
|
|
66
|
-
readonly "cli.envInvalidNumber": "环境变量 {{name}} 不是数字:\"{{value}}\"。\n";
|
|
67
66
|
readonly "cli.help": string;
|
|
68
67
|
readonly "cli.show.noResults": "{{root}} 下没有结果。先 `niceeval exp` 跑一轮,再 `niceeval show`。\n";
|
|
69
68
|
readonly "cli.show.runDirMissing": "Results directory not found: {{dir}}\n";
|
|
@@ -206,7 +205,7 @@ export declare const zhCN: {
|
|
|
206
205
|
readonly "hitl.respondAllEmpty": "没有待回答的 input.requested 请求,respond() / respondAll() 无法工作;先用 t.parked() 确认停轮,再用 t.requireInputRequest() 或 t.respond() 回答。";
|
|
207
206
|
readonly "hitl.respondEmpty": "t.respond(...) 至少需要一个回答。";
|
|
208
207
|
readonly "hitl.stringAmbiguous": "有 {{count}} 条待回答请求,字符串回答无法对位,请用 { request, optionId } 或 { request, text } 对象形式显式指名。";
|
|
209
|
-
readonly "judge.apiKeyMissing": "judge 缺少 API key
|
|
208
|
+
readonly "judge.apiKeyMissing": "judge 缺少 API key:设置 NICEEVAL_JUDGE_KEY,或用 judge.apiKeyEnv 指向别的环境变量。";
|
|
210
209
|
readonly "judge.httpError": "judge HTTP {{status}}: {{body}}";
|
|
211
210
|
readonly "judge.probeFailed": "judge 预检失败({{model}}): {{error}}";
|
|
212
211
|
readonly "judge.probeTimeout": "judge 预检 {{seconds}}s 超时({{model}}):端点接受了连接但一直不回 —— 检查 judge 的 baseUrl / 网关,或把 NICEEVAL_JUDGE_BASE 指向一个有响应的网关";
|
package/dist/i18n/zh-CN.js
CHANGED
|
@@ -65,11 +65,10 @@ export const zhCN = {
|
|
|
65
65
|
"runner.gateLeaseWaiting": "在等别的运行让出实验 {{experimentId}} 的并发名额:生效的 {{effectiveN}} 个位子全被占着({{holders}})。并行运行共用同一实验的名额,生效值取在场声明里最小的那个——本次运行声明的是 {{declaredN}}。名额腾出来之前不会派发任何 attempt;对方的名额会在它的 attempt 跑完时释放,它若已死则 30s 后过期被接管。\n",
|
|
66
66
|
"runner.dispatchHaltedExperiment": "实验已止损(dispatch-halted):{{message}}\n",
|
|
67
67
|
"runner.dispatchHaltedEval": "eval 已止损:{{message}}\n",
|
|
68
|
-
"judge.modelMissing": "judge 未配置模型:在 defineConfig({ judge: { model: \"...\" } })
|
|
68
|
+
"judge.modelMissing": "judge 未配置模型:在 defineConfig({ judge: { model: \"...\" } }) 或 eval 的 judge 配置里指定裁判模型(没有内置默认模型,也没有对应的环境变量)。\n" +
|
|
69
69
|
" 文档:node_modules/niceeval/docs-site/zh/tutorials/scoring-guide.mdx",
|
|
70
70
|
"loaders.yamlMissing": "loadYaml(\"{{path}}\") 需要 YAML 解析器:请先 `pnpm add yaml`(或改用 loadJson + JSON 数据集)。",
|
|
71
71
|
"cli.flag.parseError": "{{message}}\n运行 `niceeval --help` 查看用法。\n",
|
|
72
|
-
"cli.envInvalidNumber": "环境变量 {{name}} 不是数字:\"{{value}}\"。\n",
|
|
73
72
|
"cli.help": "niceeval — agent-native evals\n\n" +
|
|
74
73
|
"用法:\n" +
|
|
75
74
|
" niceeval exp [路径|实验] [eval-id 前缀…] 跑实验\n" +
|
|
@@ -117,8 +116,8 @@ export const zhCN = {
|
|
|
117
116
|
" --json (机器面:stdout 上的 NDJSON 事件流;默认是人读文本)\n" +
|
|
118
117
|
" --junit path --out dir --port n --open / --no-open -h, --help -v, --version\n\n" +
|
|
119
118
|
"位置参数只选「跑哪些 eval」(id 前缀);对着哪个 agent、怎么跑来自 experiments/ 与\n" +
|
|
120
|
-
"
|
|
121
|
-
"
|
|
119
|
+
"标志。取值优先级:标志 > experiment > niceeval.config.ts > 内置默认;配置项没有\n" +
|
|
120
|
+
"环境变量层,环境变量只放 API key 这类凭据。\n",
|
|
122
121
|
// show 的错误文案保持英文(错误文案英文的仓库约定);noResults 是提示,翻译。
|
|
123
122
|
"cli.show.noResults": "{{root}} 下没有结果。先 `niceeval exp` 跑一轮,再 `niceeval show`。\n",
|
|
124
123
|
"cli.show.runDirMissing": "Results directory not found: {{dir}}\n",
|
|
@@ -270,7 +269,7 @@ export const zhCN = {
|
|
|
270
269
|
"hitl.respondAllEmpty": "没有待回答的 input.requested 请求,respond() / respondAll() 无法工作;先用 t.parked() 确认停轮,再用 t.requireInputRequest() 或 t.respond() 回答。",
|
|
271
270
|
"hitl.respondEmpty": "t.respond(...) 至少需要一个回答。",
|
|
272
271
|
"hitl.stringAmbiguous": "有 {{count}} 条待回答请求,字符串回答无法对位,请用 { request, optionId } 或 { request, text } 对象形式显式指名。",
|
|
273
|
-
"judge.apiKeyMissing": "judge 缺少 API key
|
|
272
|
+
"judge.apiKeyMissing": "judge 缺少 API key:设置 NICEEVAL_JUDGE_KEY,或用 judge.apiKeyEnv 指向别的环境变量。",
|
|
274
273
|
"judge.httpError": "judge HTTP {{status}}: {{body}}",
|
|
275
274
|
"judge.probeFailed": "judge 预检失败({{model}}): {{error}}",
|
|
276
275
|
"judge.probeTimeout": "judge 预检 {{seconds}}s 超时({{model}}):端点接受了连接但一直不回 —— 检查 judge 的 baseUrl / 网关,或把 NICEEVAL_JUDGE_BASE 指向一个有响应的网关",
|
package/dist/runner/types.d.ts
CHANGED
|
@@ -280,7 +280,7 @@ export interface InvocationShape {
|
|
|
280
280
|
configs: number;
|
|
281
281
|
/** 总 attempt 数(evals × configs × runs);逐行输出与汇总计数都按它。 */
|
|
282
282
|
totalAttempts: number;
|
|
283
|
-
/** 本次运行实际生效的全局并发数(flag/
|
|
283
|
+
/** 本次运行实际生效的全局并发数(flag/config/sandbox 默认值解析后的结果);
|
|
284
284
|
* 实验级 maxConcurrency 只在该实验内部限流,不改这个全局值。 */
|
|
285
285
|
maxConcurrency: number;
|
|
286
286
|
/**
|
|
@@ -615,6 +615,11 @@ export interface Config {
|
|
|
615
615
|
* 可传字符串,或按 locale 提供多语言(如 `{ en: "...", "zh-CN": "..." }`),随 view 语言切换。
|
|
616
616
|
*/
|
|
617
617
|
name?: LocalizedText;
|
|
618
|
+
/**
|
|
619
|
+
* CLI 与运行时文案的界面语言(BCP 47,如 `"en"` / `"zh-CN"`);CI 里想让日志恒定一种语言就写这个。
|
|
620
|
+
* 省略则按系统 locale(`LC_ALL` / `LC_MESSAGES` / `LANG`)判定,都没有时用 `zh-CN`。
|
|
621
|
+
*/
|
|
622
|
+
locale?: string;
|
|
618
623
|
/** 项目级默认 Sandbox provider(docker / vercel / e2b / custom);experiment 可覆盖。 */
|
|
619
624
|
sandbox?: SandboxOption;
|
|
620
625
|
/** 上传进 Sandbox 的工作区根目录,省略则用项目根;评估用例的 sandbox 视图从这里起步。 */
|
|
@@ -623,7 +628,7 @@ export interface Config {
|
|
|
623
628
|
judge?: JudgeConfig;
|
|
624
629
|
/** 项目级默认 reporter 列表(如落盘 / 上传结果);EvalDef.reporters 会与它合并。 */
|
|
625
630
|
reporters?: Reporter[];
|
|
626
|
-
/** 项目级默认并发上限;CLI flag /
|
|
631
|
+
/** 项目级默认并发上限;CLI flag / experiment 的同名设置优先级更高(没有环境变量层)。 */
|
|
627
632
|
maxConcurrency?: number;
|
|
628
633
|
/** 项目级默认单次 attempt 超时(毫秒);CLI flag / experiment / EvalDef 的同名设置优先级更高。 */
|
|
629
634
|
timeoutMs?: number;
|
|
@@ -19,7 +19,7 @@ description: "一个纯 Python LangGraph + LangSmith OTel 导出的应用,接
|
|
|
19
19
|
|
|
20
20
|
接入的全部代码变更(生成时从两个目录实测统计):
|
|
21
21
|
|
|
22
|
-
<table className="gd-summary"><tbody><tr><th>{"类别"}</th><th>{"文件数"}</th><th>{"行数"}</th></tr><tr><td>{"评估用例侧 TS 项目脚手架(必要:被测应用是 Python,全新文件)"}</td><td>{"3"}</td><td>{"+42"}</td></tr><tr><td>{"adapter(必要:传输粘合,协议映射在官方包里)"}</td><td>{"2"}</td><td>{"+
|
|
22
|
+
<table className="gd-summary"><tbody><tr><th>{"类别"}</th><th>{"文件数"}</th><th>{"行数"}</th></tr><tr><td>{"评估用例侧 TS 项目脚手架(必要:被测应用是 Python,全新文件)"}</td><td>{"3"}</td><td>{"+42"}</td></tr><tr><td>{"adapter(必要:传输粘合,协议映射在官方包里)"}</td><td>{"2"}</td><td>{"+181"}</td></tr><tr><td>{"evals 与 experiments(评测内容,按需增长)"}</td><td>{"6"}</td><td>{"+118"}</td></tr><tr className="gd-total"><td>{"合计"}</td><td>{"11"}</td><td>{"+341"}</td></tr></tbody></table>
|
|
23
23
|
|
|
24
24
|
## 文件清单
|
|
25
25
|
|
|
@@ -67,9 +67,9 @@ langgraph/
|
|
|
67
67
|
## 新增的 adapter、evals 与 experiments
|
|
68
68
|
|
|
69
69
|
<div className="gd-file">
|
|
70
|
-
<div className="gd-head"><span className="gd-name">{"niceeval.config.ts"}</span><span className="gd-stats"><span className="gd-plus">{"+
|
|
70
|
+
<div className="gd-head"><span className="gd-name">{"niceeval.config.ts"}</span><span className="gd-stats"><span className="gd-plus">{"+13"}</span></span></div>
|
|
71
71
|
<div className="gd-body">
|
|
72
|
-
<table className="gd-table"><tbody><tr className="gd-add"><td className="gd-ln"></td><td className="gd-ln">{"1"}</td><td className="gd-sign">{"+"}</td><td className="gd-code"><span className="gdt4">{"import"}</span><span className="gdt0">{" { defineConfig } "}</span><span className="gdt4">{"from"}</span><span className="gdt0">{" "}</span><span className="gdt2">{"\"niceeval\""}</span><span className="gdt0">{";"}</span></td></tr><tr className="gd-add"><td className="gd-ln"></td><td className="gd-ln">{"2"}</td><td className="gd-sign">{"+"}</td><td className="gd-code">{" "}</td></tr><tr className="gd-add"><td className="gd-ln"></td><td className="gd-ln">{"3"}</td><td className="gd-sign">{"+"}</td><td className="gd-code"><span className="gdt6">{"// 注:这个 app 的 .env 把标准的 OPENAI_API_KEY / OPENAI_BASE_URL 挪用给了 DeepSeek"}</span></td></tr><tr className="gd-add"><td className="gd-ln"></td><td className="gd-ln">{"4"}</td><td className="gd-sign">{"+"}</td><td className="gd-code"><span className="gdt6">{"// (agent.py 里 ChatOpenAI 直接读这两个 env 名)。niceeval 的 judge(t.judge.autoevals.*)"}</span></td></tr><tr className="gd-add"><td className="gd-ln"></td><td className="gd-ln">{"5"}</td><td className="gd-sign">{"+"}</td><td className="gd-code"><span className="gdt6">{"//
|
|
72
|
+
<table className="gd-table"><tbody><tr className="gd-add"><td className="gd-ln"></td><td className="gd-ln">{"1"}</td><td className="gd-sign">{"+"}</td><td className="gd-code"><span className="gdt4">{"import"}</span><span className="gdt0">{" { defineConfig } "}</span><span className="gdt4">{"from"}</span><span className="gdt0">{" "}</span><span className="gdt2">{"\"niceeval\""}</span><span className="gdt0">{";"}</span></td></tr><tr className="gd-add"><td className="gd-ln"></td><td className="gd-ln">{"2"}</td><td className="gd-sign">{"+"}</td><td className="gd-code">{" "}</td></tr><tr className="gd-add"><td className="gd-ln"></td><td className="gd-ln">{"3"}</td><td className="gd-sign">{"+"}</td><td className="gd-code"><span className="gdt6">{"// 注:这个 app 的 .env 把标准的 OPENAI_API_KEY / OPENAI_BASE_URL 挪用给了 DeepSeek"}</span></td></tr><tr className="gd-add"><td className="gd-ln"></td><td className="gd-ln">{"4"}</td><td className="gd-sign">{"+"}</td><td className="gd-code"><span className="gdt6">{"// (agent.py 里 ChatOpenAI 直接读这两个 env 名)。niceeval 的 judge(t.judge.autoevals.*)"}</span></td></tr><tr className="gd-add"><td className="gd-ln"></td><td className="gd-ln">{"5"}</td><td className="gd-sign">{"+"}</td><td className="gd-code"><span className="gdt6">{"// 不碰这两个名字:端点写在 judge.baseUrl,key 只读 NICEEVAL_JUDGE_KEY(或 judge.apiKeyEnv"}</span></td></tr><tr className="gd-add"><td className="gd-ln"></td><td className="gd-ln">{"6"}</td><td className="gd-sign">{"+"}</td><td className="gd-code"><span className="gdt6">{"// 指定的变量名),judge 走独立凭证,不和应用的模型配置互相干扰。"}</span></td></tr><tr className="gd-add"><td className="gd-ln"></td><td className="gd-ln">{"7"}</td><td className="gd-sign">{"+"}</td><td className="gd-code"><span className="gdt4">{"export"}</span><span className="gdt0">{" "}</span><span className="gdt4">{"default"}</span><span className="gdt0">{" "}</span><span className="gdt5">{"defineConfig"}</span><span className="gdt0">{"({"}</span></td></tr><tr className="gd-add"><td className="gd-ln"></td><td className="gd-ln">{"8"}</td><td className="gd-sign">{"+"}</td><td className="gd-code"><span className="gdt0">{" name: { "}</span><span className="gdt2">{"\"zh-CN\""}</span><span className="gdt0">{": "}</span><span className="gdt2">{"\"LangGraph 示例\""}</span><span className="gdt0">{", en: "}</span><span className="gdt2">{"\"LangGraph example\""}</span><span className="gdt0">{" },"}</span></td></tr><tr className="gd-add"><td className="gd-ln"></td><td className="gd-ln">{"9"}</td><td className="gd-sign">{"+"}</td><td className="gd-code"><span className="gdt0">{" judge: { model: "}</span><span className="gdt2">{"\"gpt-5.4\""}</span><span className="gdt0">{" },"}</span></td></tr><tr className="gd-add"><td className="gd-ln"></td><td className="gd-ln">{"10"}</td><td className="gd-sign">{"+"}</td><td className="gd-code"><span className="gdt0">{" timeoutMs: "}</span><span className="gdt1">{"120_000"}</span><span className="gdt0">{","}</span></td></tr><tr className="gd-add"><td className="gd-ln"></td><td className="gd-ln">{"11"}</td><td className="gd-sign">{"+"}</td><td className="gd-code"><span className="gdt0">{" "}</span><span className="gdt6">{"// 被测应用是用户自己起的长驻服务,别开太高并发。"}</span></td></tr><tr className="gd-add"><td className="gd-ln"></td><td className="gd-ln">{"12"}</td><td className="gd-sign">{"+"}</td><td className="gd-code"><span className="gdt0">{" maxConcurrency: "}</span><span className="gdt1">{"2"}</span><span className="gdt0">{","}</span></td></tr><tr className="gd-add"><td className="gd-ln"></td><td className="gd-ln">{"13"}</td><td className="gd-sign">{"+"}</td><td className="gd-code"><span className="gdt0">{"});"}</span></td></tr></tbody></table>
|
|
73
73
|
</div>
|
|
74
74
|
</div>
|
|
75
75
|
|
|
@@ -83,7 +83,7 @@ defineEval({
|
|
|
83
83
|
t.judge.autoevals.closedQA("rubric", { on: t.reply, model: "openai/gpt-4o" });
|
|
84
84
|
```
|
|
85
85
|
|
|
86
|
-
|
|
86
|
+
三级都没配就是配置错误,调用点直接报错——judge 没有内置默认模型,也没有对应的环境变量(模型是配置,只从代码来)。
|
|
87
87
|
|
|
88
88
|
## 评判端点与 key:OpenAI 兼容协议
|
|
89
89
|
|
|
@@ -100,15 +100,17 @@ defineConfig({
|
|
|
100
100
|
});
|
|
101
101
|
```
|
|
102
102
|
|
|
103
|
-
|
|
103
|
+
端点是配置,key 是凭据,两者的来源分开:
|
|
104
104
|
|
|
105
105
|
| 项 | 解析顺序 |
|
|
106
106
|
|---|---|
|
|
107
|
-
| 端点 | `judge.baseUrl` → `
|
|
108
|
-
| key | `judge.apiKeyEnv` 指定的环境变量 → `NICEEVAL_JUDGE_KEY`
|
|
107
|
+
| 端点 | `judge.baseUrl` → `https://api.openai.com/v1` |
|
|
108
|
+
| key | `judge.apiKeyEnv` 指定的环境变量 → `NICEEVAL_JUDGE_KEY` |
|
|
109
|
+
|
|
110
|
+
接自己的网关或 OpenAI 兼容代理时把地址显式写进 `judge.baseUrl`——NiceEval 不去环境里翻 `OPENAI_BASE_URL` 这类变量猜端点。key 同理只读一个名字:`judge.apiKeyEnv` 指定的那个,或默认的 `NICEEVAL_JUDGE_KEY`;judge 有自己的凭据,不会借用被测应用或某个 agent 的 key。
|
|
109
111
|
|
|
110
112
|
<Warning>
|
|
111
|
-
key
|
|
113
|
+
模型或 key 解析不到时,这条 judge 断言记成 `unavailable`(带原因),不会静默消失:除非显式链了 `.optional()`,评不了就让这次 attempt 记 `errored`——评不出来的结论既不算通过,也不该算 agent 答错。配完 key 先跑一条带 `t.judge` 的 eval,在 `niceeval view` 里确认出现了 judge 分数。
|
|
112
114
|
</Warning>
|
|
113
115
|
|
|
114
116
|
## 严重度:judge 默认 soft
|
|
@@ -54,7 +54,7 @@ npx niceeval exp local fixtures/button --runs 5 --early-exit
|
|
|
54
54
|
|
|
55
55
|
## 缓存
|
|
56
56
|
|
|
57
|
-
[NiceEval](https://niceeval.com/) 可以根据输入、配置和相关文件 fingerprint 跳过已判定为 `passed` 或 `failed` 的结果——两者都是判定确定的终态。`errored`(超时、Sandbox 异常等框架/环境层面的不确定失败)永远重试。缓存适合加速迭代,但如果你在调试非确定性行为,应该明确关闭(`--
|
|
57
|
+
[NiceEval](https://niceeval.com/) 可以根据输入、配置和相关文件 fingerprint 跳过已判定为 `passed` 或 `failed` 的结果——两者都是判定确定的终态。`errored`(超时、Sandbox 异常等框架/环境层面的不确定失败)永远重试。缓存适合加速迭代,但如果你在调试非确定性行为,应该明确关闭(`--rerun all`)或清理相关缓存。
|
|
58
58
|
|
|
59
59
|
## 并行开多个终端
|
|
60
60
|
|
|
@@ -31,14 +31,17 @@ description: "NiceEval CLI 参考:exp、show、view、init、list 和 clean
|
|
|
31
31
|
|
|
32
32
|
## 输出语言
|
|
33
33
|
|
|
34
|
-
[NiceEval](https://niceeval.com/) 的 CLI
|
|
34
|
+
[NiceEval](https://niceeval.com/) 的 CLI 和运行时文案支持本地化。要固定输出语言(CI 日志尤其需要),写在 `niceeval.config.ts` 里:
|
|
35
35
|
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
```ts
|
|
37
|
+
import { defineConfig } from "niceeval";
|
|
38
|
+
|
|
39
|
+
export default defineConfig({
|
|
40
|
+
locale: "en",
|
|
41
|
+
});
|
|
39
42
|
```
|
|
40
43
|
|
|
41
|
-
|
|
44
|
+
没写 `locale` 时按系统 locale 判定,依次看 `LC_ALL`、`LC_MESSAGES`、`LANG`。以 `zh` 开头的值使用 `zh-CN`,其它语言使用 `en`;都没有时默认 `zh-CN`。这只影响终端/runtime 文案,不改变结果 JSON 里的机器字段,也不翻译 LLM judge prompt。
|
|
42
45
|
|
|
43
46
|
## `npx niceeval exp [path|config] [id-prefix...]`
|
|
44
47
|
|
|
@@ -193,20 +196,11 @@ npx niceeval show weather/brooklyn --history
|
|
|
193
196
|
|
|
194
197
|
`--strict` 不是"更严格地报错",而是改变软阈值断言的判定:`.atLeast(n)` 这类软阈值(`soft` severity)平时失败不会把整条评估用例判为 `failed`(只是记一条不达标的断言),加了 `--strict` 之后,软阈值没达标也会让整条评估用例的 verdict 计为 `failed`。CI 中推荐加上,避免"断言分数不够但评估用例显示通过"的情况被放过。
|
|
195
198
|
|
|
196
|
-
##
|
|
197
|
-
|
|
198
|
-
以下环境变量对应部分 flag,用于不便传 CLI 参数的场景(如 CI 环境配置):
|
|
199
|
-
|
|
200
|
-
| 环境变量 | 对应 flag |
|
|
201
|
-
|---|---|
|
|
202
|
-
| `NICEEVAL_RUNS` | `--runs` |
|
|
203
|
-
| `NICEEVAL_MAX_CONCURRENCY` | `--max-concurrency` |
|
|
204
|
-
| `NICEEVAL_TIMEOUT` | `--timeout` |
|
|
205
|
-
| `NICEEVAL_BUDGET` | `--budget` |
|
|
199
|
+
## 环境变量只放凭据
|
|
206
200
|
|
|
207
|
-
|
|
201
|
+
跑几次、超时、并发、预算、judge 模型和端点、界面语言——这些都是配置,只从 CLI flag、`experiments/` 下的 experiment 文件和 `niceeval.config.ts` 读。优先级从高到低:CLI flag > experiment > `niceeval.config.ts` > 内置默认值。没有对应的环境变量,同一个值不会有第三条来路。
|
|
208
202
|
|
|
209
|
-
|
|
203
|
+
环境变量留给凭据(API key、provider token)和终端环境(`NO_COLOR`、系统 locale)。每个 agent / sandbox / judge 只认自己那一个变量名,不会在环境里翻找其它 key;启动时自动加载 cwd 下的 `.env`(不覆盖已经存在的环境变量)。完整清单和迁移对照见[配置与环境变量](/zh/tutorials/configuration)。
|
|
210
204
|
|
|
211
205
|
## 退出码
|
|
212
206
|
|
|
@@ -8,14 +8,18 @@ description: "defineConfig 参考:judge、reporters、并发、超时和 sandb
|
|
|
8
8
|
|
|
9
9
|
```ts
|
|
10
10
|
import { defineConfig } from "niceeval";
|
|
11
|
+
import site from "./reports/site";
|
|
11
12
|
|
|
12
13
|
export default defineConfig({
|
|
13
14
|
judge: { model: "gpt-5.4-mini" },
|
|
14
15
|
maxConcurrency: 4,
|
|
15
16
|
timeoutMs: 300_000,
|
|
17
|
+
report: site,
|
|
16
18
|
});
|
|
17
19
|
```
|
|
18
20
|
|
|
21
|
+
`report` 收 `defineReport` 的产物本身(import 自己的报告文件),不是路径字符串。`niceeval show` 与 `niceeval view` 不带 `--report` 时装载它,没写就装载内置的默认报告;`--report` 按次覆盖,`--report standard` 回到内置报告。写法与整套报告能力见[编写自定义报告](/zh/tutorials/custom-reports#设成项目默认)。
|
|
22
|
+
|
|
19
23
|
## Config 字段
|
|
20
24
|
|
|
21
25
|
{/* GENERATED:BEGIN config-fields */}
|
|
@@ -31,6 +35,15 @@ name?: LocalizedText;
|
|
|
31
35
|
项目名,显示在 `niceeval view` 顶部 hero(`<h1>`),省略则回退到通用标题。
|
|
32
36
|
可传字符串,或按 locale 提供多语言(如 `{ en: "...", "zh-CN": "..." }`),随 view 语言切换。
|
|
33
37
|
|
|
38
|
+
#### `locale`
|
|
39
|
+
|
|
40
|
+
```ts
|
|
41
|
+
locale?: string;
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
CLI 与运行时文案的界面语言(BCP 47,如 `"en"` / `"zh-CN"`);CI 里想让日志恒定一种语言就写这个。
|
|
45
|
+
省略则按系统 locale(`LC_ALL` / `LC_MESSAGES` / `LANG`)判定,都没有时用 `zh-CN`。
|
|
46
|
+
|
|
34
47
|
#### `sandbox`
|
|
35
48
|
|
|
36
49
|
```ts
|
|
@@ -69,7 +82,7 @@ reporters?: Reporter[];
|
|
|
69
82
|
maxConcurrency?: number;
|
|
70
83
|
```
|
|
71
84
|
|
|
72
|
-
项目级默认并发上限;CLI flag /
|
|
85
|
+
项目级默认并发上限;CLI flag / experiment 的同名设置优先级更高(没有环境变量层)。
|
|
73
86
|
|
|
74
87
|
#### `timeoutMs`
|
|
75
88
|
|
|
@@ -18,7 +18,7 @@ niceeval exp compare/bub-e2b memory/commit0
|
|
|
18
18
|
- 只补跑缺的部分:`--runs 5` 已经落盘 3 次,就只再跑 2 次。
|
|
19
19
|
- 被强杀的实验如果留了没做完的收尾,重跑会先补一次实验级 `teardown` 再开始,泄漏不会越积越多。
|
|
20
20
|
- 判定为 `errored` 的 Attempt 不复用,照常重跑。
|
|
21
|
-
- 想全部重来,加 `--
|
|
21
|
+
- 想全部重来,加 `--rerun all`。
|
|
22
22
|
|
|
23
23
|
## 收回没清理的 Sandbox 实例
|
|
24
24
|
|
|
@@ -232,15 +232,15 @@ AI 通常按任务选择这些入口:
|
|
|
232
232
|
</Step>
|
|
233
233
|
<Step title="局部重跑并验证假设">
|
|
234
234
|
```bash
|
|
235
|
-
npx niceeval exp local weather/brooklyn --json --
|
|
235
|
+
npx niceeval exp local weather/brooklyn --json --rerun all
|
|
236
236
|
npx niceeval show weather/brooklyn
|
|
237
237
|
```
|
|
238
238
|
|
|
239
|
-
位置参数按评估用例 ID 前缀缩小实验范围。调试同一个失败时加 `--
|
|
239
|
+
位置参数按评估用例 ID 前缀缩小实验范围。调试同一个失败时加 `--rerun all`,确保刚才的修改真的触发一次新运行。然后用 `show` 验证判定、断言和证据是否按预期变化。
|
|
240
240
|
</Step>
|
|
241
241
|
<Step title="全量确认没有回归">
|
|
242
242
|
```bash
|
|
243
|
-
npx niceeval exp local --json --
|
|
243
|
+
npx niceeval exp local --json --rerun all
|
|
244
244
|
npx niceeval show
|
|
245
245
|
```
|
|
246
246
|
|
|
@@ -275,25 +275,26 @@ Coding Agent 应从 `failure` / `error` 事件里取出 `locator`,再逐个运
|
|
|
275
275
|
- `events.json` 是对话与工具调用事件,`trace.json` 是调用链,`diff.json` 是 Sandbox 文件变化。
|
|
276
276
|
- 某类证据不存在时,对应文件不会生成。先以 `show` 的提示为准,不要假设每个目录都有全部文件。
|
|
277
277
|
|
|
278
|
-
`show` 的默认结果可能合成自多次运行:每个 Experiment × 评估用例选择最新判定,因此局部重跑后仍能看到其它评估用例的旧结果。该视图用于查看每条评估用例的最新已知判定;同一版代码的整体结果必须通过一次 `--
|
|
278
|
+
`show` 的默认结果可能合成自多次运行:每个 Experiment × 评估用例选择最新判定,因此局部重跑后仍能看到其它评估用例的旧结果。该视图用于查看每条评估用例的最新已知判定;同一版代码的整体结果必须通过一次 `--rerun all` 全量运行确认。
|
|
279
279
|
|
|
280
280
|
## 结果复用条件
|
|
281
281
|
|
|
282
|
-
不传 `--
|
|
282
|
+
不传 `--rerun all` 时,NiceEval 会比较当前指纹与最近结果。指纹由评估用例源码和运行配置组成,包括实验 ID、Agent、model、flags、Sandbox、timeout 与 strict 等设置。
|
|
283
283
|
|
|
284
284
|
| 最近结果与当前输入 | 本次行为 |
|
|
285
285
|
| --- | --- |
|
|
286
286
|
| 指纹相同,判定为 `passed` 或 `failed` | 携入旧结果,不重新执行 |
|
|
287
287
|
| 指纹不同 | 重新执行 |
|
|
288
288
|
| 最近结果为 `errored` 或 `skipped` | 重新执行 |
|
|
289
|
-
| 使用 `--
|
|
289
|
+
| 使用 `--rerun` | 只有 `passed` 携入,失败项重新执行 |
|
|
290
|
+
| 使用 `--rerun all` | 忽略旧结果,全部重新执行 |
|
|
290
291
|
|
|
291
292
|
被测程序的源码不在指纹里。修改实现后,即使行为已经变化,旧的 `passed` 或 `failed` 仍可能被复用。因此可以这样选择:
|
|
292
293
|
|
|
293
294
|
- 只想重看已有结果:运行 `niceeval show`,不产生新费用。
|
|
294
295
|
- 修改了评估用例或实验配置:直接重跑;指纹变化会触发对应任务。
|
|
295
|
-
-
|
|
296
|
-
- 准备结束本轮工作:对整个实验使用 `--
|
|
296
|
+
- 修改了被测程序,要复验失败项:加 `--rerun`。已通过的照常携入,不必先去找失败的评估用例 ID——失败面板的 `Retry:` 行给的就是这条命令。
|
|
297
|
+
- 准备结束本轮工作:对整个实验使用 `--rerun all`,排除其它评估用例的回归。
|
|
297
298
|
|
|
298
299
|
## 设置自主迭代协议
|
|
299
300
|
|
|
@@ -306,9 +307,9 @@ Coding Agent 应从 `failure` / `error` 事件里取出 `locator`,再逐个运
|
|
|
306
307
|
并按问题选择 --source、--execution、--timing 或 --diff;--timing 从 lifecycle 展开 setup/teardown
|
|
307
308
|
hook、shell 命令、每轮 send 与可关联的 OTel model/tool,回答整个 Attempt 的时间花在哪里。
|
|
308
309
|
写出失败原因的假设,并判断应该修改被测程序、
|
|
309
|
-
Eval,还是实验环境。修改后用 --
|
|
310
|
+
Eval,还是实验环境。修改后用 --rerun 重跑失败项,比较新的判定和证据。
|
|
310
311
|
同一问题连续三轮没有新证据或改善时停止并汇报,不要为得到通过结果而放宽正确的断言。
|
|
311
|
-
全部局部失败清零后,用 npx niceeval exp local --json --
|
|
312
|
+
全部局部失败清零后,用 npx niceeval exp local --json --rerun all 全量验证;退出码 0 才完成。
|
|
312
313
|
```
|
|
313
314
|
|
|
314
315
|
真实 Agent 的运行可能产生费用。实验阶段可以加 `--budget <美元>` 限制本轮累计成本;预算只能限制单次命令,不能替代上面的停止条件。
|
|
@@ -11,7 +11,7 @@ description: "把 NiceEval 接入 GitHub Actions 或任意 CI。评估用例失
|
|
|
11
11
|
默认情况下,只要存在失败的 gate,[NiceEval](https://niceeval.com/) 将以非零状态码退出。CI 中通常使用 `--strict`,让失败更明确。
|
|
12
12
|
|
|
13
13
|
```bash
|
|
14
|
-
|
|
14
|
+
npx niceeval exp ci \
|
|
15
15
|
--strict \
|
|
16
16
|
--junit .niceeval/junit.xml
|
|
17
17
|
```
|
|
@@ -38,7 +38,6 @@ jobs:
|
|
|
38
38
|
- run: npm ci
|
|
39
39
|
- run: npx niceeval exp ci --strict --junit .niceeval/junit.xml
|
|
40
40
|
env:
|
|
41
|
-
NICEEVAL_LANG: en
|
|
42
41
|
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
|
43
42
|
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
|
44
43
|
```
|
|
@@ -90,7 +89,7 @@ NEXT
|
|
|
90
89
|
需要机器解析运行事件(自建 annotation adapter、实时看板)时把这条命令加上 `--json`,得到同一套事实的 NDJSON 事件流,`start` 打头、`result` 收尾:
|
|
91
90
|
|
|
92
91
|
```bash
|
|
93
|
-
|
|
92
|
+
npx niceeval exp ci --strict --junit .niceeval/junit.xml --json
|
|
94
93
|
```
|
|
95
94
|
|
|
96
95
|
需要一份 JSON 汇总文件时不解析运行日志,运行后单独读结果面:
|