File size: 5,750 Bytes
f9d4a1a b1cf75e f9d4a1a 0052e99 d33ce47 f9d4a1a d33ce47 0052e99 f9d4a1a 0052e99 d33ce47 f9d4a1a 0052e99 f9d4a1a d33ce47 f9d4a1a 0052e99 f9d4a1a d33ce47 f9d4a1a b1cf75e f9d4a1a | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | """Export every scored eval answer into release/dataset/eval/ (Parquet) so the results tables can be audited.
.venv/bin/python -I scripts/export_eval_data.py
eval/benchmarks/<model>_loops<L>[_efficient].parquet one row per sampled answer (GPQA, MATH-500, AIME, AMC, held-out)
eval/ifeval/<model>_loops2.parquet one row per IFEval answer
eval/problems.parquet prompt + reference answer per problem, except GPQA
Models: dory1.0-4b (base), dory-beam-4b (v2, with reasoning_effort; `reasoning_mode` effort-low/medium/high or
normal for the untagged default), dory-beam-4b-v1 (the first release), dory-beam-4b-accurate, and ablations.
Base Dory and v1 were run with a 32k limit (16k for IFEval) and every answer that hit it was resumed to 64k by
scripts/spawn_continue.py (`resumed_tokens` > 0). v2 and Accurate ran with 64k from the start. The ablations rarely hit
32k and stay there; `max_output_tokens` says which limit applies.
GPQA's authors ask that its questions not appear online in plain text (to keep them out of training data), so GPQA
rows keep their grades, extracted letters and token counts but drop the question and the model's text.
"""
import json
from pathlib import Path
import pyarrow as pa
import pyarrow.parquet as pq
ROOT = Path(__file__).resolve().parent.parent
RES = ROOT / "data" / "eval" / "results"
OUT = ROOT / "release" / "dataset" / "eval"
# local result file -> (model name in the dataset, loops, reasoning mode)
RUNS = {
"base_loops1-64k": ("dory1.0-4b", 1, "normal"), "base_loops2-64k": ("dory1.0-4b", 2, "normal"),
"base_loops4-64k": ("dory1.0-4b", 4, "normal"), "base_loops2eff": ("dory1.0-4b", 2, "efficient"),
"mix050_loops1-64k": ("dory-beam-4b-v1", 1, "normal"), "mix050_loops2-64k": ("dory-beam-4b-v1", 2, "normal"),
"mix050_loops4-64k": ("dory-beam-4b-v1", 4, "normal"),
"rE-t050_loops2-default-64k": ("dory-beam-4b", 2, "normal"),
"rE-t050_loops2-low-64k": ("dory-beam-4b", 2, "effort-low"),
"rE-t050_loops2-medium-64k": ("dory-beam-4b", 2, "effort-medium"),
"rE-t050_loops2-high-64k": ("dory-beam-4b", 2, "effort-high"),
"rE-t050_loops4-high-64k": ("dory-beam-4b", 4, "effort-high"),
"mix030_loops2-64k": ("dory-beam-4b-accurate", 2, "normal"),
"mix030_loops4-64k": ("dory-beam-4b-accurate", 4, "normal"),
"mix070_loops2": ("blend-70-30", 2, "normal"),
"rA_loops1": ("run-a-sft", 1, "normal"), "rA_loops2": ("run-a-sft", 2, "normal"),
"rA_loops4": ("run-a-sft", 4, "normal"),
"rA400_loops2": ("run-a-step400", 2, "normal"), "rA800_loops2": ("run-a-step800", 2, "normal"),
"rA2_loops1": ("run-a2-random-trace", 1, "normal"), "rA2_loops2": ("run-a2-random-trace", 2, "normal"),
"rA2_loops4": ("run-a2-random-trace", 4, "normal"),
}
IFEVAL = {"base_ifeval_loops2-64k": "dory1.0-4b", "mix050_ifeval_loops2-64k": "dory-beam-4b-v1",
"rE-t050_ifeval_loops2-64k": "dory-beam-4b"}
def limit(tag):
return 65536 if tag.endswith("-64k") else 16384 if "ifeval" in tag else 32768
def main():
problems = {json.loads(l)["id"]: json.loads(l) for l in open(ROOT / "data" / "evalsets.jsonl")}
for f in list((OUT / "benchmarks").glob("*.parquet")) + list((OUT / "ifeval").glob("*.parquet")):
f.unlink() # file names changed between releases; start clean
(OUT / "benchmarks").mkdir(parents=True, exist_ok=True)
(OUT / "ifeval").mkdir(parents=True, exist_ok=True)
for tag, (model, loops, mode) in RUNS.items():
rows = []
for line in open(RES / f"{tag}.jsonl"):
r = json.loads(line)
gpqa = r["bench"] == "gpqa"
rows.append({"model": model, "loops": loops, "reasoning_mode": mode, "bench": r["bench"],
"problem_id": r["id"], "sample": r["sample"], "correct": r["correct"],
"extracted_answer": r["pred"], "reference_answer": problems[r["id"]]["answer"],
"output_tokens": r["tokens"], "finish_reason": r["finish"],
"max_output_tokens": limit(tag), "resumed_tokens": r.get("continued_tokens", 0),
"thinking_closed": r["thinking_closed"], "text": None if gpqa else r["text"]})
name = f"{model}_loops{loops}{'' if mode == 'normal' else '_' + mode}.parquet"
pq.write_table(pa.Table.from_pylist(rows), OUT / "benchmarks" / name, compression="zstd")
print(f"{name}: {len(rows)} rows")
for tag, model in IFEVAL.items():
rows = []
for line in open(RES / f"{tag}.jsonl"):
r = json.loads(line)
rows.append({"model": model, "loops": 2, "key": r["key"], "sample": r["sample"],
"strict_prompt": r["strict_prompt"], "strict_instructions": r["strict_inst"],
"loose_prompt": r["loose_prompt"], "loose_instructions": r["loose_inst"],
"output_tokens": r["tokens"], "finish_reason": r["finish"],
"max_output_tokens": limit(tag), "resumed_tokens": r.get("continued_tokens", 0),
"text": r["text"]})
pq.write_table(pa.Table.from_pylist(rows), OUT / "ifeval" / f"{model}_loops2.parquet", compression="zstd")
print(f"ifeval/{model}_loops2.parquet: {len(rows)} rows")
rows = [{"bench": p["bench"], "problem_id": p["id"], "prompt": p["prompt"], "reference_answer": p["answer"],
"answer_type": p["answer_type"], "samples": p["samples"]} for p in problems.values() if p["bench"] != "gpqa"]
pq.write_table(pa.Table.from_pylist(rows), OUT / "problems.parquet", compression="zstd")
print(f"problems.parquet: {len(rows)} rows")
if __name__ == "__main__":
main()
|