eval: run the judged gold set, and meter what synthesis actually costs - #32
Merged
Conversation
Squashed base for the gold runner: carries the gold set + loader and the per-claim judge, unchanged from their own branches.
Wires the gold set and the judge into a run: same index, same server, one judged blob. Kept separate from the retrieval runner on purpose - a retrieval run is free and repeatable, a judged one costs two model calls per question, and merging them would make the cheap measurement expensive. Three things the blob carries that a correctness number alone would hide. Correctness broken down by the confidence the tool claimed, because confidence is a promise that verification is unnecessary and only the breakdown says whether it is kept. Contradictions at high confidence counted on their own, because a confident wrong mechanism and a thin honest answer both score badly and are not the same problem. And whether an expected page reached the caller at all, which separates a retrieval miss from synthesis getting it wrong - opposite fixes. The answer tool has no token accounting of its own, so synthesis spend is metered from outside by wrapping the provider the registry hands back. Two ways that could quietly report nothing are refused rather than reported: a run that answered questions while metering zero calls, and a model the price table does not know, which would otherwise cost exactly zero per question. The figure is named tool_side_usd_per_question because it is not the cache-neutral cost a caller pays - that is an agent-side quantity a different harness measures, and the two must not be read as one number.
|
✅ Health: 9.9 (unchanged) 📋 At a glance 🚨 Change risk: high (riskier than 84% of this repo's commits)
🔎 More signals (1)🔥 Hotspot touched (1)
📊 Full report · ⭐ Star Repowise · 📥 Install bot · Last updated 2026-07-29 17:53 UTC |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Wires the gold set and the judge into a run:
python -m answer_eval --gold --index <id> --checkout <tree> --commit <sha>. Same index, same server, one judged blob.Deliberately a separate runner from the retrieval one. A retrieval run is free and repeatable; a judged run costs two model calls per question. Merging them would make the cheap measurement expensive.
What the blob carries that a correctness number would hide
correctness_by_confidence— the tool's confidence is a promise to the caller that verification is unnecessary. A single number cannot say whether it is kept; only the breakdown can.n_contradicted_at_high— a confident wrong mechanism and a thin-but-honest answer both score badly, and only this separates them. They need opposite fixes.found_expected_pathper question — separates "retrieval missed it" from "retrieval found it and synthesis got it wrong". Recorded, never scored: a right answer citing an unexpected page is still right.Metering the tool's own spend
The answer tool has no token accounting — nothing captures
usage, no cost row is written anywhere, and every cost figure quoted about it so far is inferred from the agent side.token_meterwraps the provider the registry hands back for the length of a run and adds up what it reports, priced from the product's own table so an eval figure and a product figure cannot drift apart.Two ways that could quietly report nothing are refused rather than reported: a run that answered questions while metering zero calls (which would mean the tool stopped resolving through the registry, and every cost is silently $0.00), and a model the price table does not know (same result, different cause). A genuinely free provider is still allowed to cost zero.
The field is
tool_side_usd_per_questionand not$/q, because it is not the cache-neutral cost a caller pays — that is an agent-side quantity a different harness measures, and the two must not be read as one number.Tests
27 new, both the tool and the judge stubbed: the correctness mean, the answer text kept next to its verdict, an abstention recorded as such, the confidence breakdown, a contradiction at high counted on its own and warned about as it happens, retrieval recorded-but-not-scored, cost per question from a metered run,
Nonerather than0.0from an unmetered one, judge tokens reported separately, and the empty-set / non-dict / symbol-less-index / same-family-judge cases.The meter's own: totals across calls, a response with no usage counting as zero rather than crashing, cost from the price table, an unpriced model raising, a free provider costing zero without raising, the registry restored afterwards, double-wrapping not double-counting, metering nothing raising, and a multi-model meter warning.
python -m pytest tests/test_answer_eval_*.py→ 206 passed.First run
correctness=0.414 · fully-correct 2/22 · contradicted 0 · by confidence {high 0.35, low 0.75, medium 0.55} · tool-side $0.0012/qI read the zero-scoring answers by hand before trusting the judge, and it errs generous rather than pedantic. Findings are in the plan's log, not here.