The scripts are in the repository, not in the installed package. Clone it,
then
cd recipes/02-measure/public-benchmark before running the commands below. Browse this recipe on GitHub.wai.rows(), the road from a benchmark to pass_at,
eval_variance, holdout_size, select and compare; the five row keys
those calls read; why a third of the rollout budget goes to groups that
carry no gradient until select drops them.
Needs: nothing. No key, no GPU, no network. The 200 questions are
checked in.
Takes: seconds.
Run it
The road
questions are strings, answers is five strings per question (five
draws of the same prompt, which is what pass^k and select(mode="rl")
need), gold is the number after #### in each GSM8K solution.
MathEqual reads the gold off the row’s privileged.reference, where
references= put it and where no training export projects it. The rows
that come back carry the five keys the measurement calls read (task_id,
prompt, final_text, reward, markers) and the same typed shape
simulate() writes; the contract is on
docs/reference/rows.md.
The model is a seeded stand-in: each question has a difficulty drawn from
its own text, each arm a skill five points apart, and the answer is the gold
or a wrong number at that rate. Swap answer() in run.py for a call to
your model and nothing else changes.
What you get
- pass@1 0.50 [0.45..0.54] over 200 tasks, with pass@5 at 0.85: the stand-in gets most questions right some of the time. The bracket is a bootstrap over tasks, never rows.
- 60 of 200 groups dropped as unanimous. Every one of the five answers
scored the same, so a grouped update (GRPO, DAPO) has no advantage to
learn from on them. That is 30% of the rollout budget; the issue this
recipe answers measured 37% on a real outcome-reward arm.
select(mode="rl", band=(0.2, 0.8))keeps the questions the model passes 20 to 80% of the time (Lambert 2025, chapter Reasoning; Yu et al. 2025, DAPO, arXiv:2503.14476, drops accuracy 0 and 1 groups from the batch). - 313 tasks to prove a five-point gain at this base rate and k. The 200
here are not enough, and
holdout_sizesays so before a GPU-minute is spent. - +0.090 [+0.053..+0.126], read as noise. The paired interval excludes
zero, and the report still says NO DIFFERENCE: with three re-runs the
noise band is
t(df=2) = 4.30timesrun_std, 0.187 here, and the delta is inside it. More re-runs narrow the band; the honest answer from three is that a nine-point delta on this eval could be the eval moving. A flat result is a result.
Data
gsm8k_test_200.jsonl is the first 200 rows of the GSM8K test split
(Cobbe et al. 2021, arXiv:2110.14168; openai/grade-school-math,
MIT licence), as {"id", "question", "answer"}, taken from
openai/gsm8k on the Hugging Face Hub (main config, test split). To
remake it with the datasets package:
Next
Put your model behindanswer(), or build the answers elsewhere and hand
wai.rows the lists. Then is-your-eval-any-good
runs the six checks on the rows before you trust a number from them, and
recipes/papers reproduces a paper on the same road.