@axlsdk/eval 0.17.9 → 0.18.1

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.
@@ -64,10 +64,54 @@ function xorshift32(seed) {
64
64
  };
65
65
  }
66
66
 
67
- // src/compare.ts
67
+ // src/utils.ts
68
+ function computeStats(scores) {
69
+ if (scores.length === 0) return { mean: 0, min: 0, max: 0, p50: 0, p95: 0 };
70
+ const sorted = [...scores].sort((a, b) => a - b);
71
+ const mean = sorted.reduce((a, b) => a + b, 0) / sorted.length;
72
+ const min = sorted[0];
73
+ const max = sorted[sorted.length - 1];
74
+ const p50 = sorted[Math.floor(sorted.length * 0.5)];
75
+ const p95 = sorted[Math.floor(sorted.length * 0.95)];
76
+ return { mean: round2(mean), min: round2(min), max: round2(max), p50: round2(p50), p95: round2(p95) };
77
+ }
68
78
  function round2(n) {
69
79
  return Math.round(n * 1e3) / 1e3;
70
80
  }
81
+ function scorerCounts(items, name) {
82
+ let scored = 0;
83
+ let failed = 0;
84
+ let skipped = 0;
85
+ for (const i of items) {
86
+ if (i.error) continue;
87
+ if (i.scores[name] != null) scored++;
88
+ else if (i.scoreDetails?.[name]?.skipped === true) skipped++;
89
+ else if (i.scoreDetails?.[name]?.duration != null) failed++;
90
+ }
91
+ return { scored, failed, skipped };
92
+ }
93
+ function evaluateScorerTolerance(scored, failed, type, limit) {
94
+ const attempted = scored + failed;
95
+ const rate = attempted === 0 ? 0 : failed / attempted;
96
+ const exceeds = attempted > 0 && (type === "deterministic" ? failed > 0 : rate > limit);
97
+ return { attempted, rate, exceeds, zeroSample: attempted === 0 };
98
+ }
99
+ async function mapWithConcurrency(items, concurrency, task) {
100
+ const results = new Array(items.length);
101
+ const requested = Number.isFinite(concurrency) ? Math.floor(concurrency) : 1;
102
+ const workerCount = items.length === 0 ? 0 : Math.min(Math.max(1, requested), items.length);
103
+ let next = 0;
104
+ async function runNext() {
105
+ while (next < items.length) {
106
+ const i = next++;
107
+ results[i] = await task(items[i], i);
108
+ }
109
+ }
110
+ await Promise.all(Array.from({ length: workerCount }, () => runNext()));
111
+ return results;
112
+ }
113
+
114
+ // src/compare.ts
71
115
  var DEFAULT_LLM_THRESHOLD = 0.05;
72
116
  var DEFAULT_DETERMINISTIC_THRESHOLD = 0;
73
117
  var LEGACY_THRESHOLD = 0.1;
