@graphorin/evals 0.6.0 → 0.7.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/CHANGELOG.md +30 -0
- package/README.md +29 -3
- package/dist/index.d.ts +1 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/loaders/locomo.d.ts.map +1 -1
- package/dist/loaders/locomo.js +24 -2
- package/dist/loaders/locomo.js.map +1 -1
- package/dist/loaders/memory-eval.d.ts +8 -0
- package/dist/loaders/memory-eval.d.ts.map +1 -1
- package/dist/package.js +6 -0
- package/dist/package.js.map +1 -0
- package/package.json +10 -9
- package/src/cli/index.ts +124 -0
- package/src/index.ts +136 -0
- package/src/loaders/csv.ts +147 -0
- package/src/loaders/dmr.ts +137 -0
- package/src/loaders/from-traces.ts +92 -0
- package/src/loaders/index.ts +46 -0
- package/src/loaders/iterable.ts +22 -0
- package/src/loaders/jsonl.ts +94 -0
- package/src/loaders/locomo.ts +217 -0
- package/src/loaders/longmemeval.ts +164 -0
- package/src/loaders/memory-eval.ts +80 -0
- package/src/regression.ts +133 -0
- package/src/reporters/html.ts +83 -0
- package/src/reporters/index.ts +14 -0
- package/src/reporters/json.ts +18 -0
- package/src/reporters/junit.ts +53 -0
- package/src/reporters/markdown.ts +65 -0
- package/src/reporters/terminal.ts +46 -0
- package/src/runner.ts +233 -0
- package/src/scorers/code/exact-match.ts +95 -0
- package/src/scorers/code/index.ts +10 -0
- package/src/scorers/code/json-path.ts +101 -0
- package/src/scorers/code/predicate.ts +32 -0
- package/src/scorers/code/regex.ts +55 -0
- package/src/scorers/index.ts +15 -0
- package/src/scorers/llm/index.ts +13 -0
- package/src/scorers/llm/judge.ts +170 -0
- package/src/scorers/prebuilt/index.ts +95 -0
- package/src/scorers/trajectory/argument-validity.ts +63 -0
- package/src/scorers/trajectory/correct-tool-selected.ts +61 -0
- package/src/scorers/trajectory/final-state-correct.ts +62 -0
- package/src/scorers/trajectory/index.ts +25 -0
- package/src/scorers/trajectory/recovery-after-error.ts +55 -0
- package/src/scorers/trajectory/redundant-call-detection.ts +58 -0
- package/src/scorers/trajectory/types.ts +44 -0
- package/src/scorers/trajectory/util.ts +81 -0
- package/src/stats.ts +196 -0
- package/src/types.ts +135 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,35 @@
|
|
|
1
1
|
# @graphorin/evals
|
|
2
2
|
|
|
3
|
+
## 0.7.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#154](https://github.com/o-stepper/graphorin/pull/154) [`fe98522`](https://github.com/o-stepper/graphorin/commit/fe98522ce2477c9a7dc09029f9dcfdb1f7c9aa04) Thanks [@o-stepper](https://github.com/o-stepper)! - W-072: every export map's `import` condition becomes `default`, and the Node floor rises to `>=22.12.0`.
|
|
8
|
+
|
|
9
|
+
CJS consumers previously hit a bewildering `ERR_PACKAGE_PATH_NOT_EXPORTED` instead of a clear ESM-only signal. With the `default` condition, plain `require('@graphorin/core')` works via Node's stable `require(esm)` - which shipped in 22.12, hence the engines bump across every workspace manifest (packages, examples, benchmarks, docs; enforced by the widened mvp-readiness sweep). No dual-instance hazard: there is no CJS build, `require()` returns the same ESM module instance. ESM consumers are unaffected (`default` serves both paths; `types` stays first). The pack gate now runs attw under the full `node16` profile (was `esm-only`) and adds a runtime `require(esm)` smoke against the packed tarballs. Installs on Node 22.0-22.11 with `engine-strict` will refuse - upgrade Node (see the migration guide).
|
|
10
|
+
|
|
11
|
+
- [#153](https://github.com/o-stepper/graphorin/pull/153) [`832f22e`](https://github.com/o-stepper/graphorin/commit/832f22e570b8c3175c1adeb4c150070cbd131534) Thanks [@o-stepper](https://github.com/o-stepper)! - LOCOMO loader fidelity (W-022): `MemoryEvalTurn` gains an optional `speaker` field carrying the dataset-native speaker NAME alongside the two-role mapping - most LOCOMO questions reference speakers by name, and the LongMemEval benchmark runner now renders `<speaker>: ...` in both the full-context prompt and the ingested memory text. Numeric LOCOMO reference answers (e.g. `2022` - 6 of the 1986 QA pairs) are stringified instead of silently collapsing to `expected: ''`; QA pairs with no reference answer at all are SKIPPED rather than emitted, so the LLM judge never grades against an empty reference (documented in the module docs; this reduces the case count for such pairs). Any locally seeded LOCOMO baselines should be re-seeded - the ingested text changed; the committed stub-fixture CI baseline is unaffected.
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- [#164](https://github.com/o-stepper/graphorin/pull/164) [`764239b`](https://github.com/o-stepper/graphorin/commit/764239b97e0e0202442e91272583f13adeb12d00) Thanks [@o-stepper](https://github.com/o-stepper)! - TSDoc `{@link}` hygiene sweep (W-130): all 55 broken links found by TypeDoc's now-enabled `validation.invalidLink` are fixed - two resolved to their real targets (`GraphorinMCPError` was misnamed `MCPError`), the rest (cross-package, `import()`-form, unexported-constant, and DOM-type references that have never rendered as hrefs) converted to plain inline code. The docs build now fails on any new broken `{@link}` via a scoped gate.
|
|
16
|
+
|
|
17
|
+
- [#164](https://github.com/o-stepper/graphorin/pull/164) [`764239b`](https://github.com/o-stepper/graphorin/commit/764239b97e0e0202442e91272583f13adeb12d00) Thanks [@o-stepper](https://github.com/o-stepper)! - Tarballs now ship `src/` so the published `dist/**/*.d.ts.map` files actually work (W-136): the maps referenced `../src/*.ts` that the `files` whitelist excluded, so go-to-definition fell back into `.d.ts` and the shipped maps were dead weight. The pack gate gains a `map-integrity` leg: every source referenced by a shipped map must resolve inside the tarball (or be embedded via `sourcesContent`), with an anti-vacuous guard - a package whose tsdown config emits declaration maps must contain a non-zero number of `.d.ts.map` files, so a cache-restored dist that silently dropped maps fails the gate instead of passing vacuously. `mvp-readiness` now requires `src` in every publishable `files` array.
|
|
18
|
+
|
|
19
|
+
- Updated dependencies [[`fe98522`](https://github.com/o-stepper/graphorin/commit/fe98522ce2477c9a7dc09029f9dcfdb1f7c9aa04), [`fe98522`](https://github.com/o-stepper/graphorin/commit/fe98522ce2477c9a7dc09029f9dcfdb1f7c9aa04), [`fe98522`](https://github.com/o-stepper/graphorin/commit/fe98522ce2477c9a7dc09029f9dcfdb1f7c9aa04), [`fe98522`](https://github.com/o-stepper/graphorin/commit/fe98522ce2477c9a7dc09029f9dcfdb1f7c9aa04), [`832f22e`](https://github.com/o-stepper/graphorin/commit/832f22e570b8c3175c1adeb4c150070cbd131534), [`832f22e`](https://github.com/o-stepper/graphorin/commit/832f22e570b8c3175c1adeb4c150070cbd131534), [`fe98522`](https://github.com/o-stepper/graphorin/commit/fe98522ce2477c9a7dc09029f9dcfdb1f7c9aa04), [`fe98522`](https://github.com/o-stepper/graphorin/commit/fe98522ce2477c9a7dc09029f9dcfdb1f7c9aa04), [`832f22e`](https://github.com/o-stepper/graphorin/commit/832f22e570b8c3175c1adeb4c150070cbd131534), [`fe98522`](https://github.com/o-stepper/graphorin/commit/fe98522ce2477c9a7dc09029f9dcfdb1f7c9aa04), [`fe98522`](https://github.com/o-stepper/graphorin/commit/fe98522ce2477c9a7dc09029f9dcfdb1f7c9aa04), [`32bbd03`](https://github.com/o-stepper/graphorin/commit/32bbd03b588136a355e4b5ad6ac5e19b36b4d8ab), [`32bbd03`](https://github.com/o-stepper/graphorin/commit/32bbd03b588136a355e4b5ad6ac5e19b36b4d8ab), [`32bbd03`](https://github.com/o-stepper/graphorin/commit/32bbd03b588136a355e4b5ad6ac5e19b36b4d8ab), [`4ee256e`](https://github.com/o-stepper/graphorin/commit/4ee256e30fe9190cef6c48dc6785464757707156), [`4ee256e`](https://github.com/o-stepper/graphorin/commit/4ee256e30fe9190cef6c48dc6785464757707156), [`4ee256e`](https://github.com/o-stepper/graphorin/commit/4ee256e30fe9190cef6c48dc6785464757707156), [`32bbd03`](https://github.com/o-stepper/graphorin/commit/32bbd03b588136a355e4b5ad6ac5e19b36b4d8ab), [`4ee256e`](https://github.com/o-stepper/graphorin/commit/4ee256e30fe9190cef6c48dc6785464757707156), [`4ee256e`](https://github.com/o-stepper/graphorin/commit/4ee256e30fe9190cef6c48dc6785464757707156), [`4ee256e`](https://github.com/o-stepper/graphorin/commit/4ee256e30fe9190cef6c48dc6785464757707156), [`32bbd03`](https://github.com/o-stepper/graphorin/commit/32bbd03b588136a355e4b5ad6ac5e19b36b4d8ab), [`32bbd03`](https://github.com/o-stepper/graphorin/commit/32bbd03b588136a355e4b5ad6ac5e19b36b4d8ab), [`764239b`](https://github.com/o-stepper/graphorin/commit/764239b97e0e0202442e91272583f13adeb12d00), [`764239b`](https://github.com/o-stepper/graphorin/commit/764239b97e0e0202442e91272583f13adeb12d00), [`764239b`](https://github.com/o-stepper/graphorin/commit/764239b97e0e0202442e91272583f13adeb12d00), [`764239b`](https://github.com/o-stepper/graphorin/commit/764239b97e0e0202442e91272583f13adeb12d00), [`764239b`](https://github.com/o-stepper/graphorin/commit/764239b97e0e0202442e91272583f13adeb12d00), [`fe98522`](https://github.com/o-stepper/graphorin/commit/fe98522ce2477c9a7dc09029f9dcfdb1f7c9aa04), [`fe98522`](https://github.com/o-stepper/graphorin/commit/fe98522ce2477c9a7dc09029f9dcfdb1f7c9aa04), [`fe98522`](https://github.com/o-stepper/graphorin/commit/fe98522ce2477c9a7dc09029f9dcfdb1f7c9aa04)]:
|
|
20
|
+
- @graphorin/core@0.7.0
|
|
21
|
+
- @graphorin/observability@0.7.0
|
|
22
|
+
|
|
23
|
+
## 0.6.1
|
|
24
|
+
|
|
25
|
+
### Patch Changes
|
|
26
|
+
|
|
27
|
+
- [#142](https://github.com/o-stepper/graphorin/pull/142) [`436d6ca`](https://github.com/o-stepper/graphorin/commit/436d6ca5ebbd16df094e915682d3915c279a8430) Thanks [@o-stepper](https://github.com/o-stepper)! - Version constants and version-bearing strings now derive from each package's manifest at build time (`VERSION = pkg.version`; writer ids, client/server info, OTLP framework attributes, build-info metrics interpolate it). No behavioral change at the current version: the rendered strings are byte-identical. A release bump no longer edits source; the new `check-version-consistency` gate fails any reintroduced hardcoded framework version.
|
|
28
|
+
|
|
29
|
+
- Updated dependencies [[`826ee59`](https://github.com/o-stepper/graphorin/commit/826ee5933ad38693b0dd2f20a110abfecba7d23d), [`436d6ca`](https://github.com/o-stepper/graphorin/commit/436d6ca5ebbd16df094e915682d3915c279a8430)]:
|
|
30
|
+
- @graphorin/observability@0.6.1
|
|
31
|
+
- @graphorin/core@0.6.1
|
|
32
|
+
|
|
3
33
|
## 0.6.0
|
|
4
34
|
|
|
5
35
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -7,14 +7,14 @@
|
|
|
7
7
|
> bounded concurrency, and regression detection that compares the
|
|
8
8
|
> current run against a stored baseline.
|
|
9
9
|
>
|
|
10
|
-
> Project Graphorin · v0.
|
|
10
|
+
> Project Graphorin · v0.7.0 · MIT License · © 2026 Oleksiy Stepurenko ·
|
|
11
11
|
> <https://github.com/o-stepper/graphorin>
|
|
12
12
|
|
|
13
13
|
---
|
|
14
14
|
|
|
15
15
|
## Status
|
|
16
16
|
|
|
17
|
-
- **Published:** v0.
|
|
17
|
+
- **Published:** v0.7.0 (optional sub-pack; the full orchestrator is
|
|
18
18
|
decoupled from `@graphorin/observability` per RB-17 / DEC-152).
|
|
19
19
|
|
|
20
20
|
---
|
|
@@ -103,6 +103,25 @@ const report = await runEvals({
|
|
|
103
103
|
});
|
|
104
104
|
```
|
|
105
105
|
|
|
106
|
+
Every report summary carries a Wilson 95% confidence interval for the
|
|
107
|
+
pass rate (`summary.passRateCi`), and, when `iterations > 1`,
|
|
108
|
+
`summary.passHatK` - the pass^k estimate over the per-case iteration
|
|
109
|
+
outcomes (the probability that all k iterations of a case pass).
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Statistics
|
|
114
|
+
|
|
115
|
+
Sample-size-aware statistics ship as plain exported functions:
|
|
116
|
+
|
|
117
|
+
```ts
|
|
118
|
+
import { mean, sampleStddev, wilsonInterval, passHatK, pairedPassSignificance } from '@graphorin/evals';
|
|
119
|
+
|
|
120
|
+
wilsonInterval(18, 20); // { lo, hi } - 95% CI for 18/20 passes
|
|
121
|
+
passHatK(outcomesByCase); // pass^k over `-iter-N` outcome groups
|
|
122
|
+
pairedPassSignificance(a, b); // McNemar paired test between two runs
|
|
123
|
+
```
|
|
124
|
+
|
|
106
125
|
---
|
|
107
126
|
|
|
108
127
|
## Regression detection
|
|
@@ -116,6 +135,9 @@ const regression = detectRegressions(report, baseline, {
|
|
|
116
135
|
maxPassRateDropPct: 5,
|
|
117
136
|
maxAvgScoreDrop: 0.05,
|
|
118
137
|
maxAvgDurationIncreaseMs: 250,
|
|
138
|
+
// Opt-in: veto pass-rate-drop findings the McNemar paired test
|
|
139
|
+
// cannot distinguish from noise at the given alpha (default 0.05).
|
|
140
|
+
requireSignificance: true,
|
|
119
141
|
});
|
|
120
142
|
if (regression.hasRegressions) {
|
|
121
143
|
for (const f of regression.findings) {
|
|
@@ -125,6 +147,10 @@ if (regression.hasRegressions) {
|
|
|
125
147
|
exitOnFailures(report, regression);
|
|
126
148
|
```
|
|
127
149
|
|
|
150
|
+
Pass-rate findings are annotated with the paired regressed / improved
|
|
151
|
+
case counts and the McNemar p-value, so a 3-point drop on 20 cases
|
|
152
|
+
reads differently from the same drop on 2000.
|
|
153
|
+
|
|
128
154
|
---
|
|
129
155
|
|
|
130
156
|
## Multi-format report writing
|
|
@@ -154,4 +180,4 @@ MIT © 2026 Oleksiy Stepurenko
|
|
|
154
180
|
|
|
155
181
|
---
|
|
156
182
|
|
|
157
|
-
**Project Graphorin** · v0.
|
|
183
|
+
**Project Graphorin** · v0.7.0 · MIT License · © 2026 Oleksiy Stepurenko · <https://github.com/o-stepper/graphorin>
|
package/dist/index.d.ts
CHANGED
|
@@ -60,8 +60,7 @@ import { PairedSignificance, mean, pairedPassSignificance, passByBaseCase, passH
|
|
|
60
60
|
*
|
|
61
61
|
* @packageDocumentation
|
|
62
62
|
*/
|
|
63
|
-
|
|
64
|
-
declare const VERSION = "0.6.0";
|
|
63
|
+
declare const VERSION: string;
|
|
65
64
|
//#endregion
|
|
66
65
|
export { type AgentLike, type ArgumentValidityOptions, type Case, type CorrectToolSelectedOptions, type Dataset, type EvalCaseResult, type EvalReport, type ExactMatchOptions, type FinalStateCorrectOptions, type FromTracesOptions, type JsonPathOptions, type LlmJudgeOptions, type LoadCsvOptions, type LoadDmrOptions, type LoadJsonlOptions, type LoadLocomoOptions, type LoadLongMemEvalOptions, type MemoryEvalAbility, type MemoryEvalInput, type MemoryEvalSession, type MemoryEvalTurn, type PairedSignificance, type PrebuiltScorerOptions, type PredicateOptions, type ProgressEvent, type RecoveryAfterErrorOptions, type RedundantCallDetectionOptions, type RegexMatchOptions, type RegressionFinding, type RegressionOptions, type RegressionReport, type ReporterFormat, type RunEvalOptions, type RunOptions, type ScoreResult, type Scorer, type TraceEvent, type Trajectory, type TrajectoryToolCall, VERSION, type WriteReportsOptions, type WrittenReport, argumentValidity, correctToolSelected, detectRegressions, detectRegressions as detectRegressionsFromReports, exactMatch, exitOnFailures, factualityScorer, fenceForJudge, finalStateCorrect, fromIterable, helpfulnessScorer, jsonPath, llmJudge, loadCsvDataset, loadDatasetFromTraces, loadDmrDataset, loadJsonlDataset, loadLocomoDataset, loadLongMemEvalDataset, mean, pairedPassSignificance, parseCsv, parseDmr, parseJsonl, parseLocomo, parseLongMemEval, parseScore, passByBaseCase, passHatK, predicate, recoveryAfterError, redundantCallDetection, regexMatch, renderHtmlReport, renderJsonReport, renderJunitReport, renderMarkdownReport, renderTerminalReport, runEvals, sampleStddev, scoreContract, stripIterationSuffix, toxicityScorer, wilsonInterval, writeReports };
|
|
67
66
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/index.ts"],"sourcesContent":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/index.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAkCa"}
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { version } from "./package.js";
|
|
1
2
|
import { mean, pairedPassSignificance, passByBaseCase, passHatK, sampleStddev, stripIterationSuffix, wilsonInterval } from "./stats.js";
|
|
2
3
|
import { detectRegressions } from "./regression.js";
|
|
3
4
|
import { renderHtmlReport } from "./reporters/html.js";
|
|
@@ -57,8 +58,8 @@ import { redundantCallDetection } from "./scorers/trajectory/redundant-call-dete
|
|
|
57
58
|
*
|
|
58
59
|
* @packageDocumentation
|
|
59
60
|
*/
|
|
60
|
-
/** Canonical version constant
|
|
61
|
-
const VERSION =
|
|
61
|
+
/** Canonical version constant, derived from `package.json` at build time. */
|
|
62
|
+
const VERSION = version;
|
|
62
63
|
|
|
63
64
|
//#endregion
|
|
64
65
|
export { VERSION, argumentValidity, correctToolSelected, detectRegressions, detectRegressions as detectRegressionsFromReports, exactMatch, exitOnFailures, factualityScorer, fenceForJudge, finalStateCorrect, fromIterable, helpfulnessScorer, jsonPath, llmJudge, loadCsvDataset, loadDatasetFromTraces, loadDmrDataset, loadJsonlDataset, loadLocomoDataset, loadLongMemEvalDataset, mean, pairedPassSignificance, parseCsv, parseDmr, parseJsonl, parseLocomo, parseLongMemEval, parseScore, passByBaseCase, passHatK, predicate, recoveryAfterError, redundantCallDetection, regexMatch, renderHtmlReport, renderJsonReport, renderJunitReport, renderMarkdownReport, renderTerminalReport, runEvals, sampleStddev, scoreContract, stripIterationSuffix, toxicityScorer, wilsonInterval, writeReports };
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["/**\n * @graphorin/evals - eval framework for the Graphorin framework.\n *\n * Builds on the eval primitives shipped from `@graphorin/observability`\n * (RB-17 / DEC-152) - full orchestrator lives here, post-MVP, decoupled\n * from the core observability bundle so consumers do not pay the\n * dataset / reporter cost when only the inline runner is needed.\n *\n * ```ts\n * import {\n * runEvals,\n * loadJsonlDataset,\n * exactMatch,\n * renderTerminalReport,\n * exitOnFailures,\n * } from '@graphorin/evals';\n *\n * const dataset = await loadJsonlDataset('./fixtures/golden.jsonl');\n * const report = await runEvals({\n * agent,\n * dataset,\n * scorers: [exactMatch()],\n * concurrency: 4,\n * });\n * console.log(renderTerminalReport(report));\n * exitOnFailures(report);\n * ```\n *\n * @packageDocumentation\n */\n\n/** Canonical version constant
|
|
1
|
+
{"version":3,"file":"index.js","names":["VERSION: string","pkg.version"],"sources":["../src/index.ts"],"sourcesContent":["/**\n * @graphorin/evals - eval framework for the Graphorin framework.\n *\n * Builds on the eval primitives shipped from `@graphorin/observability`\n * (RB-17 / DEC-152) - full orchestrator lives here, post-MVP, decoupled\n * from the core observability bundle so consumers do not pay the\n * dataset / reporter cost when only the inline runner is needed.\n *\n * ```ts\n * import {\n * runEvals,\n * loadJsonlDataset,\n * exactMatch,\n * renderTerminalReport,\n * exitOnFailures,\n * } from '@graphorin/evals';\n *\n * const dataset = await loadJsonlDataset('./fixtures/golden.jsonl');\n * const report = await runEvals({\n * agent,\n * dataset,\n * scorers: [exactMatch()],\n * concurrency: 4,\n * });\n * console.log(renderTerminalReport(report));\n * exitOnFailures(report);\n * ```\n *\n * @packageDocumentation\n */\n\n/** Canonical version constant, derived from `package.json` at build time. */\nimport pkg from '../package.json' with { type: 'json' };\n\nexport const VERSION: string = pkg.version;\n\nexport {\n detectRegressions,\n exitOnFailures,\n type ReporterFormat,\n type WriteReportsOptions,\n type WrittenReport,\n writeReports,\n} from './cli/index.js';\nexport type {\n FromTracesOptions,\n LoadDmrOptions,\n LoadLocomoOptions,\n LoadLongMemEvalOptions,\n MemoryEvalAbility,\n MemoryEvalInput,\n MemoryEvalSession,\n MemoryEvalTurn,\n TraceEvent,\n} from './loaders/index.js';\nexport {\n fromIterable,\n type LoadCsvOptions,\n type LoadJsonlOptions,\n loadCsvDataset,\n loadDatasetFromTraces,\n loadDmrDataset,\n loadJsonlDataset,\n loadLocomoDataset,\n loadLongMemEvalDataset,\n parseCsv,\n parseDmr,\n parseJsonl,\n parseLocomo,\n parseLongMemEval,\n} from './loaders/index.js';\nexport { detectRegressions as detectRegressionsFromReports } from './regression.js';\nexport {\n renderHtmlReport,\n renderJsonReport,\n renderJunitReport,\n renderMarkdownReport,\n renderTerminalReport,\n} from './reporters/index.js';\nexport { runEvals } from './runner.js';\nexport {\n type ArgumentValidityOptions,\n argumentValidity,\n type CorrectToolSelectedOptions,\n correctToolSelected,\n type ExactMatchOptions,\n exactMatch,\n type FinalStateCorrectOptions,\n factualityScorer,\n fenceForJudge,\n finalStateCorrect,\n helpfulnessScorer,\n type JsonPathOptions,\n jsonPath,\n type LlmJudgeOptions,\n llmJudge,\n type PrebuiltScorerOptions,\n type PredicateOptions,\n parseScore,\n predicate,\n type RecoveryAfterErrorOptions,\n type RedundantCallDetectionOptions,\n type RegexMatchOptions,\n recoveryAfterError,\n redundantCallDetection,\n regexMatch,\n scoreContract,\n type Trajectory,\n type TrajectoryToolCall,\n toxicityScorer,\n} from './scorers/index.js';\nexport {\n mean,\n type PairedSignificance,\n pairedPassSignificance,\n passByBaseCase,\n passHatK,\n sampleStddev,\n stripIterationSuffix,\n wilsonInterval,\n} from './stats.js';\nexport type {\n AgentLike,\n Case,\n Dataset,\n EvalCaseResult,\n EvalReport,\n ProgressEvent,\n RegressionFinding,\n RegressionOptions,\n RegressionReport,\n RunEvalOptions,\n RunOptions,\n ScoreResult,\n Scorer,\n} from './types.js';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkCA,MAAaA,UAAkBC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"locomo.d.ts","names":[],"sources":["../../src/loaders/locomo.ts"],"sourcesContent":[],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"locomo.d.ts","names":[],"sources":["../../src/loaders/locomo.ts"],"sourcesContent":[],"mappings":";;;;;;UAuDiB,iBAAA;;;;;;;;;;;;;;;iBAgBK,iBAAA,UACX,oBACR,QAAQ,QAAQ;;;;;;;iBAmBH,WAAA,gBAA2B,cAAc,KAAK"}
|
package/dist/loaders/locomo.js
CHANGED
|
@@ -31,6 +31,16 @@ import { readFile } from "node:fs/promises";
|
|
|
31
31
|
* (adversarial), everything else (`3` open-domain, `4` single-hop)
|
|
32
32
|
* →info-extraction.
|
|
33
33
|
*
|
|
34
|
+
* Answer handling (W-022): LOCOMO answers may be numbers (e.g. `2022`)
|
|
35
|
+
* - they are stringified, never silently coerced to `''`. A QA pair
|
|
36
|
+
* with NO answer at all (neither `answer` nor `adversarial_answer`) is
|
|
37
|
+
* SKIPPED rather than emitted with an empty `expected`: the LLM judge
|
|
38
|
+
* grading against an empty reference produces meaningless verdicts, so
|
|
39
|
+
* a missing reference must reduce the case count, not poison scores.
|
|
40
|
+
* Turns carry the dataset-native `speaker` name alongside the
|
|
41
|
+
* two-role mapping (~99 percent of LOCOMO questions reference speakers
|
|
42
|
+
* by name).
|
|
43
|
+
*
|
|
34
44
|
* @packageDocumentation
|
|
35
45
|
*/
|
|
36
46
|
/**
|
|
@@ -79,7 +89,8 @@ function appendSampleCases(sample, index, out) {
|
|
|
79
89
|
if (question === void 0) continue;
|
|
80
90
|
const category = typeof item.category === "number" ? item.category : void 0;
|
|
81
91
|
const ability = mapCategory(category);
|
|
82
|
-
const answer =
|
|
92
|
+
const answer = answerToText(item.answer) ?? answerToText(item.adversarial_answer);
|
|
93
|
+
if (answer === void 0) continue;
|
|
83
94
|
const evidence = asArray(item.evidence).filter((e) => typeof e === "string");
|
|
84
95
|
out.push({
|
|
85
96
|
id: `${sampleId}-q${q}`,
|
|
@@ -121,7 +132,8 @@ function extractSessions(conversation) {
|
|
|
121
132
|
turns.push({
|
|
122
133
|
role,
|
|
123
134
|
content,
|
|
124
|
-
...date !== void 0 ? { timestamp: date } : {}
|
|
135
|
+
...date !== void 0 ? { timestamp: date } : {},
|
|
136
|
+
...speaker !== void 0 ? { speaker } : {}
|
|
125
137
|
});
|
|
126
138
|
}
|
|
127
139
|
sessions.push({
|
|
@@ -143,6 +155,16 @@ function mapCategory(category) {
|
|
|
143
155
|
function asString(value) {
|
|
144
156
|
return typeof value === "string" ? value : void 0;
|
|
145
157
|
}
|
|
158
|
+
/**
|
|
159
|
+
* LOCOMO reference answers may be strings OR bare numbers (6 of the
|
|
160
|
+
* 1986 QA pairs ship e.g. `2022`). Stringify finite numbers instead of
|
|
161
|
+
* dropping them to `''` (W-022); a blank string counts as "no answer"
|
|
162
|
+
* so the judge never grades against an empty reference.
|
|
163
|
+
*/
|
|
164
|
+
function answerToText(value) {
|
|
165
|
+
if (typeof value === "string") return value.trim().length > 0 ? value : void 0;
|
|
166
|
+
if (typeof value === "number" && Number.isFinite(value)) return String(value);
|
|
167
|
+
}
|
|
146
168
|
function asArray(value) {
|
|
147
169
|
return Array.isArray(value) ? value : [];
|
|
148
170
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"locomo.js","names":["parsed: unknown","out: Case<MemoryEvalInput, string>[]","indices: number[]","sessions: MemoryEvalSession[]","turns: MemoryEvalTurn[]","role: 'user' | 'assistant'"],"sources":["../../src/loaders/locomo.ts"],"sourcesContent":["/**\n * Real LOCOMO dataset loader (arXiv:2402.17753 -\n * https://snap-research.github.io/locomo/). LOCOMO ships as a JSON\n * **array** of samples; each sample bundles one multi-session\n * conversation with many QA pairs over it:\n *\n * ```jsonc\n * {\n * \"sample_id\": \"conv-26\",\n * \"conversation\": {\n * \"speaker_a\": \"Caroline\",\n * \"speaker_b\": \"Melanie\",\n * \"session_1_date_time\": \"1:56 pm on 8 May, 2023\",\n * \"session_1\": [ { \"speaker\": \"Caroline\", \"dia_id\": \"D1:1\", \"text\": \"...\" }, ... ],\n * \"session_2_date_time\": \"...\",\n * \"session_2\": [ ... ]\n * },\n * \"qa\": [\n * { \"question\": \"...\", \"answer\": \"...\", \"evidence\": [\"D1:1\"], \"category\": 1 },\n * { \"question\": \"...\", \"category\": 5, \"adversarial_answer\": \"Not mentioned ...\" }\n * ]\n * }\n * ```\n *\n * Each QA pair becomes one {@link MemoryEvalInput} case that shares the\n * sample's sessions. LOCOMO categories map to abilities as:\n * `1`→multi-session (multi-hop), `2`→temporal, `5`→abstention\n * (adversarial), everything else (`3` open-domain, `4` single-hop)\n * →info-extraction.\n *\n * @packageDocumentation\n */\n\nimport { readFile } from 'node:fs/promises';\n\nimport type { Case, Dataset } from '@graphorin/observability/eval';\n\nimport type {\n MemoryEvalAbility,\n MemoryEvalInput,\n MemoryEvalSession,\n MemoryEvalTurn,\n} from './memory-eval.js';\n\n/** @stable */\nexport interface LoadLocomoOptions {\n /** Local path to the LOCOMO JSON (under `benchmarks/.datasets/`). */\n readonly path: string;\n /** Optional dataset name surfaced in `Dataset.metadata.name`. */\n readonly name?: string;\n /** Optional description surfaced in `Dataset.metadata.description`. */\n readonly description?: string;\n}\n\n/**\n * Read a LOCOMO JSON file and return a fully-materialised\n * {@link Dataset} - one case per QA pair, scored against the reference\n * answer string (LLM-judge \"J\").\n *\n * @stable\n */\nexport async function loadLocomoDataset(\n options: LoadLocomoOptions,\n): Promise<Dataset<MemoryEvalInput, string>> {\n const text = await readFile(options.path, 'utf8');\n const cases = parseLocomo(text);\n return {\n cases,\n metadata: {\n name: options.name ?? 'locomo',\n ...(options.description !== undefined ? { description: options.description } : {}),\n createdAt: new Date(),\n },\n };\n}\n\n/**\n * Pure parser. Exported so tests can exercise the mapping without\n * touching the filesystem.\n *\n * @stable\n */\nexport function parseLocomo(text: string): ReadonlyArray<Case<MemoryEvalInput, string>> {\n const parsed: unknown = JSON.parse(text);\n if (!Array.isArray(parsed)) {\n throw new Error('[graphorin/evals] LOCOMO dataset must be a JSON array of samples.');\n }\n const samples = parsed as ReadonlyArray<unknown>;\n const out: Case<MemoryEvalInput, string>[] = [];\n for (let i = 0; i < samples.length; i++) {\n const sample = samples[i];\n if (sample === null || typeof sample !== 'object') {\n throw new Error(`[graphorin/evals] LOCOMO sample ${i} is not an object.`);\n }\n appendSampleCases(sample as Record<string, unknown>, i, out);\n }\n return out;\n}\n\nfunction appendSampleCases(\n sample: Record<string, unknown>,\n index: number,\n out: Case<MemoryEvalInput, string>[],\n): void {\n const sampleId = asString(sample.sample_id) ?? `locomo-${index}`;\n const conversation = isRecord(sample.conversation) ? sample.conversation : {};\n const sessions = extractSessions(conversation);\n const qa = asArray(sample.qa);\n for (let q = 0; q < qa.length; q++) {\n const item = qa[q];\n if (!isRecord(item)) continue;\n const question = asString(item.question);\n if (question === undefined) continue;\n const category = typeof item.category === 'number' ? item.category : undefined;\n const ability = mapCategory(category);\n const answer = asString(item.answer) ?? asString(item.adversarial_answer) ?? '';\n const evidence = asArray(item.evidence).filter((e): e is string => typeof e === 'string');\n out.push({\n id: `${sampleId}-q${q}`,\n input: { haystackSessions: sessions, question, ability },\n expected: answer,\n metadata: {\n datasetName: 'locomo',\n sampleId,\n ability,\n ...(category !== undefined ? { category } : {}),\n evidence,\n },\n });\n }\n}\n\nfunction extractSessions(conversation: Record<string, unknown>): MemoryEvalSession[] {\n const speakerA = asString(conversation.speaker_a);\n const indices: number[] = [];\n for (const key of Object.keys(conversation)) {\n const m = /^session_(\\d+)$/.exec(key);\n if (m?.[1] !== undefined) indices.push(Number.parseInt(m[1], 10));\n }\n indices.sort((a, b) => a - b);\n const sessions: MemoryEvalSession[] = [];\n for (const n of indices) {\n const raw = asArray(conversation[`session_${n}`]);\n const date = asString(conversation[`session_${n}_date_time`]);\n const turns: MemoryEvalTurn[] = [];\n for (const t of raw) {\n if (!isRecord(t)) continue;\n const content = asString(t.text) ?? asString(t.content);\n if (content === undefined) continue;\n const speaker = asString(t.speaker);\n const role: 'user' | 'assistant' =\n speakerA !== undefined && speaker !== undefined && speaker !== speakerA\n ? 'assistant'\n : 'user';\n turns.push({ role, content, ...(date !== undefined ? { timestamp: date } : {}) });\n }\n sessions.push({ id: `session_${n}`, turns });\n }\n return sessions;\n}\n\n/** Maps a LOCOMO numeric `category` onto a {@link MemoryEvalAbility}. */\nfunction mapCategory(category: number | undefined): MemoryEvalAbility {\n switch (category) {\n case 1:\n return 'multi-session';\n case 2:\n return 'temporal';\n case 5:\n return 'abstention';\n default:\n return 'info-extraction';\n }\n}\n\nfunction asString(value: unknown): string | undefined {\n return typeof value === 'string' ? value : undefined;\n}\n\nfunction asArray(value: unknown): ReadonlyArray<unknown> {\n return Array.isArray(value) ? (value as ReadonlyArray<unknown>) : [];\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"locomo.js","names":["parsed: unknown","out: Case<MemoryEvalInput, string>[]","indices: number[]","sessions: MemoryEvalSession[]","turns: MemoryEvalTurn[]","role: 'user' | 'assistant'"],"sources":["../../src/loaders/locomo.ts"],"sourcesContent":["/**\n * Real LOCOMO dataset loader (arXiv:2402.17753 -\n * https://snap-research.github.io/locomo/). LOCOMO ships as a JSON\n * **array** of samples; each sample bundles one multi-session\n * conversation with many QA pairs over it:\n *\n * ```jsonc\n * {\n * \"sample_id\": \"conv-26\",\n * \"conversation\": {\n * \"speaker_a\": \"Caroline\",\n * \"speaker_b\": \"Melanie\",\n * \"session_1_date_time\": \"1:56 pm on 8 May, 2023\",\n * \"session_1\": [ { \"speaker\": \"Caroline\", \"dia_id\": \"D1:1\", \"text\": \"...\" }, ... ],\n * \"session_2_date_time\": \"...\",\n * \"session_2\": [ ... ]\n * },\n * \"qa\": [\n * { \"question\": \"...\", \"answer\": \"...\", \"evidence\": [\"D1:1\"], \"category\": 1 },\n * { \"question\": \"...\", \"category\": 5, \"adversarial_answer\": \"Not mentioned ...\" }\n * ]\n * }\n * ```\n *\n * Each QA pair becomes one {@link MemoryEvalInput} case that shares the\n * sample's sessions. LOCOMO categories map to abilities as:\n * `1`→multi-session (multi-hop), `2`→temporal, `5`→abstention\n * (adversarial), everything else (`3` open-domain, `4` single-hop)\n * →info-extraction.\n *\n * Answer handling (W-022): LOCOMO answers may be numbers (e.g. `2022`)\n * - they are stringified, never silently coerced to `''`. A QA pair\n * with NO answer at all (neither `answer` nor `adversarial_answer`) is\n * SKIPPED rather than emitted with an empty `expected`: the LLM judge\n * grading against an empty reference produces meaningless verdicts, so\n * a missing reference must reduce the case count, not poison scores.\n * Turns carry the dataset-native `speaker` name alongside the\n * two-role mapping (~99 percent of LOCOMO questions reference speakers\n * by name).\n *\n * @packageDocumentation\n */\n\nimport { readFile } from 'node:fs/promises';\n\nimport type { Case, Dataset } from '@graphorin/observability/eval';\n\nimport type {\n MemoryEvalAbility,\n MemoryEvalInput,\n MemoryEvalSession,\n MemoryEvalTurn,\n} from './memory-eval.js';\n\n/** @stable */\nexport interface LoadLocomoOptions {\n /** Local path to the LOCOMO JSON (under `benchmarks/.datasets/`). */\n readonly path: string;\n /** Optional dataset name surfaced in `Dataset.metadata.name`. */\n readonly name?: string;\n /** Optional description surfaced in `Dataset.metadata.description`. */\n readonly description?: string;\n}\n\n/**\n * Read a LOCOMO JSON file and return a fully-materialised\n * {@link Dataset} - one case per QA pair, scored against the reference\n * answer string (LLM-judge \"J\").\n *\n * @stable\n */\nexport async function loadLocomoDataset(\n options: LoadLocomoOptions,\n): Promise<Dataset<MemoryEvalInput, string>> {\n const text = await readFile(options.path, 'utf8');\n const cases = parseLocomo(text);\n return {\n cases,\n metadata: {\n name: options.name ?? 'locomo',\n ...(options.description !== undefined ? { description: options.description } : {}),\n createdAt: new Date(),\n },\n };\n}\n\n/**\n * Pure parser. Exported so tests can exercise the mapping without\n * touching the filesystem.\n *\n * @stable\n */\nexport function parseLocomo(text: string): ReadonlyArray<Case<MemoryEvalInput, string>> {\n const parsed: unknown = JSON.parse(text);\n if (!Array.isArray(parsed)) {\n throw new Error('[graphorin/evals] LOCOMO dataset must be a JSON array of samples.');\n }\n const samples = parsed as ReadonlyArray<unknown>;\n const out: Case<MemoryEvalInput, string>[] = [];\n for (let i = 0; i < samples.length; i++) {\n const sample = samples[i];\n if (sample === null || typeof sample !== 'object') {\n throw new Error(`[graphorin/evals] LOCOMO sample ${i} is not an object.`);\n }\n appendSampleCases(sample as Record<string, unknown>, i, out);\n }\n return out;\n}\n\nfunction appendSampleCases(\n sample: Record<string, unknown>,\n index: number,\n out: Case<MemoryEvalInput, string>[],\n): void {\n const sampleId = asString(sample.sample_id) ?? `locomo-${index}`;\n const conversation = isRecord(sample.conversation) ? sample.conversation : {};\n const sessions = extractSessions(conversation);\n const qa = asArray(sample.qa);\n for (let q = 0; q < qa.length; q++) {\n const item = qa[q];\n if (!isRecord(item)) continue;\n const question = asString(item.question);\n if (question === undefined) continue;\n const category = typeof item.category === 'number' ? item.category : undefined;\n const ability = mapCategory(category);\n const answer = answerToText(item.answer) ?? answerToText(item.adversarial_answer);\n // No reference answer at all: skip the pair (see module docs, W-022).\n if (answer === undefined) continue;\n const evidence = asArray(item.evidence).filter((e): e is string => typeof e === 'string');\n out.push({\n id: `${sampleId}-q${q}`,\n input: { haystackSessions: sessions, question, ability },\n expected: answer,\n metadata: {\n datasetName: 'locomo',\n sampleId,\n ability,\n ...(category !== undefined ? { category } : {}),\n evidence,\n },\n });\n }\n}\n\nfunction extractSessions(conversation: Record<string, unknown>): MemoryEvalSession[] {\n const speakerA = asString(conversation.speaker_a);\n const indices: number[] = [];\n for (const key of Object.keys(conversation)) {\n const m = /^session_(\\d+)$/.exec(key);\n if (m?.[1] !== undefined) indices.push(Number.parseInt(m[1], 10));\n }\n indices.sort((a, b) => a - b);\n const sessions: MemoryEvalSession[] = [];\n for (const n of indices) {\n const raw = asArray(conversation[`session_${n}`]);\n const date = asString(conversation[`session_${n}_date_time`]);\n const turns: MemoryEvalTurn[] = [];\n for (const t of raw) {\n if (!isRecord(t)) continue;\n const content = asString(t.text) ?? asString(t.content);\n if (content === undefined) continue;\n const speaker = asString(t.speaker);\n const role: 'user' | 'assistant' =\n speakerA !== undefined && speaker !== undefined && speaker !== speakerA\n ? 'assistant'\n : 'user';\n turns.push({\n role,\n content,\n ...(date !== undefined ? { timestamp: date } : {}),\n // W-022: keep the dataset-native name; the role mapping stays\n // for cross-dataset machinery compatibility.\n ...(speaker !== undefined ? { speaker } : {}),\n });\n }\n sessions.push({ id: `session_${n}`, turns });\n }\n return sessions;\n}\n\n/** Maps a LOCOMO numeric `category` onto a {@link MemoryEvalAbility}. */\nfunction mapCategory(category: number | undefined): MemoryEvalAbility {\n switch (category) {\n case 1:\n return 'multi-session';\n case 2:\n return 'temporal';\n case 5:\n return 'abstention';\n default:\n return 'info-extraction';\n }\n}\n\nfunction asString(value: unknown): string | undefined {\n return typeof value === 'string' ? value : undefined;\n}\n\n/**\n * LOCOMO reference answers may be strings OR bare numbers (6 of the\n * 1986 QA pairs ship e.g. `2022`). Stringify finite numbers instead of\n * dropping them to `''` (W-022); a blank string counts as \"no answer\"\n * so the judge never grades against an empty reference.\n */\nfunction answerToText(value: unknown): string | undefined {\n if (typeof value === 'string') return value.trim().length > 0 ? value : undefined;\n if (typeof value === 'number' && Number.isFinite(value)) return String(value);\n return undefined;\n}\n\nfunction asArray(value: unknown): ReadonlyArray<unknown> {\n return Array.isArray(value) ? (value as ReadonlyArray<unknown>) : [];\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value);\n}\n"],"mappings":"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"}
|
|
@@ -25,6 +25,14 @@ interface MemoryEvalTurn {
|
|
|
25
25
|
readonly content: string;
|
|
26
26
|
/** Dataset-native (often ISO-8601) timestamp, when the dataset provides one. */
|
|
27
27
|
readonly timestamp?: string;
|
|
28
|
+
/**
|
|
29
|
+
* Dataset-native speaker NAME (e.g. LOCOMO's `"Melanie"`), when the
|
|
30
|
+
* dataset provides one (W-022). Distinct from `role`: two-speaker
|
|
31
|
+
* datasets map onto user/assistant for machinery compatibility, but
|
|
32
|
+
* most LOCOMO questions reference the speakers by name, so the
|
|
33
|
+
* system under test must see the names in the ingested text.
|
|
34
|
+
*/
|
|
35
|
+
readonly speaker?: string;
|
|
28
36
|
}
|
|
29
37
|
/**
|
|
30
38
|
* One prior session in the haystack the memory system must ingest
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memory-eval.d.ts","names":[],"sources":["../../src/loaders/memory-eval.ts"],"sourcesContent":[],"mappings":";;AAsBA;
|
|
1
|
+
{"version":3,"file":"memory-eval.d.ts","names":[],"sources":["../../src/loaders/memory-eval.ts"],"sourcesContent":[],"mappings":";;AAsBA;AAqBA;AAYA;AAYA;;;;;;;;;;;;;;;;;UA7CiB,cAAA;;;;;;;;;;;;;;;;;;;;UAqBA,iBAAA;;kBAEC,cAAc;;;;;;;;;KAUpB,iBAAA;;;;;;UAYK,eAAA;;6BAEY,cAAc;;;;;;;;;qBAStB"}
|
package/dist/package.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"package.js","names":[],"sources":["../package.json"],"sourcesContent":["{\n \"name\": \"@graphorin/evals\",\n \"version\": \"0.7.0\",\n \"description\": \"Eval framework for the Graphorin framework. Ships scorer libraries (`code/` exact-match, regex, JSON path, predicates; `llm/` LLM-judge; `prebuilt/` toxicity / factuality / helpfulness), dataset loaders (JSONL, CSV, from-traces, generic iterable), reporters (terminal, markdown, JSON, JUnit XML), a parallel runner with `concurrency` config, and regression detection that compares the current run against a stored baseline. Builds on the eval primitives shipped from `@graphorin/observability` (RB-17 / DEC-152 - full orchestrator lives here, post-MVP, decoupled from the core observability bundle so consumers do not pay the dataset / reporter cost when only the inline runner is needed). Created and maintained by Oleksiy Stepurenko.\",\n \"license\": \"MIT\",\n \"author\": \"Oleksiy Stepurenko\",\n \"homepage\": \"https://github.com/o-stepper/graphorin/tree/main/packages/evals\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/o-stepper/graphorin.git\",\n \"directory\": \"packages/evals\"\n },\n \"bugs\": {\n \"url\": \"https://github.com/o-stepper/graphorin/issues\"\n },\n \"keywords\": [\n \"graphorin\",\n \"ai\",\n \"agents\",\n \"framework\",\n \"evals\",\n \"evaluation\",\n \"scorers\",\n \"llm-judge\",\n \"datasets\",\n \"reporters\",\n \"regression-detection\"\n ],\n \"type\": \"module\",\n \"engines\": {\n \"node\": \">=22.12.0\"\n },\n \"main\": \"./dist/index.js\",\n \"module\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"sideEffects\": false,\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"default\": \"./dist/index.js\"\n },\n \"./scorers\": {\n \"types\": \"./dist/scorers/index.d.ts\",\n \"default\": \"./dist/scorers/index.js\"\n },\n \"./loaders\": {\n \"types\": \"./dist/loaders/index.d.ts\",\n \"default\": \"./dist/loaders/index.js\"\n },\n \"./reporters\": {\n \"types\": \"./dist/reporters/index.d.ts\",\n \"default\": \"./dist/reporters/index.js\"\n },\n \"./cli\": {\n \"types\": \"./dist/cli/index.d.ts\",\n \"default\": \"./dist/cli/index.js\"\n },\n \"./package.json\": \"./package.json\"\n },\n \"files\": [\n \"dist\",\n \"src\",\n \"README.md\",\n \"CHANGELOG.md\",\n \"LICENSE\"\n ],\n \"scripts\": {\n \"build\": \"tsdown\",\n \"typecheck\": \"tsc --noEmit && tsc -p tsconfig.tests.json\",\n \"test\": \"vitest run\",\n \"lint\": \"biome check .\",\n \"clean\": \"rimraf dist .turbo *.tsbuildinfo\"\n },\n \"dependencies\": {\n \"@graphorin/core\": \"workspace:*\",\n \"@graphorin/observability\": \"workspace:*\"\n },\n \"publishConfig\": {\n \"access\": \"public\",\n \"provenance\": true\n }\n}\n"],"mappings":";cAEa"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@graphorin/evals",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Eval framework for the Graphorin framework. Ships scorer libraries (`code/` exact-match, regex, JSON path, predicates; `llm/` LLM-judge; `prebuilt/` toxicity / factuality / helpfulness), dataset loaders (JSONL, CSV, from-traces, generic iterable), reporters (terminal, markdown, JSON, JUnit XML), a parallel runner with `concurrency` config, and regression detection that compares the current run against a stored baseline. Builds on the eval primitives shipped from `@graphorin/observability` (RB-17 / DEC-152 - full orchestrator lives here, post-MVP, decoupled from the core observability bundle so consumers do not pay the dataset / reporter cost when only the inline runner is needed). Created and maintained by Oleksiy Stepurenko.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Oleksiy Stepurenko",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
],
|
|
29
29
|
"type": "module",
|
|
30
30
|
"engines": {
|
|
31
|
-
"node": ">=22.
|
|
31
|
+
"node": ">=22.12.0"
|
|
32
32
|
},
|
|
33
33
|
"main": "./dist/index.js",
|
|
34
34
|
"module": "./dist/index.js",
|
|
@@ -37,35 +37,36 @@
|
|
|
37
37
|
"exports": {
|
|
38
38
|
".": {
|
|
39
39
|
"types": "./dist/index.d.ts",
|
|
40
|
-
"
|
|
40
|
+
"default": "./dist/index.js"
|
|
41
41
|
},
|
|
42
42
|
"./scorers": {
|
|
43
43
|
"types": "./dist/scorers/index.d.ts",
|
|
44
|
-
"
|
|
44
|
+
"default": "./dist/scorers/index.js"
|
|
45
45
|
},
|
|
46
46
|
"./loaders": {
|
|
47
47
|
"types": "./dist/loaders/index.d.ts",
|
|
48
|
-
"
|
|
48
|
+
"default": "./dist/loaders/index.js"
|
|
49
49
|
},
|
|
50
50
|
"./reporters": {
|
|
51
51
|
"types": "./dist/reporters/index.d.ts",
|
|
52
|
-
"
|
|
52
|
+
"default": "./dist/reporters/index.js"
|
|
53
53
|
},
|
|
54
54
|
"./cli": {
|
|
55
55
|
"types": "./dist/cli/index.d.ts",
|
|
56
|
-
"
|
|
56
|
+
"default": "./dist/cli/index.js"
|
|
57
57
|
},
|
|
58
58
|
"./package.json": "./package.json"
|
|
59
59
|
},
|
|
60
60
|
"files": [
|
|
61
61
|
"dist",
|
|
62
|
+
"src",
|
|
62
63
|
"README.md",
|
|
63
64
|
"CHANGELOG.md",
|
|
64
65
|
"LICENSE"
|
|
65
66
|
],
|
|
66
67
|
"dependencies": {
|
|
67
|
-
"@graphorin/core": "0.
|
|
68
|
-
"@graphorin/observability": "0.
|
|
68
|
+
"@graphorin/core": "0.7.0",
|
|
69
|
+
"@graphorin/observability": "0.7.0"
|
|
69
70
|
},
|
|
70
71
|
"publishConfig": {
|
|
71
72
|
"access": "public",
|
package/src/cli/index.ts
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI integration helpers. Convenience wrappers that combine the
|
|
3
|
+
* runner + a reporter + an exit-code mapping so consumer scripts can
|
|
4
|
+
* stay short.
|
|
5
|
+
*
|
|
6
|
+
* Typical use from a `package.json` script:
|
|
7
|
+
*
|
|
8
|
+
* ```jsonc
|
|
9
|
+
* {
|
|
10
|
+
* "scripts": {
|
|
11
|
+
* "eval": "node ./scripts/run-evals.mjs"
|
|
12
|
+
* }
|
|
13
|
+
* }
|
|
14
|
+
* ```
|
|
15
|
+
*
|
|
16
|
+
* Where `run-evals.mjs` looks like:
|
|
17
|
+
*
|
|
18
|
+
* ```ts
|
|
19
|
+
* import { runEvals, exitOnFailures, renderTerminalReport } from '@graphorin/evals';
|
|
20
|
+
*
|
|
21
|
+
* const report = await runEvals({...});
|
|
22
|
+
* console.log(renderTerminalReport(report));
|
|
23
|
+
* exitOnFailures(report);
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* @packageDocumentation
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
import { writeFile } from 'node:fs/promises';
|
|
30
|
+
import process from 'node:process';
|
|
31
|
+
|
|
32
|
+
import type { EvalReport } from '@graphorin/observability/eval';
|
|
33
|
+
|
|
34
|
+
import { detectRegressions } from '../regression.js';
|
|
35
|
+
import {
|
|
36
|
+
renderHtmlReport,
|
|
37
|
+
renderJsonReport,
|
|
38
|
+
renderJunitReport,
|
|
39
|
+
renderMarkdownReport,
|
|
40
|
+
renderTerminalReport,
|
|
41
|
+
} from '../reporters/index.js';
|
|
42
|
+
import type { RegressionOptions, RegressionReport } from '../types.js';
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Set `process.exitCode` to `1` when at least one case failed, or
|
|
46
|
+
* when a regression report contains findings. Uses `exitCode` rather
|
|
47
|
+
* than `process.exit` so other async tasks finish cleanly.
|
|
48
|
+
*
|
|
49
|
+
* @stable
|
|
50
|
+
*/
|
|
51
|
+
export function exitOnFailures<I, O>(
|
|
52
|
+
report: EvalReport<I, O>,
|
|
53
|
+
regression?: RegressionReport<I, O>,
|
|
54
|
+
): void {
|
|
55
|
+
if (report.summary.failed > 0) process.exitCode = 1;
|
|
56
|
+
if (regression?.hasRegressions) process.exitCode = 1;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Reporter ids accepted by {@link writeReports}.
|
|
61
|
+
*
|
|
62
|
+
* @stable
|
|
63
|
+
*/
|
|
64
|
+
export type ReporterFormat = 'terminal' | 'markdown' | 'json' | 'junit' | 'html';
|
|
65
|
+
|
|
66
|
+
/** @stable */
|
|
67
|
+
export interface WriteReportsOptions<I, O> {
|
|
68
|
+
readonly report: EvalReport<I, O>;
|
|
69
|
+
readonly outDir?: string;
|
|
70
|
+
readonly formats: ReadonlyArray<ReporterFormat>;
|
|
71
|
+
readonly basename?: string;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** @stable */
|
|
75
|
+
export interface WrittenReport {
|
|
76
|
+
readonly format: ReporterFormat;
|
|
77
|
+
readonly path: string;
|
|
78
|
+
readonly bytes: number;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Render the report in every requested format and write each one to a
|
|
83
|
+
* file. Returns the manifest of written files.
|
|
84
|
+
*
|
|
85
|
+
* @stable
|
|
86
|
+
*/
|
|
87
|
+
export async function writeReports<I, O>(
|
|
88
|
+
options: WriteReportsOptions<I, O>,
|
|
89
|
+
): Promise<ReadonlyArray<WrittenReport>> {
|
|
90
|
+
const out: WrittenReport[] = [];
|
|
91
|
+
const dir = options.outDir ?? '.';
|
|
92
|
+
const basename = options.basename ?? 'eval-report';
|
|
93
|
+
for (const format of options.formats) {
|
|
94
|
+
const { extension, body } = renderForFormat(format, options.report);
|
|
95
|
+
const path = `${dir}/${basename}.${extension}`;
|
|
96
|
+
await writeFile(path, body, 'utf8');
|
|
97
|
+
out.push({ format, path, bytes: Buffer.byteLength(body, 'utf8') });
|
|
98
|
+
}
|
|
99
|
+
return out;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function renderForFormat<I, O>(
|
|
103
|
+
format: ReporterFormat,
|
|
104
|
+
report: EvalReport<I, O>,
|
|
105
|
+
): { extension: string; body: string } {
|
|
106
|
+
switch (format) {
|
|
107
|
+
case 'terminal':
|
|
108
|
+
return { extension: 'txt', body: renderTerminalReport(report) };
|
|
109
|
+
case 'markdown':
|
|
110
|
+
return { extension: 'md', body: renderMarkdownReport(report) };
|
|
111
|
+
case 'json':
|
|
112
|
+
return { extension: 'json', body: renderJsonReport(report, { pretty: true }) };
|
|
113
|
+
case 'junit':
|
|
114
|
+
return { extension: 'xml', body: renderJunitReport(report) };
|
|
115
|
+
case 'html':
|
|
116
|
+
return { extension: 'html', body: renderHtmlReport(report) };
|
|
117
|
+
default: {
|
|
118
|
+
const exhaustive: never = format;
|
|
119
|
+
throw new Error(`unknown reporter format '${exhaustive as string}'`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export { detectRegressions, type RegressionOptions };
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @graphorin/evals - eval framework for the Graphorin framework.
|
|
3
|
+
*
|
|
4
|
+
* Builds on the eval primitives shipped from `@graphorin/observability`
|
|
5
|
+
* (RB-17 / DEC-152) - full orchestrator lives here, post-MVP, decoupled
|
|
6
|
+
* from the core observability bundle so consumers do not pay the
|
|
7
|
+
* dataset / reporter cost when only the inline runner is needed.
|
|
8
|
+
*
|
|
9
|
+
* ```ts
|
|
10
|
+
* import {
|
|
11
|
+
* runEvals,
|
|
12
|
+
* loadJsonlDataset,
|
|
13
|
+
* exactMatch,
|
|
14
|
+
* renderTerminalReport,
|
|
15
|
+
* exitOnFailures,
|
|
16
|
+
* } from '@graphorin/evals';
|
|
17
|
+
*
|
|
18
|
+
* const dataset = await loadJsonlDataset('./fixtures/golden.jsonl');
|
|
19
|
+
* const report = await runEvals({
|
|
20
|
+
* agent,
|
|
21
|
+
* dataset,
|
|
22
|
+
* scorers: [exactMatch()],
|
|
23
|
+
* concurrency: 4,
|
|
24
|
+
* });
|
|
25
|
+
* console.log(renderTerminalReport(report));
|
|
26
|
+
* exitOnFailures(report);
|
|
27
|
+
* ```
|
|
28
|
+
*
|
|
29
|
+
* @packageDocumentation
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
/** Canonical version constant, derived from `package.json` at build time. */
|
|
33
|
+
import pkg from '../package.json' with { type: 'json' };
|
|
34
|
+
|
|
35
|
+
export const VERSION: string = pkg.version;
|
|
36
|
+
|
|
37
|
+
export {
|
|
38
|
+
detectRegressions,
|
|
39
|
+
exitOnFailures,
|
|
40
|
+
type ReporterFormat,
|
|
41
|
+
type WriteReportsOptions,
|
|
42
|
+
type WrittenReport,
|
|
43
|
+
writeReports,
|
|
44
|
+
} from './cli/index.js';
|
|
45
|
+
export type {
|
|
46
|
+
FromTracesOptions,
|
|
47
|
+
LoadDmrOptions,
|
|
48
|
+
LoadLocomoOptions,
|
|
49
|
+
LoadLongMemEvalOptions,
|
|
50
|
+
MemoryEvalAbility,
|
|
51
|
+
MemoryEvalInput,
|
|
52
|
+
MemoryEvalSession,
|
|
53
|
+
MemoryEvalTurn,
|
|
54
|
+
TraceEvent,
|
|
55
|
+
} from './loaders/index.js';
|
|
56
|
+
export {
|
|
57
|
+
fromIterable,
|
|
58
|
+
type LoadCsvOptions,
|
|
59
|
+
type LoadJsonlOptions,
|
|
60
|
+
loadCsvDataset,
|
|
61
|
+
loadDatasetFromTraces,
|
|
62
|
+
loadDmrDataset,
|
|
63
|
+
loadJsonlDataset,
|
|
64
|
+
loadLocomoDataset,
|
|
65
|
+
loadLongMemEvalDataset,
|
|
66
|
+
parseCsv,
|
|
67
|
+
parseDmr,
|
|
68
|
+
parseJsonl,
|
|
69
|
+
parseLocomo,
|
|
70
|
+
parseLongMemEval,
|
|
71
|
+
} from './loaders/index.js';
|
|
72
|
+
export { detectRegressions as detectRegressionsFromReports } from './regression.js';
|
|
73
|
+
export {
|
|
74
|
+
renderHtmlReport,
|
|
75
|
+
renderJsonReport,
|
|
76
|
+
renderJunitReport,
|
|
77
|
+
renderMarkdownReport,
|
|
78
|
+
renderTerminalReport,
|
|
79
|
+
} from './reporters/index.js';
|
|
80
|
+
export { runEvals } from './runner.js';
|
|
81
|
+
export {
|
|
82
|
+
type ArgumentValidityOptions,
|
|
83
|
+
argumentValidity,
|
|
84
|
+
type CorrectToolSelectedOptions,
|
|
85
|
+
correctToolSelected,
|
|
86
|
+
type ExactMatchOptions,
|
|
87
|
+
exactMatch,
|
|
88
|
+
type FinalStateCorrectOptions,
|
|
89
|
+
factualityScorer,
|
|
90
|
+
fenceForJudge,
|
|
91
|
+
finalStateCorrect,
|
|
92
|
+
helpfulnessScorer,
|
|
93
|
+
type JsonPathOptions,
|
|
94
|
+
jsonPath,
|
|
95
|
+
type LlmJudgeOptions,
|
|
96
|
+
llmJudge,
|
|
97
|
+
type PrebuiltScorerOptions,
|
|
98
|
+
type PredicateOptions,
|
|
99
|
+
parseScore,
|
|
100
|
+
predicate,
|
|
101
|
+
type RecoveryAfterErrorOptions,
|
|
102
|
+
type RedundantCallDetectionOptions,
|
|
103
|
+
type RegexMatchOptions,
|
|
104
|
+
recoveryAfterError,
|
|
105
|
+
redundantCallDetection,
|
|
106
|
+
regexMatch,
|
|
107
|
+
scoreContract,
|
|
108
|
+
type Trajectory,
|
|
109
|
+
type TrajectoryToolCall,
|
|
110
|
+
toxicityScorer,
|
|
111
|
+
} from './scorers/index.js';
|
|
112
|
+
export {
|
|
113
|
+
mean,
|
|
114
|
+
type PairedSignificance,
|
|
115
|
+
pairedPassSignificance,
|
|
116
|
+
passByBaseCase,
|
|
117
|
+
passHatK,
|
|
118
|
+
sampleStddev,
|
|
119
|
+
stripIterationSuffix,
|
|
120
|
+
wilsonInterval,
|
|
121
|
+
} from './stats.js';
|
|
122
|
+
export type {
|
|
123
|
+
AgentLike,
|
|
124
|
+
Case,
|
|
125
|
+
Dataset,
|
|
126
|
+
EvalCaseResult,
|
|
127
|
+
EvalReport,
|
|
128
|
+
ProgressEvent,
|
|
129
|
+
RegressionFinding,
|
|
130
|
+
RegressionOptions,
|
|
131
|
+
RegressionReport,
|
|
132
|
+
RunEvalOptions,
|
|
133
|
+
RunOptions,
|
|
134
|
+
ScoreResult,
|
|
135
|
+
Scorer,
|
|
136
|
+
} from './types.js';
|