jevkit-bench 0.1.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 ADDED
@@ -0,0 +1,64 @@
1
+ # jevkit-bench
2
+
3
+ Score a labeled Jev suite for accuracy **and** cost, and compare two runs.
4
+
5
+ Any one number alone is easy to win. Accuracy without cost hides that you spent
6
+ ten times the tokens; cost without accuracy hides that you broke the task. This
7
+ reports them together.
8
+
9
+ > Unofficial and unaffiliated with TypeSafe.
10
+
11
+ ```bash
12
+ pip install jevkit-bench
13
+ ```
14
+
15
+ ## Use
16
+
17
+ ```python
18
+ from jevkit_core import read_records
19
+ from jevkit_bench import compare_suites, score_records
20
+
21
+ suite = score_records(read_records("suite.jevl"))
22
+ print(suite.summary())
23
+
24
+ for failure in suite.failures()[:5]:
25
+ print(failure.question_id, failure.predicted, "should be", failure.label)
26
+ ```
27
+
28
+ `failures()` sorts by probability descending, so the most confident wrong answers
29
+ come first. Those are the interesting bugs: a wrong answer at 0.35 is the model
30
+ telling you it was unsure, while a wrong answer at 0.98 is a question that needs
31
+ rewriting.
32
+
33
+ ## Comparing runs
34
+
35
+ ```python
36
+ comparison = compare_suites(baseline, candidate)
37
+ print(comparison.summary())
38
+ print(comparison.regressions) # right before, wrong now
39
+ ```
40
+
41
+ Aggregate accuracy can hold perfectly steady while the set of things you get
42
+ right churns underneath. That matters when a specific case is the one you
43
+ promised someone would work, so regressions and fixes are tracked individually
44
+ rather than netted off.
45
+
46
+ ## CLI
47
+
48
+ ```bash
49
+ jevkit-bench suite.jevl
50
+ jevkit-bench suite.jevl --baseline last-week.jevl
51
+ jevkit-bench suite.jevl --min-accuracy 0.90 # CI gate
52
+ jevkit-bench suite.jevl --baseline last-week.jevl --max-regressions 0
53
+ jevkit-bench suite.jevl --show-failures 10
54
+ ```
55
+
56
+ ## Cost
57
+
58
+ Computed from input tokens at $0.042 per million, Jev's published price. Output
59
+ tokens are free on Jev, so they are reported but never billed. Override with
60
+ `--price-per-mtok` if your plan differs.
61
+
62
+ ## License
63
+
64
+ MIT
package/dist/cli.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env node
2
+ /** `jevkit-bench` command line interface. */
3
+ export declare const EXIT_OK = 0;
4
+ export declare const EXIT_FAILED_GATE = 1;
5
+ export declare const EXIT_USAGE = 2;
6
+ export declare function main(argv?: string[]): number;
7
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,6CAA6C;AAM7C,eAAO,MAAM,OAAO,IAAI,CAAC;AACzB,eAAO,MAAM,gBAAgB,IAAI,CAAC;AAClC,eAAO,MAAM,UAAU,IAAI,CAAC;AAe5B,wBAAgB,IAAI,CAAC,IAAI,GAAE,MAAM,EAA0B,GAAG,MAAM,CA+GnE"}
package/dist/cli.js ADDED
@@ -0,0 +1,148 @@
1
+ #!/usr/bin/env node
2
+ /** `jevkit-bench` command line interface. */
3
+ import { RecordFormatError, readRecords } from "jevkit-core";
4
+ import { PRICE_PER_MTOK, compareSuites, scoreRecords } from "./score.js";
5
+ export const EXIT_OK = 0;
6
+ export const EXIT_FAILED_GATE = 1;
7
+ export const EXIT_USAGE = 2;
8
+ const USAGE = `usage: jevkit-bench <suite.jevl> [options]
9
+
10
+ Score a labeled .jevl suite for accuracy and cost, and compare two runs of it.
11
+ Never calls the API.
12
+
13
+ --baseline FILE a previous run, to compare against
14
+ --question ID restrict to this question id (repeatable)
15
+ --price-per-mtok F input price per million tokens (default ${PRICE_PER_MTOK})
16
+ --min-accuracy F exit non-zero below this
17
+ --max-regressions N exit non-zero above this many (needs --baseline)
18
+ --show-failures N print the N most confident wrong answers
19
+ --format text|json`;
20
+ export function main(argv = process.argv.slice(2)) {
21
+ const files = [];
22
+ const questions = [];
23
+ let baselinePath = null;
24
+ let pricePerMtok = PRICE_PER_MTOK;
25
+ let minAccuracy = null;
26
+ let maxRegressions = null;
27
+ let showFailures = 0;
28
+ let format = "text";
29
+ for (let i = 0; i < argv.length; i++) {
30
+ const arg = argv[i];
31
+ switch (arg) {
32
+ case "--baseline":
33
+ baselinePath = String(argv[++i]);
34
+ break;
35
+ case "--question":
36
+ questions.push(String(argv[++i]));
37
+ break;
38
+ case "--price-per-mtok":
39
+ pricePerMtok = Number(argv[++i]);
40
+ break;
41
+ case "--min-accuracy":
42
+ minAccuracy = Number(argv[++i]);
43
+ break;
44
+ case "--max-regressions":
45
+ maxRegressions = Number(argv[++i]);
46
+ break;
47
+ case "--show-failures":
48
+ showFailures = Number(argv[++i]);
49
+ break;
50
+ case "--format": {
51
+ const v = argv[++i];
52
+ if (v !== "text" && v !== "json") {
53
+ console.error("jevkit-bench: --format expects text or json");
54
+ return EXIT_USAGE;
55
+ }
56
+ format = v;
57
+ break;
58
+ }
59
+ case "-h":
60
+ case "--help":
61
+ console.log(USAGE);
62
+ return EXIT_OK;
63
+ default:
64
+ if (arg.startsWith("--")) {
65
+ console.error(`jevkit-bench: unknown option ${arg}`);
66
+ return EXIT_USAGE;
67
+ }
68
+ files.push(arg);
69
+ }
70
+ }
71
+ if (files.length !== 1) {
72
+ console.error(USAGE);
73
+ return EXIT_USAGE;
74
+ }
75
+ if (maxRegressions !== null && !baselinePath) {
76
+ console.error("jevkit-bench: --max-regressions needs --baseline");
77
+ return EXIT_USAGE;
78
+ }
79
+ const options = {
80
+ questionIds: questions.length ? questions : undefined,
81
+ pricePerMtok,
82
+ };
83
+ let suite, baseline;
84
+ try {
85
+ suite = scoreRecords(readRecords(files[0]), options);
86
+ baseline = baselinePath ? scoreRecords(readRecords(baselinePath), options) : null;
87
+ }
88
+ catch (err) {
89
+ const message = err instanceof RecordFormatError ? err.message : err.message;
90
+ console.error(`jevkit-bench: ${message}`);
91
+ return EXIT_USAGE;
92
+ }
93
+ if (!suite.count) {
94
+ console.error("jevkit-bench: nothing scored. Records need a 'label' object keyed by question id.");
95
+ return EXIT_USAGE;
96
+ }
97
+ const comparison = baseline ? compareSuites(baseline, suite) : null;
98
+ if (format === "json") {
99
+ const payload = { ...suite.toJSON() };
100
+ if (comparison) {
101
+ payload["comparison"] = {
102
+ baselineAccuracy: comparison.baseline.accuracy,
103
+ accuracyDelta: comparison.accuracyDelta,
104
+ costDelta: comparison.costDelta,
105
+ regressions: comparison.regressions,
106
+ fixes: comparison.fixes,
107
+ };
108
+ }
109
+ console.log(JSON.stringify(payload, null, 2));
110
+ }
111
+ else {
112
+ console.log(suite.summary());
113
+ if (comparison) {
114
+ console.log();
115
+ console.log(comparison.summary());
116
+ if (comparison.regressions.length) {
117
+ console.log("\nregressions:");
118
+ for (const [rid, qid] of comparison.regressions.slice(0, 20)) {
119
+ console.log(` ${rid.slice(7, 19)} ${qid}`);
120
+ }
121
+ }
122
+ }
123
+ if (showFailures) {
124
+ const failures = suite.failures().slice(0, showFailures);
125
+ if (failures.length) {
126
+ console.log(`\nmost confident wrong answers (${failures.length}):`);
127
+ for (const f of failures) {
128
+ console.log(` ${f.requestId.slice(7, 19)} ${f.questionId}: said ` +
129
+ `${JSON.stringify(f.predicted)}, label ${JSON.stringify(f.label)}, ` +
130
+ `p=${f.probability.toFixed(3)}`);
131
+ }
132
+ }
133
+ }
134
+ }
135
+ if (minAccuracy !== null && suite.accuracy < minAccuracy) {
136
+ console.error(`jevkit-bench: accuracy ${suite.accuracy.toFixed(4)} below ${minAccuracy}`);
137
+ return EXIT_FAILED_GATE;
138
+ }
139
+ if (maxRegressions !== null && comparison && comparison.regressions.length > maxRegressions) {
140
+ console.error(`jevkit-bench: ${comparison.regressions.length} regressions exceed ${maxRegressions}`);
141
+ return EXIT_FAILED_GATE;
142
+ }
143
+ return EXIT_OK;
144
+ }
145
+ const invokedDirectly = process.argv[1] !== undefined && import.meta.url === `file://${process.argv[1]}`;
146
+ if (invokedDirectly)
147
+ process.exit(main());
148
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Score a labeled Jev suite for accuracy and cost, and compare runs.
3
+ *
4
+ * Answers the question you have to defend: for this task, on my data, is Jev
5
+ * good enough and what does it cost? Accuracy, tokens and dollars together,
6
+ * because any one of them alone is easy to win.
7
+ */
8
+ export { PRICE_PER_MTOK, SuiteComparison, SuiteResult, compareSuites, scoreRecords, type QuestionResult, type ScoreOptions, } from "./score.js";
9
+ export declare const VERSION = "0.1.0";
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACL,cAAc,EAAE,eAAe,EAAE,WAAW,EAAE,aAAa,EAAE,YAAY,EACzE,KAAK,cAAc,EAAE,KAAK,YAAY,GACvC,MAAM,YAAY,CAAC;AAEpB,eAAO,MAAM,OAAO,UAAU,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Score a labeled Jev suite for accuracy and cost, and compare runs.
3
+ *
4
+ * Answers the question you have to defend: for this task, on my data, is Jev
5
+ * good enough and what does it cost? Accuracy, tokens and dollars together,
6
+ * because any one of them alone is easy to win.
7
+ */
8
+ export { PRICE_PER_MTOK, SuiteComparison, SuiteResult, compareSuites, scoreRecords, } from "./score.js";
9
+ export const VERSION = "0.1.0";
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACL,cAAc,EAAE,eAAe,EAAE,WAAW,EAAE,aAAa,EAAE,YAAY,GAE1E,MAAM,YAAY,CAAC;AAEpB,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC"}
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Scoring a labeled `.jevl` suite, and comparing two runs of it.
3
+ *
4
+ * The question this answers is the one you actually have to defend: for this
5
+ * task, on my data, is Jev good enough, and what does it cost? That needs
6
+ * accuracy and cost together, because any one of them alone is easy to win.
7
+ *
8
+ * Costs come from a price per million input tokens, defaulting to Jev's
9
+ * published $0.042. Output tokens are free on Jev and are reported but never
10
+ * billed.
11
+ */
12
+ import { type Record as JevlRecord } from "jevkit-core";
13
+ export declare const PRICE_PER_MTOK = 0.042;
14
+ /** One scored question from one record. */
15
+ export interface QuestionResult {
16
+ requestId: string;
17
+ questionId: string;
18
+ type: string;
19
+ predicted: unknown;
20
+ label: unknown;
21
+ correct: boolean;
22
+ probability: number;
23
+ confidence: number | null;
24
+ tags: readonly string[];
25
+ }
26
+ /** Everything scored from one run of a suite. */
27
+ export declare class SuiteResult {
28
+ readonly pricePerMtok: number;
29
+ results: QuestionResult[];
30
+ inputTokens: number;
31
+ outputTokens: number;
32
+ records: number;
33
+ unlabeled: number;
34
+ models: Set<string>;
35
+ constructor(pricePerMtok?: number);
36
+ get count(): number;
37
+ get correct(): number;
38
+ get accuracy(): number;
39
+ /** Input-token cost in dollars. Jev bills input only. */
40
+ get cost(): number;
41
+ get costPerQuestion(): number;
42
+ /** tag -> [n, accuracy]. A result with several tags counts under each. */
43
+ byTag(): Record<string, [number, number]>;
44
+ /** question id -> [n, accuracy]. Finds the one question dragging the suite. */
45
+ byQuestion(): Record<string, [number, number]>;
46
+ /** Wrong answers, most confident first: the most interesting bugs. */
47
+ failures(): QuestionResult[];
48
+ summary(): string;
49
+ toJSON(): {
50
+ records: number;
51
+ unlabeled: number;
52
+ scored: number;
53
+ models: string[];
54
+ accuracy: number;
55
+ correct: number;
56
+ inputTokens: number;
57
+ outputTokens: number;
58
+ cost: number;
59
+ byTag: {
60
+ [k: string]: {
61
+ n: number;
62
+ accuracy: number;
63
+ };
64
+ };
65
+ byQuestion: {
66
+ [k: string]: {
67
+ n: number;
68
+ accuracy: number;
69
+ };
70
+ };
71
+ };
72
+ }
73
+ export interface ScoreOptions {
74
+ questionIds?: Iterable<string>;
75
+ pricePerMtok?: number;
76
+ }
77
+ /**
78
+ * Score every labeled answer in a suite.
79
+ *
80
+ * Records with no `label` are counted and skipped rather than silently dropped,
81
+ * so a suite that quietly lost its labels shows up in the summary instead of
82
+ * producing a suspiciously perfect score over three records.
83
+ */
84
+ export declare function scoreRecords(records: Iterable<JevlRecord>, options?: ScoreOptions): SuiteResult;
85
+ /** Two runs of the same suite, side by side. */
86
+ export declare class SuiteComparison {
87
+ readonly baseline: SuiteResult;
88
+ readonly candidate: SuiteResult;
89
+ readonly regressions: Array<[string, string]>;
90
+ readonly fixes: Array<[string, string]>;
91
+ constructor(baseline: SuiteResult, candidate: SuiteResult, regressions?: Array<[string, string]>, fixes?: Array<[string, string]>);
92
+ get accuracyDelta(): number;
93
+ get costDelta(): number;
94
+ summary(): string;
95
+ }
96
+ /**
97
+ * Compare two scored runs by (request, question).
98
+ *
99
+ * Aggregate accuracy can hold steady while the *set* of things you get right
100
+ * churns underneath, which matters when a specific case is the one you promised
101
+ * someone would work. Regressions and fixes are tracked individually for that
102
+ * reason.
103
+ */
104
+ export declare function compareSuites(baseline: SuiteResult, candidate: SuiteResult): SuiteComparison;
105
+ //# sourceMappingURL=score.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"score.d.ts","sourceRoot":"","sources":["../src/score.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,KAAK,MAAM,IAAI,UAAU,EAAgB,MAAM,aAAa,CAAC;AAEtE,eAAO,MAAM,cAAc,QAAQ,CAAC;AAEpC,2CAA2C;AAC3C,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;CACzB;AAED,iDAAiD;AACjD,qBAAa,WAAW;IAQV,QAAQ,CAAC,YAAY;IAPjC,OAAO,EAAE,cAAc,EAAE,CAAM;IAC/B,WAAW,SAAK;IAChB,YAAY,SAAK;IACjB,OAAO,SAAK;IACZ,SAAS,SAAK;IACd,MAAM,cAAqB;gBAEN,YAAY,SAAiB;IAElD,IAAI,KAAK,IAAI,MAAM,CAElB;IAED,IAAI,OAAO,IAAI,MAAM,CAEpB;IAED,IAAI,QAAQ,IAAI,MAAM,CAErB;IAED,yDAAyD;IACzD,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,IAAI,eAAe,IAAI,MAAM,CAE5B;IAED,0EAA0E;IAC1E,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAgBzC,+EAA+E;IAC/E,UAAU,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAc9C,sEAAsE;IACtE,QAAQ,IAAI,cAAc,EAAE;IAI5B,OAAO,IAAI,MAAM;IA6BjB,MAAM;;;;;;;;;;;;;;;;;;;;;;;CAiBP;AAED,MAAM,WAAW,YAAY;IAC3B,WAAW,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC/B,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,EAC7B,OAAO,GAAE,YAAiB,GACzB,WAAW,CAmCb;AAED,gDAAgD;AAChD,qBAAa,eAAe;IAExB,QAAQ,CAAC,QAAQ,EAAE,WAAW;IAC9B,QAAQ,CAAC,SAAS,EAAE,WAAW;IAC/B,QAAQ,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7C,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;gBAH9B,QAAQ,EAAE,WAAW,EACrB,SAAS,EAAE,WAAW,EACtB,WAAW,GAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAM,EACzC,KAAK,GAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAM;IAG9C,IAAI,aAAa,IAAI,MAAM,CAE1B;IAED,IAAI,SAAS,IAAI,MAAM,CAEtB;IAED,OAAO,IAAI,MAAM;CAWlB;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,WAAW,EAAE,SAAS,EAAE,WAAW,GAAG,eAAe,CAc5F"}
package/dist/score.js ADDED
@@ -0,0 +1,211 @@
1
+ /**
2
+ * Scoring a labeled `.jevl` suite, and comparing two runs of it.
3
+ *
4
+ * The question this answers is the one you actually have to defend: for this
5
+ * task, on my data, is Jev good enough, and what does it cost? That needs
6
+ * accuracy and cost together, because any one of them alone is easy to win.
7
+ *
8
+ * Costs come from a price per million input tokens, defaulting to Jev's
9
+ * published $0.042. Output tokens are free on Jev and are reported but never
10
+ * billed.
11
+ */
12
+ import { parseAnswers } from "jevkit-core";
13
+ export const PRICE_PER_MTOK = 0.042;
14
+ /** Everything scored from one run of a suite. */
15
+ export class SuiteResult {
16
+ pricePerMtok;
17
+ results = [];
18
+ inputTokens = 0;
19
+ outputTokens = 0;
20
+ records = 0;
21
+ unlabeled = 0;
22
+ models = new Set();
23
+ constructor(pricePerMtok = PRICE_PER_MTOK) {
24
+ this.pricePerMtok = pricePerMtok;
25
+ }
26
+ get count() {
27
+ return this.results.length;
28
+ }
29
+ get correct() {
30
+ return this.results.filter((r) => r.correct).length;
31
+ }
32
+ get accuracy() {
33
+ return this.count ? this.correct / this.count : 0;
34
+ }
35
+ /** Input-token cost in dollars. Jev bills input only. */
36
+ get cost() {
37
+ return (this.inputTokens / 1_000_000) * this.pricePerMtok;
38
+ }
39
+ get costPerQuestion() {
40
+ return this.count ? this.cost / this.count : 0;
41
+ }
42
+ /** tag -> [n, accuracy]. A result with several tags counts under each. */
43
+ byTag() {
44
+ const buckets = new Map();
45
+ for (const r of this.results) {
46
+ for (const tag of r.tags) {
47
+ if (!buckets.has(tag))
48
+ buckets.set(tag, []);
49
+ buckets.get(tag).push(r);
50
+ }
51
+ }
52
+ const out = {};
53
+ for (const tag of [...buckets.keys()].sort()) {
54
+ const rs = buckets.get(tag);
55
+ out[tag] = [rs.length, rs.filter((r) => r.correct).length / rs.length];
56
+ }
57
+ return out;
58
+ }
59
+ /** question id -> [n, accuracy]. Finds the one question dragging the suite. */
60
+ byQuestion() {
61
+ const buckets = new Map();
62
+ for (const r of this.results) {
63
+ if (!buckets.has(r.questionId))
64
+ buckets.set(r.questionId, []);
65
+ buckets.get(r.questionId).push(r);
66
+ }
67
+ const out = {};
68
+ for (const qid of [...buckets.keys()].sort()) {
69
+ const rs = buckets.get(qid);
70
+ out[qid] = [rs.length, rs.filter((r) => r.correct).length / rs.length];
71
+ }
72
+ return out;
73
+ }
74
+ /** Wrong answers, most confident first: the most interesting bugs. */
75
+ failures() {
76
+ return this.results.filter((r) => !r.correct).sort((a, b) => b.probability - a.probability);
77
+ }
78
+ summary() {
79
+ const lines = [
80
+ `records: ${this.records}` +
81
+ (this.unlabeled ? ` (${this.unlabeled} unlabeled, skipped)` : ""),
82
+ `scored: ${this.count} question(s)`,
83
+ `model(s): ${[...this.models].sort().join(", ") || "?"}`,
84
+ `accuracy: ${this.accuracy.toFixed(4)} (${this.correct}/${this.count})`,
85
+ `tokens: ${this.inputTokens.toLocaleString("en-US")} in, ` +
86
+ `${this.outputTokens.toLocaleString("en-US")} out (out is free)`,
87
+ `cost: $${this.cost.toFixed(6)} ($${this.costPerQuestion.toFixed(8)}/question ` +
88
+ `at $${this.pricePerMtok}/Mtok)`,
89
+ ];
90
+ const tags = this.byTag();
91
+ if (Object.keys(tags).length) {
92
+ lines.push("by tag:");
93
+ for (const [tag, [n, acc]] of Object.entries(tags)) {
94
+ lines.push(` ${tag.padEnd(24)} ${acc.toFixed(4)} (n=${n})`);
95
+ }
96
+ }
97
+ const questions = this.byQuestion();
98
+ if (Object.keys(questions).length > 1) {
99
+ lines.push("by question:");
100
+ for (const [qid, [n, acc]] of Object.entries(questions)) {
101
+ lines.push(` ${qid.padEnd(24)} ${acc.toFixed(4)} (n=${n})`);
102
+ }
103
+ }
104
+ return lines.join("\n");
105
+ }
106
+ toJSON() {
107
+ const mapped = (src) => Object.fromEntries(Object.entries(src).map(([k, [n, a]]) => [k, { n, accuracy: a }]));
108
+ return {
109
+ records: this.records,
110
+ unlabeled: this.unlabeled,
111
+ scored: this.count,
112
+ models: [...this.models].sort(),
113
+ accuracy: this.accuracy,
114
+ correct: this.correct,
115
+ inputTokens: this.inputTokens,
116
+ outputTokens: this.outputTokens,
117
+ cost: this.cost,
118
+ byTag: mapped(this.byTag()),
119
+ byQuestion: mapped(this.byQuestion()),
120
+ };
121
+ }
122
+ }
123
+ /**
124
+ * Score every labeled answer in a suite.
125
+ *
126
+ * Records with no `label` are counted and skipped rather than silently dropped,
127
+ * so a suite that quietly lost its labels shows up in the summary instead of
128
+ * producing a suspiciously perfect score over three records.
129
+ */
130
+ export function scoreRecords(records, options = {}) {
131
+ const wanted = options.questionIds ? new Set(options.questionIds) : null;
132
+ const suite = new SuiteResult(options.pricePerMtok ?? PRICE_PER_MTOK);
133
+ for (const record of records) {
134
+ suite.records += 1;
135
+ suite.models.add(record.model);
136
+ const usage = (record.usage ?? {});
137
+ suite.inputTokens += Number(usage["input_tokens"] ?? 0);
138
+ suite.outputTokens += Number(usage["output_tokens"] ?? 0);
139
+ if (!record.label || !Object.keys(record.label).length) {
140
+ suite.unlabeled += 1;
141
+ continue;
142
+ }
143
+ const answers = parseAnswers(record.answers);
144
+ for (const [qid, label] of Object.entries(record.label)) {
145
+ if (wanted && !wanted.has(qid))
146
+ continue;
147
+ const answer = answers[qid];
148
+ if (!answer)
149
+ continue;
150
+ suite.results.push({
151
+ requestId: record.requestId,
152
+ questionId: qid,
153
+ type: answer.type,
154
+ predicted: answer.predicted(),
155
+ label,
156
+ correct: answer.isCorrect(label),
157
+ probability: answer.topProbability,
158
+ confidence: answer.confidence,
159
+ tags: [...record.tags],
160
+ });
161
+ }
162
+ }
163
+ return suite;
164
+ }
165
+ /** Two runs of the same suite, side by side. */
166
+ export class SuiteComparison {
167
+ baseline;
168
+ candidate;
169
+ regressions;
170
+ fixes;
171
+ constructor(baseline, candidate, regressions = [], fixes = []) {
172
+ this.baseline = baseline;
173
+ this.candidate = candidate;
174
+ this.regressions = regressions;
175
+ this.fixes = fixes;
176
+ }
177
+ get accuracyDelta() {
178
+ return this.candidate.accuracy - this.baseline.accuracy;
179
+ }
180
+ get costDelta() {
181
+ return this.candidate.cost - this.baseline.cost;
182
+ }
183
+ summary() {
184
+ const sign = (n, digits) => `${n >= 0 ? "+" : ""}${n.toFixed(digits)}`;
185
+ return [
186
+ `accuracy: ${this.baseline.accuracy.toFixed(4)} -> ` +
187
+ `${this.candidate.accuracy.toFixed(4)} (${sign(this.accuracyDelta, 4)})`,
188
+ `cost: $${this.baseline.cost.toFixed(6)} -> ` +
189
+ `$${this.candidate.cost.toFixed(6)} (${sign(this.costDelta, 6)})`,
190
+ `regressed: ${this.regressions.length} (right before, wrong now)`,
191
+ `fixed: ${this.fixes.length} (wrong before, right now)`,
192
+ ].join("\n");
193
+ }
194
+ }
195
+ /**
196
+ * Compare two scored runs by (request, question).
197
+ *
198
+ * Aggregate accuracy can hold steady while the *set* of things you get right
199
+ * churns underneath, which matters when a specific case is the one you promised
200
+ * someone would work. Regressions and fixes are tracked individually for that
201
+ * reason.
202
+ */
203
+ export function compareSuites(baseline, candidate) {
204
+ const index = (suite) => new Map(suite.results.map((r) => [`${r.requestId}\u0000${r.questionId}`, r]));
205
+ const before = index(baseline);
206
+ const after = index(candidate);
207
+ const shared = [...before.keys()].filter((k) => after.has(k));
208
+ const split = (k) => k.split("\u0000");
209
+ return new SuiteComparison(baseline, candidate, shared.filter((k) => before.get(k).correct && !after.get(k).correct).sort().map(split), shared.filter((k) => !before.get(k).correct && after.get(k).correct).sort().map(split));
210
+ }
211
+ //# sourceMappingURL=score.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"score.js","sourceRoot":"","sources":["../src/score.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "jevkit-bench",
3
+ "version": "0.1.0",
4
+ "description": "Score a labeled TypeSafe Jev suite for accuracy and cost, and compare two runs. Catches regressions aggregate accuracy hides.",
5
+ "keywords": [
6
+ "jev",
7
+ "typesafe",
8
+ "system-one",
9
+ "benchmark",
10
+ "evaluation",
11
+ "accuracy",
12
+ "cost"
13
+ ],
14
+ "license": "MIT",
15
+ "type": "module",
16
+ "main": "./dist/index.js",
17
+ "types": "./dist/index.d.ts",
18
+ "exports": {
19
+ ".": {
20
+ "types": "./dist/index.d.ts",
21
+ "default": "./dist/index.js"
22
+ }
23
+ },
24
+ "bin": {
25
+ "jevkit-bench": "./dist/cli.js"
26
+ },
27
+ "files": [
28
+ "dist",
29
+ "README.md"
30
+ ],
31
+ "engines": {
32
+ "node": ">=18"
33
+ },
34
+ "repository": {
35
+ "type": "git",
36
+ "url": "git+https://github.com/pjdurden/jevkit-js.git"
37
+ },
38
+ "dependencies": {
39
+ "jevkit-core": "^0.2.0"
40
+ },
41
+ "scripts": {
42
+ "build": "tsc -b"
43
+ }
44
+ }