@cogitator-ai/evals 0.7.0 → 0.9.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 +84 -21
- package/dist/assertions/error-rate.d.ts +8 -0
- package/dist/assertions/error-rate.d.ts.map +1 -0
- package/dist/assertions/error-rate.js +27 -0
- package/dist/assertions/error-rate.js.map +1 -0
- package/dist/assertions/index.d.ts +3 -0
- package/dist/assertions/index.d.ts.map +1 -1
- package/dist/assertions/index.js +1 -0
- package/dist/assertions/index.js.map +1 -1
- package/dist/assertions/regression.d.ts.map +1 -1
- package/dist/assertions/regression.js +3 -1
- package/dist/assertions/regression.js.map +1 -1
- package/dist/assertions/threshold.d.ts.map +1 -1
- package/dist/assertions/threshold.js +4 -1
- package/dist/assertions/threshold.js.map +1 -1
- package/dist/datasets/csv-loader.d.ts.map +1 -1
- package/dist/datasets/csv-loader.js +71 -7
- package/dist/datasets/csv-loader.js.map +1 -1
- package/dist/datasets/dataset.d.ts +11 -2
- package/dist/datasets/dataset.d.ts.map +1 -1
- package/dist/datasets/dataset.js +42 -13
- package/dist/datasets/dataset.js.map +1 -1
- package/dist/datasets/issues.d.ts +4 -0
- package/dist/datasets/issues.d.ts.map +1 -0
- package/dist/datasets/issues.js +7 -0
- package/dist/datasets/issues.js.map +1 -0
- package/dist/datasets/jsonl-loader.d.ts.map +1 -1
- package/dist/datasets/jsonl-loader.js +6 -1
- package/dist/datasets/jsonl-loader.js.map +1 -1
- package/dist/eval-comparison.d.ts +2 -0
- package/dist/eval-comparison.d.ts.map +1 -1
- package/dist/eval-comparison.js +25 -11
- package/dist/eval-comparison.js.map +1 -1
- package/dist/eval-suite.d.ts +7 -3
- package/dist/eval-suite.d.ts.map +1 -1
- package/dist/eval-suite.js +45 -6
- package/dist/eval-suite.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/metrics/deterministic.d.ts +4 -0
- package/dist/metrics/deterministic.d.ts.map +1 -1
- package/dist/metrics/deterministic.js +52 -0
- 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 +1 -1
- package/dist/metrics/index.js.map +1 -1
- package/dist/metrics/llm-judge.d.ts.map +1 -1
- package/dist/metrics/llm-judge.js +98 -10
- package/dist/metrics/llm-judge.js.map +1 -1
- package/dist/metrics/types.d.ts +6 -0
- package/dist/metrics/types.d.ts.map +1 -1
- package/dist/metrics/types.js.map +1 -1
- package/dist/reporters/ci.d.ts +4 -0
- package/dist/reporters/ci.d.ts.map +1 -1
- package/dist/reporters/ci.js +5 -1
- package/dist/reporters/ci.js.map +1 -1
- package/dist/reporters/console.d.ts.map +1 -1
- package/dist/reporters/console.js +6 -3
- package/dist/reporters/console.js.map +1 -1
- package/dist/reporters/csv.d.ts.map +1 -1
- package/dist/reporters/csv.js +5 -2
- package/dist/reporters/csv.js.map +1 -1
- package/dist/reporters/format.d.ts +13 -0
- package/dist/reporters/format.d.ts.map +1 -0
- package/dist/reporters/format.js +27 -0
- package/dist/reporters/format.js.map +1 -0
- package/dist/reporters/github.d.ts +11 -0
- package/dist/reporters/github.d.ts.map +1 -0
- package/dist/reporters/github.js +94 -0
- package/dist/reporters/github.js.map +1 -0
- package/dist/reporters/index.d.ts +16 -5
- package/dist/reporters/index.d.ts.map +1 -1
- package/dist/reporters/index.js +14 -3
- package/dist/reporters/index.js.map +1 -1
- package/dist/reporters/junit.d.ts +8 -0
- package/dist/reporters/junit.d.ts.map +1 -0
- package/dist/reporters/junit.js +107 -0
- package/dist/reporters/junit.js.map +1 -0
- package/dist/schema.d.ts +11 -0
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +16 -0
- package/dist/schema.js.map +1 -1
- package/dist/vitest.d.ts +35 -0
- package/dist/vitest.d.ts.map +1 -0
- package/dist/vitest.js +85 -0
- package/dist/vitest.js.map +1 -0
- package/package.json +12 -3
package/README.md
CHANGED
|
@@ -10,6 +10,7 @@ pnpm add @cogitator-ai/evals
|
|
|
10
10
|
# Optional dependencies
|
|
11
11
|
pnpm add papaparse # CSV dataset loading
|
|
12
12
|
pnpm add @cogitator-ai/core # agent targets and LLM-as-judge metrics
|
|
13
|
+
pnpm add -D vitest # describeEval from @cogitator-ai/evals/vitest
|
|
13
14
|
```
|
|
14
15
|
|
|
15
16
|
Website docs: [Evals](https://cogitator.app/docs/evals), [Datasets](https://cogitator.app/docs/evals/datasets), [Metrics](https://cogitator.app/docs/evals/metrics), [Assertions](https://cogitator.app/docs/evals/assertions), [Comparison](https://cogitator.app/docs/evals/comparison), [Reporters](https://cogitator.app/docs/evals/reporters).
|
|
@@ -17,13 +18,14 @@ Website docs: [Evals](https://cogitator.app/docs/evals), [Datasets](https://cogi
|
|
|
17
18
|
## Features
|
|
18
19
|
|
|
19
20
|
- **EvalSuite** — Run datasets against agents or plain functions with configurable concurrency, timeouts, and retries
|
|
20
|
-
- **
|
|
21
|
+
- **7 Deterministic Metrics** - exactMatch, contains, containsAll, containsAny, similarity, regex, jsonSchema (Zod)
|
|
21
22
|
- **5 LLM-as-Judge Metrics** — faithfulness, relevance, coherence, helpfulness, custom llmMetric
|
|
22
23
|
- **3 Statistical Metrics** — latency, cost, tokenUsage with full percentile breakdowns
|
|
23
24
|
- **Custom Metrics** — `metric()` factory for anything domain-specific
|
|
24
25
|
- **Assertions** — threshold, noRegression, custom assertion with auto-detection of lower-is-better metrics
|
|
25
26
|
- **A/B Testing** — EvalComparison with paired t-test and McNemar's test for statistical significance
|
|
26
|
-
- **
|
|
27
|
+
- **6 Reporters** - console (colored table), JSON, CSV, JUnit XML, GitHub Actions annotations and job summary, CI (exit code on failure)
|
|
28
|
+
- **Vitest** - `describeEval` from `@cogitator-ai/evals/vitest` runs a suite as a test file, one test per case plus one for the assertions
|
|
27
29
|
- **Builder API** — Fluent `EvalBuilder` for composable eval pipelines
|
|
28
30
|
- **Baseline Workflow** — Save baselines, compare against them, catch regressions in CI
|
|
29
31
|
- **Zod Validation** — Type-safe configuration with runtime checks
|
|
@@ -82,6 +84,8 @@ const suite = new EvalSuite({
|
|
|
82
84
|
|
|
83
85
|
`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
86
|
|
|
87
|
+
A case whose every attempt failed is not scored: its empty output costs no judge calls and counts as no 0, the aggregates cover the cases that answered (`aggregated.<metric>.count` says how many), and `maxErrorRate(rate)` fails a run where too many cases errored. An agent target's case result carries `truncated`, `iterationLimitReached` and `paused` when the run ended that way.
|
|
88
|
+
|
|
85
89
|
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
90
|
|
|
87
91
|
`result.stats` holds:
|
|
@@ -136,12 +140,15 @@ const dataset = await Dataset.fromCsv('./evals/qa.csv');
|
|
|
136
140
|
|
|
137
141
|
CSV must have an `input` column. Optional columns: `expected`, `metadata.*`, `context.*`.
|
|
138
142
|
|
|
143
|
+
Both loaders name the line of the file a case comes from when the case schema refuses it (`Invalid case at line 3: input: ...`), the CSV loader counting quoted fields that span lines. The CSV loader splits on commas and throws on a malformed row, a quote never closed for one, with its line.
|
|
144
|
+
|
|
139
145
|
### Transformations
|
|
140
146
|
|
|
141
147
|
```typescript
|
|
142
148
|
const filtered = dataset.filter((c) => c.expected !== undefined);
|
|
143
149
|
const sampled = dataset.sample(50);
|
|
144
150
|
const shuffled = dataset.shuffle();
|
|
151
|
+
const nightly = dataset.sample(50, { seed: 'nightly' }); // the same cases on every run
|
|
145
152
|
```
|
|
146
153
|
|
|
147
154
|
All transformations return new `Dataset` instances — the original is never mutated.
|
|
@@ -154,18 +161,22 @@ All transformations return new `Dataset` instances — the original is never mut
|
|
|
154
161
|
|
|
155
162
|
Metrics that compare output against expected values using string operations or schema validation.
|
|
156
163
|
|
|
157
|
-
| Metric
|
|
158
|
-
|
|
|
159
|
-
| `exactMatch`
|
|
160
|
-
| `contains`
|
|
161
|
-
| `
|
|
162
|
-
| `
|
|
163
|
-
| `
|
|
164
|
+
| Metric | Description | Requires `expected` |
|
|
165
|
+
| ------------- | ---------------------------------------------- | ------------------- |
|
|
166
|
+
| `exactMatch` | Exact string match (case optional) | Yes |
|
|
167
|
+
| `contains` | Output contains expected substring | Yes |
|
|
168
|
+
| `containsAll` | Fraction of configured keywords found | No |
|
|
169
|
+
| `containsAny` | Whether any configured keyword is found | No |
|
|
170
|
+
| `similarity` | Levenshtein distance similarity score (0 to 1) | Yes |
|
|
171
|
+
| `regex` | Output matches a regex pattern | No |
|
|
172
|
+
| `jsonSchema` | Output is valid JSON matching a Zod schema | No |
|
|
164
173
|
|
|
165
174
|
```typescript
|
|
166
175
|
import {
|
|
167
176
|
exactMatch,
|
|
168
177
|
contains,
|
|
178
|
+
containsAll,
|
|
179
|
+
containsAny,
|
|
169
180
|
similarity,
|
|
170
181
|
regex,
|
|
171
182
|
jsonSchema,
|
|
@@ -176,6 +187,8 @@ import { z } from 'zod';
|
|
|
176
187
|
const metrics = [
|
|
177
188
|
exactMatch({ caseSensitive: true }),
|
|
178
189
|
contains(),
|
|
190
|
+
containsAll(['security', 'privacy', 'compliance']),
|
|
191
|
+
containsAny(['approved', 'accepted']),
|
|
179
192
|
similarity(),
|
|
180
193
|
regex(/\d{4}-\d{2}-\d{2}/),
|
|
181
194
|
jsonSchema(z.object({ answer: z.string(), confidence: z.number() })),
|
|
@@ -194,6 +207,8 @@ const metrics = [
|
|
|
194
207
|
];
|
|
195
208
|
```
|
|
196
209
|
|
|
210
|
+
`containsAll()` scores the fraction of its keywords found and reports any missing keywords in `details`. `containsAny()` scores 1 when at least one keyword is found and 0 otherwise. Keywords use substring matching, so `cat` matches `concatenate`. Both metrics are case-insensitive by default, accept `caseSensitive` and `name` options, ignore duplicate keywords, and reject empty lists or empty and whitespace-only keywords when the metric is created.
|
|
211
|
+
|
|
197
212
|
`regex()` ignores the `g` and `y` flags, which would make identical outputs alternate between pass and fail.
|
|
198
213
|
|
|
199
214
|
### LLM-as-Judge
|
|
@@ -232,7 +247,7 @@ The judge reads the case's `context` too, so `faithfulness()` can check a respon
|
|
|
232
247
|
Dataset.from([{ input: 'Write the lede', context: { dossier: dossierText } }]);
|
|
233
248
|
```
|
|
234
249
|
|
|
235
|
-
The `judge` option is a `JudgeConfigInput`: `{ model, temperature?, maxTokens?, cogitator? }`, with `temperature` defaulting to `0`.
|
|
250
|
+
The `judge` option is a `JudgeConfigInput`: `{ model, temperature?, maxTokens?, cogitator?, cache?, concurrency? }`, with `temperature` defaulting to `0`. `cache: true` reuses a verdict for the same model, settings and prompt in memory (a `JudgeCache` with `get` and `set` keeps them across runs), and `concurrency` caps the judge calls running at once.
|
|
236
251
|
|
|
237
252
|
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`.
|
|
238
253
|
|
|
@@ -298,6 +313,16 @@ const assertions = [
|
|
|
298
313
|
|
|
299
314
|
Latency, cost and tokenUsage metrics (and names ending in `Duration` or `Latency`) are lower-is-better: the assertion passes when the value is at or below the threshold. `noRegression` uses the same rule.
|
|
300
315
|
|
|
316
|
+
### maxErrorRate
|
|
317
|
+
|
|
318
|
+
```typescript
|
|
319
|
+
import { maxErrorRate } from '@cogitator-ai/evals';
|
|
320
|
+
|
|
321
|
+
const assertions = [threshold('exactMatch', 0.9), maxErrorRate(0.05)];
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
Passes while at most `rate` (0 to 1) of the cases errored. Errored cases are not scored, so pair metric thresholds with it.
|
|
325
|
+
|
|
301
326
|
### noRegression
|
|
302
327
|
|
|
303
328
|
Compares current results against a saved baseline file.
|
|
@@ -369,22 +394,45 @@ Access full suite results via `result.baseline` and `result.challenger`. `compar
|
|
|
369
394
|
|
|
370
395
|
Call `result.report()` after a suite run to output results.
|
|
371
396
|
|
|
372
|
-
| Reporter | Output
|
|
373
|
-
| --------- |
|
|
374
|
-
| `console` | Colored table with metrics, assertions, summary
|
|
375
|
-
| `json` | Writes `eval-report.json` (configurable path)
|
|
376
|
-
| `csv` | Writes `eval-report.csv` (configurable path)
|
|
377
|
-
| `
|
|
397
|
+
| Reporter | Output |
|
|
398
|
+
| --------- | -------------------------------------------------------------------- |
|
|
399
|
+
| `console` | Colored table with metrics, assertions, summary |
|
|
400
|
+
| `json` | Writes `eval-report.json` (configurable path) |
|
|
401
|
+
| `csv` | Writes `eval-report.csv` (configurable path) |
|
|
402
|
+
| `junit` | Writes `eval-report.xml`, a JUnit report (configurable path) |
|
|
403
|
+
| `github` | GitHub Actions annotations, plus a job summary in Actions |
|
|
404
|
+
| `ci` | Compact verdict, sets `process.exitCode = 1` when an assertion fails |
|
|
378
405
|
|
|
379
406
|
```typescript
|
|
380
407
|
const result = await suite.run();
|
|
381
408
|
|
|
382
409
|
result.report('console');
|
|
383
410
|
result.report('json', { path: './reports/eval.json' });
|
|
384
|
-
result.report(['console', 'json', 'csv']);
|
|
385
|
-
result.report('ci');
|
|
411
|
+
result.report(['console', 'json', 'csv', 'junit'], { path: './reports/eval' });
|
|
412
|
+
result.report(['github', 'ci']);
|
|
386
413
|
```
|
|
387
414
|
|
|
415
|
+
The `path` is a base path: each file reporter adds its own extension (`.json`, `.csv`, `.xml`). `ci` runs last and does not end the process, so output flushes and later hooks still run before Node exits with code 1.
|
|
416
|
+
|
|
417
|
+
- **junit** writes one `<testsuite name="eval">` with a `<testcase>` per case (a `<failure>` when it errored, its scores in `<system-out>`) and a `<testcase>` per assertion (a `<failure>` when it did not pass). Everything is XML-escaped, and characters XML 1.0 does not allow are replaced.
|
|
418
|
+
- **github** prints `::error` for each failed assertion and errored case and `::warning` for each failed metric score. When `GITHUB_STEP_SUMMARY` is set it also appends a Markdown summary with the totals, the aggregated metrics (mean, p50, p95, cases scored) and the assertions.
|
|
419
|
+
|
|
420
|
+
Agent run flags (`truncated`, `iterationLimitReached`, `paused`) show up per case in the json, csv and junit reports, and each aggregated metric's `count` (cases it was scored on) in the console, json and github output.
|
|
421
|
+
|
|
422
|
+
### Vitest
|
|
423
|
+
|
|
424
|
+
```typescript
|
|
425
|
+
// eval/qa.eval.test.ts
|
|
426
|
+
import { afterAll } from 'vitest';
|
|
427
|
+
import { describeEval } from '@cogitator-ai/evals/vitest';
|
|
428
|
+
|
|
429
|
+
const qa = describeEval('qa agent', { suite, run: { maxCases: 50 }, timeout: 5 * 60_000 });
|
|
430
|
+
|
|
431
|
+
afterAll(() => qa.result().report('junit', { path: './reports/qa' }));
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
`describeEval(name, { suite, run?, timeout? })` registers a `describe` block. The suite runs once in `beforeAll` (`timeout` defaults to 10 minutes, after which the run is cancelled), each case of `suite.cases(run?.maxCases)` gets a test that fails with the case error, and an `assertions` test lists every failed assertion. When the run itself fails, every test fails with that cause. `result()` returns the `EvalSuiteResult` once the run has finished.
|
|
435
|
+
|
|
388
436
|
---
|
|
389
437
|
|
|
390
438
|
## Builder API
|
|
@@ -480,6 +528,8 @@ result.report('ci');
|
|
|
480
528
|
| -------------- | ------------- | ------------------------------------- |
|
|
481
529
|
| `exactMatch` | Deterministic | Exact string match |
|
|
482
530
|
| `contains` | Deterministic | Substring match |
|
|
531
|
+
| `containsAll` | Deterministic | Fraction of keywords found |
|
|
532
|
+
| `containsAny` | Deterministic | Any configured keyword found |
|
|
483
533
|
| `similarity` | Deterministic | Levenshtein distance similarity score |
|
|
484
534
|
| `regex` | Deterministic | Regex pattern match |
|
|
485
535
|
| `jsonSchema` | Deterministic | Zod schema validation |
|
|
@@ -498,14 +548,27 @@ result.report('ci');
|
|
|
498
548
|
| Export | Description |
|
|
499
549
|
| -------------- | ---------------------------------------------- |
|
|
500
550
|
| `threshold` | Enforce min/max on metric mean |
|
|
551
|
+
| `maxErrorRate` | Fail a run where too many cases errored |
|
|
501
552
|
| `noRegression` | Compare against saved baseline |
|
|
502
553
|
| `assertion` | Custom assertion with arbitrary check function |
|
|
503
554
|
|
|
504
555
|
### Reporters
|
|
505
556
|
|
|
506
|
-
| Export
|
|
507
|
-
|
|
|
508
|
-
| `report`
|
|
557
|
+
| Export | Description |
|
|
558
|
+
| -------------------------------- | -------------------------------------- |
|
|
559
|
+
| `report` | Dispatch to one or more reporter types |
|
|
560
|
+
| `describeEval` (`/vitest` entry) | Run a suite as a Vitest describe block |
|
|
561
|
+
|
|
562
|
+
`report` takes `console`, `json`, `csv`, `junit`, `github` and `ci`. `describeEval` takes `DescribeEvalOptions` and returns a `DescribeEvalHandle`.
|
|
563
|
+
|
|
564
|
+
### Types
|
|
565
|
+
|
|
566
|
+
| Export | Description |
|
|
567
|
+
| ------------------ | ------------------------------------------------------------------------ |
|
|
568
|
+
| `JudgeConfigInput` | The `judge` option: model, settings, `cogitator`, `cache`, `concurrency` |
|
|
569
|
+
| `JudgeCache` | Where verdicts are kept across runs: `get(key)` and `set(key, verdict)` |
|
|
570
|
+
| `AggregatedMetric` | Aggregate of a metric, with `count` for the cases it covers |
|
|
571
|
+
| `MetricComparison` | A metric of a comparison, with `n` for the cases it was compared on |
|
|
509
572
|
|
|
510
573
|
### Statistics
|
|
511
574
|
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { AssertionFn } from './index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Passes while at most `rate` (0 to 1) of the cases errored, every attempt failed or timed out.
|
|
4
|
+
* Errored cases are not scored, so a metric's mean says nothing about them: pair metric
|
|
5
|
+
* thresholds with this to catch a run where the target mostly failed.
|
|
6
|
+
*/
|
|
7
|
+
export declare function maxErrorRate(rate: number): AssertionFn;
|
|
8
|
+
//# sourceMappingURL=error-rate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-rate.d.ts","sourceRoot":"","sources":["../../src/assertions/error-rate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE3C;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAoBtD"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Passes while at most `rate` (0 to 1) of the cases errored, every attempt failed or timed out.
|
|
3
|
+
* Errored cases are not scored, so a metric's mean says nothing about them: pair metric
|
|
4
|
+
* thresholds with this to catch a run where the target mostly failed.
|
|
5
|
+
*/
|
|
6
|
+
export function maxErrorRate(rate) {
|
|
7
|
+
if (!Number.isFinite(rate) || rate < 0 || rate > 1) {
|
|
8
|
+
throw new Error(`maxErrorRate takes a rate from 0 to 1, got ${rate}`);
|
|
9
|
+
}
|
|
10
|
+
const name = `maxErrorRate(${rate})`;
|
|
11
|
+
const percent = (value) => `${Math.round(value * 1000) / 10}%`;
|
|
12
|
+
return (_aggregated, stats) => {
|
|
13
|
+
const errors = stats.errors ?? 0;
|
|
14
|
+
const actual = stats.total === 0 ? 0 : errors / stats.total;
|
|
15
|
+
const passed = actual <= rate;
|
|
16
|
+
return {
|
|
17
|
+
name,
|
|
18
|
+
passed,
|
|
19
|
+
message: passed
|
|
20
|
+
? `${errors} of ${stats.total} cases errored, at most ${percent(rate)} allowed`
|
|
21
|
+
: `${errors} of ${stats.total} cases errored (${percent(actual)}), expected at most ${percent(rate)}`,
|
|
22
|
+
actual,
|
|
23
|
+
expected: rate,
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=error-rate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-rate.js","sourceRoot":"","sources":["../../src/assertions/error-rate.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,EAAE,CAAC;QACnD,MAAM,IAAI,KAAK,CAAC,8CAA8C,IAAI,EAAE,CAAC,CAAC;IACxE,CAAC;IACD,MAAM,IAAI,GAAG,gBAAgB,IAAI,GAAG,CAAC;IACrC,MAAM,OAAO,GAAG,CAAC,KAAa,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC;IACvE,OAAO,CAAC,WAAW,EAAE,KAAK,EAAE,EAAE;QAC5B,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,IAAI,CAAC,CAAC;QACjC,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC;QAC5D,MAAM,MAAM,GAAG,MAAM,IAAI,IAAI,CAAC;QAC9B,OAAO;YACL,IAAI;YACJ,MAAM;YACN,OAAO,EAAE,MAAM;gBACb,CAAC,CAAC,GAAG,MAAM,OAAO,KAAK,CAAC,KAAK,2BAA2B,OAAO,CAAC,IAAI,CAAC,UAAU;gBAC/E,CAAC,CAAC,GAAG,MAAM,OAAO,KAAK,CAAC,KAAK,mBAAmB,OAAO,CAAC,MAAM,CAAC,uBAAuB,OAAO,CAAC,IAAI,CAAC,EAAE;YACvG,MAAM;YACN,QAAQ,EAAE,IAAI;SACf,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -8,6 +8,8 @@ export interface AggregatedMetric {
|
|
|
8
8
|
p50: number;
|
|
9
9
|
p95: number;
|
|
10
10
|
p99: number;
|
|
11
|
+
/** Cases the metric was scored on: errored cases are not scored */
|
|
12
|
+
count?: number;
|
|
11
13
|
/** Extra figures a statistical metric reports, such as the total cost */
|
|
12
14
|
metadata?: Record<string, unknown>;
|
|
13
15
|
}
|
|
@@ -39,4 +41,5 @@ export type AssertionFn = (aggregated: Record<string, AggregatedMetric>, stats:
|
|
|
39
41
|
export { threshold } from './threshold.js';
|
|
40
42
|
export { noRegression } from './regression.js';
|
|
41
43
|
export { assertion } from './custom.js';
|
|
44
|
+
export { maxErrorRate } from './error-rate.js';
|
|
42
45
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -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,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
|
+
{"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,mEAAmE;IACnE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,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;AACrC,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC"}
|
package/dist/assertions/index.js
CHANGED
|
@@ -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":"AA+CA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACrC,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,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,CA0F7F"}
|
|
@@ -38,7 +38,9 @@ export function noRegression(baselinePath, opts) {
|
|
|
38
38
|
return {
|
|
39
39
|
name: 'noRegression',
|
|
40
40
|
passed: false,
|
|
41
|
-
message:
|
|
41
|
+
message: agg.count === 0
|
|
42
|
+
? `'${metric}' has no scored cases, every case errored (baseline ${baselineValue})`
|
|
43
|
+
: `'${metric}' = ${actual} is not a finite number (baseline ${baselineValue})`,
|
|
42
44
|
actual,
|
|
43
45
|
expected: baselineValue,
|
|
44
46
|
};
|
|
@@ -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,QAAiC,CAAC;QACtC,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;YACnD,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACxC,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC3E,MAAM,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC;YACnC,CAAC;YACD,QAAQ,GAAG,MAAiC,CAAC;QAC/C,CAAC;QAAC,MAAM,CAAC;YACP,OAAO;gBACL,IAAI,EAAE,cAAc;gBACpB,MAAM,EAAE,KAAK;gBACb,OAAO,EAAE,iCAAiC,YAAY,EAAE;aACzD,CAAC;QACJ,CAAC;QAED,MAAM,SAAS,GAAG,IAAI,EAAE,SAAS,IAAI,IAAI,CAAC;QAC1C,IAAI,SAAS,GAAG,CAAC,CAAC;QAElB,KAAK,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC/D,MAAM,GAAG,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;YAC/B,IAAI,CAAC,GAAG;gBAAE,SAAS;YAEnB,SAAS,EAAE,CAAC;YACZ,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,CAAC;YAExB,IAAI,OAAO,aAAa,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;gBACzE,OAAO;oBACL,IAAI,EAAE,cAAc;oBACpB,MAAM,EAAE,KAAK;oBACb,OAAO,EAAE,sBAAsB,MAAM,QAAQ,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,4CAA4C;oBACtH,MAAM;iBACP,CAAC;YACJ,CAAC;YAED,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC7B,OAAO;oBACL,IAAI,EAAE,cAAc;oBACpB,MAAM,EAAE,KAAK;oBACb,OAAO,
|
|
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,CAuCxE"}
|
|
@@ -23,10 +23,13 @@ export function threshold(metricName, value) {
|
|
|
23
23
|
};
|
|
24
24
|
}
|
|
25
25
|
if (!Number.isFinite(actual)) {
|
|
26
|
+
const unscored = aggregated[metricName.split('.')[0]]?.count === 0;
|
|
26
27
|
return {
|
|
27
28
|
name: `threshold(${metricName})`,
|
|
28
29
|
passed: false,
|
|
29
|
-
message:
|
|
30
|
+
message: unscored
|
|
31
|
+
? `${metricName} has no scored cases: every case errored`
|
|
32
|
+
: `${metricName} = ${actual} is not a finite number`,
|
|
30
33
|
actual,
|
|
31
34
|
expected: value,
|
|
32
35
|
};
|
|
@@ -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,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;
|
|
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,MAAM,QAAQ,GAAG,UAAU,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAE,CAAC,EAAE,KAAK,KAAK,CAAC,CAAC;YACpE,OAAO;gBACL,IAAI,EAAE,aAAa,UAAU,GAAG;gBAChC,MAAM,EAAE,KAAK;gBACb,OAAO,EAAE,QAAQ;oBACf,CAAC,CAAC,GAAG,UAAU,0CAA0C;oBACzD,CAAC,CAAC,GAAG,UAAU,MAAM,MAAM,yBAAyB;gBACtD,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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"csv-loader.d.ts","sourceRoot":"","sources":["../../src/datasets/csv-loader.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"csv-loader.d.ts","sourceRoot":"","sources":["../../src/datasets/csv-loader.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAE1C,wBAAsB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,CA8E/D"}
|
|
@@ -1,22 +1,52 @@
|
|
|
1
1
|
import { readFile } from 'node:fs/promises';
|
|
2
2
|
import { EvalCaseSchema } from '../schema.js';
|
|
3
|
+
import { describeIssues } from './issues.js';
|
|
3
4
|
export async function loadCsv(path) {
|
|
4
5
|
let Papa;
|
|
5
6
|
try {
|
|
6
|
-
|
|
7
|
+
const loaded = (await import('papaparse'));
|
|
8
|
+
Papa = loaded.default ?? loaded;
|
|
7
9
|
}
|
|
8
10
|
catch {
|
|
9
11
|
throw new Error('papaparse is required for CSV loading. Install it with: npm install papaparse');
|
|
10
12
|
}
|
|
11
|
-
const content = await readFile(path, 'utf-8');
|
|
12
|
-
const
|
|
13
|
-
|
|
13
|
+
const content = (await readFile(path, 'utf-8')).replace(/^\uFEFF/, '');
|
|
14
|
+
const lineOf = lineFinder(content);
|
|
15
|
+
let fields;
|
|
16
|
+
const rows = [];
|
|
17
|
+
let rowStart = 0;
|
|
18
|
+
let malformed;
|
|
19
|
+
Papa.parse(content, {
|
|
20
|
+
delimiter: ',',
|
|
14
21
|
skipEmptyLines: true,
|
|
22
|
+
step: (result, parser) => {
|
|
23
|
+
const line = lineOf(firstContent(content, rowStart));
|
|
24
|
+
rowStart = result.meta.cursor;
|
|
25
|
+
const [error] = result.errors;
|
|
26
|
+
if (error) {
|
|
27
|
+
malformed = `Invalid CSV at line ${line}: ${error.message}`;
|
|
28
|
+
parser.abort();
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
if (!fields) {
|
|
32
|
+
fields = result.data;
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
const row = {};
|
|
36
|
+
fields.forEach((field, at) => {
|
|
37
|
+
const value = result.data[at];
|
|
38
|
+
if (value !== undefined)
|
|
39
|
+
row[field] = value;
|
|
40
|
+
});
|
|
41
|
+
rows.push({ row, line });
|
|
42
|
+
},
|
|
15
43
|
});
|
|
16
|
-
if (
|
|
44
|
+
if (malformed)
|
|
45
|
+
throw new Error(malformed);
|
|
46
|
+
if (!fields?.includes('input')) {
|
|
17
47
|
throw new Error('CSV must have an "input" column');
|
|
18
48
|
}
|
|
19
|
-
return
|
|
49
|
+
return rows.map(({ row, line }) => {
|
|
20
50
|
const evalCase = { input: row.input };
|
|
21
51
|
if (row.expected !== undefined && row.expected !== '') {
|
|
22
52
|
evalCase.expected = row.expected;
|
|
@@ -37,7 +67,41 @@ export async function loadCsv(path) {
|
|
|
37
67
|
evalCase.metadata = metadata;
|
|
38
68
|
if (Object.keys(context).length > 0)
|
|
39
69
|
evalCase.context = context;
|
|
40
|
-
|
|
70
|
+
const checked = EvalCaseSchema.safeParse(evalCase);
|
|
71
|
+
if (!checked.success) {
|
|
72
|
+
throw new Error(`Invalid case at line ${line}: ${describeIssues(checked.error)}`);
|
|
73
|
+
}
|
|
74
|
+
return checked.data;
|
|
41
75
|
});
|
|
42
76
|
}
|
|
77
|
+
/** Where the text after `offset` starts, past the line breaks of blank lines before it */
|
|
78
|
+
function firstContent(content, offset) {
|
|
79
|
+
let at = offset;
|
|
80
|
+
while (at < content.length && (content[at] === '\n' || content[at] === '\r'))
|
|
81
|
+
at++;
|
|
82
|
+
return at;
|
|
83
|
+
}
|
|
84
|
+
/** The 1-based line of an offset in `content`, a line ending at `\r\n`, `\r` or `\n` */
|
|
85
|
+
function lineFinder(content) {
|
|
86
|
+
const starts = [0];
|
|
87
|
+
for (let at = 0; at < content.length; at++) {
|
|
88
|
+
const char = content[at];
|
|
89
|
+
if (char === '\r' && content[at + 1] === '\n')
|
|
90
|
+
continue;
|
|
91
|
+
if (char === '\n' || char === '\r')
|
|
92
|
+
starts.push(at + 1);
|
|
93
|
+
}
|
|
94
|
+
return (offset) => {
|
|
95
|
+
let low = 0;
|
|
96
|
+
let high = starts.length - 1;
|
|
97
|
+
while (low < high) {
|
|
98
|
+
const mid = (low + high + 1) >> 1;
|
|
99
|
+
if (starts[mid] <= offset)
|
|
100
|
+
low = mid;
|
|
101
|
+
else
|
|
102
|
+
high = mid - 1;
|
|
103
|
+
}
|
|
104
|
+
return low + 1;
|
|
105
|
+
};
|
|
106
|
+
}
|
|
43
107
|
//# sourceMappingURL=csv-loader.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"csv-loader.js","sourceRoot":"","sources":["../../src/datasets/csv-loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"csv-loader.js","sourceRoot":"","sources":["../../src/datasets/csv-loader.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,7 +9,16 @@ export declare class Dataset {
|
|
|
9
9
|
get cases(): readonly EvalCase[];
|
|
10
10
|
[Symbol.iterator](): Iterator<EvalCase>;
|
|
11
11
|
filter(fn: (c: EvalCase) => boolean): Dataset;
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
/**
|
|
13
|
+
* `n` cases picked at random, all of them when `n` is at least the size. With `seed` the pick
|
|
14
|
+
* is the same on every run, so a sampled eval compares like with like
|
|
15
|
+
*/
|
|
16
|
+
sample(n: number, options?: {
|
|
17
|
+
seed?: number | string;
|
|
18
|
+
}): Dataset;
|
|
19
|
+
/** The cases in random order, the same order on every run with `seed` */
|
|
20
|
+
shuffle(options?: {
|
|
21
|
+
seed?: number | string;
|
|
22
|
+
}): Dataset;
|
|
14
23
|
}
|
|
15
24
|
//# sourceMappingURL=dataset.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dataset.d.ts","sourceRoot":"","sources":["../../src/datasets/dataset.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAI1C,qBAAa,OAAO;IAClB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAsB;IAE7C,OAAO;IAIP,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,OAAO;WAI1B,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;WAKzC,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKpD,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,IAAI,KAAK,IAAI,SAAS,QAAQ,EAAE,CAE/B;IAED,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC;IAavC,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,QAAQ,KAAK,OAAO,GAAG,OAAO;IAI7C,MAAM,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO;
|
|
1
|
+
{"version":3,"file":"dataset.d.ts","sourceRoot":"","sources":["../../src/datasets/dataset.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAI1C,qBAAa,OAAO;IAClB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAsB;IAE7C,OAAO;IAIP,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,OAAO;WAI1B,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;WAKzC,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKpD,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,IAAI,KAAK,IAAI,SAAS,QAAQ,EAAE,CAE/B;IAED,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC;IAavC,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,QAAQ,KAAK,OAAO,GAAG,OAAO;IAI7C;;;OAGG;IACH,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,GAAE;QAAE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;KAAO,GAAG,OAAO;IAYpE,yEAAyE;IACzE,OAAO,CAAC,OAAO,GAAE;QAAE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;KAAO,GAAG,OAAO;CAG3D"}
|
package/dist/datasets/dataset.js
CHANGED
|
@@ -38,25 +38,54 @@ export class Dataset {
|
|
|
38
38
|
filter(fn) {
|
|
39
39
|
return new Dataset(this._cases.filter(fn));
|
|
40
40
|
}
|
|
41
|
-
|
|
41
|
+
/**
|
|
42
|
+
* `n` cases picked at random, all of them when `n` is at least the size. With `seed` the pick
|
|
43
|
+
* is the same on every run, so a sampled eval compares like with like
|
|
44
|
+
*/
|
|
45
|
+
sample(n, options = {}) {
|
|
42
46
|
if (n <= 0 || this._cases.length === 0) {
|
|
43
47
|
return new Dataset([]);
|
|
44
48
|
}
|
|
45
49
|
const count = Math.min(n, this._cases.length);
|
|
46
|
-
const indices = Array.from({ length: this._cases.length }, (_, i) => i);
|
|
47
|
-
for (let i = indices.length - 1; i > 0; i--) {
|
|
48
|
-
const j = Math.floor(Math.random() * (i + 1));
|
|
49
|
-
[indices[i], indices[j]] = [indices[j], indices[i]];
|
|
50
|
-
}
|
|
50
|
+
const indices = shuffled(Array.from({ length: this._cases.length }, (_, i) => i), randomOf(options.seed));
|
|
51
51
|
return new Dataset(indices.slice(0, count).map((i) => this._cases[i]));
|
|
52
52
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
53
|
+
/** The cases in random order, the same order on every run with `seed` */
|
|
54
|
+
shuffle(options = {}) {
|
|
55
|
+
return new Dataset(shuffled([...this._cases], randomOf(options.seed)));
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/** Shuffles `items` in place (Fisher-Yates) with the random numbers `random` gives */
|
|
59
|
+
function shuffled(items, random) {
|
|
60
|
+
for (let i = items.length - 1; i > 0; i--) {
|
|
61
|
+
const j = Math.floor(random() * (i + 1));
|
|
62
|
+
[items[i], items[j]] = [items[j], items[i]];
|
|
63
|
+
}
|
|
64
|
+
return items;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* `Math.random`, or a mulberry32 generator seeded by the hash of `seed`, so every number and
|
|
68
|
+
* string seeds its own sequence (`1.2` and `1.7`, `-1` and `2 ** 32 - 1` alike)
|
|
69
|
+
*/
|
|
70
|
+
function randomOf(seed) {
|
|
71
|
+
if (seed === undefined)
|
|
72
|
+
return Math.random;
|
|
73
|
+
let state = hashSeed(String(seed));
|
|
74
|
+
return () => {
|
|
75
|
+
state = (state + 0x6d2b79f5) >>> 0;
|
|
76
|
+
let t = state;
|
|
77
|
+
t = Math.imul(t ^ (t >>> 15), t | 1);
|
|
78
|
+
t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
|
|
79
|
+
return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
/** FNV-1a of a string, to seed the generator */
|
|
83
|
+
function hashSeed(seed) {
|
|
84
|
+
let hash = 0x811c9dc5;
|
|
85
|
+
for (let i = 0; i < seed.length; i++) {
|
|
86
|
+
hash ^= seed.charCodeAt(i);
|
|
87
|
+
hash = Math.imul(hash, 0x01000193) >>> 0;
|
|
60
88
|
}
|
|
89
|
+
return hash;
|
|
61
90
|
}
|
|
62
91
|
//# sourceMappingURL=dataset.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dataset.js","sourceRoot":"","sources":["../../src/datasets/dataset.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAE3C,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,MAAM,OAAO,OAAO;IACD,MAAM,CAAsB;IAE7C,YAAoB,KAAiB;QACnC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACzE,CAAC;IAED,MAAM,CAAC,IAAI,CAAC,KAAiB;QAC3B,OAAO,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC;IAC5B,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,IAAY;QACjC,MAAM,KAAK,GAAG,MAAM,SAAS,CAAC,IAAI,CAAC,CAAC;QACpC,OAAO,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC7B,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,IAAY;QAC/B,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;QAClC,OAAO,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC7B,CAAC;IAED,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;IAC5B,CAAC;IAED,IAAI,KAAK;QACP,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED,CAAC,MAAM,CAAC,QAAQ,CAAC;QACf,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC;QAC1B,OAAO;YACL,IAAI;gBACF,IAAI,KAAK,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;oBACzB,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;gBAChD,CAAC;gBACD,OAAO,EAAE,KAAK,EAAE,SAAkB,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;YACnD,CAAC;SACF,CAAC;IACJ,CAAC;IAED,MAAM,CAAC,EAA4B;QACjC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IAC7C,CAAC;IAED,MAAM,CAAC,CAAS;
|
|
1
|
+
{"version":3,"file":"dataset.js","sourceRoot":"","sources":["../../src/datasets/dataset.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"issues.d.ts","sourceRoot":"","sources":["../../src/datasets/issues.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAE7B,4EAA4E;AAC5E,wBAAgB,cAAc,CAAC,KAAK,EAAE,CAAC,CAAC,QAAQ,GAAG,MAAM,CAIxD"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** What a case breaks of the case schema, one `field: problem` per issue */
|
|
2
|
+
export function describeIssues(error) {
|
|
3
|
+
return error.issues
|
|
4
|
+
.map((issue) => `${issue.path.length > 0 ? issue.path.join('.') : '(case)'}: ${issue.message}`)
|
|
5
|
+
.join('; ');
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=issues.js.map
|