Skip to content

Commit f017442

Browse files
Count non-binding budgets correctly in published results (#14)
1 parent c42df67 commit f017442

3 files changed

Lines changed: 136 additions & 57 deletions

File tree

site/attempt-outcome.ts

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import type { AttemptAnalysisRow } from "../src/export/analysis.ts";
2+
3+
export type PublicAttemptOutcome =
4+
| "accepted"
5+
| "quality_failed"
6+
| "abstained"
7+
| "generation_failed"
8+
| "budget_exceeded"
9+
| "budget_unverifiable"
10+
| "infrastructure_failed"
11+
| "not_started";
12+
13+
export interface PublicAttemptClassificationInput {
14+
generation_state: string;
15+
generation_outcome: string | null;
16+
evaluation_status: string | null;
17+
evaluator_strict_success: boolean | null;
18+
strict_success: boolean | null;
19+
generation_budget_status: AttemptAnalysisRow["generation_budget_status"];
20+
}
21+
22+
export function classifyPublicOutcome(
23+
attempt: PublicAttemptClassificationInput,
24+
): PublicAttemptOutcome {
25+
if (attempt.generation_state === "planned") {
26+
return "not_started";
27+
}
28+
const generated =
29+
attempt.generation_state === "completed" && attempt.generation_outcome === "succeeded";
30+
if (attempt.generation_state === "completed" && attempt.generation_outcome === "abstained") {
31+
return "abstained";
32+
}
33+
if (attempt.generation_outcome === "infra_failed") {
34+
return "infrastructure_failed";
35+
}
36+
if (attempt.generation_state === "completed" && attempt.generation_outcome !== "succeeded") {
37+
return "generation_failed";
38+
}
39+
if (generated && attempt.generation_budget_status === "exceeded") {
40+
return "budget_exceeded";
41+
}
42+
if (generated && attempt.generation_budget_status === "unverifiable") {
43+
return "budget_unverifiable";
44+
}
45+
const evaluatorStrictSuccess = attempt.evaluator_strict_success ?? attempt.strict_success;
46+
if (
47+
generated &&
48+
(attempt.generation_budget_status === "compliant" ||
49+
attempt.generation_budget_status === "non_binding") &&
50+
attempt.evaluation_status === "succeeded" &&
51+
evaluatorStrictSuccess === true
52+
) {
53+
return "accepted";
54+
}
55+
if (
56+
generated &&
57+
attempt.evaluation_status === "quality_failed" &&
58+
evaluatorStrictSuccess === false
59+
) {
60+
return "quality_failed";
61+
}
62+
return "infrastructure_failed";
63+
}

site/publish.ts

Lines changed: 8 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -4,25 +4,24 @@ import { canonicalJson, sha256 } from "../src/core/canonical.ts";
44
import { toCsv, toJsonLines } from "../src/export/serialize.ts";
55
import { verifyRelease } from "../src/export/verify.ts";
66
import { assignApproachColors } from "./approach-colors.ts";
7+
import {
8+
classifyPublicOutcome,
9+
type PublicAttemptClassificationInput,
10+
type PublicAttemptOutcome,
11+
} from "./attempt-outcome.ts";
712
import { buildStaticSite } from "./build.ts";
813
import {
914
type FormalReleaseStatus,
1015
formalReleaseDesignationSchema,
1116
publicReleaseSchema,
1217
} from "./contracts.ts";
1318

14-
interface FormalAttempt {
19+
interface FormalAttempt extends PublicAttemptClassificationInput {
1520
attempt_id: string;
1621
case_id: string;
1722
system_id: string;
1823
replicate: number;
19-
generation_state: string;
20-
generation_outcome: string | null;
2124
generation_error: string | null;
22-
evaluation_status: string | null;
23-
evaluator_strict_success: boolean | null;
24-
strict_success: boolean | null;
25-
generation_budget_status: "compliant" | "exceeded" | "unverifiable" | null;
2625
evaluation_failure: string | null;
2726
generation_duration_ms: number | null;
2827
cost_amount: number | null;
@@ -35,15 +34,7 @@ interface PublicAttempt {
3534
system_id: string;
3635
replicate: number;
3736
lifecycle: string;
38-
outcome:
39-
| "accepted"
40-
| "quality_failed"
41-
| "abstained"
42-
| "generation_failed"
43-
| "budget_exceeded"
44-
| "budget_unverifiable"
45-
| "infrastructure_failed"
46-
| "not_started";
37+
outcome: PublicAttemptOutcome;
4738
strict_accepted: boolean | null;
4839
evaluator_strict_accepted?: boolean | null;
4940
generation_completed: boolean;
@@ -96,46 +87,6 @@ async function readJson<T>(path: string): Promise<T> {
9687
return JSON.parse(await readFile(path, "utf8")) as T;
9788
}
9889

99-
function disposition(attempt: FormalAttempt): PublicAttempt["outcome"] {
100-
if (attempt.generation_state === "planned") {
101-
return "not_started";
102-
}
103-
const generated =
104-
attempt.generation_state === "completed" && attempt.generation_outcome === "succeeded";
105-
if (attempt.generation_state === "completed" && attempt.generation_outcome === "abstained") {
106-
return "abstained";
107-
}
108-
if (attempt.generation_outcome === "infra_failed") {
109-
return "infrastructure_failed";
110-
}
111-
if (attempt.generation_state === "completed" && attempt.generation_outcome !== "succeeded") {
112-
return "generation_failed";
113-
}
114-
if (generated && attempt.generation_budget_status === "exceeded") {
115-
return "budget_exceeded";
116-
}
117-
if (generated && attempt.generation_budget_status === "unverifiable") {
118-
return "budget_unverifiable";
119-
}
120-
const evaluatorStrictSuccess = attempt.evaluator_strict_success ?? attempt.strict_success;
121-
if (
122-
generated &&
123-
attempt.generation_budget_status === "compliant" &&
124-
attempt.evaluation_status === "succeeded" &&
125-
evaluatorStrictSuccess === true
126-
) {
127-
return "accepted";
128-
}
129-
if (
130-
generated &&
131-
attempt.evaluation_status === "quality_failed" &&
132-
evaluatorStrictSuccess === false
133-
) {
134-
return "quality_failed";
135-
}
136-
return "infrastructure_failed";
137-
}
138-
13990
function strictValue(outcome: PublicAttempt["outcome"]): boolean | null {
14091
if (outcome === "accepted") {
14192
return true;
@@ -235,7 +186,7 @@ export async function publishSite(options: {
235186
await readFile(join(releaseDirectory, "data", "attempts.jsonl"), "utf8"),
236187
);
237188
const publicAttempts: PublicAttempt[] = attempts.map((attempt) => {
238-
const outcome = disposition(attempt);
189+
const outcome = classifyPublicOutcome(attempt);
239190
const costUsd =
240191
attempt.generation_state === "planned"
241192
? 0

tests/site-publish.test.ts

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import { describe, expect, test } from "bun:test";
2+
import {
3+
classifyPublicOutcome,
4+
type PublicAttemptClassificationInput,
5+
type PublicAttemptOutcome,
6+
} from "../site/attempt-outcome.ts";
7+
8+
const successfulAttempt: PublicAttemptClassificationInput = {
9+
generation_state: "completed",
10+
generation_outcome: "succeeded",
11+
evaluation_status: "succeeded",
12+
evaluator_strict_success: true,
13+
strict_success: true,
14+
generation_budget_status: "compliant",
15+
};
16+
17+
describe("public attempt classification", () => {
18+
test.each(["compliant", "non_binding"] as const)(
19+
"accepts a successful evaluation with a %s generation budget",
20+
(generationBudgetStatus) => {
21+
expect(
22+
classifyPublicOutcome({
23+
...successfulAttempt,
24+
generation_budget_status: generationBudgetStatus,
25+
}),
26+
).toBe("accepted");
27+
},
28+
);
29+
30+
test("falls back to the release strict-success field", () => {
31+
expect(classifyPublicOutcome({ ...successfulAttempt, evaluator_strict_success: null })).toBe(
32+
"accepted",
33+
);
34+
});
35+
36+
test.each([
37+
[{ generation_state: "planned" }, "not_started"],
38+
[{ generation_outcome: "abstained" }, "abstained"],
39+
[{ generation_outcome: "infra_failed" }, "infrastructure_failed"],
40+
[{ generation_outcome: "failed" }, "generation_failed"],
41+
[{ generation_budget_status: "exceeded" }, "budget_exceeded"],
42+
[{ generation_budget_status: "unverifiable" }, "budget_unverifiable"],
43+
[
44+
{
45+
evaluation_status: "quality_failed",
46+
evaluator_strict_success: false,
47+
strict_success: false,
48+
},
49+
"quality_failed",
50+
],
51+
[
52+
{
53+
evaluation_status: null,
54+
evaluator_strict_success: null,
55+
strict_success: null,
56+
},
57+
"infrastructure_failed",
58+
],
59+
] satisfies Array<[Partial<PublicAttemptClassificationInput>, PublicAttemptOutcome]>)(
60+
"classifies %j as %s",
61+
(overrides, expected) => {
62+
expect(classifyPublicOutcome({ ...successfulAttempt, ...overrides })).toBe(expected);
63+
},
64+
);
65+
});

0 commit comments

Comments
 (0)