@cogitator-ai/evals 0.8.0 → 0.10.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 +255 -54
- 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 +5 -0
- package/dist/datasets/csv-loader.d.ts.map +1 -1
- package/dist/datasets/csv-loader.js +89 -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-builder.d.ts +3 -0
- package/dist/eval-builder.d.ts.map +1 -1
- package/dist/eval-builder.js +7 -0
- package/dist/eval-builder.js.map +1 -1
- package/dist/eval-comparison.d.ts +7 -0
- package/dist/eval-comparison.d.ts.map +1 -1
- package/dist/eval-comparison.js +42 -12
- package/dist/eval-comparison.js.map +1 -1
- package/dist/eval-suite.d.ts +55 -8
- package/dist/eval-suite.d.ts.map +1 -1
- package/dist/eval-suite.js +254 -53
- package/dist/eval-suite.js.map +1 -1
- package/dist/index.d.ts +14 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -2
- package/dist/index.js.map +1 -1
- package/dist/matchers.d.ts +68 -0
- package/dist/matchers.d.ts.map +1 -0
- package/dist/matchers.js +112 -0
- package/dist/matchers.js.map +1 -0
- package/dist/metrics/custom.d.ts +19 -7
- package/dist/metrics/custom.d.ts.map +1 -1
- package/dist/metrics/custom.js +5 -0
- package/dist/metrics/custom.js.map +1 -1
- package/dist/metrics/index.d.ts +8 -4
- package/dist/metrics/index.d.ts.map +1 -1
- package/dist/metrics/index.js +4 -2
- package/dist/metrics/index.js.map +1 -1
- package/dist/metrics/llm-judge.d.ts +20 -1
- package/dist/metrics/llm-judge.d.ts.map +1 -1
- package/dist/metrics/llm-judge.js +162 -20
- package/dist/metrics/llm-judge.js.map +1 -1
- package/dist/metrics/matching.d.ts +28 -0
- package/dist/metrics/matching.d.ts.map +1 -0
- package/dist/metrics/matching.js +124 -0
- package/dist/metrics/matching.js.map +1 -0
- package/dist/metrics/retrieval.d.ts +21 -0
- package/dist/metrics/retrieval.d.ts.map +1 -0
- package/dist/metrics/retrieval.js +108 -0
- package/dist/metrics/retrieval.js.map +1 -0
- package/dist/metrics/statistical.d.ts +28 -0
- package/dist/metrics/statistical.d.ts.map +1 -1
- package/dist/metrics/statistical.js +61 -0
- package/dist/metrics/statistical.js.map +1 -1
- package/dist/metrics/tool-calls.d.ts +43 -0
- package/dist/metrics/tool-calls.d.ts.map +1 -0
- package/dist/metrics/tool-calls.js +106 -0
- package/dist/metrics/tool-calls.js.map +1 -0
- package/dist/metrics/types.d.ts +53 -5
- 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 +11 -4
- 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 +19 -0
- package/dist/reporters/format.d.ts.map +1 -0
- package/dist/reporters/format.js +31 -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 +95 -0
- package/dist/reporters/github.js.map +1 -0
- package/dist/reporters/index.d.ts +44 -20
- 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 +25 -0
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +29 -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 +17 -3
package/README.md
CHANGED
|
@@ -10,20 +10,24 @@ 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
|
-
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).
|
|
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), [Agents](https://cogitator.app/docs/evals/agents), [Comparison](https://cogitator.app/docs/evals/comparison), [Reporters](https://cogitator.app/docs/evals/reporters).
|
|
16
17
|
|
|
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
|
-
- **
|
|
22
|
+
- **6 LLM-as-Judge Metrics** - faithfulness, relevance, coherence, helpfulness, contextRelevance, custom llmMetric
|
|
23
|
+
- **4 Statistical Metrics** - latency, cost, tokenUsage with full percentile breakdowns, and passAtK over trials
|
|
23
24
|
- **Custom Metrics** — `metric()` factory for anything domain-specific
|
|
25
|
+
- **Agent Evaluation** - `toolCalls()` and `trajectory()` against expected tool calls, `retrievalRecall()`, `retrievalPrecision()`, `retrievalMRR()` and the `contextRelevance()` judge against expected passages, multi-turn cases on one conversation
|
|
26
|
+
- **Trials and pass@k** - run each case several times and score how often it passes with `passAtK()`
|
|
24
27
|
- **Assertions** — threshold, noRegression, custom assertion with auto-detection of lower-is-better metrics
|
|
25
28
|
- **A/B Testing** — EvalComparison with paired t-test and McNemar's test for statistical significance
|
|
26
|
-
- **
|
|
29
|
+
- **6 Reporters** - console (colored table), JSON, CSV, JUnit XML, GitHub Actions annotations and job summary, CI (exit code on failure)
|
|
30
|
+
- **Vitest** - `describeEval` from `@cogitator-ai/evals/vitest` runs a suite as a test file, one test per case plus one for the assertions, and `evalMatchers` from `@cogitator-ai/evals/matchers` (Vitest 5) adds `toHaveCalledTool`, `toFollowTrajectory`, `toHaveRetrieved` and `toScoreAtLeast`
|
|
27
31
|
- **Builder API** — Fluent `EvalBuilder` for composable eval pipelines
|
|
28
32
|
- **Baseline Workflow** — Save baselines, compare against them, catch regressions in CI
|
|
29
33
|
- **Zod Validation** — Type-safe configuration with runtime checks
|
|
@@ -62,7 +66,7 @@ result.report('console');
|
|
|
62
66
|
result.saveBaseline('./baseline.json');
|
|
63
67
|
```
|
|
64
68
|
|
|
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
|
|
69
|
+
A target is either `{ fn: (input, { signal, case, attempt, turn, history }) => Promise<string> }` or `{ agent, cogitator, retrieval? }`, which runs the agent with `cogitator.run(agent, { input, context, signal, onToolResult })` and records its usage, tool calls, tool results and retrieved passages (see [Agent Evaluation](#agent-evaluation)). Defaults: `concurrency` 5, `timeout` 30 000 ms (minimum 1 000), `retries` 0, `trials` 1.
|
|
66
70
|
|
|
67
71
|
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
72
|
|
|
@@ -82,25 +86,27 @@ const suite = new EvalSuite({
|
|
|
82
86
|
|
|
83
87
|
`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
88
|
|
|
89
|
+
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.
|
|
90
|
+
|
|
85
91
|
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
92
|
|
|
87
93
|
`result.stats` holds:
|
|
88
94
|
|
|
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
|
|
95
|
+
| Field | Meaning |
|
|
96
|
+
| -------------- | ---------------------------------------------------------------------------------------------------------------------- |
|
|
97
|
+
| `total` | Cases run |
|
|
98
|
+
| `errors` | Cases whose every attempt failed or timed out (with several trials, a case counts as errored when every trial errored) |
|
|
99
|
+
| `metricErrors` | Metric scores that failed and count as 0, over every trial |
|
|
100
|
+
| `duration` | Wall time of the run in ms |
|
|
101
|
+
| `cost` | USD spent, `targetCost + judgeCost` |
|
|
102
|
+
| `targetCost` | USD the target spent, over every attempt and trial that reported usage |
|
|
103
|
+
| `judgeCost` | USD the LLM judge spent |
|
|
98
104
|
|
|
99
105
|
---
|
|
100
106
|
|
|
101
107
|
## Datasets
|
|
102
108
|
|
|
103
|
-
Datasets are immutable collections of eval cases. Each case has an `input`, optional `expected`, optional `context`, and optional `metadata`.
|
|
109
|
+
Datasets are immutable collections of eval cases. Each case has an `input`, optional `expected`, optional `context`, and optional `metadata`. Agent cases may also have `turns` (further user turns run on the same conversation), `expectedToolCalls` (`{ name, arguments? }[]`) and `expectedPassages` (ids or texts the retrieval should surface).
|
|
104
110
|
|
|
105
111
|
### From inline data
|
|
106
112
|
|
|
@@ -134,7 +140,15 @@ Requires `papaparse` as an optional dependency.
|
|
|
134
140
|
const dataset = await Dataset.fromCsv('./evals/qa.csv');
|
|
135
141
|
```
|
|
136
142
|
|
|
137
|
-
CSV must have an `input` column. Optional columns: `expected`, `metadata.*`, `context
|
|
143
|
+
CSV must have an `input` column. Optional columns: `expected`, `metadata.*`, `context.*`, and `turns`, `expectedToolCalls` and `expectedPassages`, whose cells hold JSON arrays (CSV-quoted, an empty cell leaves the field out):
|
|
144
|
+
|
|
145
|
+
```csv
|
|
146
|
+
input,turns,expectedToolCalls,expectedPassages
|
|
147
|
+
Book a table,"[""For two, please""]","[{""name"":""book_table"",""arguments"":{""guests"":2}}]",
|
|
148
|
+
How long do refunds take?,,"[{""name"":""rag_search""}]","[""refund is issued within 5 days""]"
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
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.
|
|
138
152
|
|
|
139
153
|
### Transformations
|
|
140
154
|
|
|
@@ -142,6 +156,7 @@ CSV must have an `input` column. Optional columns: `expected`, `metadata.*`, `co
|
|
|
142
156
|
const filtered = dataset.filter((c) => c.expected !== undefined);
|
|
143
157
|
const sampled = dataset.sample(50);
|
|
144
158
|
const shuffled = dataset.shuffle();
|
|
159
|
+
const nightly = dataset.sample(50, { seed: 'nightly' }); // the same cases on every run
|
|
145
160
|
```
|
|
146
161
|
|
|
147
162
|
All transformations return new `Dataset` instances — the original is never mutated.
|
|
@@ -208,13 +223,14 @@ const metrics = [
|
|
|
208
223
|
|
|
209
224
|
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.
|
|
210
225
|
|
|
211
|
-
| Metric
|
|
212
|
-
|
|
|
213
|
-
| `faithfulness`
|
|
214
|
-
| `relevance`
|
|
215
|
-
| `coherence`
|
|
216
|
-
| `helpfulness`
|
|
217
|
-
| `
|
|
226
|
+
| Metric | Evaluates |
|
|
227
|
+
| ------------------ | -------------------------------------------- |
|
|
228
|
+
| `faithfulness` | Factual accuracy relative to input |
|
|
229
|
+
| `relevance` | How on-topic the response is |
|
|
230
|
+
| `coherence` | Logical structure and readability |
|
|
231
|
+
| `helpfulness` | Practical usefulness to the user |
|
|
232
|
+
| `contextRelevance` | Whether the retrieved passages fit the input |
|
|
233
|
+
| `llmMetric` | Custom prompt, you define the criteria |
|
|
218
234
|
|
|
219
235
|
```typescript
|
|
220
236
|
import { faithfulness, relevance, llmMetric } from '@cogitator-ai/evals';
|
|
@@ -240,7 +256,9 @@ The judge reads the case's `context` too, so `faithfulness()` can check a respon
|
|
|
240
256
|
Dataset.from([{ input: 'Write the lede', context: { dossier: dossierText } }]);
|
|
241
257
|
```
|
|
242
258
|
|
|
243
|
-
|
|
259
|
+
When the run retrieved passages (see [Retrieval](#retrieval)), `faithfulness()` checks the response against them instead of `context`. `contextRelevance()` judges the input against the retrieved passages alone, or against `context` when nothing was retrieved, and scores 0 without a judge call when the case has neither.
|
|
260
|
+
|
|
261
|
+
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.
|
|
244
262
|
|
|
245
263
|
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`.
|
|
246
264
|
|
|
@@ -261,7 +279,7 @@ const suite = new EvalSuite({
|
|
|
261
279
|
|
|
262
280
|
### Custom
|
|
263
281
|
|
|
264
|
-
Build domain-specific metrics with the `metric()` factory.
|
|
282
|
+
Build domain-specific metrics with the `metric()` factory. `evaluate` gets `input`, `output`, `expected` and `context`, the run's `toolCalls`, `toolResults`, `retrieved` and `turns`, and the whole case result as `result`.
|
|
265
283
|
|
|
266
284
|
```typescript
|
|
267
285
|
import { metric } from '@cogitator-ai/evals';
|
|
@@ -285,6 +303,108 @@ Scores are automatically clamped to [0, 1]. A score that is not a finite number
|
|
|
285
303
|
|
|
286
304
|
---
|
|
287
305
|
|
|
306
|
+
## Agent Evaluation
|
|
307
|
+
|
|
308
|
+
An agent target records what the agent did, not only what it answered. Each case result carries `toolCalls` (every call of the run), `toolResults` (`{ callId, name, result?, error? }`, the raw values the run's `onToolResult` reported) and `retrieved` (`{ id?, content, score?, source? }` passages the tool results surfaced), summed over every turn of the case.
|
|
309
|
+
|
|
310
|
+
### Tool calls and trajectory
|
|
311
|
+
|
|
312
|
+
```typescript
|
|
313
|
+
import { EvalSuite, Dataset, toolCalls, trajectory } from '@cogitator-ai/evals';
|
|
314
|
+
|
|
315
|
+
const dataset = Dataset.from([
|
|
316
|
+
{
|
|
317
|
+
input: 'What is the weather in Paris?',
|
|
318
|
+
expectedToolCalls: [{ name: 'get_weather', arguments: { city: 'Paris' } }],
|
|
319
|
+
},
|
|
320
|
+
]);
|
|
321
|
+
|
|
322
|
+
const suite = new EvalSuite({
|
|
323
|
+
dataset,
|
|
324
|
+
target: { agent, cogitator },
|
|
325
|
+
metrics: [toolCalls(), trajectory({ order: 'in-order' })],
|
|
326
|
+
});
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
`toolCalls({ arguments?, score? })` pairs the actual calls with the expected ones as multisets, each expected call taking at most one actual call. `arguments: 'subset'` (default) wants the expected arguments in the call with equal values, other arguments allowed, `'exact'` wants equal arguments and `'ignore'` compares names only. An expected call without `arguments` matches on its name. `score` is `'f1'` (default), `'recall'` or `'precision'`, and `details` lists the missing and unexpected calls.
|
|
330
|
+
|
|
331
|
+
`trajectory({ order? })` compares the sequence of tool names: `'exact'` (default) scores 1 for the same sequence and 0 otherwise, `'in-order'` scores the longest common subsequence over the longer sequence, and `'any-order'` the names both share over the longer sequence.
|
|
332
|
+
|
|
333
|
+
Both score 0 with `details: 'no expected tool calls provided'` on a case without `expectedToolCalls`, as `exactMatch()` does without `expected`. A case expecting no calls (`expectedToolCalls: []`) scores 1 when the agent made none.
|
|
334
|
+
|
|
335
|
+
### Retrieval
|
|
336
|
+
|
|
337
|
+
```typescript
|
|
338
|
+
import {
|
|
339
|
+
retrievalRecall,
|
|
340
|
+
retrievalPrecision,
|
|
341
|
+
retrievalMRR,
|
|
342
|
+
contextRelevance,
|
|
343
|
+
} from '@cogitator-ai/evals';
|
|
344
|
+
import { createSearchTool } from '@cogitator-ai/rag';
|
|
345
|
+
|
|
346
|
+
const agent = new Agent({ name: 'kb', model, tools: [tool(createSearchTool(pipeline))] });
|
|
347
|
+
|
|
348
|
+
const suite = new EvalSuite({
|
|
349
|
+
dataset: Dataset.from([
|
|
350
|
+
{ input: 'How long do refunds take?', expectedPassages: ['refund is issued within 5 days'] },
|
|
351
|
+
]),
|
|
352
|
+
target: { agent, cogitator },
|
|
353
|
+
metrics: [retrievalRecall(), retrievalPrecision(), retrievalMRR(), contextRelevance()],
|
|
354
|
+
judge: { model: 'google/gemini-3.5-flash-lite' },
|
|
355
|
+
});
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
The target's `retrieval` reads the passages out of each successful tool result. The default, `ragSearchPassages`, reads the `rag_search` tool of `@cogitator-ai/rag` (`{ results: [{ content, chunkId, score, source, ... }] }`, the `id` of a result or else its `chunkId` as the passage id) and any other result of that shape. Pass your own for other tools:
|
|
359
|
+
|
|
360
|
+
```typescript
|
|
361
|
+
target: {
|
|
362
|
+
agent,
|
|
363
|
+
cogitator,
|
|
364
|
+
retrieval: ({ name, result }) =>
|
|
365
|
+
name === 'search_docs' ? (result as Doc[]).map((d) => ({ id: d.slug, content: d.body })) : undefined,
|
|
366
|
+
},
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
A retrieved passage matches an expected one by an equal `id`, by an equal text once case and whitespace are normalized, or when one normalized text contains the other and the contained one has at least three words, so a short id or a single word never matches every passage that happens to hold it. `retrievalRecall()` scores the share of expected passages retrieved, `retrievalPrecision()` the share of retrieved passages expected, and `retrievalMRR()` the reciprocal rank of the first match (passages rank in the order they came). They score 0 on a case without `expectedPassages`, and a case expecting none scores 1 when nothing was retrieved.
|
|
370
|
+
|
|
371
|
+
### Multi-turn cases
|
|
372
|
+
|
|
373
|
+
```typescript
|
|
374
|
+
const cogitator = new Cogitator({ llm, memory: { adapter: 'memory' } });
|
|
375
|
+
|
|
376
|
+
Dataset.from([
|
|
377
|
+
{
|
|
378
|
+
input: 'My name is Ada.',
|
|
379
|
+
turns: ['What is my name?'],
|
|
380
|
+
expected: 'Ada',
|
|
381
|
+
},
|
|
382
|
+
]);
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
An agent case with `turns` runs `input`, then each turn, on one thread of its own (`threadId` `eval-<uuid>`, a fresh one for every attempt and trial). The Cogitator's memory carries the conversation from turn to turn, so it needs a memory adapter. The case `output` is the last answer, `toolCalls`, `toolResults`, `retrieved` and `usage` cover every turn, and `turns` lists each `{ input, output, toolCalls? }`. A turn that fails fails the case with its error, `turns` then ending with the failed one, and a cancelled or timed-out case starts no further turn. LLM judges read a multi-turn case as the conversation, each turn's input and answer, with the last user message marked as the one the response answers. A `fn` target is called once per turn, with `context.turn` (0 for `input`) and `context.history` (the earlier `{ input, output }` turns).
|
|
386
|
+
|
|
387
|
+
### Trials and pass@k
|
|
388
|
+
|
|
389
|
+
```typescript
|
|
390
|
+
import { passAtK, exactMatch, threshold } from '@cogitator-ai/evals';
|
|
391
|
+
|
|
392
|
+
const suite = new EvalSuite({
|
|
393
|
+
dataset,
|
|
394
|
+
target: { agent, cogitator },
|
|
395
|
+
metrics: [exactMatch()],
|
|
396
|
+
statisticalMetrics: [passAtK('exactMatch', { k: 1 }), passAtK('exactMatch', { k: 5 })],
|
|
397
|
+
assertions: [threshold('passAtK(exactMatch,5)', 0.9)],
|
|
398
|
+
trials: 5,
|
|
399
|
+
});
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
`trials` (a positive integer, 1 by default) runs each case that many times. Trials share the suite's concurrency, timeout, retries, abort signal and `maxCases`, and each is scored on its own. The case result is the first trial that answered (the first one when every trial errored), so it carries an error only when all trials failed, with every trial in `trials` (each with its `scores`), and the aggregate of a metric takes the mean of a case's scored trials as that case's score. `stats.errors` counts a case as errored when every trial errored, while costs and `metricErrors` cover every trial. `latency()`, `cost()` and `tokenUsage()` see every trial as one value each, `passAtK()` sees the cases with their trials. `onProgress` fires once per case, after its last trial. `EvalComparison` takes `trials` too, comparing each case's mean over its trials.
|
|
403
|
+
|
|
404
|
+
`passAtK(metric, { k, threshold = 1 })`, named `passAtK(<metric>,<k>)`, estimates per case the chance that at least one of `k` trials scores `threshold` or more, with the unbiased estimator `1 - C(n - c, k) / C(n, k)` (`n` trials, `c` passing), and averages it over the cases with at least one scored trial. An errored trial counts as a failure. The suite throws when it is created if `k` exceeds `trials` or the metric is not among its `metrics`.
|
|
405
|
+
|
|
406
|
+
---
|
|
407
|
+
|
|
288
408
|
## Assertions
|
|
289
409
|
|
|
290
410
|
Assertions check aggregated metrics after a suite run and produce pass/fail results.
|
|
@@ -306,6 +426,16 @@ const assertions = [
|
|
|
306
426
|
|
|
307
427
|
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.
|
|
308
428
|
|
|
429
|
+
### maxErrorRate
|
|
430
|
+
|
|
431
|
+
```typescript
|
|
432
|
+
import { maxErrorRate } from '@cogitator-ai/evals';
|
|
433
|
+
|
|
434
|
+
const assertions = [threshold('exactMatch', 0.9), maxErrorRate(0.05)];
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
Passes while at most `rate` (0 to 1) of the cases errored. Errored cases are not scored, so pair metric thresholds with it.
|
|
438
|
+
|
|
309
439
|
### noRegression
|
|
310
440
|
|
|
311
441
|
Compares current results against a saved baseline file.
|
|
@@ -357,6 +487,7 @@ const comparison = new EvalComparison({
|
|
|
357
487
|
},
|
|
358
488
|
metrics: [exactMatch(), contains()],
|
|
359
489
|
concurrency: 5,
|
|
490
|
+
trials: 1,
|
|
360
491
|
});
|
|
361
492
|
|
|
362
493
|
const result = await comparison.run();
|
|
@@ -377,22 +508,66 @@ Access full suite results via `result.baseline` and `result.challenger`. `compar
|
|
|
377
508
|
|
|
378
509
|
Call `result.report()` after a suite run to output results.
|
|
379
510
|
|
|
380
|
-
| Reporter | Output
|
|
381
|
-
| --------- |
|
|
382
|
-
| `console` | Colored table with metrics, assertions, summary
|
|
383
|
-
| `json` | Writes `eval-report.json` (configurable path)
|
|
384
|
-
| `csv` | Writes `eval-report.csv` (configurable path)
|
|
385
|
-
| `
|
|
511
|
+
| Reporter | Output |
|
|
512
|
+
| --------- | -------------------------------------------------------------------- |
|
|
513
|
+
| `console` | Colored table with metrics, assertions, summary |
|
|
514
|
+
| `json` | Writes `eval-report.json` (configurable path) |
|
|
515
|
+
| `csv` | Writes `eval-report.csv` (configurable path) |
|
|
516
|
+
| `junit` | Writes `eval-report.xml`, a JUnit report (configurable path) |
|
|
517
|
+
| `github` | GitHub Actions annotations, plus a job summary in Actions |
|
|
518
|
+
| `ci` | Compact verdict, sets `process.exitCode = 1` when an assertion fails |
|
|
386
519
|
|
|
387
520
|
```typescript
|
|
388
521
|
const result = await suite.run();
|
|
389
522
|
|
|
390
523
|
result.report('console');
|
|
391
524
|
result.report('json', { path: './reports/eval.json' });
|
|
392
|
-
result.report(['console', 'json', 'csv']);
|
|
393
|
-
result.report('ci');
|
|
525
|
+
result.report(['console', 'json', 'csv', 'junit'], { path: './reports/eval' });
|
|
526
|
+
result.report(['github', 'ci']);
|
|
527
|
+
```
|
|
528
|
+
|
|
529
|
+
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.
|
|
530
|
+
|
|
531
|
+
- **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.
|
|
532
|
+
- **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.
|
|
533
|
+
|
|
534
|
+
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. The json report keeps each case's `toolCalls`, `toolResults`, `retrieved`, `turns` and `trials`, and the console and github reports show the trials per case.
|
|
535
|
+
|
|
536
|
+
### Vitest
|
|
537
|
+
|
|
538
|
+
```typescript
|
|
539
|
+
// eval/qa.eval.test.ts
|
|
540
|
+
import { afterAll } from 'vitest';
|
|
541
|
+
import { describeEval } from '@cogitator-ai/evals/vitest';
|
|
542
|
+
|
|
543
|
+
const qa = describeEval('qa agent', { suite, run: { maxCases: 50 }, timeout: 5 * 60_000 });
|
|
544
|
+
|
|
545
|
+
afterAll(() => qa.result().report('junit', { path: './reports/qa' }));
|
|
546
|
+
```
|
|
547
|
+
|
|
548
|
+
`evalMatchers` adds assertions on results to Vitest's `expect`, typed through a module augmentation of `Assertion` and `AsymmetricMatchersContaining` (Vitest 5):
|
|
549
|
+
|
|
550
|
+
```typescript
|
|
551
|
+
import { expect, it } from 'vitest';
|
|
552
|
+
import { evalMatchers } from '@cogitator-ai/evals/matchers';
|
|
553
|
+
|
|
554
|
+
expect.extend(evalMatchers);
|
|
555
|
+
|
|
556
|
+
it('books a table', async () => {
|
|
557
|
+
const result = await suite.run();
|
|
558
|
+
const [booking] = result.results;
|
|
559
|
+
expect(booking).toHaveCalledTool('book_table', { guests: 2 });
|
|
560
|
+
expect(booking).toFollowTrajectory(['find_restaurant', 'book_table'], { order: 'in-order' });
|
|
561
|
+
expect(booking).toHaveRetrieved('doc:menu');
|
|
562
|
+
expect(booking).toScoreAtLeast('toolCalls', 1);
|
|
563
|
+
expect(result).toScoreAtLeast('trajectory', 0.8);
|
|
564
|
+
});
|
|
394
565
|
```
|
|
395
566
|
|
|
567
|
+
`toHaveCalledTool(name, args?)` checks a case result's calls, `args` as a subset of a call's arguments. `toFollowTrajectory(names, { order? })` wants exactly those calls in that order by default, the calls in that order with others between them for `'in-order'`, and each of them in any order for `'any-order'`. `toHaveRetrieved(idOrText)` matches passages as the retrieval metrics do. `toScoreAtLeast(metric, min)` reads a case result's score or a suite result's aggregated mean, and throws when the metric is missing.
|
|
568
|
+
|
|
569
|
+
`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.
|
|
570
|
+
|
|
396
571
|
---
|
|
397
572
|
|
|
398
573
|
## Builder API
|
|
@@ -421,6 +596,7 @@ const suite = new EvalBuilder()
|
|
|
421
596
|
.withConcurrency(10)
|
|
422
597
|
.withTimeout(60_000)
|
|
423
598
|
.withRetries(2)
|
|
599
|
+
.withTrials(3)
|
|
424
600
|
.onProgress(({ completed, total }) => {
|
|
425
601
|
console.log(`${completed}/${total}`);
|
|
426
602
|
})
|
|
@@ -484,38 +660,63 @@ result.report('ci');
|
|
|
484
660
|
|
|
485
661
|
### Metrics
|
|
486
662
|
|
|
487
|
-
| Export
|
|
488
|
-
|
|
|
489
|
-
| `exactMatch`
|
|
490
|
-
| `contains`
|
|
491
|
-
| `containsAll`
|
|
492
|
-
| `containsAny`
|
|
493
|
-
| `similarity`
|
|
494
|
-
| `regex`
|
|
495
|
-
| `jsonSchema`
|
|
496
|
-
| `faithfulness`
|
|
497
|
-
| `relevance`
|
|
498
|
-
| `coherence`
|
|
499
|
-
| `helpfulness`
|
|
500
|
-
| `
|
|
501
|
-
| `
|
|
502
|
-
| `
|
|
503
|
-
| `
|
|
504
|
-
| `
|
|
663
|
+
| Export | Type | Description |
|
|
664
|
+
| -------------------- | ------------- | ------------------------------------------------------------------ |
|
|
665
|
+
| `exactMatch` | Deterministic | Exact string match |
|
|
666
|
+
| `contains` | Deterministic | Substring match |
|
|
667
|
+
| `containsAll` | Deterministic | Fraction of keywords found |
|
|
668
|
+
| `containsAny` | Deterministic | Any configured keyword found |
|
|
669
|
+
| `similarity` | Deterministic | Levenshtein distance similarity score |
|
|
670
|
+
| `regex` | Deterministic | Regex pattern match |
|
|
671
|
+
| `jsonSchema` | Deterministic | Zod schema validation |
|
|
672
|
+
| `faithfulness` | LLM Judge | Factual accuracy |
|
|
673
|
+
| `relevance` | LLM Judge | Topical relevance |
|
|
674
|
+
| `coherence` | LLM Judge | Logical structure |
|
|
675
|
+
| `helpfulness` | LLM Judge | Practical usefulness |
|
|
676
|
+
| `contextRelevance` | LLM Judge | Relevance of the retrieved passages to the input |
|
|
677
|
+
| `llmMetric` | LLM Judge | Custom judge prompt |
|
|
678
|
+
| `toolCalls` | Agent | Tool calls against `expectedToolCalls`, F1, recall or precision |
|
|
679
|
+
| `trajectory` | Agent | Sequence of tool names, exact, in-order or any-order |
|
|
680
|
+
| `retrievalRecall` | Agent | Share of `expectedPassages` retrieved |
|
|
681
|
+
| `retrievalPrecision` | Agent | Share of retrieved passages expected |
|
|
682
|
+
| `retrievalMRR` | Agent | Reciprocal rank of the first expected passage |
|
|
683
|
+
| `latency` | Statistical | Response time percentiles |
|
|
684
|
+
| `cost` | Statistical | Token cost aggregation |
|
|
685
|
+
| `tokenUsage` | Statistical | Input/output token counts |
|
|
686
|
+
| `passAtK` | Statistical | pass@k of a metric over the trials |
|
|
687
|
+
| `metric` | Custom | Factory for domain-specific metrics |
|
|
688
|
+
| `ragSearchPassages` | Helper | The default `retrieval` of agent targets, for `rag_search` results |
|
|
505
689
|
|
|
506
690
|
### Assertions
|
|
507
691
|
|
|
508
692
|
| Export | Description |
|
|
509
693
|
| -------------- | ---------------------------------------------- |
|
|
510
694
|
| `threshold` | Enforce min/max on metric mean |
|
|
695
|
+
| `maxErrorRate` | Fail a run where too many cases errored |
|
|
511
696
|
| `noRegression` | Compare against saved baseline |
|
|
512
697
|
| `assertion` | Custom assertion with arbitrary check function |
|
|
513
698
|
|
|
514
699
|
### Reporters
|
|
515
700
|
|
|
516
|
-
| Export
|
|
517
|
-
|
|
|
518
|
-
| `report`
|
|
701
|
+
| Export | Description |
|
|
702
|
+
| ---------------------------------- | ---------------------------------------- |
|
|
703
|
+
| `report` | Dispatch to one or more reporter types |
|
|
704
|
+
| `describeEval` (`/vitest` entry) | Run a suite as a Vitest describe block |
|
|
705
|
+
| `evalMatchers` (`/matchers` entry) | Matchers for `expect.extend()`, Vitest 5 |
|
|
706
|
+
|
|
707
|
+
`report` takes `console`, `json`, `csv`, `junit`, `github` and `ci`. `describeEval` takes `DescribeEvalOptions` and returns a `DescribeEvalHandle`.
|
|
708
|
+
|
|
709
|
+
### Types
|
|
710
|
+
|
|
711
|
+
| Export | Description |
|
|
712
|
+
| ------------------ | ------------------------------------------------------------------------ |
|
|
713
|
+
| `JudgeConfigInput` | The `judge` option: model, settings, `cogitator`, `cache`, `concurrency` |
|
|
714
|
+
| `JudgeCache` | Where verdicts are kept across runs: `get(key)` and `set(key, verdict)` |
|
|
715
|
+
| `AggregatedMetric` | Aggregate of a metric, with `count` for the cases it covers |
|
|
716
|
+
| `MetricComparison` | A metric of a comparison, with `n` for the cases it was compared on |
|
|
717
|
+
| `ExpectedToolCall` | A tool call a case expects: `name` and optional `arguments` |
|
|
718
|
+
| `Passage` | A retrieved passage: `id?`, `content`, `score?`, `source?` |
|
|
719
|
+
| `EvalTurnResult` | A turn of a multi-turn case: `input`, `output`, `toolCalls?`, `error?` |
|
|
519
720
|
|
|
520
721
|
### Statistics
|
|
521
722
|
|
|
@@ -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,3 +1,8 @@
|
|
|
1
1
|
import type { EvalCase } from '../schema.js';
|
|
2
|
+
/**
|
|
3
|
+
* Cases from a CSV file with an `input` column, an optional `expected` one, `metadata.<key>` and
|
|
4
|
+
* `context.<key>` columns, and `turns`, `expectedToolCalls` and `expectedPassages` columns whose
|
|
5
|
+
* cells hold JSON arrays (an empty cell leaves the field out)
|
|
6
|
+
*/
|
|
2
7
|
export declare function loadCsv(path: string): Promise<EvalCase[]>;
|
|
3
8
|
//# sourceMappingURL=csv-loader.d.ts.map
|
|
@@ -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;AAK1C;;;;GAIG;AACH,wBAAsB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,CAwF/D"}
|