claude-opus-4-8
nano-gpt-data-curation — graded by the task's verifier against a measured baseline.
- backend
- modal
- variant
- claude claude-opus-4-8
- metric
- held-out multi-domain perplexity
- actions
- 82
- duration
- 1h 1m
- recorded
- 2026-08-04
run iddclm-nano-curation__gSSiCuY
Everything claude-opus-4-8 did on this task, in order.
download JSON ↗I'll start by exploring the environment to understand what I'm working with.
args
{
"command": "cat /workspace/.timer/remaining_secs 2>/dev/null; echo \"---\"; ls -la /workspace/; echo \"---\"; ls -la /workspace/data/ 2>/dev/null; echo \"---\"; ls -la /workspace/submission/ 2>/dev/null; echo \"---\"; nvidia-smi 2>/dev/null | head -20",
"description": "Check timer, list workspace and data"
}Bash result
5400
---
total 14
drwxr-xr-x 1 root root 100 Aug 4 03:22 .
drwxr-xr-x 1 root root 160 Aug 4 03:22 ..
drwxr-xr-x 1 root root 60 Aug 4 03:22 .live
drwxr-xr-x 1 root root 100 Aug 4 03:22 .metrics
drwxr-xr-x 1 root root 140 Aug 4 03:22 .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 4 03:22 ..
-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
---
total 1
drwxr-xr-x 1 root root 10 Aug 3 22:37 .
drwxr-xr-x 1 root root 100 Aug 4 03:22 ..
---
Tue Aug 4 03:23:00 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 H100 80GB HBM3 On | 00000000:8C:00.0 Off | 0 |
| N/A 30C P0 67W / 700W | 4MiB / 81559MiB | 0% Default |
| | | Disabled |
+-----------------------------------------+------------------------+----------------------+
+-----------------------------------------------------------------------------------------+
| Processes: |
| GPU GI CI PID Type Process name GPU Memory |
| ID ID Usage |
|=========================================================================================|
| No running processes found |
+-----------------------------------------------------------------------------------------+
[stdout]
5400
---
total 14
drwxr-xr-x 1 root root 100 Aug 4 03:22 .
drwxr-xr-x 1 root root 160 Aug 4 03:22 ..
drwxr-xr-x 1 root root 60 Aug 4 03:22 .live
drwxr-xr-x 1 root root 100 Aug 4 03:22 .metrics
drwxr-xr-x 1 root root 140 Aug 4 03:22 .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 4 03:22 ..
-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
---
total 1
drwxr-xr-x 1 root root 10 Aug 3 22:37 .
drwxr-xr-x 1 root root 100 Aug 4 03:22 ..
---
Tue Aug 4 03:23:00 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 H100 80GB HBM3 On | 00000000:8C:00.0 Off | 0 |
| N/A 30C P0 67W / 700W | 4MiB / 81559MiB | 0% Default |
| | | Disabled |
+-----------------------------------------+------------------------+----------------------+
+-----------------------------------------------------------------------------------------+
| Processes: |
| GPU GI CI PID Type Process name GPU Memory |
| ID ID Usage |
|=========================================================================================|
| No running processes found |
+-----------------------------------------------------------------------------------------+
[metadata] {"noOutputExpected": false}I have 90 minutes (5400s) and an H100. Let me read the key scripts and sample the data.
args
{
"command": "cd /workspace; echo \"=== train_nano.py ===\"; cat train_nano.py; echo; echo \"=== pack_selection.py ===\"; cat pack_selection.py; echo; echo \"=== dev_eval.sh ===\"; cat dev_eval.sh; echo; echo \"=== timer.sh ===\"; cat timer.sh",
"description": "Read training and helper scripts"
}Bash result
=== train_nano.py ===
"""From-scratch nano-GPT (30M) LM training on a 1D token .npy; report held-out perplexity.
Frozen recipe — the ONLY thing that varies between runs is the training token set."""
import argparse, math, time, numpy as np, torch
from model import GPT, GPTConfig
ap = argparse.ArgumentParser()
ap.add_argument("--train_npy", required=True)
ap.add_argument("--heldout_npy", required=True)
ap.add_argument("--out_json", required=True)
ap.add_argument("--max_iters", type=int, default=3000)
ap.add_argument("--warmup", type=int, default=150)
ap.add_argument("--batch", type=int, default=32)
ap.add_argument("--block", type=int, default=256)
ap.add_argument("--lr", type=float, default=6e-4)
ap.add_argument("--seed", type=int, default=1337)
a = ap.parse_args()
torch.manual_seed(a.seed); np.random.seed(a.seed)
dev = "cuda"
tr = np.load(a.train_npy); ho = np.load(a.heldout_npy)
tr = torch.from_numpy(tr.astype(np.int64)); ho = torch.from_numpy(ho.astype(np.int64))
rng = np.random.default_rng(a.seed)
model = GPT(GPTConfig(block_size=a.block, vocab_size=50257, n_layer=6, n_head=6,
n_embd=384, dropout=0.0, bias=False)).to(dev)
opt = model.configure_optimizers(0.1, a.lr, (0.9, 0.95), "cuda")
def lr_at(it):
if it < a.warmup: return a.lr * (it + 1) / (a.warmup + 1)
r = (it - a.warmup) / max(1, a.max_iters - a.warmup)
return 0.1 * a.lr + 0.5 * (1 + math.cos(math.pi * r)) * (a.lr - 0.1 * a.lr)
def get_batch(src):
ix = rng.integers(0, len(src) - a.block - 1, size=a.batch)
x = torch.stack([src[i:i+a.block] for i in ix]).to(dev)
y = torch.stack([src[i+1:i+1+a.block] for i in ix]).to(dev)
return x, y
t0 = time.time()
model.train()
for it in range(a.max_iters):
for g in opt.param_groups: g["lr"] = lr_at(it)
x, y = get_batch(tr)
with torch.autocast("cuda", dtype=torch.bfloat16):
_, loss = model(x, y)
opt.zero_grad(set_to_none=True); loss.backward()
torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0); opt.step()
train_s = time.time() - t0
# held-out perplexity: mean next-token CE over non-overlapping windows (window-weighted)
import json
model.eval()
nwin = (len(ho) - 1) // a.block
starts = [j * a.block for j in range(nwin)]
sum_loss, nseen = 0.0, 0
with torch.no_grad():
for i in range(0, nwin, a.batch):
bs = starts[i:i+a.batch]
x = torch.stack([ho[s:s+a.block] for s in bs]).to(dev)
y = torch.stack([ho[s+1:s+1+a.block] for s in bs]).to(dev)
with torch.autocast("cuda", dtype=torch.bfloat16):
_, l = model(x, y)
sum_loss += l.item() * len(bs); nseen += len(bs)
mean_loss = sum_loss / max(1, nseen)
ppl = math.exp(mean_loss)
out = {"train_npy": a.train_npy, "heldout_ppl": ppl, "mean_loss": mean_loss,
"max_iters": a.max_iters, "seed": a.seed, "train_s": round(train_s, 1)}
json.dump(out, open(a.out_json, "w"))
print(f"HELDOUT_PPL {ppl:.3f} loss {mean_loss:.4f} train_s {train_s:.0f} {a.train_npy}")
=== pack_selection.py ===
"""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)"
=== timer.sh ===
#!/usr/bin/env bash
# Budget timer daemon — writes /workspace/.timer/remaining_secs every 10s so the
# solver can poll time left instead of doing wall-clock arithmetic.
#
# Budget (seconds) comes from $TASK_BUDGET_SECS (set by the runner to the agent
# timeout). Idempotent via a PID file. On ScaleTrain the trial runner starts its
# own timer; this file is the fallback for the Modal/local harbor backends, which
# bootstrap /workspace/timer.sh on environment start. The fallback default below
# (7200 = 2 h) matches this task's [agent] timeout_sec and is only used if
# $TASK_BUDGET_SECS is unset.
set -u
TIMER_DIR="/workspace/.timer"
PID_FILE="$TIMER_DIR/timer.pid"
mkdir -p "$TIMER_DIR"
if [ -s "$PID_FILE" ] && kill -0 "$(cat "$PID_FILE" 2>/dev/null)" 2>/dev/null; then
exit 0 # already running
fi
echo $$ > "$PID_FILE"
trap 'rm -f "$PID_FILE"' EXIT INT TERM
START=$(date +%s)
BUDGET="${TASK_BUDGET_SECS:-7200}"
echo "$START" > "$TIMER_DIR/start_epoch"
echo "$BUDGET" > "$TIMER_DIR/budget_secs"
while true; do
NOW=$(date +%s)
ELAPSED=$((NOW - START))
REMAINING=$((BUDGET - ELAPSED))
[ "$REMAINING" -lt 0 ] && REMAINING=0
echo "$REMAINING" > "$TIMER_DIR/remaining_secs"
echo "$ELAPSED" > "$TIMER_DIR/elapsed_secs"
[ "$REMAINING" -le 1800 ] && [ ! -f "$TIMER_DIR/alert_30min" ] && touch "$TIMER_DIR/alert_30min"
[ "$REMAINING" -le 600 ] && [ ! -f "$TIMER_DIR/alert_10min" ] && touch "$TIMER_DIR/alert_10min"
[ "$REMAINING" -le 0 ] && break
sleep 10
done
[stdout]
=== train_nano.py ===
"""From-scratch nano-GPT (30M) LM training on a 1D token .npy; report held-out perplexity.
Frozen recipe — the ONLY thing that varies between runs is the training token set."""
import argparse, math, time, numpy as np, torch
from model import GPT, GPTConfig
ap = argparse.ArgumentParser()
ap.add_argument("--train_npy", required=True)
ap.add_argument("--heldout_npy", required=True)
ap.add_argument("--out_json", required=True)
ap.add_argument("--max_iters", type=int, default=3000)
ap.add_argument("--warmup", type=int, default=150)
ap.add_argument("--batch", type=int, default=32)
ap.add_argument("--block", type=int, default=256)
ap.add_argument("--lr", type=float, default=6e-4)
ap.add_argument("--seed", type=int, default=1337)
a = ap.parse_args()
torch.manual_seed(a.seed); np.random.seed(a.seed)
dev = "cuda"
tr = np.load(a.train_npy); ho = np.load(a.heldout_npy)
tr = torch.from_numpy(tr.astype(np.int64)); ho = torch.from_numpy(ho.astype(np.int64))
rng = np.random.default_rng(a.seed)
model = GPT(GPTConfig(block_size=a.block, vocab_size=50257, n_layer=6, n_head=6,
n_embd=384, dropout=0.0, bias=False)).to(dev)
opt = model.configure_optimizers(0.1, a.lr, (0.9, 0.95), "cuda")
def lr_at(it):
if it < a.warmup: return a.lr * (it + 1) / (a.warmup + 1)
r = (it - a.warmup) / max(1, a.max_iters - a.warmup)
return 0.1 * a.lr + 0.5 * (1 + math.cos(math.pi * r)) * (a.lr - 0.1 * a.lr)
def get_batch(src):
ix = rng.integers(0, len(src) - a.block - 1, size=a.batch)
x = torch.stack([src[i:i+a.block] for i in ix]).to(dev)
y = torch.stack([src[i+1:i+1+a.block] for i in ix]).to(dev)
return x, y
t0 = time.time()
model.train()
for it in range(a.max_iters):
for g in opt.param_groups: g["lr"] = lr_at(it)
x, y = get_batch(tr)
with torch.autocast("cuda", dtype=torch.bfloat16):
_, loss = model(x, y)
opt.zero_grad(set_to_none=True); loss.backward()
torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0); opt.step()
train_s = time.time() - t0
# held-out perplexity: mean next-token CE over non-overlapping windows (window-weighted)
import json
model.eval()
nwin = (len(ho) - 1) // a.block
starts = [j * a.block for j in range(nwin)]
sum_loss, nseen = 0.0, 0
with torch.no_grad():
for i in range(0, nwin, a.batch):
bs = starts[i:i+a.batch]
x = torch.stack([ho[s:s+a.block] for s in bs]).to(dev)
y = torch.stack([ho[s+1:s+1+a.block] for s in bs]).to(dev)
with torch.autocast("cuda", dtype=torch.bfloat16):
_, l = model(x, y)
sum_loss += l.item() * len(bs); nseen += len(bs)
mean_loss = sum_loss / max(1, nseen)
ppl = math.exp(mean_loss)
out = {"train_npy": a.train_npy, "heldout_ppl": ppl, "mean_loss": mean_loss,
"max_iters": a.max_iters, "seed": a.seed, "train_s": round(train_s, 1)}
json.dump(out, open(a.out_json, "w"))
print(f"HELDOUT_PPL {ppl:.3f} loss {mean_loss:.4f} train_s {train_s:.0f} {a.train_npy}")
=== pack_selection.py ===
"""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)"
=== timer.sh ===
#!/usr/bin/env bash
# Budget timer daemon — writes /workspace/.timer/remaining_secs every 10s so the
# solver can poll time left instead of doing wall-clock arithmetic.
#
# Budget (seconds) comes from $TASK_BUDGET_SECS (set by the runner to the agent
# timeout). Idempotent via a PID file. On ScaleTrain the trial runner starts its
# own timer; this file is the fallback for the Modal/local harbor backends, which
# bootstrap /workspace/timer.sh on environment start. The fallback default below
# (7200 = 2 h) matches this task's [agent] timeout_sec and is only used if
# $TASK_BUDGET_SECS is unset.
set -u
TIMER_DIR="/workspace/.timer"
PID_FILE="$TIMER_DIR/timer.pid"
mkdir -p "$TIMER_DIR"
if [ -s "$PID_FILE" ] && kill -0 "$(cat "$PID_FILE" 2>/dev/null)" 2>/dev/null; then
exit 0 # already running
fi
echo $$ > "$PID_FILE"
trap 'rm -f "$PID_FILE"' EXIT INT TERM
START=$(date +%s)
BUDGET="${TASK_BUDGET_SECS:-7200}"
echo "$START" > "$TIMER_DIR/start_epoch"
echo "$BUDGET" > "$TIMER_DIR/budget_secs"
while true; do
NOW=$(date +%s)
ELAPSED=$((NOW - START))
REMAINING=$((BUDGET - ELAPSED))
[ "$REMAINING" -lt 0 ] && REMAINING=0
echo "$REMAINING" > "$TIMER_DIR/remaining_secs"
echo "$ELAPSED" > "$TIMER_DIR/elapsed_secs"
[ "$REMAINING" -le 1800 ] && [ ! -f "$TIMER_DIR/alert_30min" ] && touch "$TIMER_DIR/alert_30min"
[ "$REMAINING" -le 600 ] && [ ! -f "$TIMER_DIR/alert_10min" ] && touch "$TIMER_DIR/alert_10min"
[ "$REMAINING" -le 0 ] && break
sleep 10
done
[metadata] {"noOutputExpected": false}90 minutes, H100, ~60s per training run. Key facts: 12M token budget, target is broad HQ English (Wikipedia/web/news/technical Q&A). Crucially, multi_dev.npy is the tokenized dev target — I can decode it back to text to get positive examples of the target domain, then train a classifier to score pool docs by target-likeness (a DSIR/fastText-style approach). Let me explore.
args
{
"command": "cd /workspace; python3 -c \"\nimport numpy as np, json\nfrom transformers import AutoTokenizer\ntok = AutoTokenizer.from_pretrained('gpt2')\ndev = np.load('data/multi_dev.npy')\nprint('dev dtype', dev.dtype, 'len', len(dev))\nEOS = tok.eos_token_id\nprint('EOS id', EOS)\n# split into docs by EOS\nimport numpy as np\nidx = np.where(dev==EOS)[0]\nprint('num EOS', len(idx))\nprint('first 30 EOS positions', idx[:30])\n# decode first few docs\nprev=0\ndocs=[]\nfor j in idx[:8]:\n docs.append(dev[prev:j]); prev=j+1\nfor d in docs[:6]:\n print('----DOC len', len(d))\n print(repr(tok.decode(d)[:600]))\n\"",
"description": "Decode multi_dev target into text"
}Bash result
dev dtype uint16 len 1000000
EOS id 50256
num EOS 2704
first 30 EOS positions [ 206 332 556 652 854 986 1010 1080 1231 1555 1789 2010 2179 2412
2473 2516 2702 2875 3017 3128 3382 3628 3930 4019 4184 4305 4447 4517
4694 4887]
----DOC len 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 conquest of both the geographical South Pole and the South Magnetic Pole . Shackleton then worked hard to persuade others of his wealthy friends and acquaintances to contribute , includin"
----DOC len 125
" On 1 January 1908 , Nimrod sailed for the Antarctic from Lyttelton Harbour , New Zealand . Shackleton 's original plans had envisaged using the old Discovery base in McMurdo Sound to launch his attempts on the South Pole and South Magnetic Pole . However , before leaving England , he had been pressured to give an undertaking to Scott that he would not base himself in the McMurdo area , which Scott was claiming as his own field of work . Shackleton reluctantly agreed to look for winter quarters at either the Barrier Inlet ( which Discovery had briefly visited in 1902 ) or King Edward VII Land "
----DOC len 223
" To conserve coal , the ship was towed 1 @,@ 650 miles ( 2 @,@ 655 km ) by the steamer Koonya to the Antarctic ice , after Shackleton had persuaded the New Zealand government and the Union Steamship Company to share the cost . In accordance with Shackleton 's promise to Scott , the ship headed for the eastern sector of the Great Ice Barrier , arriving there on 21 January 1908 . They found that the Barrier Inlet had expanded to form a large bay , in which were hundreds of whales , which led to the immediate christening of the area as the Bay of Whales . It was noted that ice conditions were uns"
----DOC len 95
" Nimrod arrived at McMurdo Sound on 29 January , but was stopped by ice 16 miles ( 26 km ) north of Discovery 's old base at Hut Point . After considerable weather delays , Shackleton 's base was eventually established at Cape Royds , about 24 miles ( 39 km ) north of Hut Point . The party was in high spirits , despite the difficult conditions ; Shackleton 's ability to communicate with each man kept the party happy and focused . \n"
----DOC len 201
' The " Great Southern Journey " , as Frank Wild called it , began on 29 October 1908 . On 9 January 1909 , Shackleton and three companions ( Wild , Eric Marshall and Jameson Adams ) reached a new Farthest South latitude of 88 ° 23 \' S , a point only 112 miles ( 180 km ) from the Pole . En route the South Pole party discovered the Beardmore Glacier ( named after Shackleton \'s patron ) and became the first persons to see and travel on the South Polar Plateau . Their return journey to McMurdo Sound was a race against starvation , on half @-@ rations for much of the way . At one point , Shackleton'
----DOC len 131
' The expedition \'s other main accomplishments included the first ascent of Mount Erebus , and the discovery of the approximate location of the South Magnetic Pole , reached on 16 January 1909 by Edgeworth David , Douglas Mawson , and Alistair Mackay . Shackleton returned to the United Kingdom as a hero , and soon afterwards published his expedition account , Heart of the Antarctic . Emily Shackleton later recorded : " The only comment he made to me about not reaching the Pole was \' a live donkey is better than a dead lion , isn \'t it ? \' and I said \' Yes darling , as far as I am concerned \' " '
[stdout]
dev dtype uint16 len 1000000
EOS id 50256
num EOS 2704
first 30 EOS positions [ 206 332 556 652 854 986 1010 1080 1231 1555 1789 2010 2179 2412
2473 2516 2702 2875 3017 3128 3382 3628 3930 4019 4184 4305 4447 4517
4694 4887]
----DOC len 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 conquest of both the geographical South Pole and the South Magnetic Pole . Shackleton then worked hard to persuade others of his wealthy friends and acquaintances to contribute , includin"
----DOC len 125
" On 1 January 1908 , Nimrod sailed for the Antarctic from Lyttelton Harbour , New Zealand . Shackleton 's original plans had envisaged using the old Discovery base in McMurdo Sound to launch his attempts on the South Pole and South Magnetic Pole . However , before leaving England , he had been pressured to give an undertaking to Scott that he would not base himself in the McMurdo area , which Scott was claiming as his own field of work . Shackleton reluctantly agreed to look for winter quarters at either the Barrier Inlet ( which Discovery had briefly visited in 1902 ) or King Edward VII Land "
----DOC len 223
" To conserve coal , the ship was towed 1 @,@ 650 miles ( 2 @,@ 655 km ) by the steamer Koonya to the Antarctic ice , after Shackleton had persuaded the New Zealand government and the Union Steamship Company to share the cost . In accordance with Shackleton 's promise to Scott , the ship headed for the eastern sector of the Great Ice Barrier , arriving there on 21 January 1908 . They found that the Barrier Inlet had expanded to form a large bay , in which were hundreds of whales , which led to the immediate christening of the area as the Bay of Whales . It was noted that ice conditions were uns"
----DOC len 95
" Nimrod arrived at McMurdo Sound on 29 January , but was stopped by ice 16 miles ( 26 km ) north of Discovery 's old base at Hut Point . After considerable weather delays , Shackleton 's base was eventually established at Cape Royds , about 24 miles ( 39 km ) north of Hut Point . The party was in high spirits , despite the difficult conditions ; Shackleton 's ability to communicate with each man kept the party happy and focused . \n"
----DOC len 201
' The " Great Southern Journey " , as Frank Wild called it , began on 29 October 1908 . On 9 January 1909 , Shackleton and three companions ( Wild , Eric Marshall and Jameson Adams ) reached a new Farthest South latitude of 88 ° 23 \' S , a point only 112 miles ( 180 km ) from the Pole . En route the South Pole party discovered the Beardmore Glacier ( named after Shackleton \'s patron ) and became the first persons to see and travel on the South Polar Plateau . Their return journey to McMurdo Sound was a race against starvation , on half @-@ rations for much of the way . At one point , Shackleton'
----DOC len 131
' The expedition \'s other main accomplishments included the first ascent of Mount Erebus , and the discovery of the approximate location of the South Magnetic Pole , reached on 16 January 1909 by Edgeworth David , Douglas Mawson , and Alistair Mackay . Shackleton returned to the United Kingdom as a hero , and soon afterwards published his expedition account , Heart of the Antarctic . Emily Shackleton later recorded : " The only comment he made to me about not reaching the Pole was \' a live donkey is better than a dead lion , isn \'t it ? \' and I said \' Yes darling , as far as I am concerned \' " '
[metadata] {"noOutputExpected": false}The dev target is clearly HQ text (Wikipedia-style shown). Let me sample across the whole dev to see all four registers, and sample the raw pool.
args
{
"command": "cd /workspace; python3 -c \"\nimport numpy as np, json\nfrom transformers import AutoTokenizer\ntok = AutoTokenizer.from_pretrained('gpt2')\ndev = np.load('data/multi_dev.npy')\nEOS = 50256\nidx = np.where(dev==EOS)[0]\n# sample docs from across the dev range\nimport random\npicks = [50, 400, 800, 1200, 1600, 2000, 2400, 2650]\nprev_positions = np.concatenate([[0], idx+1])\nfor p in picks:\n s = prev_positions[p]; e = idx[p]\n print('=== dev doc', p, 'len', e-s)\n print(repr(tok.decode(dev[s:e])[:400]))\n print()\n\"",
"description": "Sample dev docs across range for register diversity"
}Bash result
=== dev doc 50 len 89
' In addition to Barker and the regular cast , actor Jeff Bergman , voice actor Chris Cox , actor Michael Clarke Duncan , actor Keir Gilchrist , actress Beth Littleford and voice actress Rachael MacFarlane guest starred in the episode . Recurring guest voice actors Chris Sheridan , writer Danny Smith , writer Alec Sulkin and writer John Viener made minor appearances . Actor Patrick Warburton also h'
=== dev doc 400 len 479
' Chasen has appeared in other television programmes such as The Bill and The Harry Hill Show . She has had guest roles in Z @-@ Cars and Dixon of Dock Green and has voiced a number of characters in the radio show The Navy Lark , most notably WREN Heather Chasen and " battle axe " Ramona Povey . In soaps , she has had four separate stints in the BBC soap opera Doctors , with her most recent stint i'
=== dev doc 800 len 172
" The theme of family and family relationships — from the character @-@ defining experience of Angelou 's parents ' abandonment in Caged Bird to her relationships with her son , husbands , friends , and lovers — are important in all of her books . As in American autobiography generally and in African @-@ American autobiography specifically , which has its roots in the slave narrative , travel is an"
=== dev doc 1200 len 184
' Andrew Carnegie , an immigrant from Scotland , a former Pennsylvania Railroad executive turned steel magnate , founded the Carnegie Steel Company . He proceeded to play a key role in the development of the U.S. steel industry . He became a philanthropist : in 1890 , he established the first Carnegie Library , in a program to establish libraries in numerous cities and towns by the incentive of mat'
=== dev doc 1600 len 163
' A solar cell , or photovoltaic cell ( PV ) , is a device that converts light into electric current using the photovoltaic effect . The first solar cell was constructed by Charles Fritts in the 1880s . The German industrialist Ernst Werner von Siemens was among those who recognized the importance of this discovery . In 1931 , the German engineer Bruno Lange developed a photo cell using silver sele'
=== dev doc 2000 len 151
'Socialite Paris Hilton looked happy during her holiday in Formentera with her boyfriend Chris Zylka as they enjoyed a boating session together.Hilton was spotted in a lacy red dress as she held hands with the actor as they crossed the beach and took a ride in a small boat on Friday, reports dailymail.co.uk.Hilton accessorised her ensemble with a massive red-rimmed pair of sunglasses, as well as wi'
=== dev doc 2400 len 1449
'<p>In the following, the echo output is right, but the pgm is not receiving the flags correctly. Appreciate any insights.</p>\n\n<pre><code>script file:\nflags="-umc -v -v "\nr="";for d in `ls -d /tmp/passenger*`; do r="$r -x $d"; done\nflags="$flags $r"\necho $flags\n/usr/sbin/tmpwatch "$flags" -x /tmp/.X11-unix -x /tmp/.XIM-unix \\\n -x /tmp/.font-unix -x /tmp/.ICE-unix -x /tmp/.Test-unix 240 /tmp\n</'
=== dev doc 2650 len 581
"<p>We're running Java Swing and are using an SWT bridge to get ahold of the SWT browser. Everything normally works just fine, but we have a problem on a Vista test machine. It worked fine until just a week ago or so. The call stack:</p>\n\n<pre><code>org.eclipse.swt.SWTError: No more handles\n at org.eclipse.swt.SWT.error(SWT.java:3589)\n at org.eclipse.swt.SWT.error(SWT.java:3481)\n at org.ec"
[stdout]
=== dev doc 50 len 89
' In addition to Barker and the regular cast , actor Jeff Bergman , voice actor Chris Cox , actor Michael Clarke Duncan , actor Keir Gilchrist , actress Beth Littleford and voice actress Rachael MacFarlane guest starred in the episode . Recurring guest voice actors Chris Sheridan , writer Danny Smith , writer Alec Sulkin and writer John Viener made minor appearances . Actor Patrick Warburton also h'
=== dev doc 400 len 479
' Chasen has appeared in other television programmes such as The Bill and The Harry Hill Show . She has had guest roles in Z @-@ Cars and Dixon of Dock Green and has voiced a number of characters in the radio show The Navy Lark , most notably WREN Heather Chasen and " battle axe " Ramona Povey . In soaps , she has had four separate stints in the BBC soap opera Doctors , with her most recent stint i'
=== dev doc 800 len 172
" The theme of family and family relationships — from the character @-@ defining experience of Angelou 's parents ' abandonment in Caged Bird to her relationships with her son , husbands , friends , and lovers — are important in all of her books . As in American autobiography generally and in African @-@ American autobiography specifically , which has its roots in the slave narrative , travel is an"
=== dev doc 1200 len 184
' Andrew Carnegie , an immigrant from Scotland , a former Pennsylvania Railroad executive turned steel magnate , founded the Carnegie Steel Company . He proceeded to play a key role in the development of the U.S. steel industry . He became a philanthropist : in 1890 , he established the first Carnegie Library , in a program to establish libraries in numerous cities and towns by the incentive of mat'
=== dev doc 1600 len 163
' A solar cell , or photovoltaic cell ( PV ) , is a device that converts light into electric current using the photovoltaic effect . The first solar cell was constructed by Charles Fritts in the 1880s . The German industrialist Ernst Werner von Siemens was among those who recognized the importance of this discovery . In 1931 , the German engineer Bruno Lange developed a photo cell using silver sele'
=== dev doc 2000 len 151
'Socialite Paris Hilton looked happy during her holiday in Formentera with her boyfriend Chris Zylka as they enjoyed a boating session together.Hilton was spotted in a lacy red dress as she held hands with the actor as they crossed the beach and took a ride in a small boat on Friday, reports dailymail.co.uk.Hilton accessorised her ensemble with a massive red-rimmed pair of sunglasses, as well as wi'
=== dev doc 2400 len 1449
'<p>In the following, the echo output is right, but the pgm is not receiving the flags correctly. Appreciate any insights.</p>\n\n<pre><code>script file:\nflags="-umc -v -v "\nr="";for d in `ls -d /tmp/passenger*`; do r="$r -x $d"; done\nflags="$flags $r"\necho $flags\n/usr/sbin/tmpwatch "$flags" -x /tmp/.X11-unix -x /tmp/.XIM-unix \\\n -x /tmp/.font-unix -x /tmp/.ICE-unix -x /tmp/.Test-unix 240 /tmp\n</'
=== dev doc 2650 len 581
"<p>We're running Java Swing and are using an SWT bridge to get ahold of the SWT browser. Everything normally works just fine, but we have a problem on a Vista test machine. It worked fine until just a week ago or so. The call stack:</p>\n\n<pre><code>org.eclipse.swt.SWTError: No more handles\n at org.eclipse.swt.SWT.error(SWT.java:3589)\n at org.eclipse.swt.SWT.error(SWT.java:3481)\n at org.ec"
[metadata] {"noOutputExpected": false}Clear register mix: Wikipedia (spaced-punct normalization), news prose, and StackOverflow Q&A (HTML tags). Now let me examine the raw pool.
args
{
"command": "cd /workspace; python3 -c \"\nimport json\nfrom transformers import AutoTokenizer\ntok = AutoTokenizer.from_pretrained('gpt2')\nimport itertools\nn=0\nlens=[]\nwith open('data/pool.jsonl') as f:\n for i,line in enumerate(f):\n r=json.loads(line)\n if i in (0,1,2,5,10,50,200,1000,5000,50000,120000):\n print('=== pool id', r['id'], 'chars', len(r['text']))\n print(repr(r['text'][:500]))\n print()\n if i>120001: break\n\"",
"description": "Sample raw pool documents"
}Bash result
=== pool id 0 chars 414
'|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 · DAYS: News, Spoilers & Discussion|'
=== pool id 1 chars 3018
'*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'
=== pool id 2 chars 2825
'A novel two-step immunotherapy approach has shown clinically beneficial responses in patients with advanced ovarian cancer. Following Lifestyle Recommendations Reduces Risk of Cancer Death\nPeople who follow the diet and lifestyle recommendations laid out by the WCRF and the AICR have a 20 percent reduced risk of dying from cancer. UCSF Launches Social Networking Site for Patients and Families with Hereditary Cancers\nFor Immediate Release May 14, 2013 UCSF Launches Social Networking Site for Pati'
=== pool id 5 chars 2744
'September 28, 2010\n2010 Season - Bowman pulls down CCIW honor\n|Matt Bowman was named CCIW "Runner of the Week" after his fourth place finish at the Brissman-Lundeen Invitational in Rock Island, Illinois on September 24.|\nAugustana senior Matt Bowman (Geneva HS, Elburn, Ill.) was selected as the “Runner of the Week” in the College Conference of Illinois & Wisconsin. Bowman’s strong performance helped the Vikings finish second at the Brissman-Lundeen Invitational at Augustana College in Rock Islan'
=== pool id 10 chars 1307
'Category Archives: 2010 – 2011\nTO: The University Community RE: Budget Challenges for 2011-2012 and the 2011 Regular Legislative Session Weeks ago, the Jindal administration sought to lessen state-wide tensions over the future funding of postsecondary education by announcing that any budget cut for the 2011-2012 fiscal year would not amount to more than 10 percent. While providing no specificity [...]\nDr. Stephen T. Hulbert, president of Nicholls State University, issued the following statement '
=== pool id 50 chars 4466
'Southridge Minerals Hires New Legal Representation and Completes Dividend Payout\nDALLAS, Nov. 23, 2012 /PRNewswire/ -- Southridge Enterprises Inc. (Pink Sheets: SRGE) ("Southridge" or the "Company") is pleased to announce today that Southridge Minerals, Inc., its wholly owned subsidiary, has hired new legal representation to meet the Company\'s expanding legal needs going forward. The new firm is now transitioning to file all of the Company\'s future disclosures with the OTC Markets and will be th'
=== pool id 200 chars 979
"Inquiring Skeptics of Upper New York\nThe 1st Symposium on Anomalous Phenomena.\nFor three years Rensselaer\nPolytechnic Institute (RPI) hosted a UFO symposium. In 1995\nthe 3rd symposium was called the 1st Anomalous Phenomena\nSymposium. The bulk of the talks, however, were about UFOs.\nSeveral ISUNY members attended some the talks, and links are provided\nto our summaries.\n- March 31, 7:30pm\n- Robert Hastings - UFO Researcher, ``UFOs - The Hidden History''\n- April 21, 8:00pm\n- Dr. Bruce Maccabee - ph"
=== pool id 1000 chars 23480
'ANNCR: Over the years, Cory Gardner supported three personhood amendments … to make all abortions illegal.\nTEXT: Cory Gardner Supported three personhood amendments to make all abortions illegal\nSOURCE: Amendment 62, 11/2/10; Amendment 48, 11/4/08; 2006 Colorado Right to Life Voter Guide\nIN 2008 AND 2010, GARDNER SUPPORTED BALLOT INITIATIVES IN COLORADO PROMOTING PERSONHOOD\nGardner Supported Amendment 62, Or The Personhood Amendment: “I Have Signed The Personhood Petition. I Have Taken The Petiti'
=== pool id 5000 chars 3577
'11 months. I can’t believe I’ve been in Italy for so long. I seriously can’t believe it and I don’t know how I allowed myself to spend so many days of pure apathy and boredom in a row. Sounds too harsh? Believe me, it was not even nearly as harsh as it sounds here. But I talked about my struggles in my previous post already, and this is supposed to be a happy post, well, at least a positive one. So here I am with my many upcoming travel plans!\nAbout two weeks ago, I suddenly felt the urge to go '
=== pool id 50000 chars 3918
'USAToday Redesign: An Unwanted Downgrade\nUSAToday underwent a much publicized site redesign this weekend. As part of the site shuffling, USAToday got rid of several traditional front page staples and added a host of social networking type features intended to build a stronger USAToday community.\nThe initial response to the redesign seemed to be positive. The big industry blogs applauded USAToday for embracing the new medium and trying to leverage some community appeal. But as with most things, t'
=== pool id 120000 chars 1013
'Sign in - Google Accounts\nOne account. All of Google.\nSign in with your Google Account\nEnter your email\nFind my account\nSign in with a different account Create account\nOne Google Account for everything Google\nAbout Google\nPrivacy\nTerms\nHelp\n\u202aAfrikaans\u202c \u202aazərbaycan\u202c \u202acatalà\u202c \u202aČeština\u202c \u202aDansk\u202c \u202aDeutsch\u202c \u202aeesti\u202c \u202aEnglish (United Kingdom)\u202c \u202aEnglish (United States)\u202c \u202aEspañol (España)\u202c \u202aEspañol (Latinoamérica)\u202c \u202aeuskara\u202c \u202aFilipino\u202c \u202aFrançais (Canada)\u202c \u202aFrançais (France)\u202c \u202agalego\u202c \u202aHrvatski\u202c \u202aIndonesia'
[stdout]
=== pool id 0 chars 414
'|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 · DAYS: News, Spoilers & Discussion|'
=== pool id 1 chars 3018
'*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'
=== pool id 2 chars 2825
'A novel two-step immunotherapy approach has shown clinically beneficial responses in patients with advanced ovarian cancer. Following Lifestyle Recommendations Reduces Risk of Cancer Death\nPeople who follow the diet and lifestyle recommendations laid out by the WCRF and the AICR have a 20 percent reduced risk of dying from cancer. UCSF Launches Social Networking Site for Patients and Families with Hereditary Cancers\nFor Immediate Release May 14, 2013 UCSF Launches Social Networking Site for Pati'
=== pool id 5 chars 2744
'September 28, 2010\n2010 Season - Bowman pulls down CCIW honor\n|Matt Bowman was named CCIW "Runner of the Week" after his fourth place finish at the Brissman-Lundeen Invitational in Rock Island, Illinois on September 24.|\nAugustana senior Matt Bowman (Geneva HS, Elburn, Ill.) was selected as the “Runner of the Week” in the College Conference of Illinois & Wisconsin. Bowman’s strong performance helped the Vikings finish second at the Brissman-Lundeen Invitational at Augustana College in Rock Islan'
=== pool id 10 chars 1307
'Category Archives: 2010 – 2011\nTO: The University Community RE: Budget Challenges for 2011-2012 and the 2011 Regular Legislative Session Weeks ago, the Jindal administration sought to lessen state-wide tensions over the future funding of postsecondary education by announcing that any budget cut for the 2011-2012 fiscal year would not amount to more than 10 percent. While providing no specificity [...]\nDr. Stephen T. Hulbert, president of Nicholls State University, issued the following statement '
=== pool id 50 chars 4466
'Southridge Minerals Hires New Legal Representation and Completes Dividend Payout\nDALLAS, Nov. 23, 2012 /PRNewswire/ -- Southridge Enterprises Inc. (Pink Sheets: SRGE) ("Southridge" or the "Company") is pleased to announce today that Southridge Minerals, Inc., its wholly owned subsidiary, has hired new legal representation to meet the Company\'s expanding legal needs going forward. The new firm is now transitioning to file all of the Company\'s future disclosures with the OTC Markets and will be th'
=== pool id 200 chars 979
"Inquiring Skeptics of Upper New York\nThe 1st Symposium on Anomalous Phenomena.\nFor three years Rensselaer\nPolytechnic Institute (RPI) hosted a UFO symposium. In 1995\nthe 3rd symposium was called the 1st Anomalous Phenomena\nSymposium. The bulk of the talks, however, were about UFOs.\nSeveral ISUNY members attended some the talks, and links are provided\nto our summaries.\n- March 31, 7:30pm\n- Robert Hastings - UFO Researcher, ``UFOs - The Hidden History''\n- April 21, 8:00pm\n- Dr. Bruce Maccabee - ph"
=== pool id 1000 chars 23480
'ANNCR: Over the years, Cory Gardner supported three personhood amendments … to make all abortions illegal.\nTEXT: Cory Gardner Supported three personhood amendments to make all abortions illegal\nSOURCE: Amendment 62, 11/2/10; Amendment 48, 11/4/08; 2006 Colorado Right to Life Voter Guide\nIN 2008 AND 2010, GARDNER SUPPORTED BALLOT INITIATIVES IN COLORADO PROMOTING PERSONHOOD\nGardner Supported Amendment 62, Or The Personhood Amendment: “I Have Signed The Personhood Petition. I Have Taken The Petiti'
=== pool id 5000 chars 3577
'11 months. I can’t believe I’ve been in Italy for so long. I seriously can’t believe it and I don’t know how I allowed myself to spend so many days of pure apathy and boredom in a row. Sounds too harsh? Believe me, it was not even nearly as harsh as it sounds here. But I talked about my struggles in my previous post already, and this is supposed to be a happy post, well, at least a positive one. So here I am with my many upcoming travel plans!\nAbout two weeks ago, I suddenly felt the urge to go '
=== pool id 50000 chars 3918
'USAToday Redesign: An Unwanted Downgrade\nUSAToday underwent a much publicized site redesign this weekend. As part of the site shuffling, USAToday got rid of several traditional front page staples and added a host of social networking type features intended to build a stronger USAToday community.\nThe initial response to the redesign seemed to be positive. The big industry blogs applauded USAToday for embracing the new medium and trying to leverage some community appeal. But as with most things, t'
=== pool id 120000 chars 1013
'Sign in - Google Accounts\nOne account. All of Google.\nSign in with your Google Account\nEnter your email\nFind my account\nSign in with a different account Create account\nOne Google Account for everything Google\nAbout Google\nPrivacy\nTerms\nHelp\n\u202aAfrikaans\u202c \u202aazərbaycan\u202c \u202acatalà\u202c \u202aČeština\u202c \u202aDansk\u202c \u202aDeutsch\u202c \u202aeesti\u202c \u202aEnglish (United Kingdom)\u202c \u202aEnglish (United States)\u202c \u202aEspañol (España)\u202c \u202aEspañol (Latinoamérica)\u202c \u202aeuskara\u202c \u202aFilipino\u202c \u202aFrançais (Canada)\u202c \u202aFrançais (France)\u202c \u202agalego\u202c \u202aHrvatski\u202c \u202aIndonesia'
[metadata] {"noOutputExpected": false}This is classic noisy web crawl (forum junk, Google boilerplate, plus some decent prose/news). My plan:
- Decode `multi_dev` → text = positive examples of the target domain (de-normalizing the WikiText
@-@artifacts so the classifier learns real register signal, not surface tokens). - Train a target-vs-pool classifier (DSIR/fastText-style) on hashed word n-grams, score all 182k pool docs.
- Apply light quality gates + dedup, rank by score, fill the budget.
- Validate with training runs vs a random baseline.
Let me set up tasks and write the curation script.
args
{
"subject": "Build target-vs-pool classifier & score pool",
"description": "Decode multi_dev to text positives, train LR on hashed n-grams vs pool negatives, score all 182k docs, cache scores.",
"activeForm": "Building classifier and scoring pool"
}TaskCreate result
Task #1 created successfully: Build target-vs-pool classifier & score pool
[metadata] {"task": {"id": "1", "subject": "Build target-vs-pool classifier & score pool"}}encrypted chain-of-thought — recorded, not exposed
args
{
"subject": "Generate selection.json with quality gates + dedup",
"description": "From scores, apply length/quality gates and dedup, rank desc, write >12M-token ordered id list.",
"activeForm": "Generating selection with gates and dedup"
}TaskCreate result
Task #2 created successfully: Generate selection.json with quality gates + dedup
[metadata] {"task": {"id": "2", "subject": "Generate selection.json with quality gates + dedup"}}encrypted chain-of-thought — recorded, not exposed
args
{
"subject": "Validate selection vs random baseline via training runs",
"description": "Run dev_eval on random baseline and classifier selection; compare held-out ppl; iterate on policy.",
"activeForm": "Validating via training runs"
}TaskCreate result
Task #3 created successfully: Validate selection vs random baseline via training runs
[metadata] {"task": {"id": "3", "subject": "Validate selection vs random baseline via training runs"}}encrypted chain-of-thought — recorded, not exposed
args
{
"subject": "Write curate.py, selection.json, claim.md deliverables",
"description": "Finalize reproducible curate.py, the ordered selection.json, and claim.md (hypothesis/mechanism/falsification/transfer).",
"activeForm": "Writing final deliverables"
}TaskCreate result
Task #4 created successfully: Write curate.py, selection.json, claim.md deliverables
[metadata] {"task": {"id": "4", "subject": "Write curate.py, selection.json, claim.md deliverables"}}encrypted chain-of-thought — recorded, not exposed
args
{
"taskId": "1",
"status": "in_progress"
}TaskUpdate result
Updated task #1 status
[metadata] {"success": true, "taskId": "1", "updatedFields": ["status"], "statusChange": {"from": "pending", "to": "in_progress"}}encrypted chain-of-thought — recorded, not exposed
args
{
"file_path": "/workspace/curate.py",
"content": "\"\"\"Curate a raw web pool for small-LM pretraining by TARGET-DOMAIN classification.\n\nCriterion (stated, reproducible):\n Score every pool document by P(doc is drawn from the disclosed high-quality\n multi-domain target) using a logistic-regression domain classifier, then keep\n the highest-scoring documents (after light quality gates + dedup) in priority\n order until the training budget is filled.\n\nPositives for the classifier are the DEV target documents themselves, recovered\nby GPT-2-decoding /workspace/data/multi_dev.npy and de-normalizing the WikiText\n` @-@ `/` @,@ ` spacing artifacts so the classifier keys on register/quality\nrather than surface tokenization. Negatives are a random sample of the raw pool\n(PU-learning: most of the pool is off-target, so the LR direction separates\ntarget-like prose from generic web crawl).\n\nUsage:\n python3 curate.py # full run, writes submission/selection.json\n python3 curate.py --reuse # reuse cached texts + scores (fast policy tweaks)\n\"\"\"\nimport argparse, json, re, os, pickle, numpy as np\n\nPOOL = \"/workspace/data/pool.jsonl\"\nDEV = \"/workspace/data/multi_dev.npy\"\nOUT = \"/workspace/submission/selection.json\"\nCACHE_TXT = \"/tmp/pool_texts.pkl\"\nCACHE_SCORE = \"/tmp/pool_scores.npy\"\nCACHE_IDS = \"/tmp/pool_ids.npy\"\nEOS = 50256\n\nap = argparse.ArgumentParser()\nap.add_argument(\"--reuse\", action=\"store_true\", help=\"reuse cached texts and scores\")\nap.add_argument(\"--target_tokens\", type=int, default=20_000_000,\n help=\"how many tokens of ids to emit (>12M budget, extras unused)\")\nap.add_argument(\"--neg\", type=int, default=25_000, help=\"num pool negatives\")\na = ap.parse_args()\n\n# ---------- de-normalize WikiText-103 style spacing so positives look like raw web ----------\ndef denorm(t):\n t = t.replace(\" @-@ \", \"-\").replace(\" @,@ \", \",\").replace(\" @.@ \", \".\")\n # collapse \" , \" / \" . \" / \" ; \" spaced punctuation -> attached punctuation\n t = re.sub(r\"\\s+([,.;:!?%])\", r\"\\1\", t)\n t = re.sub(r\"\\(\\s+\", \"(\", t); t = re.sub(r\"\\s+\\)\", \")\", t)\n t = re.sub(r\"\\s+'s\\b\", \"'s\", t)\n return t\n\n# ---------- load pool texts (cache) ----------\nif a.reuse and os.path.exists(CACHE_TXT):\n print(\"loading cached pool texts...\")\n ids, texts = pickle.load(open(CACHE_TXT, \"rb\"))\nelse:\n print(\"reading pool.jsonl ...\")\n ids, texts = [], []\n with open(POOL) as f:\n for line in f:\n r = json.loads(line)\n ids.append(r[\"id\"]); texts.append(r[\"text\"])\n pickle.dump((ids, texts), open(CACHE_TXT, \"wb\"))\nids = np.array(ids)\nprint(f\"pool docs: {len(ids)}\")\n\n# ---------- build classifier + score (cache) ----------\nif a.reuse and os.path.exists(CACHE_SCORE):\n print(\"loading cached scores...\")\n scores = np.load(CACHE_SCORE)\n cids = np.load(CACHE_IDS)\n assert np.array_equal(cids, ids), \"cache id mismatch; rerun without --reuse\"\nelse:\n from transformers import AutoTokenizer\n from sklearn.feature_extraction.text import HashingVectorizer\n from sklearn.linear_model import LogisticRegression\n\n print(\"decoding dev target -> positive docs ...\")\n dev = np.load(DEV)\n cut = np.where(dev == EOS)[0]\n tok = AutoTokenizer.from_pretrained(\"gpt2\")\n pos_docs, prev = [], 0\n for c in cut:\n seg = dev[prev:c]; prev = c + 1\n if len(seg) >= 16:\n pos_docs.append(denorm(tok.decode(seg)))\n print(f\"positive (target) docs: {len(pos_docs)}\")\n\n rng = np.random.default_rng(0)\n neg_idx = rng.choice(len(texts), size=min(a.neg, len(texts)), replace=False)\n neg_docs = [texts[i] for i in neg_idx]\n\n Xtxt = pos_docs + neg_docs\n y = np.array([1] * len(pos_docs) + [0] * len(neg_docs))\n print(\"vectorizing (word 1-2 grams, hashed) ...\")\n vec = HashingVectorizer(ngram_range=(1, 2), n_features=2**20,\n alternate_sign=False, norm=\"l2\", lowercase=True)\n Xtr = vec.transform(Xtxt)\n print(\"fitting logistic regression ...\")\n clf = LogisticRegression(C=1.0, max_iter=200, class_weight=\"balanced\")\n clf.fit(Xtr, y)\n print(f\"train acc: {clf.score(Xtr, y):.3f}\")\n\n print(\"scoring full pool ...\")\n scores = np.empty(len(texts), dtype=np.float32)\n B = 20000\n for s in range(0, len(texts), B):\n Xb = vec.transform(texts[s:s+B])\n scores[s:s+B] = clf.decision_function(Xb).astype(np.float32)\n print(f\" scored {min(s+B,len(texts))}/{len(texts)}\", end=\"\\r\")\n print()\n np.save(CACHE_SCORE, scores); np.save(CACHE_IDS, ids)\n\n# ---------- light quality gates ----------\nprint(\"applying quality gates ...\")\nchar_len = np.array([len(t) for t in texts])\ndef bad_ratio(t):\n if not t: return 1.0\n letters = sum(c.isalpha() or c.isspace() for c in t)\n return 1.0 - letters / len(t)\n# cheap gate: length window; drop tiny fragments and enormous outliers\ngate = (char_len >= 200) & (char_len <= 60_000)\n\n# ---------- dedup: exact + normalized-prefix signature ----------\nprint(\"dedup ...\")\ndef sig(t):\n s = re.sub(r\"\\s+\", \" \", t.strip().lower())[:200]\n return s\norder = np.argsort(-scores) # best first\nseen = set()\nsel = []\napprox_tokens = 0.0\nfor j in order:\n if not gate[j]:\n continue\n t = texts[j]\n k = sig(t)\n if k in seen:\n continue\n seen.add(k)\n sel.append(int(ids[j]))\n approx_tokens += len(t) / 4.0 # ~4 chars/token heuristic for budgeting the emit size\n if approx_tokens >= a.target_tokens:\n break\n\nos.makedirs(os.path.dirname(OUT), exist_ok=True)\njson.dump(sel, open(OUT, \"w\"))\nprint(f\"wrote {len(sel)} ids (~{approx_tokens/1e6:.1f}M est tokens) -> {OUT}\")\nprint(f\"score range kept: [{scores[order][:1][0]:.2f} .. included tail]\")\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": "\"\"\"Curate a raw web pool for small-LM pretraining by TARGET-DOMAIN classification.\n\nCriterion (stated, reproducible):\n Score every pool document by P(doc is drawn from the disclosed high-quality\n multi-domain target) using a logistic-regression domain classifier, then keep\n the highest-scoring documents (after light quality gates + dedup) in priority\n order until the training budget is filled.\n\nPositives for the classifier are the DEV target documents themselves, recovered\nby GPT-2-decoding /workspace/data/multi_dev.npy and de-normalizing the WikiText\n` @-@ `/` @,@ ` spacing artifacts so the classifier keys on register/quality\nrather than surface tokenization. Negatives are a random sample of the raw pool\n(PU-learning: most of the pool is off-target, so the LR direction separates\ntarget-like prose from generic web crawl).\n\nUsage:\n python3 curate.py # full run, writes submission/selection.json\n python3 curate.py --reuse # reuse cached texts + scores (fast policy tweaks)\n\"\"\"\nimport argparse, json, re, os, pickle, numpy as np\n\nPOOL = \"/workspace/data/pool.jsonl\"\nDEV = \"/workspace/data/multi_dev.npy\"\nOUT = \"/workspace/submission/selection.json\"\nCACHE_TXT = \"/tmp/pool_texts.pkl\"\nCACHE_SCORE = \"/tmp/pool_scores.npy\"\nCACHE_IDS = \"/tmp/pool_ids.npy\"\nEOS = 50256\n\nap = argparse.ArgumentParser()\nap.add_argument(\"--reuse\", action=\"store_true\", help=\"reuse cached texts and scores\")\nap.add_argument(\"--target_tokens\", type=int, default=20_000_000,\n help=\"how many tokens of ids to emit (>12M budget, extras unused)\")\nap.add_argument(\"--neg\", type=int, default=25_000, help=\"num pool negatives\")\na = ap.parse_args()\n\n# ---------- de-normalize WikiText-103 style spacing so positives look like raw web ----------\ndef denorm(t):\n t = t.replace(\" @-@ \", \"-\").replace(\" @,@ \", \",\").replace(\" @.@ \", \".\")\n # collapse \" , \" / \" . \" / \" ; \" spaced punctuation -> attached punctuation\n t = re.sub(r\"\\s+([,.;:!?%])\", r\"\\1\", t)\n t = re.sub(r\"\\(\\s+\", \"(\", t); t = re.sub(r\"\\s+\\)\", \")\", t)\n t = re.sub(r\"\\s+'s\\b\", \"'s\", t)\n return t\n\n# ---------- load pool texts (cache) ----------\nif a.reuse and os.path.exists(CACHE_TXT):\n print(\"loading cached pool texts...\")\n ids, texts = pickle.load(open(CACHE_TXT, \"rb\"))\nelse:\n print(\"reading pool.jsonl ...\")\n ids, texts = [], []\n with open(POOL) as f:\n for line in f:\n r = json.loads(line)\n ids.append(r[\"id\"]); texts.append(r[\"text\"])\n pickle.dump((ids, texts), open(CACHE_TXT, \"wb\"))\nids = np.array(ids)\nprint(f\"pool docs: {len(ids)}\")\n\n# ---------- build classifier + score (cache) ----------\nif a.reuse and os.path.exists(CACHE_SCORE):\n print(\"loading cached scores...\")\n scores = np.load(CACHE_SCORE)\n cids = np.load(CACHE_IDS)\n assert np.array_equal(cids, ids), \"cache id mismatch; rerun without --reuse\"\nelse:\n from transformers import AutoTokenizer\n from sklearn.feature_extraction.text import HashingVectorizer\n from sklearn.linear_model import LogisticRegression\n\n print(\"decoding dev target -> positive docs ...\")\n dev = np.load(DEV)\n cut = np.where(dev == EOS)[0]\n tok = AutoTokenizer.from_pretrained(\"gpt2\")\n pos_docs, prev = [], 0\n for c in cut:\n seg = dev[prev:c]; prev = c + 1\n if len(seg) >= 16:\n pos_docs.append(denorm(tok.decode(seg)))\n print(f\"positive (target) docs: {len(pos_docs)}\")\n\n rng = np.random.default_rng(0)\n neg_idx = rng.choice(len(texts), size=min(a.neg, len(texts)), replace=False)\n neg_docs = [texts[i] for i in neg_idx]\n\n Xtxt = pos_docs + neg_docs\n y = np.array([1] * len(pos_docs) + [0] * len(neg_docs))\n print(\"vectorizing (word 1-2 grams, hashed) ...\")\n vec = HashingVectorizer(ngram_range=(1, 2), n_features=2**20,\n alternate_sign=False, norm=\"l2\", lowercase=True)\n Xtr = vec.transform(Xtxt)\n print(\"fitting logistic regression ...\")\n clf = LogisticRegression(C=1.0, max_iter=200, class_weight=\"balanced\")\n clf.fit(Xtr, y)\n print(f\"train acc: {clf.score(Xtr, y):.3f}\")\n\n print(\"scoring full pool ...\")\n scores = np.empty(len(texts), dtype=np.float32)\n B = 20000\n for s in range(0, len(texts), B):\n Xb = vec.transform(texts[s:s+B])\n scores[s:s+B] = clf.decision_function(Xb).astype(np.float32)\n print(f\" scored {min(s+B,len(texts))}/{len(texts)}\", end=\"\\r\")\n print()\n np.save(CACHE_SCORE, scores); np.save(CACHE_IDS, ids)\n\n# ---------- light quality gates ----------\nprint(\"applying quality gates ...\")\nchar_len = np.array([len(t) for t in texts])\ndef bad_ratio(t):\n if not t: return 1.0\n letters = sum(c.isalpha() or c.isspace() for c in t)\n return 1.0 - letters / len(t)\n# cheap gate: length window; drop tiny fragments and enormous outliers\ngate = (char_len >= 200) & (char_len <= 60_000)\n\n# ---------- dedup: exact + normalized-prefix signature ----------\nprint(\"dedup ...\")\ndef sig(t):\n s = re.sub(r\"\\s+\", \" \", t.strip().lower())[:200]\n return s\norder = np.argsort(-scores) # best first\nseen = set()\nsel = []\napprox_tokens = 0.0\nfor j in order:\n if not gate[j]:\n continue\n t = texts[j]\n k = sig(t)\n if k in seen:\n continue\n seen.add(k)\n sel.append(int(ids[j]))\n approx_tokens += len(t) / 4.0 # ~4 chars/token heuristic for budgeting the emit size\n if approx_tokens >= a.target_tokens:\n break\n\nos.makedirs(os.path.dirname(OUT), exist_ok=True)\njson.dump(sel, open(OUT, \"w\"))\nprint(f\"wrote {len(sel)} ids (~{approx_tokens/1e6:.1f}M est tokens) -> {OUT}\")\nprint(f\"score range kept: [{scores[order][:1][0]:.2f} .. included tail]\")\n", "structuredPatch": [], "originalFile": null, "userModified": false}encrypted chain-of-thought — recorded, not exposed
args
{
"command": "cd /workspace; export TOKENIZERS_PARALLELISM=false; time python3 curate.py 2>&1 | tail -30; echo \"REMAIN:\"; cat .timer/remaining_secs",
"description": "Run full curation: build classifier, score, write selection"
}Bash result
reading pool.jsonl ...
pool docs: 182016
Traceback (most recent call last):
File "/workspace/curate.py", line 69, in <module>
from sklearn.feature_extraction.text import HashingVectorizer
ModuleNotFoundError: No module named 'sklearn'
real 0m16.010s
user 0m14.390s
sys 0m1.890s
REMAIN:
5190
[stdout]
reading pool.jsonl ...
pool docs: 182016
Traceback (most recent call last):
File "/workspace/curate.py", line 69, in <module>
from sklearn.feature_extraction.text import HashingVectorizer
ModuleNotFoundError: No module named 'sklearn'
real 0m16.010s
user 0m14.390s
sys 0m1.890s
REMAIN:
5190
[metadata] {"noOutputExpected": false}encrypted chain-of-thought — recorded, not exposed
args
{
"command": "cd /workspace; python3 -c \"import sklearn\" 2>&1 | head -1; pip install scikit-learn 2>&1 | tail -3; echo \"---scipy---\"; python3 -c \"import scipy; print('scipy', scipy.__version__)\" 2>&1 | head -1; python3 -c \"import numpy; print('numpy', numpy.__version__)\"",
"description": "Check sklearn/scipy availability, try install"
}Bash result
Command did not complete within its 120s timeout and was moved to the background (ID: beyqlitvg). Output is being written to: /tmp/claude-0/-workspace/ecb1feaa-77c8-46ab-b37a-9020f62d37d0/tasks/beyqlitvg.output. You will be notified when it completes. To check interim output, use Read on that file path.
Session cwd remains /workspace; directory changes made by the backgrounded command do not apply to subsequent commands.
[metadata] {"noOutputExpected": false, "backgroundTaskId": "beyqlitvg", "timedOutAfterMs": 120000, "backgroundCwdHint": "Session cwd remains /workspace; directory changes made by the backgrounded command do not apply to subsequent commands."}encrypted chain-of-thought — recorded, not exposed
args
{
"command": "kill %1 2>/dev/null; pkill -f \"pip install\" 2>/dev/null; cd /workspace; python3 -c \"import scipy; print('scipy', scipy.__version__)\" 2>&1 | head -1; python3 -c \"import torch; print('torch', torch.__version__)\"; echo \"remain:\"; cat .timer/remaining_secs",
"description": "Kill pip, check scipy and torch"
}Bash result · error
Exit code 144
[error] tool reported failureencrypted chain-of-thought — recorded, not exposed
args
{
"command": "cd /workspace; python3 -c \"import scipy; print('scipy', scipy.__version__)\" 2>&1 | head -1; python3 -c \"import torch; print('torch', torch.__version__)\" 2>&1 | head -1; echo \"remain:\"; cat .timer/remaining_secs",
"description": "Check scipy and torch availability"
}Bash result
Traceback (most recent call last):
torch 2.8.0+cu128
remain:
5049
[stdout]
Traceback (most recent call last):
torch 2.8.0+cu128
remain:
5049
[metadata] {"noOutputExpected": false}No sklearn/scipy, but I have torch + numpy on an H100. I'll implement the domain classifier as a hashing/vocab bag-of-words logistic regression in torch (deterministic vocab for reproducibility, GPU-fast). Let me rewrite the classifier section.
args
{
"file_path": "/workspace/curate.py",
"content": "\"\"\"Curate a raw web pool for small-LM pretraining by TARGET-DOMAIN classification.\n\nCriterion (stated, reproducible):\n Score every pool document by how much it looks like the disclosed high-quality\n multi-domain target, using a bag-of-words logistic-regression domain classifier\n (target vs. random pool). Keep the highest-scoring documents (after light\n quality gates + near-dup removal) in priority order until the training budget\n is filled.\n\nPositives = the DEV target docs themselves, recovered by GPT-2-decoding\n/workspace/data/multi_dev.npy and de-normalizing the WikiText ` @-@ `/` @,@ `\nspacing artifacts so the classifier keys on register/quality, not surface\ntokenization. Negatives = a random sample of the raw pool (PU learning: most of\nthe pool is off-target, so the LR direction separates target-like prose from\ngeneric web crawl).\n\nImplemented with numpy + torch only (no sklearn). Deterministic vocab -> the\nselection is fully reproducible.\n\nUsage:\n python3 curate.py # full run -> submission/selection.json\n python3 curate.py --reuse # reuse cached texts + scores (instant policy tweaks)\n\"\"\"\nimport argparse, json, re, os, pickle, numpy as np, torch\n\nPOOL = \"/workspace/data/pool.jsonl\"\nDEV = \"/workspace/data/multi_dev.npy\"\nOUT = \"/workspace/submission/selection.json\"\nCACHE_TXT = \"/tmp/pool_texts.pkl\"\nCACHE_SCORE = \"/tmp/pool_scores.npy\"\nCACHE_IDS = \"/tmp/pool_ids.npy\"\nEOS = 50256\nWORD = re.compile(r\"[a-z0-9']+\")\nMAXW = 1000 # cap words/doc for featurization (focus on main content, bound cost)\n\nap = argparse.ArgumentParser()\nap.add_argument(\"--reuse\", action=\"store_true\")\nap.add_argument(\"--target_tokens\", type=int, default=20_000_000)\nap.add_argument(\"--neg\", type=int, default=25_000)\nap.add_argument(\"--min_chars\", type=int, default=200)\nap.add_argument(\"--max_chars\", type=int, default=60_000)\na = ap.parse_args()\n\n# ---------- de-normalize WikiText-103 spacing so positives look like raw web ----------\ndef denorm(t):\n t = t.replace(\" @-@ \", \"-\").replace(\" @,@ \", \",\").replace(\" @.@ \", \".\")\n t = re.sub(r\"\\s+([,.;:!?%])\", r\"\\1\", t)\n t = re.sub(r\"\\(\\s+\", \"(\", t); t = re.sub(r\"\\s+\\)\", \")\", t)\n return t\n\n# ---------- featurization: word uni+bigrams -> column ids via vocab ----------\ndef doc_feats(t, vocab, add=False):\n ws = WORD.findall(t.lower())[:MAXW]\n cols = set()\n for w in ws:\n c = vocab.get(w)\n if c is None and add:\n c = vocab[w] = len(vocab)\n if c is not None: cols.add(c)\n for i in range(len(ws) - 1):\n bg = ws[i] + \" \" + ws[i+1]\n c = vocab.get(bg)\n if c is None and add:\n c = vocab[bg] = len(vocab)\n if c is not None: cols.add(c)\n return cols\n\ndef build_sparse(list_of_colsets, D, device):\n rows, cols = [], []\n for r, cs in enumerate(list_of_colsets):\n if not cs: continue\n rows.extend([r] * len(cs)); cols.extend(cs)\n idx = torch.tensor([rows, cols], dtype=torch.long, device=device)\n # L2-normalized binary values\n rowlen = np.bincount(np.array(rows), minlength=len(list_of_colsets)).astype(np.float32)\n rowlen[rowlen == 0] = 1.0\n vals = torch.tensor([1.0 / np.sqrt(rowlen[r]) for r in rows], dtype=torch.float32, device=device)\n return torch.sparse_coo_tensor(idx, vals, (len(list_of_colsets), D)).coalesce()\n\n# ---------- load pool texts (cache) ----------\nif a.reuse and os.path.exists(CACHE_TXT):\n print(\"loading cached pool texts...\"); ids, texts = pickle.load(open(CACHE_TXT, \"rb\"))\nelse:\n print(\"reading pool.jsonl ...\")\n ids, texts = [], []\n with open(POOL) as f:\n for line in f:\n r = json.loads(line); ids.append(r[\"id\"]); texts.append(r[\"text\"])\n pickle.dump((ids, texts), open(CACHE_TXT, \"wb\"))\nids = np.array(ids); print(f\"pool docs: {len(ids)}\")\n\n# ---------- classifier + scores (cache) ----------\nif a.reuse and os.path.exists(CACHE_SCORE):\n print(\"loading cached scores...\"); scores = np.load(CACHE_SCORE)\n assert np.array_equal(np.load(CACHE_IDS), ids)\nelse:\n dev = \"cuda\" if torch.cuda.is_available() else \"cpu\"\n print(\"decoding dev target -> positives ...\")\n from transformers import AutoTokenizer\n arr = np.load(DEV); cut = np.where(arr == EOS)[0]\n tok = AutoTokenizer.from_pretrained(\"gpt2\")\n pos_docs, prev = [], 0\n for c in cut:\n seg = arr[prev:c]; prev = c + 1\n if len(seg) >= 16: pos_docs.append(denorm(tok.decode(seg)))\n print(f\"positives: {len(pos_docs)}\")\n\n rng = np.random.default_rng(0)\n neg_idx = rng.choice(len(texts), size=min(a.neg, len(texts)), replace=False)\n neg_docs = [texts[i] for i in neg_idx]\n\n print(\"building vocab + training features ...\")\n vocab = {}\n train_txt = pos_docs + neg_docs\n y = np.array([1.0]*len(pos_docs) + [0.0]*len(neg_docs), dtype=np.float32)\n colsets = [doc_feats(t, vocab, add=True) for t in train_txt]\n D = len(vocab); print(f\"vocab size: {D}\")\n Xtr = build_sparse(colsets, D, dev)\n yt = torch.tensor(y, device=dev)\n\n print(\"training logistic regression (torch, GPU) ...\")\n w = torch.zeros(D, device=dev, requires_grad=True)\n b = torch.zeros(1, device=dev, requires_grad=True)\n opt = torch.optim.Adam([w, b], lr=0.5)\n pos_w = torch.tensor([(y == 0).sum() / max(1,(y == 1).sum())], device=dev) # balance\n for it in range(300):\n opt.zero_grad()\n logits = torch.sparse.mm(Xtr, w.unsqueeze(1)).squeeze(1) + b\n loss = torch.nn.functional.binary_cross_entropy_with_logits(\n logits, yt, pos_weight=pos_w) + 1e-4 * (w*w).sum()\n loss.backward(); opt.step()\n with torch.no_grad():\n acc = (((torch.sparse.mm(Xtr, w.unsqueeze(1)).squeeze(1)+b) > 0).float() == yt).float().mean().item()\n print(f\"train acc: {acc:.3f} final loss {loss.item():.4f}\")\n\n print(\"scoring full pool ...\")\n scores = np.empty(len(texts), dtype=np.float32)\n wv = w.detach(); bv = b.detach()\n B = 20000\n for s in range(0, len(texts), B):\n cs = [doc_feats(t, vocab, add=False) for t in texts[s:s+B]]\n Xb = build_sparse(cs, D, dev)\n with torch.no_grad():\n scores[s:s+B] = (torch.sparse.mm(Xb, wv.unsqueeze(1)).squeeze(1)+bv).cpu().numpy()\n print(f\" scored {min(s+B,len(texts))}/{len(texts)}\", end=\"\\r\")\n print()\n np.save(CACHE_SCORE, scores); np.save(CACHE_IDS, ids)\n\n# ---------- quality gates ----------\nprint(\"quality gates + dedup ...\")\nchar_len = np.array([len(t) for t in texts])\ngate = (char_len >= a.min_chars) & (char_len <= a.max_chars)\n\n# ---------- rank + near-dup removal ----------\ndef sig(t): return re.sub(r\"\\s+\", \" \", t.strip().lower())[:200]\norder = np.argsort(-scores)\nseen, sel, approx = set(), [], 0.0\nfor j in order:\n if not gate[j]: continue\n k = sig(texts[j])\n if k in seen: continue\n seen.add(k)\n sel.append(int(ids[j])); approx += len(texts[j]) / 4.0\n if approx >= a.target_tokens: break\n\nos.makedirs(os.path.dirname(OUT), exist_ok=True)\njson.dump(sel, open(OUT, \"w\"))\nprint(f\"wrote {len(sel)} ids (~{approx/1e6:.1f}M est tokens) -> {OUT}\")\n"
}Write result
The file /workspace/curate.py has been updated successfully. (file state is current in your context — no need to Read it back)
[metadata] {"type": "update", "filePath": "/workspace/curate.py", "content": "\"\"\"Curate a raw web pool for small-LM pretraining by TARGET-DOMAIN classification.\n\nCriterion (stated, reproducible):\n Score every pool document by how much it looks like the disclosed high-quality\n multi-domain target, using a bag-of-words logistic-regression domain classifier\n (target vs. random pool). Keep the highest-scoring documents (after light\n quality gates + near-dup removal) in priority order until the training budget\n is filled.\n\nPositives = the DEV target docs themselves, recovered by GPT-2-decoding\n/workspace/data/multi_dev.npy and de-normalizing the WikiText ` @-@ `/` @,@ `\nspacing artifacts so the classifier keys on register/quality, not surface\ntokenization. Negatives = a random sample of the raw pool (PU learning: most of\nthe pool is off-target, so the LR direction separates target-like prose from\ngeneric web crawl).\n\nImplemented with numpy + torch only (no sklearn). Deterministic vocab -> the\nselection is fully reproducible.\n\nUsage:\n python3 curate.py # full run -> submission/selection.json\n python3 curate.py --reuse # reuse cached texts + scores (instant policy tweaks)\n\"\"\"\nimport argparse, json, re, os, pickle, numpy as np, torch\n\nPOOL = \"/workspace/data/pool.jsonl\"\nDEV = \"/workspace/data/multi_dev.npy\"\nOUT = \"/workspace/submission/selection.json\"\nCACHE_TXT = \"/tmp/pool_texts.pkl\"\nCACHE_SCORE = \"/tmp/pool_scores.npy\"\nCACHE_IDS = \"/tmp/pool_ids.npy\"\nEOS = 50256\nWORD = re.compile(r\"[a-z0-9']+\")\nMAXW = 1000 # cap words/doc for featurization (focus on main content, bound cost)\n\nap = argparse.ArgumentParser()\nap.add_argument(\"--reuse\", action=\"store_true\")\nap.add_argument(\"--target_tokens\", type=int, default=20_000_000)\nap.add_argument(\"--neg\", type=int, default=25_000)\nap.add_argument(\"--min_chars\", type=int, default=200)\nap.add_argument(\"--max_chars\", type=int, default=60_000)\na = ap.parse_args()\n\n# ---------- de-normalize WikiText-103 spacing so positives look like raw web ----------\ndef denorm(t):\n t = t.replace(\" @-@ \", \"-\").replace(\" @,@ \", \",\").replace(\" @.@ \", \".\")\n t = re.sub(r\"\\s+([,.;:!?%])\", r\"\\1\", t)\n t = re.sub(r\"\\(\\s+\", \"(\", t); t = re.sub(r\"\\s+\\)\", \")\", t)\n return t\n\n# ---------- featurization: word uni+bigrams -> column ids via vocab ----------\ndef doc_feats(t, vocab, add=False):\n ws = WORD.findall(t.lower())[:MAXW]\n cols = set()\n for w in ws:\n c = vocab.get(w)\n if c is None and add:\n c = vocab[w] = len(vocab)\n if c is not None: cols.add(c)\n for i in range(len(ws) - 1):\n bg = ws[i] + \" \" + ws[i+1]\n c = vocab.get(bg)\n if c is None and add:\n c = vocab[bg] = len(vocab)\n if c is not None: cols.add(c)\n return cols\n\ndef build_sparse(list_of_colsets, D, device):\n rows, cols = [], []\n for r, cs in enumerate(list_of_colsets):\n if not cs: continue\n rows.extend([r] * len(cs)); cols.extend(cs)\n idx = torch.tensor([rows, cols], dtype=torch.long, device=device)\n # L2-normalized binary values\n rowlen = np.bincount(np.array(rows), minlength=len(list_of_colsets)).astype(np.float32)\n rowlen[rowlen == 0] = 1.0\n vals = torch.tensor([1.0 / np.sqrt(rowlen[r]) for r in rows], dtype=torch.float32, device=device)\n return torch.sparse_coo_tensor(idx, vals, (len(list_of_colsets), D)).coalesce()\n\n# ---------- load pool texts (cache) ----------\nif a.reuse and os.path.exists(CACHE_TXT):\n print(\"loading cached pool texts...\"); ids, texts = pickle.load(open(CACHE_TXT, \"rb\"))\nelse:\n print(\"reading pool.jsonl ...\")\n ids, texts = [], []\n with open(POOL) as f:\n for line in f:\n r = json.loads(line); ids.append(r[\"id\"]); texts.append(r[\"text\"])\n pickle.dump((ids, texts), open(CACHE_TXT, \"wb\"))\nids = np.array(ids); print(f\"pool docs: {len(ids)}\")\n\n# ---------- classifier + scores (cache) ----------\nif a.reuse and os.path.exists(CACHE_SCORE):\n print(\"loading cached scores...\"); scores = np.load(CACHE_SCORE)\n assert np.array_equal(np.load(CACHE_IDS), ids)\nelse:\n dev = \"cuda\" if torch.cuda.is_available() else \"cpu\"\n print(\"decoding dev target -> positives ...\")\n from transformers import AutoTokenizer\n arr = np.load(DEV); cut = np.where(arr == EOS)[0]\n tok = AutoTokenizer.from_pretrained(\"gpt2\")\n pos_docs, prev = [], 0\n for c in cut:\n seg = arr[prev:c]; prev = c + 1\n if len(seg) >= 16: pos_docs.append(denorm(tok.decode(seg)))\n print(f\"positives: {len(pos_docs)}\")\n\n rng = np.random.default_rng(0)\n neg_idx = rng.choice(len(texts), size=min(a.neg, len(texts)), replace=False)\n neg_docs = [texts[i] for i in neg_idx]\n\n print(\"building vocab + training features ...\")\n vocab = {}\n train_txt = pos_docs + neg_docs\n y = np.array([1.0]*len(pos_docs) + [0.0]*len(neg_docs), dtype=np.float32)\n colsets = [doc_feats(t, vocab, add=True) for t in train_txt]\n D = len(vocab); print(f\"vocab size: {D}\")\n Xtr = build_sparse(colsets, D, dev)\n yt = torch.tensor(y, device=dev)\n\n print(\"training logistic regression (torch, GPU) ...\")\n w = torch.zeros(D, device=dev, requires_grad=True)\n b = torch.zeros(1, device=dev, requires_grad=True)\n opt = torch.optim.Adam([w, b], lr=0.5)\n pos_w = torch.tensor([(y == 0).sum() / max(1,(y == 1).sum())], device=dev) # balance\n for it in range(300):\n opt.zero_grad()\n logits = torch.sparse.mm(Xtr, w.unsqueeze(1)).squeeze(1) + b\n loss = torch.nn.functional.binary_cross_entropy_with_logits(\n logits, yt, pos_weight=pos_w) + 1e-4 * (w*w).sum()\n loss.backward(); opt.step()\n with torch.no_grad():\n acc = (((torch.sparse.mm(Xtr, w.unsqueeze(1)).squeeze(1)+b) > 0).float() == yt).float().mean().item()\n print(f\"train acc: {acc:.3f} final loss {loss.item():.4f}\")\n\n print(\"scoring full pool ...\")\n scores = np.empty(len(texts), dtype=np.float32)\n wv = w.detach(); bv = b.detach()\n B = 20000\n for s in range(0, len(texts), B):\n cs = [doc_feats(t, vocab, add=False) for t in texts[s:s+B]]\n Xb = build_sparse(cs, D, dev)\n with torch.no_grad():\n scores[s:s+B] = (torch.sparse.mm(Xb, wv.unsqueeze(1)).squeeze(1)+bv).cpu().numpy()\n print(f\" scored {min(s+B,len(texts))}/{len(texts)}\", end=\"\\r\")\n print()\n np.save(CACHE_SCORE, scores); np.save(CACHE_IDS, ids)\n\n# ---------- quality gates ----------\nprint(\"quality gates + dedup ...\")\nchar_len = np.array([len(t) for t in texts])\ngate = (char_len >= a.min_chars) & (char_len <= a.max_chars)\n\n# ---------- rank + near-dup removal ----------\ndef sig(t): return re.sub(r\"\\s+\", \" \", t.strip().lower())[:200]\norder = np.argsort(-scores)\nseen, sel, approx = set(), [], 0.0\nfor j in order:\n if not gate[j]: continue\n k = sig(texts[j])\n if k in seen: continue\n seen.add(k)\n sel.append(int(ids[j])); approx += len(texts[j]) / 4.0\n if approx >= a.target_tokens: break\n\nos.makedirs(os.path.dirname(OUT), exist_ok=True)\njson.dump(sel, open(OUT, \"w\"))\nprint(f\"wrote {len(sel)} ids (~{approx/1e6:.1f}M est tokens) -> {OUT}\")\n", "structuredPatch": [{"oldStart": 1, "oldLines": 143, "newStart": 1, "newLines": 168, "lines": [" \"\"\"Curate a raw web pool for small-LM pretraining by TARGET-DOMAIN classification.", " ", " Criterion (stated, reproducible):", "- Score every pool document by P(doc is drawn from the disclosed high-quality", "- multi-domain target) using a logistic-regression domain classifier, then keep", "- the highest-scoring documents (after light quality gates + dedup) in priority", "- order until the training budget is filled.", "+ Score every pool document by how much it looks like the disclosed high-quality", "+ multi-domain target, using a bag-of-words logistic-regression domain classifier", "+ (target vs. random pool). Keep the highest-scoring documents (after light", "+ quality gates + near-dup removal) in priority order until the training budget", "+ is filled.", " ", "-Positives for the classifier are the DEV target documents themselves, recovered", "-by GPT-2-decoding /workspace/data/multi_dev.npy and de-normalizing the WikiText", "-` @-@ `/` @,@ ` spacing artifacts so the classifier keys on register/quality", "-rather than surface tokenization. Negatives are a random sample of the raw pool", "-(PU-learning: most of the pool is off-target, so the LR direction separates", "-target-like prose from generic web crawl).", "+Positives = the DEV target docs themselves, recovered by GPT-2-decoding", "+/workspace/data/multi_dev.npy and de-normalizing the WikiText ` @-@ `/` @,@ `", "+spacing artifacts so the classifier keys on register/quality, not surface", "+tokenization. Negatives = a random sample of the raw pool (PU learning: most of", "+the pool is off-target, so the LR direction separates target-like prose from", "+generic web crawl).", " ", "+Implemented with numpy + torch only (no sklearn). Deterministic vocab -> the", "+selection is fully reproducible.", "+", " Usage:", "- python3 curate.py # full run, writes submission/selection.json", "- python3 curate.py --reuse # reuse cached texts + scores (fast policy tweaks)", "+ python3 curate.py # full run -> submission/selection.json", "+ python3 curate.py --reuse # reuse cached texts + scores (instant policy tweaks)", " \"\"\"", "-import argparse, json, re, os, pickle, numpy as np", "+import argparse, json, re, os, pickle, numpy as np, torch", " ", " POOL = \"/workspace/data/pool.jsonl\"", " DEV = \"/workspace/data/multi_dev.npy\"", " OUT = \"/workspace/submission/selection.json\"", "-CACHE_TXT = \"/tmp/pool_texts.pkl\"", "+CACHE_TXT = \"/tmp/pool_texts.pkl\"", " CACHE_SCORE = \"/tmp/pool_scores.npy\"", "-CACHE_IDS = \"/tmp/pool_ids.npy\"", "+CACHE_IDS = \"/tmp/pool_ids.npy\"", " EOS = 50256", "+WORD = re.compile(r\"[a-z0-9']+\")", "+MAXW = 1000 # cap words/doc for featurization (focus on main content, bound cost)", " ", " ap = argparse.ArgumentParser()", "-ap.add_argument(\"--reuse\", action=\"store_true\", help=\"reuse cached texts and scores\")", "-ap.add_argument(\"--target_tokens\", type=int, default=20_000_000,", "- help=\"how many tokens of ids to emit (>12M budget, extras unused)\")", "-ap.add_argument(\"--neg\", type=int, default=25_000, help=\"num pool negatives\")", "+ap.add_argument(\"--reuse\", action=\"store_true\")", "+ap.add_argument(\"--target_tokens\", type=int, default=20_000_000)", "+ap.add_argument(\"--neg\", type=int, default=25_000)", "+ap.add_argument(\"--min_chars\", type=int, default=200)", "+ap.add_argument(\"--max_chars\", type=int, default=60_000)", " a = ap.parse_args()", " ", "-# ---------- de-normalize WikiText-103 style spacing so positives look like raw web ----------", "+# ---------- de-normalize WikiText-103 spacing so positives look like raw web ----------", " def denorm(t):", " t = t.replace(\" @-@ \", \"-\").replace(\" @,@ \", \",\").replace(\" @.@ \", \".\")", "- # collapse \" , \" / \" . \" / \" ; \" spaced punctuation -> attached punctuation", " t = re.sub(r\"\\s+([,.;:!?%])\", r\"\\1\", t)", " t = re.sub(r\"\\(\\s+\", \"(\", t); t = re.sub(r\"\\s+\\)\", \")\", t)", "- t = re.sub(r\"\\s+'s\\b\", \"'s\", t)", " return t", " ", "+# ---------- featurization: word uni+bigrams -> column ids via vocab ----------", "+def doc_feats(t, vocab, add=False):", "+ ws = WORD.findall(t.lower())[:MAXW]", "+ cols = set()", "+ for w in ws:", "+ c = vocab.get(w)", "+ if c is None and add:", "+ c = vocab[w] = len(vocab)", "+ if c is not None: cols.add(c)", "+ for i in range(len(ws) - 1):", "+ bg = ws[i] + \" \" + ws[i+1]", "+ c = vocab.get(bg)", "+ if c is None and add:", "+ c = vocab[bg] = len(vocab)", "+ if c is not None: cols.add(c)", "+ return cols", "+", "+def build_sparse(list_of_colsets, D, device):", "+ rows, cols = [], []", "+ for r, cs in enumerate(list_of_colsets):", "+ if not cs: continue", "+ rows.extend([r] * len(cs)); cols.extend(cs)", "+ idx = torch.tensor([rows, cols], dtype=torch.long, device=device)", "+ # L2-normalized binary values", "+ rowlen = np.bincount(np.array(rows), minlength=len(list_of_colsets)).astype(np.float32)", "+ rowlen[rowlen == 0] = 1.0", "+ vals = torch.tensor([1.0 / np.sqrt(rowlen[r]) for r in rows], dtype=torch.float32, device=device)", "+ return torch.sparse_coo_tensor(idx, vals, (len(list_of_colsets), D)).coalesce()", "+", " # ---------- load pool texts (cache) ----------", " if a.reuse and os.path.exists(CACHE_TXT):", "- print(\"loading cached pool texts...\")", "- ids, texts = pickle.load(open(CACHE_TXT, \"rb\"))", "+ print(\"loading cached pool texts...\"); ids, texts = pickle.load(open(CACHE_TXT, \"rb\"))", " else:", " print(\"reading pool.jsonl ...\")", " ids, texts = [], []", " with open(POOL) as f:", " for line in f:", "- r = json.loads(line)", "- ids.append(r[\"id\"]); texts.append(r[\"text\"])", "+ r = json.loads(line); ids.append(r[\"id\"]); texts.append(r[\"text\"])", " pickle.dump((ids, texts), open(CACHE_TXT, \"wb\"))", "-ids = np.array(ids)", "-print(f\"pool docs: {len(ids)}\")", "+ids = np.array(ids); print(f\"pool docs: {len(ids)}\")", " ", "-# ---------- build classifier + score (cache) ----------", "+# ---------- classifier + scores (cache) ----------", " if a.reuse and os.path.exists(CACHE_SCORE):", "- print(\"loading cached scores...\")", "- scores = np.load(CACHE_SCORE)", "- cids = np.load(CACHE_IDS)", "- assert np.array_equal(cids, ids), \"cache id mismatch; rerun without --reuse\"", "+ print(\"loading cached scores...\"); scores = np.load(CACHE_SCORE)", "+ assert np.array_equal(np.load(CACHE_IDS), ids)", " else:", "+ dev = \"cuda\" if torch.cuda.is_available() else \"cpu\"", "+ print(\"decoding dev target -> positives ...\")", " from transformers import AutoTokenizer", "- from sklearn.feature_extraction.text import HashingVectorizer", "- from sklearn.linear_model import LogisticRegression", "-", "- print(\"decoding dev target -> positive docs ...\")", "- dev = np.load(DEV)", "- cut = np.where(dev == EOS)[0]", "+ arr = np.load(DEV); cut = np.where(arr == EOS)[0]", " tok = AutoTokenizer.from_pretrained(\"gpt2\")", " pos_docs, prev = [], 0", " for c in cut:", "- seg = dev[prev:c]; prev = c + 1", "- if len(seg) >= 16:", "- pos_docs.append(denorm(tok.decode(seg)))", "- print(f\"positive (target) docs: {len(pos_docs)}\")", "+ seg = arr[prev:c]; prev = c + 1", "+ if len(seg) >= 16: pos_docs.append(denorm(tok.decode(seg)))", "+ print(f\"positives: {len(pos_docs)}\")", " ", " rng = np.random.default_rng(0)", " neg_idx = rng.choice(len(texts), size=min(a.neg, len(texts)), replace=False)", " neg_docs = [texts[i] for i in neg_idx]", " ", "- Xtxt = pos_docs + neg_docs", "- y = np.array([1] * len(pos_docs) + [0] * len(neg_docs))", "- print(\"vectorizing (word 1-2 grams, hashed) ...\")", "- vec = HashingVectorizer(ngram_range=(1, 2), n_features=2**20,", "- alternate_sign=False, norm=\"l2\", lowercase=True)", "- Xtr = vec.transform(Xtxt)", "- print(\"fitting logistic regression ...\")", "- clf = LogisticRegression(C=1.0, max_iter=200, class_weight=\"balanced\")", "- clf.fit(Xtr, y)", "- print(f\"train acc: {clf.score(Xtr, y):.3f}\")", "+ print(\"building vocab + training features ...\")", "+ vocab = {}", "+ train_txt = pos_docs + neg_docs", "+ y = np.array([1.0]*len(pos_docs) + [0.0]*len(neg_docs), dtype=np.float32)", "+ colsets = [doc_feats(t, vocab, add=True) for t in train_txt]", "+ D = len(vocab); print(f\"vocab size: {D}\")", "+ Xtr = build_sparse(colsets, D, dev)", "+ yt = torch.tensor(y, device=dev)", " ", "+ print(\"training logistic regression (torch, GPU) ...\")", "+ w = torch.zeros(D, device=dev, requires_grad=True)", "+ b = torch.zeros(1, device=dev, requires_grad=True)", "+ opt = torch.optim.Adam([w, b], lr=0.5)", "+ pos_w = torch.tensor([(y == 0).sum() / max(1,(y == 1).sum())], device=dev) # balance", "+ for it in range(300):", "+ opt.zero_grad()", "+ logits = torch.sparse.mm(Xtr, w.unsqueeze(1)).squeeze(1) + b", "+ loss = torch.nn.functional.binary_cross_entropy_with_logits(", "+ logits, yt, pos_weight=pos_w) + 1e-4 * (w*w).sum()", "+ loss.backward(); opt.step()", "+ with torch.no_grad():", "+ acc = (((torch.sparse.mm(Xtr, w.unsqueeze(1)).squeeze(1)+b) > 0).float() == yt).float().mean().item()", "+ print(f\"train acc: {acc:.3f} final loss {loss.item():.4f}\")", "+", " print(\"scoring full pool ...\")", " scores = np.empty(len(texts), dtype=np.float32)", "+ wv = w.detach(); bv = b.detach()", " B = 20000", " for s in range(0, len(texts), B):", "- Xb = vec.transform(texts[s:s+B])", "- scores[s:s+B] = clf.decision_function(Xb).astype(np.float32)", "+ cs = [doc_feats(t, vocab, add=False) for t in texts[s:s+B]]", "+ Xb = build_sparse(cs, D, dev)", "+ with torch.no_grad():", "+ scores[s:s+B] = (torch.sparse.mm(Xb, wv.unsqueeze(1)).squeeze(1)+bv).cpu().numpy()", " print(f\" scored {min(s+B,len(texts))}/{len(texts)}\", end=\"\\r\")", " print()", " np.save(CACHE_SCORE, scores); np.save(CACHE_IDS, ids)", " ", "-# ---------- light quality gates ----------", "-print(\"applying quality gates ...\")", "+# ---------- quality gates ----------", "+print(\"quality gates + dedup ...\")", " char_len = np.array([len(t) for t in texts])", "-def bad_ratio(t):", "- if not t: return 1.0", "- letters = sum(c.isalpha() or c.isspace() for c in t)", "- return 1.0 - letters / len(t)", "-# cheap gate: length window; drop tiny fragments and enormous outliers", "-gate = (char_len >= 200) & (char_len <= 60_000)", "+gate = (char_len >= a.min_chars) & (char_len <= a.max_chars)", " ", "-# ---------- dedup: exact + normalized-prefix signature ----------", "-print(\"dedup ...\")", "-def sig(t):", "- s = re.sub(r\"\\s+\", \" \", t.strip().lower())[:200]", "- return s", "-order = np.argsort(-scores) # best first", "-seen = set()", "-sel = []", "-approx_tokens = 0.0", "+# ---------- rank + near-dup removal ----------", "+def sig(t): return re.sub(r\"\\s+\", \" \", t.strip().lower())[:200]", "+order = np.argsort(-scores)", "+seen, sel, approx = set(), [], 0.0", " for j in order:", "- if not gate[j]:", "- continue", "- t = texts[j]", "- k = sig(t)", "- if k in seen:", "- continue", "+ if not gate[j]: continue", "+ k = sig(texts[j])", "+ if k in seen: continue", " seen.add(k)", "- sel.append(int(ids[j]))", "- approx_tokens += len(t) / 4.0 # ~4 chars/token heuristic for budgeting the emit size", "- if approx_tokens >= a.target_tokens:", "- break", "+ sel.append(int(ids[j])); approx += len(texts[j]) / 4.0", "+ if approx >= a.target_tokens: break", " ", " os.makedirs(os.path.dirname(OUT), exist_ok=True)", " json.dump(sel, open(OUT, \"w\"))", "-print(f\"wrote {len(sel)} ids (~{approx_tokens/1e6:.1f}M est tokens) -> {OUT}\")", "-print(f\"score range kept: [{scores[order][:1][0]:.2f} .. included tail]\")", "+print(f\"wrote {len(sel)} ids (~{approx/1e6:.1f}M est tokens) -> {OUT}\")"]}], "originalFile": "\"\"\"Curate a raw web pool for small-LM pretraining by TARGET-DOMAIN classification.\n\nCriterion (stated, reproducible):\n Score every pool document by P(doc is drawn from the disclosed high-quality\n multi-domain target) using a logistic-regression domain classifier, then keep\n the highest-scoring documents (after light quality gates + dedup) in priority\n order until the training budget is filled.\n\nPositives for the classifier are the DEV target documents themselves, recovered\nby GPT-2-decoding /workspace/data/multi_dev.npy and de-normalizing the WikiText\n` @-@ `/` @,@ ` spacing artifacts so the classifier keys on register/quality\nrather than surface tokenization. Negatives are a random sample of the raw pool\n(PU-learning: most of the pool is off-target, so the LR direction separates\ntarget-like prose from generic web crawl).\n\nUsage:\n python3 curate.py # full run, writes submission/selection.json\n python3 curate.py --reuse # reuse cached texts + scores (fast policy tweaks)\n\"\"\"\nimport argparse, json, re, os, pickle, numpy as np\n\nPOOL = \"/workspace/data/pool.jsonl\"\nDEV = \"/workspace/data/multi_dev.npy\"\nOUT = \"/workspace/submission/selection.json\"\nCACHE_TXT = \"/tmp/pool_texts.pkl\"\nCACHE_SCORE = \"/tmp/pool_scores.npy\"\nCACHE_IDS = \"/tmp/pool_ids.npy\"\nEOS = 50256\n\nap = argparse.ArgumentParser()\nap.add_argument(\"--reuse\", action=\"store_true\", help=\"reuse cached texts and scores\")\nap.add_argument(\"--target_tokens\", type=int, default=20_000_000,\n help=\"how many tokens of ids to emit (>12M budget, extras unused)\")\nap.add_argument(\"--neg\", type=int, default=25_000, help=\"num pool negatives\")\na = ap.parse_args()\n\n# ---------- de-normalize WikiText-103 style spacing so positives look like raw web ----------\ndef denorm(t):\n t = t.replace(\" @-@ \", \"-\").replace(\" @,@ \", \",\").replace(\" @.@ \", \".\")\n # collapse \" , \" / \" . \" / \" ; \" spaced punctuation -> attached punctuation\n t = re.sub(r\"\\s+([,.;:!?%])\", r\"\\1\", t)\n t = re.sub(r\"\\(\\s+\", \"(\", t); t = re.sub(r\"\\s+\\)\", \")\", t)\n t = re.sub(r\"\\s+'s\\b\", \"'s\", t)\n return t\n\n# ---------- load pool texts (cache) ----------\nif a.reuse and os.path.exists(CACHE_TXT):\n print(\"loading cached pool texts...\")\n ids, texts = pickle.load(open(CACHE_TXT, \"rb\"))\nelse:\n print(\"reading pool.jsonl ...\")\n ids, texts = [], []\n with open(POOL) as f:\n for line in f:\n r = json.loads(line)\n ids.append(r[\"id\"]); texts.append(r[\"text\"])\n pickle.dump((ids, texts), open(CACHE_TXT, \"wb\"))\nids = np.array(ids)\nprint(f\"pool docs: {len(ids)}\")\n\n# ---------- build classifier + score (cache) ----------\nif a.reuse and os.path.exists(CACHE_SCORE):\n print(\"loading cached scores...\")\n scores = np.load(CACHE_SCORE)\n cids = np.load(CACHE_IDS)\n assert np.array_equal(cids, ids), \"cache id mismatch; rerun without --reuse\"\nelse:\n from transformers import AutoTokenizer\n from sklearn.feature_extraction.text import HashingVectorizer\n from sklearn.linear_model import LogisticRegression\n\n print(\"decoding dev target -> positive docs ...\")\n dev = np.load(DEV)\n cut = np.where(dev == EOS)[0]\n tok = AutoTokenizer.from_pretrained(\"gpt2\")\n pos_docs, prev = [], 0\n for c in cut:\n seg = dev[prev:c]; prev = c + 1\n if len(seg) >= 16:\n pos_docs.append(denorm(tok.decode(seg)))\n print(f\"positive (target) docs: {len(pos_docs)}\")\n\n rng = np.random.default_rng(0)\n neg_idx = rng.choice(len(texts), size=min(a.neg, len(texts)), replace=False)\n neg_docs = [texts[i] for i in neg_idx]\n\n Xtxt = pos_docs + neg_docs\n y = np.array([1] * len(pos_docs) + [0] * len(neg_docs))\n print(\"vectorizing (word 1-2 grams, hashed) ...\")\n vec = HashingVectorizer(ngram_range=(1, 2), n_features=2**20,\n alternate_sign=False, norm=\"l2\", lowercase=True)\n Xtr = vec.transform(Xtxt)\n print(\"fitting logistic regression ...\")\n clf = LogisticRegression(C=1.0, max_iter=200, class_weight=\"balanced\")\n clf.fit(Xtr, y)\n print(f\"train acc: {clf.score(Xtr, y):.3f}\")\n\n print(\"scoring full pool ...\")\n scores = np.empty(len(texts), dtype=np.float32)\n B = 20000\n for s in range(0, len(texts), B):\n Xb = vec.transform(texts[s:s+B])\n scores[s:s+B] = clf.decision_function(Xb).astype(np.float32)\n print(f\" scored {min(s+B,len(texts))}/{len(texts)}\", end=\"\\r\")\n print()\n np.save(CACHE_SCORE, scores); np.save(CACHE_IDS, ids)\n\n# ---------- light quality gates ----------\nprint(\"applying quality gates ...\")\nchar_len = np.array([len(t) for t in texts])\ndef bad_ratio(t):\n if not t: return 1.0\n letters = sum(c.isalpha() or c.isspace() for c in t)\n return 1.0 - letters / len(t)\n# cheap gate: length window; drop tiny fragments and enormous outliers\ngate = (char_len >= 200) & (char_len <= 60_000)\n\n# ---------- dedup: exact + normalized-prefix signature ----------\nprint(\"dedup ...\")\ndef sig(t):\n s = re.sub(r\"\\s+\", \" \", t.strip().lower())[:200]\n return s\norder = np.argsort(-scores) # best first\nseen = set()\nsel = []\napprox_tokens = 0.0\nfor j in order:\n if not gate[j]:\n continue\n t = texts[j]\n k = sig(t)\n if k in seen:\n continue\n seen.add(k)\n sel.append(int(ids[j]))\n approx_tokens += len(t) / 4.0 # ~4 chars/token heuristic for budgeting the emit size\n if approx_tokens >= a.target_tokens:\n break\n\nos.makedirs(os.path.dirname(OUT), exist_ok=True)\njson.dump(sel, open(OUT, \"w\"))\nprint(f\"wrote {len(sel)} ids (~{approx_tokens/1e6:.1f}M est tokens) -> {OUT}\")\nprint(f\"score range kept: [{scores[order][:1][0]:.2f} .. included tail]\")\n", "userModified": false}encrypted chain-of-thought — recorded, not exposed
args
{
"command": "cd /workspace; export TOKENIZERS_PARALLELISM=false; time python3 curate.py 2>&1 | tail -25; echo \"REMAIN:\"; cat .timer/remaining_secs",
"description": "Run curation pipeline with torch classifier"
}Bash result
Command did not complete within its 120s timeout and was moved to the background (ID: bgsbw7h73). Output is being written to: /tmp/claude-0/-workspace/ecb1feaa-77c8-46ab-b37a-9020f62d37d0/tasks/bgsbw7h73.output. You will be notified when it completes. To check interim output, use Read on that file path.
Session cwd remains /workspace; directory changes made by the backgrounded command do not apply to subsequent commands.
[metadata] {"noOutputExpected": false, "backgroundTaskId": "bgsbw7h73", "timedOutAfterMs": 120000, "backgroundCwdHint": "Session cwd remains /workspace; directory changes made by the backgrounded command do not apply to subsequent commands."}encrypted chain-of-thought — recorded, not exposed
args
{
"command": "sleep 45; cat /tmp/claude-0/-workspace/ecb1feaa-77c8-46ab-b37a-9020f62d37d0/tasks/bgsbw7h73.output 2>/dev/null | tail -25; echo \"REMAIN:\"; cat /workspace/.timer/remaining_secs",
"description": "Check curation progress"
}Bash result
REMAIN:
4809
[stdout]
REMAIN:
4809
[metadata] {"noOutputExpected": false}encrypted chain-of-thought — recorded, not exposed
args
{
"command": "sleep 60; cat /tmp/claude-0/-workspace/ecb1feaa-77c8-46ab-b37a-9020f62d37d0/tasks/bgsbw7h73.output 2>/dev/null | tail -25; echo \"REMAIN:\"; cat /workspace/.timer/remaining_secs",
"description": "Check curation progress again"
}Bash result
REMAIN:
4739
[stdout]
REMAIN:
4739
[metadata] {"noOutputExpected": false}The piped tail buffers until completion — let me check progress via the output file and process state directly.
args
{
"command": "cd /workspace; ls -la submission/ /tmp/pool_scores.npy /tmp/pool_texts.pkl 2>/dev/null; echo \"--- python procs ---\"; ps aux | grep -c \"[c]urate.py\"; echo \"--- gpu ---\"; nvidia-smi --query-gpu=utilization.gpu,memory.used --format=csv,noheader; echo \"REMAIN:\"; cat .timer/remaining_secs",
"description": "Check output files, process, GPU"
}Bash result
-rw-r--r-- 1 root root 779347812 Aug 4 03:30 /tmp/pool_texts.pkl
submission/:
total 1
drwxr-xr-x 1 root root 10 Aug 3 22:37 .
drwxr-xr-x 1 root root 160 Aug 4 03:29 ..
--- python procs ---
5
--- gpu ---
0 %, 2065 MiB
REMAIN:
4729
[stdout]
-rw-r--r-- 1 root root 779347812 Aug 4 03:30 /tmp/pool_texts.pkl
submission/:
total 1
drwxr-xr-x 1 root root 10 Aug 3 22:37 .
drwxr-xr-x 1 root root 160 Aug 4 03:29 ..
--- python procs ---
5
--- gpu ---
0 %, 2065 MiB
REMAIN:
4729
[metadata] {"noOutputExpected": false}encrypted chain-of-thought — recorded, not exposed
args
{
"command": "sleep 75; cd /workspace; ls -la /tmp/pool_scores.npy submission/selection.json 2>/dev/null; echo \"--- procs ---\"; ps aux | grep -c \"[c]urate.py\"; echo \"REMAIN:\"; cat .timer/remaining_secs",
"description": "Wait and check for scores/selection output"
}Bash result
-rw-r--r-- 1 root root 728192 Aug 4 03:35 /tmp/pool_scores.npy
-rw-r--r-- 1 root root 217896 Aug 4 03:35 submission/selection.json
--- procs ---
3
REMAIN:
4649
[stdout]
-rw-r--r-- 1 root root 728192 Aug 4 03:35 /tmp/pool_scores.npy
-rw-r--r-- 1 root root 217896 Aug 4 03:35 submission/selection.json
--- procs ---
3
REMAIN:
4649
[metadata] {"noOutputExpected": false}encrypted chain-of-thought — recorded, not exposed
args
{
"command": "cat /tmp/claude-0/-workspace/ecb1feaa-77c8-46ab-b37a-9020f62d37d0/tasks/bgsbw7h73.output 2>/dev/null | tail -25",
"description": "Read full curation output"
}Bash result
reading pool.jsonl ...
pool docs: 182016
decoding dev target -> positives ...
positives: 2704
building vocab + training features ...
vocab size: 4182559
training logistic regression (torch, GPU) ...
train acc: 0.950 final loss 0.5254
scoring full pool ...
scored 20000/182016
scored 40000/182016
scored 60000/182016
scored 80000/182016
scored 100000/182016
scored 120000/182016
scored 140000/182016
scored 160000/182016
scored 180000/182016
scored 182016/182016
quality gates + dedup ...
wrote 31358 ids (~20.0M est tokens) -> /workspace/submission/selection.json
real 5m16.764s
user 4m55.140s
sys 0m3.610s
REMAIN:
4659
[stdout]
reading pool.jsonl ...
pool docs: 182016
decoding dev target -> positives ...
positives: 2704
building vocab + training features ...
vocab size: 4182559
training logistic regression (torch, GPU) ...
train acc: 0.950 final loss 0.5254
scoring full pool ...
scored 20000/182016
scored 40000/182016
scored 60000/182016
scored 80000/182016
scored 100000/182016
scored 120000/182016
scored 140000/182016
scored 160000/182016
scored 180000/182016
scored 182016/182016
quality gates + dedup ...
wrote 31358 ids (~20.0M est tokens) -> /workspace/submission/selection.json
real 5m16.764s
user 4m55.140s
sys 0m3.610s
REMAIN:
4659
[metadata] {"noOutputExpected": false}Pipeline works: classifier train acc 0.95, scored all 182k docs, wrote 31k ids (~20M tokens). Let me sanity-check what got ranked high vs low, then run evals.
args
{
"command": "cd /workspace; python3 -c \"\nimport numpy as np, pickle, json\nids, texts = pickle.load(open('/tmp/pool_texts.pkl','rb'))\nids=np.array(ids); scores=np.load('/tmp/pool_scores.npy')\norder=np.argsort(-scores)\nprint('score stats: min %.2f p10 %.2f median %.2f p90 %.2f max %.2f'%(\n scores.min(), np.percentile(scores,10), np.median(scores), np.percentile(scores,90), scores.max()))\nprint()\nprint('===== TOP 4 =====')\nfor j in order[:4]:\n print('score %.2f id %d chars %d'%(scores[j], ids[j], len(texts[j])))\n print(repr(texts[j][:350])); print()\nprint('===== BOTTOM 3 =====')\nfor j in order[-3:]:\n print('score %.2f id %d'%(scores[j], ids[j]))\n print(repr(texts[j][:250])); print()\nprint('===== MEDIAN 2 =====')\nmid=len(order)//2\nfor j in order[mid:mid+2]:\n print('score %.2f'%scores[j]); print(repr(texts[j][:250])); print()\n\"",
"description": "Inspect top/bottom/median scored docs"
}Bash result
score stats: min -17.02 p10 -4.04 median -2.22 p90 -0.40 max 3.43
===== TOP 4 =====
score 3.43 id 5347 chars 388
"Aonb sentence example\n- Each AONB has been designated for special attention by reason of their high qualities.\n- The AONB's headlands and hilltops show many traces of prehistoric settlement.\n- It was not progressed because it was considered too unsightly in a conservation area and in the AONB.\n- The AONB 's headlands and hilltops show many traces o"
score 3.05 id 76107 chars 903
'Major Bhupinder Singh\nIn sept. 1965, Major Bhupinder Singh commanded the "B" squadron of the 4 Horse against Pakistani forces. On the 11th Sept. he successfully led his forces in cutting of the enemy retreat along the Gadgor-Phillora road. In the battle of Sadoke that folowed, Major took over the command of the regiment after the commander was forc'
score 2.87 id 8524 chars 1281
'GAZA STRIP, Palestinian territories - A Hamas commander trying to stop two youths from approaching the border fence in the northern Gaza strip was shot dead by the Israeli army on Thursday.\nAccording to The Jerusalem Post the Israeli army has confirmed the death occurred, but says it was a misunderstanding.\nThe death of Hamas operative Mahmoud Ahma'
score 2.84 id 3196 chars 2140
'DMK chief MK Stalin on Sunday hit out at the Election Commission for not announcing by-elections to two Tamil Nadu assembly constituencies citing monsoon as the reason and said it was not a ‘justifiable’ decision.\nExpressing ‘surprise’ at the Election Commission’s decision, he said by-elections had been held in the state in the past during the Nort'
===== BOTTOM 3 =====
score -17.02 id 142235
'<|endoftext|>Koncept'
score -17.02 id 119579
'<|endoftext|>Koncept'
score -17.02 id 125244
'<|endoftext|>EmpireMods'
===== MEDIAN 2 =====
score -2.22
" in VA? - Car Forums and Automotive Chat\nAutomotive Forums .com Car Chat > Engineering/Technical > Swapping in VA?\nSwapping in VA?\nsossy\n04-29-2003, 08:56 AM\nDoes anybody know if its legal to swap in an H22 in an accord in VA? I don't want to do it i"
score -2.22
' Novel Updates\nNovel Updates\nRegisterLogin\nLogin\nRegister\nForum\nGroup News\nNovels Listing\nRandom Novel\nSeries Finder\nSeries Ranking\nLatest Series\nIsekai Ryouridou\nHome >\nNovel >\nIsekai Ryouridou\nAdvertisement\nType\nWeb Novel (JP)\nGenre\nAction Adventur'
[stdout]
score stats: min -17.02 p10 -4.04 median -2.22 p90 -0.40 max 3.43
===== TOP 4 =====
score 3.43 id 5347 chars 388
"Aonb sentence example\n- Each AONB has been designated for special attention by reason of their high qualities.\n- The AONB's headlands and hilltops show many traces of prehistoric settlement.\n- It was not progressed because it was considered too unsightly in a conservation area and in the AONB.\n- The AONB 's headlands and hilltops show many traces o"
score 3.05 id 76107 chars 903
'Major Bhupinder Singh\nIn sept. 1965, Major Bhupinder Singh commanded the "B" squadron of the 4 Horse against Pakistani forces. On the 11th Sept. he successfully led his forces in cutting of the enemy retreat along the Gadgor-Phillora road. In the battle of Sadoke that folowed, Major took over the command of the regiment after the commander was forc'
score 2.87 id 8524 chars 1281
'GAZA STRIP, Palestinian territories - A Hamas commander trying to stop two youths from approaching the border fence in the northern Gaza strip was shot dead by the Israeli army on Thursday.\nAccording to The Jerusalem Post the Israeli army has confirmed the death occurred, but says it was a misunderstanding.\nThe death of Hamas operative Mahmoud Ahma'
score 2.84 id 3196 chars 2140
'DMK chief MK Stalin on Sunday hit out at the Election Commission for not announcing by-elections to two Tamil Nadu assembly constituencies citing monsoon as the reason and said it was not a ‘justifiable’ decision.\nExpressing ‘surprise’ at the Election Commission’s decision, he said by-elections had been held in the state in the past during the Nort'
===== BOTTOM 3 =====
score -17.02 id 142235
'<|endoftext|>Koncept'
score -17.02 id 119579
'<|endoftext|>Koncept'
score -17.02 id 125244
'<|endoftext|>EmpireMods'
===== MEDIAN 2 =====
score -2.22
" in VA? - Car Forums and Automotive Chat\nAutomotive Forums .com Car Chat > Engineering/Technical > Swapping in VA?\nSwapping in VA?\nsossy\n04-29-2003, 08:56 AM\nDoes anybody know if its legal to swap in an H22 in an accord in VA? I don't want to do it i"
score -2.22
' Novel Updates\nNovel Updates\nRegisterLogin\nLogin\nRegister\nForum\nGroup News\nNovels Listing\nRandom Novel\nSeries Finder\nSeries Ranking\nLatest Series\nIsekai Ryouridou\nHome >\nNovel >\nIsekai Ryouridou\nAdvertisement\nType\nWeb Novel (JP)\nGenre\nAction Adventur'
[metadata] {"noOutputExpected": false}Excellent — the classifier is working well: top = clean encyclopedic/news prose, bottom = literal <|endoftext|>Koncept garbage, median = forum/site boilerplate. Now let me get ground-truth numbers: eval my selection vs a random baseline.
args
{
"command": "cd /workspace; python3 -c \"\nimport json, numpy as np, pickle\nids, texts = pickle.load(open('/tmp/pool_texts.pkl','rb'))\nids=np.array(ids)\nrng=np.random.default_rng(1337)\npick=rng.choice(len(ids), size=25000, replace=False)\njson.dump([int(ids[i]) for i in pick], open('/tmp/random_sel.json','w'))\nprint('random baseline selection: 25000 ids')\n\"; echo \"REMAIN:\"; cat .timer/remaining_secs",
"description": "Create random baseline selection"
}Bash result
random baseline selection: 25000 ids
REMAIN:
4609
[stdout]
random baseline selection: 25000 ids
REMAIN:
4609
[metadata] {"noOutputExpected": false}encrypted chain-of-thought — recorded, not exposed
args
{
"command": "cd /workspace; export TOKENIZERS_PARALLELISM=false\necho \"===== EVAL: classifier selection =====\"; time bash dev_eval.sh /workspace/submission/selection.json 2>&1 | grep -E \"HELDOUT_PPL|packed\"\necho \"REMAIN:\"; cat .timer/remaining_secs",
"description": "Eval classifier selection on dev"
}Bash result
===== EVAL: classifier selection =====
packed 12000000 tokens from 31358 ids -> /tmp/dev_train.npy
HELDOUT_PPL 361.611 loss 5.8906 train_s 56 /tmp/dev_train.npy
real 1m43.105s
user 1m37.210s
sys 0m3.110s
REMAIN:
4499
[stdout]
===== EVAL: classifier selection =====
packed 12000000 tokens from 31358 ids -> /tmp/dev_train.npy
HELDOUT_PPL 361.611 loss 5.8906 train_s 56 /tmp/dev_train.npy
real 1m43.105s
user 1m37.210s
sys 0m3.110s
REMAIN:
4499
[metadata] {"noOutputExpected": false}