Training (2026-10-10, ERISHPC, 4 × H200)
Table with columns: official sft_trainer_2.yaml, this checkpoint | official sft_trainer_2.yaml | this checkpoint |
|---|
| data | official E²C SFT parquet, 58,136 rows (question / solution) | same; official split train 55,229 / val 2,907 (seed 42) |
| global batch / steps | 160 / 1000 | 160 (4 GPUs × micro 8 × grad-accum 5) / 1000 (≈ 2.9 epochs) |
| lr / betas / wd / warmup / schedule / clip | 2e-5 / (0.9, 0.95) / 0.01 / 0.1 / cosine / 1.0 | same |
| precision / parallelism | bf16, FSDP2, full-parameter, gradient checkpointing, flash-attention-2 | same |
max_length / truncation | 1000 / right | 3400 / error (see below) |
| seed | 114514 | same |
| wall-clock | — | 5 h 04 min, 17.7 s/step |
| loss | — | train 0.402 (step 1) → 0.150 (step 1000); val 0.160 |
Why max_length 3400: with the Qwen3 tokenizer the longest prompt+solution in the official data is 3,310 tokens and
62.3 % of rows exceed 1,000, so the official value would right-truncate most samples inside <EXECUTION>. Before training,
the official SFTDataset was run on the longest and random rows to confirm zero truncation, prompt masking, and that both
<EXPLORATION> and <EXECUTION> tokens are supervised. All other hyper-parameters follow the official config.
Plain Qwen3 chat template, no system prompt, no <think> prefix (identical to the official SFTDataset):
from transformers import AutoTokenizer, AutoModelForCausalLMrepo = "Levi980623/Qwen3-8B-E2C-SFT"tok = AutoTokenizer.from_pretrained(repo)model = AutoModelForCausalLM.from_pretrained(repo, dtype="bfloat16", device_map="auto")prompt = tok.apply_chat_template([{"role": "user", "content": QUESTION}], tokenize=False, add_generation_prompt=True)ids = tok(prompt, return_tensors="pt", add_special_tokens=False).to(model.device)out = model.generate(**ids, max_new_tokens=4096, do_sample=True, temperature=0.7, top_p=0.9, stop_strings=["</EXECUTION>"], tokenizer=tok)print(tok.decode(out[0, ids["input_ids"].shape[1]:], skip_special_tokens=True))
The official training targets end with </EXECUTION> and carry no EOS token, so stop on the string </EXECUTION>
(official inference does the same; vLLM: SamplingParams(stop=["</EXECUTION>"])). <EXPLORATION> / <EXECUTION> are
ordinary text, not added special tokens (as in the official setup).
Sanity check (not a benchmark)
20 prompts (8 repo example_problems.json, 12 held-out official-val questions), temperature 0.7 / top_p 0.9:
20/20 produce <EXPLORATION>…</EXPLORATION><EXECUTION>…</EXECUTION> and stop on the tag; 18/20 end with a \boxed{}
answer; manual check: 5/8 repo examples and 4/12 val questions correct (2 multiple-choice undecidable, 1 without reference).
Example (GSM8K):
<EXPLORATION>I need to make a step-by-step plan.1. Calculate the total number of eggs laid by the ducks each day.2. Subtract the number of eggs Janet uses for breakfast.3. Subtract the number of eggs used for baking muffins.4. Multiply the remaining number of eggs by the price per egg to find the daily earnings.</EXPLORATION><EXECUTION>1. ... Janet's ducks lay 16 eggs per day.2. ... $ 16 - 3 = 13 $ eggs remaining.3. ... $ 13 - 4 = 9 $ eggs remaining.4. ... $ 9 \times 2 = 18 $ dollars.Final answer: $\boxed{18}$</EXECUTION>
Files
Weights (4 safetensors shards, bf16), tokenizer, chat template, generation config, and training_config_and_logs/
(the exact training yaml and sbatch, the full training log, the pre-training mask/length check, length statistics and
pip freeze). The verl-native checkpoint with optimizer state is kept locally only.