Skip to content
on-policy-self-distillation

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
627
duration
6h 30m
recorded
2026-08-02

run idopsd-aime24-4gpus__RqGcDty

Everything gpt-5.6-sol did on this task, in order.

download JSON ↗
codexgpt-5.6-sol684 turns57 narration627 reasoning627 action627 observation1 final
#676
reasoning (redacted)

encrypted chain-of-thought — recorded, not exposed

toolexec
args
{
  "input": "const r = await tools.write_stdin({session_id:32207,chars:\"\",yield_time_ms:30000,max_output_tokens:300});\ntext(r.output);\n"
}
exec result
Script running with cell ID 343
Wall time 11.0 seconds
Output:
#677
reasoning (redacted)

encrypted chain-of-thought — recorded, not exposed

toolwait
args
{
  "cell_id": "343",
  "yield_time_ms": 30000,
  "max_tokens": 300
}
wait result
Script completed
Wall time 10.9 seconds
Output:

Processed prompts:  57%|█████▋    | 48/84 [14:02<07:14, 12.06s/it, est. speed input: 5.84 toks/s, output: 1178.78 toks/s]
Processed prompts:  71%|███████▏  | 60/84 [14:13<03:12,  8.04s/it, est. speed input: 7.17 toks/s, output: 1497.27 toks/s]
Processed prompts:  75%|███████▌  | 72/96 [14:25<02:57,  7.40s/it, est. speed input: 11.18 toks/s, output: 1581.10 toks/s]
#678
reasoning (redacted)

encrypted chain-of-thought — recorded, not exposed

toolexec
args
{
  "input": "const r = await tools.write_stdin({session_id:32207,chars:\"\",yield_time_ms:30000,max_output_tokens:300});\ntext(r.output);\n"
}
exec result
Script running with cell ID 344
Wall time 11.0 seconds
Output:
#679
reasoning (redacted)

encrypted chain-of-thought — recorded, not exposed

toolwait
args
{
  "cell_id": "344",
  "yield_time_ms": 30000,
  "max_tokens": 300
}
wait result
Script completed
Wall time 0.0 seconds
Output:

Processed prompts:  86%|████████▌ | 72/84 [14:48<01:15,  6.29s/it, est. speed input: 8.23 toks/s, output: 1703.73 toks/s]
Processed prompts: 100%|██████████| 84/84 [14:51<00:00,  4.32s/it, est. speed input: 11.16 toks/s, output: 2071.09 toks/s]
Processed prompts: 100%|██████████| 84/84 [14:51<00:00,  4.32s/it, est. speed input: 11.16 toks/s, output: 2071.09 toks/s]
Processed prompts: 100%|██████████| 84/84 [14:51<00:00, 10.61s/it, est. speed input: 11.16 toks/s, output: 2071.09 toks/s]
#680
reasoning (redacted)

encrypted chain-of-thought — recorded, not exposed

toolexec
args
{
  "input": "const r = await tools.write_stdin({session_id:32207,chars:\"\",yield_time_ms:30000,max_output_tokens:500});\ntext(r.output);\n"
}
exec result
Script completed
Wall time 0.0 seconds
Output:

Processed prompts:  88%|████████▊ | 84/96 [15:23<01:18,  6.58s/it, est. speed input: 11.88 toks/s, output: 1832.69 toks/s]
Processed prompts: 100%|██████████| 96/96 [15:30<00:00,  4.66s/it, est. speed input: 14.06 toks/s, output: 2178.87 toks/s]
Processed prompts: 100%|██████████| 96/96 [15:30<00:00,  4.66s/it, est. speed input: 14.06 toks/s, output: 2178.87 toks/s]
Processed prompts: 100%|██████████| 96/96 [15:30<00:00,  9.69s/it, est. speed input: 14.06 toks/s, output: 2178.87 toks/s]

FINAL avg@12 accuracy: 58.06% (209/360 solutions correct on 30 problems)
Results written to /workspace/eval_results/refined_repeat3_full.json
#681
narration

