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
- 44
- duration
- 27m
- recorded
- 2026-08-03
run iddclm-nano-curation__8gThzQg
Everything claude-opus-5 did on this task, in order.
download JSON ↗I'll start by getting oriented — checking the time budget, the data, and the training script.
args
{
"command": "cat /workspace/.timer/remaining_secs 2>/dev/null; echo \"---\"; ls -la /workspace/; echo \"---\"; ls -la /workspace/data/; echo \"---\"; nvidia-smi 2>/dev/null | head -20",
"description": "Check timer, workspace layout, GPU"
}Bash result
5390
---
total 14
drwxr-xr-x 1 root root 100 Aug 3 23:25 .
drwxr-xr-x 1 root root 160 Aug 3 23:25 ..
drwxr-xr-x 1 root root 60 Aug 3 23:25 .live
drwxr-xr-x 1 root root 100 Aug 3 23:25 .metrics
drwxr-xr-x 1 root root 140 Aug 3 23:25 .timer
drwxr-xr-x 1 root root 57 Aug 3 22:37 data
-rwxrwxr-x 1 root root 714 Aug 3 22:34 dev_eval.sh
-rw-rw-r-- 1 root root 5706 Aug 3 22:34 model.py
-rw-rw-r-- 1 root root 869 Aug 3 22:34 pack_selection.py
drwxr-xr-x 1 root root 10 Aug 3 22:37 submission
-rwxrwxr-x 1 root root 1509 Aug 3 22:34 timer.sh
-rw-rw-r-- 1 root root 2962 Aug 3 22:34 train_nano.py
---
total 792657
drwxr-xr-x 1 root root 57 Aug 3 22:37 .
drwxr-xr-x 1 root root 100 Aug 3 23:25 ..
-r--r--r-- 1 root root 2000128 Aug 3 22:34 multi_dev.npy
-r--r--r-- 1 root root 809679384 Aug 3 22:35 pool.jsonl
---
Mon Aug 3 23:25:57 2026
+-----------------------------------------------------------------------------------------+
| NVIDIA-SMI 580.95.05 Driver Version: 580.95.05 CUDA Version: 13.0 |
+-----------------------------------------+------------------------+----------------------+
| GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. |
| | | MIG M. |
|=========================================+========================+======================|
| 0 NVIDIA H200 On | 00000000:CC:00.0 Off | 0 |
| N/A 31C P0 76W / 700W | 4MiB / 143771MiB | 0% Default |
| | | Disabled |
+-----------------------------------------+------------------------+----------------------+
+-----------------------------------------------------------------------------------------+
| Processes: |
| GPU GI CI PID Type Process name GPU Memory |
| ID ID Usage |
|=========================================================================================|
| No running processes found |
+-----------------------------------------------------------------------------------------+
[stdout]
5390
---
total 14
drwxr-xr-x 1 root root 100 Aug 3 23:25 .
drwxr-xr-x 1 root root 160 Aug 3 23:25 ..
drwxr-xr-x 1 root root 60 Aug 3 23:25 .live
drwxr-xr-x 1 root root 100 Aug 3 23:25 .metrics
drwxr-xr-x 1 root root 140 Aug 3 23:25 .timer
drwxr-xr-x 1 root root 57 Aug 3 22:37 data
-rwxrwxr-x 1 root root 714 Aug 3 22:34 dev_eval.sh
-rw-rw-r-- 1 root root 5706 Aug 3 22:34 model.py
-rw-rw-r-- 1 root root 869 Aug 3 22:34 pack_selection.py
drwxr-xr-x 1 root root 10 Aug 3 22:37 submission
-rwxrwxr-x 1 root root 1509 Aug 3 22:34 timer.sh
-rw-rw-r-- 1 root root 2962 Aug 3 22:34 train_nano.py
---
total 792657
drwxr-xr-x 1 root root 57 Aug 3 22:37 .
drwxr-xr-x 1 root root 100 Aug 3 23:25 ..
-r--r--r-- 1 root root 2000128 Aug 3 22:34 multi_dev.npy
-r--r--r-- 1 root root 809679384 Aug 3 22:35 pool.jsonl
---
Mon Aug 3 23:25:57 2026
+-----------------------------------------------------------------------------------------+
| NVIDIA-SMI 580.95.05 Driver Version: 580.95.05 CUDA Version: 13.0 |
+-----------------------------------------+------------------------+----------------------+
| GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. |
| | | MIG M. |
|=========================================+========================+======================|
| 0 NVIDIA H200 On | 00000000:CC:00.0 Off | 0 |
| N/A 31C P0 76W / 700W | 4MiB / 143771MiB | 0% Default |
| | | Disabled |
+-----------------------------------------+------------------------+----------------------+
+-----------------------------------------------------------------------------------------+
| Processes: |
| GPU GI CI PID Type Process name GPU Memory |
| ID ID Usage |
|=========================================================================================|
| No running processes found |
+-----------------------------------------------------------------------------------------+
[metadata] {"noOutputExpected": false}args
{
"file_path": "/workspace/train_nano.py"
}Read result
1 """From-scratch nano-GPT (30M) LM training on a 1D token .npy; report held-out perplexity.
2 Frozen recipe — the ONLY thing that varies between runs is the training token set."""
3 import argparse, math, time, numpy as np, torch
4 from model import GPT, GPTConfig
5
6 ap = argparse.ArgumentParser()
7 ap.add_argument("--train_npy", required=True)
8 ap.add_argument("--heldout_npy", required=True)
9 ap.add_argument("--out_json", required=True)
10 ap.add_argument("--max_iters", type=int, default=3000)
11 ap.add_argument("--warmup", type=int, default=150)
12 ap.add_argument("--batch", type=int, default=32)
13 ap.add_argument("--block", type=int, default=256)
14 ap.add_argument("--lr", type=float, default=6e-4)
15 ap.add_argument("--seed", type=int, default=1337)
16 a = ap.parse_args()
17
18 torch.manual_seed(a.seed); np.random.seed(a.seed)
19 dev = "cuda"
20 tr = np.load(a.train_npy); ho = np.load(a.heldout_npy)
21 tr = torch.from_numpy(tr.astype(np.int64)); ho = torch.from_numpy(ho.astype(np.int64))
22 rng = np.random.default_rng(a.seed)
23
24 model = GPT(GPTConfig(block_size=a.block, vocab_size=50257, n_layer=6, n_head=6,
25 n_embd=384, dropout=0.0, bias=False)).to(dev)
26 opt = model.configure_optimizers(0.1, a.lr, (0.9, 0.95), "cuda")
27
28 def lr_at(it):
29 if it < a.warmup: return a.lr * (it + 1) / (a.warmup + 1)
30 r = (it - a.warmup) / max(1, a.max_iters - a.warmup)
31 return 0.1 * a.lr + 0.5 * (1 + math.cos(math.pi * r)) * (a.lr - 0.1 * a.lr)
32
33 def get_batch(src):
34 ix = rng.integers(0, len(src) - a.block - 1, size=a.batch)
35 x = torch.stack([src[i:i+a.block] for i in ix]).to(dev)
36 y = torch.stack([src[i+1:i+1+a.block] for i in ix]).to(dev)
37 return x, y
38
39 t0 = time.time()
40 model.train()
41 for it in range(a.max_iters):
42 for g in opt.param_groups: g["lr"] = lr_at(it)
43 x, y = get_batch(tr)
44 with torch.autocast("cuda", dtype=torch.bfloat16):
45 _, loss = model(x, y)
46 opt.zero_grad(set_to_none=True); loss.backward()
47 torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0); opt.step()
48 train_s = time.time() - t0
49
50 # held-out perplexity: mean next-token CE over non-overlapping windows (window-weighted)
51 import json
52 model.eval()
53 nwin = (len(ho) - 1) // a.block
54 starts = [j * a.block for j in range(nwin)]
55 sum_loss, nseen = 0.0, 0
56 with torch.no_grad():
57 for i in range(0, nwin, a.batch):
58 bs = starts[i:i+a.batch]
59 x = torch.stack([ho[s:s+a.block] for s in bs]).to(dev)
60 y = torch.stack([ho[s+1:s+1+a.block] for s in bs]).to(dev)
61 with torch.autocast("cuda", dtype=torch.bfloat16):
62 _, l = model(x, y)
63 sum_loss += l.item() * len(bs); nseen += len(bs)
64 mean_loss = sum_loss / max(1, nseen)
65 ppl = math.exp(mean_loss)
66 out = {"train_npy": a.train_npy, "heldout_ppl": ppl, "mean_loss": mean_loss,
67 "max_iters": a.max_iters, "seed": a.seed, "train_s": round(train_s, 1)}
68 json.dump(out, open(a.out_json, "w"))
69 print(f"HELDOUT_PPL {ppl:.3f} loss {mean_loss:.4f} train_s {train_s:.0f} {a.train_npy}")
70
[metadata] {"type": "text", "file": {"filePath": "/workspace/train_nano.py", "content": "\"\"\"From-scratch nano-GPT (30M) LM training on a 1D token .npy; report held-out perplexity.\nFrozen recipe — the ONLY thing that varies between runs is the training token set.\"\"\"\nimport argparse, math, time, numpy as np, torch\nfrom model import GPT, GPTConfig\n\nap = argparse.ArgumentParser()\nap.add_argument(\"--train_npy\", required=True)\nap.add_argument(\"--heldout_npy\", required=True)\nap.add_argument(\"--out_json\", required=True)\nap.add_argument(\"--max_iters\", type=int, default=3000)\nap.add_argument(\"--warmup\", type=int, default=150)\nap.add_argument(\"--batch\", type=int, default=32)\nap.add_argument(\"--block\", type=int, default=256)\nap.add_argument(\"--lr\", type=float, default=6e-4)\nap.add_argument(\"--seed\", type=int, default=1337)\na = ap.parse_args()\n\ntorch.manual_seed(a.seed); np.random.seed(a.seed)\ndev = \"cuda\"\ntr = np.load(a.train_npy); ho = np.load(a.heldout_npy)\ntr = torch.from_numpy(tr.astype(np.int64)); ho = torch.from_numpy(ho.astype(np.int64))\nrng = np.random.default_rng(a.seed)\n\nmodel = GPT(GPTConfig(block_size=a.block, vocab_size=50257, n_layer=6, n_head=6,\n n_embd=384, dropout=0.0, bias=False)).to(dev)\nopt = model.configure_optimizers(0.1, a.lr, (0.9, 0.95), \"cuda\")\n\ndef lr_at(it):\n if it < a.warmup: return a.lr * (it + 1) / (a.warmup + 1)\n r = (it - a.warmup) / max(1, a.max_iters - a.warmup)\n return 0.1 * a.lr + 0.5 * (1 + math.cos(math.pi * r)) * (a.lr - 0.1 * a.lr)\n\ndef get_batch(src):\n ix = rng.integers(0, len(src) - a.block - 1, size=a.batch)\n x = torch.stack([src[i:i+a.block] for i in ix]).to(dev)\n y = torch.stack([src[i+1:i+1+a.block] for i in ix]).to(dev)\n return x, y\n\nt0 = time.time()\nmodel.train()\nfor it in range(a.max_iters):\n for g in opt.param_groups: g[\"lr\"] = lr_at(it)\n x, y = get_batch(tr)\n with torch.autocast(\"cuda\", dtype=torch.bfloat16):\n _, loss = model(x, y)\n opt.zero_grad(set_to_none=True); loss.backward()\n torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0); opt.step()\ntrain_s = time.time() - t0\n\n# held-out perplexity: mean next-token CE over non-overlapping windows (window-weighted)\nimport json\nmodel.eval()\nnwin = (len(ho) - 1) // a.block\nstarts = [j * a.block for j in range(nwin)]\nsum_loss, nseen = 0.0, 0\nwith torch.no_grad():\n for i in range(0, nwin, a.batch):\n bs = starts[i:i+a.batch]\n x = torch.stack([ho[s:s+a.block] for s in bs]).to(dev)\n y = torch.stack([ho[s+1:s+1+a.block] for s in bs]).to(dev)\n with torch.autocast(\"cuda\", dtype=torch.bfloat16):\n _, l = model(x, y)\n sum_loss += l.item() * len(bs); nseen += len(bs)\nmean_loss = sum_loss / max(1, nseen)\nppl = math.exp(mean_loss)\nout = {\"train_npy\": a.train_npy, \"heldout_ppl\": ppl, \"mean_loss\": mean_loss,\n \"max_iters\": a.max_iters, \"seed\": a.seed, \"train_s\": round(train_s, 1)}\njson.dump(out, open(a.out_json, \"w\"))\nprint(f\"HELDOUT_PPL {ppl:.3f} loss {mean_loss:.4f} train_s {train_s:.0f} {a.train_npy}\")\n", "numLines": 70, "startLine": 1, "totalLines": 70}}90 minutes on the clock. Key insight already visible: multi_dev.npy is the target in GPT-2 token form — I can decode it back to text and use it as positive supervision for a classifier. Let me move fast.
args
{
"command": "cat pack_selection.py; echo \"=== dev_eval.sh\"; cat dev_eval.sh; echo \"=== nproc\"; nproc; echo \"=== free\"; free -g | head -2; echo \"=== head pool\"; head -c 1200 data/pool.jsonl; echo; echo \"=== python pkgs\"; python -c \"import sklearn, transformers, tiktoken; print('sk',sklearn.__version__,'tf',transformers.__version__)\" 2>&1 | tail -3",
"description": "Inspect helper scripts and environment"
}Bash result
"""Solver-side: pack a selection.json (ordered ids) into a 12M-token train array from pool.jsonl."""
import json, sys, numpy as np
from transformers import AutoTokenizer
POOL = "/workspace/data/pool.jsonl"
SEL = sys.argv[1] if len(sys.argv) > 1 else "/workspace/submission/selection.json"
OUT = sys.argv[2] if len(sys.argv) > 2 else "/tmp/dev_train.npy"
BUDGET = 12_000_000
tok = AutoTokenizer.from_pretrained("gpt2"); EOS = tok.eos_token_id
text = {}
for line in open(POOL):
r = json.loads(line); text[r["id"]] = r["text"]
sel = json.load(open(SEL))
parts, tot = [], 0
for i in sel:
ids = tok(text[i], add_special_tokens=False).input_ids
parts.extend(ids); parts.append(EOS); tot += len(ids) + 1
if tot >= BUDGET: break
arr = np.array(parts[:BUDGET], dtype=np.uint16)
np.save(OUT, arr)
print(f"packed {len(arr)} tokens from {len(sel)} ids -> {OUT}")
=== dev_eval.sh
#!/bin/bash
# Diagnostic: train the frozen 30M GPT on your selection and report DEV perplexity.
# Usage: bash dev_eval.sh [selection.json] (default /workspace/submission/selection.json)
# NOTE: the official target is a DIFFERENT (hidden) sample from the same HQ domain.
set -euo pipefail
export TOKENIZERS_PARALLELISM=false
SEL="${1:-/workspace/submission/selection.json}"
cd /workspace
python3 pack_selection.py "$SEL" /tmp/dev_train.npy
python3 train_nano.py --train_npy /tmp/dev_train.npy --heldout_npy /workspace/data/multi_dev.npy \
--out_json /tmp/dev.json --max_iters 3000 --seed 1337 2>&1 | grep HELDOUT_PPL
echo "(dev PPL on multi_dev; official uses a hidden disjoint sample of the same HQ domain)"
=== nproc
16
=== free
total used free shared buff/cache available
Mem: 1024 0 1023 0 0 1023
=== head pool
{"id": 0, "text": "|Viewing Single Post From: Spoilers for the Week of February 11th|\n|Lil||Feb 1 2013, 09:58 AM|\nDon't care about Chloe/Taniel/Jen-Jen. Don't care about Sami, really, but hoping that we get some good \"SAMANTHA GENE!!\" Marlena Death-Stares out of it. And \"newfound\" feelings. Please. If only.\nSTEFANO!! STEFANO, STEFANO, STEFANO!!!! :cheer:\n|Spoilers for the Week of February 11th \u00b7 DAYS: News, Spoilers & Discussion|"}
{"id": 1, "text": "*sigh* Fundamentalist community, let me pass on some advice to you I learned from the atheistic community:\nIf you have set yourself on fire, do not run.\nOkay? Okay?? Please?\nLook, D, you had two months to say to Harvard in private emails, \"Im sorry, I shouldnt have been using that animation in my paid presentations. I wont use it again. I really do like 'Inner Life', though, and would love to use it in classroom presentations, from the BioVisions site, if that is acceptable.\"\nI sat here, for two months, waiting for that to happen, anything to happen, and it didnt. Two months, on your own terms, you could have written a similar post to yesterdays. I would have given you the benefit of the doubt-- maybe you didnt know
=== python pkgs
Traceback (most recent call last):
File "<string>", line 1, in <module>
ModuleNotFoundError: No module named 'sklearn'
[stdout]
"""Solver-side: pack a selection.json (ordered ids) into a 12M-token train array from pool.jsonl."""
import json, sys, numpy as np
from transformers import AutoTokenizer
POOL = "/workspace/data/pool.jsonl"
SEL = sys.argv[1] if len(sys.argv) > 1 else "/workspace/submission/selection.json"
OUT = sys.argv[2] if len(sys.argv) > 2 else "/tmp/dev_train.npy"
BUDGET = 12_000_000
tok = AutoTokenizer.from_pretrained("gpt2"); EOS = tok.eos_token_id
text = {}
for line in open(POOL):
r = json.loads(line); text[r["id"]] = r["text"]
sel = json.load(open(SEL))
parts, tot = [], 0
for i in sel:
ids = tok(text[i], add_special_tokens=False).input_ids
parts.extend(ids); parts.append(EOS); tot += len(ids) + 1
if tot >= BUDGET: break
arr = np.array(parts[:BUDGET], dtype=np.uint16)
np.save(OUT, arr)
print(f"packed {len(arr)} tokens from {len(sel)} ids -> {OUT}")
=== dev_eval.sh
#!/bin/bash
# Diagnostic: train the frozen 30M GPT on your selection and report DEV perplexity.
# Usage: bash dev_eval.sh [selection.json] (default /workspace/submission/selection.json)
# NOTE: the official target is a DIFFERENT (hidden) sample from the same HQ domain.
set -euo pipefail
export TOKENIZERS_PARALLELISM=false
SEL="${1:-/workspace/submission/selection.json}"
cd /workspace
python3 pack_selection.py "$SEL" /tmp/dev_train.npy
python3 train_nano.py --train_npy /tmp/dev_train.npy --heldout_npy /workspace/data/multi_dev.npy \
--out_json /tmp/dev.json --max_iters 3000 --seed 1337 2>&1 | grep HELDOUT_PPL
echo "(dev PPL on multi_dev; official uses a hidden disjoint sample of the same HQ domain)"
=== nproc
16
=== free
total used free shared buff/cache available
Mem: 1024 0 1023 0 0 1023
=== head pool
{"id": 0, "text": "|Viewing Single Post From: Spoilers for the Week of February 11th|\n|Lil||Feb 1 2013, 09:58 AM|\nDon't care about Chloe/Taniel/Jen-Jen. Don't care about Sami, really, but hoping that we get some good \"SAMANTHA GENE!!\" Marlena Death-Stares out of it. And \"newfound\" feelings. Please. If only.\nSTEFANO!! STEFANO, STEFANO, STEFANO!!!! :cheer:\n|Spoilers for the Week of February 11th \u00b7 DAYS: News, Spoilers & Discussion|"}
{"id": 1, "text": "*sigh* Fundamentalist community, let me pass on some advice to you I learned from the atheistic community:\nIf you have set yourself on fire, do not run.\nOkay? Okay?? Please?\nLook, D, you had two months to say to Harvard in private emails, \"Im sorry, I shouldnt have been using that animation in my paid presentations. I wont use it again. I really do like 'Inner Life', though, and would love to use it in classroom presentations, from the BioVisions site, if that is acceptable.\"\nI sat here, for two months, waiting for that to happen, anything to happen, and it didnt. Two months, on your own terms, you could have written a similar post to yesterdays. I would have given you the benefit of the doubt-- maybe you didnt know
=== python pkgs
Traceback (most recent call last):
File "<string>", line 1, in <module>
ModuleNotFoundError: No module named 'sklearn'
[metadata] {"noOutputExpected": false}1TB RAM, 16 cores, H200. No sklearn — I'll use torch. The long pole is tokenizing the 200M-token pool, so let me launch that in the background first and analyze the target while it runs.
args
{
"file_path": "/workspace/tok_pool.py",
"content": "\"\"\"Tokenize the whole pool once with GPT-2 BPE; cache as flat uint16 + offsets.\nReused for (a) features, (b) exact token counts, (c) fast packing at the end.\"\"\"\nimport json, os, numpy as np, time\nos.environ[\"TOKENIZERS_PARALLELISM\"] = \"true\"\nfrom transformers import AutoTokenizer\n\ntok = AutoTokenizer.from_pretrained(\"gpt2\")\nPOOL = \"/workspace/data/pool.jsonl\"\n\nids, texts = [], []\nfor line in open(POOL):\n r = json.loads(line)\n ids.append(r[\"id\"]); texts.append(r[\"text\"])\nprint(\"loaded\", len(texts), flush=True)\n\nt0 = time.time()\nB = 2000\nflat = []\nlens = np.zeros(len(texts), dtype=np.int64)\nk = 0\nfor s in range(0, len(texts), B):\n enc = tok(texts[s:s+B], add_special_tokens=False)[\"input_ids\"]\n for e in enc:\n lens[k] = len(e); k += 1\n flat.append(np.asarray(e, dtype=np.uint16))\n if s % 20000 == 0:\n print(f\"{s}/{len(texts)} {time.time()-t0:.0f}s\", flush=True)\n\nflat = np.concatenate(flat)\noff = np.zeros(len(texts) + 1, dtype=np.int64)\nnp.cumsum(lens, out=off[1:])\nnp.save(\"/workspace/cache/pool_tokens.npy\", flat)\nnp.save(\"/workspace/cache/pool_offsets.npy\", off)\nnp.save(\"/workspace/cache/pool_ids.npy\", np.asarray(ids, dtype=np.int64))\nprint(\"DONE\", flat.shape, off[-1], f\"{time.time()-t0:.0f}s\", flush=True)\n"
}Write result
File created successfully at: /workspace/tok_pool.py (file state is current in your context — no need to Read it back)
[metadata] {"type": "create", "filePath": "/workspace/tok_pool.py", "content": "\"\"\"Tokenize the whole pool once with GPT-2 BPE; cache as flat uint16 + offsets.\nReused for (a) features, (b) exact token counts, (c) fast packing at the end.\"\"\"\nimport json, os, numpy as np, time\nos.environ[\"TOKENIZERS_PARALLELISM\"] = \"true\"\nfrom transformers import AutoTokenizer\n\ntok = AutoTokenizer.from_pretrained(\"gpt2\")\nPOOL = \"/workspace/data/pool.jsonl\"\n\nids, texts = [], []\nfor line in open(POOL):\n r = json.loads(line)\n ids.append(r[\"id\"]); texts.append(r[\"text\"])\nprint(\"loaded\", len(texts), flush=True)\n\nt0 = time.time()\nB = 2000\nflat = []\nlens = np.zeros(len(texts), dtype=np.int64)\nk = 0\nfor s in range(0, len(texts), B):\n enc = tok(texts[s:s+B], add_special_tokens=False)[\"input_ids\"]\n for e in enc:\n lens[k] = len(e); k += 1\n flat.append(np.asarray(e, dtype=np.uint16))\n if s % 20000 == 0:\n print(f\"{s}/{len(texts)} {time.time()-t0:.0f}s\", flush=True)\n\nflat = np.concatenate(flat)\noff = np.zeros(len(texts) + 1, dtype=np.int64)\nnp.cumsum(lens, out=off[1:])\nnp.save(\"/workspace/cache/pool_tokens.npy\", flat)\nnp.save(\"/workspace/cache/pool_offsets.npy\", off)\nnp.save(\"/workspace/cache/pool_ids.npy\", np.asarray(ids, dtype=np.int64))\nprint(\"DONE\", flat.shape, off[-1], f\"{time.time()-t0:.0f}s\", flush=True)\n", "structuredPatch": [], "originalFile": null, "userModified": false}encrypted chain-of-thought — recorded, not exposed
args
{
"command": "mkdir -p /workspace/cache /workspace/submission && nohup python tok_pool.py > /workspace/cache/tok.log 2>&1 &\necho \"launched\"; sleep 5; cat /workspace/cache/tok.log",
"description": "Launch pool tokenization in background"
}Bash result
launched
[stdout]
launched
[metadata] {"noOutputExpected": false}encrypted chain-of-thought — recorded, not exposed
args
{
"command": "python -c \"\nimport numpy as np\nfrom transformers import AutoTokenizer\ntok = AutoTokenizer.from_pretrained('gpt2')\nd = np.load('data/multi_dev.npy')\nprint('dtype', d.dtype, 'len', len(d))\ntxt = tok.decode(d[:d.size].tolist())\nopen('/workspace/cache/dev_text.txt','w').write(txt)\nprint('chars', len(txt))\n# EOS boundaries\neos = np.where(d == 50256)[0]\nprint('n_eos', len(eos), 'first20', eos[:20])\n\" 2>&1 | tail -10",
"description": "Decode dev target tokens to text"
}Bash result
dtype uint16 len 1000000
chars 4150110
n_eos 2704 first20 [ 206 332 556 652 854 986 1010 1080 1231 1555 1789 2010 2179 2412
2473 2516 2702 2875 3017 3128]
[stdout]
dtype uint16 len 1000000
chars 4150110
n_eos 2704 first20 [ 206 332 556 652 854 986 1010 1080 1231 1555 1789 2010 2179 2412
2473 2516 2702 2875 3017 3128]
[metadata] {"noOutputExpected": false}encrypted chain-of-thought — recorded, not exposed
args
{
"command": "python -c \"\nimport numpy as np\nfrom transformers import AutoTokenizer\ntok = AutoTokenizer.from_pretrained('gpt2')\nd = np.load('data/multi_dev.npy')\neos = np.where(d==50256)[0]\nsegs=[]; prev=0\nfor e in eos:\n segs.append(d[prev:e]); prev=e+1\nprint('nsegs',len(segs))\nimport random\nrandom.seed(0)\nfor i in [0, 300, 676, 1000, 1352, 1700, 2028, 2400, 2700]:\n if i < len(segs):\n s = tok.decode(segs[i].tolist())\n print('='*25, 'SEG', i, 'ntok', len(segs[i]))\n print(s[:420].replace(chr(10),' | '))\n\" 2>&1 | tail -40",
"description": "Sample dev target segments to identify domains"
}Bash result
nsegs 2704
========================= SEG 0 ntok 206
Beardmore was sufficiently impressed with Shackleton to offer financial support , but other donations proved hard to come by . Nevertheless , in February 1907 , Shackleton presented to the Royal Geographic Society his plans for an Antarctic expedition , the details of which , under the name British Antarctic Expedition , were published in the Royal Society 's newsletter , Geographic Journal . The aim was the conques
========================= SEG 300 ntok 73
" Mystery Date " received steady viewership that was consistent with the ratings for the previous week . It received 2 @.@ 8 million viewers , down only from 2 @.@ 9 from " Tea Leaves " . The episode also received a 1 @.@ 0 rating in the important 18 @-@ 49 demographic , the same rating as the week before . |
========================= SEG 676 ntok 249
In the early 18th century , the establishment of Russian naval power in the Baltic challenged the interests of Sweden , at the time one of the major powers in the Baltic . The Swedish Empire at the time included territory in Northern Germany , all of modern Finland and most of the Baltic states , a dominion held together by the Baltic sea routes . Russian Tsar Peter the Great had established a new capital and naval
========================= SEG 1000 ntok 107
In April 2006 , a team of astronomers , believing that Oval BA might converge with the GRS that year , observed the storms through the Hubble Space Telescope . The storms pass each other about every two years , but the passings of 2002 and 2004 did not produce anything exciting . Dr. Amy Simon @-@ Miller , of the Goddard Space Flight Center , predicted the storms would have their closest passing on July 4 , 2006 . O
========================= SEG 1352 ntok 100
Mining subsidence coupled with structural and political changes to the mining industry began the decline in Astley 's industrial activities during the mid @-@ 20th century ; its cotton mill closed in 1955 , and the last coal was brought to the surface in 1970 . However , Astley has grown as part of a commuter belt , supported by its proximity to Manchester city centre and inter @-@ city transport links . Astley Gree
========================= SEG 1700 ntok 165
The Kalpoe brothers were rearrested on August 26 along with another new suspect . According to his lawyer , 21 @-@ year @-@ old Freddy Arambatzis was suspected of taking photographs of and having physical contact with an underage girl , an incident which allegedly occurred before the Holloway disappearance and in which Arambatzis 's friends Van der Sloot and the Kalpoe brothers were supposedly involved . Van der Slo
========================= SEG 2028 ntok 873
When Congress president Rahul Gandhi enters the imposing corridors of the 1300-year-old Sharada Peeth on Wednesday, historians will remember the time his grandmother Indira Gandhi visited the spot 40 years ago in 1978.Like the Congress of today, the party was going through a slump in 1978. The excesses of Emergency had cost her the chair of the Prime Minister, she was not even a Member of Parliament.Her family was go
========================= SEG 2400 ntok 1449
<p>In the following, the echo output is right, but the pgm is not receiving the flags correctly. Appreciate any insights.</p> | | <pre><code>script file: | flags="-umc -v -v " | r="";for d in `ls -d /tmp/passenger*`; do r="$r -x $d"; done | flags="$flags $r" | echo $flags | /usr/sbin/tmpwatch "$flags" -x /tmp/.X11-unix -x /tmp/.XIM-unix \ | -x /tmp/.font-unix -x /tmp/.ICE-unix -x /tmp/.Test-unix 240 /tmp | </code></pre> | | <p>Outp
========================= SEG 2700 ntok 638
<p>I'm working on a project which makes heavy use of extension methods to convert strings from the UI-layer into their appropriate object-types in the code-layer: <em>(pseudo-code)</em></p> | | <pre><code>// C# | | /* | Converts a String from the UI-layer, formatted according to a user-defined | UI-culture preference (in this case from da-DK) into a Double | */ | | Double d = "1.000,50".fromWebStringToDouble(); // 1000.5 | </code></p
[stdout]
nsegs 2704
========================= SEG 0 ntok 206
Beardmore was sufficiently impressed with Shackleton to offer financial support , but other donations proved hard to come by . Nevertheless , in February 1907 , Shackleton presented to the Royal Geographic Society his plans for an Antarctic expedition , the details of which , under the name British Antarctic Expedition , were published in the Royal Society 's newsletter , Geographic Journal . The aim was the conques
========================= SEG 300 ntok 73
" Mystery Date " received steady viewership that was consistent with the ratings for the previous week . It received 2 @.@ 8 million viewers , down only from 2 @.@ 9 from " Tea Leaves " . The episode also received a 1 @.@ 0 rating in the important 18 @-@ 49 demographic , the same rating as the week before . |
========================= SEG 676 ntok 249
In the early 18th century , the establishment of Russian naval power in the Baltic challenged the interests of Sweden , at the time one of the major powers in the Baltic . The Swedish Empire at the time included territory in Northern Germany , all of modern Finland and most of the Baltic states , a dominion held together by the Baltic sea routes . Russian Tsar Peter the Great had established a new capital and naval
========================= SEG 1000 ntok 107
In April 2006 , a team of astronomers , believing that Oval BA might converge with the GRS that year , observed the storms through the Hubble Space Telescope . The storms pass each other about every two years , but the passings of 2002 and 2004 did not produce anything exciting . Dr. Amy Simon @-@ Miller , of the Goddard Space Flight Center , predicted the storms would have their closest passing on July 4 , 2006 . O
========================= SEG 1352 ntok 100
Mining subsidence coupled with structural and political changes to the mining industry began the decline in Astley 's industrial activities during the mid @-@ 20th century ; its cotton mill closed in 1955 , and the last coal was brought to the surface in 1970 . However , Astley has grown as part of a commuter belt , supported by its proximity to Manchester city centre and inter @-@ city transport links . Astley Gree
========================= SEG 1700 ntok 165
The Kalpoe brothers were rearrested on August 26 along with another new suspect . According to his lawyer , 21 @-@ year @-@ old Freddy Arambatzis was suspected of taking photographs of and having physical contact with an underage girl , an incident which allegedly occurred before the Holloway disappearance and in which Arambatzis 's friends Van der Sloot and the Kalpoe brothers were supposedly involved . Van der Slo
========================= SEG 2028 ntok 873
When Congress president Rahul Gandhi enters the imposing corridors of the 1300-year-old Sharada Peeth on Wednesday, historians will remember the time his grandmother Indira Gandhi visited the spot 40 years ago in 1978.Like the Congress of today, the party was going through a slump in 1978. The excesses of Emergency had cost her the chair of the Prime Minister, she was not even a Member of Parliament.Her family was go
========================= SEG 2400 ntok 1449
<p>In the following, the echo output is right, but the pgm is not receiving the flags correctly. Appreciate any insights.</p> | | <pre><code>script file: | flags="-umc -v -v " | r="";for d in `ls -d /tmp/passenger*`; do r="$r -x $d"; done | flags="$flags $r" | echo $flags | /usr/sbin/tmpwatch "$flags" -x /tmp/.X11-unix -x /tmp/.XIM-unix \ | -x /tmp/.font-unix -x /tmp/.ICE-unix -x /tmp/.Test-unix 240 /tmp | </code></pre> | | <p>Outp
========================= SEG 2700 ntok 638
<p>I'm working on a project which makes heavy use of extension methods to convert strings from the UI-layer into their appropriate object-types in the code-layer: <em>(pseudo-code)</em></p> | | <pre><code>// C# | | /* | Converts a String from the UI-layer, formatted according to a user-defined | UI-culture preference (in this case from da-DK) into a Double | */ | | Double d = "1.000,50".fromWebStringToDouble(); // 1000.5 | </code></p
[metadata] {"noOutputExpected": false}encrypted chain-of-thought — recorded, not exposed
args
{
"command": "tail -3 /workspace/cache/tok.log; echo \"=== domains ===\"; python -c \"\nimport numpy as np\nfrom transformers import AutoTokenizer\ntok = AutoTokenizer.from_pretrained('gpt2')\nd = np.load('data/multi_dev.npy'); eos=np.where(d==50256)[0]\nsegs=[]; prev=0\nfor e in eos: segs.append(d[prev:e]); prev=e+1\ndef feat(s):\n t=tok.decode(s.tolist())\n return ('@-@' in t or '@.@' in t or ' , ' in t[:300]), ('<p>' in t or '<pre>' in t or '<code>' in t), len(s)\n# print a marker map every 50 segs\nfor i in range(0,len(segs),100):\n w,h,n=feat(segs[i])\n print(i, 'wikistyle' if w else ' ', 'html' if h else ' ', n, repr(tok.decode(segs[i].tolist())[:90]))\n\" 2>&1 | tail -30",
"description": "Map dev target domain boundaries"
}Bash result
20000/182016 7s
40000/182016 13s
60000/182016 19s
=== domains ===
0 wikistyle 206 ' Beardmore was sufficiently impressed with Shackleton to offer financial support , but oth'
100 wikistyle 283 ' In the late Vedic period , around the 6th century BCE , the small states and chiefdoms of'
200 wikistyle 174 " Monroe was declared a ward of the state , and her mother 's friend , Grace McKee Goddard "
300 wikistyle 73 ' " Mystery Date " received steady viewership that was consistent with the ratings for the '
400 wikistyle 479 ' Chasen has appeared in other television programmes such as The Bill and The Harry Hill Sh'
500 wikistyle 151 ' Citizens were organized on the basis of centuries and tribes , which would each gather in'
600 wikistyle 159 ' Stricklett attended Santa Clara University , where he played college baseball for the San'
700 wikistyle 274 ' In 1968 , Lennon was told The Dairy Cottage was too cramped for them all , so he told Bir'
800 wikistyle 172 ' The theme of family and family relationships — from the character @-@ defining experience'
900 wikistyle 77 ' In 2001 , Boosey & Hawkes was put up for sale after accounting irregularities were discov'
1000 wikistyle 107 ' In April 2006 , a team of astronomers , believing that Oval BA might converge with the GR'
1100 wikistyle 108 ' Just as Julie and Keys celebrate their victory , the dog , without warning , turns its at'
1200 wikistyle 184 ' Andrew Carnegie , an immigrant from Scotland , a former Pennsylvania Railroad executive t'
1300 wikistyle 176 ' In 1925 , US 112 was originally proposed to run from Oshkosh to Fremont , Wisconsin , on '
1400 wikistyle 78 ' Grissom is often regarded as well @-@ educated , but unusual in his approach toward his w'
1500 wikistyle 111 ' In his 2002 State of the Union Address , Bush referred to an axis of evil including Iraq '
1600 wikistyle 163 ' A solar cell , or photovoltaic cell ( PV ) , is a device that converts light into electri'
1700 wikistyle 165 ' The Kalpoe brothers were rearrested on August 26 along with another new suspect . Accordi'
1800 1790 'WASHINGTON — US President Donald Trump raised the prospect of Syria safe zones in a call w'
1900 605 'PETALING JAYA: Times are a-changing. Blue collar foreign workers in Malaysia are climbing '
2000 151 'Socialite Paris Hilton looked happy during her holiday in Formentera with her boyfriend Ch'
2100 559 'TREI-RB Recruitment 2018 Notification to fill 1972 vacancies for the posts of Post Graduat'
2200 928 'After five days of scouring the life of Las Vegas gunman Stephen Paddock and chasing 1,000'
2300 1624 'As the horrific details about gang-rape and murder of an eight-year-old girl from Jammu’s '
2400 html 1449 '<p>In the following, the echo output is right, but the pgm is not receiving the flags corr'
2500 html 289 '<p>in C# winforms when we display a message box it has no title in the title bar and no ti'
2600 html 589 "<p>I was wondering if there is a more elegant way to do IN() queries with Spring's JDBCTem"
2700 html 638 "<p>I'm working on a project which makes heavy use of extension methods to convert strings "
[stdout]
20000/182016 7s
40000/182016 13s
60000/182016 19s
=== domains ===
0 wikistyle 206 ' Beardmore was sufficiently impressed with Shackleton to offer financial support , but oth'
100 wikistyle 283 ' In the late Vedic period , around the 6th century BCE , the small states and chiefdoms of'
200 wikistyle 174 " Monroe was declared a ward of the state , and her mother 's friend , Grace McKee Goddard "
300 wikistyle 73 ' " Mystery Date " received steady viewership that was consistent with the ratings for the '
400 wikistyle 479 ' Chasen has appeared in other television programmes such as The Bill and The Harry Hill Sh'
500 wikistyle 151 ' Citizens were organized on the basis of centuries and tribes , which would each gather in'
600 wikistyle 159 ' Stricklett attended Santa Clara University , where he played college baseball for the San'
700 wikistyle 274 ' In 1968 , Lennon was told The Dairy Cottage was too cramped for them all , so he told Bir'
800 wikistyle 172 ' The theme of family and family relationships — from the character @-@ defining experience'
900 wikistyle 77 ' In 2001 , Boosey & Hawkes was put up for sale after accounting irregularities were discov'
1000 wikistyle 107 ' In April 2006 , a team of astronomers , believing that Oval BA might converge with the GR'
1100 wikistyle 108 ' Just as Julie and Keys celebrate their victory , the dog , without warning , turns its at'
1200 wikistyle 184 ' Andrew Carnegie , an immigrant from Scotland , a former Pennsylvania Railroad executive t'
1300 wikistyle 176 ' In 1925 , US 112 was originally proposed to run from Oshkosh to Fremont , Wisconsin , on '
1400 wikistyle 78 ' Grissom is often regarded as well @-@ educated , but unusual in his approach toward his w'
1500 wikistyle 111 ' In his 2002 State of the Union Address , Bush referred to an axis of evil including Iraq '
1600 wikistyle 163 ' A solar cell , or photovoltaic cell ( PV ) , is a device that converts light into electri'
1700 wikistyle 165 ' The Kalpoe brothers were rearrested on August 26 along with another new suspect . Accordi'
1800 1790 'WASHINGTON — US President Donald Trump raised the prospect of Syria safe zones in a call w'
1900 605 'PETALING JAYA: Times are a-changing. Blue collar foreign workers in Malaysia are climbing '
2000 151 'Socialite Paris Hilton looked happy during her holiday in Formentera with her boyfriend Ch'
2100 559 'TREI-RB Recruitment 2018 Notification to fill 1972 vacancies for the posts of Post Graduat'
2200 928 'After five days of scouring the life of Las Vegas gunman Stephen Paddock and chasing 1,000'
2300 1624 'As the horrific details about gang-rape and murder of an eight-year-old girl from Jammu’s '
2400 html 1449 '<p>In the following, the echo output is right, but the pgm is not receiving the flags corr'
2500 html 289 '<p>in C# winforms when we display a message box it has no title in the title bar and no ti'
2600 html 589 "<p>I was wondering if there is a more elegant way to do IN() queries with Spring's JDBCTem"
2700 html 638 "<p>I'm working on a project which makes heavy use of extension methods to convert strings "
[metadata] {"noOutputExpected": false}encrypted chain-of-thought — recorded, not exposed
args
{
"command": "tail -2 /workspace/cache/tok.log; python -c \"\nimport numpy as np\nfrom transformers import AutoTokenizer\ntok = AutoTokenizer.from_pretrained('gpt2')\nd=np.load('data/multi_dev.npy'); eos=np.where(d==50256)[0]\nsegs=[]; prev=0\nfor e in eos: segs.append(d[prev:e]); prev=e+1\nL=np.array([len(s) for s in segs]); c=np.cumsum(L)\nprint('total tok in segs', c[-1])\nfor q in [250_000,500_000,750_000]:\n i=int(np.searchsorted(c,q)); print('tok',q,'-> seg',i)\nfor i in [1750,1790,1795,1798,1799,1800,1805,1850,2380,2395,2399,2400]:\n print('--',i,L[i],repr(tok.decode(segs[i].tolist())[:110]))\n\" 2>&1 | tail -20",
"description": "Find token-weighted domain boundaries in dev"
}Bash result
100000/182016 31s
120000/182016 40s
total tok in segs 996890
tok 250000 -> seg 1714
tok 500000 -> seg 1918
tok 750000 -> seg 2348
-- 1750 3900 'CLOSE Residents of Watertown, Massachusetts erupted in cheers as Boston Marathon bombing suspect Dzhokhar Tsar'
-- 1790 284 'BEIRUT (Reuters) - Air strikes and government artillery killed at least 20 people, including 10 children, in t'
-- 1795 222 "The next entry in Giants Software's farming simulation series, Farming Simulator 2014, will be available for N"
-- 1798 304 'NYC construction groups blame insurers for 2 WTC holdup\n\nA city construction industry coalition is pushing ins'
-- 1799 343 'This article is from the archive of our partner .\n\nJust in time for his State of The Union address, the latest'
-- 1800 1790 'WASHINGTON — US President Donald Trump raised the prospect of Syria safe zones in a call with the Saudi king J'
-- 1805 303 "The government of Alberta has announced a formal review of the Workers' Compensation Board (WCB.)\n\nThe review,"
-- 1850 462 '“Game of Thrones” and “The Hunger Games” actress Natalie Dormer is to star as English headmistress Hester Appl'
-- 2380 261 '<p>I have a TextBox in a column with dynamic column:</p>\n\n<pre><code><Grid.ColumnDefinitions>\n <Co'
-- 2395 440 '<p>I tar a directory full of JPEG images: </p>\n\n<pre><code>tar cvfz myarchive.tar.gz mydirectory\n</code></pre>'
-- 2399 1244 '<p>I have a text file which looks like this:</p>\n\n<pre><code>blah blah\nfoo1 bar1\nfoo1 bar2\nfoo1 bar3\nfoo2 bar4'
-- 2400 1449 '<p>In the following, the echo output is right, but the pgm is not receiving the flags correctly. Appreciate an'
[stdout]
100000/182016 31s
120000/182016 40s
total tok in segs 996890
tok 250000 -> seg 1714
tok 500000 -> seg 1918
tok 750000 -> seg 2348
-- 1750 3900 'CLOSE Residents of Watertown, Massachusetts erupted in cheers as Boston Marathon bombing suspect Dzhokhar Tsar'
-- 1790 284 'BEIRUT (Reuters) - Air strikes and government artillery killed at least 20 people, including 10 children, in t'
-- 1795 222 "The next entry in Giants Software's farming simulation series, Farming Simulator 2014, will be available for N"
-- 1798 304 'NYC construction groups blame insurers for 2 WTC holdup\n\nA city construction industry coalition is pushing ins'
-- 1799 343 'This article is from the archive of our partner .\n\nJust in time for his State of The Union address, the latest'
-- 1800 1790 'WASHINGTON — US President Donald Trump raised the prospect of Syria safe zones in a call with the Saudi king J'
-- 1805 303 "The government of Alberta has announced a formal review of the Workers' Compensation Board (WCB.)\n\nThe review,"
-- 1850 462 '“Game of Thrones” and “The Hunger Games” actress Natalie Dormer is to star as English headmistress Hester Appl'
-- 2380 261 '<p>I have a TextBox in a column with dynamic column:</p>\n\n<pre><code><Grid.ColumnDefinitions>\n <Co'
-- 2395 440 '<p>I tar a directory full of JPEG images: </p>\n\n<pre><code>tar cvfz myarchive.tar.gz mydirectory\n</code></pre>'
-- 2399 1244 '<p>I have a text file which looks like this:</p>\n\n<pre><code>blah blah\nfoo1 bar1\nfoo1 bar2\nfoo1 bar3\nfoo2 bar4'
-- 2400 1449 '<p>In the following, the echo output is right, but the pgm is not receiving the flags correctly. Appreciate an'
[metadata] {"noOutputExpected": false}Tokenization is nearly done. The dev target decodes into 4 equal-token blocks: WikiText-style encyclopedic, general web prose, news, and StackExchange Q&A. Now building the selector.
args
{
"command": "sleep 25; tail -3 /workspace/cache/tok.log; ls -la /workspace/cache/",
"description": "Check tokenization completion"
}Bash result
160000/182016 68s
180000/182016 82s
DONE (199911772,) 199911772 82s
total 397365
drwxr-xr-x 1 root root 140 Aug 3 23:28 .
drwxr-xr-x 1 root root 160 Aug 3 23:26 ..
-rw-r--r-- 1 root root 4163402 Aug 3 23:27 dev_text.txt
-rw-r--r-- 1 root root 1456256 Aug 3 23:28 pool_ids.npy
-rw-r--r-- 1 root root 1456264 Aug 3 23:28 pool_offsets.npy
-rw-r--r-- 1 root root 399823672 Aug 3 23:28 pool_tokens.npy
-rw-r--r-- 1 root root 399 Aug 3 23:28 tok.log
[stdout]
160000/182016 68s
180000/182016 82s
DONE (199911772,) 199911772 82s
total 397365
drwxr-xr-x 1 root root 140 Aug 3 23:28 .
drwxr-xr-x 1 root root 160 Aug 3 23:26 ..
-rw-r--r-- 1 root root 4163402 Aug 3 23:27 dev_text.txt
-rw-r--r-- 1 root root 1456256 Aug 3 23:28 pool_ids.npy
-rw-r--r-- 1 root root 1456264 Aug 3 23:28 pool_offsets.npy
-rw-r--r-- 1 root root 399823672 Aug 3 23:28 pool_tokens.npy
-rw-r--r-- 1 root root 399 Aug 3 23:28 tok.log
[metadata] {"noOutputExpected": false}encrypted chain-of-thought — recorded, not exposed
args
{
"file_path": "/workspace/curate.py",
"content": "\"\"\"\nCurate /workspace/data/pool.jsonl -> /workspace/submission/selection.json\n\nSTATED CRITERION\n----------------\nKeep documents that are (a) fluent, non-degenerate English prose and (b) *distributionally\nclose to the disclosed evaluation target* -- a four-register mix of encyclopedic text,\ngeneral high-quality web prose, news, and technical Q&A.\n\nRegister-closeness is measured with four independent length-normalised unigram logistic\nregressions in GPT-2 BPE space. For register d, the positive class is the target text\nitself (recovered by decoding the provided dev token stream, which is a labelled-free\nsample of the target distribution) and the negative class is a uniform random sample of\nthe pool. The per-document score is the mean per-token log-odds\n\n s_d(doc) = b_d + (1/N) * sum_{i<N} w_d[ token_i ]\n\nwhich is exactly the LR decision value on length-normalised counts, so it is comparable\nacross documents of any length. This is a discriminative form of Moore-Lewis\ncross-entropy-difference selection.\n\nDocuments first pass a hard prose gate (length, stop-word rate, symbol/digit rate,\nnon-ASCII rate, repetition, near-duplicate removal), then are emitted by ROUND-ROBIN over\nthe four registers in descending s_d order. Round-robin is the point: the target is\n*equal parts* four registers, so the head of the priority list -- the part that actually\nfits in the 12M-token budget -- is balanced by construction instead of collapsing onto\nwhichever single register is easiest to separate from web noise.\n\nAll vocabulary-level statistics (word-ness, digits, punctuation, case, non-ASCII) are\nderived from a precomputed 50257-entry property table over the GPT-2 vocabulary, so every\ndocument statistic is a segment-reduction over the cached token stream: no second pass\nover the raw text is needed.\n\"\"\"\nimport json, os, re, sys, time\nimport numpy as np\n\nos.environ.setdefault(\"TOKENIZERS_PARALLELISM\", \"false\")\nimport torch\nfrom transformers import AutoTokenizer\n\nCACHE = \"/workspace/cache\"\nPOOL = \"/workspace/data/pool.jsonl\"\nDEV = \"/workspace/data/multi_dev.npy\"\nOUT = \"/workspace/submission/selection.json\"\nBUDGET = 12_000_000\nEMIT_TOKENS = int(os.environ.get(\"EMIT_TOKENS\", 30_000_000)) # provide >2x budget\nSEED = 0\n\n# --- knobs (overridable for ablation) -------------------------------------------------\nMIN_TOK = int(os.environ.get(\"MIN_TOK\", 128))\nMAX_TOK = int(os.environ.get(\"MAX_TOK\", 20000))\nMIN_STOP = float(os.environ.get(\"MIN_STOP\", 0.16))\nMAX_SYMB = float(os.environ.get(\"MAX_SYMB\", 0.28))\nMAX_DIGIT = float(os.environ.get(\"MAX_DIGIT\", 0.08))\nMAX_NONASCII = float(os.environ.get(\"MAX_NONASCII\", 0.06))\nMAX_UPPER = float(os.environ.get(\"MAX_UPPER\", 0.22))\nMIN_UNIQ = float(os.environ.get(\"MIN_UNIQ\", 0.18))\nMAX_TOPFREQ = float(os.environ.get(\"MAX_TOPFREQ\", 0.06))\nNEG_N = int(os.environ.get(\"NEG_N\", 40000))\nCHUNK = 256 # positive pseudo-document length (== training block size)\nVOCAB_KEEP = 24000 # feature vocabulary: most frequent GPT-2 ids in the pool\nL2 = float(os.environ.get(\"L2\", 3e-4))\nSTEPS = 400\nBALANCE = os.environ.get(\"BALANCE\", \"rr\") # rr | pooled\n\ntok = AutoTokenizer.from_pretrained(\"gpt2\")\n\n\n# ======================================================================================\n# 0. cached tokenisation of the pool\n# ======================================================================================\ndef tokenize_pool():\n \"\"\"One-time GPT-2 tokenisation of the pool, cached as flat uint16 + offsets.\"\"\"\n f_tok = f\"{CACHE}/pool_tokens.npy\"\n if os.path.exists(f_tok):\n return (np.load(f_tok), np.load(f\"{CACHE}/pool_offsets.npy\"),\n np.load(f\"{CACHE}/pool_ids.npy\"))\n os.makedirs(CACHE, exist_ok=True)\n os.environ[\"TOKENIZERS_PARALLELISM\"] = \"true\"\n ids, texts = [], []\n for line in open(POOL):\n r = json.loads(line)\n ids.append(r[\"id\"]); texts.append(r[\"text\"])\n flat, lens = [], np.zeros(len(texts), dtype=np.int64)\n k = 0\n for s in range(0, len(texts), 2000):\n for e in tok(texts[s:s + 2000], add_special_tokens=False)[\"input_ids\"]:\n lens[k] = len(e); k += 1\n flat.append(np.asarray(e, dtype=np.uint16))\n flat = np.concatenate(flat)\n off = np.zeros(len(texts) + 1, dtype=np.int64); np.cumsum(lens, out=off[1:])\n ids = np.asarray(ids, dtype=np.int64)\n np.save(f_tok, flat); np.save(f\"{CACHE}/pool_offsets.npy\", off)\n np.save(f\"{CACHE}/pool_ids.npy\", ids)\n return flat, off, ids\n\n\n# ======================================================================================\n# 1. GPT-2 vocabulary property table -> every doc statistic is a segment reduction\n# ======================================================================================\nSTOPWORDS = set(\"\"\"the of and to a in that is was it for as with his he on be at by i this\nhad not are but from or have an they which one you were her all she there would their we him\nbeen has when who will no more if out so said what up its about into them can only other new\nsome could time these two then do now my than may made over did down way our me any where\nmost after also back your very us man such because through even how must does before here\neach much own between should those while both under three same another year years people world\nbeing use used using\"\"\".split())\n\n\ndef vocab_tables():\n \"\"\"Per-id lexical properties for the whole GPT-2 vocabulary.\"\"\"\n V = 50257\n strs = tok.convert_ids_to_tokens(list(range(V)))\n strs = [s.replace(\"Ġ\", \" \").replace(\"Ċ\", \"\\n\") for s in strs]\n is_word = np.zeros(V, bool); is_digit = np.zeros(V, bool)\n is_symb = np.zeros(V, bool); is_upper = np.zeros(V, bool)\n is_nonascii = np.zeros(V, bool); is_stop = np.zeros(V, bool)\n nchar = np.zeros(V, np.float32)\n for i, s in enumerate(strs):\n c = s.strip(); nchar[i] = len(s)\n if not c:\n is_symb[i] = True; continue\n a = c[0]\n if a.isalpha():\n is_word[i] = True\n if a.isupper(): is_upper[i] = True\n if c.lower() in STOPWORDS: is_stop[i] = True\n elif a.isdigit():\n is_digit[i] = True\n else:\n is_symb[i] = True\n if any(ord(ch) > 127 for ch in c): is_nonascii[i] = True\n return dict(word=is_word, digit=is_digit, symb=is_symb, upper=is_upper,\n nonascii=is_nonascii, stop=is_stop, nchar=nchar)\n\n\ndef doc_means(flat, off, table):\n \"\"\"Mean of a per-id property over each document (vectorised segment reduction).\"\"\"\n v = table[flat]\n if v.dtype == bool: v = v.view(np.uint8)\n cs = np.concatenate(([0], np.cumsum(v, dtype=np.float64)))\n n = np.maximum(off[1:] - off[:-1], 1)\n return ((cs[off[1:]] - cs[off[:-1]]) / n).astype(np.float32)\n\n\n# ======================================================================================\n# 2. recover the four target registers from the dev token stream\n# ======================================================================================\nWIKI_FIX = [(\" @-@ \", \"-\"), (\" @.@ \", \".\"), (\" @,@ \", \",\"), (\"@-@\", \"-\"),\n (\" 's\", \"'s\"), (\" n't\", \"n't\"), (\" 'll\", \"'ll\"), (\" 're\", \"'re\"),\n (\" 've\", \"'ve\"), (\" 'm\", \"'m\"), (\" ,\", \",\"), (\" .\", \".\"), (\" ;\", \";\"),\n (\" :\", \":\"), (\" !\", \"!\"), (\" ?\", \"?\"), (\" %\", \"%\"), (\" )\", \")\"),\n (\"( \", \"(\"), (\" ]\", \"]\"), (\"[ \", \"[\"), (\" 'd\", \"'d\")]\n\n\ndef denorm_wikitext(t):\n \"\"\"WikiText ships pre-tokenised (spaced punctuation, @-@ ). Raw web text never looks\n like that, so undo it -- otherwise the classifier keys on a formatting artefact that\n carries no information about which pool documents are useful.\"\"\"\n for a, b in WIKI_FIX: t = t.replace(a, b)\n return re.sub(r\" +\", \" \", t)\n\n\ndef target_registers():\n d = np.load(DEV)\n eos = np.where(d == 50256)[0]\n segs, prev = [], 0\n for e in eos:\n if e > prev: segs.append(d[prev:e])\n prev = e + 1\n L = np.array([len(s) for s in segs]); c = np.cumsum(L)\n # four equal-token blocks: encyclopedic | general web prose | news | technical Q&A\n cut = [0] + [int(np.searchsorted(c, q)) for q in (250_000, 500_000, 750_000)] + [len(segs)]\n names = [\"wiki\", \"web\", \"news\", \"qa\"]\n out = {}\n for k, nm in enumerate(names):\n txt = \"\\n\\n\".join(tok.decode(s.tolist()) for s in segs[cut[k]:cut[k + 1]])\n if nm == \"wiki\": txt = denorm_wikitext(txt)\n ids = tok(txt, add_special_tokens=False)[\"input_ids\"]\n ids = np.asarray(ids, dtype=np.int32)\n n = len(ids) // CHUNK\n out[nm] = ids[:n * CHUNK].reshape(n, CHUNK)\n return names, out\n\n\n# ======================================================================================\n# 3. length-normalised unigram logistic regression, one per register\n# ======================================================================================\ndef counts_matrix(chunks, vmap, V):\n \"\"\"rows = length-normalised token counts restricted to the feature vocabulary.\"\"\"\n x = torch.zeros(len(chunks), V, device=\"cuda\")\n idx = torch.from_numpy(vmap[chunks]).cuda().long()\n src = torch.ones_like(idx, dtype=torch.float32)\n x.scatter_add_(1, idx, src)\n x[:, 0] = 0.0 # column 0 = out-of-vocabulary sink\n return x / x.sum(1, keepdim=True).clamp(min=1)\n\n\ndef fit_lr(xp, xn, l2, steps=STEPS):\n \"\"\"Class-balanced logistic regression, full-batch LBFGS-free Adam.\"\"\"\n V = xp.shape[1]\n w = torch.zeros(V, device=\"cuda\", requires_grad=True)\n b = torch.zeros(1, device=\"cuda\", requires_grad=True)\n opt = torch.optim.Adam([w, b], lr=0.05)\n for _ in range(steps):\n lp = xp @ w + b\n ln = xn @ w + b\n loss = (torch.nn.functional.softplus(-lp).mean()\n + torch.nn.functional.softplus(ln).mean()) * 0.5 + l2 * (w * w).sum()\n opt.zero_grad(); loss.backward(); opt.step()\n return w.detach(), b.detach().item()\n\n\n# ======================================================================================\ndef main():\n t0 = time.time()\n flat, off, pool_ids = tokenize_pool()\n ndoc = len(pool_ids); ntok = (off[1:] - off[:-1]).astype(np.int64)\n print(f\"pool {ndoc} docs / {ntok.sum()/1e6:.1f}M tokens ({time.time()-t0:.0f}s)\")\n\n # ---- prose gate ------------------------------------------------------------------\n T = vocab_tables()\n st = {k: doc_means(flat, off, T[k]) for k in (\"stop\", \"digit\", \"symb\", \"upper\", \"nonascii\")}\n\n # repetition statistics: unique-token ratio and most-frequent-token share\n uniq = np.zeros(ndoc, np.float32); topf = np.zeros(ndoc, np.float32)\n for i in range(ndoc):\n s, e = off[i], off[i + 1]\n if e <= s: continue\n _, cnt = np.unique(flat[s:e], return_counts=True)\n uniq[i] = len(cnt) / (e - s); topf[i] = cnt.max() / (e - s)\n\n keep = ((ntok >= MIN_TOK) & (ntok <= MAX_TOK) & (st[\"stop\"] >= MIN_STOP)\n & (st[\"symb\"] <= MAX_SYMB) & (st[\"digit\"] <= MAX_DIGIT)\n & (st[\"nonascii\"] <= MAX_NONASCII) & (st[\"upper\"] <= MAX_UPPER)\n & (uniq >= MIN_UNIQ) & (topf <= MAX_TOPFREQ))\n print(f\"prose gate keeps {keep.sum()} / {ndoc} ({keep.mean()*100:.1f}%)\")\n\n # ---- near-duplicate removal ------------------------------------------------------\n def sig(a, b):\n h = np.zeros(ndoc, np.int64)\n for i in np.flatnonzero(keep):\n s, e = off[i], off[i + 1]; n = e - s\n p = s + int(n * a)\n h[i] = hash(flat[p:min(p + b, e)].tobytes())\n return h\n seen, dup = set(), np.zeros(ndoc, bool)\n for h in (sig(0.0, 48), sig(0.30, 48)):\n for i in np.flatnonzero(keep & ~dup):\n if h[i] in seen: dup[i] = True\n else: seen.add(h[i])\n keep &= ~dup\n print(f\"after dedup {keep.sum()} (-{dup.sum()}) ({time.time()-t0:.0f}s)\")\n\n # ---- feature vocabulary ----------------------------------------------------------\n freq = np.bincount(flat.astype(np.int64), minlength=50257)\n top = np.argsort(-freq)[:VOCAB_KEEP - 1]\n vmap = np.zeros(50257, np.int32) # 0 == OOV sink\n vmap[top] = np.arange(1, len(top) + 1, dtype=np.int32)\n V = VOCAB_KEEP\n\n # ---- train one register classifier per target block ------------------------------\n names, regs = target_registers()\n rng = np.random.default_rng(SEED)\n cand = np.flatnonzero(keep)\n negsrc = rng.choice(ndoc, size=min(NEG_N, ndoc), replace=False)\n neg_chunks = []\n for i in negsrc: # 256-token window per negative doc\n s, e = off[i], off[i + 1]\n if e - s < CHUNK: continue\n p = s + (e - s - CHUNK) // 2\n neg_chunks.append(flat[p:p + CHUNK].astype(np.int32))\n neg_chunks = np.stack(neg_chunks)\n xn = counts_matrix(neg_chunks, vmap, V)\n print(f\"neg {xn.shape} ({time.time()-t0:.0f}s)\")\n\n # per-document mean weight = LR decision value on length-normalised counts\n scores = {}\n flat_mapped = torch.from_numpy(vmap[flat.astype(np.int32)]).cuda().long()\n seg_end = torch.from_numpy(off[1:]).cuda()\n seg_beg = torch.from_numpy(off[:-1]).cuda()\n for nm in names:\n xp = counts_matrix(regs[nm], vmap, V)\n w, b = fit_lr(xp, xn, L2)\n with torch.no_grad():\n wv = w[flat_mapped] # weight of every pool token\n wv[flat_mapped == 0] = 0.0\n cs = torch.cat([torch.zeros(1, device=\"cuda\", dtype=torch.float64),\n torch.cumsum(wv.double(), 0)])\n tot = cs[seg_end] - cs[seg_beg]\n n = (seg_end - seg_beg).clamp(min=1).double()\n scores[nm] = (tot / n + b).float().cpu().numpy()\n acc = ((xp @ w + b > 0).float().mean().item(), (xn @ w + b < 0).float().mean().item())\n print(f\" {nm}: train pos-acc {acc[0]:.3f} neg-acc {acc[1]:.3f} ({time.time()-t0:.0f}s)\")\n del wv, cs\n torch.cuda.empty_cache()\n\n # ---- emit: round-robin over registers by descending score ------------------------\n order = {nm: cand[np.argsort(-scores[nm][cand])] for nm in names}\n sel, taken, tot = [], np.zeros(ndoc, bool), 0\n if BALANCE == \"pooled\":\n z = np.mean([(scores[nm] - scores[nm][cand].mean()) / (scores[nm][cand].std() + 1e-9)\n for nm in names], axis=0)\n for i in cand[np.argsort(-z[cand])]:\n sel.append(int(pool_ids[i])); tot += ntok[i] + 1\n if tot >= EMIT_TOKENS: break\n else:\n ptr = {nm: 0 for nm in names}\n while tot < EMIT_TOKENS:\n progress = False\n for nm in names:\n o = order[nm]\n while ptr[nm] < len(o) and taken[o[ptr[nm]]]: ptr[nm] += 1\n if ptr[nm] >= len(o): continue\n i = o[ptr[nm]]; ptr[nm] += 1; taken[i] = True\n sel.append(int(pool_ids[i])); tot += ntok[i] + 1; progress = True\n if not progress: break\n\n assert len(sel) == len(set(sel))\n os.makedirs(os.path.dirname(OUT), exist_ok=True)\n json.dump(sel, open(os.environ.get(\"OUT\", OUT), \"w\"))\n print(f\"wrote {len(sel)} ids ~{tot/1e6:.1f}M tokens (budget {BUDGET/1e6:.0f}M) \"\n f\"({time.time()-t0:.0f}s)\")\n\n\nif __name__ == \"__main__\":\n main()\n"
}Write result
File created successfully at: /workspace/curate.py (file state is current in your context — no need to Read it back)
[metadata] {"type": "create", "filePath": "/workspace/curate.py", "content": "\"\"\"\nCurate /workspace/data/pool.jsonl -> /workspace/submission/selection.json\n\nSTATED CRITERION\n----------------\nKeep documents that are (a) fluent, non-degenerate English prose and (b) *distributionally\nclose to the disclosed evaluation target* -- a four-register mix of encyclopedic text,\ngeneral high-quality web prose, news, and technical Q&A.\n\nRegister-closeness is measured with four independent length-normalised unigram logistic\nregressions in GPT-2 BPE space. For register d, the positive class is the target text\nitself (recovered by decoding the provided dev token stream, which is a labelled-free\nsample of the target distribution) and the negative class is a uniform random sample of\nthe pool. The per-document score is the mean per-token log-odds\n\n s_d(doc) = b_d + (1/N) * sum_{i<N} w_d[ token_i ]\n\nwhich is exactly the LR decision value on length-normalised counts, so it is comparable\nacross documents of any length. This is a discriminative form of Moore-Lewis\ncross-entropy-difference selection.\n\nDocuments first pass a hard prose gate (length, stop-word rate, symbol/digit rate,\nnon-ASCII rate, repetition, near-duplicate removal), then are emitted by ROUND-ROBIN over\nthe four registers in descending s_d order. Round-robin is the point: the target is\n*equal parts* four registers, so the head of the priority list -- the part that actually\nfits in the 12M-token budget -- is balanced by construction instead of collapsing onto\nwhichever single register is easiest to separate from web noise.\n\nAll vocabulary-level statistics (word-ness, digits, punctuation, case, non-ASCII) are\nderived from a precomputed 50257-entry property table over the GPT-2 vocabulary, so every\ndocument statistic is a segment-reduction over the cached token stream: no second pass\nover the raw text is needed.\n\"\"\"\nimport json, os, re, sys, time\nimport numpy as np\n\nos.environ.setdefault(\"TOKENIZERS_PARALLELISM\", \"false\")\nimport torch\nfrom transformers import AutoTokenizer\n\nCACHE = \"/workspace/cache\"\nPOOL = \"/workspace/data/pool.jsonl\"\nDEV = \"/workspace/data/multi_dev.npy\"\nOUT = \"/workspace/submission/selection.json\"\nBUDGET = 12_000_000\nEMIT_TOKENS = int(os.environ.get(\"EMIT_TOKENS\", 30_000_000)) # provide >2x budget\nSEED = 0\n\n# --- knobs (overridable for ablation) -------------------------------------------------\nMIN_TOK = int(os.environ.get(\"MIN_TOK\", 128))\nMAX_TOK = int(os.environ.get(\"MAX_TOK\", 20000))\nMIN_STOP = float(os.environ.get(\"MIN_STOP\", 0.16))\nMAX_SYMB = float(os.environ.get(\"MAX_SYMB\", 0.28))\nMAX_DIGIT = float(os.environ.get(\"MAX_DIGIT\", 0.08))\nMAX_NONASCII = float(os.environ.get(\"MAX_NONASCII\", 0.06))\nMAX_UPPER = float(os.environ.get(\"MAX_UPPER\", 0.22))\nMIN_UNIQ = float(os.environ.get(\"MIN_UNIQ\", 0.18))\nMAX_TOPFREQ = float(os.environ.get(\"MAX_TOPFREQ\", 0.06))\nNEG_N = int(os.environ.get(\"NEG_N\", 40000))\nCHUNK = 256 # positive pseudo-document length (== training block size)\nVOCAB_KEEP = 24000 # feature vocabulary: most frequent GPT-2 ids in the pool\nL2 = float(os.environ.get(\"L2\", 3e-4))\nSTEPS = 400\nBALANCE = os.environ.get(\"BALANCE\", \"rr\") # rr | pooled\n\ntok = AutoTokenizer.from_pretrained(\"gpt2\")\n\n\n# ======================================================================================\n# 0. cached tokenisation of the pool\n# ======================================================================================\ndef tokenize_pool():\n \"\"\"One-time GPT-2 tokenisation of the pool, cached as flat uint16 + offsets.\"\"\"\n f_tok = f\"{CACHE}/pool_tokens.npy\"\n if os.path.exists(f_tok):\n return (np.load(f_tok), np.load(f\"{CACHE}/pool_offsets.npy\"),\n np.load(f\"{CACHE}/pool_ids.npy\"))\n os.makedirs(CACHE, exist_ok=True)\n os.environ[\"TOKENIZERS_PARALLELISM\"] = \"true\"\n ids, texts = [], []\n for line in open(POOL):\n r = json.loads(line)\n ids.append(r[\"id\"]); texts.append(r[\"text\"])\n flat, lens = [], np.zeros(len(texts), dtype=np.int64)\n k = 0\n for s in range(0, len(texts), 2000):\n for e in tok(texts[s:s + 2000], add_special_tokens=False)[\"input_ids\"]:\n lens[k] = len(e); k += 1\n flat.append(np.asarray(e, dtype=np.uint16))\n flat = np.concatenate(flat)\n off = np.zeros(len(texts) + 1, dtype=np.int64); np.cumsum(lens, out=off[1:])\n ids = np.asarray(ids, dtype=np.int64)\n np.save(f_tok, flat); np.save(f\"{CACHE}/pool_offsets.npy\", off)\n np.save(f\"{CACHE}/pool_ids.npy\", ids)\n return flat, off, ids\n\n\n# ======================================================================================\n# 1. GPT-2 vocabulary property table -> every doc statistic is a segment reduction\n# ======================================================================================\nSTOPWORDS = set(\"\"\"the of and to a in that is was it for as with his he on be at by i this\nhad not are but from or have an they which one you were her all she there would their we him\nbeen has when who will no more if out so said what up its about into them can only other new\nsome could time these two then do now my than may made over did down way our me any where\nmost after also back your very us man such because through even how must does before here\neach much own between should those while both under three same another year years people world\nbeing use used using\"\"\".split())\n\n\ndef vocab_tables():\n \"\"\"Per-id lexical properties for the whole GPT-2 vocabulary.\"\"\"\n V = 50257\n strs = tok.convert_ids_to_tokens(list(range(V)))\n strs = [s.replace(\"Ġ\", \" \").replace(\"Ċ\", \"\\n\") for s in strs]\n is_word = np.zeros(V, bool); is_digit = np.zeros(V, bool)\n is_symb = np.zeros(V, bool); is_upper = np.zeros(V, bool)\n is_nonascii = np.zeros(V, bool); is_stop = np.zeros(V, bool)\n nchar = np.zeros(V, np.float32)\n for i, s in enumerate(strs):\n c = s.strip(); nchar[i] = len(s)\n if not c:\n is_symb[i] = True; continue\n a = c[0]\n if a.isalpha():\n is_word[i] = True\n if a.isupper(): is_upper[i] = True\n if c.lower() in STOPWORDS: is_stop[i] = True\n elif a.isdigit():\n is_digit[i] = True\n else:\n is_symb[i] = True\n if any(ord(ch) > 127 for ch in c): is_nonascii[i] = True\n return dict(word=is_word, digit=is_digit, symb=is_symb, upper=is_upper,\n nonascii=is_nonascii, stop=is_stop, nchar=nchar)\n\n\ndef doc_means(flat, off, table):\n \"\"\"Mean of a per-id property over each document (vectorised segment reduction).\"\"\"\n v = table[flat]\n if v.dtype == bool: v = v.view(np.uint8)\n cs = np.concatenate(([0], np.cumsum(v, dtype=np.float64)))\n n = np.maximum(off[1:] - off[:-1], 1)\n return ((cs[off[1:]] - cs[off[:-1]]) / n).astype(np.float32)\n\n\n# ======================================================================================\n# 2. recover the four target registers from the dev token stream\n# ======================================================================================\nWIKI_FIX = [(\" @-@ \", \"-\"), (\" @.@ \", \".\"), (\" @,@ \", \",\"), (\"@-@\", \"-\"),\n (\" 's\", \"'s\"), (\" n't\", \"n't\"), (\" 'll\", \"'ll\"), (\" 're\", \"'re\"),\n (\" 've\", \"'ve\"), (\" 'm\", \"'m\"), (\" ,\", \",\"), (\" .\", \".\"), (\" ;\", \";\"),\n (\" :\", \":\"), (\" !\", \"!\"), (\" ?\", \"?\"), (\" %\", \"%\"), (\" )\", \")\"),\n (\"( \", \"(\"), (\" ]\", \"]\"), (\"[ \", \"[\"), (\" 'd\", \"'d\")]\n\n\ndef denorm_wikitext(t):\n \"\"\"WikiText ships pre-tokenised (spaced punctuation, @-@ ). Raw web text never looks\n like that, so undo it -- otherwise the classifier keys on a formatting artefact that\n carries no information about which pool documents are useful.\"\"\"\n for a, b in WIKI_FIX: t = t.replace(a, b)\n return re.sub(r\" +\", \" \", t)\n\n\ndef target_registers():\n d = np.load(DEV)\n eos = np.where(d == 50256)[0]\n segs, prev = [], 0\n for e in eos:\n if e > prev: segs.append(d[prev:e])\n prev = e + 1\n L = np.array([len(s) for s in segs]); c = np.cumsum(L)\n # four equal-token blocks: encyclopedic | general web prose | news | technical Q&A\n cut = [0] + [int(np.searchsorted(c, q)) for q in (250_000, 500_000, 750_000)] + [len(segs)]\n names = [\"wiki\", \"web\", \"news\", \"qa\"]\n out = {}\n for k, nm in enumerate(names):\n txt = \"\\n\\n\".join(tok.decode(s.tolist()) for s in segs[cut[k]:cut[k + 1]])\n if nm == \"wiki\": txt = denorm_wikitext(txt)\n ids = tok(txt, add_special_tokens=False)[\"input_ids\"]\n ids = np.asarray(ids, dtype=np.int32)\n n = len(ids) // CHUNK\n out[nm] = ids[:n * CHUNK].reshape(n, CHUNK)\n return names, out\n\n\n# ======================================================================================\n# 3. length-normalised unigram logistic regression, one per register\n# ======================================================================================\ndef counts_matrix(chunks, vmap, V):\n \"\"\"rows = length-normalised token counts restricted to the feature vocabulary.\"\"\"\n x = torch.zeros(len(chunks), V, device=\"cuda\")\n idx = torch.from_numpy(vmap[chunks]).cuda().long()\n src = torch.ones_like(idx, dtype=torch.float32)\n x.scatter_add_(1, idx, src)\n x[:, 0] = 0.0 # column 0 = out-of-vocabulary sink\n return x / x.sum(1, keepdim=True).clamp(min=1)\n\n\ndef fit_lr(xp, xn, l2, steps=STEPS):\n \"\"\"Class-balanced logistic regression, full-batch LBFGS-free Adam.\"\"\"\n V = xp.shape[1]\n w = torch.zeros(V, device=\"cuda\", requires_grad=True)\n b = torch.zeros(1, device=\"cuda\", requires_grad=True)\n opt = torch.optim.Adam([w, b], lr=0.05)\n for _ in range(steps):\n lp = xp @ w + b\n ln = xn @ w + b\n loss = (torch.nn.functional.softplus(-lp).mean()\n + torch.nn.functional.softplus(ln).mean()) * 0.5 + l2 * (w * w).sum()\n opt.zero_grad(); loss.backward(); opt.step()\n return w.detach(), b.detach().item()\n\n\n# ======================================================================================\ndef main():\n t0 = time.time()\n flat, off, pool_ids = tokenize_pool()\n ndoc = len(pool_ids); ntok = (off[1:] - off[:-1]).astype(np.int64)\n print(f\"pool {ndoc} docs / {ntok.sum()/1e6:.1f}M tokens ({time.time()-t0:.0f}s)\")\n\n # ---- prose gate ------------------------------------------------------------------\n T = vocab_tables()\n st = {k: doc_means(flat, off, T[k]) for k in (\"stop\", \"digit\", \"symb\", \"upper\", \"nonascii\")}\n\n # repetition statistics: unique-token ratio and most-frequent-token share\n uniq = np.zeros(ndoc, np.float32); topf = np.zeros(ndoc, np.float32)\n for i in range(ndoc):\n s, e = off[i], off[i + 1]\n if e <= s: continue\n _, cnt = np.unique(flat[s:e], return_counts=True)\n uniq[i] = len(cnt) / (e - s); topf[i] = cnt.max() / (e - s)\n\n keep = ((ntok >= MIN_TOK) & (ntok <= MAX_TOK) & (st[\"stop\"] >= MIN_STOP)\n & (st[\"symb\"] <= MAX_SYMB) & (st[\"digit\"] <= MAX_DIGIT)\n & (st[\"nonascii\"] <= MAX_NONASCII) & (st[\"upper\"] <= MAX_UPPER)\n & (uniq >= MIN_UNIQ) & (topf <= MAX_TOPFREQ))\n print(f\"prose gate keeps {keep.sum()} / {ndoc} ({keep.mean()*100:.1f}%)\")\n\n # ---- near-duplicate removal ------------------------------------------------------\n def sig(a, b):\n h = np.zeros(ndoc, np.int64)\n for i in np.flatnonzero(keep):\n s, e = off[i], off[i + 1]; n = e - s\n p = s + int(n * a)\n h[i] = hash(flat[p:min(p + b, e)].tobytes())\n return h\n seen, dup = set(), np.zeros(ndoc, bool)\n for h in (sig(0.0, 48), sig(0.30, 48)):\n for i in np.flatnonzero(keep & ~dup):\n if h[i] in seen: dup[i] = True\n else: seen.add(h[i])\n keep &= ~dup\n print(f\"after dedup {keep.sum()} (-{dup.sum()}) ({time.time()-t0:.0f}s)\")\n\n # ---- feature vocabulary ----------------------------------------------------------\n freq = np.bincount(flat.astype(np.int64), minlength=50257)\n top = np.argsort(-freq)[:VOCAB_KEEP - 1]\n vmap = np.zeros(50257, np.int32) # 0 == OOV sink\n vmap[top] = np.arange(1, len(top) + 1, dtype=np.int32)\n V = VOCAB_KEEP\n\n # ---- train one register classifier per target block ------------------------------\n names, regs = target_registers()\n rng = np.random.default_rng(SEED)\n cand = np.flatnonzero(keep)\n negsrc = rng.choice(ndoc, size=min(NEG_N, ndoc), replace=False)\n neg_chunks = []\n for i in negsrc: # 256-token window per negative doc\n s, e = off[i], off[i + 1]\n if e - s < CHUNK: continue\n p = s + (e - s - CHUNK) // 2\n neg_chunks.append(flat[p:p + CHUNK].astype(np.int32))\n neg_chunks = np.stack(neg_chunks)\n xn = counts_matrix(neg_chunks, vmap, V)\n print(f\"neg {xn.shape} ({time.time()-t0:.0f}s)\")\n\n # per-document mean weight = LR decision value on length-normalised counts\n scores = {}\n flat_mapped = torch.from_numpy(vmap[flat.astype(np.int32)]).cuda().long()\n seg_end = torch.from_numpy(off[1:]).cuda()\n seg_beg = torch.from_numpy(off[:-1]).cuda()\n for nm in names:\n xp = counts_matrix(regs[nm], vmap, V)\n w, b = fit_lr(xp, xn, L2)\n with torch.no_grad():\n wv = w[flat_mapped] # weight of every pool token\n wv[flat_mapped == 0] = 0.0\n cs = torch.cat([torch.zeros(1, device=\"cuda\", dtype=torch.float64),\n torch.cumsum(wv.double(), 0)])\n tot = cs[seg_end] - cs[seg_beg]\n n = (seg_end - seg_beg).clamp(min=1).double()\n scores[nm] = (tot / n + b).float().cpu().numpy()\n acc = ((xp @ w + b > 0).float().mean().item(), (xn @ w + b < 0).float().mean().item())\n print(f\" {nm}: train pos-acc {acc[0]:.3f} neg-acc {acc[1]:.3f} ({time.time()-t0:.0f}s)\")\n del wv, cs\n torch.cuda.empty_cache()\n\n # ---- emit: round-robin over registers by descending score ------------------------\n order = {nm: cand[np.argsort(-scores[nm][cand])] for nm in names}\n sel, taken, tot = [], np.zeros(ndoc, bool), 0\n if BALANCE == \"pooled\":\n z = np.mean([(scores[nm] - scores[nm][cand].mean()) / (scores[nm][cand].std() + 1e-9)\n for nm in names], axis=0)\n for i in cand[np.argsort(-z[cand])]:\n sel.append(int(pool_ids[i])); tot += ntok[i] + 1\n if tot >= EMIT_TOKENS: break\n else:\n ptr = {nm: 0 for nm in names}\n while tot < EMIT_TOKENS:\n progress = False\n for nm in names:\n o = order[nm]\n while ptr[nm] < len(o) and taken[o[ptr[nm]]]: ptr[nm] += 1\n if ptr[nm] >= len(o): continue\n i = o[ptr[nm]]; ptr[nm] += 1; taken[i] = True\n sel.append(int(pool_ids[i])); tot += ntok[i] + 1; progress = True\n if not progress: break\n\n assert len(sel) == len(set(sel))\n os.makedirs(os.path.dirname(OUT), exist_ok=True)\n json.dump(sel, open(os.environ.get(\"OUT\", OUT), \"w\"))\n print(f\"wrote {len(sel)} ids ~{tot/1e6:.1f}M tokens (budget {BUDGET/1e6:.0f}M) \"\n f\"({time.time()-t0:.0f}s)\")\n\n\nif __name__ == \"__main__\":\n main()\n", "structuredPatch": [], "originalFile": null, "userModified": false}encrypted chain-of-thought — recorded, not exposed
args
{
"file_path": "/workspace/fastpack.py",
"content": "\"\"\"Fast dev-side packer: same semantics as pack_selection.py but reuses the cached\nGPT-2 tokenisation instead of re-tokenising (identical output, seconds instead of minutes).\"\"\"\nimport json, sys, numpy as np\nSEL = sys.argv[1]; OUT = sys.argv[2]; BUDGET = 12_000_000\nflat = np.load(\"/workspace/cache/pool_tokens.npy\")\noff = np.load(\"/workspace/cache/pool_offsets.npy\")\nids = np.load(\"/workspace/cache/pool_ids.npy\")\npos = {int(v): k for k, v in enumerate(ids)}\nsel = json.load(open(SEL))\nparts, tot = [], 0\nfor i in sel:\n k = pos[i]; a, b = off[k], off[k + 1]\n parts.append(flat[a:b]); parts.append(np.array([50256], np.uint16))\n tot += (b - a) + 1\n if tot >= BUDGET: break\narr = np.concatenate(parts)[:BUDGET]\nnp.save(OUT, arr)\nprint(f\"packed {len(arr)} tokens from {len(sel)} ids -> {OUT}\")\n"
}Write result
File created successfully at: /workspace/fastpack.py (file state is current in your context — no need to Read it back)
[metadata] {"type": "create", "filePath": "/workspace/fastpack.py", "content": "\"\"\"Fast dev-side packer: same semantics as pack_selection.py but reuses the cached\nGPT-2 tokenisation instead of re-tokenising (identical output, seconds instead of minutes).\"\"\"\nimport json, sys, numpy as np\nSEL = sys.argv[1]; OUT = sys.argv[2]; BUDGET = 12_000_000\nflat = np.load(\"/workspace/cache/pool_tokens.npy\")\noff = np.load(\"/workspace/cache/pool_offsets.npy\")\nids = np.load(\"/workspace/cache/pool_ids.npy\")\npos = {int(v): k for k, v in enumerate(ids)}\nsel = json.load(open(SEL))\nparts, tot = [], 0\nfor i in sel:\n k = pos[i]; a, b = off[k], off[k + 1]\n parts.append(flat[a:b]); parts.append(np.array([50256], np.uint16))\n tot += (b - a) + 1\n if tot >= BUDGET: break\narr = np.concatenate(parts)[:BUDGET]\nnp.save(OUT, arr)\nprint(f\"packed {len(arr)} tokens from {len(sel)} ids -> {OUT}\")\n", "structuredPatch": [], "originalFile": null, "userModified": false}encrypted chain-of-thought — recorded, not exposed
args
{
"command": "nohup python curate.py > cache/cur1.log 2>&1 & echo launched\n# meanwhile: random baseline selection for reference\npython -c \"\nimport numpy as np, json\nids=np.load('/workspace/cache/pool_ids.npy'); off=np.load('/workspace/cache/pool_offsets.npy')\nntok=off[1:]-off[:-1]\nrng=np.random.default_rng(1234); p=rng.permutation(len(ids))\nsel=[];tot=0\nfor i in p:\n sel.append(int(ids[i])); tot+=ntok[i]+1\n if tot>=30_000_000: break\njson.dump(sel, open('/workspace/cache/sel_random.json','w')); print('random baseline ids',len(sel),tot/1e6)\n\"",
"description": "Run curate.py; build random baseline selection"
}Bash result
launched
random baseline ids 27678 30.000132
[stdout]
launched
random baseline ids 27678 30.000132
[metadata] {"noOutputExpected": false}encrypted chain-of-thought — recorded, not exposed
args
{
"command": "python fastpack.py cache/sel_random.json /tmp/rand.npy && echo \"--- curate log ---\" && cat cache/cur1.log",
"description": "Pack random baseline; check curate progress"
}Bash result
packed 12000000 tokens from 27678 ids -> /tmp/rand.npy
--- curate log ---
[stdout]
packed 12000000 tokens from 27678 ids -> /tmp/rand.npy
--- curate log ---
[metadata] {"noOutputExpected": false}encrypted chain-of-thought — recorded, not exposed
args
{
"command": "sleep 45; cat cache/cur1.log; cat /workspace/.timer/remaining_secs",
"description": "Check curate progress and time"
}Bash result
Token indices sequence length is longer than the specified maximum sequence length for this model (242922 > 1024). Running this sequence through the model will result in indexing errors
pool 182016 docs / 199.9M tokens (0s)
prose gate keeps 63475 / 182016 (34.9%)
after dedup 62733 (-742) (19s)
neg torch.Size([29835, 24000]) (24s)
wiki: train pos-acc 0.988 neg-acc 0.749 (26s)
web: train pos-acc 0.766 neg-acc 0.479 (27s)
news: train pos-acc 0.968 neg-acc 0.594 (27s)
qa: train pos-acc 0.937 neg-acc 0.998 (28s)
wrote 34072 ids ~30.0M tokens (budget 12M) (28s)
5039
[stdout]
Token indices sequence length is longer than the specified maximum sequence length for this model (242922 > 1024). Running this sequence through the model will result in indexing errors
pool 182016 docs / 199.9M tokens (0s)
prose gate keeps 63475 / 182016 (34.9%)
after dedup 62733 (-742) (19s)
neg torch.Size([29835, 24000]) (24s)
wiki: train pos-acc 0.988 neg-acc 0.749 (26s)
web: train pos-acc 0.766 neg-acc 0.479 (27s)
news: train pos-acc 0.968 neg-acc 0.594 (27s)
qa: train pos-acc 0.937 neg-acc 0.998 (28s)
wrote 34072 ids ~30.0M tokens (budget 12M) (28s)
5039
[metadata] {"noOutputExpected": false}Curate finished in 28s. Note the "web" register barely separates from the pool — expected, since the pool is web text. Let me get empirical numbers, running the baseline and candidate concurrently on the H200.
args
{
"command": "python fastpack.py submission/selection.json /tmp/c1.npy && cp submission/selection.json cache/sel_c1.json\nexport TOKENIZERS_PARALLELISM=false\n( python train_nano.py --train_npy /tmp/rand.npy --heldout_npy data/multi_dev.npy --out_json /tmp/r_rand.json 2>&1 | grep -E \"HELDOUT|Error\" | sed 's/^/[RANDOM] /' ) &\n( python train_nano.py --train_npy /tmp/c1.npy --heldout_npy data/multi_dev.npy --out_json /tmp/r_c1.json 2>&1 | grep -E \"HELDOUT|Error\" | sed 's/^/[CAND1 ] /' ) &\nwait",
"description": "Train random baseline and candidate 1 concurrently"
}Bash result
packed 12000000 tokens from 34072 ids -> /tmp/c1.npy
[CAND1 ] HELDOUT_PPL 382.582 loss 5.9469 train_s 109 /tmp/c1.npy
[RANDOM] HELDOUT_PPL 479.477 loss 6.1727 train_s 109 /tmp/rand.npy
[1]- Done ( python train_nano.py --train_npy /tmp/rand.npy --heldout_npy data/multi_dev.npy --out_json /tmp/r_rand.json 2>&1 | grep -E "HELDOUT|Error" | sed 's/^/[RANDOM] /' )
[2]+ Done ( python train_nano.py --train_npy /tmp/c1.npy --heldout_npy data/multi_dev.npy --out_json /tmp/r_c1.json 2>&1 | grep -E "HELDOUT|Error" | sed 's/^/[CAND1 ] /' )
[stdout]
packed 12000000 tokens from 34072 ids -> /tmp/c1.npy
[CAND1 ] HELDOUT_PPL 382.582 loss 5.9469 train_s 109 /tmp/c1.npy
[RANDOM] HELDOUT_PPL 479.477 loss 6.1727 train_s 109 /tmp/rand.npy
[1]- Done ( python train_nano.py --train_npy /tmp/rand.npy --heldout_npy data/multi_dev.npy --out_json /tmp/r_rand.json 2>&1 | grep -E "HELDOUT|Error" | sed 's/^/[RANDOM] /' )
[2]+ Done ( python train_nano.py --train_npy /tmp/c1.npy --heldout_npy data/multi_dev.npy --out_json /tmp/r_c1.json 2>&1 | grep -E "HELDOUT|Error" | sed 's/^/[CAND1 ] /' )
[metadata] {"noOutputExpected": false}Baseline 479.5 → my selection 382.6. Now let me diagnose: a good prose gate must not reject the target itself. Let me check the gate's pass rate on each target register.
args
{
"command": "python -c \"\nimport numpy as np, importlib.util, sys\nspec=importlib.util.spec_from_file_location('c','/workspace/curate.py'); c=importlib.util.module_from_spec(spec)\nsys.modules['c']=c; spec.loader.exec_module(c)\nT=c.vocab_tables(); names,regs=c.target_registers()\nprint('gate pass-rate on the TARGET itself (should be high!):')\nfor nm in names:\n ch=regs[nm].astype(np.int64)\n n=ch.shape[0]\n off=np.arange(n+1,dtype=np.int64)*c.CHUNK\n flat=ch.reshape(-1)\n st={k:c.doc_means(flat.astype(np.int64),off,T[k]) for k in ('stop','digit','symb','upper','nonascii')}\n u=np.zeros(n); tf=np.zeros(n)\n for i in range(n):\n _,cnt=np.unique(ch[i],return_counts=True); u[i]=len(cnt)/c.CHUNK; tf[i]=cnt.max()/c.CHUNK\n conds={'stop>=.16':st['stop']>=.16,'digit<=.08':st['digit']<=.08,'symb<=.28':st['symb']<=.28,\n 'upper<=.22':st['upper']<=.22,'nonascii<=.06':st['nonascii']<=.06,'uniq>=.18':u>=.18,'topf<=.06':tf<=.06}\n allc=np.ones(n,bool)\n for v in conds.values(): allc&=v\n print(f' {nm:5s} n={n:5d} ALL={allc.mean():.3f} | '+' '.join(f'{k}={v.mean():.2f}' for k,v in conds.items()))\n print(f' medians: stop={np.median(st[\\\"stop\\\"]):.3f} digit={np.median(st[\\\"digit\\\"]):.3f} symb={np.median(st[\\\"symb\\\"]):.3f} upper={np.median(st[\\\"upper\\\"]):.3f} topf={np.median(tf):.3f}')\n\" 2>&1 | grep -v \"Token indices\"",
"description": "Calibrate gate against target distribution"
}Bash result
gate pass-rate on the TARGET itself (should be high!):
wiki n= 948 ALL=0.500 | stop>=.16=0.99 digit<=.08=0.95 symb<=.28=0.99 upper<=.22=0.86 nonascii<=.06=0.99 uniq>=.18=1.00 topf<=.06=0.59
medians: stop=0.324 digit=0.023 symb=0.145 upper=0.160 topf=0.059
web n= 982 ALL=0.459 | stop>=.16=0.98 digit<=.08=0.97 symb<=.28=0.99 upper<=.22=0.94 nonascii<=.06=0.78 uniq>=.18=1.00 topf<=.06=0.68
medians: stop=0.348 digit=0.008 symb=0.141 upper=0.129 topf=0.055
news n= 978 ALL=0.515 | stop>=.16=0.98 digit<=.08=0.83 symb<=.28=0.99 upper<=.22=0.92 nonascii<=.06=0.96 uniq>=.18=1.00 topf<=.06=0.64
medians: stop=0.344 digit=0.020 symb=0.119 upper=0.145 topf=0.055
qa n= 969 ALL=0.122 | stop>=.16=0.59 digit<=.08=0.96 symb<=.28=0.15 upper<=.22=0.98 nonascii<=.06=1.00 uniq>=.18=0.98 topf<=.06=0.30
medians: stop=0.184 digit=0.012 symb=0.398 upper=0.082 topf=0.078
[stdout]
gate pass-rate on the TARGET itself (should be high!):
wiki n= 948 ALL=0.500 | stop>=.16=0.99 digit<=.08=0.95 symb<=.28=0.99 upper<=.22=0.86 nonascii<=.06=0.99 uniq>=.18=1.00 topf<=.06=0.59
medians: stop=0.324 digit=0.023 symb=0.145 upper=0.160 topf=0.059
web n= 982 ALL=0.459 | stop>=.16=0.98 digit<=.08=0.97 symb<=.28=0.99 upper<=.22=0.94 nonascii<=.06=0.78 uniq>=.18=1.00 topf<=.06=0.68
medians: stop=0.348 digit=0.008 symb=0.141 upper=0.129 topf=0.055
news n= 978 ALL=0.515 | stop>=.16=0.98 digit<=.08=0.83 symb<=.28=0.99 upper<=.22=0.92 nonascii<=.06=0.96 uniq>=.18=1.00 topf<=.06=0.64
medians: stop=0.344 digit=0.020 symb=0.119 upper=0.145 topf=0.055
qa n= 969 ALL=0.122 | stop>=.16=0.59 digit<=.08=0.96 symb<=.28=0.15 upper<=.22=0.98 nonascii<=.06=1.00 uniq>=.18=0.98 topf<=.06=0.30
medians: stop=0.184 digit=0.012 symb=0.398 upper=0.082 topf=0.078
[metadata] {"noOutputExpected": false}Confirmed: my gate rejected 88% of the QA register (code/HTML has high symbol rates) and ~40% of the prose registers. The gate was fighting the target. Let me make it self-calibrating — thresholds derived from the target's own quantiles.
args
{
"replace_all": false,
"file_path": "/workspace/curate.py",
"old_string": "# --- knobs (overridable for ablation) -------------------------------------------------\nMIN_TOK = int(os.environ.get(\"MIN_TOK\", 128))\nMAX_TOK = int(os.environ.get(\"MAX_TOK\", 20000))\nMIN_STOP = float(os.environ.get(\"MIN_STOP\", 0.16))\nMAX_SYMB = float(os.environ.get(\"MAX_SYMB\", 0.28))\nMAX_DIGIT = float(os.environ.get(\"MAX_DIGIT\", 0.08))\nMAX_NONASCII = float(os.environ.get(\"MAX_NONASCII\", 0.06))\nMAX_UPPER = float(os.environ.get(\"MAX_UPPER\", 0.22))\nMIN_UNIQ = float(os.environ.get(\"MIN_UNIQ\", 0.18))\nMAX_TOPFREQ = float(os.environ.get(\"MAX_TOPFREQ\", 0.06))\nNEG_N = int(os.environ.get(\"NEG_N\", 40000))",
"new_string": "# --- knobs (overridable for ablation) -------------------------------------------------\nMIN_TOK = int(os.environ.get(\"MIN_TOK\", 128))\nMAX_TOK = int(os.environ.get(\"MAX_TOK\", 20000))\n# The prose gate is SELF-CALIBRATING: each threshold is set from the empirical quantiles\n# of the target registers themselves, so the gate provably cannot reject the distribution\n# we are trying to match. Hand-picked thresholds fail badly here -- a symbol-rate cap\n# tuned on prose throws away 88% of the technical-Q&A register (HTML + code is symbol\n# dense), i.e. it silently deletes a quarter of the target. Only clear garbage\n# (non-English, keyword spam, degenerate repetition) should be removed by the gate; all\n# register-specific discrimination is left to the four classifiers.\nGATE_Q = float(os.environ.get(\"GATE_Q\", 0.98)) # keep this quantile of every register\nGATE_SLACK = float(os.environ.get(\"GATE_SLACK\", 1.15))\nNEG_N = int(os.environ.get(\"NEG_N\", 40000))"
}Edit result
The file /workspace/curate.py has been updated successfully. (file state is current in your context — no need to Read it back)
[metadata] {"filePath": "/workspace/curate.py", "oldString": "# --- knobs (overridable for ablation) -------------------------------------------------\nMIN_TOK = int(os.environ.get(\"MIN_TOK\", 128))\nMAX_TOK = int(os.environ.get(\"MAX_TOK\", 20000))\nMIN_STOP = float(os.environ.get(\"MIN_STOP\", 0.16))\nMAX_SYMB = float(os.environ.get(\"MAX_SYMB\", 0.28))\nMAX_DIGIT = float(os.environ.get(\"MAX_DIGIT\", 0.08))\nMAX_NONASCII = float(os.environ.get(\"MAX_NONASCII\", 0.06))\nMAX_UPPER = float(os.environ.get(\"MAX_UPPER\", 0.22))\nMIN_UNIQ = float(os.environ.get(\"MIN_UNIQ\", 0.18))\nMAX_TOPFREQ = float(os.environ.get(\"MAX_TOPFREQ\", 0.06))\nNEG_N = int(os.environ.get(\"NEG_N\", 40000))", "newString": "# --- knobs (overridable for ablation) -------------------------------------------------\nMIN_TOK = int(os.environ.get(\"MIN_TOK\", 128))\nMAX_TOK = int(os.environ.get(\"MAX_TOK\", 20000))\n# The prose gate is SELF-CALIBRATING: each threshold is set from the empirical quantiles\n# of the target registers themselves, so the gate provably cannot reject the distribution\n# we are trying to match. Hand-picked thresholds fail badly here -- a symbol-rate cap\n# tuned on prose throws away 88% of the technical-Q&A register (HTML + code is symbol\n# dense), i.e. it silently deletes a quarter of the target. Only clear garbage\n# (non-English, keyword spam, degenerate repetition) should be removed by the gate; all\n# register-specific discrimination is left to the four classifiers.\nGATE_Q = float(os.environ.get(\"GATE_Q\", 0.98)) # keep this quantile of every register\nGATE_SLACK = float(os.environ.get(\"GATE_SLACK\", 1.15))\nNEG_N = int(os.environ.get(\"NEG_N\", 40000))", "originalFile": null, "structuredPatch": [{"oldStart": 49, "oldLines": 13, "newStart": 49, "newLines": 15, "lines": [" # --- knobs (overridable for ablation) -------------------------------------------------", " MIN_TOK = int(os.environ.get(\"MIN_TOK\", 128))", " MAX_TOK = int(os.environ.get(\"MAX_TOK\", 20000))", "-MIN_STOP = float(os.environ.get(\"MIN_STOP\", 0.16))", "-MAX_SYMB = float(os.environ.get(\"MAX_SYMB\", 0.28))", "-MAX_DIGIT = float(os.environ.get(\"MAX_DIGIT\", 0.08))", "-MAX_NONASCII = float(os.environ.get(\"MAX_NONASCII\", 0.06))", "-MAX_UPPER = float(os.environ.get(\"MAX_UPPER\", 0.22))", "-MIN_UNIQ = float(os.environ.get(\"MIN_UNIQ\", 0.18))", "-MAX_TOPFREQ = float(os.environ.get(\"MAX_TOPFREQ\", 0.06))", "+# The prose gate is SELF-CALIBRATING: each threshold is set from the empirical quantiles", "+# of the target registers themselves, so the gate provably cannot reject the distribution", "+# we are trying to match. Hand-picked thresholds fail badly here -- a symbol-rate cap", "+# tuned on prose throws away 88% of the technical-Q&A register (HTML + code is symbol", "+# dense), i.e. it silently deletes a quarter of the target. Only clear garbage", "+# (non-English, keyword spam, degenerate repetition) should be removed by the gate; all", "+# register-specific discrimination is left to the four classifiers.", "+GATE_Q = float(os.environ.get(\"GATE_Q\", 0.98)) # keep this quantile of every register", "+GATE_SLACK = float(os.environ.get(\"GATE_SLACK\", 1.15))", " NEG_N = int(os.environ.get(\"NEG_N\", 40000))", " CHUNK = 256 # positive pseudo-document length (== training block size)", " VOCAB_KEEP = 24000 # feature vocabulary: most frequent GPT-2 ids in the pool"]}], "userModified": false, "replaceAll": false}encrypted chain-of-thought — recorded, not exposed
args
{
"replace_all": false,
"file_path": "/workspace/curate.py",
"old_string": "def main():\n t0 = time.time()\n flat, off, pool_ids = tokenize_pool()\n ndoc = len(pool_ids); ntok = (off[1:] - off[:-1]).astype(np.int64)\n print(f\"pool {ndoc} docs / {ntok.sum()/1e6:.1f}M tokens ({time.time()-t0:.0f}s)\")\n\n # ---- prose gate ------------------------------------------------------------------\n T = vocab_tables()\n st = {k: doc_means(flat, off, T[k]) for k in (\"stop\", \"digit\", \"symb\", \"upper\", \"nonascii\")}\n\n # repetition statistics: unique-token ratio and most-frequent-token share\n uniq = np.zeros(ndoc, np.float32); topf = np.zeros(ndoc, np.float32)\n for i in range(ndoc):\n s, e = off[i], off[i + 1]\n if e <= s: continue\n _, cnt = np.unique(flat[s:e], return_counts=True)\n uniq[i] = len(cnt) / (e - s); topf[i] = cnt.max() / (e - s)\n\n keep = ((ntok >= MIN_TOK) & (ntok <= MAX_TOK) & (st[\"stop\"] >= MIN_STOP)\n & (st[\"symb\"] <= MAX_SYMB) & (st[\"digit\"] <= MAX_DIGIT)\n & (st[\"nonascii\"] <= MAX_NONASCII) & (st[\"upper\"] <= MAX_UPPER)\n & (uniq >= MIN_UNIQ) & (topf <= MAX_TOPFREQ))\n print(f\"prose gate keeps {keep.sum()} / {ndoc} ({keep.mean()*100:.1f}%)\")",
"new_string": "UP_STATS = (\"digit\", \"symb\", \"upper\", \"nonascii\", \"topf\") # upper-bounded\nLO_STATS = (\"stop\", \"uniq\") # lower-bounded\n\n\ndef rep_stats(flat, off, ndoc):\n \"\"\"unique-token ratio and most-frequent-token share, per document.\"\"\"\n uniq = np.zeros(ndoc, np.float32); topf = np.zeros(ndoc, np.float32)\n for i in range(ndoc):\n s, e = off[i], off[i + 1]\n if e <= s: continue\n _, cnt = np.unique(flat[s:e], return_counts=True)\n uniq[i] = len(cnt) / (e - s); topf[i] = cnt.max() / (e - s)\n return uniq, topf\n\n\ndef calibrate_gate(T, names, regs):\n \"\"\"Thresholds = envelope of the target registers' own quantiles (+ slack).\"\"\"\n thr = {}\n per = {}\n for nm in names:\n ch = regs[nm].astype(np.int64); n = ch.shape[0]\n o = np.arange(n + 1, dtype=np.int64) * CHUNK\n fl = ch.reshape(-1)\n s = {k: doc_means(fl, o, T[k]) for k in (\"stop\", \"digit\", \"symb\", \"upper\", \"nonascii\")}\n s[\"uniq\"], s[\"topf\"] = rep_stats(fl, o, n)\n per[nm] = s\n for k in UP_STATS:\n thr[k] = float(max(np.quantile(per[nm][k], GATE_Q) for nm in names)) * GATE_SLACK\n for k in LO_STATS:\n thr[k] = float(min(np.quantile(per[nm][k], 1 - GATE_Q) for nm in names)) / GATE_SLACK\n return thr\n\n\ndef main():\n t0 = time.time()\n flat, off, pool_ids = tokenize_pool()\n ndoc = len(pool_ids); ntok = (off[1:] - off[:-1]).astype(np.int64)\n print(f\"pool {ndoc} docs / {ntok.sum()/1e6:.1f}M tokens ({time.time()-t0:.0f}s)\")\n\n # ---- prose gate, calibrated on the target itself ----------------------------------\n T = vocab_tables()\n names, regs = target_registers()\n thr = calibrate_gate(T, names, regs)\n print(\"calibrated gate:\", {k: round(v, 3) for k, v in thr.items()})\n\n st = {k: doc_means(flat, off, T[k]) for k in (\"stop\", \"digit\", \"symb\", \"upper\", \"nonascii\")}\n st[\"uniq\"], st[\"topf\"] = rep_stats(flat, off, ndoc)\n\n keep = (ntok >= MIN_TOK) & (ntok <= MAX_TOK)\n for k in UP_STATS: keep &= st[k] <= thr[k]\n for k in LO_STATS: keep &= st[k] >= thr[k]\n print(f\"prose gate keeps {keep.sum()} / {ndoc} ({keep.mean()*100:.1f}%)\")"
}Edit result
The file /workspace/curate.py has been updated successfully. (file state is current in your context — no need to Read it back)
[metadata] {"filePath": "/workspace/curate.py", "oldString": "def main():\n t0 = time.time()\n flat, off, pool_ids = tokenize_pool()\n ndoc = len(pool_ids); ntok = (off[1:] - off[:-1]).astype(np.int64)\n print(f\"pool {ndoc} docs / {ntok.sum()/1e6:.1f}M tokens ({time.time()-t0:.0f}s)\")\n\n # ---- prose gate ------------------------------------------------------------------\n T = vocab_tables()\n st = {k: doc_means(flat, off, T[k]) for k in (\"stop\", \"digit\", \"symb\", \"upper\", \"nonascii\")}\n\n # repetition statistics: unique-token ratio and most-frequent-token share\n uniq = np.zeros(ndoc, np.float32); topf = np.zeros(ndoc, np.float32)\n for i in range(ndoc):\n s, e = off[i], off[i + 1]\n if e <= s: continue\n _, cnt = np.unique(flat[s:e], return_counts=True)\n uniq[i] = len(cnt) / (e - s); topf[i] = cnt.max() / (e - s)\n\n keep = ((ntok >= MIN_TOK) & (ntok <= MAX_TOK) & (st[\"stop\"] >= MIN_STOP)\n & (st[\"symb\"] <= MAX_SYMB) & (st[\"digit\"] <= MAX_DIGIT)\n & (st[\"nonascii\"] <= MAX_NONASCII) & (st[\"upper\"] <= MAX_UPPER)\n & (uniq >= MIN_UNIQ) & (topf <= MAX_TOPFREQ))\n print(f\"prose gate keeps {keep.sum()} / {ndoc} ({keep.mean()*100:.1f}%)\")", "newString": "UP_STATS = (\"digit\", \"symb\", \"upper\", \"nonascii\", \"topf\") # upper-bounded\nLO_STATS = (\"stop\", \"uniq\") # lower-bounded\n\n\ndef rep_stats(flat, off, ndoc):\n \"\"\"unique-token ratio and most-frequent-token share, per document.\"\"\"\n uniq = np.zeros(ndoc, np.float32); topf = np.zeros(ndoc, np.float32)\n for i in range(ndoc):\n s, e = off[i], off[i + 1]\n if e <= s: continue\n _, cnt = np.unique(flat[s:e], return_counts=True)\n uniq[i] = len(cnt) / (e - s); topf[i] = cnt.max() / (e - s)\n return uniq, topf\n\n\ndef calibrate_gate(T, names, regs):\n \"\"\"Thresholds = envelope of the target registers' own quantiles (+ slack).\"\"\"\n thr = {}\n per = {}\n for nm in names:\n ch = regs[nm].astype(np.int64); n = ch.shape[0]\n o = np.arange(n + 1, dtype=np.int64) * CHUNK\n fl = ch.reshape(-1)\n s = {k: doc_means(fl, o, T[k]) for k in (\"stop\", \"digit\", \"symb\", \"upper\", \"nonascii\")}\n s[\"uniq\"], s[\"topf\"] = rep_stats(fl, o, n)\n per[nm] = s\n for k in UP_STATS:\n thr[k] = float(max(np.quantile(per[nm][k], GATE_Q) for nm in names)) * GATE_SLACK\n for k in LO_STATS:\n thr[k] = float(min(np.quantile(per[nm][k], 1 - GATE_Q) for nm in names)) / GATE_SLACK\n return thr\n\n\ndef main():\n t0 = time.time()\n flat, off, pool_ids = tokenize_pool()\n ndoc = len(pool_ids); ntok = (off[1:] - off[:-1]).astype(np.int64)\n print(f\"pool {ndoc} docs / {ntok.sum()/1e6:.1f}M tokens ({time.time()-t0:.0f}s)\")\n\n # ---- prose gate, calibrated on the target itself ----------------------------------\n T = vocab_tables()\n names, regs = target_registers()\n thr = calibrate_gate(T, names, regs)\n print(\"calibrated gate:\", {k: round(v, 3) for k, v in thr.items()})\n\n st = {k: doc_means(flat, off, T[k]) for k in (\"stop\", \"digit\", \"symb\", \"upper\", \"nonascii\")}\n st[\"uniq\"], st[\"topf\"] = rep_stats(flat, off, ndoc)\n\n keep = (ntok >= MIN_TOK) & (ntok <= MAX_TOK)\n for k in UP_STATS: keep &= st[k] <= thr[k]\n for k in LO_STATS: keep &= st[k] >= thr[k]\n print(f\"prose gate keeps {keep.sum()} / {ndoc} ({keep.mean()*100:.1f}%)\")", "originalFile": null, "structuredPatch": [{"oldStart": 214, "oldLines": 28, "newStart": 214, "newLines": 57, "lines": [" ", " ", " # ======================================================================================", "-def main():", "- t0 = time.time()", "- flat, off, pool_ids = tokenize_pool()", "- ndoc = len(pool_ids); ntok = (off[1:] - off[:-1]).astype(np.int64)", "- print(f\"pool {ndoc} docs / {ntok.sum()/1e6:.1f}M tokens ({time.time()-t0:.0f}s)\")", "+UP_STATS = (\"digit\", \"symb\", \"upper\", \"nonascii\", \"topf\") # upper-bounded", "+LO_STATS = (\"stop\", \"uniq\") # lower-bounded", " ", "- # ---- prose gate ------------------------------------------------------------------", "- T = vocab_tables()", "- st = {k: doc_means(flat, off, T[k]) for k in (\"stop\", \"digit\", \"symb\", \"upper\", \"nonascii\")}", " ", "- # repetition statistics: unique-token ratio and most-frequent-token share", "+def rep_stats(flat, off, ndoc):", "+ \"\"\"unique-token ratio and most-frequent-token share, per document.\"\"\"", " uniq = np.zeros(ndoc, np.float32); topf = np.zeros(ndoc, np.float32)", " for i in range(ndoc):", " s, e = off[i], off[i + 1]", " if e <= s: continue", " _, cnt = np.unique(flat[s:e], return_counts=True)", " uniq[i] = len(cnt) / (e - s); topf[i] = cnt.max() / (e - s)", "+ return uniq, topf", " ", "- keep = ((ntok >= MIN_TOK) & (ntok <= MAX_TOK) & (st[\"stop\"] >= MIN_STOP)", "- & (st[\"symb\"] <= MAX_SYMB) & (st[\"digit\"] <= MAX_DIGIT)", "- & (st[\"nonascii\"] <= MAX_NONASCII) & (st[\"upper\"] <= MAX_UPPER)", "- & (uniq >= MIN_UNIQ) & (topf <= MAX_TOPFREQ))", "+", "+def calibrate_gate(T, names, regs):", "+ \"\"\"Thresholds = envelope of the target registers' own quantiles (+ slack).\"\"\"", "+ thr = {}", "+ per = {}", "+ for nm in names:", "+ ch = regs[nm].astype(np.int64); n = ch.shape[0]", "+ o = np.arange(n + 1, dtype=np.int64) * CHUNK", "+ fl = ch.reshape(-1)", "+ s = {k: doc_means(fl, o, T[k]) for k in (\"stop\", \"digit\", \"symb\", \"upper\", \"nonascii\")}", "+ s[\"uniq\"], s[\"topf\"] = rep_stats(fl, o, n)", "+ per[nm] = s", "+ for k in UP_STATS:", "+ thr[k] = float(max(np.quantile(per[nm][k], GATE_Q) for nm in names)) * GATE_SLACK", "+ for k in LO_STATS:", "+ thr[k] = float(min(np.quantile(per[nm][k], 1 - GATE_Q) for nm in names)) / GATE_SLACK", "+ return thr", "+", "+", "+def main():", "+ t0 = time.time()", "+ flat, off, pool_ids = tokenize_pool()", "+ ndoc = len(pool_ids); ntok = (off[1:] - off[:-1]).astype(np.int64)", "+ print(f\"pool {ndoc} docs / {ntok.sum()/1e6:.1f}M tokens ({time.time()-t0:.0f}s)\")", "+", "+ # ---- prose gate, calibrated on the target itself ----------------------------------", "+ T = vocab_tables()", "+ names, regs = target_registers()", "+ thr = calibrate_gate(T, names, regs)", "+ print(\"calibrated gate:\", {k: round(v, 3) for k, v in thr.items()})", "+", "+ st = {k: doc_means(flat, off, T[k]) for k in (\"stop\", \"digit\", \"symb\", \"upper\", \"nonascii\")}", "+ st[\"uniq\"], st[\"topf\"] = rep_stats(flat, off, ndoc)", "+", "+ keep = (ntok >= MIN_TOK) & (ntok <= MAX_TOK)", "+ for k in UP_STATS: keep &= st[k] <= thr[k]", "+ for k in LO_STATS: keep &= st[k] >= thr[k]", " print(f\"prose gate keeps {keep.sum()} / {ndoc} ({keep.mean()*100:.1f}%)\")", " ", " # ---- near-duplicate removal ------------------------------------------------------"]}], "userModified": false, "replaceAll": false}encrypted chain-of-thought — recorded, not exposed
args
{
"replace_all": false,
"file_path": "/workspace/curate.py",
"old_string": " # ---- train one register classifier per target block ------------------------------\n names, regs = target_registers()\n rng = np.random.default_rng(SEED)",
"new_string": " # ---- train one register classifier per target block ------------------------------\n rng = np.random.default_rng(SEED)"
}Edit result
The file /workspace/curate.py has been updated successfully. (file state is current in your context — no need to Read it back)
[metadata] {"filePath": "/workspace/curate.py", "oldString": " # ---- train one register classifier per target block ------------------------------\n names, regs = target_registers()\n rng = np.random.default_rng(SEED)", "newString": " # ---- train one register classifier per target block ------------------------------\n rng = np.random.default_rng(SEED)", "originalFile": null, "structuredPatch": [{"oldStart": 291, "oldLines": 7, "newStart": 291, "newLines": 6, "lines": [" V = VOCAB_KEEP", " ", " # ---- train one register classifier per target block ------------------------------", "- names, regs = target_registers()", " rng = np.random.default_rng(SEED)", " cand = np.flatnonzero(keep)", " negsrc = rng.choice(ndoc, size=min(NEG_N, ndoc), replace=False)"]}], "userModified": false, "replaceAll": false}encrypted chain-of-thought — recorded, not exposed
args
{
"command": "OUT=/workspace/cache/sel_c2.json python curate.py 2>&1 | grep -v \"Token indices\"; echo \"TIME $(cat .timer/remaining_secs)\"",
"description": "Run curate with self-calibrated gate"
}Bash result
pool 182016 docs / 199.9M tokens (0s)
calibrated gate: {'digit': 0.139, 'symb': 0.894, 'upper': 0.337, 'nonascii': 0.157, 'topf': 0.642, 'stop': 0.01, 'uniq': 0.163}
prose gate keeps 132624 / 182016 (72.9%)
after dedup 126500 (-6124) (22s)
neg torch.Size([29835, 24000]) (23s)
wiki: train pos-acc 0.988 neg-acc 0.749 (26s)
web: train pos-acc 0.766 neg-acc 0.479 (26s)
news: train pos-acc 0.968 neg-acc 0.594 (27s)
qa: train pos-acc 0.937 neg-acc 0.998 (28s)
wrote 31804 ids ~30.0M tokens (budget 12M) (28s)
TIME 4769
[stdout]
pool 182016 docs / 199.9M tokens (0s)
calibrated gate: {'digit': 0.139, 'symb': 0.894, 'upper': 0.337, 'nonascii': 0.157, 'topf': 0.642, 'stop': 0.01, 'uniq': 0.163}
prose gate keeps 132624 / 182016 (72.9%)
after dedup 126500 (-6124) (22s)
neg torch.Size([29835, 24000]) (23s)
wiki: train pos-acc 0.988 neg-acc 0.749 (26s)
web: train pos-acc 0.766 neg-acc 0.479 (26s)
news: train pos-acc 0.968 neg-acc 0.594 (27s)
qa: train pos-acc 0.937 neg-acc 0.998 (28s)
wrote 31804 ids ~30.0M tokens (budget 12M) (28s)
TIME 4769
[metadata] {"noOutputExpected": false}Gate now keeps 73%, but the union-envelope makes it too permissive for prose (the code-heavy QA register drives symb≤0.89). Better: gate each register by its own envelope. Let me train C2 while I implement that.
args
{
"command": "python fastpack.py cache/sel_c2.json /tmp/c2.npy >/dev/null && export TOKENIZERS_PARALLELISM=false && nohup python train_nano.py --train_npy /tmp/c2.npy --heldout_npy data/multi_dev.npy --out_json /tmp/r_c2.json > /tmp/log_c2.txt 2>&1 & echo \"C2 training launched\"",
"description": "Launch C2 training in background"
}Bash result
C2 training launched
[stdout]
C2 training launched
[metadata] {"noOutputExpected": false}encrypted chain-of-thought — recorded, not exposed
args
{
"replace_all": false,
"file_path": "/workspace/curate.py",
"old_string": "def calibrate_gate(T, names, regs):\n \"\"\"Thresholds = envelope of the target registers' own quantiles (+ slack).\"\"\"\n thr = {}\n per = {}\n for nm in names:\n ch = regs[nm].astype(np.int64); n = ch.shape[0]\n o = np.arange(n + 1, dtype=np.int64) * CHUNK\n fl = ch.reshape(-1)\n s = {k: doc_means(fl, o, T[k]) for k in (\"stop\", \"digit\", \"symb\", \"upper\", \"nonascii\")}\n s[\"uniq\"], s[\"topf\"] = rep_stats(fl, o, n)\n per[nm] = s\n for k in UP_STATS:\n thr[k] = float(max(np.quantile(per[nm][k], GATE_Q) for nm in names)) * GATE_SLACK\n for k in LO_STATS:\n thr[k] = float(min(np.quantile(per[nm][k], 1 - GATE_Q) for nm in names)) / GATE_SLACK\n return thr",
"new_string": "def calibrate_gate(T, names, regs):\n \"\"\"One threshold set PER REGISTER, from that register's own quantiles (+ slack).\n\n A single shared envelope is dominated by whichever register is most extreme on each\n axis -- the code-bearing Q&A register pushes the symbol cap to ~0.9, which disables\n the filter for the three prose registers too. Gating each register separately keeps\n the prose gates tight while still admitting code for the Q&A register.\n \"\"\"\n thr = {}\n for nm in names:\n ch = regs[nm].astype(np.int64); n = ch.shape[0]\n o = np.arange(n + 1, dtype=np.int64) * CHUNK\n fl = ch.reshape(-1)\n s = {k: doc_means(fl, o, T[k]) for k in (\"stop\", \"digit\", \"symb\", \"upper\", \"nonascii\")}\n s[\"uniq\"], s[\"topf\"] = rep_stats(fl, o, n)\n t = {}\n for k in UP_STATS: t[k] = float(np.quantile(s[k], GATE_Q)) * GATE_SLACK\n for k in LO_STATS: t[k] = float(np.quantile(s[k], 1 - GATE_Q)) / GATE_SLACK\n thr[nm] = t\n return thr"
}Edit result
The file /workspace/curate.py has been updated successfully. (file state is current in your context — no need to Read it back)
[metadata] {"filePath": "/workspace/curate.py", "oldString": "def calibrate_gate(T, names, regs):\n \"\"\"Thresholds = envelope of the target registers' own quantiles (+ slack).\"\"\"\n thr = {}\n per = {}\n for nm in names:\n ch = regs[nm].astype(np.int64); n = ch.shape[0]\n o = np.arange(n + 1, dtype=np.int64) * CHUNK\n fl = ch.reshape(-1)\n s = {k: doc_means(fl, o, T[k]) for k in (\"stop\", \"digit\", \"symb\", \"upper\", \"nonascii\")}\n s[\"uniq\"], s[\"topf\"] = rep_stats(fl, o, n)\n per[nm] = s\n for k in UP_STATS:\n thr[k] = float(max(np.quantile(per[nm][k], GATE_Q) for nm in names)) * GATE_SLACK\n for k in LO_STATS:\n thr[k] = float(min(np.quantile(per[nm][k], 1 - GATE_Q) for nm in names)) / GATE_SLACK\n return thr", "newString": "def calibrate_gate(T, names, regs):\n \"\"\"One threshold set PER REGISTER, from that register's own quantiles (+ slack).\n\n A single shared envelope is dominated by whichever register is most extreme on each\n axis -- the code-bearing Q&A register pushes the symbol cap to ~0.9, which disables\n the filter for the three prose registers too. Gating each register separately keeps\n the prose gates tight while still admitting code for the Q&A register.\n \"\"\"\n thr = {}\n for nm in names:\n ch = regs[nm].astype(np.int64); n = ch.shape[0]\n o = np.arange(n + 1, dtype=np.int64) * CHUNK\n fl = ch.reshape(-1)\n s = {k: doc_means(fl, o, T[k]) for k in (\"stop\", \"digit\", \"symb\", \"upper\", \"nonascii\")}\n s[\"uniq\"], s[\"topf\"] = rep_stats(fl, o, n)\n t = {}\n for k in UP_STATS: t[k] = float(np.quantile(s[k], GATE_Q)) * GATE_SLACK\n for k in LO_STATS: t[k] = float(np.quantile(s[k], 1 - GATE_Q)) / GATE_SLACK\n thr[nm] = t\n return thr", "originalFile": null, "structuredPatch": [{"oldStart": 230, "oldLines": 20, "newStart": 230, "newLines": 24, "lines": [" ", " ", " def calibrate_gate(T, names, regs):", "- \"\"\"Thresholds = envelope of the target registers' own quantiles (+ slack).\"\"\"", "+ \"\"\"One threshold set PER REGISTER, from that register's own quantiles (+ slack).", "+", "+ A single shared envelope is dominated by whichever register is most extreme on each", "+ axis -- the code-bearing Q&A register pushes the symbol cap to ~0.9, which disables", "+ the filter for the three prose registers too. Gating each register separately keeps", "+ the prose gates tight while still admitting code for the Q&A register.", "+ \"\"\"", " thr = {}", "- per = {}", " for nm in names:", " ch = regs[nm].astype(np.int64); n = ch.shape[0]", " o = np.arange(n + 1, dtype=np.int64) * CHUNK", " fl = ch.reshape(-1)", " s = {k: doc_means(fl, o, T[k]) for k in (\"stop\", \"digit\", \"symb\", \"upper\", \"nonascii\")}", " s[\"uniq\"], s[\"topf\"] = rep_stats(fl, o, n)", "- per[nm] = s", "- for k in UP_STATS:", "- thr[k] = float(max(np.quantile(per[nm][k], GATE_Q) for nm in names)) * GATE_SLACK", "- for k in LO_STATS:", "- thr[k] = float(min(np.quantile(per[nm][k], 1 - GATE_Q) for nm in names)) / GATE_SLACK", "+ t = {}", "+ for k in UP_STATS: t[k] = float(np.quantile(s[k], GATE_Q)) * GATE_SLACK", "+ for k in LO_STATS: t[k] = float(np.quantile(s[k], 1 - GATE_Q)) / GATE_SLACK", "+ thr[nm] = t", " return thr", " ", " "]}], "userModified": false, "replaceAll": false}encrypted chain-of-thought — recorded, not exposed
args
{
"replace_all": false,
"file_path": "/workspace/curate.py",
"old_string": " thr = calibrate_gate(T, names, regs)\n print(\"calibrated gate:\", {k: round(v, 3) for k, v in thr.items()})\n\n st = {k: doc_means(flat, off, T[k]) for k in (\"stop\", \"digit\", \"symb\", \"upper\", \"nonascii\")}\n st[\"uniq\"], st[\"topf\"] = rep_stats(flat, off, ndoc)\n\n keep = (ntok >= MIN_TOK) & (ntok <= MAX_TOK)\n for k in UP_STATS: keep &= st[k] <= thr[k]\n for k in LO_STATS: keep &= st[k] >= thr[k]\n print(f\"prose gate keeps {keep.sum()} / {ndoc} ({keep.mean()*100:.1f}%)\")",
"new_string": " thr = calibrate_gate(T, names, regs)\n\n st = {k: doc_means(flat, off, T[k]) for k in (\"stop\", \"digit\", \"symb\", \"upper\", \"nonascii\")}\n st[\"uniq\"], st[\"topf\"] = rep_stats(flat, off, ndoc)\n\n lenok = (ntok >= MIN_TOK) & (ntok <= MAX_TOK)\n gate = {}\n for nm in names:\n g = lenok.copy()\n for k in UP_STATS: g &= st[k] <= thr[nm][k]\n for k in LO_STATS: g &= st[k] >= thr[nm][k]\n gate[nm] = g\n print(f\" gate[{nm:5s}] keeps {g.sum():6d} ({g.mean()*100:4.1f}%) \"\n + \" \".join(f\"{k}{'<' if k in UP_STATS else '>'}{thr[nm][k]:.3f}\" for k in\n (\"stop\", \"symb\", \"digit\", \"upper\", \"nonascii\", \"topf\")))\n keep = np.zeros(ndoc, bool)\n for nm in names: keep |= gate[nm]\n print(f\"union gate keeps {keep.sum()} / {ndoc} ({keep.mean()*100:.1f}%)\")"
}Edit result
The file /workspace/curate.py has been updated successfully. (file state is current in your context — no need to Read it back)
[metadata] {"filePath": "/workspace/curate.py", "oldString": " thr = calibrate_gate(T, names, regs)\n print(\"calibrated gate:\", {k: round(v, 3) for k, v in thr.items()})\n\n st = {k: doc_means(flat, off, T[k]) for k in (\"stop\", \"digit\", \"symb\", \"upper\", \"nonascii\")}\n st[\"uniq\"], st[\"topf\"] = rep_stats(flat, off, ndoc)\n\n keep = (ntok >= MIN_TOK) & (ntok <= MAX_TOK)\n for k in UP_STATS: keep &= st[k] <= thr[k]\n for k in LO_STATS: keep &= st[k] >= thr[k]\n print(f\"prose gate keeps {keep.sum()} / {ndoc} ({keep.mean()*100:.1f}%)\")", "newString": " thr = calibrate_gate(T, names, regs)\n\n st = {k: doc_means(flat, off, T[k]) for k in (\"stop\", \"digit\", \"symb\", \"upper\", \"nonascii\")}\n st[\"uniq\"], st[\"topf\"] = rep_stats(flat, off, ndoc)\n\n lenok = (ntok >= MIN_TOK) & (ntok <= MAX_TOK)\n gate = {}\n for nm in names:\n g = lenok.copy()\n for k in UP_STATS: g &= st[k] <= thr[nm][k]\n for k in LO_STATS: g &= st[k] >= thr[nm][k]\n gate[nm] = g\n print(f\" gate[{nm:5s}] keeps {g.sum():6d} ({g.mean()*100:4.1f}%) \"\n + \" \".join(f\"{k}{'<' if k in UP_STATS else '>'}{thr[nm][k]:.3f}\" for k in\n (\"stop\", \"symb\", \"digit\", \"upper\", \"nonascii\", \"topf\")))\n keep = np.zeros(ndoc, bool)\n for nm in names: keep |= gate[nm]\n print(f\"union gate keeps {keep.sum()} / {ndoc} ({keep.mean()*100:.1f}%)\")", "originalFile": null, "structuredPatch": [{"oldStart": 261, "oldLines": 15, "newStart": 261, "newLines": 23, "lines": [" T = vocab_tables()", " names, regs = target_registers()", " thr = calibrate_gate(T, names, regs)", "- print(\"calibrated gate:\", {k: round(v, 3) for k, v in thr.items()})", " ", " st = {k: doc_means(flat, off, T[k]) for k in (\"stop\", \"digit\", \"symb\", \"upper\", \"nonascii\")}", " st[\"uniq\"], st[\"topf\"] = rep_stats(flat, off, ndoc)", " ", "- keep = (ntok >= MIN_TOK) & (ntok <= MAX_TOK)", "- for k in UP_STATS: keep &= st[k] <= thr[k]", "- for k in LO_STATS: keep &= st[k] >= thr[k]", "- print(f\"prose gate keeps {keep.sum()} / {ndoc} ({keep.mean()*100:.1f}%)\")", "+ lenok = (ntok >= MIN_TOK) & (ntok <= MAX_TOK)", "+ gate = {}", "+ for nm in names:", "+ g = lenok.copy()", "+ for k in UP_STATS: g &= st[k] <= thr[nm][k]", "+ for k in LO_STATS: g &= st[k] >= thr[nm][k]", "+ gate[nm] = g", "+ print(f\" gate[{nm:5s}] keeps {g.sum():6d} ({g.mean()*100:4.1f}%) \"", "+ + \" \".join(f\"{k}{'<' if k in UP_STATS else '>'}{thr[nm][k]:.3f}\" for k in", "+ (\"stop\", \"symb\", \"digit\", \"upper\", \"nonascii\", \"topf\")))", "+ keep = np.zeros(ndoc, bool)", "+ for nm in names: keep |= gate[nm]", "+ print(f\"union gate keeps {keep.sum()} / {ndoc} ({keep.mean()*100:.1f}%)\")", " ", " # ---- near-duplicate removal ------------------------------------------------------", " def sig(a, b):"]}], "userModified": false, "replaceAll": false}encrypted chain-of-thought — recorded, not exposed
args
{
"replace_all": false,
"file_path": "/workspace/curate.py",
"old_string": " # ---- emit: round-robin over registers by descending score ------------------------\n order = {nm: cand[np.argsort(-scores[nm][cand])] for nm in names}",
"new_string": " # ---- emit: round-robin over registers by descending score ------------------------\n # each register ranks only the documents that passed ITS OWN gate\n order = {}\n for nm in names:\n c_nm = np.flatnonzero(gate[nm] & keep)\n order[nm] = c_nm[np.argsort(-scores[nm][c_nm])]"
}Edit result
The file /workspace/curate.py has been updated successfully. (file state is current in your context — no need to Read it back)
[metadata] {"filePath": "/workspace/curate.py", "oldString": " # ---- emit: round-robin over registers by descending score ------------------------\n order = {nm: cand[np.argsort(-scores[nm][cand])] for nm in names}", "newString": " # ---- emit: round-robin over registers by descending score ------------------------\n # each register ranks only the documents that passed ITS OWN gate\n order = {}\n for nm in names:\n c_nm = np.flatnonzero(gate[nm] & keep)\n order[nm] = c_nm[np.argsort(-scores[nm][c_nm])]", "originalFile": null, "structuredPatch": [{"oldStart": 338, "oldLines": 7, "newStart": 338, "newLines": 11, "lines": [" torch.cuda.empty_cache()", " ", " # ---- emit: round-robin over registers by descending score ------------------------", "- order = {nm: cand[np.argsort(-scores[nm][cand])] for nm in names}", "+ # each register ranks only the documents that passed ITS OWN gate", "+ order = {}", "+ for nm in names:", "+ c_nm = np.flatnonzero(gate[nm] & keep)", "+ order[nm] = c_nm[np.argsort(-scores[nm][c_nm])]", " sel, taken, tot = [], np.zeros(ndoc, bool), 0", " if BALANCE == \"pooled\":", " z = np.mean([(scores[nm] - scores[nm][cand].mean()) / (scores[nm][cand].std() + 1e-9)"]}], "userModified": false, "replaceAll": false}encrypted chain-of-thought — recorded, not exposed
args
{
"command": "cat /tmp/log_c2.txt | grep -E \"HELDOUT\" ; echo \"=== C3 curate ===\"; OUT=/workspace/cache/sel_c3.json python curate.py 2>&1 | grep -v \"Token indices\"; echo \"TIME $(cat .timer/remaining_secs)\"",
"description": "Check C2 result and run C3 with per-register gates"
}Bash result
=== C3 curate ===
pool 182016 docs / 199.9M tokens (0s)
gate[wiki ] keeps 67138 (36.9%) stop>0.190 symb<0.243 digit<0.117 upper<0.337 nonascii<0.041 topf<0.108
gate[web ] keeps 95358 (52.4%) stop>0.117 symb<0.294 digit<0.099 upper<0.312 nonascii<0.157 topf<0.123
gate[news ] keeps 98776 (54.3%) stop>0.141 symb<0.238 digit<0.139 upper<0.330 nonascii<0.087 topf<0.103
gate[qa ] keeps 51404 (28.2%) stop>0.010 symb<0.894 digit<0.121 upper<0.261 nonascii<0.009 topf<0.642
union gate keeps 113293 / 182016 (62.2%)
after dedup 109787 (-3506) (21s)
neg torch.Size([29835, 24000]) (23s)
wiki: train pos-acc 0.988 neg-acc 0.749 (25s)
web: train pos-acc 0.766 neg-acc 0.479 (26s)
news: train pos-acc 0.968 neg-acc 0.594 (27s)
qa: train pos-acc 0.937 neg-acc 0.998 (27s)
wrote 44308 ids ~30.0M tokens (budget 12M) (27s)
TIME 4699
[stdout]
=== C3 curate ===
pool 182016 docs / 199.9M tokens (0s)
gate[wiki ] keeps 67138 (36.9%) stop>0.190 symb<0.243 digit<0.117 upper<0.337 nonascii<0.041 topf<0.108
gate[web ] keeps 95358 (52.4%) stop>0.117 symb<0.294 digit<0.099 upper<0.312 nonascii<0.157 topf<0.123
gate[news ] keeps 98776 (54.3%) stop>0.141 symb<0.238 digit<0.139 upper<0.330 nonascii<0.087 topf<0.103
gate[qa ] keeps 51404 (28.2%) stop>0.010 symb<0.894 digit<0.121 upper<0.261 nonascii<0.009 topf<0.642
union gate keeps 113293 / 182016 (62.2%)
after dedup 109787 (-3506) (21s)
neg torch.Size([29835, 24000]) (23s)
wiki: train pos-acc 0.988 neg-acc 0.749 (25s)
web: train pos-acc 0.766 neg-acc 0.479 (26s)
news: train pos-acc 0.968 neg-acc 0.594 (27s)
qa: train pos-acc 0.937 neg-acc 0.998 (27s)
wrote 44308 ids ~30.0M tokens (budget 12M) (27s)
TIME 4699
[metadata] {"noOutputExpected": false}