@axlsdk/eval 0.13.5 → 0.13.7
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 +170 -6
- package/dist/chunk-CMWRFU3P.js +653 -0
- package/dist/chunk-CMWRFU3P.js.map +1 -0
- package/dist/cli.cjs +577 -73
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +169 -23
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +413 -47
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +74 -2
- package/dist/index.d.ts +74 -2
- package/dist/index.js +7 -1
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/dist/chunk-F2AALK5U.js +0 -290
- package/dist/chunk-F2AALK5U.js.map +0 -1
package/README.md
CHANGED
|
@@ -275,6 +275,8 @@ console.log(results.summary.count); // 50 items
|
|
|
275
275
|
console.log(results.summary.failures); // 2 workflow errors
|
|
276
276
|
console.log(results.summary.timing); // { mean, min, max, p50, p95 } in ms
|
|
277
277
|
console.log(results.totalCost); // 0.42 (workflow + scorer LLM costs)
|
|
278
|
+
console.log(results.metadata.models); // ["openai:gpt-4o"] (sorted by usage)
|
|
279
|
+
console.log(results.metadata.modelCounts); // { "openai:gpt-4o": 48, "openai:gpt-4o-mini": 2 } (total LLM calls per model)
|
|
278
280
|
|
|
279
281
|
// ── Per-item inspection ──────────────────────────────
|
|
280
282
|
for (const item of results.items) {
|
|
@@ -285,6 +287,11 @@ for (const item of results.items) {
|
|
|
285
287
|
console.log(item.cost); // workflow LLM cost
|
|
286
288
|
console.log(item.scorerCost); // total scorer cost for this item
|
|
287
289
|
|
|
290
|
+
// Execution metadata (models, tokens, agent calls — captured by AxlRuntime)
|
|
291
|
+
console.log(item.metadata?.models); // ["openai:gpt-4o"]
|
|
292
|
+
console.log(item.metadata?.tokens); // { input: 150, output: 320, reasoning: 0 }
|
|
293
|
+
console.log(item.metadata?.agentCalls); // 1
|
|
294
|
+
|
|
288
295
|
// Quick score access
|
|
289
296
|
console.log(item.scores['quality']); // 0.85 or null
|
|
290
297
|
|
|
@@ -310,16 +317,16 @@ Compare two runs to detect regressions and improvements. Runs must use the same
|
|
|
310
317
|
|
|
311
318
|
```bash
|
|
312
319
|
npx axl-eval compare ./results/v1.json ./results/v2.json
|
|
313
|
-
npx axl-eval compare v1.json v2.json --fail-on-regression # exit 1 if
|
|
320
|
+
npx axl-eval compare v1.json v2.json --fail-on-regression # exit 1 if significant regressions
|
|
314
321
|
```
|
|
315
322
|
|
|
316
323
|
```
|
|
317
324
|
Compare: baseline (3f8a2b1c) -> candidate (9d4e7f6a)
|
|
318
325
|
|
|
319
|
-
Scorer Baseline Candidate Delta Change
|
|
320
|
-
|
|
321
|
-
quality 0.750 0.850 +0.100 +13.3%
|
|
322
|
-
safety 0.900 0.900 +0.000 +0.0%
|
|
326
|
+
Scorer Baseline Candidate Delta Change CI 95% Sig
|
|
327
|
+
────────────────────────────────────────────────────────────────────────
|
|
328
|
+
quality 0.750 0.850 +0.100 +13.3% [+0.0312, +0.1688] *
|
|
329
|
+
safety 0.900 0.900 +0.000 +0.0% [-0.0250, +0.0250]
|
|
323
330
|
|
|
324
331
|
Timing: baseline 2.10s -> candidate 4.30s (+104.8%)
|
|
325
332
|
Cost: baseline $0.45 -> candidate $0.31 (-31.1%)
|
|
@@ -338,11 +345,18 @@ const comparison = evalCompare(v1Results, v2Results);
|
|
|
338
345
|
console.log(comparison.scorers.quality.delta); // +0.1
|
|
339
346
|
console.log(comparison.scorers.quality.deltaPercent); // +13.3
|
|
340
347
|
|
|
348
|
+
// Statistical significance
|
|
349
|
+
console.log(comparison.scorers.quality.ci); // { lower: 0.0312, upper: 0.1688 }
|
|
350
|
+
console.log(comparison.scorers.quality.significant); // true
|
|
351
|
+
console.log(comparison.scorers.quality.pRegression); // 0.02 (2% chance of regression)
|
|
352
|
+
console.log(comparison.scorers.quality.pImprovement); // 0.98 (98% chance of improvement)
|
|
353
|
+
console.log(comparison.scorers.quality.n); // 50 (paired sample count)
|
|
354
|
+
|
|
341
355
|
// Timing and cost tradeoffs
|
|
342
356
|
console.log(comparison.timing?.deltaPercent); // +104.8 (slower)
|
|
343
357
|
console.log(comparison.cost?.deltaPercent); // -31.1 (cheaper)
|
|
344
358
|
|
|
345
|
-
// Per-item regressions/improvements
|
|
359
|
+
// Per-item regressions/improvements
|
|
346
360
|
for (const r of comparison.regressions) {
|
|
347
361
|
console.log(`Item ${r.itemIndex}: ${r.scorer} dropped ${r.baselineScore} → ${r.candidateScore}`);
|
|
348
362
|
}
|
|
@@ -350,6 +364,53 @@ for (const r of comparison.regressions) {
|
|
|
350
364
|
console.log(comparison.summary); // human-readable one-liner
|
|
351
365
|
```
|
|
352
366
|
|
|
367
|
+
`evalCompare()` also accepts arrays for multi-run comparison — see [Multi-Run](#multi-run).
|
|
368
|
+
|
|
369
|
+
### Configurable Thresholds
|
|
370
|
+
|
|
371
|
+
By default, thresholds auto-calibrate from scorer type metadata embedded in eval results: **0** for deterministic scorers, **0.05** for LLM scorers (which have natural variance). Results without `scorerTypes` metadata fall back to **0.1**.
|
|
372
|
+
|
|
373
|
+
Override with `--threshold` on the CLI:
|
|
374
|
+
|
|
375
|
+
```bash
|
|
376
|
+
# Global threshold for all scorers
|
|
377
|
+
npx axl-eval compare v1.json v2.json --threshold 0.05
|
|
378
|
+
|
|
379
|
+
# Per-scorer thresholds
|
|
380
|
+
npx axl-eval compare v1.json v2.json --threshold accuracy=0,tone=0.1
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
Programmatically via `EvalCompareOptions`:
|
|
384
|
+
|
|
385
|
+
```typescript
|
|
386
|
+
import { evalCompare } from '@axlsdk/eval';
|
|
387
|
+
import type { EvalCompareOptions } from '@axlsdk/eval';
|
|
388
|
+
|
|
389
|
+
// Global threshold
|
|
390
|
+
evalCompare(baseline, candidate, { thresholds: 0.05 });
|
|
391
|
+
|
|
392
|
+
// Per-scorer map
|
|
393
|
+
evalCompare(baseline, candidate, { thresholds: { accuracy: 0, tone: 0.1 } });
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
### Statistical Significance
|
|
397
|
+
|
|
398
|
+
`evalCompare()` computes a 95% bootstrap confidence interval on paired per-item score differences. A scorer change is marked `significant` when:
|
|
399
|
+
|
|
400
|
+
1. The CI excludes zero (the effect is unlikely due to chance), **and**
|
|
401
|
+
2. The absolute delta exceeds the threshold (the effect is practically meaningful).
|
|
402
|
+
|
|
403
|
+
`--fail-on-regression` uses significance when available — it only exits with code 1 if at least one scorer has a significant negative delta. Without enough paired data for CI (fewer than 2 items), it falls back to threshold-only comparison.
|
|
404
|
+
|
|
405
|
+
The underlying `pairedBootstrapCI()` function is exported for direct use:
|
|
406
|
+
|
|
407
|
+
```typescript
|
|
408
|
+
import { pairedBootstrapCI } from '@axlsdk/eval';
|
|
409
|
+
|
|
410
|
+
const ci = pairedBootstrapCI(differences, { nResamples: 1000, alpha: 0.05, seed: 42 });
|
|
411
|
+
console.log(ci); // { lower: -0.02, upper: 0.15, mean: 0.065, pRegression: 0.12, pImprovement: 0.88 }
|
|
412
|
+
```
|
|
413
|
+
|
|
353
414
|
## Eval Files in Detail
|
|
354
415
|
|
|
355
416
|
### Execution function
|
|
@@ -436,6 +497,109 @@ const ctx = runtime.createContext({
|
|
|
436
497
|
});
|
|
437
498
|
```
|
|
438
499
|
|
|
500
|
+
## Rescore Mode
|
|
501
|
+
|
|
502
|
+
Re-run scorers on saved outputs without re-executing the workflow. Useful when iterating on scorer logic — avoids burning LLM cost on generation.
|
|
503
|
+
|
|
504
|
+
```bash
|
|
505
|
+
npx axl-eval rescore ./results/v1.json ./evals/qa.eval.ts
|
|
506
|
+
npx axl-eval rescore ./results/v1.json ./evals/qa.eval.ts --output ./results/v1-rescored.json
|
|
507
|
+
```
|
|
508
|
+
|
|
509
|
+
The rescored result gets a new `id` and has `metadata.rescored: true` and `metadata.originalId` pointing to the source run. `runGroupId` and `runIndex` are stripped from inherited metadata (rescored results are independent evaluations). Only scorer cost is tracked (workflow cost is zero).
|
|
510
|
+
|
|
511
|
+
Programmatically:
|
|
512
|
+
|
|
513
|
+
```typescript
|
|
514
|
+
import { rescore } from '@axlsdk/eval';
|
|
515
|
+
|
|
516
|
+
const rescored = await rescore(originalResult, [updatedScorer, newScorer], runtime, {
|
|
517
|
+
concurrency: 10,
|
|
518
|
+
});
|
|
519
|
+
|
|
520
|
+
console.log(rescored.metadata.rescored); // true
|
|
521
|
+
console.log(rescored.metadata.originalId); // original result ID
|
|
522
|
+
console.log(rescored.totalCost); // scorer cost only
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
## Multi-Run
|
|
526
|
+
|
|
527
|
+
Run the same eval multiple times to measure variance across runs. The CLI aggregates per-scorer means into mean ± std:
|
|
528
|
+
|
|
529
|
+
```bash
|
|
530
|
+
npx axl-eval ./evals/qa.eval.ts --runs 5
|
|
531
|
+
npx axl-eval ./evals/qa.eval.ts --runs 5 --output ./results/qa-5runs.json
|
|
532
|
+
```
|
|
533
|
+
|
|
534
|
+
```
|
|
535
|
+
Eval: qa-eval x qa-basics — 5 runs
|
|
536
|
+
Scorer Mean ± Std Min Max
|
|
537
|
+
──────────────────────────────────────────────
|
|
538
|
+
not-empty 1.000 ± 0.000 1.000 1.000
|
|
539
|
+
relevance 0.870 ± 0.024 0.840 0.900
|
|
540
|
+
|
|
541
|
+
Total Cost: $0.05 | Total Duration: 16.2s
|
|
542
|
+
```
|
|
543
|
+
|
|
544
|
+
The output JSON contains all individual run results (as an array). Each run has `metadata.runGroupId` and `metadata.runIndex`.
|
|
545
|
+
|
|
546
|
+
Programmatically, use `aggregateRuns()`:
|
|
547
|
+
|
|
548
|
+
```typescript
|
|
549
|
+
import { aggregateRuns } from '@axlsdk/eval';
|
|
550
|
+
import type { MultiRunSummary } from '@axlsdk/eval';
|
|
551
|
+
|
|
552
|
+
const summary: MultiRunSummary = aggregateRuns(runs);
|
|
553
|
+
console.log(summary.scorers.relevance.mean); // 0.87
|
|
554
|
+
console.log(summary.scorers.relevance.std); // 0.024
|
|
555
|
+
console.log(summary.runCount); // 5
|
|
556
|
+
```
|
|
557
|
+
|
|
558
|
+
### Multi-run comparison
|
|
559
|
+
|
|
560
|
+
`evalCompare()` accepts arrays of `EvalResult` for both baseline and candidate, pooling paired differences across runs for more robust CI estimates:
|
|
561
|
+
|
|
562
|
+
```typescript
|
|
563
|
+
import { evalCompare } from '@axlsdk/eval';
|
|
564
|
+
|
|
565
|
+
const comparison = evalCompare(baselineRuns, candidateRuns);
|
|
566
|
+
// CI is computed from all paired (baseline[r].items[i], candidate[r].items[i]) differences
|
|
567
|
+
```
|
|
568
|
+
|
|
569
|
+
## API Reference
|
|
570
|
+
|
|
571
|
+
### Functions
|
|
572
|
+
|
|
573
|
+
| Function | Description |
|
|
574
|
+
|----------|-------------|
|
|
575
|
+
| `dataset(config)` | Create a dataset from inline items or a JSON file |
|
|
576
|
+
| `scorer(config)` | Create a deterministic scorer |
|
|
577
|
+
| `llmScorer(config)` | Create an LLM-as-judge scorer |
|
|
578
|
+
| `defineEval(config)` | Wrap an eval config for CLI discovery |
|
|
579
|
+
| `runEval(config, executeFn, runtime)` | Run an eval programmatically |
|
|
580
|
+
| `evalCompare(baseline, candidate, options?)` | Compare eval results with bootstrap CI |
|
|
581
|
+
| `rescore(result, scorers, runtime, options?)` | Re-run scorers on saved outputs |
|
|
582
|
+
| `aggregateRuns(runs)` | Aggregate multiple runs into mean ± std |
|
|
583
|
+
| `pairedBootstrapCI(differences, options?)` | Compute bootstrap confidence interval |
|
|
584
|
+
| `normalizeScorerResult(value)` | Convert `number \| ScorerResult` to `ScorerResult` |
|
|
585
|
+
|
|
586
|
+
### Types
|
|
587
|
+
|
|
588
|
+
| Type | Description |
|
|
589
|
+
|------|-------------|
|
|
590
|
+
| `EvalConfig` | Eval definition (workflow, dataset, scorers, concurrency, budget) |
|
|
591
|
+
| `EvalResult` | Full eval output (items, summary, cost, duration) |
|
|
592
|
+
| `EvalItem` | Per-item result (input, output, scores, scoreDetails, metadata) |
|
|
593
|
+
| `EvalSummary` | Aggregate statistics (count, failures, scorer stats, timing) |
|
|
594
|
+
| `EvalComparison` | Comparison output (scorer deltas, CI, pRegression/pImprovement, n, regressions, improvements) |
|
|
595
|
+
| `EvalCompareOptions` | Options for `evalCompare()` (`thresholds`) |
|
|
596
|
+
| `EvalRegression` / `EvalImprovement` | Per-item change record (itemIndex, scorer, scores, delta) |
|
|
597
|
+
| `ScorerDetail` | Per-scorer detail (score, metadata, duration, cost) |
|
|
598
|
+
| `ScorerResult` | Scorer return type (`{ score, metadata?, cost? }`) |
|
|
599
|
+
| `RescoreOptions` | Options for `rescore()` (`concurrency`) |
|
|
600
|
+
| `MultiRunSummary` | Aggregated multi-run output (per-scorer mean/std/min/max) |
|
|
601
|
+
| `BootstrapCIResult` | CI result (`{ lower, upper, mean, pRegression, pImprovement }`) |
|
|
602
|
+
|
|
439
603
|
## License
|
|
440
604
|
|
|
441
605
|
[Apache 2.0](../../LICENSE)
|