@@ -141,19 +185,43 @@ function evalCompare(baseline, candidate, options) {
141
185
  const delta = round2(deltaRaw);
142
186
  const deltaPercent = bMeanRaw > 0 ? round2(deltaRaw / bMeanRaw * 100) : 0;
143
187
  const threshold = resolveThreshold(name, options, baselineRef.metadata);
188
+ let baselineScored = 0;
189
+ let baselineFailed = 0;
190
+ let baselineSkipped = 0;
191
+ for (const run of baselineRuns) {
192
+ const c = scorerCounts(run.items, name);
193
+ baselineScored += c.scored;
194
+ baselineFailed += c.failed;
195
+ baselineSkipped += c.skipped;
196
+ }
197
+ let candidateScored = 0;
198
+ let candidateFailed = 0;
199
+ let candidateSkipped = 0;
200
+ for (const run of candidateRuns) {
201
+ const c = scorerCounts(run.items, name);
202
+ candidateScored += c.scored;
203
+ candidateFailed += c.failed;
204
+ candidateSkipped += c.skipped;
205
+ }
144
206
  const entry = {
145
207
  baselineMean: bMean,
146
208
  candidateMean: cMean,
147
209
  delta,
148
- deltaPercent
210
+ deltaPercent,
211
+ baselineScored,
212
+ baselineFailed,
213
+ candidateScored,
214
+ candidateFailed,
215
+ baselineSkipped,
216
+ candidateSkipped
149
217
  };
150
218
  const diffs = pairedDiffs[name];
219
+ entry.n = diffs.length;
151
220
  if (diffs.length >= 2) {
152
221
  const ci = pairedBootstrapCI(diffs);
153
222
  entry.ci = { lower: ci.lower, upper: ci.upper };
154
223
  entry.pRegression = ci.pRegression;
155
224
  entry.pImprovement = ci.pImprovement;
156
- entry.n = diffs.length;
157
225
  const ciExcludesZero = ci.lower > 0 || ci.upper < 0;
158
226
  entry.significant = ciExcludesZero && Math.abs(ci.mean) >= threshold;
159
227
  }
@@ -281,33 +349,112 @@ function detectPartial(runs) {
281
349
  if (runs.length >= attempted) return void 0;
282
350
  return { completed: runs.length, attempted };
283
351
  }
352
+ function evaluateScorerErrorRateGate(comparison, maxScorerErrorRate) {
353
+ const scorerTypes = comparison.baseline.metadata?.scorerTypes ?? {};
354
+ for (const name of Object.keys(comparison.scorers)) {
355
+ const s = comparison.scorers[name];
356
+ const type = scorerTypes[name] === "deterministic" ? "deterministic" : "llm";
357
+ const limit = type === "deterministic" ? 0 : maxScorerErrorRate;
358
+ for (const side of ["baseline", "candidate"]) {
359
+ const scored = (side === "baseline" ? s.baselineScored : s.candidateScored) ?? 0;
360
+ const failed = (side === "baseline" ? s.baselineFailed : s.candidateFailed) ?? 0;
361
+ const skipped = (side === "baseline" ? s.baselineSkipped : s.candidateSkipped) ?? 0;
362
+ const verdict = evaluateScorerTolerance(scored, failed, type, limit);
363
+ if (verdict.zeroSample) {
364
+ const cause = skipped > 0 ? `every one of its items was N/A (the \`applies\` predicate skipped all ${skipped})` : `its items errored or produced no score`;
365
+ return `scorer "${name}" has no scored items on ${side} (${cause}) \u2014 cannot certify a mean over an empty sample.`;
366
+ }
367
+ if (verdict.exceeds) {
368
+ const limitStr = type === "deterministic" ? "deterministic zero-tolerance" : `${(limit * 100).toFixed(1)}%`;
369
+ return `scorer "${name}" failed ${(verdict.rate * 100).toFixed(1)}% on ${side} (${failed}/${verdict.attempted}), over the ${limitStr} limit.`;
370
+ }
371
+ }
372
+ }
373
+ return null;
374
+ }
284
375
 
285
376
  // src/scorer.ts
286
377
  function normalizeScorerResult(result) {
287
378
  return typeof result === "number" ? { score: result } : result;
288
379
  }
380
+ function attachScorerErrorCost(err, cost) {
381
+ if (err && typeof err === "object" && typeof cost === "number" && Number.isFinite(cost) && cost >= 0) {
382
+ err.cost = cost;
383
+ }
384
+ }
385
+ function extractScorerErrorCost(err) {
386
+ const v = err && typeof err === "object" ? err.cost : void 0;
387
+ return typeof v === "number" && Number.isFinite(v) && v >= 0 ? v : void 0;
388
+ }
289
389
  function scorer(config) {
290
390
  return {
291
391
  name: config.name,
292
392
  description: config.description,
293
393
  isLlm: false,
294
- score: config.score
394
+ score: config.score,
395
+ applies: config.applies
295
396
  };
296
397
  }
297
398
 
298
- // src/utils.ts
299
- function computeStats(scores) {
300
- if (scores.length === 0) return { mean: 0, min: 0, max: 0, p50: 0, p95: 0 };
301
- const sorted = [...scores].sort((a, b) => a - b);
302
- const mean = sorted.reduce((a, b) => a + b, 0) / sorted.length;
303
- const min = sorted[0];
304
- const max = sorted[sorted.length - 1];
305
- const p50 = sorted[Math.floor(sorted.length * 0.5)];
306
- const p95 = sorted[Math.floor(sorted.length * 0.95)];
307
- return { mean: round3(mean), min: round3(min), max: round3(max), p50: round3(p50), p95: round3(p95) };
308
- }
309
- function round3(n) {
310
- return Math.round(n * 1e3) / 1e3;
399
+ // src/score-item.ts
400
+ async function scoreItem(item, scorers, scorerConcurrency, scorerContext, signal) {
401
+ const scoreDetails = item.scoreDetails ??= {};
402
+ for (const s of scorers) {
403
+ item.scores[s.name] = null;
404
+ scoreDetails[s.name] = { score: null };
405
+ }
406
+ let itemScorerCost = 0;
407
+ const scorerErrorsByName = {};
408
+ await mapWithConcurrency(scorers, scorerConcurrency, async (scorer2) => {
409
+ if (signal?.aborted) return;
410
+ const scorerStart = Date.now();
411
+ try {
412
+ if (scorer2.applies && !scorer2.applies(item.output, item.input, item.annotations)) {
413
+ item.scores[scorer2.name] = null;
414
+ scoreDetails[scorer2.name] = { score: null, skipped: true };
415
+ return;
416
+ }
417
+ const raw = await scorer2.score(item.output, item.input, item.annotations, scorerContext);
418
+ const scorerResult = normalizeScorerResult(raw);
419
+ if (scorerResult.cost != null) {
420
+ itemScorerCost += scorerResult.cost;
421
+ }
422
+ const scorerDuration = Date.now() - scorerStart;
423
+ if (!Number.isFinite(scorerResult.score) || scorerResult.score < 0 || scorerResult.score > 1) {
424
+ scorerErrorsByName[scorer2.name] = `Scorer "${scorer2.name}" returned out-of-range score ${scorerResult.score} for input ${JSON.stringify(item.input)}`;
425
+ item.scores[scorer2.name] = null;
426
+ scoreDetails[scorer2.name] = {
427
+ score: null,
428
+ metadata: scorerResult.metadata,
429
+ duration: scorerDuration,
430
+ cost: scorerResult.cost
431
+ };
432
+ } else {
433
+ item.scores[scorer2.name] = round2(scorerResult.score);
434
+ scoreDetails[scorer2.name] = {
435
+ score: round2(scorerResult.score),
436
+ metadata: scorerResult.metadata,
437
+ duration: scorerDuration,
438
+ cost: scorerResult.cost
439
+ };
440
+ }
441
+ } catch (err) {
442
+ if (err?.name === "AbortError") return;
443
+ const errCost = extractScorerErrorCost(err);
444
+ if (errCost != null) itemScorerCost += errCost;
445
+ scorerErrorsByName[scorer2.name] = `Scorer "${scorer2.name}" threw: ${err instanceof Error ? err.message : String(err)}`;
446
+ item.scores[scorer2.name] = null;
447
+ scoreDetails[scorer2.name] = {
448
+ score: null,
449
+ duration: Date.now() - scorerStart,
450
+ cost: errCost
451
+ };
452
+ }
453
+ });
454
+ const orderedErrors = scorers.map((s) => scorerErrorsByName[s.name]).filter((e) => e != null);
455
+ if (orderedErrors.length > 0) item.scorerErrors = orderedErrors;
456
+ item.scorerCost = itemScorerCost > 0 ? itemScorerCost : void 0;
457
+ return itemScorerCost;
311
458
  }
312
459
 
313
460
  // src/runner.ts
@@ -350,7 +497,9 @@ async function runEval(config, executeWorkflow, runtime, options) {
350
497
  const startTime = Date.now();
351
498
  const id = randomUUID();
352
499
  const items = await config.dataset.getItems();
500
+ const droppedAnnotationKeys = [...config.dataset.droppedAnnotationKeys ?? []];
353
501
  const concurrency = config.concurrency ?? 5;
502
+ const scorerConcurrency = config.scorerConcurrency ?? 5;
354
503
  const budgetLimit = config.budget ? parseCost(config.budget) : void 0;
355
504
  const scorerContext = {
356
505
  resolveProvider: (uri) => {
@@ -439,89 +588,53 @@ async function runEval(config, executeWorkflow, runtime, options) {
439
588
  if (budgetLimit != null && totalCost > budgetLimit) {
440
589
  budgetExceeded = true;
441
590
  }
442
- evalItem.scoreDetails = {};
443
- let itemScorerCost = 0;
444
- for (const scorer2 of config.scorers) {
445
- if (options?.signal?.aborted) break;
446
- const scorerStart = Date.now();
447
- try {
448
- const raw = await scorer2.score(
449
- evalItem.output,
450
- item.input,
451
- item.annotations,
452
- scorerContext
453
- );
454
- const scorerResult = normalizeScorerResult(raw);
455
- if (scorerResult.cost != null) {
456
- itemScorerCost += scorerResult.cost;
457
- totalCost += scorerResult.cost;
458
- }
459
- const scorerDuration = Date.now() - scorerStart;
460
- if (!Number.isFinite(scorerResult.score) || scorerResult.score < 0 || scorerResult.score > 1) {
461
- if (!evalItem.scorerErrors) evalItem.scorerErrors = [];
462
- evalItem.scorerErrors.push(
463
- `Scorer "${scorer2.name}" returned out-of-range score ${scorerResult.score} for input ${JSON.stringify(item.input)}`
464
- );
465
- evalItem.scores[scorer2.name] = null;
466
- evalItem.scoreDetails[scorer2.name] = {
467
- score: null,
468
- metadata: scorerResult.metadata,
469
- duration: scorerDuration,
470
- cost: scorerResult.cost
471
- };
472
- } else {
473
- evalItem.scores[scorer2.name] = round3(scorerResult.score);
474
- evalItem.scoreDetails[scorer2.name] = {
475
- score: round3(scorerResult.score),
476
- metadata: scorerResult.metadata,
477
- duration: scorerDuration,
478
- cost: scorerResult.cost
479
- };
480
- }
481
- } catch (err) {
482
- const errCost = typeof err?.cost === "number" ? err.cost : void 0;
483
- if (errCost != null) {
484
- itemScorerCost += errCost;
485
- totalCost += errCost;
486
- }
487
- if (!evalItem.scorerErrors) evalItem.scorerErrors = [];
488
- evalItem.scorerErrors.push(
489
- `Scorer "${scorer2.name}" threw: ${err instanceof Error ? err.message : String(err)}`
490
- );
491
- evalItem.scores[scorer2.name] = null;
492
- evalItem.scoreDetails[scorer2.name] = {
493
- score: null,
494
- duration: Date.now() - scorerStart,
495
- cost: errCost
496
- };
497
- }
498
- }
499
- evalItem.scorerCost = itemScorerCost > 0 ? itemScorerCost : void 0;
591
+ const itemScorerCost = await scoreItem(
592
+ evalItem,
593
+ config.scorers,
594
+ scorerConcurrency,
595
+ scorerContext,
596
+ options?.signal
597
+ );
598
+ totalCost += itemScorerCost;
500
599
  evalItems[itemIndex] = evalItem;
501
600
  options?.onProgress?.({ type: "item_done", itemIndex, totalItems: items.length });
502
601
  }
503
- let index = 0;
504
- async function runNext() {
505
- while (index < items.length) {
506
- const currentIndex = index++;
507
- await processItem(items[currentIndex], currentIndex);
508
- }
509
- }
510
- const workers = Array.from({ length: Math.min(concurrency, items.length) }, () => runNext());
511
- await Promise.all(workers);
602
+ await mapWithConcurrency(items, concurrency, (item, i) => processItem(item, i));
512
603
  const failures = evalItems.filter((i) => i.error).length;
513
604
  const scorerNames = config.scorers.map((s) => s.name);
514
605
  const scorerStats = {};
515
606
  for (const name of scorerNames) {
516
607
  const scores = evalItems.filter((i) => !i.error && i.scores[name] != null).map((i) => i.scores[name]);
517
- scorerStats[name] = computeStats(scores);
608
+ const { scored, failed, skipped } = scorerCounts(evalItems, name);
609
+ scorerStats[name] = { ...computeStats(scores), scored, failed, skipped };
518
610
  }
519
- const durations = evalItems.filter((i) => !i.error && i.duration != null).map((i) => i.duration);
520
- const timing = durations.length > 0 ? computeStats(durations) : void 0;
521
611
  const scorerTypes = {};
522
612
  for (const s of config.scorers) {
523
613
  scorerTypes[s.name] = s.isLlm ? "llm" : "deterministic";
524
614
  }
615
+ let degraded;
616
+ const rawLimit = config.failOnScorerErrorRate;
617
+ if (rawLimit != null) {
618
+ if (!Number.isFinite(rawLimit) || rawLimit < 0 || rawLimit > 1) {
619
+ console.warn(
620
+ `[axl-eval] Ignoring invalid failOnScorerErrorRate (${rawLimit}); expected a number in [0, 1].`
621
+ );
622
+ } else {
623
+ for (const name of scorerNames) {
624
+ const stats = scorerStats[name];
625
+ const scored = stats.scored ?? 0;
626
+ const failed = stats.failed ?? 0;
627
+ const type = scorerTypes[name] === "llm" ? "llm" : "deterministic";
628
+ const limit = type === "deterministic" ? 0 : rawLimit;
629
+ const verdict = evaluateScorerTolerance(scored, failed, type, limit);
630
+ if (verdict.exceeds) {
631
+ (degraded ??= []).push({ scorer: name, rate: verdict.rate, limit, type, scored, failed });
632
+ }
633
+ }
634
+ }
635
+ }
636
+ const durations = evalItems.filter((i) => !i.error && i.duration != null).map((i) => i.duration);
637
+ const timing = durations.length > 0 ? computeStats(durations) : void 0;
525
638
  const totalModelCalls = /* @__PURE__ */ new Map();
526
639
  for (const item of evalItems) {
527
640
  const itemCounts = item.metadata?.modelCallCounts;
@@ -580,13 +693,20 @@ async function runEval(config, executeWorkflow, runtime, options) {
580
693
  ...config.metadata,
581
694
  scorerTypes,
582
695
  ...modelsMeta,
583
- ...workflowsMeta
696
+ ...workflowsMeta,
697
+ ...droppedAnnotationKeys.length > 0 ? { droppedAnnotationKeys } : {}
584
698
  },
585
699
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
586
700
  totalCost,
587
701
  duration: Date.now() - startTime,
588
702
  items: evalItems,
589
- summary: { count: items.length, failures, scorers: scorerStats, timing }
703
+ summary: {
704
+ count: items.length,
705
+ failures,
706
+ scorers: scorerStats,
707
+ timing,
708
+ ...degraded ? { degraded } : {}
709
+ }
590
710
  };
591
711
  }
592
712
 
@@ -595,6 +715,7 @@ import { randomUUID as randomUUID2 } from "crypto";
595
715
  async function rescore(result, scorers, runtime, options) {
596
716
  const startTime = Date.now();
597
717
  const concurrency = options?.concurrency ?? 5;
718
+ const scorerConcurrency = options?.scorerConcurrency ?? 5;
598
719
  const scorerContext = {
599
720
  resolveProvider: (uri) => {
600
721
  if (typeof runtime.resolveProvider !== "function") {
@@ -638,77 +759,24 @@ async function rescore(result, scorers, runtime, options) {
638
759
  scores: {},
639
760
  scoreDetails: {}
640
761
  };
641
- let itemScorerCost = 0;
642
- for (const scorer2 of scorers) {
643
- const scorerStart = Date.now();
644
- try {
645
- const raw = await scorer2.score(item.output, item.input, item.annotations, scorerContext);
646
- const scorerResult = normalizeScorerResult(raw);
647
- if (scorerResult.cost != null) {
648
- itemScorerCost += scorerResult.cost;
649
- totalCost += scorerResult.cost;
650
- }
651
- const scorerDuration = Date.now() - scorerStart;
652
- if (!Number.isFinite(scorerResult.score) || scorerResult.score < 0 || scorerResult.score > 1) {
653
- if (!item.scorerErrors) item.scorerErrors = [];
654
- item.scorerErrors.push(
655
- `Scorer "${scorer2.name}" returned out-of-range score ${scorerResult.score} for input ${JSON.stringify(item.input)}`
656
- );
657
- item.scores[scorer2.name] = null;
658
- item.scoreDetails[scorer2.name] = {
659
- score: null,
660
- metadata: scorerResult.metadata,
661
- duration: scorerDuration,
662
- cost: scorerResult.cost
663
- };
664
- } else {
665
- item.scores[scorer2.name] = round3(scorerResult.score);
666
- item.scoreDetails[scorer2.name] = {
667
- score: round3(scorerResult.score),
668
- metadata: scorerResult.metadata,
669
- duration: scorerDuration,
670
- cost: scorerResult.cost
671
- };
672
- }
673
- } catch (err) {
674
- const errCost = typeof err?.cost === "number" ? err.cost : void 0;
675
- if (errCost != null) {
676
- itemScorerCost += errCost;
677
- totalCost += errCost;
678
- }
679
- if (!item.scorerErrors) item.scorerErrors = [];
680
- item.scorerErrors.push(
681
- `Scorer "${scorer2.name}" threw: ${err instanceof Error ? err.message : String(err)}`
682
- );
683
- item.scores[scorer2.name] = null;
684
- item.scoreDetails[scorer2.name] = {
685
- score: null,
686
- duration: Date.now() - scorerStart,
687
- cost: errCost
688
- };
689
- }
690
- }
691
- item.scorerCost = itemScorerCost > 0 ? itemScorerCost : void 0;
762
+ const itemScorerCost = await scoreItem(
763
+ item,
764
+ scorers,
765
+ scorerConcurrency,
766
+ scorerContext,
767
+ options?.signal
768
+ );
769
+ totalCost += itemScorerCost;
692
770
  rescored[itemIndex] = item;
693
771
  }
694
- let index = 0;
695
- async function runNext() {
696
- while (index < result.items.length) {
697
- const currentIndex = index++;
698
- await rescoreItem(result.items[currentIndex], currentIndex);
699
- }
700
- }
701
- const workers = Array.from(
702
- { length: Math.min(concurrency, result.items.length) },
703
- () => runNext()
704
- );
705
- await Promise.all(workers);
772
+ await mapWithConcurrency(result.items, concurrency, (item, i) => rescoreItem(item, i));
706
773
  const failures = rescored.filter((i) => i.error).length;
707
774
  const scorerNames = scorers.map((s) => s.name);
708
775
  const scorerStats = {};
709
776
  for (const name of scorerNames) {
710
777
  const scores = rescored.filter((i) => !i.error && i.scores[name] != null).map((i) => i.scores[name]);
711
- scorerStats[name] = computeStats(scores);
778
+ const { scored, failed, skipped } = scorerCounts(rescored, name);
779
+ scorerStats[name] = { ...computeStats(scores), scored, failed, skipped };
712
780
  }
713
781
  const scorerTypes = {};
714
782
  for (const s of scorers) {
@@ -718,7 +786,11 @@ async function rescore(result, scorers, runtime, options) {
718
786
  id: randomUUID2(),
719
787
  dataset: result.dataset,
720
788
  metadata: (() => {
721
- const { runGroupId: _, runIndex: __, ...rest } = result.metadata;
789
+ const rest = { ...result.metadata };
790
+ delete rest.runGroupId;
791
+ delete rest.runIndex;
792
+ delete rest.scorerFiltered;
793
+ delete rest.scorersRun;
722
794
  const merged = {
723
795
  ...rest,
724
796
  rescored: true,
@@ -771,15 +843,26 @@ function aggregateRuns(runs) {
771
843
  const scorerNames = Object.keys(runs[0].summary.scorers);
772
844
  const scorers = {};
773
845
  for (const name of scorerNames) {
774
- const means = runs.map((r) => r.summary.scorers[name]?.mean ?? 0);
846
+ const contributing = runs.filter((r) => {
847
+ const sc = r.summary.scorers[name]?.scored;
848
+ return sc == null || sc > 0;
849
+ });
850
+ const meanSource = contributing.length > 0 ? contributing : runs;
851
+ const means = meanSource.map((r) => r.summary.scorers[name]?.mean ?? 0);
775
852
  const meanOfMeans = means.reduce((a, b) => a + b, 0) / means.length;
776
853
  const minMean = Math.min(...means);
777
854
  const maxMean = Math.max(...means);
855
+ const scored = runs.reduce((sum, r) => sum + (r.summary.scorers[name]?.scored ?? 0), 0);
856
+ const failed = runs.reduce((sum, r) => sum + (r.summary.scorers[name]?.failed ?? 0), 0);
857
+ const skipped = runs.reduce((sum, r) => sum + (r.summary.scorers[name]?.skipped ?? 0), 0);
778
858
  scorers[name] = {
779
- mean: round3(meanOfMeans),
780
- std: round3(std(means, meanOfMeans)),
781
- min: round3(minMean),
782
- max: round3(maxMean)
859
+ mean: round2(meanOfMeans),
860
+ std: round2(std(means, meanOfMeans)),
861
+ min: round2(minMean),
862
+ max: round2(maxMean),
863
+ scored,
864
+ failed,
865
+ skipped
783
866
  };
784
867
  }
785
868
  let timing;
@@ -787,8 +870,8 @@ function aggregateRuns(runs) {
787
870
  if (timingMeans.length === runs.length && timingMeans.length > 0) {
788
871
  const meanTiming = timingMeans.reduce((a, b) => a + b, 0) / timingMeans.length;
789
872
  timing = {
790
- mean: round3(meanTiming),
791
- std: round3(std(timingMeans, meanTiming))
873
+ mean: round2(meanTiming),
874
+ std: round2(std(timingMeans, meanTiming))
792
875
  };
793
876
  }
794
877
  return {
@@ -796,8 +879,8 @@ function aggregateRuns(runs) {
796
879
  runCount: runs.length,
797
880
  workflows,
798
881
  dataset,
799
- totalCost: round3(totalCost),
800
- totalDuration: round3(totalDuration),
882
+ totalCost: round2(totalCost),
883
+ totalDuration: round2(totalDuration),
801
884
  scorers,
802
885
  timing
803
886
  };
@@ -805,11 +888,15 @@ function aggregateRuns(runs) {
805
888
 
806
889
  export {
807
890
  pairedBootstrapCI,
891
+ scorerCounts,
892
+ evaluateScorerTolerance,
808
893
  evalCompare,
894
+ evaluateScorerErrorRateGate,
809
895
  normalizeScorerResult,
896
+ attachScorerErrorCost,
810
897
  scorer,
811
898
  runEval,
812
899
  rescore,
813
900
  aggregateRuns
814
901
  };
815
- //# sourceMappingURL=chunk-NETD4AUB.js.map
902
+ //# sourceMappingURL=chunk-66EYSYQS.js.map