Repository navigation
evaluation-harness v0.3.0
Re-measure what you already have. Stored outputs can now be scored again by LLM judges, as an
optional pass that never touches a committed run: evh judge-score, for any text task you
declare (what an item is, what the outputs are, the dimensions, the scale). The harness refuses
a judge until the scorer names, for each judge, a committed run that measured it against human
ratings; it runs at least two judges from different vendors blind, measures their position bias
and noise, and stores every verdict so a rerun costs $0. The tutorial has an offline, $0
judging step (GUIDE step 10). Upgrading from 0.2.0 changes no committed run or score and adds
no dependency. Design: ADR-0001;
what it found here: the judging page.
Added
evh judge-score(andmake judge-score). Re-measure an experiment's frozen outputs
with a validated LLM judge, billed, cost-capped and resumable. It runs from the installed
package in a project that has only its own data directory, scorer, prompt and runs: the
prompt builder, reply parser, tau-b and Spearman, and an OpenAI-compatible judge client
(LiteLLM proxy, OpenRouter direct, per-judgebase_url/api_key_env, billed cost read
from the response, retries) are inevaluation_harness.judging, with no dependency on
examples/.- The judge scorer artifact (
data/scorers/<id>.yaml): two or more judges from different
vendor families, the task, the prompt (with its sha256), the protocol, avalidation
block and a cost cap. - Any text task, declared in the scorer. An optional
taskblock names what each item is
(source_label), what the arms wrote (output_label), thedimensionsthe judge scores
and thescale; a prompt writes{n}where the number of outputs per call goes. Without a
taskblock a scorer judges SummEval's news-summary task (ARTICLE, SUMMARIES, four
dimensions, 1-5), byte for byte as before. A declared task is hashed into the judging set. - A judging step in the tutorial (
docs/GUIDE.mdstep 10):
harness/tutorial/scorers/tickets-judge-v1.yamlre-measures the tutorial's arms with two
fake judges, offline and $0,
through the refusal, the dry run, the pass and the leaderboard. - A validation gate. A scorer runs only if its
validationblock names a committed run
for each judge whose metric equals the stated value (and is at leastmin_metric, when the
scorer sets one) and whose model, temperature, reasoning, provider, max tokens, prompt file
and prompt sha256 are the judge's. The gate checks that a validation exists and is current,
not that it transfers to your outputs. Otherwise--unvalidatedruns it and labels every number
"unvalidated judge".provider: fakejudges (offline, free, for testing a scorer) can never
pass the gate. - Judging sets and stored verdicts. One item is the article plus every arm's output, arm
identities hidden, order shuffled by a seed; the set is hashed into its id and frozen in
data/judging-sets/. Every reply is stored per call indata/judge-verdicts/, with its
scores, so a rerun resumes and re-reading costs $0; a reply that is not bare JSON scores, or
repeats 8 consecutive words of the item or an output, is kept only as its hash, since a
judge that reasons aloud can copy the source. A different arm set is a new set, never an
append. A block retried with--retry-unparsedkeeps the earlier calls' cost in its record. - Controls. A position check (a second shuffle that re-forms the blocks) and a noise check
(a repeat on a subset), plus per-judge agreement and a self-family flag, insummary.json. - Adjudicated gold re-measurement (repository tooling,
examples/_shared/adjudicate.py,
not in the package): a committed adjudication file overwrites only the disputed items of a
local gold reference set to make a new reference version, andrescorere-scores every run
against it for $0, the old reference kept beside it. - Judge validation on published human ratings (repository tooling, not in the package):
validate_judge_goyal.py(Goyal, Li & Durrett 2022) andvalidate_judge_zhang.py(Zhang et
al. 2024, crowd ratings of 19 LLM-era summarisers) check a scorer's judges against people.
The ratings are downloaded when the check runs, pinned by sha256, and never committed; the
committed records hold article ids, the judges' replies and scores, and hashes; a reply that
is not bare JSON scores, or repeats 8 consecutive words of the source, is kept only as its hash. validateV11-V13. V11: every judging set's stored hash is the hash of its content.
V12: every stored verdict names a real set, item, pass and block, and itsnis that
block's size, and every committed judge reply (verdicts and validation records) is bare
JSON or kept only as its hash. V13: every judge scorer loads, is structurally valid (itstaskincluded),
and its prompt file resolves and renders. They read the configured data directory.judge-scorejudges every arm on the dataset by default. A scorer'sarms_match,
--matchand--armsnarrow it, and it warns when the arm set mixes config versions (_v1
and_v2of one arm are judged as two arms).- A scorer's
prompt.fileresolves against the project root, then the scorer file's own
directory, then (in a checkout of this repository only) the repository root. - Judged runs carry no
reference_tier, since a judge reads no reference: the source
run's tier is kept asjudged_with.source_reference_tier, andleaderboardsays the scores
come from a judge, with its label. - A refused judge call stops the pass cleanly. A call refused, or still failing after its
retries (a provider's own budget guardrail answering 403, for example), stops the pass the
way the cost cap does: every stored verdict is kept, the partial result is projected and
labelled, and the same command resumes. - Scorer checks.
task.scalemust be whole numbers, and a prompt with both{n}and
SummEval's fixed count phrases is refused (the phrases would keep saying 16). V13 renders
each prompt at 2 outputs, so a prompt that cannot be rendered fails there, not at run time. - Experiment-level results this enables are reported in the repository's reports (the
summarisation experiment re-measured with two pairs of SummEval-validated judges, not confirmed by people on those outputs; AG News and DBpedia
against adjudicated gold); none of them is in the package.
Changed
leaderboard's precision note no longer fires on values that are exact small-integer
fractions (a mean of 1-5 ratings over two judges and four dimensions is in eighths); scores
rounded on the way to disk still get it.- Nothing that scores a run changed: committed runs and their recorded hashes are untouched,
and the committed summarisation judging set rebuilds from its stored verdicts with the same
id.
Install
pip install "evaluation-harness @ git+https://github.com/chipi/eval-harness@v0.3.0#subdirectory=harness"