niceeval 0.6.1 → 0.6.2
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/dist/agents/types.d.ts +67 -5
- package/dist/context/types.d.ts +32 -12
- package/dist/i18n/en.d.ts +54 -0
- package/dist/i18n/zh-CN.d.ts +55 -1
- package/dist/o11y/types.d.ts +16 -2
- package/dist/report/aggregate.d.ts +5 -3
- package/dist/report/aggregate.js +32 -5
- package/dist/report/built-ins/experiment-comparison.d.ts +39 -1
- package/dist/report/built-ins/experiment-comparison.js +116 -10
- package/dist/report/built-ins/index.d.ts +1 -0
- package/dist/report/built-ins/index.js +1 -1
- package/dist/report/components.d.ts +8 -2
- package/dist/report/components.js +3 -3
- package/dist/report/compute.d.ts +11 -18
- package/dist/report/compute.js +54 -34
- package/dist/report/flag.d.ts +16 -1
- package/dist/report/flag.js +19 -1
- package/dist/report/format.d.ts +16 -8
- package/dist/report/format.js +27 -12
- package/dist/report/index.d.ts +4 -3
- package/dist/report/index.js +5 -4
- package/dist/report/locale.d.ts +11 -2
- package/dist/report/locale.js +23 -5
- package/dist/report/metrics.d.ts +13 -1
- package/dist/report/metrics.js +65 -14
- package/dist/report/primitives.d.ts +6 -0
- package/dist/report/react/AttemptList.d.ts +2 -2
- package/dist/report/react/AttemptList.js +5 -6
- package/dist/report/react/EvalList.d.ts +1 -1
- package/dist/report/react/EvalList.js +0 -0
- package/dist/report/react/ExperimentComparison.d.ts +8 -0
- package/dist/report/react/ExperimentComparison.js +11 -0
- package/dist/report/react/ExperimentList.d.ts +2 -1
- package/dist/report/react/ExperimentList.js +8 -10
- package/dist/report/react/MetricScatter.js +5 -11
- package/dist/report/react/chart-math.d.ts +23 -6
- package/dist/report/react/chart-math.js +71 -19
- package/dist/report/react/fixtures.d.ts +3 -3
- package/dist/report/react/fixtures.js +21 -14
- package/dist/report/report.d.ts +5 -1
- package/dist/report/report.js +6 -2
- package/dist/report/text/faces.d.ts +1 -1
- package/dist/report/text/faces.js +42 -41
- package/dist/report/text/table.js +36 -5
- package/dist/report/types.d.ts +39 -21
- package/dist/results/types.d.ts +11 -0
- package/dist/runner/feedback/sink.d.ts +110 -0
- package/dist/runner/types.d.ts +513 -22
- package/dist/sandbox/docker.d.ts +23 -2
- package/dist/sandbox/e2b.d.ts +15 -1
- package/dist/sandbox/errors.d.ts +30 -3
- package/dist/sandbox/io-retry.d.ts +17 -0
- package/dist/sandbox/registry.d.ts +2 -0
- package/dist/sandbox/resolve.d.ts +18 -5
- package/dist/sandbox/retry.d.ts +11 -1
- package/dist/sandbox/types.d.ts +39 -5
- package/dist/sandbox/vercel.d.ts +7 -1
- package/dist/scoring/coverage.d.ts +30 -0
- package/dist/scoring/display.d.ts +21 -0
- package/dist/scoring/display.js +120 -0
- package/dist/scoring/types.d.ts +103 -20
- package/dist/shared/aggregate.d.ts +1 -0
- package/dist/shared/aggregate.js +3 -3
- package/dist/shared/types.d.ts +28 -0
- package/dist/tty-line.d.ts +0 -4
- package/dist/util.d.ts +23 -0
- package/docs-site/zh/concepts/adapter.mdx +22 -4
- package/docs-site/zh/concepts/experiment.mdx +1 -1
- package/docs-site/zh/concepts/overview.mdx +6 -6
- package/docs-site/zh/guides/agent-feedback-loop.mdx +28 -26
- package/docs-site/zh/guides/authoring.mdx +33 -0
- package/docs-site/zh/guides/ci-integration.mdx +23 -12
- package/docs-site/zh/guides/connect-your-agent.mdx +29 -3
- package/docs-site/zh/guides/custom-reports.mdx +29 -34
- package/docs-site/zh/guides/dataset-fanout.mdx +25 -3
- package/docs-site/zh/guides/debug-sandbox.mdx +57 -0
- package/docs-site/zh/guides/debugging.mdx +210 -0
- package/docs-site/zh/guides/experiments.mdx +10 -3
- package/docs-site/zh/guides/official-adapters.mdx +26 -2
- package/docs-site/zh/guides/publish-report.mdx +30 -16
- package/docs-site/zh/guides/report-components.mdx +42 -30
- package/docs-site/zh/guides/reporters.mdx +2 -2
- package/docs-site/zh/guides/results-data.mdx +17 -9
- package/docs-site/zh/guides/runner.mdx +17 -7
- package/docs-site/zh/guides/sandbox-agent.mdx +56 -7
- package/docs-site/zh/guides/sandbox-providers.mdx +257 -9
- package/docs-site/zh/guides/scoring-guide.mdx +4 -4
- package/docs-site/zh/guides/viewing-results.mdx +79 -36
- package/docs-site/zh/guides/write-experiment.mdx +5 -3
- package/docs-site/zh/guides/write-send.mdx +17 -1
- package/docs-site/zh/index.mdx +1 -1
- package/docs-site/zh/reference/builtin-agents.mdx +27 -0
- package/docs-site/zh/reference/capabilities.mdx +2 -2
- package/docs-site/zh/reference/cli.mdx +33 -7
- package/docs-site/zh/reference/define-agent.mdx +57 -4
- package/docs-site/zh/reference/define-config.mdx +1 -1
- package/docs-site/zh/reference/define-eval.mdx +42 -9
- package/docs-site/zh/reference/expect.mdx +26 -1
- package/package.json +5 -1
- package/src/agents/ai-sdk-otel.test.ts +1 -0
- package/src/agents/ai-sdk.test.ts +3 -0
- package/src/agents/ai-sdk.ts +3 -0
- package/src/agents/bub-install-spec.test.ts +34 -0
- package/src/agents/bub-install-spec.ts +32 -0
- package/src/agents/bub.ts +31 -32
- package/src/agents/claude-code.test.ts +130 -9
- package/src/agents/claude-code.ts +76 -4
- package/src/agents/codex.test.ts +189 -40
- package/src/agents/codex.ts +155 -14
- package/src/agents/coding-cli-versions.test.ts +15 -0
- package/src/agents/coding-cli-versions.ts +3 -0
- package/src/agents/index.ts +11 -0
- package/src/agents/langgraph.test.ts +204 -0
- package/src/agents/langgraph.ts +495 -0
- package/src/agents/marketplace.ts +85 -0
- package/src/agents/native-config.test.ts +179 -0
- package/src/agents/native-config.ts +267 -0
- package/src/agents/openai-compat.test.ts +1 -0
- package/src/agents/openclaw.test.ts +31 -0
- package/src/agents/openclaw.ts +171 -0
- package/src/agents/plugin-config.test.ts +1 -0
- package/src/agents/sdk-streams.test.ts +79 -0
- package/src/agents/sdk-streams.ts +55 -10
- package/src/agents/skills.test.ts +1 -0
- package/src/agents/streaming.test.ts +3 -9
- package/src/agents/types.ts +68 -5
- package/src/agents/ui-message-stream.test.ts +3 -0
- package/src/cli.ts +411 -108
- package/src/context/context.test.ts +51 -12
- package/src/context/context.ts +161 -29
- package/src/context/session.test.ts +1 -0
- package/src/context/session.ts +114 -6
- package/src/context/types.ts +30 -12
- package/src/define.test.ts +13 -8
- package/src/define.ts +25 -4
- package/src/expect/index.ts +53 -23
- package/src/i18n/en.ts +64 -2
- package/src/i18n/zh-CN.ts +65 -3
- package/src/o11y/cost.test.ts +1 -0
- package/src/o11y/execution-tree.test.ts +1 -20
- package/src/o11y/otlp/mappers/claude-code.test.ts +1 -0
- package/src/o11y/otlp/parse.test.ts +1 -0
- package/src/o11y/otlp/turn-otel.test.ts +1 -0
- package/src/o11y/parsers/bub.test.ts +1 -0
- package/src/o11y/parsers/claude-code.test.ts +1 -34
- package/src/o11y/parsers/openclaw.test.ts +154 -0
- package/src/o11y/parsers/openclaw.ts +310 -0
- package/src/o11y/prices.json +746 -311
- package/src/o11y/tool-names.test.ts +1 -0
- package/src/o11y/types.ts +16 -2
- package/src/report/aggregate.ts +34 -5
- package/src/report/built-in-user-parity.test.tsx +110 -153
- package/src/report/built-ins/experiment-comparison.tsx +173 -13
- package/src/report/built-ins/index.ts +6 -1
- package/src/report/components.tsx +9 -3
- package/src/report/compute.ts +70 -40
- package/src/report/dual-render.test.tsx +194 -67
- package/src/report/flag.ts +30 -2
- package/src/report/format.ts +35 -11
- package/src/report/index.ts +22 -4
- package/src/report/locale.ts +25 -5
- package/src/report/metrics.ts +67 -14
- package/src/report/primitives.tsx +6 -0
- package/src/report/react/AttemptList.tsx +6 -31
- package/src/report/react/EvalList.tsx +0 -0
- package/src/report/react/ExperimentComparison.tsx +68 -0
- package/src/report/react/ExperimentList.tsx +15 -9
- package/src/report/react/MetricScatter.tsx +12 -14
- package/src/report/react/chart-math.test.ts +85 -0
- package/src/report/react/chart-math.ts +101 -22
- package/src/report/react/enhance.js +33 -1
- package/src/report/react/fixtures.ts +24 -17
- package/src/report/react/render.test.tsx +9 -64
- package/src/report/react/styles.css +73 -2
- package/src/report/report.test.ts +306 -98
- package/src/report/report.ts +6 -2
- package/src/report/text/faces.ts +47 -43
- package/src/report/text/table.ts +42 -5
- package/src/report/types.ts +41 -21
- package/src/results/annotated-source.test.ts +62 -9
- package/src/results/annotated-source.ts +64 -6
- package/src/results/attempt-evidence.test.ts +9 -7
- package/src/results/attempt-evidence.ts +15 -8
- package/src/results/attempt-source.ts +6 -3
- package/src/results/copy.ts +145 -55
- package/src/results/host-equivalence.test.ts +8 -6
- package/src/results/index.ts +2 -0
- package/src/results/locator.test.ts +1 -22
- package/src/results/open.ts +7 -1
- package/src/results/publish.ts +149 -0
- package/src/results/results.test.ts +85 -51
- package/src/results/truncate.ts +90 -0
- package/src/results/types.ts +7 -0
- package/src/results/writer.ts +31 -13
- package/src/runner/attempt.test.ts +138 -7
- package/src/runner/attempt.ts +603 -104
- package/src/runner/discover.test.ts +47 -0
- package/src/runner/discover.ts +36 -2
- package/src/runner/eval-source.test.ts +1 -27
- package/src/runner/feedback/agent.test.ts +504 -0
- package/src/runner/feedback/agent.ts +409 -0
- package/src/runner/feedback/ci.test.ts +562 -0
- package/src/runner/feedback/ci.ts +401 -0
- package/src/runner/feedback/coordinator.test.ts +317 -0
- package/src/runner/feedback/coordinator.ts +397 -0
- package/src/runner/feedback/failure.ts +40 -0
- package/src/runner/feedback/human.test.ts +616 -0
- package/src/runner/feedback/human.ts +535 -0
- package/src/runner/feedback/index.ts +66 -0
- package/src/runner/feedback/io.ts +78 -0
- package/src/runner/feedback/profile.test.ts +50 -0
- package/src/runner/feedback/profile.ts +58 -0
- package/src/runner/feedback/reducer.test.ts +395 -0
- package/src/runner/feedback/reducer.ts +260 -0
- package/src/runner/feedback/renderer.ts +82 -0
- package/src/runner/feedback/sink.ts +203 -0
- package/src/runner/feedback/testing.ts +106 -0
- package/src/runner/ledger.test.ts +230 -0
- package/src/runner/ledger.ts +329 -0
- package/src/runner/report.test.ts +128 -3
- package/src/runner/report.ts +33 -9
- package/src/runner/reporters/artifacts.ts +8 -2
- package/src/runner/reporters/braintrust.test.ts +8 -7
- package/src/runner/reporters/braintrust.ts +9 -2
- package/src/runner/reporters/index.ts +2 -2
- package/src/runner/reporters/json.test.ts +162 -0
- package/src/runner/reporters/json.ts +35 -8
- package/src/runner/reporters/shared.ts +1 -5
- package/src/runner/run.test.ts +760 -3
- package/src/runner/run.ts +242 -36
- package/src/runner/sandbox-prep.ts +3 -42
- package/src/runner/timing.ts +158 -0
- package/src/runner/types.ts +518 -22
- package/src/sandbox/checkpoint.test.ts +55 -0
- package/src/sandbox/checkpoint.ts +29 -8
- package/src/sandbox/cli-commands.ts +407 -0
- package/src/sandbox/docker.ts +115 -16
- package/src/sandbox/e2b-agent-template.test.ts +56 -0
- package/src/sandbox/e2b-agent-template.ts +94 -0
- package/src/sandbox/e2b.ts +74 -9
- package/src/sandbox/errors.ts +111 -4
- package/src/sandbox/index.ts +2 -0
- package/src/sandbox/io-retry.test.ts +58 -0
- package/src/sandbox/io-retry.ts +45 -0
- package/src/sandbox/keep-registry.test.ts +86 -0
- package/src/sandbox/keep-registry.ts +142 -0
- package/src/sandbox/keep.ts +178 -0
- package/src/sandbox/paths.test.ts +1 -0
- package/src/sandbox/paths.ts +19 -8
- package/src/sandbox/registry.ts +20 -3
- package/src/sandbox/resolve.ts +76 -11
- package/src/sandbox/retry.test.ts +70 -0
- package/src/sandbox/retry.ts +46 -4
- package/src/sandbox/types.ts +44 -6
- package/src/sandbox/vercel.ts +43 -20
- package/src/scoring/collector.ts +60 -17
- package/src/scoring/coverage.ts +95 -0
- package/src/scoring/diff.ts +81 -0
- package/src/scoring/display.test.ts +121 -0
- package/src/scoring/display.ts +133 -0
- package/src/scoring/evidence.test.ts +189 -0
- package/src/scoring/judge.test.ts +142 -0
- package/src/scoring/judge.ts +15 -18
- package/src/scoring/scoped.ts +217 -50
- package/src/scoring/types.ts +117 -20
- package/src/scoring/verdict.ts +16 -4
- package/src/shared/aggregate.ts +3 -2
- package/src/shared/types.ts +31 -0
- package/src/show/compose.ts +2 -2
- package/src/show/index.ts +21 -1
- package/src/show/render.ts +619 -104
- package/src/show/show.test.ts +235 -19
- package/src/tty-line.ts +8 -26
- package/src/util.test.ts +1 -0
- package/src/util.ts +41 -0
- package/src/view/app/components/AttemptModal.tsx +153 -2
- package/src/view/app/components/CodeView.tsx +32 -11
- package/src/view/app/components/CopyControls.tsx +2 -2
- package/src/view/app/i18n.ts +6 -0
- package/src/view/app/lib/attempt-route.test.ts +1 -0
- package/src/view/app/lib/verdict.ts +7 -9
- package/src/view/artifact-serving.test.ts +2 -1
- package/src/view/client-dist/app.css +1 -1
- package/src/view/client-dist/app.js +17 -17
- package/src/view/data.test.ts +1 -0
- package/src/view/data.ts +11 -1
- package/src/view/index.ts +11 -0
- package/src/view/server.ts +2 -0
- package/src/view/styles.css +3 -0
- package/src/view/view-report.test.ts +6 -5
- package/src/runner/reporters/console.ts +0 -70
- package/src/runner/reporters/live.test.ts +0 -56
- package/src/runner/reporters/live.ts +0 -247
- package/src/runner/reporters/quiet.test.ts +0 -66
- package/src/runner/reporters/quiet.ts +0 -49
- package/src/runner/reporters/table.ts +0 -277
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: "官方适配器一览"
|
|
3
3
|
sidebarTitle: "官方适配器"
|
|
4
|
-
description: "NiceEval 内置的 Sandbox 和非 Sandbox 适配器分别是什么、怎么鉴权,Sandbox 型里怎么装 MCP server、Skill
|
|
4
|
+
description: "NiceEval 内置的 Sandbox 和非 Sandbox 适配器分别是什么、怎么鉴权,Sandbox 型里怎么装 MCP server、Skill、插件,怎么使用 Agent 官方配置文件。"
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
[NiceEval](https://niceeval.com/) 随包带几个官方 Adapter(`niceeval/adapter` 导出的工厂函数),按被测对象要不要隔离工作区分两类:**Sandbox 型**(`claude-code` / `codex` / `bub`)在 Docker 或云端沙箱里跑 coding-agent CLI,能装 MCP server、Skill、Python 插件;**非 Sandbox 型**无侵入连一个已经在跑的 HTTP 服务,或者帮你手写 adapter 时省掉事件流映射。这篇按类型和具体 Adapter 分节,重点是每个 Adapter 的配置项——怎么选、怎么跑通第一条 eval,见[接入你的 Agent](/zh/guides/connect-your-agent)。
|
|
@@ -10,14 +10,26 @@ description: "NiceEval 内置的 Sandbox 和非 Sandbox 适配器分别是什么
|
|
|
10
10
|
|
|
11
11
|
三个内置 Sandbox agent 都用 `defineSandboxAgent` 构造,鉴权走环境变量(可用工厂参数覆盖),并且都支持在沙箱 `setup` 阶段装扩展。怎么运行内置 Sandbox agent、目录结构和自定义 Sandbox adapter,见 [Sandbox Agent](/zh/guides/sandbox-agent);这里只讲每个 Adapter 能装什么、配置项怎么写。
|
|
12
12
|
|
|
13
|
+
本页的 `settingsFile` / `configFile` 都相对 NiceEval 项目根解析。项目根是执行 `niceeval` 时的当前工作目录,也就是包含 `niceeval.config.ts` 的目录,不是 Eval 或 Experiment 文件所在目录。例如 Experiment 在 `experiments/web/no-search.ts`、配置在 `configs/codex/no-web.toml` 时,仍写 `configFile: "configs/codex/no-web.toml"`。
|
|
14
|
+
|
|
13
15
|
### claude-code
|
|
14
16
|
|
|
15
17
|
- **鉴权**:`ANTHROPIC_API_KEY`(工厂参数 `apiKey` 可覆盖),可选 `ANTHROPIC_BASE_URL`(工厂参数 `baseUrl`)。
|
|
16
18
|
- **装 MCP server**:`mcpServers` 配置项,`setup` 阶段写进沙箱里用户级的 `~/.claude.json`(顶层 `mcpServers` 字段)。
|
|
17
19
|
- **装 Skill**:`skills: SkillSpec[]`——本地 Skill(`{ kind: "local", path }`,从项目根读文件或目录)或 Repo Skill(`{ kind: "repo", source, ref, skills }`,可钉 commit/tag、可只启用多 Skill 仓库里的一部分)。装进沙箱的 project 级 `.claude/skills/<name>/`,claude CLI 原生发现(原生 `Skill` 工具调用被 adapter 归一为 `skill.loaded` 事件,不重复记成工具调用;用 `t.loadedSkill()` 断言,不是 `t.calledTool("Skill", ...)`)。
|
|
18
20
|
- **装原生 Plugin**:`plugins: ClaudeCodePluginSpec[]`,每一项声明 Marketplace 连接(`name` / `source` / 可选 `ref`)和其中的 Plugin 名。这个类型只属于 claude-code,传不进 codex。
|
|
21
|
+
- **官方配置文件**:`settingsFile` 是运行 NiceEval 的机器上的本地项目路径,不是 Sandbox 内路径;它指向一份完整的 Claude Code `settings.json`。路径相对项目根,只允许普通相对路径或 `./` 前缀;`..`、绝对路径、`~` 和解析后逃出项目根的符号链接都会报错。Adapter 从本地读取后上传文件,原样替换 Sandbox 中原本为空的用户级 `~/.claude/settings.json`;不继承宿主机配置,也不 deep merge 或重新序列化。`model` 和 `env` 归 Experiment 和 Adapter 管,出现在文件里会在 `setup` 阶段报错并点名冲突键。Secret 走环境变量,别写进配置文件。
|
|
19
22
|
- **tracing**:claude CLI 的 beta 原生遥测(`CLAUDE_CODE_ENHANCED_TELEMETRY_BETA`),span 只有结构和计时,细节见 [OTel 接入](/zh/guides/connect-otel)。
|
|
20
23
|
|
|
24
|
+
例如,用 `configs/claude-code/no-web.json` 关闭内置联网检索:
|
|
25
|
+
|
|
26
|
+
```json
|
|
27
|
+
{
|
|
28
|
+
"$schema": "https://json.schemastore.org/claude-code-settings.json",
|
|
29
|
+
"permissions": { "deny": ["WebSearch", "WebFetch"] }
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
21
33
|
```ts
|
|
22
34
|
import { defineExperiment } from "niceeval";
|
|
23
35
|
import { claudeCodeAgent } from "niceeval/adapter";
|
|
@@ -38,6 +50,7 @@ export default defineExperiment({
|
|
|
38
50
|
name: "safe-shell",
|
|
39
51
|
},
|
|
40
52
|
],
|
|
53
|
+
settingsFile: "configs/claude-code/no-web.json",
|
|
41
54
|
}),
|
|
42
55
|
model: "claude-sonnet-4-6",
|
|
43
56
|
sandbox: dockerSandbox(),
|
|
@@ -55,8 +68,16 @@ export default defineExperiment({
|
|
|
55
68
|
|
|
56
69
|
- **装 Skill**:`skills: SkillSpec[]`,与 claude-code 同一个类型。装进 `.agents/skills/<name>/`,并把发现指引写进 AGENTS.md——codex 没有 claude-code 那种原生 Skill 工具,只把文件装进去它不会主动去读;断言"用没用到"看它是否真的执行过读那个文件的 shell 命令,没有工具调用可以直接认。
|
|
57
70
|
- **装原生 Plugin**:`plugins: CodexPluginSpec[]`,声明 Marketplace 连接(`name` / `source` / 可选 `ref`)和其中的 Plugin 名。这个类型只属于 codex,传不进 claude-code。
|
|
71
|
+
- **官方配置文件**:`configFile` 是运行 NiceEval 的机器上的本地项目路径,不是 Sandbox 内路径;它指向一份完整的 Codex `config.toml`。路径相对项目根,只允许普通相对路径或 `./` 前缀;`..`、绝对路径、`~` 和解析后逃出项目根的符号链接都会报错。Adapter 从本地读取后上传文件,原样替换 Sandbox 中原本为空的用户级 `~/.codex/config.toml`;不继承宿主机配置,也不拼接、deep merge 或解析后重写。`model`、`model_provider`、`model_providers`、`model_reasoning_effort`、`mcp_servers`、`otel` 归 Experiment 和 Adapter 管,出现在文件里会在 `setup` 阶段报错并点名冲突键。Secret 走环境变量,别写进配置文件。
|
|
58
72
|
- **tracing**:内置,通过 `config.toml` 的 `[otel.trace_exporter.otlp-http]` 段配置,协议 `http/json`。
|
|
59
73
|
|
|
74
|
+
例如,用 `configs/codex/no-web.toml` 关闭内置联网检索:
|
|
75
|
+
|
|
76
|
+
```toml
|
|
77
|
+
#:schema https://developers.openai.com/codex/config-schema.json
|
|
78
|
+
web_search = "disabled"
|
|
79
|
+
```
|
|
80
|
+
|
|
60
81
|
```ts
|
|
61
82
|
import { defineExperiment } from "niceeval";
|
|
62
83
|
import { codexAgent } from "niceeval/adapter";
|
|
@@ -74,6 +95,7 @@ export default defineExperiment({
|
|
|
74
95
|
name: "repo-map",
|
|
75
96
|
},
|
|
76
97
|
],
|
|
98
|
+
configFile: "configs/codex/no-web.toml",
|
|
77
99
|
}),
|
|
78
100
|
model: "gpt-5.4",
|
|
79
101
|
sandbox: dockerSandbox(),
|
|
@@ -85,6 +107,7 @@ export default defineExperiment({
|
|
|
85
107
|
- **鉴权**:`BUB_API_KEY` + `BUB_API_BASE`(OpenAI 兼容代理),工厂参数 `apiKey` / `apiBase` 可覆盖。
|
|
86
108
|
- **装 Skill**:`skills: SkillSpec[]`,与另外两个 Adapter 同一个类型。装进 `.agents/skills/<name>/`,发现指引写进 AGENTS.md。
|
|
87
109
|
- **装插件**:`pythonPlugins: PythonPluginSpec[]`(`{ package }`:PyPI 包、版本约束或 git URL),`setup` 阶段进 `uv tool install … --with <package>`。这个类型只属于 bub;package 集合进安装 checkpoint key,插件不同的两个变体不会复用同一份安装缓存。
|
|
110
|
+
- **预制 Bub**:NiceEval 的 E2B 配方会把 Bub、OTel 插件和 Python 插件集合算成安装指纹。Adapter 只复用指纹完全一致的环境;仅在 PATH 里放一个 `bub` 不足以证明兼容。构建入口见 [沙箱 provider · 从官方基线继续构建以提速](/zh/guides/sandbox-providers#从官方基线继续构建以提速)。
|
|
88
111
|
- bub 没有 `mcpServers`——MCP 只属于支持它的 Adapter,Config 上压根没有这个字段。
|
|
89
112
|
- **安装方式**:走 `uv tool install`(PyPI 包,不是 npm 包),首次安装会建 checkpoint 缓存加速后续沙箱。
|
|
90
113
|
- **tracing**:内置,通过环境变量注入,协议 `http/protobuf`。
|
|
@@ -112,11 +135,12 @@ export default defineExperiment({
|
|
|
112
135
|
| MCP server | ✅ `mcpServers` | ✅ `mcpServers` | ❌ |
|
|
113
136
|
| Skill | ✅ `skills: SkillSpec[]`(原生发现) | ✅ `skills: SkillSpec[]`(+ 发现指引) | ✅ `skills: SkillSpec[]`(+ 发现指引) |
|
|
114
137
|
| 原生 Plugin | ✅ `plugins: ClaudeCodePluginSpec[]` | ✅ `plugins: CodexPluginSpec[]` | ❌ |
|
|
138
|
+
| 官方配置文件 | ✅ `settingsFile`(完整 settings.json) | ✅ `configFile`(完整 config.toml) | ❌ |
|
|
115
139
|
| Python Plugin | ❌ | ❌ | ✅ `pythonPlugins: PythonPluginSpec[]` |
|
|
116
140
|
| tracing | ✅(beta,仅结构与计时) | ✅ | ✅ |
|
|
117
141
|
| 安装方式 | npm 全局包 | npm 全局包 | `uv tool install`(PyPI) |
|
|
118
142
|
|
|
119
|
-
装了什么有据可查:Adapter 在 `setup` 收尾把安装清单写进沙箱的 `__niceeval__/agent-setup.json`,运行器把它存成 Attempt Artifact `agent-setup.json`(库里读 `attempt.agentSetup()`)。清单只记来源、ref、Skill/Plugin
|
|
143
|
+
装了什么有据可查:Adapter 在 `setup` 收尾把安装清单写进沙箱的 `__niceeval__/agent-setup.json`,运行器把它存成 Attempt Artifact `agent-setup.json`(库里读 `attempt.agentSetup()`)。清单只记来源、ref、Skill/Plugin 名、解析出的版本,以及官方配置文件的项目相对路径和 SHA-256;不保存配置正文、API Key 或环境变量值。
|
|
120
144
|
|
|
121
145
|
## 非 Sandbox 适配器
|
|
122
146
|
|
|
@@ -1,36 +1,50 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: "通过 CI 发布报告"
|
|
3
3
|
sidebarTitle: "CI 发布报告"
|
|
4
|
-
description: "
|
|
4
|
+
description: "把经过 copySnapshots 大小预检的结果目录提交进仓库,CI 用一行 view --run 导出报告站;超大文件在 commit 前就会得到可执行错误。"
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
`niceeval view --out <目录>` 把查看器导出成一个纯静态目录:报告、结果快照列表、transcript、trace 瀑布,和本地 `niceeval view` 看到的完全一样(导出行为见[查看结果 · 导出与静态托管](/zh/guides/viewing-results#导出与静态托管))。CI
|
|
7
|
+
`niceeval view --out <目录>` 把查看器导出成一个纯静态目录:报告、结果快照列表、transcript、trace 瀑布,和本地 `niceeval view` 看到的完全一样(导出行为见[查看结果 · 导出与静态托管](/zh/guides/viewing-results#导出与静态托管))。CI 发布只需要让结果数据到构建机手里,但不要直接提交本地事实根 `.niceeval/`:逐字符串截断能防一条失控输出膨胀,不能保证整个文件小于 Git host 的限制。先用 `copySnapshots` 生成经过 50 MiB 单文件预检的发布结果根,再提交这个目录。
|
|
8
8
|
|
|
9
|
-
##
|
|
9
|
+
## 生成可提交的结果目录
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
新建 `scripts/publish-results.ts`(项目里 eval 和配置本来就是 TypeScript,脚本也用 `.ts`,由 `tsx` 直接运行):
|
|
12
|
+
|
|
13
|
+
```javascript
|
|
14
|
+
import { rm } from "node:fs/promises";
|
|
15
|
+
import { copySnapshots, openResults } from "niceeval/results";
|
|
16
|
+
|
|
17
|
+
const output = "report-data";
|
|
18
|
+
const results = await openResults(".niceeval");
|
|
19
|
+
|
|
20
|
+
await rm(output, { recursive: true, force: true });
|
|
21
|
+
await copySnapshots(results.latest(), output, {
|
|
22
|
+
artifacts: ["sources", "events", "trace", "o11y", "agentSetup"],
|
|
23
|
+
redact: (text) => text.replaceAll(/sk-[A-Za-z0-9]+/g, "[redacted]"),
|
|
24
|
+
});
|
|
15
25
|
```
|
|
16
26
|
|
|
27
|
+
`redact` 是必填项:给一个函数改写待发布文件里的自由文本,或者确认这批数据可以原文公开、显式传 `redact: false`。要发布的站点谁都能翻到 prompt 和工具输出,这个选择必须写在脚本里。
|
|
28
|
+
|
|
29
|
+
运行 `npx tsx scripts/publish-results.ts`,然后提交 `report-data/`。`copySnapshots` 在创建目录前检查所有待发布文件;任何文件超过 50 MiB 时整体失败并列出路径、大小和处理建议,不会留下半份目录。`diff` 缺省不发布;需要 diff 时显式加进 `artifacts`,它也受同一个预算约束。历史版本留下的超大 events / trace 不会被悄悄改写,预检会要求你排除这类证据或用当前版本重跑。
|
|
30
|
+
|
|
17
31
|
## 构建命令就是导出命令
|
|
18
32
|
|
|
19
33
|
```bash
|
|
20
|
-
npx niceeval view --out site
|
|
34
|
+
npx niceeval view --run report-data --out site
|
|
21
35
|
```
|
|
22
36
|
|
|
23
|
-
`view`
|
|
37
|
+
`view` 对零可读结果直接报错、非零退出,不会导出一张空报告——`report-data/` checkout 坏掉,或所有落盘与当前 niceeval 的 schemaVersion 不兼容被整批跳过时,构建失败,Vercel / GitHub Pages 保留上一次部署。错误逐条列出被跳过的快照目录与原因,schemaVersion 场景还给出能直接查看旧落盘的 `npx niceeval@<版本> view` 命令。
|
|
24
38
|
|
|
25
39
|
## 发布自定义报告
|
|
26
40
|
|
|
27
41
|
不传 `--report` 时,发布出来的首页是默认报告。想让首页换成自己的报告,把 [`defineReport` 报告文件](/zh/guides/custom-reports)传给 `--report` 就行——attempt 证据页(transcript、trace、代码视图)仍在同一个站里,报告里的每个数字点进去就是对应证据,和本地 `view --report` 看到的一模一样:
|
|
28
42
|
|
|
29
43
|
```bash
|
|
30
|
-
npx niceeval view --report reports/exam.tsx --out site
|
|
44
|
+
npx niceeval view --run report-data --report reports/exam.tsx --out site
|
|
31
45
|
```
|
|
32
46
|
|
|
33
|
-
报告文件和
|
|
47
|
+
报告文件和 `report-data/` 一样提交在仓库里,改完版面 push,线上就跟着更新。用下面的 `vercel.json` / workflow 时,把构建命令换成这一行即可,其余配置不用动。
|
|
34
48
|
|
|
35
49
|
## 接托管平台
|
|
36
50
|
|
|
@@ -39,7 +53,7 @@ npx niceeval view --report reports/exam.tsx --out site
|
|
|
39
53
|
```json
|
|
40
54
|
{
|
|
41
55
|
"installCommand": "pnpm install --frozen-lockfile",
|
|
42
|
-
"buildCommand": "npx niceeval view --out site",
|
|
56
|
+
"buildCommand": "npx niceeval view --run report-data --out site",
|
|
43
57
|
"outputDirectory": "site"
|
|
44
58
|
}
|
|
45
59
|
```
|
|
@@ -69,7 +83,7 @@ jobs:
|
|
|
69
83
|
node-version: 22
|
|
70
84
|
cache: pnpm
|
|
71
85
|
- run: pnpm install --frozen-lockfile
|
|
72
|
-
- run: npx niceeval view --out site
|
|
86
|
+
- run: npx niceeval view --run report-data --out site
|
|
73
87
|
- uses: actions/upload-pages-artifact@v3
|
|
74
88
|
with:
|
|
75
89
|
path: site
|
|
@@ -84,8 +98,8 @@ jobs:
|
|
|
84
98
|
uses: actions/deploy-pages@v4
|
|
85
99
|
```
|
|
86
100
|
|
|
87
|
-
|
|
101
|
+
日常循环是:本地跑 eval,运行 `npx tsx scripts/publish-results.ts`,提交更新后的 `report-data/` 并 push。发布目录只保留每个实验的最新结果快照;要发布其它选择策略,在脚本里替换 `results.latest()`。本地 `.niceeval/` 可以保留完整历史和 diff,不需要为了 Git 限制削掉调试证据。
|
|
88
102
|
|
|
89
|
-
##
|
|
103
|
+
## 发布的是选中的证据
|
|
90
104
|
|
|
91
|
-
|
|
105
|
+
整站导出会带上发布结果根里选中的 transcript、源码快照和 trace。新写入的超大 events / trace 字符串可能带结构化截断标记。`copySnapshots` 只在你给了消毒函数时改写自由文本(`redact` 是必填项,见上),其余只做选择和整文件大小预检;传 `redact: false` 的目录再导出时还要加 `--allow-sensitive-artifacts` 确认一次。发布到公网前确认结果里没有密钥或敏感数据。
|
|
@@ -8,10 +8,11 @@ description: "报告文件里能摆的全部官方双面组件:每个组件回
|
|
|
8
8
|
|
|
9
9
|
## 名称与用途
|
|
10
10
|
|
|
11
|
-
英文术语描述组件形态,API
|
|
11
|
+
英文术语描述组件形态,API 名是代码里的导出名。组件分四类:默认组合件按可比组组织完整比较;实体列表逐项展示 experiment、Eval 或 Attempt;汇总组件概括整批 Selection;指标图形把指定维度聚合成值。三个实体列表的 `.data(selection)` 都返回普通数组,报告作者先用 JavaScript `.filter()` 收窄,再把 `items` 交给组件。过滤条件不藏在组件里。中文正文首次提到时用“中文名(`API 名`)”,后续可以只写中文名或 `API 名`。
|
|
12
12
|
|
|
13
13
|
| 分类 | 中文名 | English | API | 主展示单位 |
|
|
14
14
|
| --- | --- | --- | --- | --- |
|
|
15
|
+
| 组合 | 实验组比较 | Experiment comparison | `ExperimentComparison` | 按 experiment 父目录分组;每组独立的摘要、散点与实验列表 |
|
|
15
16
|
| 汇总 | 运行总览 | Run overview | `RunOverview` | 一批 Selection;汇总其中的 experiment、Eval 和 Attempt |
|
|
16
17
|
| 汇总 | 组摘要 | Group summary | `GroupSummary` | 收窄后的一批 Selection;汇总一组 experiment 和 Eval |
|
|
17
18
|
| 实体列表 | 实验列表 | Experiment list | `ExperimentList` | 每项一个 experiment;展开到该 experiment 的 Eval |
|
|
@@ -95,6 +96,18 @@ description: "报告文件里能摆的全部官方双面组件:每个组件回
|
|
|
95
96
|
|
|
96
97
|
指标表、指标矩阵、成绩单和成对差异表的终端面就建在 `Table` 上,所以你的表和官方的表用的是同一把尺子。表格之外的形态要自己排字符时,用[自定义报告](/zh/guides/custom-reports)「换形态」一节里那套文本排版函数。
|
|
97
98
|
|
|
99
|
+
## 实验组比较(`ExperimentComparison`)
|
|
100
|
+
|
|
101
|
+
`niceeval show` / `view` 不传 `--report` 时使用的默认组合件。它先按 experiment id 的完整父目录分组,再为每组分别计算组摘要、成本 × 端到端成功率散点和实验列表:
|
|
102
|
+
|
|
103
|
+
```tsx
|
|
104
|
+
<ExperimentComparison data={await ExperimentComparison.data(selection)} />
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
`compare/bub` 与 `compare/codex` 属于 `compare`,可以横向比较;`dev-e2b/bub` 属于另一个组,不会进入同一张图、同一条 series 或同一张表。顶层 experiment 没有父目录时,以自己的完整 id 形成单例组。网页面持有完整组索引并一次聚焦一组,切组不重新读取 Selection;终端面命中多组时只显示组索引与单组查看命令,命中单组时才展开详情。浏览器禁用 JS 时,每组仍以独立 `<details>` 保留完整内容。
|
|
108
|
+
|
|
109
|
+
这个分区只属于默认组合件。下面的 `MetricScatter`、`MetricTable` 和 `ExperimentList` 都忠实消费调用方传入的数据;自定义报告把跨组 Selection 传给它们,就表示明确选择跨组分析。
|
|
110
|
+
|
|
98
111
|
## 运行总览(`RunOverview`)
|
|
99
112
|
|
|
100
113
|
每张报告开头「这批数据是什么」:几个配置、几道题、通过分布、总成本、何时跑的;Selection 里的挑选警告随数据一起进来、直接显示在条内,诚实不用你另外传一遍。
|
|
@@ -126,13 +139,15 @@ Pass rate 73.3% · 2 experiments · 15 evals · failed 3 · errored 1 · $0.93
|
|
|
126
139
|
latest 2026-07-09T10:00:00Z
|
|
127
140
|
```
|
|
128
141
|
|
|
129
|
-
通过率是 eval 级折叠计票口径:同一 eval 的多轮 attempt 先折成一个判定(任一轮通过则算通过,否则取最严重的),`passed / (passed + failed + errored)`,`skipped`
|
|
142
|
+
通过率是 eval 级折叠计票口径:同一 eval 的多轮 attempt 先折成一个判定(任一轮通过则算通过,否则取最严重的),`passed / (passed + failed + errored)`,`skipped` 不进分母。页头 `RunOverview` 使用 `endToEndPassRate` 的两级聚合:先算同一道题各 Attempt 的端到端成功率,再跨题平均。两者的聚合粒度不同,但都会让 errored 降低成功率。`GroupSummary` 回答「这组题最终过了几道」,`RunOverview` 回答「每次实际运行交付成功结果的比例」,不要互相替代。`evals` 按 `experimentId + eval id` 的完整身份键去重——组里两个 experiment 各自的同名 eval 算两道题,不会被误合并成一道。`errored` 为 0 时这一段省略,但 `verdicts.errored` 这个数据字段本身永远在,省略只发生在渲染层。`totalCostUSD` 是组内可测 attempt 成本求和,一个 attempt 都没报成本时是 `null`,两面都渲染缺数据而不是 `$0`。
|
|
130
143
|
|
|
131
144
|
组摘要是普通的公开组件,`GroupSummary.data` 是普通的公开计算函数——想在自己的报告里按目录前缀分组、每组摆一块,按上面的写法收窄 Selection 再调它就行。
|
|
132
145
|
|
|
133
146
|
## 实验列表(`ExperimentList`)
|
|
134
147
|
|
|
135
|
-
每项固定代表一个 experiment。主行显示 experiment id、agent、model、flags、Eval 判定构成、通过率、Tokens、成本和耗时;展开后显示这个 experiment 的 Eval
|
|
148
|
+
每项固定代表一个 experiment。主行显示 experiment id、agent、model、flags、Eval 判定构成、通过率、Tokens、成本和耗时;展开后显示这个 experiment 的 Eval 列表。Eval 父行显示折叠判定、Attempt 数、平均耗时和平均成本;下面每个 Attempt 再显示该轮自己的失败摘要。失败内容只出现一次,不会在 Eval 与唯一 Attempt 上重复。它不接受列配置——这是 experiment 的诊断视图,不是通用指标表。默认 `ExperimentComparison` 每次只把一个可比组的 items 交给它;组件本身不猜组边界。
|
|
149
|
+
|
|
150
|
+
默认比较已经用组名作面板 / 段落标题,所以组内每行的 experiment 标签会去掉这层文件夹前缀,只显示 id 末段(和同组散点的点标签一致),不在每行重复文件夹名;完整 id 仍是排序、着色和身份的依据。独立使用 `ExperimentList`、不告诉它相对哪个组时,显示完整 id。
|
|
136
151
|
|
|
137
152
|
```tsx
|
|
138
153
|
const experiments = await ExperimentList.data(selection);
|
|
@@ -142,22 +157,19 @@ const experiments = await ExperimentList.data(selection);
|
|
|
142
157
|
/>
|
|
143
158
|
```
|
|
144
159
|
|
|
145
|
-
`niceeval show`
|
|
160
|
+
`niceeval show` 先输出 experiment 比较表,再按 experiment 展开 Eval / Attempt 父子表。Eval 父行给题级平均值,Attempt 子行给这一轮的失败摘要和 locator:
|
|
146
161
|
|
|
147
162
|
```text
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
✗
|
|
158
|
-
✗ weather/brooklyn @1h6t3vbe✗ @1j9m2qfg✗ @1k7c5rxh✗ gate calledTool("get_weather")
|
|
159
|
-
|
|
160
|
-
inspect: niceeval show @<id> [--eval|--execution|--diff]
|
|
163
|
+
Experiment Model Agent Avg duration E2E pass rate Result Tokens Est. cost
|
|
164
|
+
bub-gpt-5.4 gpt-5.4 bub 41.0s 50% 1 passed / 1 failed 42k $0.08
|
|
165
|
+
|
|
166
|
+
bub-gpt-5.4
|
|
167
|
+
Status Eval / Attempt Result Duration Cost
|
|
168
|
+
✓ passed algebra/quadratic 18.0s avg $0.02 avg
|
|
169
|
+
✓ └─ @12f9k3aq — 18.0s $0.02
|
|
170
|
+
✗ failed weather/brooklyn 42.0s avg $0.04 avg
|
|
171
|
+
✗ ├─ @1k2m9qrs calledTool("get_weather") · no calls 41.0s $0.04
|
|
172
|
+
✗ └─ @1nx4dpqr calledTool("get_weather") · no calls 43.0s $0.04
|
|
161
173
|
```
|
|
162
174
|
|
|
163
175
|
locator 由 `experimentId + snapshot.startedAt + evalId + attempt index` 的不可变身份确定,复制或发布结果后保持不变。宿主在当前结果根解析 locator;不存在或发生冲突时直接报错,不回退到“最新一次”。`@` 前缀让它与 Eval ID 前缀选择器无歧义。
|
|
@@ -166,7 +178,7 @@ locator 由 `experimentId + snapshot.startedAt + evalId + attempt index` 的不
|
|
|
166
178
|
|
|
167
179
|
## Eval 列表(`EvalList`)
|
|
168
180
|
|
|
169
|
-
每项固定代表一个 `experimentId + evalId`,因为同一个 Eval 跑在两个 experiment 上是两条不同结果。主行显示判定、Attempt
|
|
181
|
+
每项固定代表一个 `experimentId + evalId`,因为同一个 Eval 跑在两个 experiment 上是两条不同结果。主行显示判定、Attempt 数、聚合分数、平均成本和平均耗时;展开后显示这个 Eval 的 Attempt 列表,由每个 Attempt 行显示该轮自己的失败原因。Eval 主行不挑某一轮的失败原因冒充题级结论。
|
|
170
182
|
|
|
171
183
|
```tsx
|
|
172
184
|
const evals = await EvalList.data(selection);
|
|
@@ -196,7 +208,7 @@ inspect: niceeval show @<id> [--eval|--execution|--diff]
|
|
|
196
208
|
|
|
197
209
|
## Attempt 列表(`AttemptList`)
|
|
198
210
|
|
|
199
|
-
每项固定代表一个 Attempt,显示 experiment、Eval、Attempt
|
|
211
|
+
每项固定代表一个 Attempt,显示 experiment、Eval、Attempt 序号、判定、耗时、成本、失败断言、结构化 error 的一层摘要、Judge 评语和证据链接。diagnostics、cause 和 stack 留给 locator 下钻详情,避免比较列表被基础设施日志撑开。它既能列失败证据,也能列通过样本,不把 verdict 过滤写死在组件名里。
|
|
200
212
|
|
|
201
213
|
```tsx
|
|
202
214
|
const attempts = await AttemptList.data(selection, { redact });
|
|
@@ -206,7 +218,7 @@ const attempts = await AttemptList.data(selection, { redact });
|
|
|
206
218
|
/>
|
|
207
219
|
```
|
|
208
220
|
|
|
209
|
-
`niceeval show` 每项完整输出一个 Attempt
|
|
221
|
+
`niceeval show` 每项完整输出一个 Attempt,不折叠到 Eval 汇总。这里已经是叶子层,只在末尾给一条与该 Attempt 可用证据对应的模板:
|
|
210
222
|
|
|
211
223
|
```text
|
|
212
224
|
✗ @1k2m9qrs · weather/brooklyn · compare/bub-gpt-5.4 · 41s · $0.04
|
|
@@ -222,7 +234,7 @@ inspect: niceeval show @<id> [--eval|--execution|--diff]
|
|
|
222
234
|
(3 more not shown · showing 20 of 23)
|
|
223
235
|
```
|
|
224
236
|
|
|
225
|
-
|
|
237
|
+
要在页面显示前遮蔽 error message/cause/stack、diagnostic message/data、断言 detail 或 Judge 评语,把 `redact` 交给 `.data()`;稳定 code、lifecycle operation、experiment、Eval 和 locator 不改。它只影响这份组件数据,管不到发布目录里的 artifact 文件——发布数据集的消毒用 [`copySnapshots` 的 `redact` 选项](/zh/guides/results-data)。要展示哪些 Attempt,过滤返回的 `AttemptListItem[]`。`limit` 也由报告作者在数组上用 `.slice(0, 20)` 表达,截断时把原始数量交给组件的 `total`,组件据此显示“还有 n 项未展示”,不静默截断。
|
|
226
238
|
|
|
227
239
|
## 指标表(`MetricTable`)
|
|
228
240
|
|
|
@@ -231,8 +243,8 @@ inspect: niceeval show @<id> [--eval|--execution|--diff]
|
|
|
231
243
|
```tsx
|
|
232
244
|
<MetricTable data={await MetricTable.data(selection, {
|
|
233
245
|
rows: "agent",
|
|
234
|
-
columns: [
|
|
235
|
-
sort:
|
|
246
|
+
columns: [endToEndPassRate, codeLines, costUSD],
|
|
247
|
+
sort: endToEndPassRate,
|
|
236
248
|
})} />
|
|
237
249
|
```
|
|
238
250
|
|
|
@@ -251,7 +263,7 @@ codex 80% 12/15 355 lines $0.51
|
|
|
251
263
|
行 × 列两个维度、格子里一个指标,回答「哪道题谁挂了」。稀疏渲染:没有样本的格子空着,不编数。
|
|
252
264
|
|
|
253
265
|
```tsx
|
|
254
|
-
<MetricMatrix data={await MetricMatrix.data(selection, { rows: "eval", columns: "agent", cell:
|
|
266
|
+
<MetricMatrix data={await MetricMatrix.data(selection, { rows: "eval", columns: "agent", cell: endToEndPassRate })} />
|
|
255
267
|
```
|
|
256
268
|
|
|
257
269
|
```text
|
|
@@ -273,7 +285,7 @@ next: niceeval show geometry/area
|
|
|
273
285
|
<MetricBars data={await MetricBars.data(selection, {
|
|
274
286
|
rows: "evalGroup", // 一组条 = 一个科目/benchmark
|
|
275
287
|
columns: "agent", // 一根条 = 一个 agent
|
|
276
|
-
cell:
|
|
288
|
+
cell: endToEndPassRate,
|
|
277
289
|
})} />
|
|
278
290
|
```
|
|
279
291
|
|
|
@@ -317,11 +329,11 @@ codex 71.0/100 40/50 31/50 (1 missing)
|
|
|
317
329
|
points="experiment" // 每个点 = 一个配置的聚合
|
|
318
330
|
series="agent" // 同 agent 的档位连成线
|
|
319
331
|
x={costUSD}
|
|
320
|
-
y={
|
|
332
|
+
y={endToEndPassRate}
|
|
321
333
|
/>
|
|
322
334
|
```
|
|
323
335
|
|
|
324
|
-
直接把 `selection`
|
|
336
|
+
直接把 `selection` 传给它,宿主渲染前替你算好数据。`MetricScatter` 不根据 experiment id 自动分组;默认 `ExperimentComparison` 会先收窄到一个可比组,再逐组调用它。要在自己已经跑起来的 React 应用里嵌这张图、或数据是预先算好的,改传 `data`:`<MetricScatter data={await MetricScatter.data(selection, { points: "experiment", series: "agent", x: costUSD, y: endToEndPassRate })} />`;同时传 `data` 和 `selection`、或两者都不传,类型检查都会报错。
|
|
325
337
|
|
|
326
338
|
```text
|
|
327
339
|
pass ↑ (好 → 右上)
|
|
@@ -335,7 +347,7 @@ pass ↑ (好 → 右上)
|
|
|
335
347
|
A bub-high B bub-medium C codex-high D codex-low
|
|
336
348
|
```
|
|
337
349
|
|
|
338
|
-
网页面点带悬停提示(值与 `samples/total`,禁用 JS 时退化为图内提示)、同系列连线、点击深链下钻。终端面用字母标点、图例列在图下;x 或 y 缺数据的点两个面都不画,注脚如实报「n 个点缺数据」;点太密排不下时降级为坐标表,不硬挤。画得出来的点是 0 个(x 或 y
|
|
350
|
+
网页面点带悬停提示(值与 `samples/total`,禁用 JS 时退化为图内提示)、同系列连线、点击深链下钻。终端面用字母标点、图例列在图下;x 或 y 缺数据的点两个面都不画,注脚如实报「n 个点缺数据」;点太密排不下时降级为坐标表,不硬挤。画得出来的点是 0 个(x 或 y 全缺数据)时,两个面都明说这两个指标没有可用数据,不留一片空白;1 个点也照常出图——组件从不因为点不够就整块消失,让你不知道图为什么没了。维度槽也收自定义维度(`{ name, of }`,从 attempt 已有数据算组名)和 `flag()`(experiment 声明的变量),怎么选见[自定义报告](/zh/guides/custom-reports)的「换分组」一节。
|
|
339
351
|
|
|
340
352
|
## 指标趋势图(`MetricLine`)
|
|
341
353
|
|
|
@@ -345,7 +357,7 @@ x 是有序变量、每个系列一条线,回答「变量拧大,分数怎么
|
|
|
345
357
|
<MetricLine data={await MetricLine.data(selection, {
|
|
346
358
|
x: flag("latencyMs", { label: "Simulated latency", unit: "ms" }),
|
|
347
359
|
series: flag("agents", { label: (v) => `${v} agents` }),
|
|
348
|
-
y:
|
|
360
|
+
y: endToEndPassRate,
|
|
349
361
|
})} />
|
|
350
362
|
```
|
|
351
363
|
|
|
@@ -376,7 +388,7 @@ A 1 agents B 4 agents C 16 agents
|
|
|
376
388
|
{ a: "compare/bub", b: "compare/bub--agents-md", label: "bub" },
|
|
377
389
|
{ a: "compare/codex", b: "compare/codex--agents-md", label: "codex" },
|
|
378
390
|
],
|
|
379
|
-
metrics: [
|
|
391
|
+
metrics: [endToEndPassRate, costUSD],
|
|
380
392
|
})} />
|
|
381
393
|
```
|
|
382
394
|
|
|
@@ -4,7 +4,7 @@ sidebarTitle: "Reporter 上报"
|
|
|
4
4
|
description: "用内置 reporters 把 eval 结果送到 Braintrust 实验、JUnit XML 或自定义目的地。"
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
[NiceEval](https://niceeval.com/) 自己跑、自己判分;
|
|
7
|
+
[NiceEval](https://niceeval.com/) 自己跑、自己判分;Reporter 负责把完成结果送到其它目的地。运行中的 Human/Agent/CI 反馈由 `niceeval exp --output ...` 选择,不是用户配置的 Reporter;`.niceeval/` results artifacts 始终开启。其余 Reporter 从 `niceeval/reporters` 导入,按需挂载。
|
|
8
8
|
|
|
9
9
|
挂载位置有两个:
|
|
10
10
|
|
|
@@ -110,4 +110,4 @@ const notify: Reporter = {
|
|
|
110
110
|
- `onRunComplete(summary)`:运行结束,收到聚合汇总。
|
|
111
111
|
- `onEvent(event)`:更细粒度的事件流(`eval:start`、`run:budgetExceeded` 等)。
|
|
112
112
|
|
|
113
|
-
|
|
113
|
+
用户在 config/eval 中挂载的 Reporter 默认是 best-effort:抛错会形成永久 diagnostic,但不会中断在飞 Attempt。CLI 显式要求的 `--json` / `--junit` 与默认 results artifacts 是 required 输出,写失败会让最终运行判红。只有目的地没被内置覆盖时才需要自定义——`.niceeval/` 的 artifacts 已经记录了完整结果,事后分析直接读它(见[查看结果](./viewing-results))。
|
|
@@ -68,7 +68,7 @@ const attempt = snap.evals[0].attempts[0];
|
|
|
68
68
|
|
|
69
69
|
attempt.evalId; // "algebra/quadratic" —— 属于哪道题,不用绕 result
|
|
70
70
|
attempt.experimentId; // 属于哪个实验
|
|
71
|
-
attempt.result; // EvalResult
|
|
71
|
+
attempt.result; // EvalResult:判定、断言、结构化 error/diagnostics、用量、成本
|
|
72
72
|
attempt.ref; // { snapshot, attempt }:证据引用,与 view 深链、报告格子的 refs 同一身份
|
|
73
73
|
await attempt.events(); // StreamEvent[] | null
|
|
74
74
|
await attempt.trace(); // TraceSpan[] | null
|
|
@@ -83,6 +83,8 @@ await attempt.sources(); // SourceArtifact[] | null
|
|
|
83
83
|
- **读不了的落盘不静默。** 版本不兼容、目录损坏的快照进 `skipped` 并带原因;要不要展示由你定,但缺口永远被算出来。
|
|
84
84
|
- **同进程内按句柄记忆化。** 两处都读同一个 `diff()` 不会把上百 MB 读两遍。
|
|
85
85
|
|
|
86
|
+
`attempt.result.error` 是让 Attempt 进入 `errored` 的唯一致命执行错误,包含稳定 `code`、人可读 `message`、发生错误的 lifecycle operation,以及可选的有限 cause/stack。`attempt.result.diagnostics` 可以与任意判定共存,保存运行仍可继续或收尾时发现的问题。瞬时 `progress` 不落盘;OTel trace 也不是错误存储的前提。
|
|
87
|
+
|
|
86
88
|
## 超大输出会被截断
|
|
87
89
|
|
|
88
90
|
Agent 跑一条命令,输出可以大得离谱——一次递归 `grep` 扫进 `node_modules`,撞上压缩过的 JS 文件,单行就有几 MB。这种输出会同时进 `events.json` 和 `trace.json`,不管的话一个 attempt 就能占上百 MB。
|
|
@@ -106,7 +108,9 @@ for (const e of events ?? []) {
|
|
|
106
108
|
}
|
|
107
109
|
```
|
|
108
110
|
|
|
109
|
-
|
|
111
|
+
这条上限管的是**单个字符串值**,不是整个 JSON 文件。一个文件可以有很多正常值;`diff.json` 和源码也不能截断,因为它们要保持完整语义。所以 `.niceeval/` 适合做本地事实根,不默认适合直接提交进 Git。发布前用下面的 `copySnapshots` 做 artifact 选择和整文件大小检查。
|
|
112
|
+
|
|
113
|
+
截断发生在持久化边界,不能替 agent runtime 限制发给模型的工具输出。如果 runtime 先把 50 MB 工具结果完整塞进模型请求并收到 413,NiceEval 仍会把 Attempt 记为 `errored`;这里只保证失败后的 events / trace 不再被同一段输出撑爆。
|
|
110
114
|
|
|
111
115
|
## 版本:谁写的、读不读得了
|
|
112
116
|
|
|
@@ -182,7 +186,7 @@ for (const exp of results.experiments) {
|
|
|
182
186
|
|
|
183
187
|
即使在这条最深的路径上也不碰磁盘布局:路径拼接、存在性、版本过滤、快照切分全被库消化。要把这份分布摆进报告页,用 [`defineComponent`](/zh/guides/custom-reports) 包一个双面组件即可。
|
|
184
188
|
|
|
185
|
-
|
|
189
|
+
一条跨快照累计时的义务:NiceEval 默认把上一轮已有确定判定(passed / failed)、且 eval 代码和配置没变的结果携带合入新快照(`--force` 全部重跑),同一个 attempt 因此可能存在于多份落盘。携带条目不是空壳:它带着原快照的 `startedAt`(身份锚)与 `artifactBase`(指向原快照 attempt 目录的相对路径),懒加载按候选顺序回退——先本快照的 attempt 目录,再 `artifactBase` 指向的原快照目录(原快照被清理后如实返回 `null`);`ref` 指向条目所在的落盘,即携带入的那份新快照。身份键 `(experimentId, evalId, attempt, startedAt)` 的四个字段都在数据上——前两个是 attempt 的直达字段,序号与 `startedAt` 在 `attempt.result` 上。reader 忠实反映这份重复;跨快照聚合前用 `dedupeAttempts` 按身份键去重,重复保留最新快照里的那份——报告积木的计算函数内置这条,自己写脚本时记得过一遍:
|
|
186
190
|
|
|
187
191
|
```typescript
|
|
188
192
|
import { dedupeAttempts } from "niceeval/results";
|
|
@@ -210,7 +214,7 @@ const snap = await writer.snapshot({ // 建快照目录(独占创建,撞名换
|
|
|
210
214
|
});
|
|
211
215
|
|
|
212
216
|
for (const r of convertedResults) {
|
|
213
|
-
await snap.writeAttempt(r.result, { // 写 result.json(
|
|
217
|
+
await snap.writeAttempt(r.result, { // 写 result.json(判定权威落点,一次写成)+ 拆 artifact 文件
|
|
214
218
|
events: r.events, // 第二参 = artifact,都可选;缺哪样读取面就懒加载出 null
|
|
215
219
|
diff: r.diff,
|
|
216
220
|
}); // 拆 artifact 文件、算目录、回填引用,全在库内发生
|
|
@@ -219,7 +223,7 @@ for (const r of convertedResults) {
|
|
|
219
223
|
await writer.finish(); // 给每个快照补 completedAt,没有任何收尾聚合
|
|
220
224
|
```
|
|
221
225
|
|
|
222
|
-
`writer.snapshot()` 就是读取面「实验 → 快照」层次的镜像:转多个 experiment 就开多个快照目录,experimentId / agent / model / startedAt 这些快照级元数据在这里声明一次,不用塞进每条 attempt;可选的 `knownEvalIds`(该实验已知的 eval 并集)也在这里声明——它是残缺检测的分母,转换只覆盖部分题目时如实交代全集,下游的覆盖警告就能算出来(`copySnapshots` 发布时会自动补记这个字段,见下文)。转完的目录就是标准结果目录:`niceeval show` / `niceeval view` 直接能看,报告积木直接能算,不用抄格式文档;`producer` 会原样出现在读取面的 `snap.producer` 上。**每个文件恰好写入一次**是写入面的核心承诺:`snapshot.json` 开跑即写、收尾只补 `completedAt`;`result.json` 与 artifact 随 attempt 完成落盘。进程中断只丢未完成的 attempt
|
|
226
|
+
`writer.snapshot()` 就是读取面「实验 → 快照」层次的镜像:转多个 experiment 就开多个快照目录,experimentId / agent / model / startedAt 这些快照级元数据在这里声明一次,不用塞进每条 attempt;可选的 `knownEvalIds`(该实验已知的 eval 并集)也在这里声明——它是残缺检测的分母,转换只覆盖部分题目时如实交代全集,下游的覆盖警告就能算出来(`copySnapshots` 发布时会自动补记这个字段,见下文)。转完的目录就是标准结果目录:`niceeval show` / `niceeval view` 直接能看,报告积木直接能算,不用抄格式文档;`producer` 会原样出现在读取面的 `snap.producer` 上。**每个文件恰好写入一次**是写入面的核心承诺:`snapshot.json` 开跑即写、收尾只补 `completedAt`;`result.json` 与 artifact 随 attempt 完成落盘。进程中断只丢未完成的 attempt,已完成的判定与 artifact 已经在盘上——真正「有 attempt 落盘却没有 `snapshot.json`」的极端情况才归 `skipped("incomplete")`,未收尾但元数据齐全的快照能正常读,只带一条警告。
|
|
223
227
|
|
|
224
228
|
## 发布:`copySnapshots`
|
|
225
229
|
|
|
@@ -230,15 +234,19 @@ import { openResults, copySnapshots } from "niceeval/results";
|
|
|
230
234
|
|
|
231
235
|
const results = await openResults(".niceeval");
|
|
232
236
|
await copySnapshots(results.latest(), "site-data/run", {
|
|
233
|
-
artifacts: ["sources", "events", "trace", "o11y"], // diff
|
|
234
|
-
|
|
237
|
+
artifacts: ["sources", "events", "trace", "o11y"], // diff 不截断,缺省也不带;
|
|
238
|
+
redact: (text) => text.replaceAll(/sk-[A-Za-z0-9]+/g, "[redacted]"),
|
|
239
|
+
}); // redact 必填:函数消毒,或 false 显式声明原文发布;
|
|
240
|
+
// 每个待发布文件还会经过 50 MiB 预检;
|
|
235
241
|
// o11y 只有几 KB,报告用到 turns 这类
|
|
236
242
|
// 读 o11y 的指标就把它带上,不然渲染成「—」
|
|
237
243
|
```
|
|
238
244
|
|
|
239
|
-
第一个参数收 `Selection` 或手工挑的 `Snapshot[]`——和报告积木同一个输入约定。`artifacts` 的合法值是 `"events" | "trace" | "o11y" | "diff" | "sources"
|
|
245
|
+
第一个参数收 `Selection` 或手工挑的 `Snapshot[]`——和报告积木同一个输入约定。`artifacts` 的合法值是 `"events" | "trace" | "o11y" | "agentSetup" | "diff" | "sources"`;缺省带除 `diff` 外的五类。目标目录已存在且非空时报错,不静默覆盖——发布脚本要幂等就自己先清目标目录。
|
|
246
|
+
|
|
247
|
+
复制开始前,NiceEval 会规划全部目标文件并检查序列化后的大小。任一文件超过固定的 50 MiB,整次复制在创建目标目录前失败,错误会列出路径、实际大小和处理建议。你可以从 `artifacts` 排除那类证据;如果是旧版本留下的超大 events / trace,用当前版本重跑后再发布。这个检查既覆盖没有逐值截断的源码 / diff,也覆盖单值都正常但累计过大的 JSON,避免直到 `git push` 才撞上 Git host 的单文件限制。
|
|
240
248
|
|
|
241
|
-
|
|
249
|
+
大小预检只决定整次复制成功或失败,不会从一个超大文件中间删内容。消毒不是可选项——`copySnapshots` 要求显式传 `redact`:给一个函数就改写复制出来的所有文件里的自由文本(events、trace、源码、diff、运行摘要都在内;id、事件类型这类标识字段不动),确定这批数据可以原文公开就传 `redact: false`,两个都不传会直接报错。注意报告积木 `AttemptList.data` 的 `redact` 只影响页面上显示的数据,管不到发布目录里的 artifact 文件;发布场景一律在 `copySnapshots` 这一步消毒。唯一随行补记的是挑选时的**覆盖事实**:`partial-coverage` 警告的分母是实验的历史并集,而发布目录没有历史——所以每个复制出的快照带上 `knownEvalIds`(复制时刻该实验已知的 eval 并集),reader 端把它并进 `exp.evalIds` 的计算(取本地历史与快照携带值的并集)。发布目录上重新 `openResults().latest()`,残缺警告被同一套机制重新算出来,不靠发布者转述。复制出的目录就是标准结果目录,`niceeval view --run <目录>` 直接能看;要让报告站随 push 自动更新,workflow 见[通过 CI 发布报告](/zh/guides/publish-report)。
|
|
242
250
|
|
|
243
251
|
## 分层速览
|
|
244
252
|
|
|
@@ -42,10 +42,11 @@ npx niceeval exp local --max-concurrency 8
|
|
|
42
42
|
## runs 与 early-exit
|
|
43
43
|
|
|
44
44
|
```bash
|
|
45
|
-
npx niceeval exp local fixtures/button --runs 5
|
|
45
|
+
npx niceeval exp local fixtures/button --runs 5
|
|
46
|
+
npx niceeval exp local fixtures/button --runs 5 --no-early-exit
|
|
46
47
|
```
|
|
47
48
|
|
|
48
|
-
`runs` 用于测 pass rate
|
|
49
|
+
`runs` 用于测 pass rate。首过即停默认开启:某个 Attempt 通过后,同一 eval 的剩余 Attempt 会被停止。想拿完整的通过率分布时,用 `--no-early-exit` 关闭,让每个 eval 跑满 `runs` 次。
|
|
49
50
|
|
|
50
51
|
## 缓存
|
|
51
52
|
|
|
@@ -57,13 +58,22 @@ npx niceeval exp local fixtures/button --runs 5 --early-exit
|
|
|
57
58
|
npx niceeval exp local --timeout 300000 --budget 5
|
|
58
59
|
```
|
|
59
60
|
|
|
60
|
-
超时保护单个 eval,预算保护整次运行成本。
|
|
61
|
+
超时保护单个 eval,预算保护整次运行成本。NiceEval 只有在 Attempt 已经发起 Agent Turn、却连续拿不到成本数据时,才提示预算无法执行。如果 Attempt 在 `sandbox.create` 或 setup 阶段就失败,Agent 尚未运行,CLI 只显示对应的结构化执行错误,不再追加容易误导排查方向的预算警告。
|
|
61
62
|
|
|
62
63
|
## Reporter
|
|
63
64
|
|
|
64
|
-
|
|
65
|
+
运行中的反馈由 `--output` 选择消费者模型;Reporter 负责把完成后的结果写到其它目的地。两者不是同一层:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
npx niceeval exp local --output human # 人:TTY dashboard + 永久错误/诊断
|
|
69
|
+
npx niceeval exp local --output agent # AI:稳定 envelope + locator handoff
|
|
70
|
+
npx niceeval exp local --output ci # CI:单一有序 stdout 事件流
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
省略时使用 `auto`:TTY 选择 Human,CI 环境选择 CI,其它非 TTY 选择 Agent。输出模型只改变反馈,不改变调度、判定或 artifact。
|
|
74
|
+
|
|
75
|
+
Runner 在 Eval 完成后把结果交给 Reporters:
|
|
65
76
|
|
|
66
|
-
- console reporter 提供实时反馈。
|
|
67
77
|
- JSON artifacts 用于后续分析。
|
|
68
78
|
- JUnit reporter 适合 CI。
|
|
69
79
|
- Braintrust reporter 把一次运行作为实验上报,跨提交比较。
|
|
@@ -72,11 +82,11 @@ runner 在 eval 完成后把结果交给 reporters:
|
|
|
72
82
|
|
|
73
83
|
## 输出目录
|
|
74
84
|
|
|
75
|
-
每次运行会写入该实验的结果快照目录 `.niceeval/<experiment>/<快照>/`,包括快照级 `snapshot.json`,以及每个
|
|
85
|
+
每次运行会写入该实验的结果快照目录 `.niceeval/<experiment>/<快照>/`,包括快照级 `snapshot.json`,以及每个 Attempt 的 `result.json`(判定、断言、结构化错误、diagnostics)和按需生成的 `events.json`、`sources.json`、`trace.json`、`o11y.json`、`diff.json` 等拆分 artifact。瞬时 progress 不落盘。
|
|
76
86
|
|
|
77
87
|
## 推荐调试流程
|
|
78
88
|
|
|
79
89
|
1. 先跑 `npx niceeval list` 确认发现结果。
|
|
80
90
|
2. 用 `npx niceeval exp <实验> <ID 前缀>` 缩小到一个 eval。
|
|
81
|
-
3.
|
|
91
|
+
3. 失败后复制终端里的 locator,先运行 `npx niceeval show @<locator>` 看错误或断言摘要;需要 Agent 行为时再加 `--execution`,需要文件变化时加 `--diff`。
|
|
82
92
|
4. 再扩大到完整 suite 或 experiment。
|