niceeval 0.13.3 → 0.13.4-canary.38

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 CHANGED
@@ -44,7 +44,7 @@
44
44
  - `docs-site/zh/tutorials/connect-your-agent.mdx` — 接入你的 Agent:写一个 Adapter、配置一个 Experiment,并运行第一条评估用例。再把配置和参数从 Experiment 传给 Adapter 与被测应用。
45
45
  - `docs-site/zh/tutorials/control-run-cost.mdx` — 控制一次运行的成本:用 attempts、首过即停、budget、并发和结果沿用分别控制统计样本、停止派发、花费保护与资源占用。
46
46
  - `docs-site/zh/tutorials/criteria-files.mdx` — 隐藏测试判分:让判据文件进缓存 fingerprint:用 loadText 在模块顶层读入隐藏测试、跑测脚本等判据文件,文件内容进入 fingerprint:改一字节自动重跑,不靠人工 --rerun。
47
- - `docs-site/zh/tutorials/custom-reports.mdx` — 编写自定义报告:先定义 Analysis 统计口径,再用标准 React JSX 编写可在终端、网页和静态站阅读的 Report。
47
+ - `docs-site/zh/tutorials/custom-reports.mdx` — 编写自定义报告:用内建统计口径写出第一个 Report,再添加自定义 Measure、详情 overlay 和项目默认配置。
48
48
  - `docs-site/zh/tutorials/dataset-fanout.mdx` — 数据驱动测试(dataset fan-out):用多份数据运行同一套评估用例:从 .eval.ts 文件导出数组或 keyed record,将一套评估逻辑展开为多个 case。用 loadYaml 或 loadJson 读取外部测试集,并获得稳定 ID。
49
49
  - `docs-site/zh/tutorials/debug-lifecycle-plan.mdx` — 运行前检查生命周期计划:用 niceeval debug 查看一个 Experiment 与评估用例配对的 Plugin、Sandbox、Agent、Fixture 和 teardown 顺序,而不创建任何运行资源。
50
50
  - `docs-site/zh/tutorials/deploy-report-site.mdx` — 部署静态报告站:将 view --out 生成的完整自包含报告目录部署到任意静态托管服务。
@@ -54,6 +54,7 @@ export default defineReport({
54
54
  id: "overview",
55
55
  path: "/",
56
56
  title: { en: "Overview", "zh-CN": "概览" },
57
+ presentation: "page",
57
58
  render: () => <Overview />,
58
59
  }],
59
60
  });
@@ -96,20 +97,20 @@ const MetricCard = defineComponent<
96
97
 
97
98
  ## Page、参数和页面选择
98
99
 
99
- 普通 Page 的 `render` 可以直接接收固定 Sample,或先用 `load(sample, params, context)` 关闭输入。参数 Page 还要声明 `navigation: false` 与 `params`:
100
+ 普通 Page 的 `render` 可以直接接收固定 Sample,或先用 `load(sample, params, context)` 关闭输入。普通业务 Page 的 `presentation` 是 `"page"`。参数 Page 还要声明 `navigation: false`、`presentation` 与 `params`:
100
101
 
101
102
  - `encode(params)` 产生 canonical key;
102
103
  - `decode(key)` 必须能把同一种 key 还原;
103
104
  - `enumerate(sample)` 只为完整站点列出实例;
104
105
  - `context.evidence(locator)` 只返回当前 Sample 内的关闭证据视图。
105
106
 
106
- `pages` Report 唯一的页面集合,详情必须作为 Page 或参数 Page 显式声明;Host 不补建任何 route。`niceeval show --page <route>` 只 decode、load 和 render 这个目标 Page。它不会调用 `enumerate()` 或执行其它 Page。`niceeval view` 与 `niceeval view --out` 才会枚举全部普通 Page 和参数实例,并在所有路径、链接、资源和预算通过校验后形成完整站点。
107
+ `presentation: "overlay"` 用于叠加在当前业务 Page 上的 Attempt、Source Diff 详情。其它业务页面使用 `"page"`。`pages` 是 Report 唯一的页面集合,Host 不补建任何详情或 route。`niceeval show --page <route>` 只 decode、load 和 render 这个目标 Page。它不会调用 `enumerate()` 或执行其它 Page。`niceeval view` 与 `niceeval view --out` 才会枚举全部普通 Page 和参数实例,并在所有路径、链接、资源和预算通过校验后形成完整站点。
107
108
 
