Buckets:

Pranav2748's picture
|
download
raw
16.3 kB
# Deviations from the plan
Every change to "Reasoning decision model: A100 training plan", with its reason. The plan says to use judgment;
these are the places where I did.
| # | Plan | What I did | Why |
|---|---|---|---|
| 1 | Readout eval in transformers | Readout runs in vLLM: next token restricted to the K option letters (`allowed_token_ids`), processed logprobs returned for all K. Trained models are evaluated from merged bf16 checkpoints, one engine each | Exactly the K-way letter softmax of one forward pass, batched: ~5,400 items in 1.5 minutes. LoRA serving was tried and rejected: vLLM 0.32 silently ignores LoRA adapters on Qwen3.5 (with a perturbed adapter, vLLM's outputs equalled the base model's while PEFT's moved by 0.53). A merged checkpoint in vLLM matches PEFT up to bf16 rounding, and the text-only and multimodal vLLM code paths give identical base outputs (max difference 0.0 on 40 items), so base and trained models are compared on equal terms |
| 2 | Thinking answer = first capital letter after `</think>` | Kept as the primary answer, and added a readout after the chain: the letter softmax at the answer position, given the prompt and the chain | Gives the reasoning mode a probability over options, and checks whether the decision is the one the reasoning leads into (letter vs post-chain readout agreement is reported) |
| 3 | OpenDecisions by tier and family | Also scored with OpenDecisions' own `score.py` (Capability, Intelligence, Calibration) | Puts the numbers on the public OpenDecisions leaderboard scale (4B systems: 58.9 to 77.1) |
| 4 | Margin router only | Margin router plus a learned agreement router: logistic regression on readout features (top probability, margin, entropy, K, type), fitted on the calibration set only, predicting agreement with the same model's reasoning | LEV (arXiv 2610.20951) finds a stopper that predicts agreement with the deeper answer beats confidence thresholds, since shallow readouts are overconfident on new data. Costs nothing extra |
| 5 | Generation in dataset option order | One fixed shuffled option order per item (score levels keep theirs), saved with the record | Reasoner examples and votes are not tied to the first-listed option; votes are mapped back to the original options |
| 6 | Calibration set ~400 | 515 items (216 procedural, 299 tasksource validation), also given one reasoning sample | Fits per-type temperatures and the learned router (which needs reasoning on its fitting items) |
| 7 | Scorer from the dataset repo | `od_score.py` is a reviewed, unchanged copy of OpenDecisions' MIT `score.py` | Downloaded code is not imported from the download directory |
| 8 | Reasoner loss on chain and letter | Chain, letter and the end-of-turn token | Keeps the trained reasoner stopping cleanly after its letter |
| 9 | Base model Qwen3-4B | **Qwen3.5-4B** (Qwen3-4B kept as the fallback). Measured on the same items before deciding, see the table below | Much stronger decision model: raw OpenDecisions Capability 55.2 vs 31.9, readout +5 to +7 points on the natural-language sets, reasoner 97% vs 87% on procedural items. It is the base of every public 4B decision model, so results are comparable. The plan's concern (custom inference code) did not hold: vLLM 0.32 runs its readout, thinking and post-chain readout. The user also preferred it |
| 10 | LoRA on q, k, v, o, gate, up, down | Also on the linear-attention projections `in_proj_qkv`, `in_proj_z`, `out_proj` | 24 of Qwen3.5-4B's 32 layers are gated-delta (linear attention) layers; this follows the Inner Jev recipe for Qwen3.5 |
| 11 | `pip install vllm peft datasets accelerate scikit-learn` | Also `flash-linear-attention` (pure Triton) and `kernels` | Without them transformers runs Qwen3.5's delta rule in a reference PyTorch implementation that ran out of memory at 16k tokens. With them: 3,600-3,900 training tokens/s, 18.4 GB peak at 16k tokens. `causal_conv1d` stays on its PyTorch fallback (cheap, no build) |
| 12 | Preflight with Qwen3-0.6B | Qwen3.5-0.8B | Same architecture as the base, so the preflight tests the hybrid-attention paths |
| 14 | Preflight ran every stage | Preflight found four bugs, all fixed before the run: async `n=4` sampling returned one sample; vLLM ignored LoRA (see #1); a self-pointing symlink; the speed test lacked `model.train()`. The preflight's latency stage was stopped (20 sequential 32k-token loops of the 0.8B model) and the remaining paths were tested on few items | Testing the code, not the tiny model's patience |
| 15 | vLLM defaults | `max_num_seqs=256` from 03:16 UTC on (generation and later stages). The probe and baseline ran at 128 | The in-process async engine falls back to vLLM's global default of 128 running sequences (its usage context is not in the per-GPU table). Engine stats: 4.1-4.6k generated tok/s at 128 with the KV cache at ~40%, 4.7k at 256 with ~70%. A first try at 512 (02:51-03:08) could not be judged, since engine stats were off and the completion-based counter lags; my first reading of it ("no faster") was a bad comparison and is withdrawn |
| 16 | Generation budget 165 min, ending 3.2-3.4 h before the 8 h end | Generation stopped at 03:12 UTC (380 items kept, none partial) and restarted to run until 05:41 UTC: global window 8.67 h (`TOTAL_H=8.67`) | Qwen3.5 chains (about 12k tokens per item for 4 samples) at 3.4k tok/s give about 19 items/min, so about 2,500 items by the original deadline, and joint training on that data takes about 40 min instead of the 75 budgeted. The freed time goes to generation (about +750 items) rather than idling; the overall finish moves little |
| 17 | If N < 4,000, run only the gold-only ablation | Both ablations run | N will be about 2,800-3,000 (Qwen3.5 chains). The rule saved time; here each readout-only ablation is about 3M tokens (~15 min), and votes-only is the control for the readout copying the reasoner's mistakes |
| 18 | 10-step timing probe sets how many examples fit | Kept as written; it dropped 5.3% of joint examples (318 of 5,987, whole examples) | The probe ran during first-shape kernel compilation (flash-linear-attention, Triton) and measured 2.1k tok/s; steady state was 2.9k, at which everything would have fit. A probe that skips its first steps would avoid this next time |
| 19 | Ablations on the same items as the joint model | Ablations use all 3,169 generated items; the joint readout saw 2,996 (the rest went in #18's drop) | The drop happened inside the joint run. The ablations therefore have about 5% more readout data, which biases H1 against the joint model (conservative) |
| 13 | Ablation budget ~25 min each | 30 min each; generation stops at the earlier of 165 min or 3.4 h before the global end | Qwen3.5 chains are about 3x longer (median 1,801 vs 553 tokens), so later stages need the margin |
| 20 | V2 chains come from the 4B itself | 662 tasksource questions from the back of the pool got 4 chains each from Qwen3.5-35B-A3B on OpenRouter (`teacher_gen.py`, user's key and $7 budget; $6.60 spent, 11.5 min), merged into `gen.jsonl` before training (`source: teacher`). Same prompt, option order and sampling (0.6 / 0.95 / 20), no reasoning budget, 12,288-token cost cap (3 of 2,648 hit it). Same filters as local chains. Result: 835 extra training chains from 454 questions; votes for 662 readout targets | User request. Off-policy for the 4B, but same family and tokenizer; Apache-2.0. Teacher accuracy on its tasksource items matches the 4B's on its own (64% 4/4, 21% 0/4 vs 61% / 21%), so the 0/4 tail is mostly label noise (checked by hand on 5), and the teacher's value is shorter (median 1,083 vs 1,567 tokens) and non-repetitive chains, not harder questions solved. Local generation was not shortened, so this adds ~35 min of A100-equivalent generation rather than saving time |
| 21 | Training setup fixed (all layers checkpointed, 16K micro-batches, HF kernels) | A ~12 min benchmark (`bench_speed.py`) runs first: current vs Liger RMSNorm+SwiGLU vs checkpointing only micro-batches above 8K padded tokens vs both (+12K variant). A setup counts only if its loss and LoRA-gradient errors against an fp32 reference are at most 1.5x the current bf16 setup's; the fastest passing one under 72 GB wins if >= 3% faster, else nothing changes | User asked for Liger/compile analysis. A smoke test on 0.8B showed checkpointing changes nothing numerically (bit-identical losses) while Liger is not bit-identical (0.6% loss, 6.5% gradient difference vs HF bf16), so a fixed threshold against bf16 could not tell kernel error from rounding; the fp32 reference can. No fused CE (our loss uses only letter rows and chunked chain CE), no torch.compile |
| 22 | LR sweep on 4,000 questions, 30 min each, lowest dev NLL wins | 1,500 questions (~754K tokens, ~23 steps), scored on 500 dev questions, no timing probe, 15 min box; pick = the lowest LR whose dev NLL is within 0.01 of the best (fixed before any result) | User: keep it short and narrow. A ~23-step run favours high LRs relative to the ~1,700-step joint run, so ties go to the lower LR |
| 23 | Invented-recall filter (#V2 chain audit) | Widened with 'found a reference to', 'I recall/remember seeing similar examples/datasets', 'search for the exact text': +317 correct chains dropped (1.8%; 74 teacher). 12/12 sampled new matches were invented look-ups; 'the exact text provided' and GitHub mentions stay | A teacher chain claimed 'I found a reference to this exact text in a GitHub repository... Okay, confirmed' and the old pattern missed it |
| 24 | RL: 32 prompts x 8 chains per step, 100-150 steps in ~4 h | Rounds of 128 chains (16 prompts x 8) feeding 4 optimizer steps of 32; one chain per forward; vLLM at 0.5 of the GPU; ~120 steps in ~3.2 h | RL prompts' chains are long (median 5,280 tokens, 21% past 8,192): the original shape is ~1.3M generated tokens a step, ~15 h for 100 steps |
| 25 | RL prompts: items with 1-3 of 4 correct; reward +1 / -1 | `rl_select.py` first: exact (procedural) labels kept at 1-3 of 4; hard-label tasksource items need >= 2 of 4 (1 of 4 = three chains reject the label, the small-loss rule of noisy-label learning; 126 of 485 dropped); soft-label items rewarded by annotator share (2 * share - 1); then the V2 fast readout drops items it already gets right at >= 0.95 (would be 8 of 8, no signal) and hard-label items it puts gold below 0.05. Advantages scaled by batch spread, not per group (Dr. GRPO) | User: noisy gold labels must be handled. A generation-based re-check would cost ~50 min for these long chains, about what it saves; the readout check costs ~1 min. Rules-only count today: 645 of 771 mixed items kept |
| 26 | Speed setup picked by `bench_speed.py`'s rule (equivalent to fp32 within 1.5x of current, < 72 GB peak, >= 3% faster) | The rule kept the current setup (Liger failed the loss check; C passed equivalence but peaked at 74.9 GB). On the user's call, V2 joint and the ablations use C: no checkpointing for micro-batches up to 8K padded tokens, 8K micro-batches (+48%, 3,023 -> 4,474 tok/s; grad error vs fp32 0.334 vs 0.331, loss error identical). 74.9 GB is torch's decimal figure = 69.8 GiB of the card's 80 GiB. Safeguards: an unchecked micro-batch that runs out of memory is redone with checkpointing after restoring the gradients from before it (tested by forcing an OOM half-way through backward on the 0.8B: adapter difference 1.3e-4 relative, from the recompute), and `expandable_segments` for the allocator on training stages. Sweep ran with the current setup (C is equivalent). | User decision; ~1.5 h saved on V2 joint, the full V2 data fits with room instead of just. |
| 27 | RL prompts from the training pool only (rl_select.py rules, #25) | User asked for RL on questions the model never trained on, for out-of-domain transfer. 480 prompts: 60% fresh tasksource train-split questions outside the V2 pool/dev/eval/calib by id and content (`rl_fresh.py`; 2/3 from 53 reasoning-heavy sources: logic, rules, spatial, contracts, agent safety; 1/3 spread over 651 others), kept when the V2 readout gives gold 0.15-0.85 (unsure, not memorised; also drops labels it is sure are wrong); 40% in-domain from #25's rules. OpenDecisions and LocalLLaMA have no training split, so they stay untouched and measure transfer. | Fresh questions carry no 4-chain noise check; the readout band replaces it. In-domain items were mostly in V2's chain training and may be partly memorised. |
| 28 | RL importance-sampling correction with TRL defaults (sequence_mask, cap 3) | token_truncate (per-token ratios clipped at 3). First round under sequence_mask: per-token engine/trainer log-prob gap 0.006 on average, but summed over ~4.5K-token chains the sequence ratio collapses (mean 0.55, min 0), so long and unfinished chains, the ones the cap penalty is for, got near-zero weight. Run restarted at 19:27 (one 9-minute round lost; log kept as logs/rl_grpo_seqmask_aborted.log). | Token-level truncated IS (as in Yao et al. 2025, 'off-policy RL training' with vLLM) keeps every chain in the loss. |
| 29 | RL: 120 steps at lr 1e-5 (constant after 5 warm-up steps) | Steps 1-40 at 1e-5; then 20 steps at 2.5e-5 (user's call) from the step-40 adapter with a fresh AdamW, only questions not yet used (320 left; seed 17 as in steps 1-40, so the used prompts match exactly); eval after step 60 total. At 1e-5 the policy barely moved: PPO-clipped tokens 0.08-0.16% on the 4th (most off-policy) step of each round, gradient norm 0.08-0.15 against the 1.0 clip; difficulty-adjusted gains were small (share right +1.4 points per round, se 1.2). | 120 steps would have taken ~6 h; the short run needs more movement per step. Mixed schedule: the eval measures the end point, not either rate alone. |
| 30 | ~2B model after V2, same pipeline (own chains, probe-then-pick) | Started overnight on the user's instruction regardless of the RL result. Probe Qwen3.5-2B and MiniCPM5-2B the way the 4B candidates were probed; pick by a pre-registered rule (mean of readout accuracy over the 4 eval sets and first-chain accuracy on the pool; parse >= 0.9; Qwen within 0.02 wins). Trained on V2's data as is: chains written by the 4B and the 35B teacher (distillation), readout targets 50/50 gold + the 4B's votes; V2 flags, speed setup C, its own 3-rate sweep. | 2B-generated chains would take 5+ h; the overnight window is ~6 h. The 2B's results are distillation results, not self-generated ones. |
| 31 | Report after V2, RL and the 2B (no external benchmarks named) | External evals on the user's request: Jevals 0.1.0 and S1MB English v1, scored with our reimplementations of their published rules (running S1MB's evaluator was refused by the permission check as third-party code; the scorer reproduces 48 published benchmark scores to 6e-16); then bootstrap CIs, an error analysis, a yes/no offset check and a routed S1MB run (V2 + RL, 30% to thinking). Skipped to save GPU time: Jevals thinking runs for base, v1 and the 2B V2 recipe; S1MB for V2 and the 2B V2 recipe; routed S1MB for the 2B hybrid; the Jev Decision Index (needs its own harness) | Rank the work against published models and test whether the routed system transfers, within the remaining GPU time |
## Base-model probe (same 5,442 eval items; thinking: 4 samples on the first 128 pool items)
| | Qwen3-4B | Qwen3.5-4B |
|---|---|---|
| Readout accuracy: procedural / tasksource / OpenDecisions / LocalLLaMA (%) | 48.7 / 54.4 / 61.3 / 58.0 | 47.1 / 61.1 / 66.5 / 62.8 |
| OpenDecisions Capability, raw (no temperatures) | 31.9 | 55.2 |
| Pool items, procedural: readout / 1 chain / majority of 4 (%) | 37 / 87 / 92 | 48 / 97 / 98 |
| Pool items, tasksource: readout / 1 chain / majority of 4 (%) | 64 / 71 / 71 | 59 / 68 / 68 |
| Chain tokens: median / p90 / max | 553 / 2,162 / 32,473 | 1,801 / 6,680 / 32,640 |
| Tokens per item (4 samples) | 4,197 | 12,230 |
| Chains that looped to the context limit | 1 of 512 | 3 of 512 |
| Batch throughput, tail-bound (generated tokens/s) | 1,338 | 2,804 |
| Post-chain readout argmax = generated letter | 100% | 98.4% |
Shorter reasoning: the reasoner is trained on the shortest correct chain of its 4 samples (rejection sampling for brevity, as in the plan); nothing is cut or rewritten. Chain lengths before and after training are reported.

Xet Storage Details

Size:
16.3 kB
·
Xet hash:
7b4077028107c899e65bd57091916170b0a70a29270fe43c2a2b7bce878453d7

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.