Argonne 3.0-think
Argonne 3.0-think is a 2.88B-parameter
reasoning model from the Argonne 3.x family. It supports an explicit chain-of-thought "think" mode (
<think> … </think>) and answers directly in no-think mode. It is built entirely from
Argonne 3.0-base through a multi-stage pipeline that ends in
training-free weight-soups — one to repair the pretraining base, one to reconcile reasoning with general chat, and further recovery soups after each round of self-improvement.
On a 40-item internal 4-quadrant probe ({math, general} × {no-think, with-CoT}) it scores 33/40, with strong arithmetic in both modes while remaining a loop-free general chat model. (This is a small hand-checked probe — for held-out benchmark numbers and how to get the most out of the model, see Getting more accuracy: test-time compute below.)
📝
Companion blog post: How I Taught a Small Language Model to Reason — a plain-language walkthrough of how this model was built (calibrated chain-of-thought data + training-free weight-soups), for readers who want the story without the code.
Update (2026-07-12) — v4. A modest, external-teacher-distillation reasoning update. A stronger open model (Qwen3-4B) solved the GSM8K train split (contamination-safe, 87.8% correct → 3,714 short worked solutions); those distilled traces — plus new tool-calling and coding data tiers — were CoT-SFT'd from dpo_soup (→ think_v7) and cross-souped with v3 (v4 = 0.3·think_v7 + 0.7·v3). On clean held-out math the teacher distillation raised greedy ASDiv 25.8→30.5 and strengthened native </think> termination; SVAMP greedy is ~flat and self-consistency regressed ~6 pts (a trade — see Getting more accuracy and Limitations). Honestly, v4 is a mixed, reasoning-focused update, not a clean dominance over v3. The new tool-calling capability was learned cleanly (the training checkpoint emits 100% valid <tool_call>s) but is not baked into this shipped card (it dilutes out of the conservative soup and, without a real executor, the model hallucinates tool outputs); it is exposed instead as a serving-side tool-execution loop — see Tool use & serving-system capabilities. Coding did not measurably transfer at this scale (HumanEval ≈ 0, base-capacity-limited). See step 10 in How it was trained. v3 (x_v6v2_040) is retained upstream for rollback.
Update (2026-07-11) — v3. This release targets the model's #1 deployable failure: non-termination — on clean held-out problems (SVAMP/ASDiv) ~50–60% of sampled <think> traces never close </think>, even on one-step problems (the model over-thinks). v3 distills the fix into the weights: a SHORT-trace CoT-SFT (train only on ≤768-token closed-correct traces) so greedy decoding natively terminates with the answer — turning the decode-time budget-forcing win into a weights-level one — plus a contamination-safe grade-school procedure tier; the result is then weight-soup–fused with v2 to keep v2's self-consistency diversity. On clean held-out math (SVAMP / ASDiv, greedy): 18.0→22.7 / 22.7→27.3; self-consistency held (36.3→40.3 / 51.0→48.0); pass@32 up (73.3→74.7 / 74.3→77.0). See step 9 in How it was trained. (GSM8K remains contaminated for this model — see the note under Benchmarks — so held-out SVAMP/ASDiv are the honest judge.)
Update (2026-07-08) — v2. The model was improved by a round of STaR self-improvement (rejection-sampling fine-tuning on the model's own verified-correct GSM8K <think> traces) followed by a third training-free soup that recovers the no-think arithmetic that step regressed — improving held-out math (on the clean SVAMP/ASDiv benchmarks, greedy ~9%→~18% / ~18%→~23%; see Benchmarks) while keeping general chat and no-think math intact. (Earlier versions of this card reported a GSM8K 2%→~7.5% gain; GSM8K is now known to be contaminated for this model — see the note under Benchmarks — so held-out SVAMP/ASDiv are used instead.) See step 8 in How it was trained. Also: config.json now ships an auto_map, so AutoModelForCausalLM.from_pretrained(..., trust_remote_code=True) loads it directly (no manual import model needed).
Decoding note (important): for math/arithmetic, use greedy decoding and do not apply an aggressive repetition_penalty / no_repeat_ngram_size. Anti-repeat decoding corrupts multi-digit arithmetic (it blocks the model from re-emitting digits it just used, e.g. turning 80 / 2 into 8 / 2) and collapses math accuracy. See Recommended inference settings below.
How it was trained
Argonne 3.0-think is the endpoint of the following pipeline. Every stage runs at 13,568-token context with RoPE θ = 1,000,000 (the base is RoPE-extrapolated from a 1,024-ctx pretraining run).
| # | Stage | Init from | Data | What it does |
|---|
| 1 | Pretraining (from scratch) | — | HuggingFaceFW/fineweb (~76B tokens, 1,024 ctx) | The 2.88B base, Argonne 3.0-base. |
| 2 | Intermix midtraining | Argonne 3.0-base | FineWeb (crawl CC-MAIN-2025-21) + HuggingFaceTB/finemath subset finemath-4plus, mixed 50:50 → 60:40 by document | Injects grade-school + competition numeracy the pure-FineWeb base lacked. |
| 3 | Soup base (training-free) | — | (weight interpolation, no data) | 0.35 · base + 0.65 · intermix. A linear weight-soup of the two same-lineage checkpoints — recovers general knowledge the midtraining LR over-wrote while keeping the math. This is the reasoning-ready base. |
| 4 | SFT | Soup base | HuggingFaceH4/ultrachat_200k (train_sft) | Instruction / multi-turn chat. |
| 5 | DPO | SFT model | KatoHF/chatbot_arena_binarized | Preference alignment on real user comparisons. Kept as dpo_soup (the general-healthy pre-CoT checkpoint). |
| 6 | CoT-SFT | DPO model | cot_sft_mix_v3 (see table below) | Teaches explicit <think> chain-of-thought; brings math to 10/10 but regresses general chat (over-reasons / loops). |
| 7 | Final weight-soup (training-free) | — | (weight interpolation, no data) | 0.15 · (DPO model) + 0.85 · (CoT-SFT model). Fractionally "un-applies" the CoT stage's general-chat regression while keeping its math. The soup_blend_a085 reasoning model (v1). |
| 8 | STaR self-improvement + soup-recovery (v2, 2026-07-08) | step 7 model | Rejection-sampled, verified-correct GSM8K <think> traces (the model's own, filtered by a \boxed{} checker) + a general/no-think anchor; then a training-free soup 0.4 · (step 7) + 0.6 · (STaR model) | STaR: fine-tunes on the model's own correct solutions. The third soup recovers the no-think multi-step arithmetic the STaR step regressed (e.g. divisor-counting), keeping general chat intact. |
| 9 | SHORT-trace termination + procedure distillation → cross-soup (v3, 2026-07-11) | dpo_soup (step-5 pre-CoT) → CoT-SFT → think_v6; then cross-soup with v2 | cot_sft_mix_v6: short-only (≤768-token) closed-correct traces — drops the contaminated easy_gsm8k and adds a contamination-safe gsm8k-train-only short procedure tier (canonicalized \boxed{} close). Ship = training-free cross-soup 0.4 · think_v6 + 0.6 · v2 | Short-only SFT makes greedy natively close </think> with the answer (turns the decode-time budget-force win into a weights-level win) and installs grade-school procedure; the cross-soup with v2 keeps v2's self-consistency diversity. Clean SVAMP/ASDiv greedy +4.7/+4.6, self-cons held. |
| 10 | External-teacher distillation + tool/coding → cross-soup (v4, 2026-07-12) | dpo_soup → CoT-SFT (cot_sft_mix_v7) → think_v7; then cross-soup with v3 | cot_sft_mix_v7 (~35.6k): the v6 short-only backbone + teacher_gsm (Qwen3-4B's correct gsm8k-train solutions, 3,714) + code_magicoder (decontaminated code) + synthesized tool_calc (calculator/python tool-use). Ship = training-free cross-soup 0.3 · think_v7 + 0.6·… (0.7 · v3) | Distills a stronger teacher's worked solutions into the model (self-STaR had saturated). Lifts greedy ASDiv (25.8→30.5) + native termination; self-consistency regressed ~6 pts (a trade). Tool-calling learned in think_v7 but not shipped in the soup (see Tool use); coding did not transfer at 2.88B. |
The soups are the key idea. The CoT-SFT model (step 6) and the DPO model (step 5) live in the same optimization basin (step 6 fine-tunes step 5), so CoT-SFT = DPO + Δ for a chain-of-thought weight-delta Δ. Blending back 15% of the DPO weights (0.85 · CoT-SFT + 0.15 · DPO) scales that delta down just enough to remove the loop/forgetting pathology the CoT stage introduced — the grammar loop disappears, lost facts (e.g. "the Red Planet is Mars") return — without hurting the 10/10 math. α = 0.85 is a knee: lower values recover even more general chat but start breaking <think> trace-closure (the CoT format itself lives in Δ). The same recovery trick is reused after each self-improvement round (steps 8 and 9).
Chain-of-thought SFT data
v3 (cot_sft_mix_v6, ~26.4k examples, all ≤768 tokens). Deliberately short-only — training on short, terminating traces is what teaches greedy to natively close </think> (the fix for non-termination). The contaminated easy_gsm8k tier is dropped and replaced with a contamination-safe gsm8k-train-only procedure tier; every long tier from v3-mix is removed.
| Tier | Share | Source |
|---|
direct_tulu (no-think chat) | 30.3% | allenai/tulu-3-sft-mixture |
gsm8k_train_short (NEW, contamination-safe) | 16.4% | openai/gsm8k (main) — train split only, ≤512 tok, verified closed+boxed, canonicalized to the deployed \boxed{} close |
synth_arith | 9.5% | Synthetic, correct-by-construction |
ms_algebra / ms_series / ms_geometry / ms_divisors | ~18% | Synthetic multi-step (Python-verified) |
med_math | 7.6% | nlile/hendrycks-MATH-benchmark (levels 1–3) |
gen_ultrachat / hq_opus / med_openmath / hard_strict | small | ultrachat-derived / Opus / OpenMathReasoning / MiniMax-M2.1, all ≤768 tok |
v1/v2 (cot_sft_mix_v3, ~113k examples). The mix used for pipeline step 6 (still the basis of v1/v2):
| Tier | Rows | Source |
|---|
direct_tulu (no-think chat) | 34,000 | allenai/tulu-3-sft-mixture |
synth_arith | 15,000 | Synthetic, correct-by-construction |
gen_ultrachat (CoT-augmented) | 15,000 | Derived from HuggingFaceH4/ultrachat_200k |
hard_strict | 12,000 | PursuitOfDataScience/MiniMax-M2.1-Mixture-of-Thoughts (open-ended, strict-filtered) |
easy_gsm8k (dropped in v3 — contaminated) | 8,402 | openai/gsm8k (main), curated with <think> / \boxed{} |
med_math | 5,729 | nlile/hendrycks-MATH-benchmark (levels 1–3) |
ms_algebra | 5,000 | Synthetic multi-step (Python-verified) |
ms_series | 5,000 | Synthetic multi-step (Python-verified) |
ms_geometry | 5,000 | Synthetic multi-step (Python-verified) |
med_openmath | 4,620 | Problems from nvidia/OpenMathReasoning (CoT subset); solutions regenerated |
hq_opus | 2,300 | nohurry/Opus-4.6-Reasoning-3000x-filtered |
ms_divisors | 1,290 | Synthetic multi-step (Python-verified) |
Every example is capped at 4,000 tokens (768 for v3); all synthetic and ms_* traces are re-verified with a \boxed{} answer extractor.
Key hyperparameters
| Stage | LR | Epochs | Effective batch | Ctx | θ |
|---|
| SFT | 2e-5 | 1 | 18 | 13,568 | 1e6 |
| DPO | 1e-6 (β = 0.03) | 1 | 8 | 13,568 | 1e6 |
| CoT-SFT (v1/v2) | 1e-5 | 1 | 12 (3× H200 DDP) | 13,568 | 1e6 |
| CoT-SFT (v3, short-only) | 1e-5 | 1 | 12 (1× H100) | 13,568 | 1e6 |
Datasets used (all stages)
- HuggingFaceFW/fineweb — pretraining + intermix general half (crawl
CC-MAIN-2025-21).
- HuggingFaceTB/finemath (
finemath-4plus) — intermix math half.
- HuggingFaceH4/ultrachat_200k — SFT, and the
gen_ultrachat CoT tier.
- KatoHF/chatbot_arena_binarized — DPO preferences.
- allenai/tulu-3-sft-mixture — CoT
direct_tulu no-think tier.
- openai/gsm8k (
main) — CoT easy_gsm8k tier (v1/v2, contaminated) and the v3 gsm8k_train_short tier (train split only).
- nvidia/OpenMathReasoning — CoT
med_openmath tier.
- nlile/hendrycks-MATH-benchmark — CoT
med_math tier.
- nohurry/Opus-4.6-Reasoning-3000x-filtered — CoT
hq_opus tier.
- PursuitOfDataScience/MiniMax-M2.1-Mixture-of-Thoughts — CoT
hard_strict tier.
Fully synthetic (no external dataset): synth_arith, ms_algebra, ms_series, ms_geometry, ms_divisors.
Model architecture
| Component | Specification |
|---|
| Parameters | 2,882,162,688 (~2.88B) |
| Layers | 24 transformer blocks |
| Hidden size | 3,072 |
| Attention heads | 12 query / 4 key-value (GQA) |
| Head dimension | 256 |
| Feed-forward | SwiGLU MLP, 8,192 intermediate dim |
| Attention pattern | Interleaved local/global causal attention |
| Normalization | RMSNorm with QK / V / sandwich norms |
| Position encoding | RoPE (θ = 1,000,000) |
| Logit stabilization | Final logit softcap = 15.0 |
| Context length | 13,568 tokens (RoPE-extrapolated from a 1,024-ctx base) |
| Vocabulary size | 151,669 |
| Tied embeddings | Yes (input ↔ output) |
| Precision | bf16 safetensor shards + model.safetensors.index.json |
Tokenizer
Reuses the Qwen3 tokenizer (vocab 151,669) via the Qwen2Tokenizer compatibility class. The chat template (chat_template.jinja) supports enable_thinking and parses <think> … </think>. Tokenizer files are bundled — no extra download needed.
Evaluation
Internal 4-quadrant probe, 10 items each, graded leniently (greedy for no-think, sampled for with-CoT):
| Quadrant | Score |
|---|
| Math, no-think (greedy) | 10 / 10 |
| Math, with-CoT (sampled) | 10 / 10 |
| General, no-think (greedy) | 7 / 10 |
| General, with-CoT (sampled) | 6 / 10 |
| Total | 33 / 40 |
The final weight-soup lifts general no-think from 5→7 vs. the pre-soup CoT model (the grammar loop is gone; the "Red Planet = Mars" fact is restored) while keeping math perfect. The residual general misses (e.g. naming the third primary color, a taller-than transitivity puzzle) are genuine capability gaps of the 2.88B base — present already before CoT training — and are not fixable by souping, decoding, or data changes at this scale.
Guardrail note (v2 / v3): this 4-quadrant probe was measured on v1. Each self-improvement round is gated to preserve the general/no-think axes (verified head-to-head) while improving the held-out math path; the honest math signal is the clean SVAMP/ASDiv numbers below, not this small hand-checked probe. The v3 no-think guardrail vs v2: general no-think unchanged (identical successes and identical residual base-gaps — no new loops, no lost facts) and math no-think 9/10, with one regression (divisor-counting) documented under Limitations.
Benchmarks (lm-evaluation-harness)
⚠ GSM8K contamination (disclosed 2026-07-10). The CoT-SFT data tier easy_gsm8k was built from a curated GSM8K shard that pooled the train and test splits with no split filter, so a large fraction of the GSM8K test set — with worked <think>/\boxed{} solutions — was seen during training; the v2 STaR step also trained on GSM8K problems. GSM8K is therefore not a valid held-out benchmark for this model; its rows below are marked ⚠ and should not be read as held-out. (v3 removes easy_gsm8k and trains only on the GSM8K train split, keeping the SVAMP/ASDiv eval disjoint — but GSM8K itself remains off-limits as a held-out metric.) For an honest held-out math signal, see the SVAMP / ASDiv numbers under Getting more accuracy: test-time compute. The knowledge/commonsense tasks (ARC, HellaSwag, MMLU, TruthfulQA, WinoGrande, SciQ, PIQA, …) are unaffected — standard academic benchmarks not used in any training stage.
Standard academic benchmarks via
EleutherAI lm-evaluation-harness v0.4.11, run through its
vLLM backend (continuous batching) — bf16, greedy for generative tasks (no repetition penalty; see the decoding note above), completion-style prompting (no chat template, for comparability).
v1 → v2. Both checkpoints are shown: the previous release (soup_blend_a085, v1) and the v2 upload (blend_star_a06). The STaR + soup-recovery step (pipeline step 8) lifts the math path while every knowledge/commonsense task is unchanged (the STaR delta is math-only). v3 (step 9) is again expected to be a math-only upgrade — knowledge/commonsense tasks unchanged — with the improvement measured on clean SVAMP/ASDiv, not GSM8K.
Open LLM Leaderboard v1 + GSM8K
| Benchmark | Setup | v1 | v2 |
|---|
| ARC-Challenge | 25-shot, acc_norm | 34.0 | 34.2 |
| HellaSwag | 10-shot, acc_norm | 58.7 | 58.6 |
| MMLU | 5-shot, acc | 25.0 | 25.0 |
| TruthfulQA (MC2) | 0-shot | 45.1 | 45.4 |
| WinoGrande | 5-shot, acc | 57.9 | 57.8 |
| GSM8K ⚠contaminated | 5-shot, exact-match | 6.2 | 7.2 |
| Average (incl. contaminated GSM8K⚠) | | 37.8 | 38.0 |
(The lm-eval table below was not re-run for v3; the v3 change is a math-focused CoT-SFT + weight-soup, so these knowledge/commonsense rows are expected within noise of v2. The v3 improvement is measured on clean SVAMP/ASDiv — see Getting more accuracy above.)
Additional benchmarks (0-shot)
| Benchmark | Metric | v1 | v2 |
|---|
| SciQ | acc | 82.9 | 83.2 |
| PIQA | acc | 72.3 | 72.4 |
| BoolQ | acc | 62.3 | 62.4 |
| ARC-Easy | acc | 55.3 | 55.7 |
| LAMBADA (OpenAI) | acc / ppl | 44.6 / 16.7 | 45.3 / 16.8 |
| OpenBookQA | acc_norm | 35.2 | 34.6 |
| CommonsenseQA | acc | 20.1 | 20.1 |
Reading these numbers (2.88B, from scratch):
- Real commonsense/science signal: SciQ 82.9, PIQA 72.3, HellaSwag 58.7, BoolQ 62.3, ARC-Easy 55.3 — the from-scratch base is not hollow.
- At/near chance where knowledge-dense pretraining is required: MMLU 25.0 and CommonsenseQA 20.1 (≈ 5-way random) — the base was pretrained on FineWeb + math only.
- GSM8K is contaminated — do not read it as held-out (see the note above). For honest held-out math see the clean SVAMP/ASDiv numbers under Getting more accuracy: test-time compute.
- These are honest reference points for a small from-scratch reasoner, not a leaderboard flex.
(MathQA and LogiQA were skipped — their loaders use legacy dataset scripts unsupported by current datasets; GPQA is a gated dataset.)
Inference
1from transformers import AutoModelForCausalLM, AutoTokenizer
2import torch
3
4model_id = "PursuitOfDataScience/Argonne-3.0-think"
5
6tokenizer = AutoTokenizer.from_pretrained(model_id, trust_remote_code=True)
7model = AutoModelForCausalLM.from_pretrained(
8 model_id,
9 trust_remote_code=True,
10 dtype=torch.bfloat16,
11)
12device = "cuda" if torch.cuda.is_available() else "cpu"
13model = model.to(device).eval()
14
15# --- Math / factual: GREEDY, no anti-repeat penalty ---
16messages = [{"role": "user", "content": "What is 15% of 80?"}]
17prompt_ids = tokenizer.apply_chat_template(
18 messages,
19 tokenize=True,
20 add_generation_prompt=True,
21 enable_thinking=True, # set False to answer directly (also 10/10 on math)
22)
23input_ids = torch.tensor([prompt_ids], dtype=torch.long, device=device)
24
25output_ids = model.generate(
26 input_ids,
27 max_length=input_ids.shape[1] + 512,
28 do_sample=False, # greedy — best for arithmetic
29)
30print(tokenizer.decode(output_ids[0], skip_special_tokens=True))
For open-ended general chat, mild sampling is fine (do_sample=True, temperature=0.7, top_p=0.9).
Recommended inference settings
| Task | do_sample | temperature | top_p | repetition_penalty | notes |
|---|
| Math / arithmetic | False (greedy) | — | — | 1.0 (off) | Do not use no_repeat_ngram — it corrupts multi-digit numbers. |
| No-think factual Q&A | False (greedy) | — | — | 1.0 | |
| Open-ended chat / brainstorming | True | 0.7 | 0.9 | ≤ 1.1 | Keep any repetition penalty mild. |
- Load with
trust_remote_code=True so the custom ArgonneModel / argonne2 classes (model.py) register.
- Use
apply_chat_template(..., enable_thinking=True) to elicit a <think> … </think> trace, or enable_thinking=False for a direct answer. Math is strong on the internal probe in both modes; for held-out benchmark numbers and how to get the most out of the model, see Getting more accuracy: test-time compute below.
- The custom
generate uses max_length (total length), not max_new_tokens.
- Weights are bf16 safetensor shards with a
model.safetensors.index.json weight map for sharded loading.
Getting more accuracy: test-time compute
The 33/40 internal probe (and "10/10 math") is a small, hand-checked sanity probe (10 items per quadrant): it shows the capability is present, not competition-grade math. For an honest held-out signal we use SVAMP and ASDiv — elementary math-word-problem benchmarks that appear in none of the training stages (unlike GSM8K, which is contaminated for this model — see the note under Benchmarks). The model holds substantial latent capability that cheap test-time compute unlocks:
| decoding (v2, with-think) | SVAMP (n=300) | ASDiv (n=300) |
|---|
| greedy, single sample | 18.0 | 22.7 |
+ budget-forcing (force-close </think> past a think-token budget) | 20.7 | 29.3 |
self-consistency (sample K=32, majority-vote the \boxed{} answer) | 36.3 | 51.0 |
| pass@32 (a correct answer is somewhere in 32 samples) | 73.3 | 74.3 |
v3 (2026-07-11, shipped): the goal — raise the greedy row toward the budget-force row (native termination) while holding self-consistency — is met:
| decoding (v3, with-think) | SVAMP (n=300) | ASDiv (n=300) |
|---|
| greedy, single sample | 22.7 (v2 18.0) | 27.3 (v2 22.7) |
| + budget-forcing | 24.3 | 32.3 |
| self-consistency (K=32) | 40.3 (v2 36.3) | 48.0 (v2 51.0) |
| pass@32 | 74.7 (v2 73.3) | 77.0 (v2 74.3) |
Greedy is now ≈ its own budget-forced number (the model terminates natively instead of rambling to max length), self-consistency is held, and pass@32 is up — a clean single-pass upgrade. Cost: one fragile no-think probe (divisor-counting) regressed — see Limitations.
v4 (2026-07-12, shipped) — broad held-out gate (n=400/set, +MAWPS & GSM-Plus, Wilson 95% CIs): v4 vs v3, both re-measured at n=400. The external-teacher distillation lifts greedy on ASDiv and holds pass@K, but self-consistency regressed on MAWPS — a trade, not a clean win:
| set — greedy / self-cons(K=32) / pass@32 | v3 | v4 |
|---|
| SVAMP (clean) | 23.5 / 39.5 / 75.5 | 20.5 / 38.0 / 76.3 |
| ASDiv (clean) | 25.8 / 47.3 / 76.0 | 30.5 / 47.8 / 78.0 |
| MAWPS (clean) | 21.3 / 45.3 / 78.8 | 21.5 / 40.0 / 78.0 |
| GSM-Plus (semi-clean, adversarial) | 9.3 / 12.8 / 46.8 | 8.3 / 12.8 / 47.0 |
Greedy ASDiv clearly up (teacher distillation landed), other greedy ≈ flat; self-consistency down on MAWPS (the code/tool/teacher diet cut sample diversity); pass@K held. This is an honest mixed result — v3 is retained upstream for rollback if the self-consistency path matters more for your use.
Read: on clean, never-trained problems the model is a genuine small reasoner — pass@32 of 73–74% shows the capability is real, not memorized. (A permutation null-control confirms this: against a magnitude-matched chance floor, the pass@32 and self-consistency scores clear the null by tens of points — the ceiling is genuine, not lucky small-integer collisions.) The dominant single-shot failure is non-termination (~half of greedy traces never close </think>), which is exactly why budget-forcing (force a stop) and self-consistency (vote over K samples) are the biggest free wins — and exactly what the v3 training round targets at the weights level.
Recommended recipe (single model): sample K ≈ 16–32 traces (temperature 0.8, top_p 0.95), force-close the <think> block if it runs past a token budget, then majority-vote the extracted \boxed{} answers — roughly 2× greedy at zero training cost. Among single-model pickers this is the best: neither a learned same-base verifier nor confidence-weighted / budget-forced voting beats plain majority vote (reliably judging a solution needs capability this 2.88B base lacks). For the highest accuracy, add a stronger external reranker — it nearly doubles the vote again (SVAMP/ASDiv ~75, ≈ the pass@32 ceiling); see Tool use & serving-system capabilities below.
Fast inference with vLLM
The custom argonne2 architecture (a Gemma2-style sandwich-norm layer + Qwen3 qk-norm + an extra value-norm + final logit soft-cap, full-causal, tied embeddings) ports cleanly to vLLM — validated numerically exact (token-for-token greedy) against the reference model.py. vLLM's continuous batching makes the large-K sampling above cheap (~65× the naive per-token HF decode loop, and it actually fills the GPU). The custom-model class is in the training repo.
Tool use & serving-system capabilities
The v4 round added tool-calling and coding training data, and studied the two ways to push this
small model further at inference (both are serving-system components in the training repo, not baked into
the single shipped card):
-
Tool-calling (calculator / python). The v4 training checkpoint (
think_v7) learned the format
cleanly — on held-out arithmetic it emits a
100%-valid <tool_call> with the correct expression. But
(a) that behavior
dilutes out of the conservative shipped soup (v4 emits ~0% tool calls), and (b) if
the model
generates its own <tool_response> it hallucinates the result (~53% correct). The fix is a
real tool-execution loop —
reasoning/tool_decode.py: stop generation at
</tool_call>, actually execute the call,
inject the
real <tool_response>, and resume. With real execution,
think_v7 goes
53% → 100% on
held-out single-operation arithmetic (+46.7 pts). The chat template already renders the standard
tokenizer.apply_chat_template(..., tools=[…]) format, so the emitted calls are API-compatible.
(This is a
proof on tool-friendly single-op problems — it shows the arithmetic-offload mechanism works, not that
multi-step word problems become 100%.)
-
External-verifier best-of-N — the highest-accuracy recipe. For the pass@K → pass@1 selection gap
(the right answer is present in ~77–79% of 32 samples but the same-base majority vote only picks ~36–49%),
no same-base picker helps (majority vote / confidence-weighting / a same-base learned verifier all saturate
— the base can't reliably judge its own solutions). A stronger external reranker does: sample K=32 with
the shipped card, then have Qwen3-4B reason through each distinct candidate answer and keep the one it
verifies (ext_verify.py, "reasoned" lens). Validated on the shipped weights (v4), n=500, McNemar vs the
same-base vote (all p<0.001):
| clean set | same-base self-consistency (vote) | + Qwen3-4B reranker | pass@32 (ceiling) |
|---|
| SVAMP | 36.4 | 74.8 (+38.4) | 77.0 |
| ASDiv | 49.0 | 76.0 (+27.0) | 79.2 |
| MAWPS | 38.4 | 58.0 (+19.6) | 77.2 |
The reranker recovers
~97% of the pass@32 ceiling on SVAMP/ASDiv and lifts the deployable metric
~41 →
~70 on average (+28 pts) — including the MAWPS self-consistency that the v4 weights had traded away. Note
the judge must
reason: a 1-token "Yes/No" verifier scores
below the vote. This is a
2-model serving
win — the accuracy is the external reasoner's competence applied to this model's candidate set, not the
single 2.88B card unlocked. Tooling:
reasoning/ext_verify.py (two-phase generate → rerank).
Both point to the same lesson: on this 2.88B base, the remaining gains are serving-system moves (a tool
executor, an external reranker) or a stronger base — not further single-checkpoint weight edits. A broad
n=1000 held-out sweep (SVAMP/ASDiv/MAWPS/GSM-Plus) confirms this at the weight level: v3, v4, and every
weight-soup between them sit on one flat Pareto line — identical pass@32 (~78%, the capability ceiling is
fixed), trading only greedy ↔ self-consistency. No single-checkpoint edit improves both axes; the reranker
above is the way to cash the fixed ceiling.
Limitations
- 2.88B parameters — far smaller than frontier models; expect weaker performance on hard reasoning, long-form knowledge, and code.
- Base-capability gaps persist: some simple general questions (e.g. listing all three primary colors, multi-hop comparison puzzles) are answered incorrectly regardless of think mode — these are limits of the underlying pretraining, not of the reasoning recipe.
- v3 divisor-counting regression: v3's short-trace diet erodes one fragile synthetic capability — counting the number of divisors of an integer via prime factorization (e.g. "how many divisors does 12 have?") is answered correctly by v2 but garbled by v3. This is a single narrow templated pattern; broad held-out math (SVAMP/ASDiv) improved. Noted for transparency.
- v4 self-consistency trade: v4's external-teacher distillation + tool/coding diet improved greedy ASDiv (+4.7) and native termination but cut sample diversity, regressing self-consistency ~6 pts (mainly MAWPS) vs v3 — an honest mixed update, not a clean win. If your use relies on K-sample majority voting, v3 may serve you better; v3 (
x_v6v2_040) is retained upstream for rollback. Tool-calling and coding data were added but are not in this shipped card (see Tool use & serving-system capabilities).
- Anti-repeat decoding breaks math (see notes above) — a property of this small model's arithmetic being token-repetition-heavy.
- The selection gap is base-limited: the correct answer is present in ~73% of 32 samples but only picked ~36–51% of the time; no cheap picker (majority vote, confidence-weighting, a same-base learned verifier) closes this gap — it caps at the base's ability to judge a solution.
- Context extended via RoPE extrapolation; very-long-context retrieval may degrade.
- English-centric SFT/DPO data; limited multilingual ability. No safety filtering or content moderation has been applied.
Source code
All training code is on the
main branch of the Argonne repo:
https://github.com/PursuitOfDataScience/ArgonneAI
The custom architecture (ArgonneModel, model_type = argonne2) is bundled with this
model as model.py. The exact scripts that produced this checkpoint, by pipeline stage:
The SLURM launcher scripts that wire these together with per-stage hyperparameters are
intentionally untracked in the repo (they carry cluster-specific paths); every stage's
hyperparameters are recorded in
reasoning/thinking_training.md and summarized in the
tables above.
Citation
1@misc{argonne30think,
2 author = {PursuitOfDataScience},
3 title = {Argonne 3.0-think},
4 year = {2026},
5 publisher = {Hugging Face},
6 url = {https://huggingface.co/PursuitOfDataScience/Argonne-3.0-think}
7}