Skip to content
nano-gpt-data-curation

claude-opus-5

nano-gpt-data-curation — graded by the task's verifier against a measured baseline.

backend
modal
variant
claude claude-opus-5
metric
held-out multi-domain perplexity
actions
55
duration
1h 12m
recorded
2026-08-03

run iddclm-nano-curation__BgDz4nG

Everything claude-opus-5 did on this task, in order.

download JSON ↗
claude-codeclaude-opus-554 turns19 narration55 action55 observation35 reasoning1 final
#51
narration

I (8 finer registers): 308.3 — worse. D stands. Final step: regenerate the submission from scratch with curate.py defaults (no cache) to verify reproducibility.

toolBash
args
{
  "command": "cd /workspace; rm -f /tmp/scores.npz; nohup python submission/curate.py > /tmp/curF.log 2>&1 & sleep 115; tail -1 /tmp/curF.log"
}
Bash result
0

[stdout]
   0
[metadata] {"noOutputExpected": false}
#52
reasoning (redacted)

encrypted chain-of-thought — recorded, not exposed

toolBash
args
{
  "command": "sleep 230; tail -1 /tmp/curF.log; cat /workspace/.timer/remaining_secs"
}
Bash result · error
Exit code 143
Command timed out after 2m 0s

[error] tool reported failure
#53
reasoning (redacted)

encrypted chain-of-thought — recorded, not exposed

toolBash
args
{
  "command": "sleep 165; tail -2 /tmp/curF.log; cat /workspace/.timer/remaining_secs"
}
Bash result · error
Exit code 143
Command timed out after 2m 0s

[error] tool reported failure
#54
reasoning (redacted)

encrypted chain-of-thought — recorded, not exposed

toolBash
args
{
  "command": "sleep 55; tail -2 /tmp/curF.log; python - <<'EOF'\nimport json\ntry:\n    a=json.load(open('/workspace/submission/selection.json')); b=json.load(open('/tmp/FINAL_D.json'))\n    print('ids:',len(a),'identical to evaluated best:',a==b,'unique:',len(set(a))==len(a),'range:',min(a)>=0,max(a)<182016)\nexcept Exception as e: print('ERR',e)\nEOF\ncat /workspace/.timer/remaining_secs"
}
Bash result
{'wiki': 9000101, 'news': 9000033, 'web': 9000406, 'qa': 9002587}
wrote 34960 ids -> /workspace/submission/selection.json
ids: 34960 identical to evaluated best: True unique: True range: True True
1385

[stdout]
{'wiki': 9000101, 'news': 9000033, 'web': 9000406, 'qa': 9002587}
wrote 34960 ids -> /workspace/submission/selection.json
ids: 34960 identical to evaluated best: True unique: True range: True True
1385
[metadata] {"noOutputExpected": false}
final summary

All three deliverables are in place and verified.

Result: dev perplexity 302.6 vs. 458.0 for a random selection (−34%).

What I did:

  1. Recovered the target distribution. Decoded multi_dev.npy back to text with the GPT-2 tokenizer. It's four contiguous register blocks — WikiText-style encyclopedic, news, general web prose, StackExchange HTML Q&A — located by scanning marker densities, and ~25% each in tokens.
  2. Quality gates on the raw pool (length, alphabetic/ASCII ratio, mean word length, line- and word-level repetition, sentence structure, spam markers): 182,016 → 138,771 docs.
  3. Per-register importance scoring (DSIR-style): hashed unigram+bigram distributions for each register vs. a pool background sample; each document scored by the length-normalised log-likelihood ratio for all four registers, ranked independently within each.
  4. Proportional round-robin merge so the emitted priority list matches the target's 25/25/25/25 token mixture at every prefix — the packer can stop anywhere.
  5. MinHash near-duplicate removal at emit time (4 bands of 2).

Ablations, each a real training run (see the table in claim.md): arg-max register assignment 339.8 → per-register global ranking 340.3 → floored log-ratio + English gate + token-proportion mixture 314.6 → near-dup removal 302.6. Length cap (305.1), stricter (309.4) and looser (305.4) dedup, an 8-sub-register split (308.3), and a 30/20/20/30 mixture tilt (304.9) all lost.

Two bugs caught before they cost anything: add-one smoothing gave n-grams absent from both corpora a positive weight, which put Amharic navigation spam and minified JS at the top of every register; and my char-based mixture estimate (28.5/27/26/18.5) was wrong in token space.

Notes for you:

  • The mixture-tilt loss (304.9 vs 302.6) is the one prediction of the hypothesis I could test directly, and it held. The per-register loss decomposition — the sharpest test — I did not run: the frozen trainer takes one held-out array per run and doesn't save the model, so it would have cost four extra runs. claim.md says so explicitly rather than implying the mechanism was fully confirmed.
  • Differences among the losing variants (303–309) are single-seed and within plausible noise; the gap to random (458) and to the pre-fix versions (340) is not.
  • curate.py was re-run from scratch with no cache at the end: it reproduces the submitted 34,960 ids bit-identically. The MIX/LENCAP/DEDUP/BLOCKS8 env knobs exist only to reproduce the ablation rows; defaults are the submitted config.