evalsense 0.2.1 → 0.3.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 +99 -82
- package/dist/{chunk-HDJID3GC.cjs → chunk-DFC6FRTG.cjs} +8 -26
- package/dist/chunk-DFC6FRTG.cjs.map +1 -0
- package/dist/chunk-DGUM43GV.js +10 -0
- package/dist/chunk-DGUM43GV.js.map +1 -0
- package/dist/chunk-JEQ2X3Z6.cjs +12 -0
- package/dist/chunk-JEQ2X3Z6.cjs.map +1 -0
- package/dist/{chunk-5P7LNNO6.js → chunk-JPVZL45G.js} +8 -26
- package/dist/chunk-JPVZL45G.js.map +1 -0
- package/dist/{chunk-Y23VHTD3.cjs → chunk-RZFLCWTW.cjs} +2 -2
- package/dist/chunk-RZFLCWTW.cjs.map +1 -0
- package/dist/{chunk-BRPM6AB6.js → chunk-Z3U6AUWX.js} +2 -2
- package/dist/chunk-Z3U6AUWX.js.map +1 -0
- package/dist/cli.cjs +39 -36
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +37 -34
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +300 -101
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +76 -6
- package/dist/index.d.ts +76 -6
- package/dist/index.js +222 -23
- package/dist/index.js.map +1 -1
- package/dist/metrics/index.cjs +257 -17
- package/dist/metrics/index.cjs.map +1 -1
- package/dist/metrics/index.d.cts +252 -1
- package/dist/metrics/index.d.ts +252 -1
- package/dist/metrics/index.js +240 -2
- package/dist/metrics/index.js.map +1 -1
- package/dist/metrics/opinionated/index.cjs +6 -5
- package/dist/metrics/opinionated/index.js +2 -1
- package/package.json +4 -3
- package/dist/chunk-5P7LNNO6.js.map +0 -1
- package/dist/chunk-BRPM6AB6.js.map +0 -1
- package/dist/chunk-HDJID3GC.cjs.map +0 -1
- package/dist/chunk-Y23VHTD3.cjs.map +0 -1
package/README.md
CHANGED
|
@@ -3,10 +3,12 @@
|
|
|
3
3
|
> JS-native LLM evaluation framework with Jest-like API and statistical assertions
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/evalsense)
|
|
6
|
-
[](https://opensource.org/licenses/Apache-2.0)
|
|
7
7
|
|
|
8
8
|
**evalsense** brings classical ML-style statistical evaluation to LLM systems in JavaScript. Instead of evaluating individual test cases, evalsense evaluates entire datasets and computes confusion matrices, precision/recall, F1 scores, and other statistical metrics.
|
|
9
9
|
|
|
10
|
+
> **New in v0.3.0:** Regression assertions (MAE, RMSE, R²) and flexible ID matching for custom identifier fields! [See migration guide](./docs/migration-v0.3.0.md).
|
|
11
|
+
> **New in v0.2.x:** Built-in adapters for OpenAI, Anthropic, and OpenRouter - no boilerplate needed!
|
|
10
12
|
> **New in v0.2.0:** LLM-powered metrics for hallucination, relevance, faithfulness, and toxicity detection. [See migration guide](./docs/migration-v0.2.md).
|
|
11
13
|
|
|
12
14
|
## Why evalsense?
|
|
@@ -57,7 +59,7 @@ function classifySentiment(record) {
|
|
|
57
59
|
|
|
58
60
|
return {
|
|
59
61
|
id: record.id,
|
|
60
|
-
sentiment: hasPositive && !hasNegative ? "positive" : "negative"
|
|
62
|
+
sentiment: hasPositive && !hasNegative ? "positive" : "negative",
|
|
61
63
|
};
|
|
62
64
|
}
|
|
63
65
|
|
|
@@ -109,14 +111,14 @@ describe("Spam classifier", () => {
|
|
|
109
111
|
|
|
110
112
|
const result = await runModel(dataset, (record) => ({
|
|
111
113
|
id: record.id,
|
|
112
|
-
isSpam: classifyEmail(record.text)
|
|
114
|
+
isSpam: classifyEmail(record.text),
|
|
113
115
|
}));
|
|
114
116
|
|
|
115
117
|
expectStats(result)
|
|
116
118
|
.field("isSpam")
|
|
117
119
|
.toHaveAccuracyAbove(0.9)
|
|
118
|
-
.toHavePrecisionAbove(true, 0.85)
|
|
119
|
-
.toHaveRecallAbove(true, 0.85)
|
|
120
|
+
.toHavePrecisionAbove(true, 0.85) // Precision for spam=true
|
|
121
|
+
.toHaveRecallAbove(true, 0.85) // Recall for spam=true
|
|
120
122
|
.toHaveConfusionMatrix();
|
|
121
123
|
});
|
|
122
124
|
});
|
|
@@ -134,13 +136,13 @@ describe("Hallucination detector", () => {
|
|
|
134
136
|
// Your model returns a continuous score
|
|
135
137
|
const result = await runModel(dataset, (record) => ({
|
|
136
138
|
id: record.id,
|
|
137
|
-
hallucinated: computeHallucinationScore(record.output)
|
|
139
|
+
hallucinated: computeHallucinationScore(record.output), // 0.0 to 1.0
|
|
138
140
|
}));
|
|
139
141
|
|
|
140
142
|
// Binarize the score at threshold 0.3
|
|
141
143
|
expectStats(result)
|
|
142
144
|
.field("hallucinated")
|
|
143
|
-
.binarize(0.3)
|
|
145
|
+
.binarize(0.3) // >= 0.3 means hallucinated
|
|
144
146
|
.toHaveRecallAbove(true, 0.7)
|
|
145
147
|
.toHavePrecisionAbove(true, 0.6)
|
|
146
148
|
.toHaveConfusionMatrix();
|
|
@@ -159,7 +161,7 @@ describe("Intent classifier", () => {
|
|
|
159
161
|
|
|
160
162
|
const result = await runModel(dataset, (record) => ({
|
|
161
163
|
id: record.id,
|
|
162
|
-
intent: classifyIntent(record.query)
|
|
164
|
+
intent: classifyIntent(record.query),
|
|
163
165
|
}));
|
|
164
166
|
|
|
165
167
|
expectStats(result)
|
|
@@ -191,12 +193,10 @@ describe("LLM classifier", () => {
|
|
|
191
193
|
const response = await callLLM(record.text);
|
|
192
194
|
return { id: record.id, category: response.category };
|
|
193
195
|
},
|
|
194
|
-
5
|
|
196
|
+
5 // concurrency limit
|
|
195
197
|
);
|
|
196
198
|
|
|
197
|
-
expectStats(result)
|
|
198
|
-
.field("category")
|
|
199
|
-
.toHaveAccuracyAbove(0.9);
|
|
199
|
+
expectStats(result).field("category").toHaveAccuracyAbove(0.9);
|
|
200
200
|
});
|
|
201
201
|
});
|
|
202
202
|
```
|
|
@@ -283,6 +283,7 @@ npx evalsense list tests/
|
|
|
283
283
|
### Core API
|
|
284
284
|
|
|
285
285
|
#### `describe(name, fn)`
|
|
286
|
+
|
|
286
287
|
Groups related evaluation tests (like Jest's describe).
|
|
287
288
|
|
|
288
289
|
```javascript
|
|
@@ -292,6 +293,7 @@ describe("My model", () => {
|
|
|
292
293
|
```
|
|
293
294
|
|
|
294
295
|
#### `evalTest(name, fn)` / `test(name, fn)` / `it(name, fn)`
|
|
296
|
+
|
|
295
297
|
Defines an evaluation test.
|
|
296
298
|
|
|
297
299
|
```javascript
|
|
@@ -303,6 +305,7 @@ evalTest("should have 90% accuracy", async () => {
|
|
|
303
305
|
### Dataset Functions
|
|
304
306
|
|
|
305
307
|
#### `loadDataset(path)`
|
|
308
|
+
|
|
306
309
|
Loads a dataset from a JSON file. Records must have an `id` or `_id` field.
|
|
307
310
|
|
|
308
311
|
```javascript
|
|
@@ -310,44 +313,45 @@ const dataset = loadDataset("./data.json");
|
|
|
310
313
|
```
|
|
311
314
|
|
|
312
315
|
#### `runModel(dataset, modelFn)`
|
|
316
|
+
|
|
313
317
|
Runs a model function on each record sequentially.
|
|
314
318
|
|
|
315
319
|
```javascript
|
|
316
320
|
const result = await runModel(dataset, (record) => ({
|
|
317
321
|
id: record.id,
|
|
318
|
-
prediction: classify(record.text)
|
|
322
|
+
prediction: classify(record.text),
|
|
319
323
|
}));
|
|
320
324
|
```
|
|
321
325
|
|
|
322
326
|
#### `runModelParallel(dataset, modelFn, concurrency)`
|
|
327
|
+
|
|
323
328
|
Runs a model function with parallel execution.
|
|
324
329
|
|
|
325
330
|
```javascript
|
|
326
|
-
const result = await runModelParallel(dataset, modelFn, 10);
|
|
331
|
+
const result = await runModelParallel(dataset, modelFn, 10); // concurrency=10
|
|
327
332
|
```
|
|
328
333
|
|
|
329
334
|
### Assertions
|
|
330
335
|
|
|
331
336
|
#### `expectStats(result)`
|
|
337
|
+
|
|
332
338
|
Creates a statistical assertion chain from model results.
|
|
333
339
|
|
|
334
340
|
```javascript
|
|
335
|
-
expectStats(result)
|
|
336
|
-
.field("prediction")
|
|
337
|
-
.toHaveAccuracyAbove(0.8);
|
|
341
|
+
expectStats(result).field("prediction").toHaveAccuracyAbove(0.8);
|
|
338
342
|
```
|
|
339
343
|
|
|
340
344
|
#### `expectStats(predictions, groundTruth)`
|
|
345
|
+
|
|
341
346
|
Two-argument form for judge validation. Aligns predictions with ground truth by `id` field.
|
|
342
347
|
|
|
343
348
|
```javascript
|
|
344
349
|
// Validate judge outputs against human labels
|
|
345
|
-
expectStats(judgeOutputs, humanLabels)
|
|
346
|
-
.field("label")
|
|
347
|
-
.toHaveAccuracyAbove(0.85);
|
|
350
|
+
expectStats(judgeOutputs, humanLabels).field("label").toHaveAccuracyAbove(0.85);
|
|
348
351
|
```
|
|
349
352
|
|
|
350
353
|
**When to use:**
|
|
354
|
+
|
|
351
355
|
- Validating LLM judges against human labels
|
|
352
356
|
- Evaluating metric quality
|
|
353
357
|
- Testing automated detection systems
|
|
@@ -355,19 +359,21 @@ expectStats(judgeOutputs, humanLabels)
|
|
|
355
359
|
### Field Selection
|
|
356
360
|
|
|
357
361
|
#### `.field(fieldName)`
|
|
362
|
+
|
|
358
363
|
Selects a field for evaluation.
|
|
359
364
|
|
|
360
365
|
```javascript
|
|
361
|
-
expectStats(result).field("sentiment")
|
|
366
|
+
expectStats(result).field("sentiment");
|
|
362
367
|
```
|
|
363
368
|
|
|
364
369
|
#### `.binarize(threshold)`
|
|
370
|
+
|
|
365
371
|
Converts continuous scores to binary (>=threshold is true).
|
|
366
372
|
|
|
367
373
|
```javascript
|
|
368
374
|
expectStats(result)
|
|
369
375
|
.field("score")
|
|
370
|
-
.binarize(0.5)
|
|
376
|
+
.binarize(0.5) // score >= 0.5 is true
|
|
371
377
|
.toHaveAccuracyAbove(0.8);
|
|
372
378
|
```
|
|
373
379
|
|
|
@@ -403,23 +409,20 @@ Distribution assertions validate output distributions **without requiring ground
|
|
|
403
409
|
|
|
404
410
|
```javascript
|
|
405
411
|
// Assert that at least 80% of confidence scores are above 0.7
|
|
406
|
-
expectStats(predictions)
|
|
407
|
-
.field("confidence")
|
|
408
|
-
.toHavePercentageAbove(0.7, 0.8);
|
|
412
|
+
expectStats(predictions).field("confidence").toHavePercentageAbove(0.7, 0.8);
|
|
409
413
|
|
|
410
414
|
// Assert that at least 90% of toxicity scores are below 0.3
|
|
411
|
-
expectStats(predictions)
|
|
412
|
-
.field("toxicity")
|
|
413
|
-
.toHavePercentageBelow(0.3, 0.9);
|
|
415
|
+
expectStats(predictions).field("toxicity").toHavePercentageBelow(0.3, 0.9);
|
|
414
416
|
|
|
415
417
|
// Chain multiple distribution assertions
|
|
416
418
|
expectStats(predictions)
|
|
417
419
|
.field("score")
|
|
418
|
-
.toHavePercentageAbove(0.5, 0.6)
|
|
420
|
+
.toHavePercentageAbove(0.5, 0.6) // At least 60% above 0.5
|
|
419
421
|
.toHavePercentageBelow(0.9, 0.8); // At least 80% below 0.9
|
|
420
422
|
```
|
|
421
423
|
|
|
422
424
|
**Use cases:**
|
|
425
|
+
|
|
423
426
|
- Monitor confidence score distributions
|
|
424
427
|
- Validate schema compliance rates
|
|
425
428
|
- Check output range constraints
|
|
@@ -436,35 +439,35 @@ Validate judge outputs against human-labeled ground truth using the **two-argume
|
|
|
436
439
|
const judgeOutputs = [
|
|
437
440
|
{ id: "1", hallucinated: true },
|
|
438
441
|
{ id: "2", hallucinated: false },
|
|
439
|
-
{ id: "3", hallucinated: true }
|
|
442
|
+
{ id: "3", hallucinated: true },
|
|
440
443
|
];
|
|
441
444
|
|
|
442
445
|
// Human labels (ground truth)
|
|
443
446
|
const humanLabels = [
|
|
444
447
|
{ id: "1", hallucinated: true },
|
|
445
448
|
{ id: "2", hallucinated: false },
|
|
446
|
-
{ id: "3", hallucinated: false }
|
|
449
|
+
{ id: "3", hallucinated: false },
|
|
447
450
|
];
|
|
448
451
|
|
|
449
452
|
// Validate judge performance
|
|
450
453
|
expectStats(judgeOutputs, humanLabels)
|
|
451
454
|
.field("hallucinated")
|
|
452
|
-
.toHaveRecallAbove(true, 0.9)
|
|
453
|
-
.toHavePrecisionAbove(true, 0.7)
|
|
455
|
+
.toHaveRecallAbove(true, 0.9) // Don't miss hallucinations
|
|
456
|
+
.toHavePrecisionAbove(true, 0.7) // Some false positives OK
|
|
454
457
|
.toHaveConfusionMatrix();
|
|
455
458
|
```
|
|
456
459
|
|
|
457
460
|
**Use cases:**
|
|
461
|
+
|
|
458
462
|
- Evaluate LLM-as-judge accuracy
|
|
459
463
|
- Validate heuristic metrics against human labels
|
|
460
464
|
- Test automated detection systems (refusal, policy compliance)
|
|
461
465
|
- Calibrate metric thresholds
|
|
462
466
|
|
|
463
467
|
**Two-argument expectStats:**
|
|
468
|
+
|
|
464
469
|
```javascript
|
|
465
|
-
expectStats(actual, expected)
|
|
466
|
-
.field("fieldName")
|
|
467
|
-
.toHaveAccuracyAbove(0.8);
|
|
470
|
+
expectStats(actual, expected).field("fieldName").toHaveAccuracyAbove(0.8);
|
|
468
471
|
```
|
|
469
472
|
|
|
470
473
|
The first argument is your predictions (judge outputs), the second is ground truth (human labels). Both must have matching `id` fields for alignment.
|
|
@@ -493,6 +496,7 @@ Datasets must be JSON arrays where each record has an `id` or `_id` field:
|
|
|
493
496
|
```
|
|
494
497
|
|
|
495
498
|
**Requirements:**
|
|
499
|
+
|
|
496
500
|
- Each record MUST have `id` or `_id` for alignment
|
|
497
501
|
- Ground truth fields (e.g., `label`, `sentiment`, `category`) are compared against model outputs
|
|
498
502
|
- Model functions must return predictions with matching `id`
|
|
@@ -522,6 +526,7 @@ project/
|
|
|
522
526
|
```
|
|
523
527
|
|
|
524
528
|
Run with:
|
|
529
|
+
|
|
525
530
|
```bash
|
|
526
531
|
npx evalsense run tests/
|
|
527
532
|
```
|
|
@@ -551,26 +556,25 @@ evalsense includes LLM-powered metrics for hallucination detection, relevance as
|
|
|
551
556
|
### Quick Setup
|
|
552
557
|
|
|
553
558
|
```javascript
|
|
554
|
-
import { setLLMClient } from "evalsense/metrics";
|
|
559
|
+
import { setLLMClient, createOpenAIAdapter } from "evalsense/metrics";
|
|
555
560
|
import { hallucination, relevance, faithfulness, toxicity } from "evalsense/metrics/opinionated";
|
|
556
561
|
|
|
557
562
|
// 1. Configure your LLM client (one-time setup)
|
|
558
|
-
setLLMClient(
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
});
|
|
563
|
+
setLLMClient(
|
|
564
|
+
createOpenAIAdapter(process.env.OPENAI_API_KEY, {
|
|
565
|
+
model: "gpt-4-turbo-preview",
|
|
566
|
+
temperature: 0,
|
|
567
|
+
})
|
|
568
|
+
);
|
|
565
569
|
|
|
566
570
|
// 2. Use metrics in evaluations
|
|
567
571
|
const results = await hallucination({
|
|
568
572
|
outputs: [{ id: "1", output: "Paris has 50 million people." }],
|
|
569
|
-
context: ["Paris has approximately 2.1 million residents."]
|
|
573
|
+
context: ["Paris has approximately 2.1 million residents."],
|
|
570
574
|
});
|
|
571
575
|
|
|
572
|
-
console.log(results[0].score);
|
|
573
|
-
console.log(results[0].reasoning);
|
|
576
|
+
console.log(results[0].score); // 0.9 (high hallucination)
|
|
577
|
+
console.log(results[0].reasoning); // "Output claims 50M, context says 2.1M"
|
|
574
578
|
```
|
|
575
579
|
|
|
576
580
|
### Available Metrics
|
|
@@ -589,62 +593,74 @@ Choose between accuracy and cost:
|
|
|
589
593
|
await hallucination({
|
|
590
594
|
outputs,
|
|
591
595
|
context,
|
|
592
|
-
evaluationMode: "per-row"
|
|
596
|
+
evaluationMode: "per-row", // default
|
|
593
597
|
});
|
|
594
598
|
|
|
595
599
|
// Batch: Lower cost, single API call
|
|
596
600
|
await hallucination({
|
|
597
601
|
outputs,
|
|
598
602
|
context,
|
|
599
|
-
evaluationMode: "batch"
|
|
603
|
+
evaluationMode: "batch",
|
|
600
604
|
});
|
|
601
605
|
```
|
|
602
606
|
|
|
603
|
-
### Provider
|
|
607
|
+
### Built-in Provider Adapters
|
|
608
|
+
|
|
609
|
+
evalsense includes ready-to-use adapters for popular LLM providers:
|
|
610
|
+
|
|
611
|
+
**OpenAI (GPT-4, GPT-3.5)**
|
|
604
612
|
|
|
605
|
-
**OpenAI:**
|
|
606
613
|
```javascript
|
|
607
|
-
import
|
|
614
|
+
import { createOpenAIAdapter } from "evalsense/metrics";
|
|
608
615
|
|
|
609
|
-
|
|
610
|
-
setLLMClient(
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
}
|
|
618
|
-
});
|
|
616
|
+
// npm install openai
|
|
617
|
+
setLLMClient(
|
|
618
|
+
createOpenAIAdapter(process.env.OPENAI_API_KEY, {
|
|
619
|
+
model: "gpt-4-turbo-preview", // or "gpt-3.5-turbo" for lower cost
|
|
620
|
+
temperature: 0,
|
|
621
|
+
maxTokens: 4096,
|
|
622
|
+
})
|
|
623
|
+
);
|
|
619
624
|
```
|
|
620
625
|
|
|
621
|
-
**Anthropic
|
|
626
|
+
**Anthropic (Claude)**
|
|
627
|
+
|
|
622
628
|
```javascript
|
|
623
|
-
import
|
|
629
|
+
import { createAnthropicAdapter } from "evalsense/metrics";
|
|
624
630
|
|
|
625
|
-
|
|
626
|
-
setLLMClient(
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
631
|
+
// npm install @anthropic-ai/sdk
|
|
632
|
+
setLLMClient(
|
|
633
|
+
createAnthropicAdapter(process.env.ANTHROPIC_API_KEY, {
|
|
634
|
+
model: "claude-3-5-sonnet-20241022", // or "claude-3-haiku-20240307" for speed
|
|
635
|
+
maxTokens: 4096,
|
|
636
|
+
})
|
|
637
|
+
);
|
|
638
|
+
```
|
|
639
|
+
|
|
640
|
+
**OpenRouter (100+ models from one API)**
|
|
641
|
+
|
|
642
|
+
```javascript
|
|
643
|
+
import { createOpenRouterAdapter } from "evalsense/metrics";
|
|
644
|
+
|
|
645
|
+
// No SDK needed - uses fetch
|
|
646
|
+
setLLMClient(
|
|
647
|
+
createOpenRouterAdapter(process.env.OPENROUTER_API_KEY, {
|
|
648
|
+
model: "anthropic/claude-3.5-sonnet", // or "openai/gpt-3.5-turbo", etc.
|
|
649
|
+
temperature: 0,
|
|
650
|
+
appName: "my-eval-system",
|
|
651
|
+
})
|
|
652
|
+
);
|
|
636
653
|
```
|
|
637
654
|
|
|
638
|
-
**
|
|
655
|
+
**Custom Adapter (for any provider)**
|
|
656
|
+
|
|
639
657
|
```javascript
|
|
640
658
|
setLLMClient({
|
|
641
659
|
async complete(prompt) {
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
return (await response.json()).response;
|
|
647
|
-
}
|
|
660
|
+
// Implement for your LLM provider
|
|
661
|
+
const response = await yourLLM.generate(prompt);
|
|
662
|
+
return response.text;
|
|
663
|
+
},
|
|
648
664
|
});
|
|
649
665
|
```
|
|
650
666
|
|
|
@@ -660,6 +676,7 @@ setLLMClient({
|
|
|
660
676
|
evalsense is built on the principle that **metrics are predictions, not facts**.
|
|
661
677
|
|
|
662
678
|
Instead of treating LLM-as-judge metrics (relevance, hallucination, etc.) as ground truth, evalsense:
|
|
679
|
+
|
|
663
680
|
- Treats them as **weak labels** from a model
|
|
664
681
|
- Validates them statistically against human references when available
|
|
665
682
|
- Computes confusion matrices to reveal bias and systematic errors
|
|
@@ -146,10 +146,7 @@ function getSupport(cm, label) {
|
|
|
146
146
|
}
|
|
147
147
|
function formatConfusionMatrix(cm) {
|
|
148
148
|
const maxLabelLen = Math.max(...cm.labels.map((l) => l.length), 8);
|
|
149
|
-
const colWidth = Math.max(
|
|
150
|
-
...cm.matrix.flat().map((n) => String(n).length),
|
|
151
|
-
maxLabelLen
|
|
152
|
-
);
|
|
149
|
+
const colWidth = Math.max(...cm.matrix.flat().map((n) => String(n).length), maxLabelLen);
|
|
153
150
|
const header = " ".repeat(maxLabelLen + 2) + cm.labels.map((l) => l.padStart(colWidth)).join(" ");
|
|
154
151
|
const rows = cm.labels.map((label, i) => {
|
|
155
152
|
const rowData = cm.matrix[i].map((n) => String(n).padStart(colWidth)).join(" ");
|
|
@@ -261,7 +258,7 @@ var ConsoleReporter = class {
|
|
|
261
258
|
*/
|
|
262
259
|
printHeader(fileCount) {
|
|
263
260
|
this.log("");
|
|
264
|
-
this.log(this.color("bold", `EvalSense v0.
|
|
261
|
+
this.log(this.color("bold", `EvalSense v0.3.0`));
|
|
265
262
|
this.log(this.color("dim", `Running ${fileCount} eval file(s)...`));
|
|
266
263
|
this.log("");
|
|
267
264
|
}
|
|
@@ -296,9 +293,7 @@ var ConsoleReporter = class {
|
|
|
296
293
|
for (const fm of test.fieldMetrics) {
|
|
297
294
|
this.printFieldMetrics(fm);
|
|
298
295
|
}
|
|
299
|
-
if (test.error && test.status === "
|
|
300
|
-
this.log(this.color("red", ` ${test.error.message}`));
|
|
301
|
-
} else if (test.error && test.status === "error") {
|
|
296
|
+
if (test.error && test.status === "error") {
|
|
302
297
|
this.log(this.color("red", ` Error: ${test.error.message}`));
|
|
303
298
|
}
|
|
304
299
|
for (const assertion of test.assertions) {
|
|
@@ -426,23 +421,10 @@ var ConsoleReporter = class {
|
|
|
426
421
|
console.log(message);
|
|
427
422
|
}
|
|
428
423
|
};
|
|
429
|
-
var DEFAULT_PATTERNS = [
|
|
430
|
-
|
|
431
|
-
"**/*.eval.ts",
|
|
432
|
-
"**/*.eval.mjs"
|
|
433
|
-
];
|
|
434
|
-
var DEFAULT_IGNORE = [
|
|
435
|
-
"**/node_modules/**",
|
|
436
|
-
"**/dist/**",
|
|
437
|
-
"**/build/**",
|
|
438
|
-
"**/.git/**"
|
|
439
|
-
];
|
|
424
|
+
var DEFAULT_PATTERNS = ["**/*.eval.js", "**/*.eval.ts", "**/*.eval.mjs"];
|
|
425
|
+
var DEFAULT_IGNORE = ["**/node_modules/**", "**/dist/**", "**/build/**", "**/.git/**"];
|
|
440
426
|
async function discoverEvalFiles(options = {}) {
|
|
441
|
-
const {
|
|
442
|
-
patterns = DEFAULT_PATTERNS,
|
|
443
|
-
ignore = DEFAULT_IGNORE,
|
|
444
|
-
cwd = process.cwd()
|
|
445
|
-
} = options;
|
|
427
|
+
const { patterns = DEFAULT_PATTERNS, ignore = DEFAULT_IGNORE, cwd = process.cwd() } = options;
|
|
446
428
|
const files = [];
|
|
447
429
|
for (const pattern of patterns) {
|
|
448
430
|
const matches = await glob.glob(pattern, {
|
|
@@ -775,5 +757,5 @@ exports.parseReport = parseReport;
|
|
|
775
757
|
exports.recordAssertion = recordAssertion;
|
|
776
758
|
exports.recordFieldMetrics = recordFieldMetrics;
|
|
777
759
|
exports.setCurrentSuite = setCurrentSuite;
|
|
778
|
-
//# sourceMappingURL=chunk-
|
|
779
|
-
//# sourceMappingURL=chunk-
|
|
760
|
+
//# sourceMappingURL=chunk-DFC6FRTG.cjs.map
|
|
761
|
+
//# sourceMappingURL=chunk-DFC6FRTG.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/errors.ts","../src/statistics/confusion-matrix.ts","../src/report/json-reporter.ts","../src/report/console-reporter.ts","../src/runner/discovery.ts","../src/core/types.ts","../src/core/context.ts","../src/runner/executor.ts"],"names":["stringify","writeFileSync","glob","path","resolve","existsSync","pathToFileURL"],"mappings":"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","file":"chunk-DFC6FRTG.cjs","sourcesContent":["/**\n * Custom error classes for EvalSense\n */\n\nexport class EvalSenseError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"EvalSenseError\";\n }\n}\n\nexport class AssertionError extends EvalSenseError {\n public readonly expected: unknown;\n public readonly actual: unknown;\n public readonly field?: string;\n\n constructor(message: string, expected?: unknown, actual?: unknown, field?: string) {\n super(message);\n this.name = \"AssertionError\";\n this.expected = expected;\n this.actual = actual;\n this.field = field;\n }\n}\n\nexport class DatasetError extends EvalSenseError {\n public readonly source?: string;\n\n constructor(message: string, source?: string) {\n super(message);\n this.name = \"DatasetError\";\n this.source = source;\n }\n}\n\nexport class IntegrityError extends EvalSenseError {\n public readonly missingIds?: string[];\n public readonly duplicateIds?: string[];\n\n constructor(message: string, missingIds?: string[], duplicateIds?: string[]) {\n super(message);\n this.name = \"IntegrityError\";\n this.missingIds = missingIds;\n this.duplicateIds = duplicateIds;\n }\n}\n\nexport class ConfigurationError extends EvalSenseError {\n constructor(message: string) {\n super(message);\n this.name = \"ConfigurationError\";\n }\n}\n\nexport class TestExecutionError extends EvalSenseError {\n public readonly testName: string;\n public readonly originalError?: Error;\n\n constructor(message: string, testName: string, originalError?: Error) {\n super(message);\n this.name = \"TestExecutionError\";\n this.testName = testName;\n this.originalError = originalError;\n }\n}\n","/**\n * Confusion matrix computation\n */\n\nimport type { ConfusionMatrix } from \"../core/types.js\";\n\n/**\n * Builds a confusion matrix from actual and predicted values\n *\n * @param actual - Actual/predicted values from the model\n * @param expected - Expected/ground truth values\n * @returns ConfusionMatrix with matrix, labels, and total\n *\n * @example\n * ```ts\n * const matrix = buildConfusionMatrix(\n * [\"positive\", \"negative\", \"positive\"],\n * [\"positive\", \"positive\", \"positive\"]\n * );\n * // matrix.matrix[i][j] = count of expected[i] predicted as actual[j]\n * ```\n */\nexport function buildConfusionMatrix(actual: unknown[], expected: unknown[]): ConfusionMatrix {\n if (actual.length !== expected.length) {\n throw new Error(\n `Array length mismatch: actual has ${actual.length} elements, expected has ${expected.length}`\n );\n }\n\n // Collect all unique labels\n const labelSet = new Set<string>();\n for (const val of actual) {\n if (val !== undefined && val !== null) {\n labelSet.add(String(val));\n }\n }\n for (const val of expected) {\n if (val !== undefined && val !== null) {\n labelSet.add(String(val));\n }\n }\n\n // Sort labels for deterministic ordering\n const labels = Array.from(labelSet).sort();\n const labelIndex = new Map<string, number>();\n labels.forEach((label, idx) => labelIndex.set(label, idx));\n\n // Initialize confusion matrix with zeros\n const matrix: number[][] = labels.map(() => labels.map(() => 0));\n\n // Fill the matrix\n // Row = expected (ground truth), Column = actual (predicted)\n for (let i = 0; i < actual.length; i++) {\n const actualVal = actual[i];\n const expectedVal = expected[i];\n\n if (actualVal === undefined || actualVal === null) continue;\n if (expectedVal === undefined || expectedVal === null) continue;\n\n const actualIdx = labelIndex.get(String(actualVal));\n const expectedIdx = labelIndex.get(String(expectedVal));\n\n if (actualIdx !== undefined && expectedIdx !== undefined) {\n matrix[expectedIdx]![actualIdx]!++;\n }\n }\n\n const total = actual.filter(\n (v, i) => v !== undefined && v !== null && expected[i] !== undefined && expected[i] !== null\n ).length;\n\n return { matrix, labels, total };\n}\n\n/**\n * Gets the count from a confusion matrix for a specific cell\n */\nexport function getCount(cm: ConfusionMatrix, expectedLabel: string, actualLabel: string): number {\n const expectedIdx = cm.labels.indexOf(expectedLabel);\n const actualIdx = cm.labels.indexOf(actualLabel);\n\n if (expectedIdx === -1 || actualIdx === -1) {\n return 0;\n }\n\n return cm.matrix[expectedIdx]?.[actualIdx] ?? 0;\n}\n\n/**\n * Gets true positives for a class\n */\nexport function getTruePositives(cm: ConfusionMatrix, label: string): number {\n return getCount(cm, label, label);\n}\n\n/**\n * Gets false positives for a class (predicted as class but wasn't)\n */\nexport function getFalsePositives(cm: ConfusionMatrix, label: string): number {\n const labelIdx = cm.labels.indexOf(label);\n if (labelIdx === -1) return 0;\n\n let fp = 0;\n for (let i = 0; i < cm.labels.length; i++) {\n if (i !== labelIdx) {\n fp += cm.matrix[i]?.[labelIdx] ?? 0;\n }\n }\n return fp;\n}\n\n/**\n * Gets false negatives for a class (was class but predicted as something else)\n */\nexport function getFalseNegatives(cm: ConfusionMatrix, label: string): number {\n const labelIdx = cm.labels.indexOf(label);\n if (labelIdx === -1) return 0;\n\n let fn = 0;\n for (let j = 0; j < cm.labels.length; j++) {\n if (j !== labelIdx) {\n fn += cm.matrix[labelIdx]?.[j] ?? 0;\n }\n }\n return fn;\n}\n\n/**\n * Gets true negatives for a class\n */\nexport function getTrueNegatives(cm: ConfusionMatrix, label: string): number {\n const labelIdx = cm.labels.indexOf(label);\n if (labelIdx === -1) return 0;\n\n let tn = 0;\n for (let i = 0; i < cm.labels.length; i++) {\n for (let j = 0; j < cm.labels.length; j++) {\n if (i !== labelIdx && j !== labelIdx) {\n tn += cm.matrix[i]?.[j] ?? 0;\n }\n }\n }\n return tn;\n}\n\n/**\n * Gets support (total instances) for a class in ground truth\n */\nexport function getSupport(cm: ConfusionMatrix, label: string): number {\n const labelIdx = cm.labels.indexOf(label);\n if (labelIdx === -1) return 0;\n\n let support = 0;\n for (let j = 0; j < cm.labels.length; j++) {\n support += cm.matrix[labelIdx]?.[j] ?? 0;\n }\n return support;\n}\n\n/**\n * Formats a confusion matrix as a string table\n */\nexport function formatConfusionMatrix(cm: ConfusionMatrix): string {\n const maxLabelLen = Math.max(...cm.labels.map((l) => l.length), 8);\n const colWidth = Math.max(...cm.matrix.flat().map((n) => String(n).length), maxLabelLen);\n\n const header = \" \".repeat(maxLabelLen + 2) + cm.labels.map((l) => l.padStart(colWidth)).join(\" \");\n\n const rows = cm.labels.map((label, i) => {\n const rowData = cm.matrix[i]!.map((n) => String(n).padStart(colWidth)).join(\" \");\n return label.padEnd(maxLabelLen) + \" \" + rowData;\n });\n\n return [header, ...rows].join(\"\\n\");\n}\n","/**\n * JSON Reporter - deterministic JSON output\n */\n\nimport { writeFileSync } from \"node:fs\";\nimport stringify from \"fast-json-stable-stringify\";\nimport type { EvalReport } from \"../core/types.js\";\n\n/**\n * JSON Reporter for machine-readable output\n */\nexport class JsonReporter {\n /**\n * Formats a report as deterministic JSON\n */\n format(report: EvalReport): string {\n // Create a serializable version of the report\n const serializable = this.toSerializable(report);\n return stringify(serializable) ?? \"{}\";\n }\n\n /**\n * Writes report to a file\n */\n writeToFile(report: EvalReport, path: string): void {\n const json = this.format(report);\n writeFileSync(path, json, \"utf-8\");\n }\n\n /**\n * Converts report to a JSON-serializable format\n */\n private toSerializable(report: EvalReport): Record<string, unknown> {\n return {\n version: report.version,\n timestamp: report.timestamp,\n summary: report.summary,\n suites: report.suites.map((suite) => ({\n name: suite.name,\n passed: suite.passed,\n failed: suite.failed,\n errors: suite.errors,\n skipped: suite.skipped,\n duration: suite.duration,\n tests: suite.tests.map((test) => ({\n name: test.name,\n status: test.status,\n duration: test.duration,\n error: test.error\n ? {\n name: test.error.name,\n message: test.error.message,\n }\n : undefined,\n assertions: test.assertions.map((a) => ({\n type: a.type,\n passed: a.passed,\n message: a.message,\n expected: a.expected,\n actual: a.actual,\n field: a.field,\n class: a.class,\n })),\n fieldMetrics: test.fieldMetrics.map((fm) => ({\n field: fm.field,\n binarized: fm.binarized,\n binarizeThreshold: fm.binarizeThreshold,\n metrics: {\n accuracy: fm.metrics.accuracy,\n perClass: fm.metrics.perClass,\n macroAvg: fm.metrics.macroAvg,\n weightedAvg: fm.metrics.weightedAvg,\n confusionMatrix: {\n labels: fm.metrics.confusionMatrix.labels,\n matrix: fm.metrics.confusionMatrix.matrix,\n total: fm.metrics.confusionMatrix.total,\n },\n },\n })),\n })),\n })),\n integrity: report.integrity,\n };\n }\n}\n\n/**\n * Parses a JSON report back into an EvalReport\n */\nexport function parseReport(json: string): EvalReport {\n const data = JSON.parse(json) as EvalReport;\n return data;\n}\n","/**\n * Console Reporter - human-readable output\n */\n\nimport type { EvalReport, TestResult, FieldMetricResult } from \"../core/types.js\";\nimport { formatConfusionMatrix } from \"../statistics/confusion-matrix.js\";\n\n/**\n * ANSI color codes\n */\nconst colors = {\n reset: \"\\x1b[0m\",\n bold: \"\\x1b[1m\",\n dim: \"\\x1b[2m\",\n red: \"\\x1b[31m\",\n green: \"\\x1b[32m\",\n yellow: \"\\x1b[33m\",\n blue: \"\\x1b[34m\",\n cyan: \"\\x1b[36m\",\n gray: \"\\x1b[90m\",\n};\n\n/**\n * Status symbols\n */\nconst symbols = {\n pass: \"\\u2713\", // ✓\n fail: \"\\u2717\", // ✗\n error: \"!\",\n skip: \"-\",\n};\n\n/**\n * Console reporter for human-readable output\n */\nexport class ConsoleReporter {\n private useColors: boolean;\n\n constructor(useColors = true) {\n this.useColors = useColors && process.stdout.isTTY !== false;\n }\n\n /**\n * Prints the run header\n */\n printHeader(fileCount: number): void {\n this.log(\"\");\n this.log(this.color(\"bold\", `EvalSense v0.3.0`));\n this.log(this.color(\"dim\", `Running ${fileCount} eval file(s)...`));\n this.log(\"\");\n }\n\n /**\n * Prints the full report\n */\n printReport(report: EvalReport): void {\n // Print each suite\n for (const suite of report.suites) {\n this.printSuite(suite.name, suite.tests);\n }\n\n // Print summary\n this.printSummary(report);\n }\n\n /**\n * Prints a suite's results\n */\n private printSuite(name: string, tests: TestResult[]): void {\n this.log(this.color(\"bold\", ` ${name}`));\n this.log(\"\");\n\n for (const test of tests) {\n this.printTest(test);\n }\n\n this.log(\"\");\n }\n\n /**\n * Prints a single test result\n */\n private printTest(test: TestResult): void {\n const symbol = this.getStatusSymbol(test.status);\n const statusColor = this.getStatusColor(test.status);\n const duration = this.color(\"dim\", `(${test.duration}ms)`);\n\n this.log(` ${this.color(statusColor, symbol)} ${test.name} ${duration}`);\n\n // Print field metrics\n for (const fm of test.fieldMetrics) {\n this.printFieldMetrics(fm);\n }\n\n // Print error only for execution errors (not assertion failures)\n // Assertion failures are printed from test.assertions below\n if (test.error && test.status === \"error\") {\n this.log(this.color(\"red\", ` Error: ${test.error.message}`));\n }\n\n // Print failed assertions\n for (const assertion of test.assertions) {\n if (!assertion.passed) {\n this.log(this.color(\"red\", ` ${assertion.message}`));\n }\n }\n }\n\n /**\n * Prints field metrics summary\n */\n private printFieldMetrics(fm: FieldMetricResult): void {\n const { metrics, field, binarized, binarizeThreshold } = fm;\n\n const fieldLabel = binarized ? `${field} (binarized @ ${binarizeThreshold})` : field;\n\n this.log(\n this.color(\n \"cyan\",\n ` Field: ${fieldLabel} | Accuracy: ${this.pct(metrics.accuracy)} | F1: ${this.pct(metrics.macroAvg.f1)}`\n )\n );\n\n // Show per-class metrics if multiple classes\n if (Object.keys(metrics.perClass).length > 1) {\n for (const [cls, classMetrics] of Object.entries(metrics.perClass)) {\n this.log(\n this.color(\n \"dim\",\n ` ${cls}: P=${this.pct(classMetrics.precision)} R=${this.pct(classMetrics.recall)} F1=${this.pct(classMetrics.f1)} (n=${classMetrics.support})`\n )\n );\n }\n }\n }\n\n /**\n * Prints the summary\n */\n private printSummary(report: EvalReport): void {\n const { summary } = report;\n\n this.log(this.color(\"bold\", \" Summary\"));\n this.log(\"\");\n\n const passedStr = this.color(\"green\", `${summary.passed} passed`);\n const failedStr =\n summary.failed > 0\n ? this.color(\"red\", `${summary.failed} failed`)\n : `${summary.failed} failed`;\n const errorsStr =\n summary.errors > 0\n ? this.color(\"red\", `${summary.errors} errors`)\n : `${summary.errors} errors`;\n const skippedStr =\n summary.skipped > 0\n ? this.color(\"yellow\", `${summary.skipped} skipped`)\n : `${summary.skipped} skipped`;\n\n this.log(` Tests: ${passedStr}, ${failedStr}, ${errorsStr}, ${skippedStr}`);\n this.log(` Suites: ${summary.totalSuites}`);\n this.log(` Duration: ${this.formatDuration(summary.duration)}`);\n this.log(\"\");\n\n // Final status\n if (summary.failed === 0 && summary.errors === 0) {\n this.log(this.color(\"green\", \" All tests passed!\"));\n } else {\n this.log(this.color(\"red\", \" Some tests failed.\"));\n }\n\n this.log(\"\");\n }\n\n /**\n * Prints a confusion matrix\n */\n printConfusionMatrix(fm: FieldMetricResult): void {\n this.log(\"\");\n this.log(this.color(\"bold\", ` Confusion Matrix: ${fm.field}`));\n this.log(\"\");\n\n const matrixStr = formatConfusionMatrix(fm.metrics.confusionMatrix);\n for (const line of matrixStr.split(\"\\n\")) {\n this.log(` ${line}`);\n }\n\n this.log(\"\");\n }\n\n /**\n * Formats a percentage\n */\n private pct(value: number): string {\n return `${(value * 100).toFixed(1)}%`;\n }\n\n /**\n * Formats duration\n */\n private formatDuration(ms: number): string {\n if (ms < 1000) {\n return `${ms}ms`;\n }\n return `${(ms / 1000).toFixed(2)}s`;\n }\n\n /**\n * Gets status symbol\n */\n private getStatusSymbol(status: TestResult[\"status\"]): string {\n switch (status) {\n case \"passed\":\n return symbols.pass;\n case \"failed\":\n return symbols.fail;\n case \"error\":\n return symbols.error;\n case \"skipped\":\n return symbols.skip;\n }\n }\n\n /**\n * Gets status color\n */\n private getStatusColor(status: TestResult[\"status\"]): keyof typeof colors {\n switch (status) {\n case \"passed\":\n return \"green\";\n case \"failed\":\n return \"red\";\n case \"error\":\n return \"red\";\n case \"skipped\":\n return \"yellow\";\n }\n }\n\n /**\n * Applies color if enabled\n */\n private color(colorName: keyof typeof colors, text: string): string {\n if (!this.useColors) {\n return text;\n }\n return `${colors[colorName]}${text}${colors.reset}`;\n }\n\n /**\n * Logs a line\n */\n private log(message: string): void {\n console.log(message);\n }\n}\n","/**\n * Test file discovery - finds *.eval.js files\n */\n\nimport { glob } from \"glob\";\nimport { resolve, dirname } from \"node:path\";\nimport { existsSync } from \"node:fs\";\n\n/**\n * Default patterns for eval files\n */\nexport const DEFAULT_PATTERNS = [\"**/*.eval.js\", \"**/*.eval.ts\", \"**/*.eval.mjs\"];\n\n/**\n * Patterns to ignore\n */\nexport const DEFAULT_IGNORE = [\"**/node_modules/**\", \"**/dist/**\", \"**/build/**\", \"**/.git/**\"];\n\n/**\n * Options for file discovery\n */\nexport interface DiscoveryOptions {\n /** Patterns to match (default: *.eval.{js,ts,mjs}) */\n patterns?: string[];\n /** Patterns to ignore */\n ignore?: string[];\n /** Base directory to search from */\n cwd?: string;\n /** Filter pattern for test names */\n filter?: string;\n}\n\n/**\n * Discovers eval files matching the patterns\n *\n * @param options - Discovery options\n * @returns Array of absolute file paths\n */\nexport async function discoverEvalFiles(options: DiscoveryOptions = {}): Promise<string[]> {\n const { patterns = DEFAULT_PATTERNS, ignore = DEFAULT_IGNORE, cwd = process.cwd() } = options;\n\n const files: string[] = [];\n\n for (const pattern of patterns) {\n const matches = await glob(pattern, {\n cwd,\n ignore,\n absolute: true,\n nodir: true,\n });\n files.push(...matches);\n }\n\n // Remove duplicates and sort\n const unique = [...new Set(files)].sort();\n\n return unique;\n}\n\n/**\n * Discovers eval files from a specific path (file or directory)\n */\nexport async function discoverFromPath(\n path: string,\n options: DiscoveryOptions = {}\n): Promise<string[]> {\n const absolutePath = resolve(process.cwd(), path);\n\n if (!existsSync(absolutePath)) {\n throw new Error(`Path does not exist: ${path}`);\n }\n\n // Check if it's a file\n const { statSync } = await import(\"node:fs\");\n const stat = statSync(absolutePath);\n\n if (stat.isFile()) {\n // Single file\n return [absolutePath];\n }\n\n // Directory - discover within it\n return discoverEvalFiles({\n ...options,\n cwd: absolutePath,\n });\n}\n\n/**\n * Filters file paths by a pattern\n */\nexport function filterFiles(files: string[], filter?: string): string[] {\n if (!filter) {\n return files;\n }\n\n const filterLower = filter.toLowerCase();\n return files.filter((file) => file.toLowerCase().includes(filterLower));\n}\n\n/**\n * Groups files by their directory\n */\nexport function groupByDirectory(files: string[]): Map<string, string[]> {\n const groups = new Map<string, string[]>();\n\n for (const file of files) {\n const dir = dirname(file);\n const existing = groups.get(dir) ?? [];\n existing.push(file);\n groups.set(dir, existing);\n }\n\n return groups;\n}\n","/**\n * Core type definitions for EvalSense\n */\n\n// ============================================================================\n// Dataset & Alignment Types\n// ============================================================================\n\n/**\n * A loaded dataset with records and metadata\n */\nexport interface Dataset<T = Record<string, unknown>> {\n records: T[];\n metadata: DatasetMetadata;\n}\n\nexport interface DatasetMetadata {\n source: string;\n count: number;\n loadedAt: Date;\n}\n\n/**\n * A record aligned between actual (model output) and expected (ground truth)\n */\nexport interface AlignedRecord {\n id: string;\n actual: Record<string, unknown>;\n expected: Record<string, unknown>;\n}\n\n/**\n * Output from runModel() - predictions with IDs for alignment\n */\nexport interface Prediction {\n id: string;\n [field: string]: unknown;\n}\n\n// ============================================================================\n// LLM Types\n// ============================================================================\n\n/**\n * JSON Schema for structured LLM outputs\n */\nexport interface JSONSchema {\n type: string;\n properties?: Record<string, unknown>;\n required?: string[];\n [key: string]: unknown;\n}\n\n/**\n * LLM client interface for metric evaluation\n */\nexport interface LLMClient {\n /**\n * Generate a text completion from a prompt\n */\n complete(prompt: string): Promise<string>;\n\n /**\n * Generate a structured JSON completion (optional)\n */\n completeStructured?<T>(prompt: string, schema: JSONSchema): Promise<T>;\n}\n\n// ============================================================================\n// Metric Types\n// ============================================================================\n\n/**\n * Output from an LLM metric evaluation\n */\nexport interface MetricOutput {\n id: string;\n metric: string;\n score: number;\n label?: string;\n\n /** LLM's reasoning/explanation (for LLM-based metrics) */\n reasoning?: string;\n\n /** Evaluation mode used (for LLM-based metrics) */\n evaluationMode?: \"per-row\" | \"batch\";\n}\n\n/**\n * Configuration for a metric function\n */\nexport interface MetricConfig {\n outputs: Array<{ id: string; output: string }>;\n context?: string[];\n query?: string[];\n source?: string[];\n\n /** LLM client override (defaults to global client) */\n llmClient?: LLMClient;\n\n /** Evaluation mode: per-row (accurate, expensive) or batch (cheaper, potentially less accurate) */\n evaluationMode?: \"per-row\" | \"batch\";\n\n /** Custom prompt template override */\n customPrompt?: string;\n\n /** LLM temperature (default: 0) */\n temperature?: number;\n\n /** Max tokens per completion */\n maxTokens?: number;\n\n /** Timeout in milliseconds */\n timeout?: number;\n}\n\n/**\n * A metric function that evaluates outputs\n */\nexport type MetricFn = (config: MetricConfig) => Promise<MetricOutput[]>;\n\n// ============================================================================\n// Statistics Types\n// ============================================================================\n\n/**\n * Confusion matrix with labels\n */\nexport interface ConfusionMatrix {\n matrix: number[][];\n labels: string[];\n total: number;\n}\n\n/**\n * Per-class classification metrics\n */\nexport interface ClassMetrics {\n precision: number;\n recall: number;\n f1: number;\n support: number;\n}\n\n/**\n * Full classification metrics result\n */\nexport interface ClassificationMetrics {\n accuracy: number;\n perClass: Record<string, ClassMetrics>;\n macroAvg: { precision: number; recall: number; f1: number };\n weightedAvg: { precision: number; recall: number; f1: number };\n confusionMatrix: ConfusionMatrix;\n}\n\n/**\n * Regression metrics result\n */\nexport interface RegressionMetrics {\n mae: number;\n mse: number;\n rmse: number;\n r2: number;\n}\n\n// ============================================================================\n// Field Evaluation Types\n// ============================================================================\n\n/**\n * Result of evaluating a single field across all predictions\n */\nexport interface FieldMetricResult {\n field: string;\n metrics: ClassificationMetrics;\n binarized: boolean;\n binarizeThreshold?: number;\n}\n\n// ============================================================================\n// Test & Suite Types\n// ============================================================================\n\n/**\n * Test function signature\n */\nexport type TestFn = () => Promise<void> | void;\n\n/**\n * An individual eval test\n */\nexport interface EvalTest {\n name: string;\n fn: TestFn;\n}\n\n/**\n * A test suite (describe block)\n */\nexport interface Suite {\n name: string;\n tests: EvalTest[];\n beforeAll?: TestFn[];\n afterAll?: TestFn[];\n beforeEach?: TestFn[];\n afterEach?: TestFn[];\n}\n\n/**\n * Current test execution context\n */\nexport interface TestContext {\n currentSuite: Suite | null;\n suites: Suite[];\n results: SuiteResult[];\n}\n\n// ============================================================================\n// Assertion Types\n// ============================================================================\n\n/**\n * Result of a single assertion\n */\nexport interface AssertionResult {\n type: string;\n passed: boolean;\n message: string;\n expected?: unknown;\n actual?: unknown;\n field?: string;\n class?: string;\n}\n\n// ============================================================================\n// Result & Report Types\n// ============================================================================\n\n/**\n * Result of a single test\n */\nexport interface TestResult {\n name: string;\n status: \"passed\" | \"failed\" | \"error\" | \"skipped\";\n assertions: AssertionResult[];\n fieldMetrics: FieldMetricResult[];\n duration: number;\n error?: Error;\n}\n\n/**\n * Result of a test suite\n */\nexport interface SuiteResult {\n name: string;\n tests: TestResult[];\n passed: number;\n failed: number;\n errors: number;\n skipped: number;\n duration: number;\n}\n\n/**\n * Integrity check results for a dataset\n */\nexport interface IntegrityResult {\n valid: boolean;\n totalRecords: number;\n missingIds: string[];\n duplicateIds: string[];\n missingFields: Array<{ id: string; fields: string[] }>;\n}\n\n/**\n * Final evaluation report\n */\nexport interface EvalReport {\n version: string;\n timestamp: string;\n suites: SuiteResult[];\n summary: {\n totalSuites: number;\n totalTests: number;\n passed: number;\n failed: number;\n errors: number;\n skipped: number;\n duration: number;\n };\n integrity?: IntegrityResult;\n}\n\n// ============================================================================\n// CLI Types\n// ============================================================================\n\n/**\n * CLI configuration options\n */\nexport interface CLIOptions {\n filter?: string;\n output?: string;\n reporter?: \"json\" | \"console\" | \"both\";\n bail?: boolean;\n timeout?: number;\n}\n\n/**\n * Exit codes for CI integration\n */\nexport const ExitCodes = {\n SUCCESS: 0,\n ASSERTION_FAILURE: 1,\n INTEGRITY_FAILURE: 2,\n EXECUTION_ERROR: 3,\n CONFIGURATION_ERROR: 4,\n} as const;\n\nexport type ExitCode = (typeof ExitCodes)[keyof typeof ExitCodes];\n","/**\n * Test context management for EvalSense\n * Manages the global state during test execution\n */\n\nimport type { Suite, EvalTest, TestContext, AssertionResult, FieldMetricResult } from \"./types.js\";\n\n/**\n * Global test context - singleton for the current test run\n */\nlet globalContext: TestContext = createEmptyContext();\n\n/**\n * Current test execution state\n */\ninterface CurrentTestState {\n assertions: AssertionResult[];\n fieldMetrics: FieldMetricResult[];\n}\n\nlet currentTestState: CurrentTestState | null = null;\n\n/**\n * Creates an empty test context\n */\nexport function createEmptyContext(): TestContext {\n return {\n currentSuite: null,\n suites: [],\n results: [],\n };\n}\n\n/**\n * Gets the global test context\n */\nexport function getContext(): TestContext {\n return globalContext;\n}\n\n/**\n * Resets the global test context (used between test runs)\n */\nexport function resetContext(): void {\n globalContext = createEmptyContext();\n currentTestState = null;\n}\n\n/**\n * Gets the current suite being defined\n */\nexport function getCurrentSuite(): Suite | null {\n return globalContext.currentSuite;\n}\n\n/**\n * Sets the current suite being defined\n */\nexport function setCurrentSuite(suite: Suite | null): void {\n globalContext.currentSuite = suite;\n}\n\n/**\n * Adds a suite to the context\n */\nexport function addSuite(suite: Suite): void {\n globalContext.suites.push(suite);\n}\n\n/**\n * Adds a test to the current suite\n */\nexport function addTestToCurrentSuite(test: EvalTest): void {\n if (!globalContext.currentSuite) {\n throw new Error(\"Cannot add test outside of a describe() block\");\n }\n globalContext.currentSuite.tests.push(test);\n}\n\n/**\n * Gets all registered suites\n */\nexport function getSuites(): Suite[] {\n return globalContext.suites;\n}\n\n/**\n * Starts a new test execution (for collecting assertions)\n */\nexport function startTestExecution(): void {\n currentTestState = {\n assertions: [],\n fieldMetrics: [],\n };\n}\n\n/**\n * Ends the current test execution and returns collected data\n */\nexport function endTestExecution(): CurrentTestState {\n const state = currentTestState;\n currentTestState = null;\n return state ?? { assertions: [], fieldMetrics: [] };\n}\n\n/**\n * Records an assertion result in the current test\n */\nexport function recordAssertion(result: AssertionResult): void {\n if (currentTestState) {\n currentTestState.assertions.push(result);\n }\n}\n\n/**\n * Records field metrics in the current test\n */\nexport function recordFieldMetrics(metrics: FieldMetricResult): void {\n if (currentTestState) {\n currentTestState.fieldMetrics.push(metrics);\n }\n}\n\n/**\n * Checks if we're currently executing a test\n */\nexport function isInTestExecution(): boolean {\n return currentTestState !== null;\n}\n\n/**\n * Gets the current test state (for assertions to check)\n */\nexport function getCurrentTestState(): CurrentTestState | null {\n return currentTestState;\n}\n","/**\n * Test executor - runs discovered eval files\n */\n\nimport { pathToFileURL } from \"node:url\";\nimport type { Suite, TestResult, SuiteResult, EvalReport } from \"../core/types.js\";\nimport { ExitCodes } from \"../core/types.js\";\nimport { getSuites, startTestExecution, endTestExecution } from \"../core/context.js\";\nimport { AssertionError, TestExecutionError } from \"../core/errors.js\";\n\n/**\n * Options for test execution\n */\nexport interface ExecutorOptions {\n /** Stop on first failure */\n bail?: boolean;\n /** Test timeout in ms */\n timeout?: number;\n /** Filter pattern for test names */\n filter?: string;\n}\n\n/**\n * Executes all eval files and returns results\n */\nexport async function executeEvalFiles(\n files: string[],\n options: ExecutorOptions = {}\n): Promise<EvalReport> {\n const startTime = Date.now();\n const suiteResults: SuiteResult[] = [];\n\n // Load all eval files (this registers suites via describe())\n // Note: We don't reset context here because in CLI usage, each run\n // is a fresh Node process. For programmatic usage, call resetContext()\n // before calling this function if you need a clean slate.\n for (const file of files) {\n try {\n const fileUrl = pathToFileURL(file).href;\n await import(fileUrl);\n } catch (error) {\n throw new TestExecutionError(`Failed to load eval file: ${file}`, file, error as Error);\n }\n }\n\n // Get all registered suites\n const suites = getSuites();\n\n // Execute each suite\n for (const suite of suites) {\n const result = await executeSuite(suite, options);\n suiteResults.push(result);\n\n if (options.bail && result.failed > 0) {\n break;\n }\n }\n\n // Build report\n const report = buildReport(suiteResults, Date.now() - startTime);\n\n return report;\n}\n\n/**\n * Executes a single suite\n */\nasync function executeSuite(suite: Suite, options: ExecutorOptions): Promise<SuiteResult> {\n const startTime = Date.now();\n const testResults: TestResult[] = [];\n let passed = 0;\n let failed = 0;\n let errors = 0;\n let skipped = 0;\n\n // Run beforeAll hooks\n for (const hook of suite.beforeAll ?? []) {\n try {\n await hook();\n } catch (error) {\n // beforeAll failure fails all tests\n const message = error instanceof Error ? error.message : String(error);\n for (const test of suite.tests) {\n testResults.push({\n name: test.name,\n status: \"error\",\n assertions: [],\n fieldMetrics: [],\n duration: 0,\n error: new Error(`beforeAll hook failed: ${message}`),\n });\n errors++;\n }\n return {\n name: suite.name,\n tests: testResults,\n passed,\n failed,\n errors,\n skipped,\n duration: Date.now() - startTime,\n };\n }\n }\n\n // Run each test\n for (const test of suite.tests) {\n // Check filter\n if (options.filter && !test.name.toLowerCase().includes(options.filter.toLowerCase())) {\n testResults.push({\n name: test.name,\n status: \"skipped\",\n assertions: [],\n fieldMetrics: [],\n duration: 0,\n });\n skipped++;\n continue;\n }\n\n // Check if skipped\n if (test.name.startsWith(\"[SKIPPED]\")) {\n testResults.push({\n name: test.name,\n status: \"skipped\",\n assertions: [],\n fieldMetrics: [],\n duration: 0,\n });\n skipped++;\n continue;\n }\n\n // Run beforeEach hooks\n for (const hook of suite.beforeEach ?? []) {\n try {\n await hook();\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n testResults.push({\n name: test.name,\n status: \"error\",\n assertions: [],\n fieldMetrics: [],\n duration: 0,\n error: new Error(`beforeEach hook failed: ${message}`),\n });\n errors++;\n continue;\n }\n }\n\n // Execute the test\n const result = await executeTest(test.name, test.fn, options.timeout);\n testResults.push(result);\n\n if (result.status === \"passed\") {\n passed++;\n } else if (result.status === \"failed\") {\n failed++;\n } else if (result.status === \"error\") {\n errors++;\n }\n\n // Run afterEach hooks\n for (const hook of suite.afterEach ?? []) {\n try {\n await hook();\n } catch {\n // Log but don't fail the test\n }\n }\n\n // Bail on failure\n if (options.bail && (failed > 0 || errors > 0)) {\n break;\n }\n }\n\n // Run afterAll hooks\n for (const hook of suite.afterAll ?? []) {\n try {\n await hook();\n } catch {\n // Log but don't fail\n }\n }\n\n return {\n name: suite.name,\n tests: testResults,\n passed,\n failed,\n errors,\n skipped,\n duration: Date.now() - startTime,\n };\n}\n\n/**\n * Executes a single test with timeout\n */\nasync function executeTest(\n name: string,\n fn: () => Promise<void> | void,\n timeout = 30000\n): Promise<TestResult> {\n const startTime = Date.now();\n\n // Start collecting assertions\n startTestExecution();\n\n try {\n // Run with timeout\n await Promise.race([\n fn(),\n new Promise<never>((_, reject) =>\n setTimeout(() => reject(new Error(`Test timed out after ${timeout}ms`)), timeout)\n ),\n ]);\n\n // Test passed - collect results\n const { assertions, fieldMetrics } = endTestExecution();\n\n return {\n name,\n status: \"passed\",\n assertions,\n fieldMetrics,\n duration: Date.now() - startTime,\n };\n } catch (error) {\n const { assertions, fieldMetrics } = endTestExecution();\n\n if (error instanceof AssertionError) {\n // Assertion failure\n return {\n name,\n status: \"failed\",\n assertions,\n fieldMetrics,\n duration: Date.now() - startTime,\n error,\n };\n }\n\n // Execution error\n return {\n name,\n status: \"error\",\n assertions,\n fieldMetrics,\n duration: Date.now() - startTime,\n error: error instanceof Error ? error : new Error(String(error)),\n };\n }\n}\n\n/**\n * Builds the final report from suite results\n */\nfunction buildReport(suiteResults: SuiteResult[], totalDuration: number): EvalReport {\n let totalTests = 0;\n let totalPassed = 0;\n let totalFailed = 0;\n let totalErrors = 0;\n let totalSkipped = 0;\n\n for (const suite of suiteResults) {\n totalTests += suite.tests.length;\n totalPassed += suite.passed;\n totalFailed += suite.failed;\n totalErrors += suite.errors;\n totalSkipped += suite.skipped;\n }\n\n return {\n version: \"1.0.0\",\n timestamp: new Date().toISOString(),\n suites: suiteResults,\n summary: {\n totalSuites: suiteResults.length,\n totalTests,\n passed: totalPassed,\n failed: totalFailed,\n errors: totalErrors,\n skipped: totalSkipped,\n duration: totalDuration,\n },\n };\n}\n\n/**\n * Determines exit code from report\n */\nexport function getExitCode(report: EvalReport): number {\n if (report.summary.errors > 0) {\n return ExitCodes.EXECUTION_ERROR;\n }\n if (report.summary.failed > 0) {\n return ExitCodes.ASSERTION_FAILURE;\n }\n return ExitCodes.SUCCESS;\n}\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
2
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
3
|
+
}) : x)(function(x) {
|
|
4
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
5
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
export { __require };
|
|
9
|
+
//# sourceMappingURL=chunk-DGUM43GV.js.map
|
|
10
|
+
//# sourceMappingURL=chunk-DGUM43GV.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"chunk-DGUM43GV.js"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
4
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
5
|
+
}) : x)(function(x) {
|
|
6
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
7
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
exports.__require = __require;
|
|
11
|
+
//# sourceMappingURL=chunk-JEQ2X3Z6.cjs.map
|
|
12
|
+
//# sourceMappingURL=chunk-JEQ2X3Z6.cjs.map
|