The third full retrain scored 58.06% (209/360). The three replicated scores are 57.22%, 55.28%, and 58.06%, averaging 56.85%—a +2.63-point margin over the 54.22 baseline anchor. I’m performing final integrity and scorer-compatibility checks now.

#682
reasoning (redacted)

encrypted chain-of-thought — recorded, not exposed

toolexec
args
{
  "input": "const r = await tools.exec_command({cmd:\"git diff --check; python -m py_compile opsd_train.py opsd_trainer.py data_collator.py; git status --short; git diff -- data_collator.py opsd_train.py; printf '%s\\\\n' '--- recipe.env ---'; sed -n '1,40p' /workspace/submission/recipe.env; python - <<'PY'\\nimport json\\nps=['/workspace/eval_results/refined_long_full.json','/workspace/eval_results/refined_repeat2_full.json','/workspace/eval_results/refined_repeat3_full.json']\\nxs=[]\\nfor p in ps:\\n d=json.load(open(p)); xs.append(d['average_at_n_pct']); print(p,d['average_at_n_pct'],d['total_correct'])\\nprint('mean',sum(xs)/len(xs),'gain',sum(xs)/len(xs)-54.22)\\nPY\\ncat /workspace/.timer/remaining_secs\",\"workdir\":\"/workspace/repo\",\"yield_time_ms\":10000,\"max_output_tokens\":20000});\ntext(r.output);\n"
}
exec result
Script completed
Wall time 0.2 seconds
Output:
README.md:285: trailing whitespace.
+| `--jsd_token_clip` | 0.05 | Clip the JSD loss for each token to a maximum value. This can improve stability. | 
 M README.md
 M data_collator.py
 M opsd_train.py
diff --git a/data_collator.py b/data_collator.py
index 0829108..d596a51 100644
--- a/data_collator.py
+++ b/data_collator.py
@@ -64,7 +64,10 @@ class SelfDistillationDataCollator:
             solution = feature["solution"]
 
             # Student prompt: just the problem with instruction (matching evaluation format)
-            student_user_message = f"Problem: {problem}\n\nPlease reason step by step, and put your final answer within \\boxed{{}}."
+            # Match the frozen AIME evaluator exactly.  The released collator
+            # prepended "Problem: " even though evaluation supplies the raw
+            # problem, creating a needless train/inference context shift.
+            student_user_message = f"{problem}\n\nPlease reason step by step, and put your final answer within \\boxed{{}}."
             student_messages = [{"role": "user", "content": student_user_message}]
 
             # Apply chat template for student (matching evaluation)
diff --git a/opsd_train.py b/opsd_train.py
index 8526a68..86a3494 100644
--- a/opsd_train.py
+++ b/opsd_train.py
@@ -1,7 +1,8 @@
 import os
+import re
 import wandb
 
