mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-10 05:12:14 +00:00
test(coach): put the dialog scenarios to a real model nightly
The live evaluation now captures the tool calls a generation makes, with their arguments, and hands them to the judge. runScenarioLive puts a scenario to the model in the chat turn's own context (system prompt, tool-mode and dialog addenda, DATA INVENTORY, EARLIER TABLES, transcript) over the real tool catalogue, answers each call with a stand-in result, and reads the reply through the turn's clarification and chip parsers. runScenarioJudge grades each scenario a few times with the same evaluateScenario the deterministic suite uses and reports a pass rate per scenario; the server-only scenarios and checks are left out. Like the existing judge it runs only with COACH_EVAL_API_KEY, from the nightly workflow's non-blocking step, and never throws.
This commit is contained in:
1 parent
ec281c02e2
commit
c2ab9cda11
6 files changed
+651
-8
No files matched your search
@@ -10,7 +10,10 @@
|
||||
* summary for the nightly log.
|
||||
* 2. The LIVE JUDGE runs ONLY when `COACH_EVAL_API_KEY` is present. With the
|
||||
* secret absent it no-ops with a clear line and exits 0 — the nightly
|
||||
* workflow stays green and non-blocking.
|
||||
* workflow stays green and non-blocking. The same key runs the dialog
|
||||
* scenarios live: each is put to the model a few times and the tool
|
||||
* calls (with their arguments) are graded, reported as a pass rate per
|
||||
* scenario.
|
||||
*
|
||||
* Usage (nightly workflow / manual):
|
||||
* COACH_EVAL_API_KEY=... pnpm dlx tsx scripts/run-coach-eval.ts
|
||||
@@ -22,7 +25,7 @@ import {
|
||||
} from "@/lib/ai/coach/eval/golden-cases";
|
||||
import { captureDeterministic } from "@/lib/ai/coach/eval/run-case";
|
||||
import { gradeSet } from "@/lib/ai/coach/eval/grade-groundedness";
|
||||
import { runJudge } from "@/lib/ai/coach/eval/judge";
|
||||
import { runJudge, runScenarioJudge } from "@/lib/ai/coach/eval/judge";
|
||||
|
||||
async function main() {
|
||||
// Deterministic summary (the gate itself is the Vitest suite).
|
||||
@@ -57,6 +60,26 @@ async function main() {
|
||||
);
|
||||
}
|
||||
}
|
||||
await reportScenarios();
|
||||
}
|
||||
|
||||
/** The dialog scenarios, live: a pass rate per scenario, misses listed. */
|
||||
async function reportScenarios() {
|
||||
const run = await runScenarioJudge();
|
||||
console.log(run.note);
|
||||
for (const scenario of run.scenarios) {
|
||||
console.log(
|
||||
` ${scenario.passRate === 1 ? "PASS" : "MISS"} ${scenario.id} ${scenario.passed}/${scenario.runs}`,
|
||||
);
|
||||
scenario.misses.forEach((missed, i) => {
|
||||
console.log(` run ${i + 1}: ${missed.join("; ")}`);
|
||||
});
|
||||
scenario.toolCalls.forEach((calls, i) => {
|
||||
console.log(
|
||||
` calls ${i + 1}: ${calls.map((c) => `${c.name}(${JSON.stringify(c.args)})`).join(", ") || "none"}`,
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
|
||||
Reference in new issue
Block a user