108
109
  ## JSON、网页和静态站
109
110
 
110
111
  `show --json` 固定输出英语 JSON。内建 Report 输出 Host 拥有的具名领域文档;自定义 Report 输出一个 Page 的 route、标题、80-column rendered text、下载摘要和问题表。两种 v1 JSON 都在顶层以相同的 `projections` 对象携带该目标 Page 的闭合成本数据;它们不包含作者树、HTML、全站路由或站点 identity。
111
112
 
112
- view 与静态导出使用同一份完整站点版本。同一路由的 HTTP body 与导出目录页面 body 逐字节相同。两者都携带同一个 Host runtime;静态目录找不到 view 的端点时,实时刷新会安静停用。目录不需要网络、源 Record 或 NiceEval 安装,但浏览器必须启用随包交付的 JavaScript。禁用时页面显示可操作的错误,不维护第二套阅读路径。
113
+ view 与静态导出使用同一份完整站点版本。两者只交付一个根 app shell,并通过 hash 打开已经关闭的 Page 或 overlay。它们都携带同一个 Host runtime;静态目录不会探测 view 的实时刷新端点。目录不需要网络、源 Record 或 NiceEval 安装,但必须通过 HTTP(S) 托管,且浏览器必须启用随包交付的 JavaScript。禁用时页面显示可操作的错误,不维护第二套阅读路径。
113
114
 
114
115
  ## 样式和资源边界
115
116
 
@@ -1,9 +1,10 @@
1
1
  ---
2
2
  title: "编写自定义报告"
3
- description: "先定义 Analysis 统计口径,再用标准 React JSX 编写可在终端、网页和静态站阅读的 Report。"
3
+ sidebarTitle: "编写自定义报告"
4
+ description: "用内建统计口径写出第一个 Report,再添加自定义 Measure、详情 overlay 和项目默认配置。"
4
5
  ---
5
6
 
6
- 自定义 Report 只负责页面和显示。Record 保存已发布事实,Analysis 定义总体、分母和缺失语义;Report 组织 `ClosedRows`、`MetricValue` 与关闭的 DomainView
7
+ 这篇教程会先用内建的 `model` `passRate` 写出一份可运行报告。跑通以后,再把业务统计口径拆成自定义 Measure,并了解详情 overlay
7
8
 
8
9
  ```text
9
10
  Record → Sample → Analysis
@@ -15,9 +16,169 @@ Record → Sample → Analysis
15
16
  show:一个目标 Page view / --out:全部 Page
16
17
  ```
17
18
 
18
- ## Measure 开始
19
+ ## 写出第一个 Page
19
20
 