-from datasets import load_dataset
+from datasets import concatenate_datasets, load_dataset
 from transformers import AutoTokenizer, GenerationConfig
 
 from trl import (
@@ -266,6 +267,45 @@ if __name__ == "__main__":
     dataset = load_dataset("siyanzhao/Openthoughts_math_30k_opsd")
     train_dataset = dataset["train"]
 
+    # Difficulty/format-matched replay.  AIME uses hard free-response problems
+    # whose answers are small integers, while the released pool is 72% broad
+    # olympiad data and its `amc_aime` source is mostly easy multiple choice.
+    # Select examples using only frozen dataset metadata, then replay the scarce
+    # past-AIME slice.  The mix remains diverse (AoPS, MATH, and olympiad) and is
+    # shuffled by Trainer with the scoring seed.  This changes neither the
+    # number of optimizer steps nor the global batch size.
+    def has_integer_answer(example):
+        answer = (example.get("Answer") or "").strip()
+        return re.fullmatch(r"(?:\\boxed\{)?-?\d{1,3}(?:\})?", answer) is not None
+
+    past_aime = train_dataset.filter(
+        lambda example: example["source"] == "amc_aime" and has_integer_answer(example)
+    )
+    hard_aops = train_dataset.filter(
+        lambda example: example["source"] == "aops_forum"
+        and has_integer_answer(example)
+        and example["generated_token_count"] >= 2500
+    )
+    hard_math = train_dataset.filter(
+        lambda example: example["source"] == "math"
+        and has_integer_answer(example)
+        and example["generated_token_count"] >= 2500
+    )
+    hard_olympiad = train_dataset.filter(
+        lambda example: example["source"] == "olympiads"
+        and has_integer_answer(example)
+        and example["generated_token_count"] >= 3000
+    )
+    hard_olympiad = hard_olympiad.select(range(min(1000, len(hard_olympiad))))
+    train_dataset = concatenate_datasets(
+        [past_aime] * 8 + [hard_aops, hard_math, hard_olympiad]
+    )
+    print(
+        f"AIME-matched OPSD mixture: {len(train_dataset)} rows "
+        f"({8 * len(past_aime)} past-AIME replay, {len(hard_aops)} AoPS, "
+        f"{len(hard_math)} MATH, {len(hard_olympiad)} olympiad)"
+    )
+
     trainer = OPSDTrainer(
         model=model_args.model_name_or_path,
         args=training_args,
--- recipe.env ---
max_completion_length=1536
lr_scheduler_type=linear
/workspace/eval_results/refined_long_full.json 57.22222222222222 206
/workspace/eval_results/refined_repeat2_full.json 55.27777777777778 199
/workspace/eval_results/refined_repeat3_full.json 58.05555555555556 209
mean 56.85185185185185 gain 2.631851851851849
9915
#683
narration

Final checks found only a pre-existing trailing space in the already-dirty README; I did not alter that user-owned change. The two method files compile cleanly, the recipe contains only whitelisted keys, and the exact current repository/recipe trained successfully three times.

#684
reasoning (redacted)

encrypted chain-of-thought — recorded, not exposed

toolexec
args
{
  "input": "const r = await tools.exec_command({cmd:\"git diff --check -- data_collator.py opsd_train.py; python -m py_compile data_collator.py opsd_train.py opsd_trainer.py; test \\\"$(sed '/^$/d' /workspace/submission/recipe.env | wc -l)\\\" -eq 2; rg -n \\\"^(max_completion_length|lr_scheduler_type)=\\\" /workspace/submission/recipe.env; find /workspace/submission -maxdepth 1 -type f -printf '%f %s bytes\\\\n'; git diff --name-only; cat /workspace/.timer/remaining_secs\",\"workdir\":\"/workspace/repo\",\"yield_time_ms\":10000,\"max_output_tokens\":3000});\ntext(r.output);\nconst p = await tools.update_plan({explanation:\"Implemented and replicated the final AIME-matched replay + prompt alignment + longer-rollout method. Three full retrains average 56.85%, and final scorer-compatibility checks pass.\",plan:[\n {step:\"Audit repository, paper, baseline recipe, and training logs\",status:\"completed\"},\n {step:\"Formulate and implement a budget-neutral OPSD improvement\",status:\"completed\"},\n {step:\"Run targeted training/evaluation experiments and compare candidates\",status:\"completed\"},\n {step:\"Finalize method, recipe, and verify scorer-compatible training\",status:\"completed\"}\n]}); text(p);\n"
}
exec result
Script completed
Wall time 0.2 seconds
Output:
1:max_completion_length=1536
2:lr_scheduler_type=linear
recipe.env 52 bytes
README.md
data_collator.py
opsd_train.py
9884
{}
final summary

Implemented and validated an improved OPSD method.

  • Hard integer-answer curriculum with past-AIME replay and diverse difficult examples: opsd_train.py
  • Training prompt aligned exactly with evaluation: data_collator.py
  • 1,536-token rollouts and linear LR decay: recipe.env

Three independent full evaluations scored 57.22%, 55.28%, and 58.06%, averaging 56.85%+2.63 points over the 54.22 baseline.

All modified training files compile and three scorer-equivalent training runs completed successfully.