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` —
|
|
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)`
|
|
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
|
-
`
|
|
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
|
|
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
|
-
|
|
3
|
+
sidebarTitle: "编写自定义报告"
|
|
4
|
+
description: "用内建统计口径写出第一个 Report,再添加自定义 Measure、详情 overlay 和项目默认配置。"
|
|
4
5
|
---
|
|
5
6
|
|
|
6
|
-
|
|
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
|
-
##
|
|
19
|
+
## 写出第一个 Page
|
|
19
20
|
|
|
20
|
-
|
|
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
|
-
##
|
|
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
|
-
<
|
|
243
|
+
<Col>
|
|
83
244
|
<Bars points={rows} x="experiment" y="passRate" />
|
|
84
245
|
<Table rows={rows} caption="实验通过率" />
|
|
85
|
-
</
|
|
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
|
|
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
|
|