20
- 把业务统计口径定义在 Report 模块之外。Measure 决定分母、缺失和 Evidence;页面不应从数组长度重新计算通过率或成本。
21
+ 项目需要使用 React JSX。确认 `tsconfig.json` 包含下面的选项:
22
+
23
+ ```json
24
+ {
25
+ "compilerOptions": {
26
+ "jsx": "react-jsx"
27
+ }
28
+ }
29
+ ```
30
+
31
+ 新建 `reports/quality.tsx`。先直接使用 NiceEval 提供的维度和 Measure:
32
+
33
+ ```tsx
34
+ import {
35
+ aggregate,
36
+ Bars,
37
+ Col,
38
+ defineComponent,
39
+ defineReport,
40
+ model,
41
+ passRate,
42
+ durationMs,
43
+ Section,
44
+ Table,
45
+ tokens,
46
+ } from "niceeval/report";
47
+
48
+ const QualityComparison = defineComponent(async (_props: {}, ctx) => {
49
+ const rows = await aggregate(ctx.scope, {
50
+ by: { model },
51
+ values: { passRate, durationMs, tokens },
52
+ });
53
+
54
+ return (
55
+ <Section title="模型质量">
56
+ <Col>
57
+ <Bars points={rows} x="model" y="passRate" />
58
+ <Table rows={rows} caption="各模型质量与用量" />
59
+ </Col>
60
+ </Section>
61
+ );
62
+ });
63
+
64
+ export default defineReport({
65
+ title: { en: "Quality", "zh-CN": "质量" },
66
+ pages: [{
67
+ id: "overview",
68
+ path: "/",
69
+ title: { en: "Overview", "zh-CN": "概览" },
70
+ presentation: "page",
71
+ render: () => <QualityComparison />,
72
+ }],
73
+ });
74
+ ```
75
+
76
+ Report module 必须默认导出 `defineReport()` 的结果。`ctx.scope` 是这次命令选中的固定 Sample;`aggregate()` 按模型分组,并为每组计算通过率、平均耗时和平均 Token 数。
77
+
78
+ 先用已有 Run 在终端检查这个 Page,再打开完整网页:
79
+
80
+ ```sh
81
+ pnpm exec niceeval show --run <run-id> --report ./reports/quality.tsx
82
+ pnpm exec niceeval view --run <run-id> --report ./reports/quality.tsx
83
+ ```
84
+
85
+ 第一条命令应打印“模型质量”和各模型的通过率。第二条命令会打开报告站;修改 `quality.tsx` 后,成功的 rebuild 会替换当前内容,失败时仍保留上一份可用报告。
86
+
87
+ ## 用 `aggregate()` 组装图表数据
88
+
89
+ 所有内建图表都读取 `aggregate()` 返回的同一批 rows。组装时只做三件事:
90
+
91
+ 1. `by` 决定一行代表什么,例如一个模型、Agent、Experiment 或评估用例。
92
+ 2. `values` 决定每行计算哪些指标,例如通过率、平均耗时和平均 Token 数。
93
+ 3. 图表的 `x`、`y` 与 `color` 引用这些字段名,不再读取或重新计算 Sample。
94
+
95
+ 下面这个输入会得到每个“模型 × Agent”一行的数据:
96
+
97
+ ```tsx
98
+ const rows = await aggregate(ctx.scope, {
99
+ by: { model, agent },
100
+ values: { passRate, durationMs, tokens },
101
+ });
102
+ ```
103
+
104
+ 每个指标格都是完整的 `MetricValue`,包含数值、状态、实际样本数和固定分母。把同一份 `rows` 交给多个图表,才能保证图和表使用相同口径。
105
+
106
+ ### 用柱状图比较通过率
107
+
108
+ `Bars` 适合比较一个离散维度上的同一指标。`color` 可以把第二个维度拆成不同系列:
109
+
110
+ ```tsx
111
+ import {
112
+ agent,
113
+ aggregate,
114
+ Bars,
115
+ model,
116
+ passRate,
117
+ } from "niceeval/report";
118
+
119
+ const rows = await aggregate(ctx.scope, {
120
+ by: { model, agent },
121
+ values: { passRate },
122
+ });
123
+
124
+ return <Bars points={rows} x="model" y="passRate" color="agent" />;
125
+ ```
126
+
127
+ 同一个模型由多个 Agent 运行时,这张图会按 Agent 分色。若只想比较模型,删掉 `agent` 分组和 `color` 即可。
128
+
129
+ ### 用散点图找质量与速度的取舍
130
+
131
+ `Scatter` 适合把两个连续指标放在一起。下面每个点代表一个 Experiment,横轴越靠左表示平均耗时越短,纵轴越靠上表示通过率越高:
132
+
133
+ ```tsx
134
+ import {
135
+ aggregate,
136
+ durationMs,
137
+ experiment,
138
+ model,
139
+ passRate,
140
+ Scatter,
141
+ } from "niceeval/report";
142
+
143
+ const rows = await aggregate(ctx.scope, {
144
+ by: { experiment, model },
145
+ values: { durationMs, passRate },
146
+ });
147
+
148
+ return (
149
+ <Scatter
150
+ points={rows}
151
+ x="durationMs"
152
+ y="passRate"
153
+ color="model"
154
+ />
155
+ );
156
+ ```
157
+
158
+ ### 用表格保留完整读数
159
+
160
+ 图表适合看趋势,`Table` 适合核对精确值和缺失状态。通常用 `Col` 把大图表和完整表格纵向排列:
161
+
162
+ ```tsx
163
+ return (
164
+ <Col>
165
+ <Bars points={rows} x="model" y="passRate" color="agent" />
166
+ <Table
167
+ rows={rows}
168
+ columns={["model", "agent", "passRate", "durationMs", "tokens"]}
169
+ caption="模型与 Agent 对比"
170
+ />
171
+ </Col>
172
+ );
173
+ ```
174
+
175
+ `columns` 控制展示顺序,不会改变 rows 或统计口径。省略它时,`Table` 按 rows 的字段顺序显示全部列。
176
+
177
+ `Grid` 是另一种选择,但不是另一套数据 API。它让每个直接子节点占一格,并根据宽度自动换列。截图里的摘要条就是 `<Grid><Stat ... /><Stat ... /></Grid>`。它适合 KPI 卡片或多个小面板;把 `Bars` 和大表格直接放进去时,两者也会各占一格,宽屏上可能并排,因此不是本教程的默认写法。
178
+
179
+ ## 定义自己的统计口径
180
+
181
+ 内建 Measure 不足时,把业务统计口径定义在 Report 模块之外。Measure 决定分母、缺失和 Evidence;页面不应从数组长度重新计算通过率或成本。
21
182
 
