@cogitator-ai/evals 0.5.1 → 0.6.0
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/README.md +50 -5
- package/dist/assertions/custom.d.ts +2 -6
- package/dist/assertions/custom.d.ts.map +1 -1
- package/dist/assertions/custom.js.map +1 -1
- package/dist/assertions/index.d.ts +15 -2
- package/dist/assertions/index.d.ts.map +1 -1
- package/dist/assertions/index.js.map +1 -1
- package/dist/assertions/regression.d.ts.map +1 -1
- package/dist/assertions/regression.js +22 -1
- package/dist/assertions/regression.js.map +1 -1
- package/dist/assertions/threshold.d.ts.map +1 -1
- package/dist/assertions/threshold.js +9 -0
- package/dist/assertions/threshold.js.map +1 -1
- package/dist/eval-comparison.d.ts +5 -1
- package/dist/eval-comparison.d.ts.map +1 -1
- package/dist/eval-comparison.js +9 -3
- package/dist/eval-comparison.js.map +1 -1
- package/dist/eval-suite.d.ts +40 -7
- package/dist/eval-suite.d.ts.map +1 -1
- package/dist/eval-suite.js +204 -61
- package/dist/eval-suite.js.map +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/metrics/custom.d.ts +5 -0
- package/dist/metrics/custom.d.ts.map +1 -1
- package/dist/metrics/custom.js +19 -3
- package/dist/metrics/custom.js.map +1 -1
- package/dist/metrics/deterministic.d.ts +9 -4
- package/dist/metrics/deterministic.d.ts.map +1 -1
- package/dist/metrics/deterministic.js +26 -16
- package/dist/metrics/deterministic.js.map +1 -1
- package/dist/metrics/index.d.ts +1 -1
- package/dist/metrics/index.d.ts.map +1 -1
- package/dist/metrics/index.js.map +1 -1
- package/dist/metrics/llm-judge.d.ts +6 -5
- package/dist/metrics/llm-judge.d.ts.map +1 -1
- package/dist/metrics/llm-judge.js +84 -24
- package/dist/metrics/llm-judge.js.map +1 -1
- package/dist/metrics/types.d.ts +30 -0
- package/dist/metrics/types.d.ts.map +1 -1
- package/dist/metrics/types.js +6 -1
- package/dist/metrics/types.js.map +1 -1
- package/dist/reporters/ci.d.ts.map +1 -1
- package/dist/reporters/ci.js +2 -1
- package/dist/reporters/ci.js.map +1 -1
- package/dist/reporters/console.d.ts.map +1 -1
- package/dist/reporters/console.js +3 -1
- package/dist/reporters/console.js.map +1 -1
- package/dist/reporters/index.d.ts +5 -5
- package/dist/reporters/index.d.ts.map +1 -1
- package/dist/reporters/index.js.map +1 -1
- package/dist/schema.d.ts +7 -1
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js.map +1 -1
- package/dist/stats/t-test.js +1 -1
- package/dist/stats/t-test.js.map +1 -1
- package/package.json +5 -4
package/README.md
CHANGED
|
@@ -62,11 +62,39 @@ result.report('console');
|
|
|
62
62
|
result.saveBaseline('./baseline.json');
|
|
63
63
|
```
|
|
64
64
|
|
|
65
|
-
A target is either `{ fn: (input) => Promise<string> }` or `{ agent, cogitator }`, which runs the agent with `cogitator.run(agent, { input })` and records its usage for the statistical metrics. Defaults: `concurrency` 5, `timeout` 30 000 ms (minimum 1 000), `retries` 0.
|
|
65
|
+
A target is either `{ fn: (input, { signal, case, attempt }) => Promise<string> }` or `{ agent, cogitator }`, which runs the agent with `cogitator.run(agent, { input, context, signal })` and records its usage for the statistical metrics. Defaults: `concurrency` 5, `timeout` 30 000 ms (minimum 1 000), `retries` 0.
|
|
66
66
|
|
|
67
|
-
A case that throws or exceeds `timeout` is retried up to `retries` times. If every attempt fails, its result has an empty `output` and an `error` message describing the last failure.
|
|
67
|
+
A case that throws or exceeds `timeout` is retried up to `retries` times. A timed-out attempt is cancelled through its `signal`: an agent target's run is aborted, and a `fn` target should pass the signal on to its model call. The suite waits for the cancelled attempt to stop (at most another `timeout`) before it retries, so attempts of one case never overlap and `concurrency` holds. If every attempt fails, its result has an empty `output` and an `error` message describing the last failure.
|
|
68
68
|
|
|
69
|
-
|
|
69
|
+
```typescript
|
|
70
|
+
const suite = new EvalSuite({
|
|
71
|
+
dataset,
|
|
72
|
+
target: {
|
|
73
|
+
fn: async (input, { signal }) => {
|
|
74
|
+
const res = await fetch(MODEL_URL, { method: 'POST', body: input, signal });
|
|
75
|
+
return res.text();
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
timeout: 10_000,
|
|
79
|
+
retries: 2,
|
|
80
|
+
});
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
`suite.run(options?: EvalRunOptions)` takes `{ maxCases?: number, signal?: AbortSignal }`: with `maxCases` only the first N cases of the dataset run, and the results, aggregates, assertions and `stats.total` cover just those cases. Aborting `signal` cancels the attempts in flight, starts no further case, and `run()` rejects with the signal's reason.
|
|
84
|
+
|
|
85
|
+
A failure never drops a case. A metric that throws or returns a score that is not a finite number (such as NaN) scores 0 for that case with the reason in `score.error`, and an `onProgress` callback that throws is reported as a process warning.
|
|
86
|
+
|
|
87
|
+
`result.stats` holds:
|
|
88
|
+
|
|
89
|
+
| Field | Meaning |
|
|
90
|
+
| -------------- | ------------------------------------------------------------ |
|
|
91
|
+
| `total` | Cases run |
|
|
92
|
+
| `errors` | Cases whose every attempt failed or timed out |
|
|
93
|
+
| `metricErrors` | Metric scores that failed and count as 0 |
|
|
94
|
+
| `duration` | Wall time of the run in ms |
|
|
95
|
+
| `cost` | USD spent, `targetCost + judgeCost` |
|
|
96
|
+
| `targetCost` | USD the target spent, over every attempt that reported usage |
|
|
97
|
+
| `judgeCost` | USD the LLM judge spent |
|
|
70
98
|
|
|
71
99
|
---
|
|
72
100
|
|
|
@@ -145,6 +173,17 @@ const metrics = [
|
|
|
145
173
|
];
|
|
146
174
|
```
|
|
147
175
|
|
|
176
|
+
Every built-in per-case metric takes a `name` option. A suite refuses two metrics with the same name, because their scores would merge into one aggregate, so name the second of a kind:
|
|
177
|
+
|
|
178
|
+
```typescript
|
|
179
|
+
const metrics = [
|
|
180
|
+
regex(/\d{4}-\d{2}-\d{2}/, { name: 'hasDate' }),
|
|
181
|
+
regex(/\[\d+\]/, { name: 'hasCitation' }),
|
|
182
|
+
];
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
`regex()` ignores the `g` and `y` flags, which would make identical outputs alternate between pass and fail.
|
|
186
|
+
|
|
148
187
|
### LLM-as-Judge
|
|
149
188
|
|
|
150
189
|
Metrics scored by an LLM judge (0.0 to 1.0). They require a `judge` config on the suite and a Cogitator to run the judge agent: `judge.cogitator`, or the `cogitator` of an agent target. Without one, the suite throws when it is created.
|
|
@@ -183,6 +222,8 @@ Dataset.from([{ input: 'Write the lede', context: { dossier: dossierText } }]);
|
|
|
183
222
|
|
|
184
223
|
The `judge` option is a `JudgeConfigInput`: `{ model, temperature?, maxTokens?, cogitator? }`, with `temperature` defaulting to `0`.
|
|
185
224
|
|
|
225
|
+
The judge answers with `{ "score", "reasoning" }` JSON. A verdict in a code fence or with the score as a numeric string is read as well, and an answer without JSON falls back to its last labelled score (`Score: 0.4`, `score is 4/5`), never to a stray number in the prose. When no verdict can be read, or the judge call fails, the metric scores 0 with the reason in `score.error`. The judge's usage is reported on each score and counted in `stats.judgeCost`.
|
|
226
|
+
|
|
186
227
|
### Statistical
|
|
187
228
|
|
|
188
229
|
Aggregate metrics computed across all results. These report percentile breakdowns (p50, p95, p99) rather than per-case scores.
|
|
@@ -220,7 +261,7 @@ const suite = new EvalSuite({
|
|
|
220
261
|
});
|
|
221
262
|
```
|
|
222
263
|
|
|
223
|
-
Scores are automatically clamped to [0, 1].
|
|
264
|
+
Scores are automatically clamped to [0, 1]. A score that is not a finite number (NaN from a division by zero, Infinity) is not clamped: the metric scores 0 and reports the problem in `error`.
|
|
224
265
|
|
|
225
266
|
---
|
|
226
267
|
|
|
@@ -254,6 +295,8 @@ import { noRegression } from '@cogitator-ai/evals';
|
|
|
254
295
|
const assertions = [noRegression('./baseline.json', { tolerance: 0.05 })];
|
|
255
296
|
```
|
|
256
297
|
|
|
298
|
+
`threshold` and `noRegression` fail on a value that is not a finite number, in the results or in the baseline, and `result.saveBaseline()` refuses to write one.
|
|
299
|
+
|
|
257
300
|
### Custom assertion
|
|
258
301
|
|
|
259
302
|
```typescript
|
|
@@ -268,6 +311,8 @@ const assertions = [
|
|
|
268
311
|
];
|
|
269
312
|
```
|
|
270
313
|
|
|
314
|
+
`stats.cost` includes the LLM judge, `stats.targetCost` and `stats.judgeCost` split it.
|
|
315
|
+
|
|
271
316
|
---
|
|
272
317
|
|
|
273
318
|
## A/B Testing
|
|
@@ -303,7 +348,7 @@ for (const [name, mc] of Object.entries(result.summary.metrics)) {
|
|
|
303
348
|
}
|
|
304
349
|
```
|
|
305
350
|
|
|
306
|
-
Access full suite results via `result.baseline` and `result.challenger`.
|
|
351
|
+
Access full suite results via `result.baseline` and `result.challenger`. `comparison.run({ signal })` cancels both runs.
|
|
307
352
|
|
|
308
353
|
---
|
|
309
354
|
|
|
@@ -1,11 +1,7 @@
|
|
|
1
|
-
import type { AssertionFn, AggregatedMetric } from './index.js';
|
|
1
|
+
import type { AssertionFn, AggregatedMetric, EvalStats } from './index.js';
|
|
2
2
|
export declare function assertion(opts: {
|
|
3
3
|
name: string;
|
|
4
|
-
check: (aggregated: Record<string, AggregatedMetric>, stats:
|
|
5
|
-
total: number;
|
|
6
|
-
duration: number;
|
|
7
|
-
cost: number;
|
|
8
|
-
}) => boolean;
|
|
4
|
+
check: (aggregated: Record<string, AggregatedMetric>, stats: EvalStats) => boolean;
|
|
9
5
|
message?: string;
|
|
10
6
|
}): AssertionFn;
|
|
11
7
|
//# sourceMappingURL=custom.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"custom.d.ts","sourceRoot":"","sources":["../../src/assertions/custom.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"custom.d.ts","sourceRoot":"","sources":["../../src/assertions/custom.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAExE,wBAAgB,SAAS,CAAC,IAAI,EAAE;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,EAAE,KAAK,EAAE,SAAS,KAAK,OAAO,CAAC;IACnF,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,GAAG,WAAW,CAqBd"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"custom.js","sourceRoot":"","sources":["../../src/assertions/custom.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,SAAS,CAAC,
|
|
1
|
+
{"version":3,"file":"custom.js","sourceRoot":"","sources":["../../src/assertions/custom.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,SAAS,CAAC,IAIzB;IACC,OAAO,CAAC,UAAU,EAAE,KAAK,EAAE,EAAE;QAC3B,IAAI,MAAe,CAAC;QACpB,IAAI,CAAC;YACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;QACzC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO;gBACL,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,MAAM,EAAE,KAAK;gBACb,OAAO,EAAE,qBAAqB,IAAI,CAAC,IAAI,YAAa,GAAa,CAAC,OAAO,EAAE;aAC5E,CAAC;QACJ,CAAC;QAED,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,MAAM;YACN,OAAO,EAAE,MAAM;gBACb,CAAC,CAAC,qBAAqB,IAAI,CAAC,IAAI,UAAU;gBAC1C,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,IAAI,qBAAqB,IAAI,CAAC,IAAI,UAAU,CAAC;SAC/D,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -18,11 +18,24 @@ export interface AssertionResult {
|
|
|
18
18
|
actual?: number;
|
|
19
19
|
expected?: number;
|
|
20
20
|
}
|
|
21
|
-
|
|
21
|
+
/** Run-wide figures of a suite run */
|
|
22
|
+
export interface EvalStats {
|
|
23
|
+
/** Cases run */
|
|
22
24
|
total: number;
|
|
25
|
+
/** Cases whose every attempt failed or timed out (`error` set on the result) */
|
|
26
|
+
errors?: number;
|
|
27
|
+
/** Metric scores that failed (`error` set on the score) and count as 0 */
|
|
28
|
+
metricErrors?: number;
|
|
29
|
+
/** Wall time of the run, in milliseconds */
|
|
23
30
|
duration: number;
|
|
31
|
+
/** USD spent: `targetCost` plus `judgeCost` */
|
|
24
32
|
cost: number;
|
|
25
|
-
|
|
33
|
+
/** USD the target spent, over every attempt that reported usage */
|
|
34
|
+
targetCost?: number;
|
|
35
|
+
/** USD the LLM judge spent */
|
|
36
|
+
judgeCost?: number;
|
|
37
|
+
}
|
|
38
|
+
export type AssertionFn = (aggregated: Record<string, AggregatedMetric>, stats: EvalStats) => AssertionResult;
|
|
26
39
|
export { threshold } from './threshold.js';
|
|
27
40
|
export { noRegression } from './regression.js';
|
|
28
41
|
export { assertion } from './custom.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/assertions/index.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,yEAAyE;IACzE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/assertions/index.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,yEAAyE;IACzE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,sCAAsC;AACtC,MAAM,WAAW,SAAS;IACxB,gBAAgB;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,gFAAgF;IAChF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,0EAA0E;IAC1E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4CAA4C;IAC5C,QAAQ,EAAE,MAAM,CAAC;IACjB,+CAA+C;IAC/C,IAAI,EAAE,MAAM,CAAC;IACb,mEAAmE;IACnE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8BAA8B;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,WAAW,GAAG,CACxB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,EAC5C,KAAK,EAAE,SAAS,KACb,eAAe,CAAC;AAErB,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/assertions/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/assertions/index.ts"],"names":[],"mappings":"AA6CA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"regression.d.ts","sourceRoot":"","sources":["../../src/assertions/regression.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAG3C,wBAAgB,YAAY,CAAC,YAAY,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,WAAW,
|
|
1
|
+
{"version":3,"file":"regression.d.ts","sourceRoot":"","sources":["../../src/assertions/regression.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAG3C,wBAAgB,YAAY,CAAC,YAAY,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,WAAW,CAuF7F"}
|
|
@@ -5,7 +5,11 @@ export function noRegression(baselinePath, opts) {
|
|
|
5
5
|
let baseline;
|
|
6
6
|
try {
|
|
7
7
|
const raw = fs.readFileSync(baselinePath, 'utf-8');
|
|
8
|
-
|
|
8
|
+
const parsed = JSON.parse(raw);
|
|
9
|
+
if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
|
|
10
|
+
throw new Error('not an object');
|
|
11
|
+
}
|
|
12
|
+
baseline = parsed;
|
|
9
13
|
}
|
|
10
14
|
catch {
|
|
11
15
|
return {
|
|
@@ -22,6 +26,23 @@ export function noRegression(baselinePath, opts) {
|
|
|
22
26
|
continue;
|
|
23
27
|
validated++;
|
|
24
28
|
const actual = agg.mean;
|
|
29
|
+
if (typeof baselineValue !== 'number' || !Number.isFinite(baselineValue)) {
|
|
30
|
+
return {
|
|
31
|
+
name: 'noRegression',
|
|
32
|
+
passed: false,
|
|
33
|
+
message: `Baseline value of '${metric}' is ${JSON.stringify(baselineValue)}, not a finite number: save a new baseline`,
|
|
34
|
+
actual,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
if (!Number.isFinite(actual)) {
|
|
38
|
+
return {
|
|
39
|
+
name: 'noRegression',
|
|
40
|
+
passed: false,
|
|
41
|
+
message: `'${metric}' = ${actual} is not a finite number (baseline ${baselineValue})`,
|
|
42
|
+
actual,
|
|
43
|
+
expected: baselineValue,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
25
46
|
const lowerBetter = isLowerBetter(metric);
|
|
26
47
|
if (lowerBetter) {
|
|
27
48
|
const limit = baselineValue * (1 + tolerance);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"regression.js","sourceRoot":"","sources":["../../src/assertions/regression.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAE9B,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,MAAM,UAAU,YAAY,CAAC,YAAoB,EAAE,IAA6B;IAC9E,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE;QAC5B,IAAI,
|
|
1
|
+
{"version":3,"file":"regression.js","sourceRoot":"","sources":["../../src/assertions/regression.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"threshold.d.ts","sourceRoot":"","sources":["../../src/assertions/threshold.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAoB,MAAM,SAAS,CAAC;AAoB7D,wBAAgB,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,WAAW,
|
|
1
|
+
{"version":3,"file":"threshold.d.ts","sourceRoot":"","sources":["../../src/assertions/threshold.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAoB,MAAM,SAAS,CAAC;AAoB7D,wBAAgB,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,WAAW,CAoCxE"}
|
|
@@ -22,6 +22,15 @@ export function threshold(metricName, value) {
|
|
|
22
22
|
message: `Metric '${metricName}' not found in aggregated results`,
|
|
23
23
|
};
|
|
24
24
|
}
|
|
25
|
+
if (!Number.isFinite(actual)) {
|
|
26
|
+
return {
|
|
27
|
+
name: `threshold(${metricName})`,
|
|
28
|
+
passed: false,
|
|
29
|
+
message: `${metricName} = ${actual} is not a finite number`,
|
|
30
|
+
actual,
|
|
31
|
+
expected: value,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
25
34
|
const lowerBetter = isLowerBetter(metricName);
|
|
26
35
|
const passed = lowerBetter ? actual <= value : actual >= value;
|
|
27
36
|
const direction = lowerBetter ? '<=' : '>=';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"threshold.js","sourceRoot":"","sources":["../../src/assertions/threshold.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,SAAS,OAAO,CACd,UAA4C,EAC5C,IAAY;IAEZ,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC9B,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACpC,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;IAE/C,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IAEnE,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAA2B,CAAC;IACjD,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAC1B,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;IAE/D,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AACrC,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,UAAkB,EAAE,KAAa;IACzD,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE;QAC5B,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;QAEjE,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO;gBACL,IAAI,EAAE,aAAa,UAAU,GAAG;gBAChC,MAAM,EAAE,KAAK;gBACb,OAAO,EAAE,WAAW,UAAU,mCAAmC;aAClE,CAAC;QACJ,CAAC;QAED,MAAM,WAAW,GAAG,aAAa,CAAC,UAAU,CAAC,CAAC;QAC9C,MAAM,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,MAAM,IAAI,KAAK,CAAC,CAAC,CAAC,MAAM,IAAI,KAAK,CAAC;QAC/D,MAAM,SAAS,GAAG,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;QAE5C,OAAO;YACL,IAAI,EAAE,aAAa,UAAU,GAAG;YAChC,MAAM;YACN,OAAO,EAAE,MAAM;gBACb,CAAC,CAAC,GAAG,UAAU,MAAM,MAAM,IAAI,SAAS,IAAI,KAAK,EAAE;gBACnD,CAAC,CAAC,GAAG,UAAU,MAAM,MAAM,cAAc,SAAS,IAAI,KAAK,EAAE;YAC/D,MAAM;YACN,QAAQ,EAAE,KAAK;SAChB,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC"}
|
|
1
|
+
{"version":3,"file":"threshold.js","sourceRoot":"","sources":["../../src/assertions/threshold.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,SAAS,OAAO,CACd,UAA4C,EAC5C,IAAY;IAEZ,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC9B,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACpC,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;IAE/C,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IAEnE,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAA2B,CAAC;IACjD,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAC1B,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;IAE/D,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AACrC,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,UAAkB,EAAE,KAAa;IACzD,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE;QAC5B,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;QAEjE,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO;gBACL,IAAI,EAAE,aAAa,UAAU,GAAG;gBAChC,MAAM,EAAE,KAAK;gBACb,OAAO,EAAE,WAAW,UAAU,mCAAmC;aAClE,CAAC;QACJ,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YAC7B,OAAO;gBACL,IAAI,EAAE,aAAa,UAAU,GAAG;gBAChC,MAAM,EAAE,KAAK;gBACb,OAAO,EAAE,GAAG,UAAU,MAAM,MAAM,yBAAyB;gBAC3D,MAAM;gBACN,QAAQ,EAAE,KAAK;aAChB,CAAC;QACJ,CAAC;QAED,MAAM,WAAW,GAAG,aAAa,CAAC,UAAU,CAAC,CAAC;QAC9C,MAAM,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,MAAM,IAAI,KAAK,CAAC,CAAC,CAAC,MAAM,IAAI,KAAK,CAAC;QAC/D,MAAM,SAAS,GAAG,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;QAE5C,OAAO;YACL,IAAI,EAAE,aAAa,UAAU,GAAG;YAChC,MAAM;YACN,OAAO,EAAE,MAAM;gBACb,CAAC,CAAC,GAAG,UAAU,MAAM,MAAM,IAAI,SAAS,IAAI,KAAK,EAAE;gBACnD,CAAC,CAAC,GAAG,UAAU,MAAM,MAAM,cAAc,SAAS,IAAI,KAAK,EAAE;YAC/D,MAAM;YACN,QAAQ,EAAE,KAAK;SAChB,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -20,6 +20,10 @@ export interface EvalComparisonOptions {
|
|
|
20
20
|
total: number;
|
|
21
21
|
}) => void;
|
|
22
22
|
}
|
|
23
|
+
export interface EvalComparisonRunOptions {
|
|
24
|
+
/** Cancels both runs; `run()` rejects with the signal's reason */
|
|
25
|
+
signal?: AbortSignal;
|
|
26
|
+
}
|
|
23
27
|
export interface MetricComparison {
|
|
24
28
|
baseline: number;
|
|
25
29
|
challenger: number;
|
|
@@ -38,6 +42,6 @@ export interface ComparisonResult {
|
|
|
38
42
|
export declare class EvalComparison {
|
|
39
43
|
private readonly opts;
|
|
40
44
|
constructor(opts: EvalComparisonOptions);
|
|
41
|
-
run(): Promise<ComparisonResult>;
|
|
45
|
+
run(options?: EvalComparisonRunOptions): Promise<ComparisonResult>;
|
|
42
46
|
}
|
|
43
47
|
//# sourceMappingURL=eval-comparison.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eval-comparison.d.ts","sourceRoot":"","sources":["../src/eval-comparison.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAChE,OAAO,KAAK,EAAE,QAAQ,EAAe,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAClF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"eval-comparison.d.ts","sourceRoot":"","sources":["../src/eval-comparison.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAChE,OAAO,KAAK,EAAE,QAAQ,EAAe,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAClF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAEjD,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAKrC,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE;QACP,QAAQ,EAAE,UAAU,CAAC;QACrB,UAAU,EAAE,UAAU,CAAC;KACxB,CAAC;IACF,OAAO,CAAC,EAAE,QAAQ,EAAE,CAAC;IACrB,kBAAkB,CAAC,EAAE,mBAAmB,EAAE,CAAC;IAC3C,KAAK,CAAC,EAAE,gBAAgB,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;CACvF;AAED,MAAM,WAAW,wBAAwB;IACvC,kEAAkE;IAClE,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,OAAO,CAAC;IACrB,MAAM,EAAE,UAAU,GAAG,YAAY,GAAG,KAAK,CAAC;CAC3C;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE;QACP,MAAM,EAAE,UAAU,GAAG,YAAY,GAAG,KAAK,CAAC;QAC1C,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;KAC3C,CAAC;IACF,QAAQ,EAAE,eAAe,CAAC;IAC1B,UAAU,EAAE,eAAe,CAAC;CAC7B;AAkED,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAwB;gBAEjC,IAAI,EAAE,qBAAqB;IASjC,GAAG,CAAC,OAAO,GAAE,wBAA6B,GAAG,OAAO,CAAC,gBAAgB,CAAC;CAoE7E"}
|
package/dist/eval-comparison.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { EvalSuite } from './eval-suite.js';
|
|
2
|
+
import { EvalComparisonConfigSchema } from './schema.js';
|
|
2
3
|
import { pairedTTest } from './stats/t-test.js';
|
|
3
4
|
import { mcnemarsTest } from './stats/mcnemar.js';
|
|
4
5
|
import { mean } from './stats/percentiles.js';
|
|
@@ -63,9 +64,14 @@ function determineOverallWinner(metrics) {
|
|
|
63
64
|
export class EvalComparison {
|
|
64
65
|
opts;
|
|
65
66
|
constructor(opts) {
|
|
67
|
+
EvalComparisonConfigSchema.parse({
|
|
68
|
+
concurrency: opts.concurrency,
|
|
69
|
+
timeout: opts.timeout,
|
|
70
|
+
retries: opts.retries,
|
|
71
|
+
});
|
|
66
72
|
this.opts = opts;
|
|
67
73
|
}
|
|
68
|
-
async run() {
|
|
74
|
+
async run(options = {}) {
|
|
69
75
|
const { dataset, targets, metrics, statisticalMetrics, judge, concurrency, timeout, retries, onProgress, } = this.opts;
|
|
70
76
|
const sharedConfig = {
|
|
71
77
|
dataset,
|
|
@@ -91,8 +97,8 @@ export class EvalComparison {
|
|
|
91
97
|
: undefined,
|
|
92
98
|
});
|
|
93
99
|
const [baselineResult, challengerResult] = await Promise.all([
|
|
94
|
-
baselineSuite.run(),
|
|
95
|
-
challengerSuite.run(),
|
|
100
|
+
baselineSuite.run({ signal: options.signal }),
|
|
101
|
+
challengerSuite.run({ signal: options.signal }),
|
|
96
102
|
]);
|
|
97
103
|
const metricNames = new Set();
|
|
98
104
|
for (const r of baselineResult.results) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eval-comparison.js","sourceRoot":"","sources":["../src/eval-comparison.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"eval-comparison.js","sourceRoot":"","sources":["../src/eval-comparison.ts"],"names":[],"mappings":"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"}
|
package/dist/eval-suite.d.ts
CHANGED
|
@@ -3,12 +3,25 @@ import type { EvalCase } from './schema.js';
|
|
|
3
3
|
import type { JudgeConfigInput } from './schema.js';
|
|
4
4
|
import type { MetricFn, MetricScore, EvalCaseResult, StatisticalMetricFn } from './metrics/types.js';
|
|
5
5
|
import type { LLMMetricFn } from './metrics/llm-judge.js';
|
|
6
|
-
import type { AssertionFn, AssertionResult, AggregatedMetric } from './assertions/index.js';
|
|
6
|
+
import type { AssertionFn, AssertionResult, AggregatedMetric, EvalStats } from './assertions/index.js';
|
|
7
7
|
import type { ReporterType, ReporterOptions } from './reporters/index.js';
|
|
8
|
+
/** What a function target gets besides the input */
|
|
9
|
+
export interface EvalTargetContext {
|
|
10
|
+
/**
|
|
11
|
+
* Aborted when the attempt times out or the suite run is cancelled. Pass it on to the model
|
|
12
|
+
* call (`cogitator.run(agent, { input, signal })`, `fetch(url, { signal })`) so an abandoned
|
|
13
|
+
* attempt stops instead of running, and paying, in the background.
|
|
14
|
+
*/
|
|
15
|
+
signal: AbortSignal;
|
|
16
|
+
/** The case being run */
|
|
17
|
+
case: EvalCase;
|
|
18
|
+
/** 0 for the first attempt, then 1, 2 and so on for retries */
|
|
19
|
+
attempt: number;
|
|
20
|
+
}
|
|
8
21
|
export interface EvalTarget {
|
|
9
22
|
agent?: unknown;
|
|
10
23
|
cogitator?: unknown;
|
|
11
|
-
fn?: (input: string) => Promise<string>;
|
|
24
|
+
fn?: (input: string, context: EvalTargetContext) => Promise<string>;
|
|
12
25
|
}
|
|
13
26
|
export interface EvalProgress {
|
|
14
27
|
completed: number;
|
|
@@ -25,24 +38,29 @@ export interface EvalSuiteOptions {
|
|
|
25
38
|
concurrency?: number;
|
|
26
39
|
timeout?: number;
|
|
27
40
|
retries?: number;
|
|
41
|
+
/** Called after each case. A callback that throws is reported as a process warning */
|
|
28
42
|
onProgress?: (progress: EvalProgress) => void;
|
|
29
43
|
}
|
|
30
44
|
export interface EvalRunOptions {
|
|
31
45
|
/** Run only the first `maxCases` cases of the dataset (a positive integer) */
|
|
32
46
|
maxCases?: number;
|
|
47
|
+
/**
|
|
48
|
+
* Cancels the run: the attempts in flight are aborted, no further case starts, and `run()`
|
|
49
|
+
* rejects with the signal's reason
|
|
50
|
+
*/
|
|
51
|
+
signal?: AbortSignal;
|
|
33
52
|
}
|
|
53
|
+
/** The run-wide figures of a finished suite run, every field filled in */
|
|
54
|
+
export type EvalSuiteStats = Required<EvalStats>;
|
|
34
55
|
export interface EvalSuiteResult {
|
|
35
56
|
results: Array<EvalCaseResult & {
|
|
36
57
|
scores: MetricScore[];
|
|
37
58
|
}>;
|
|
38
59
|
aggregated: Record<string, AggregatedMetric>;
|
|
39
60
|
assertions: AssertionResult[];
|
|
40
|
-
stats:
|
|
41
|
-
total: number;
|
|
42
|
-
duration: number;
|
|
43
|
-
cost: number;
|
|
44
|
-
};
|
|
61
|
+
stats: EvalSuiteStats;
|
|
45
62
|
report: (type: ReporterType | ReporterType[], options?: ReporterOptions) => void;
|
|
63
|
+
/** Writes the mean of each metric as JSON; throws when a mean is not a finite number */
|
|
46
64
|
saveBaseline: (path: string) => void;
|
|
47
65
|
}
|
|
48
66
|
export declare function isLLMMetric(m: MetricFn): m is LLMMetricFn;
|
|
@@ -58,12 +76,27 @@ export declare class EvalSuite {
|
|
|
58
76
|
private readonly onProgress?;
|
|
59
77
|
constructor(opts: EvalSuiteOptions);
|
|
60
78
|
private validateTarget;
|
|
79
|
+
/** Two metrics with one name would be aggregated, compared and reported as one */
|
|
80
|
+
private validateMetricNames;
|
|
61
81
|
run(options?: EvalRunOptions): Promise<EvalSuiteResult>;
|
|
82
|
+
private reportProgress;
|
|
83
|
+
private runCase;
|
|
62
84
|
private executeCase;
|
|
85
|
+
/**
|
|
86
|
+
* One attempt, aborted through its signal after `timeout`. An aborted attempt gets as long
|
|
87
|
+
* again to stop before the case moves on, so a target that honors the signal never overlaps
|
|
88
|
+
* its retry and the concurrency limit holds. Usage of an attempt that still finished counts.
|
|
89
|
+
*/
|
|
63
90
|
private executeCaseAttempt;
|
|
64
91
|
private executeFnTarget;
|
|
65
92
|
private executeAgentTarget;
|
|
66
93
|
private evaluateCaseMetrics;
|
|
94
|
+
/**
|
|
95
|
+
* A metric's score for one case. A metric that throws, or whose score is not a finite number,
|
|
96
|
+
* scores 0 with the reason in `error`, so one bad metric neither drops the case nor poisons
|
|
97
|
+
* the aggregate with NaN.
|
|
98
|
+
*/
|
|
99
|
+
private scoreMetric;
|
|
67
100
|
private aggregateScores;
|
|
68
101
|
}
|
|
69
102
|
//# sourceMappingURL=eval-suite.d.ts.map
|
package/dist/eval-suite.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eval-suite.d.ts","sourceRoot":"","sources":["../src/eval-suite.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACrC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,KAAK,EAAkB,gBAAgB,EAAE,MAAM,UAAU,CAAC;AACjE,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"eval-suite.d.ts","sourceRoot":"","sources":["../src/eval-suite.ts"],"names":[],"mappings":"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"}
|