seed: add the 20 metrics the every_eval_ever harness converters publish (+ inspect_ai harness) - #60
seed: add the 20 metrics the every_eval_ever harness converters publish (+ inspect_ai harness)#60borgr wants to merge 2 commits into
Conversation
7e3a4fc to
bba6f2a
Compare
The lm-evaluation-harness, HELM and Inspect converters in evaleval/every_eval_ever now emit a metric_id on every result. Resolving their 45 metric names against this registry left 22 with no entry. This closes 18 of them: 14 new metric entries and 4 aliases onto existing canonicals. Each entry's metadata.source is the upstream definition it was read off (HELM static/schema_*.yaml and its metric modules, lm-evaluation-harness api/metrics.py and api/task.py). cot-correct carried "COT correct" and "Equivalent (CoT)", which are the display names of two different HELM metrics — chain_of_thought_correctness and math_equiv_chain_of_thought. "Equivalent (CoT)" moves onto the new math-equivalent-chain-of-thought and cot-correct gains a metadata note saying which of the two it is. That is the only change to reviewed data and the only alias removed anywhere. brier-score is 0 to 2, not 0 to 1: lm-eval sums the squared error over every class, so all the mass on one wrong class scores 2.0. harnesses.yaml gains inspect_ai under the slug the converter already publishes as eval_library.name. eval_entity_resolver.eee._METRIC_KEYWORDS gains macro/micro F1 patterns above the generic \bf1\b, which otherwise matches inside both and made macro-f1 unreachable from an EEE metric name. Held back: chrf and ter pending evaleval#57 (sacrebleu scale), and ece / calibration_error, which HELM never emits bare — only ece_10_bin, ece_1_bin and their platt_ variants.
chrf is [0, 1] like the chrf-plus-plus and bleu entries; ter is [0.0, null] like wer and cer, and lower_is_better because it is an edit rate. evaleval#57 asks whether sacrebleu-scaled metrics belong here as 0-100 or 0-1. It is a question about scale, not direction, and these two follow the convention their siblings already use, so they move with the family whichever way it is answered rather than becoming a third convention. curation/UPSTREAM_DATA_ISSUES.md gains an lm-evaluation-harness section for the two upstream defects the sourcing turned up: ter registered higher_is_better=True against its own "Lower is better" docstring, and chrf documented as chrF++ while calling sacrebleu with word_order=0, which is chrF.
bba6f2a to
ac8af15
Compare
|
Rebased onto
All 38 gate invariants and the seed suite pass locally on a clean fixture rebuild. The |
What / why
evaleval/every_eval_ever's three harness converters (lm-evaluation-harness, HELM, Inspect) now publish ametric_idon every result so a consumer can join the same metric across sources. Resolving their metric names against this registry at8b83e9cleft 22 of 45 with no entry, so they ship as<harness>.<name>— a stable join key inside one harness and no global identity. This PR closes 20 of those 22.Everything here is a metric one of those converters publishes today. Each entry's
metadata.sourceis the upstream definition it was read off — HELM'sstatic/schema_*.yamland metric modules, lm-evaluation-harness'sapi/metrics.py/api/task.py, sacrebleu's metric classes — and nothing was added because it looked like a plausible spelling.16 new metrics
quasi-exact-matchexact-matchon the same runschema_classic.yamlprefix-exact-matchexact-matchschema_classic.yamlquasi-prefix-exact-matchschema_classic.yamlmicro-f1f1for the same reasonmacro-f1already isclassification_metrics.py,schema_classic.yamlmath-equivalentschema_classic.yamlmath-equivalent-chain-of-thoughtschema_lite.yaml,schema_classic.yamlifeval-strict-accuracyschema_capabilities.yaml,ifeval_metrics.pylength-normalized-accuracyacc_norm: argmax overloglikelihood / len(choice), a different argmax fromaccapi/task.pybrier-scoreapi/task.pybits-per-byteapi/metrics.pyword-perplexityexp(-weighted_mean(logprob))normalized by wordsapi/metrics.pybyte-perplexityperplexityapi/metrics.pyrouge-lsumrouge-lon the same pairrouge_scoreviaevaluatetruthfulqa-mc1truthfulqa-mc2entry, which had no MC1 counterpartmc1chrfchrf-plus-plus— sacrebleu is chrF++ only atword_order=2(see below)sacrebleu.CHRFviaapi/metrics.pyterlower_is_better: true, no ceilingsacrebleu.TERviaapi/metrics.pybrier-scoreis 0 to 2, not 0 to 1. lm-eval computesmean(sum((softmax(loglikelihoods) - one_hot(gold)) ** 2)), so a model putting all its mass on one wrong class scores 2.0. The two-class definition people usually quote maxes at 1.0. A[0, 1]bound here makes a legitimate score look out of range.Four carry
max_score: nullbecause they have no upper bound:bits-per-byte(from 0.0),word-perplexity/byte-perplexity(from 1.0, the perplexity of a perfect predictor), andter(from 0.0 — a hypothesis can need more edits than the reference has words).nullis the spelling every unbounded entry inseed/metrics.yamluses today. #49 proposes replacing it with.infand reservingnullfor a genuinely-undefined bound; these four are exactly its "unbounded above" species, so whichever way that goes they should move with the rest. I keptmain's spelling here rather than pre-applying an unmerged proposal — happy to flip them in either PR, whichever a maintainer prefers.chrfandter: why they are here and not waiting on #57I said on #57 I would hold these until the sacrebleu scale question was settled. That was the wrong call and I have sent them: #57 is about scale, not identity or direction, and neither entry needs #57 answered to be correct.
chrftakes[0, 1], the bounds the existingchrf-plus-plusandbleuentries already use.tertakes[0.0, null], the bounds the existingwerandcerentries already use.So each one follows the convention its own siblings follow. If #57 lands on 0–100, it moves the whole sacrebleu family together; holding these two out would only have created a third convention in the meantime. Both
metadata.scalefields say sacrebleu reports ×100 and point at #57, so nothing here is silently assuming an answer.Two things the sourcing turned up, both verified against lm-evaluation-harness at
mainrather than inferred, and both now recorded incuration/UPSTREAM_DATA_ISSUES.md:ter— lm-eval registers the direction backwards.lm_eval/api/metrics.pyhas@register_metric(metric="ter", higher_is_better=True)while the aggregation it registers says "Lower is better" in its own docstring and computessacrebleu.corpus_ter. This is not a display hint:higher_is_betterreachesis_higher_better()(api/registry.py) →Task.higher_is_better(), which lm-eval writes into its results JSON. The same registration table is correct (False) forperplexity,word_perplexity,byte_perplexity,bits_per_byteandbrier_score, soteris the lone inverted entry rather than a convention I am misreading. This registry stateslower_is_better: true— the metric definition wins over one harness's registration.chrfis documented as chrF++ but computes chrF. lm-eval's docstring for the metric calls it "chrF++" and links the chrF++ paper; the function callssacrebleu.corpus_chrf(preds, refs)with the defaults, andsacrebleu.CHRF.WORD_ORDER = 0— chrF++ isword_order=2. Different numbers on the same run, which is why this entry ischrfand not an alias ontochrf-plus-plus. The entry'smetadata.noterecords the mislabel so a future contributor doesn't merge them back.Neither is a data defect this registry corrects for other people, so
UPSTREAM_DATA_ISSUES.mdcarries both with Action: flag to the lm-evaluation-harness maintainers, matching that file's existing shape, and says to delete each entry once upstream lands the fix.4 aliases onto existing entries
macro-f1classification_macro_f1matthews-correlationmcccot-correctchain_of_thought_correctnessdisplay_nameis this entry's "COT correct"truthfulqa-mc2mc2One correction to a
reviewedentry — please look at this onecot-correctcarried two aliases,"COT correct"and"Equivalent (CoT)". Those are the display names of two different HELM metrics:chain_of_thought_correctness→display_name: COT correct(schema_capabilities.yaml) — "Fraction of correct answers after chain of thought"math_equiv_chain_of_thought→display_name: Equivalent (CoT)(schema_lite.yaml) — mathematical equivalence under CoT promptingThey were merged by a display-name scrape.
"Equivalent (CoT)"moves offcot-correctonto the newmath-equivalent-chain-of-thought, andcot-correctgains ametadata.notesaying which of the two it is so it does not drift back. This is the only change to existing reviewed data, and it is the only alias this PR removes from anywhere.I checked the move against the publish path rather than assuming: seeding without
--prune-staleover the pre-change fixtures rewrites that alias row'scanonical_idin place rather than leaving a second row, and afterwards 0 metric surfaces resolve to more than one canonical id (30,487 alias rows checked).One code change
packages/eval-entity-resolver/src/eval_entity_resolver/eee.py—_METRIC_KEYWORDSgainsmacro[\s_-]*f1andmicro[\s_-]*f1above the generic\bf1\b.Without them the generic pattern matches inside both, so
extract_metric("Micro F1") == "F1": the newmicro-f1entry would be unreachable from an EEE metric name, andmacro-f1already was. This is the same "compound before generic" shape the table already uses forast[\s_-]*accuracybefore\baccuracy\b.extract_metric("Tokenized F1")still returns"F1". Covered bytest_class_averaged_f1_distinct_from_f1.The comment two functions up used
"Equivalent (CoT)" → cot-correctas its worked example; it now names the entry that alias actually resolves to.2 names deliberately held back
eceandcalibration_error— HELM never emits either bare name. It emitsece_10_bin,ece_1_bin,platt_ece_10_bin,platt_ece_1_bin(basic_metrics.py::compute_calibration_metrics), and lm-evaluation-harness has no ECE at all. A genericeceentry would be an entry nothing resolves to, and a bareecealias would have to swallowece_10_binand throw away the bin count — a 10-bin and a 1-bin ECE are not the same number on the same run.That is a slug-family question the registry has to take a position on, the same species as HELM's
@kmetrics whichpass-at-1/recall-at-5answer one way, so it is #61 rather than a guess in a seed PR. I will send the four calibration entries with the same sourcing as this PR once #61 has an answer.Verification
Cross-checked from the consumer side with
every_eval_ever'stools/verify_metric_ids.pyagainst this branch's seed: 20 of the 22 namespaced names now resolve, one per entry/alias above, with 0 ambiguous, and the 2 that remain are exactly the 2 held back.seed/harnesses.yaml:inspect_aiThe Inspect converter publishes
inspect_aiaseval_library.nameand this registry carried no Inspect entry, so that harness slug did not resolve. Added asdraftunder the name the converter already emits, so the id it publishes and the id here agree without a migration.Notes for review
review_status: draft.score_type: continuousthroughout, matching all 400 existing entries.brier_scorefolds ontobrier-scoreanyway), so a maintainer can find the entry by the string their tool printed.short_display_namesEMandPEM. It reusesEMfor bothexact_matchandquasi_exact_match, andPEMfor both prefix variants, so either would resolve one metric's abbreviation to the other's entry.EMalready belongs toexact-matchhere and stays there.truthfulqa-mc1iskind: dataset_specific, like thetruthfulqa-mc2entry it mirrors: a consumer joining on it is joining within TruthfulQA, not across every benchmark that ever called something "MC1".every_eval_everbumps its pinned revision and moves these 20 from<harness>.<name>to the canonical ids in a follow-up PR. Records already published under the namespaced form need remapping, which is why that is a separate change with its own review.Pre-PR checklist
uv run eval-card-registry seed --local --prune-stalesucceeds from a clean fixture stateuv run pytestgreen from a clean tree on this branch (818 passed)