22
183
  ```ts
23
184
  // reports/quality-measures.ts
@@ -56,7 +217,7 @@ export const passRate = defineMeasure({
56
217
  });
57
218
  ```
58
219
 
59
- ## 组织一个 Page
220
+ ## Page 中使用自定义 Measure
60
221
 
61
222
  Report 模块是 `.tsx` 文件,并使用 TypeScript 的 `"jsx": "react-jsx"`。组合组件通过 `ctx.scope` 获得这次选择固定的 Sample。组件和 Page 不获得 Record reader、文件路径或浏览器请求能力。
62
223
 
@@ -65,9 +226,9 @@ Report 模块是 `.tsx` 文件,并使用 TypeScript 的 `"jsx": "react-jsx"`
65
226
  import {
66
227
  aggregate,
67
228
  Bars,
229
+ Col,
68
230
  defineComponent,
69
231
  defineReport,
70
- Grid,
71
232
  Table,
72
233
  } from "niceeval/report";
73
234
  import { experiment, passRate } from "./quality-measures.ts";
@@ -79,10 +240,10 @@ const QualityComparison = defineComponent(async (_props: {}, ctx) => {
79
240
  });
80
241
 
81
242
  return (
82
- <Grid>
243
+ <Col>
83
244
  <Bars points={rows} x="experiment" y="passRate" />
84
245
  <Table rows={rows} caption="实验通过率" />
85
- </Grid>
246
+ </Col>
86
247
  );
87
248
  });
88
249
 
@@ -92,6 +253,7 @@ export default defineReport({
92
253
  id: "overview",
93
254
  path: "/",
94
255
  title: { en: "Overview", "zh-CN": "概览" },
256
+ presentation: "page",
95
257
  render: () => <QualityComparison />,
96
258
  }],
97
259
  });
@@ -153,7 +315,11 @@ Codex sealed Usage 含 `requestKind: "model"` observation。因此即使 model r
153
315
 
154
316
  ## 添加详情与显示原语
155
317
 
156
- 需要多个详情地址时,定义参数 Page。`pages` 是唯一的页面集合,详情页必须在此显式声明;`params.enumerate(sample)` 只在 view 或静态导出时列出全部实例,Host 不会补建详情 route。`show --page <route>` 只执行请求的一个实例,并检查 `decode()` 后再 `encode()` 得到同一 canonical key。
318
+ 需要多个详情地址时,定义参数 Page。每个 Page 都要说明 `presentation`:独立业务页面使用 `"page"`,在当前页面上打开的 Attempt、Source Diff 详情使用 `"overlay"`。
319
+
320
+ `pages` 是唯一的页面集合,详情必须在此显式声明;`params.enumerate(sample)` 只在 view 或静态导出时列出全部实例,Host 不会补建详情。`show --page <route>` 只执行请求的一个实例,并检查 `decode()` 后再 `encode()` 得到同一 canonical key。
321
+
322
+ 浏览器中的 Report 只有一个根 document。业务 Page 和 overlay 通过 hash 导航;overlay 会保留当前业务 Page,按 Escape、点击关闭按钮或浏览器返回即可关闭。静态报告仍需要浏览器启用随包交付的 JavaScript。
157
323
 
158
324
  新的显示原语使用双面 `defineComponent()`:`resolve()` 最多取得一次关闭输入,`text()` 与 `web()` 同步读取同一个值。两个面不能各自再次调用 Analysis,也不能用网页专有内容代替终端文字。
159
325
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "niceeval",
3
- "version": "0.13.3",
3
+ "version": "0.13.4-canary.38",
4
4
  "description": "Agent-native eval tool — eval agents, services, functions, and coding-agent fixtures",
5
5
  "type": "module",
6
6
  "license": "MIT",