Source: services/ratings/METHODOLOGY.md, shipped with humaneval-ratings 1.1.0. Section numbers below are the document's own.
Rating methodology — humaneval-ratings v1
Normative description of the mathematics implemented by this package. The public methodology page is derived from this file. Input/output formats are specified in DUMP_FORMAT.md. Every choice below is deliberate and fixed; changing any of it is a methodology version change and will be announced in the ranking changelog.
1. Model: Bradley-Terry maximum likelihood, per category
Ratings are computed independently per category from that
category's eligible votes. We fit a Bradley-Terry model: each model
i has a latent strength theta_i, and the probability that model
i beats model j is
P(i beats j) = sigma(theta_i - theta_j), sigma(x) = 1/(1+e^{-x})
This is a maximum-likelihood fit on the whole vote set at once — NOT sequential Elo. Order of votes does not matter; there is no recency weighting in v1. Slot randomization is handled upstream by the platform; the model contains no slot/position term in v1 (the raw fit), while the style-controlled fit (§7) absorbs presentation differences.
Only models that appear in at least one eligible vote's battle in the category are fitted there. A model can appear (and be rated) in several categories independently.
2. Ties
A tie vote of weight w is treated as half a win and half a loss for
both sides (LMArena-style): it contributes an event "A beats B" with
weight w/2 and an event "B beats A" with weight w/2 to the
likelihood. Ties therefore pull the two models' ratings together and
still count toward vote totals at full weight w.
3. Vote weights
Every vote carries an effective weight weight > 0 from the dump
(DUMP_FORMAT.md §4.2). The log-likelihood is weight-weighted:
L(theta) = sum over events w_e * log sigma(delta_e)
where delta_e is the winner-minus-loser strength difference of event
e. A vote with weight 0.25 moves the ratings a quarter as much as a
full vote. vote_count in the output is the unweighted record
count (transparency: how many humans voted), while the fit uses
weights.
4. Anchor and scale
The natural-parameter fit is converted to displayed ratings as
rating_i = 1000 + (400 / ln 10) * (theta_i - mean(theta))
- Center: the unweighted arithmetic mean of the fitted strengths of
the category's non-provisional models (vote_count >=
--min-votes, determined once from the full data) is anchored at 1000; when no model qualifies, the mean of all models is used. Anchoring on the non-provisional set matters for the bootstrap: a provisional model with a handful of votes can hit perfect separation in a resample and blow up, and with an all-model anchor that explosion would shift the center and contaminate every model's confidence interval. The anchor set is fixed across bootstrap rounds. The anchor is per category and per snapshot; ratings are not comparable across categories. - Scale:
400 / ln 10 ≈ 173.7178rating points per natural-log unit. This makes the scale Elo-equivalent: a 400-point gap means 10:1 expected odds, exactly as in classical Elo (P = 1/(1+10^{-(R_a-R_b)/400})).
5. Regularization, existence, uniqueness
A small L2 (ridge) penalty is applied to make the optimum exist and be unique even under perfect separation (a model with only wins) or a disconnected comparison graph:
objective = L(theta) - (lambda/2) * ||theta||^2,
lambda = 1e-6 * (total vote weight entering the fit)
(for the full fit that is the category's total vote weight; for a bootstrap round it is the resample's total weight).
Scaling lambda with total weight makes the fit invariant to
multiplying all weights by a constant, and keeps the relative bias at
the 1e-6 level — far below bootstrap CI widths. In the style-controlled
fit the same lambda also penalizes the style coefficients.
If the comparison graph is disconnected, the ridge yields finite numbers but strengths across components are only weakly identified; the platform's pairing keeps the graph connected in practice, and the huge bootstrap CIs such models get are the honest signal.
Optimization: Newton-Raphson on the penalized objective (strictly
concave, so the optimum is unique and start-point independent), from
theta = 0, until the max absolute Newton step is < 1e-10 (cap 100
iterations). The Hessian solve is a small dense numpy.linalg.solve
(dimension = number of models + 4 covariates at most); no scipy needed.
6. Uncertainty: bootstrap CIs and rank bands
Point estimates are the fit on the full vote set. Uncertainty comes
from a case bootstrap on votes: each of --bootstrap-rounds
(default 100) rounds draws N votes uniformly with replacement from
the category's N vote records (each keeping its weight) and refits both
the raw and the style-controlled model on the resample. A model can
lose all its votes in a resample; its strength then falls back toward
the ridge prior for that round — widening its CI, which is the honest
outcome.
ci_low/ci_high are the 2.5th and 97.5th percentiles of the
bootstrapped rating (numpy percentile, method="linear"), i.e. a 95%
percentile interval. Same for the _sc fields from the same resamples.
Provisional: a model with vote_count < --min-votes (default
30) is flagged provisional: true. It keeps its rating estimate,
CI and order, but gets rank: null — no rank number is displayed.
Rank bands: computed over non-provisional models only, in leaderboard
order (published rating descending, ties by slug), using the
published (4-decimal-rounded) CI bounds so bands are verifiable from
leaderboard.json alone:
- The first rated model gets
rank = 1. - Each next rated model at position
p(1-based among rated models) gets the same rank as the model immediately above it if their CIs overlap (closed intervals:ci_high >= above.ci_lowandci_low <= above.ci_high); otherwise it starts a new band withrank = p(competition numbering — after two models share rank 1, the next distinct band is rank 3).
The chain rule means a band extends while each member overlaps its
immediate predecessor. order (the plain sort position, all models
including provisional) is emitted alongside rank.
Canonical rank/order come from the raw ratings; the analytics
site may re-sort by style-controlled values client-side, but the
published band structure is raw-based.
7. Style control
Votes reward presentation as well as substance. To separate the two we also fit an extended Bradley-Terry model with shared style covariates (Arena-style contestant-difference features):
P(A beats B) = sigma(theta_A - theta_B + beta . z)
where z is the battle's style-difference feature vector and beta is
shared across all models in the category. The style-controlled rating
is theta from this joint fit (anchored and scaled as in §4): it is
the estimate of model strength with presentation differences held
constant. Both raw and style-controlled ratings are always published.
7.1 Features (computed per response text)
Deterministic heuristics on the exact response_* strings from the
dump (normative definitions — they matter for reproducibility):
| Feature | Definition |
|---|---|
length_chars | Number of Unicode code points in the text |
markdown_density | (count of characters in the set ` * _ # ~ > |) / max(1, length_chars) — a simple, deterministic proxy for formatting-character density, not a Markdown parser |
list_count | Number of lines matching `^\s*(?:[-*+] |
header_count | Number of lines matching ^ {0,3}#{1,6}\s (ATX headings) |
7.2 Per-battle covariates
For each battle, each feature f becomes a normalized difference
d = (f_A - f_B) / (f_A + f_B) (0 when the denominator is 0)
so z is bounded in [-1, 1] and scale-free. Each of the four d
components is then standardized to zero mean / unit variance across the
category's votes (each vote contributes its battle's d once;
population std, ddof = 0). A component with zero variance is dropped
(kept at 0). Standardization parameters are computed once on the full
vote set and reused inside bootstrap resamples.
For an event with the roles reversed (B beats A, e.g. from a win_b
vote or a tie half), the sign of z flips with the roles.
7.3 Reported coefficients
style_coefficients in the output are beta converted to rating
points (beta * 400/ln 10) per +1 standard deviation of the normalized
feature difference — e.g. length_chars: 24.18 means "being one SD
longer than your opponent is worth ~24 rating points in raw votes".
7.4 Fallback
Style fitting needs enough data. If a category has fewer than
--style-min-votes (default 50) vote records, or all four
covariates are degenerate (zero variance), the category falls back to
raw ratings: style_control: false in the output, the _sc fields
mirror the raw values, and style_coefficients is null.
7.5 Battles without response text (recordings)
Computer-use battles (DUMP_FORMAT.md §3.1, modality: "recording")
carry no response text — the "response" is a recorded browser session.
Their four style covariates are defined as exactly zero. A category
consisting only of recording battles is therefore degenerate under §7.4
and always reports style_control: false (raw = style-controlled);
inside a text category a recording battle cannot move the style fit.
Whether presentation effects exist for recordings (e.g. speed) is an
open question; v1 of the methodology deliberately does not model them.
8. Determinism
- RNG:
numpy.random.default_rngseeded per category withSeedSequence([seed, h])wherehis the first 8 bytes (big-endian) ofsha256(category_slug). Adding or removing a category therefore never changes another category's numbers under the same seed. - Categories are processed in sorted slug order; models are indexed in sorted slug order; all reductions run in fixed order.
- Output serialization is fixed-format (DUMP_FORMAT.md §6.4): floats rounded half-even to 4 decimals, printed with exactly 4 decimals, sorted keys, ASCII-only, LF.
- Byte-identical reproduction is guaranteed under the pinned
environment in
requirements-lock.txt. Other numpy builds should agree to far below CI widths, but byte-identity is only promised under the pins.
9. Defaults summary
| Parameter | CLI flag | Default |
|---|---|---|
| Bootstrap rounds | --bootstrap-rounds | 100 |
| Provisional threshold (votes) | --min-votes | 30 |
| Style-control minimum votes | --style-min-votes | 50 |
| Ridge strength | (fixed) | 1e-6 x total category vote weight |
| CI level | (fixed) | 95% (2.5/97.5 percentile) |
| Anchor / scale | (fixed) | mean 1000 / 400 per log10-odds |
10. Computer-use battles ("Browser Use")
The ratings mathematics above is modality-agnostic: a vote is a vote. What differs for computer-use battles is how the battle itself is produced and shown, and those rules are part of the methodology because they decide what a vote means.
- Live sites are the game. Both contestants drive a real browser through the same task on the live web — not a replay, not a sandbox. Consequently the two runs are not deterministic replicas of each other: site latency, rate limits, A/B tests and what a page showed at that moment are real life. A slower model may legitimately see a different world. We accept this nondeterminism and state it here rather than hide it behind a sandbox.
- Identical starting scene. A curated scene (a saved browser profile: cookies, logged-in throwaway accounts, open tabs) is snapshotted once by a curator and both contestants start from an identical copy. Scenes are versioned; a battle records which version it used. Public users never log into their own accounts inside our infrastructure; scenes use throwaway accounts only. Tasks that mutate account state give each contestant its own throwaway account cloned to the same scene, so contestants compete against the live world, not against each other's writes.
- Concurrent, simultaneous start. The two runs are always executed concurrently, and a barrier releases control to both agents at the same tick. That tick is t=0 of both recordings and of every latency number below.
- Equal resources, one scaffold. Each contestant gets pinned,
equal CPU/memory; every model runs through ONE uniform scaffold —
screenshot + accessibility tree in, one structured action
(click/type/scroll/key/navigate/done/needs_human) out — with no
vendor-native computer-use tools, or the leaderboard would measure
scaffolds instead of models. Per-step harness overhead (
harness_ms) is logged for every contestant and published in the dump's telemetry so that equal treatment is checkable, alongside the model's own latency (model_ms). - Wall-clock-faithful recordings. Judges see continuous video whose
duration equals the real run: a model that thinks for nine seconds is
seen waiting for nine seconds. The two recordings share t=0 and are
scrubbed together; a run that finishes early holds its last frame.
The pointer is not in the browser's frames, so cursor travel, clicks
and typing are drawn from the harness's own timestamped event trace —
the pointer animation is identical for every model (a constant, not a
bias). Keystrokes into password/OTP fields are never recorded in
clear (traces say
[redacted, N chars]; frames are dropped while such a field has focus). - Hard budgets. Every run has the same wall-clock and step budget;
exceeding either ends the run (
budget), and the vote is on what was achieved within it. - The
assistedrule. If a run required a human — the agent asked for help (needs_human) or an operator took over — the battle is marked assisted. This is disclosed to the judge only at reveal (after the vote), and assisted battles never enter the public dump or the ratings (DUMP_FORMAT.md exporter rule 8). Symmetric assistance does not rescue a battle in v1. - Latency on the analytics site. Rating-vs-latency charts use
time_to_first_action_msfor computer-use categories (the closest analogue of time-to-first-token), where text categories use response duration.