gpt-5.6-sol
on-policy-self-distillation — graded by the task's verifier against a measured baseline.
- backend
- modal
- variant
- codex azure_ai/gpt-5.6-sol
- metric
- AIME24 avg@12 accuracy
- actions
- 428
- duration
- 9h 21m
- recorded
- 2026-08-02
run idopsd-aime24-4gpus__eNDoWrD
Everything gpt-5.6-sol did on this task, in order.
download JSON ↗encrypted chain-of-thought — recorded, not exposed
args
{
"cell_id": "117",
"yield_time_ms": 60000,
"max_tokens": 80
}wait result
Script running with cell ID 117
Wall time 61.0 seconds
Output:
encrypted chain-of-thought — recorded, not exposed
args
{
"cell_id": "117",
"yield_time_ms": 60000,
"max_tokens": 80
}wait result
Script running with cell ID 117
Wall time 61.0 seconds
Output:
encrypted chain-of-thought — recorded, not exposed
args
{
"cell_id": "117",
"yield_time_ms": 60000,
"max_tokens": 80
}wait result
Script running with cell ID 117
Wall time 61.0 seconds
Output:
encrypted chain-of-thought — recorded, not exposed
args
{
"cell_id": "117",
"yield_time_ms": 60000,
"max_tokens": 80
}wait result
Script running with cell ID 117
Wall time 61.0 seconds
Output:
encrypted chain-of-thought — recorded, not exposed
args
{
"cell_id": "117",
"yield_time_ms": 60000,
"max_tokens": 80
}wait result
Script running with cell ID 117
Wall time 61.0 seconds
Output:
encrypted chain-of-thought — recorded, not exposed
args
{
"cell_id": "117",
"yield_time_ms": 60000,
"max_tokens": 80
}wait result
Script running with cell ID 117
Wall time 61.0 seconds
Output:
encrypted chain-of-thought — recorded, not exposed
args
{
"cell_id": "117",
"yield_time_ms": 60000,
"max_tokens": 80
}wait result
Script running with cell ID 117
Wall time 61.0 seconds
Output:
encrypted chain-of-thought — recorded, not exposed
args
{
"cell_id": "117",
"yield_time_ms": 60000,
"max_tokens": 80
}wait result
Script running with cell ID 117
Wall time 61.0 seconds
Output:
encrypted chain-of-thought — recorded, not exposed
args
{
"cell_id": "117",
"yield_time_ms": 60000,
"max_tokens": 80
}wait result
Script completed
Wall time 28.8 seconds
Output:
Warning: truncated output (original token count: 226)
Total output lines: 21
| 0/96 [00:00<?, ?it/s, est. speed input: 0.00 toks/s, output: 0.00 toks/s]
[03:22<08:29, 7.08s/it, est. speed input: 19.11 toks/s, output: 862.73 toks…146 tokens truncated…<05:56, 9.91s/it, est. speed input: 8.49 toks/s, output: 1318.83 toks/s]
0 problems)
Results written to /workspace/eval_results/dev_eval_1785711242.json
EXIT0encrypted chain-of-thought — recorded, not exposed
args
{
"input": "const r = await tools.exec_command({cmd:\"python - <<'PY'\\nimport json\\nf='/workspace/eval_results/dev_eval_1785711242.json';d=json.load(open(f));print(d['average_at_n_pct'],sum(x['num_correct'] for x in d['results']));print([(x['problem_id'],x['num_correct']) for x in d['results']])\\nPY\\ncat /workspace/.timer/remaining_secs\",\"workdir\":\"/workspace\",\"yield_time_ms\":10000,\"max_output_tokens\":3000});\ntext(r.output);"
}exec result
Script completed
Wall time 0.1 seconds
Output:
57.22222222222222 206
[(60, 12), (61, 12), (62, 0), (63, 0), (64, 5), (65, 5), (66, 11), (67, 12), (68, 11), (69, 11), (70, 7), (71, 12), (72, 12), (73, 0), (74, 8), (75, 8), (76, 9), (77, 2), (78, 5), (79, 12), (80, 3), (81, 0), (82, 8), (83, 12), (84, 12), (85, 0), (86, 11), (87, 6), (88, 0), (89, 0)]
4597
The repeat confirms the signal: 57.22% (206/360). Across the two independent same-seed retrains, the curriculum averages 56.39%, about +2.17 over the 54.22 baseline anchor. I’m locking this candidate and cleaning out the disabled experimental branches so the submitted method is only the validated reasoning-effort curriculum with the released OPSD loss and linear schedule.
encrypted chain-of-thought — recorded, not exposed
args
{
"input": "const r = await tools.exec_command({cmd:\"git diff -- opsd_train.py opsd_trainer.py data_collator.py /workspace/submission/recipe.env | sed -n '1,500p'\",\"workdir\":\"/workspace/repo\",\"yield_time_ms\":10000,\"max_output_tokens\":30000});\ntext(r.output);"
}exec result
Script completed
Wall time 0.1 seconds
Output:
fatal: /workspace/submission/recipe.env: '/workspace/submission/recipe.env' is outside repository at '/workspace/repo'
encrypted chain-of-thought — recorded, not exposed
args
{
"input": "const r = await tools.exec_command({cmd:\"git diff -- opsd_train.py opsd_trainer.py data_collator.py | sed -n '1,520p'; echo RECIPE; cat /workspace/submission/recipe.env\",\"workdir\":\"/workspace/repo\",\"yield_time_ms\":10000,\"max_output_tokens\":30000});\ntext(r.output);"
}exec result
Script completed
Wall time 0.1 seconds
Output:
diff --git a/data_collator.py b/data_collator.py
index 0829108..221b555 100644
--- a/data_collator.py
+++ b/data_collator.py
@@ -55,6 +55,7 @@ class SelfDistillationDataCollator:
# Prepare student and teacher prompts using chat template (matching evaluation)
student_prompts = []
teacher_prompts = []
+ anchor_sequences = []
teacher_reasoning_prompts = [] # NEW: for reason_first mode
for feature in features:
@@ -73,6 +74,13 @@ class SelfDistillationDataCollator:
)
student_prompts.append(student_prompt)
+ # Expert trajectory used as a weak anchor for OPSD. It starts at
+ # exactly the same non-privileged student prompt; unlike the
+ # teacher context below it never exposes the solution in the user
+ # message. The reference solution is available in every row of
+ # the released OPSD dataset.
+ anchor_sequences.append(student_prompt + solution.strip() + self.tokenizer.eos_token)
+
if self.reason_first:
# Reasoning prompt: ask teacher to analyze the solution
reasoning_user_message = (
@@ -138,6 +146,25 @@ class SelfDistillationDataCollator:
"student_prompt_lengths_per_example": torch.tensor(student_prompt_lengths),
}
+ anchor_encoded = self.tokenizer(
+ anchor_sequences,
+ padding=True,
+ truncation=True,
+ max_length=self.max_length,
+ return_tensors="pt",
+ )
+ anchor_labels = anchor_encoded["input_ids"].clone()
+ for i, prompt_len in enumerate(student_prompt_lengths):
+ anchor_labels[i, :prompt_len] = -100
+ anchor_labels[anchor_encoded["attention_mask"] == 0] = -100
+ result.update(
+ {
+ "anchor_input_ids": anchor_encoded["input_ids"],
+ "anchor_attention_mask": anchor_encoded["attention_mask"],
+ "anchor_labels": anchor_labels,
+ }
+ )
+
if self.reason_first:
# Tokenize reasoning prompts
reasoning_encoded_no_pad = self.tokenizer(
diff --git a/opsd_train.py b/opsd_train.py
index 8526a68..b4be7a4 100644
--- a/opsd_train.py
+++ b/opsd_train.py
@@ -266,6 +266,19 @@ if __name__ == "__main__":
dataset = load_dataset("siyanzhao/Openthoughts_math_30k_opsd")
train_dataset = dataset["train"]
+ # Reasoning-effort curriculum. `generated_token_count` is metadata shipped
+ # with the released dataset and measures how much reasoning was needed to
+ # obtain its verified solution. Under a 100-step budget, uniformly drawing
+ # many short arithmetic items wastes privileged-teacher calls. Retain the
+ # broad source mix but train on examples requiring at least 3k reasoning
+ # tokens, a model-native difficulty signal rather than a benchmark label.
+ train_dataset = train_dataset.filter(
+ lambda example: example["generated_token_count"] >= 3000,
+ desc="Selecting high-reasoning-effort OPSD examples",
+ )
+ if os.environ.get("LOCAL_RANK", "0") == "0":
+ print(f"Reasoning-effort curriculum: {len(train_dataset)} training rows")
+
trainer = OPSDTrainer(
model=model_args.model_name_or_path,
args=training_args,
diff --git a/opsd_trainer.py b/opsd_trainer.py
index c151bd7..8011b79 100644
--- a/opsd_trainer.py
+++ b/opsd_trainer.py
@@ -428,15 +428,31 @@ class OPSDTrainer(SFTTrainer):
teacher_logits = teacher_logits / temperature
if top_k is not None and top_k > 0:
- # Restrict to top-k tokens of the teacher distribution and renormalize.
- # Shape: [batch, seq_len, top_k]
+ # Teacher-support KL: retain the teacher's most actionable
+ # alternatives and aggregate every remaining vocabulary item
+ # into one exact "other" bucket. Renormalizing only the
+ # selected logits (the old implementation) discarded the
+ # student's probability leakage outside teacher support and
+ # was not a projection of the full distributions.
_, top_k_indices = torch.topk(teacher_logits, k=top_k, dim=-1)
- student_logits = torch.gather(student_logits, dim=-1, index=top_k_indices)
- teacher_logits = torch.gather(teacher_logits, dim=-1, index=top_k_indices)
-
- # Compute log probabilities for student and probabilities for teacher
- student_log_probs = F.log_softmax(student_logits, dim=-1)
- teacher_log_probs = F.log_softmax(teacher_logits, dim=-1)
+ student_full_log_probs = F.log_softmax(student_logits, dim=-1)
+ teacher_full_log_probs = F.log_softmax(teacher_logits, dim=-1)
+ student_head = torch.gather(student_full_log_probs, dim=-1, index=top_k_indices)
+ teacher_head = torch.gather(teacher_full_log_probs, dim=-1, index=top_k_indices)
+ # Accumulate retained mass in fp32: in bf16, 1-1e-6 rounds to
+ # one and log1p(-mass) can become -inf.
+ student_mass = student_head.float().exp().sum(dim=-1, keepdim=True).clamp(max=1 - 1e-5)
+ teacher_mass = teacher_head.float().exp().sum(dim=-1, keepdim=True).clamp(max=1 - 1e-5)
+ student_tail = torch.log1p(-student_mass)
+ teacher_tail = torch.log1p(-teacher_mass)
+ student_head = student_head.float()
+ teacher_head = teacher_head.float()
+ student_log_probs = torch.cat([student_head, student_tail], dim=-1)
+ teacher_log_probs = torch.cat([teacher_head, teacher_tail], dim=-1)
+ else:
+ # Compute log probabilities for student and teacher
+ student_log_probs = F.log_softmax(student_logits, dim=-1)
+ teacher_log_probs = F.log_softmax(teacher_logits, dim=-1)
if beta == 0:
jsd = F.kl_div(student_log_probs, teacher_log_probs, reduction="none", log_target=True)
@@ -459,7 +475,9 @@ class OPSDTrainer(SFTTrainer):
# Compute the Generalized Jensen-Shannon Divergence
jsd = beta * kl_teacher + (1 - beta) * kl_student
- # Per-token clipping: cap each token's divergence value
+ # Per-token clipping: cap each vocabulary contribution. Although the
+ # individual KL summands are signed, retaining this released behavior
+ # is important for the paper's point-wise robustness heuristic.
if token_clip is not None:
jsd = jsd.clamp(max=token_clip)
@@ -636,13 +654,39 @@ class OPSDTrainer(SFTTrainer):
shifted_labels = inputs["labels"][:, student_prompt_len:]
# === STUDENT FORWARD - Extract log-probs immediately ===
- outputs_student = model(
- input_ids=inputs["student_input_ids"],
- attention_mask=inputs["student_attention_mask"],
- )
+ # Put the on-policy and correct anchor trajectories in one forward.
+ # Besides being cheaper than two calls, this is required by ZeRO-2,
+ # whose overlapping reducer cannot visit the same LoRA parameter from
+ # two checkpointed graphs in one backward pass.
+ use_anchor = self.lmbda > 0 and "anchor_input_ids" in inputs and not self.use_thinking_machines_loss
+ student_batch_size = inputs["student_input_ids"].shape[0]
+ student_seq_len = inputs["student_input_ids"].shape[1]
+ if use_anchor:
+ anchor_seq_len = inputs["anchor_input_ids"].shape[1]
+ combined_seq_len = max(student_seq_len, anchor_seq_len)
+ pad_id = self.processing_class.pad_token_id
+ student_ids = F.pad(inputs["student_input_ids"], (0, combined_seq_len - student_seq_len), value=pad_id)
+ student_mask = F.pad(inputs["student_attention_mask"], (0, combined_seq_len - student_seq_len), value=0)
+ anchor_ids = F.pad(inputs["anchor_input_ids"], (0, combined_seq_len - anchor_seq_len), value=pad_id)
+ anchor_mask = F.pad(inputs["anchor_attention_mask"], (0, combined_seq_len - anchor_seq_len), value=0)
+ forward_ids = torch.cat([student_ids, anchor_ids], dim=0)
+ forward_mask = torch.cat([student_mask, anchor_mask], dim=0)
+ else:
+ forward_ids = inputs["student_input_ids"]
+ forward_mask = inputs["student_attention_mask"]
+
+ outputs_student = model(input_ids=forward_ids, attention_mask=forward_mask)
# Extract only what we need and convert to log-probs immediately
- student_logits = outputs_student.logits[:, student_prompt_len - 1 : -1, :]
+ student_logits = outputs_student.logits[:student_batch_size, student_prompt_len - 1 : student_seq_len - 1, :]
+
+ if use_anchor:
+ anchor_logits = outputs_student.logits[student_batch_size:, :anchor_seq_len, :]
+ anchor_loss = F.cross_entropy(
+ anchor_logits[:, :-1, :].reshape(-1, anchor_logits.shape[-1]),
+ inputs["anchor_labels"][:, 1:].reshape(-1),
+ ignore_index=-100,
+ )
if self.use_thinking_machines_loss:
# For reverse KL, we only need log-probs of sampled tokens
@@ -733,7 +777,7 @@ class OPSDTrainer(SFTTrainer):
)
else:
# Temperature is applied inside generalized_jsd_loss
- loss = self.generalized_jsd_loss(
+ opsd_loss = self.generalized_jsd_loss(
student_logits=student_logits_for_loss,
teacher_logits=teacher_logits_for_loss,
labels=shifted_labels,
@@ -744,6 +788,18 @@ class OPSDTrainer(SFTTrainer):
)
del student_logits_for_loss, teacher_logits_for_loss
+ # OPSD only visits student trajectories. A weak maximum-
+ # likelihood anchor on the known-correct trajectory prevents
+ # self-distillation from polishing an incorrect branch forever.
+ # `lmbda` is the anchor coefficient; setting it to zero recovers
+ # pure OPSD exactly.
+ if use_anchor:
+ loss = opsd_loss + self.lmbda * anchor_loss
+ self._metrics["train"]["opsd_kl"].append(float(opsd_loss.detach()))
+ self._metrics["train"]["anchor_ce"].append(float(anchor_loss.detach()))
+ else:
+ loss = opsd_loss
+
empty_cache()
if return_outputs:
RECIPE
# Difficulty-curriculum OPSD with the released optimizer/model settings.
lmbda=0
top_k_loss=0
lora_r=64
lora_alpha=128
max_completion_length=1024
lr_scheduler_type=linear
encrypted chain-of-thought — recorded, not exposed
args
{
"input": "const patch = \"*** Begin Patch\\n*** Update File: /workspace/repo/data_collator.py\\n@@\\n student_prompts = []\\n teacher_prompts = []\\n- anchor_sequences = []\\n teacher_reasoning_prompts = [] # NEW: for reason_first mode\\n@@\\n- # Expert trajectory used as a weak anchor for OPSD. It starts at\\n- # exactly the same non-privileged student prompt; unlike the\\n- # teacher context below it never exposes the solution in the user\\n- # message. The reference solution is available in every row of\\n- # the released OPSD dataset.\\n- anchor_sequences.append(student_prompt + solution.strip() + self.tokenizer.eos_token)\\n-\\n@@\\n- anchor_encoded = self.tokenizer(\\n- anchor_sequences,\\n- padding=True,\\n- truncation=True,\\n- max_length=self.max_length,\\n- return_tensors=\\\"pt\\\",\\n- )\\n- anchor_labels = anchor_encoded[\\\"input_ids\\\"].clone()\\n- for i, prompt_len in enumerate(student_prompt_lengths):\\n- anchor_labels[i, :prompt_len] = -100\\n- anchor_labels[anchor_encoded[\\\"attention_mask\\\"] == 0] = -100\\n- result.update(\\n- {\\n- \\\"anchor_input_ids\\\": anchor_encoded[\\\"input_ids\\\"],\\n- \\\"anchor_attention_mask\\\": anchor_encoded[\\\"attention_mask\\\"],\\n- \\\"anchor_labels\\\": anchor_labels,\\n- }\\n- )\\n-\\n*** Update File: /workspace/repo/opsd_trainer.py\\n@@\\n if top_k is not None and top_k > 0:\\n- # Teacher-support KL: retain the teacher's most actionable\\n- # alternatives and aggregate every remaining vocabulary item\\n- # into one exact \\\"other\\\" bucket. Renormalizing only the\\n- # selected logits (the old implementation) discarded the\\n- # student's probability leakage outside teacher support and\\n- # was not a projection of the full distributions.\\n+ # Restrict to top-k tokens of the teacher distribution and renormalize.\\n+ # Shape: [batch, seq_len, top_k]\\n _, top_k_indices = torch.topk(teacher_logits, k=top_k, dim=-1)\\n- student_full_log_probs = F.log_softmax(student_logits, dim=-1)\\n- teacher_full_log_probs = F.log_softmax(teacher_logits, dim=-1)\\n- student_head = torch.gather(student_full_log_probs, dim=-1, index=top_k_indices)\\n- teacher_head = torch.gather(teacher_full_log_probs, dim=-1, index=top_k_indices)\\n- # Accumulate retained mass in fp32: in bf16, 1-1e-6 rounds to\\n- # one and log1p(-mass) can become -inf.\\n- student_mass = student_head.float().exp().sum(dim=-1, keepdim=True).clamp(max=1 - 1e-5)\\n- teacher_mass = teacher_head.float().exp().sum(dim=-1, keepdim=True).clamp(max=1 - 1e-5)\\n- student_tail = torch.log1p(-student_mass)\\n- teacher_tail = torch.log1p(-teacher_mass)\\n- student_head = student_head.float()\\n- teacher_head = teacher_head.float()\\n- student_log_probs = torch.cat([student_head, student_tail], dim=-1)\\n- teacher_log_probs = torch.cat([teacher_head, teacher_tail], dim=-1)\\n- else:\\n- # Compute log probabilities for student and teacher\\n- student_log_probs = F.log_softmax(student_logits, dim=-1)\\n- teacher_log_probs = F.log_softmax(teacher_logits, dim=-1)\\n+ student_logits = torch.gather(student_logits, dim=-1, index=top_k_indices)\\n+ teacher_logits = torch.gather(teacher_logits, dim=-1, index=top_k_indices)\\n+\\n+ # Compute log probabilities for student and probabilities for teacher\\n+ student_log_probs = F.log_softmax(student_logits, dim=-1)\\n+ teacher_log_probs = F.log_softmax(teacher_logits, dim=-1)\\n@@\\n- # Per-token clipping: cap each vocabulary contribution. Although the\\n- # individual KL summands are signed, retaining this released behavior\\n- # is important for the paper's point-wise robustness heuristic.\\n+ # Per-token clipping: cap each token's divergence value\\n@@\\n- # Put the on-policy and correct anchor trajectories in one forward.\\n- # Besides being cheaper than two calls, this is required by ZeRO-2,\\n- # whose overlapping reducer cannot visit the same LoRA parameter from\\n- # two checkpointed graphs in one backward pass.\\n- use_anchor = self.lmbda > 0 and \\\"anchor_input_ids\\\" in inputs and not self.use_thinking_machines_loss\\n- student_batch_size = inputs[\\\"student_input_ids\\\"].shape[0]\\n- student_seq_len = inputs[\\\"student_input_ids\\\"].shape[1]\\n- if use_anchor:\\n- anchor_seq_len = inputs[\\\"anchor_input_ids\\\"].shape[1]\\n- combined_seq_len = max(student_seq_len, anchor_seq_len)\\n- pad_id = self.processing_class.pad_token_id\\n- student_ids = F.pad(inputs[\\\"student_input_ids\\\"], (0, combined_seq_len - student_seq_len), value=pad_id)\\n- student_mask = F.pad(inputs[\\\"student_attention_mask\\\"], (0, combined_seq_len - student_seq_len), value=0)\\n- anchor_ids = F.pad(inputs[\\\"anchor_input_ids\\\"], (0, combined_seq_len - anchor_seq_len), value=pad_id)\\n- anchor_mask = F.pad(inputs[\\\"anchor_attention_mask\\\"], (0, combined_seq_len - anchor_seq_len), value=0)\\n- forward_ids = torch.cat([student_ids, anchor_ids], dim=0)\\n- forward_mask = torch.cat([student_mask, anchor_mask], dim=0)\\n- else:\\n- forward_ids = inputs[\\\"student_input_ids\\\"]\\n- forward_mask = inputs[\\\"student_attention_mask\\\"]\\n-\\n- outputs_student = model(input_ids=forward_ids, attention_mask=forward_mask)\\n+ outputs_student = model(\\n+ input_ids=inputs[\\\"student_input_ids\\\"],\\n+ attention_mask=inputs[\\\"student_attention_mask\\\"],\\n+ )\\n@@\\n- student_logits = outputs_student.logits[:student_batch_size, student_prompt_len - 1 : student_seq_len - 1, :]\\n-\\n- if use_anchor:\\n- anchor_logits = outputs_student.logits[student_batch_size:, :anchor_seq_len, :]\\n- anchor_loss = F.cross_entropy(\\n- anchor_logits[:, :-1, :].reshape(-1, anchor_logits.shape[-1]),\\n- inputs[\\\"anchor_labels\\\"][:, 1:].reshape(-1),\\n- ignore_index=-100,\\n- )\\n+ student_logits = outputs_student.logits[:, student_prompt_len - 1 : -1, :]\\n@@\\n- opsd_loss = self.generalized_jsd_loss(\\n+ loss = self.generalized_jsd_loss(\\n@@\\n- # OPSD only visits student trajectories. A weak maximum-\\n- # likelihood anchor on the known-correct trajectory prevents\\n- # self-distillation from polishing an incorrect branch forever.\\n- # `lmbda` is the anchor coefficient; setting it to zero recovers\\n- # pure OPSD exactly.\\n- if use_anchor:\\n- loss = opsd_loss + self.lmbda * anchor_loss\\n- self._metrics[\\\"train\\\"][\\\"opsd_kl\\\"].append(float(opsd_loss.detach()))\\n- self._metrics[\\\"train\\\"][\\\"anchor_ce\\\"].append(float(anchor_loss.detach()))\\n- else:\\n- loss = opsd_loss\\n-\\n*** End Patch\";\ntext(await tools.apply_patch(patch));"
}exec result
Script completed
Wall time 0.0 seconds
Output:
{}encrypted chain-of-thought — recorded, not exposed
args
{
"input": "const r = await tools.exec_command({cmd:\"git diff --stat && git diff -- opsd_trainer.py data_collator.py && git diff -- opsd_train.py && python -m py_compile opsd_train.py opsd_trainer.py data_collator.py && git status --short && cat /workspace/.timer/remaining_secs\",\"workdir\":\"/workspace/repo\",\"yield_time_ms\":10000,\"max_output_tokens\":15000});\ntext(r.output);"
}exec result
Script completed
Wall time 0.2 seconds
Output:
README.md | 4 +---
opsd_train.py | 13 +++++++++++++
2 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/opsd_train.py b/opsd_train.py
index 8526a68..b4be7a4 100644
--- a/opsd_train.py
+++ b/opsd_train.py
@@ -266,6 +266,19 @@ if __name__ == "__main__":
dataset = load_dataset("siyanzhao/Openthoughts_math_30k_opsd")
train_dataset = dataset["train"]
+ # Reasoning-effort curriculum. `generated_token_count` is metadata shipped
+ # with the released dataset and measures how much reasoning was needed to
+ # obtain its verified solution. Under a 100-step budget, uniformly drawing
+ # many short arithmetic items wastes privileged-teacher calls. Retain the
+ # broad source mix but train on examples requiring at least 3k reasoning
+ # tokens, a model-native difficulty signal rather than a benchmark label.
+ train_dataset = train_dataset.filter(
+ lambda example: example["generated_token_count"] >= 3000,
+ desc="Selecting high-reasoning-effort OPSD examples",
+ )
+ if os.environ.get("LOCAL_RANK", "0") == "0":
+ print(f"Reasoning-effort curriculum: {len(train_dataset)} training rows")
+
trainer = OPSDTrainer(
model=model_args.model_name_or_path,
args=training_args,
M README.md
M opsd_train.py
4537
The validated submission is now clean: only the 13-line reasoning-effort filter changes training code; the abandoned loss/anchor experiments are removed. I have enough time for one final, principled interaction test: the selected hard problems are disproportionately truncated at 1,024 tokens, so I’ll test the same curriculum with 2,048-token rollouts. If it does not beat the two-run curriculum mean, I’ll revert the recipe to the validated 1,024 setting.
encrypted chain-of-thought — recorded, not exposed
args
{
"input": "const patch = \"*** Begin Patch\\n*** Update File: /workspace/submission/recipe.env\\n@@\\n-max_completion_length=1024\\n+max_completion_length=2048\\n*** End Patch\";\ntext(await tools.apply_patch(patch));"
}exec result
Script completed
Wall time 0.0 seconds
Output:
{}encrypted chain-of-thought — recorded, not exposed
args
{
"input": "const r = await tools.exec_command({cmd:\"SEED=42 OUT_DIR=/workspace/runs/hard3000_long PORT=12961 bash /workspace/train_capped.sh\",\"workdir\":\"/workspace\",\"yield_time_ms\":1000,\"max_output_tokens\":300});\ntext(r.output);if(r.session_id)text(`SESSION_ID=${r.session_id}`);"
}exec result
Script completed
Wall time 1.2 seconds
Output:
SESSION_ID=70713encrypted chain-of-thought — recorded, not exposed
args
{
"input": "let out=\"\";for(let i=0;i<18;i++){const r=await tools.write_stdin({session_id:70713,chars:\"\",yield_time_ms:60000,max_output_tokens:30});out+=r.output.slice(-60)+\"\\n\";if(r.exit_code!==undefined){out+=`EXIT${r.exit_code}`;break;}}text(out);\n"
}exec result
Script running with cell ID 125
Wall time 11.0 seconds
Output:
encrypted chain-of-thought — recorded, not exposed
args
{
"cell_id": "125",
"yield_time_ms": 60000,
"max_tokens": 60
}wait result
Script running with cell ID 125
Wall time 61.0 seconds
Output:
encrypted chain-of-thought — recorded, not exposed
args
{
"cell_id": "125",
"yield_time_ms": 60000,
"max_tokens": 60
}wait result
Script running with cell ID 125
Wall time 61.0 seconds
Output:
encrypted chain-of-thought — recorded, not exposed
args
{
"cell_id": "125",
"yield_time_ms": 60000,
"max_tokens": 60
}wait result
Script running with cell ID 125
Wall time 61.0 seconds
Output:
encrypted chain-of-thought — recorded, not exposed
args
{
"cell_id": "125",
"yield_time_ms": 60000,
"max_tokens": 60
}wait result
Script running with cell ID 125
Wall time 61.0 seconds
Output:
encrypted chain-of-thought — recorded, not exposed
args
{
"cell_id": "125",
"yield_time_ms": 60000,
"max_tokens": 60
}wait result
Script running with cell ID 125
Wall time 61.0 seconds
Output:
encrypted chain-of-thought — recorded, not exposed
args
{
"cell_id": "125",
"yield_time_ms": 60000,
"max_tokens": 60
}wait result
Script running with cell ID 125
Wall time 61.0 seconds
Output: