mathcompose / README.md
42e's picture
Upload folder using huggingface_hub
014b14c verified
|
Raw
History Blame Contribute Delete
6.13 kB
# mathcompose — two ≤4B math models that demonstrate the generator–verifier gap
**Thesis:** you can't make a 1.5B model *out-reason* a frontier model, but you can make a small
**specialist** win on the *easy side of the generator–verifier asymmetry* — and you can **measure the
asymmetry itself** with two small models that compose.
- **Model V — a generative process verifier.** Given a problem and a step-by-step solution, it emits
a paragraph-by-paragraph critique ending in `\boxed{k}` (0-based index of the first wrong step, or
`-1` if all correct). Evaluated on **ProcessBench** (objective harmonic-mean F1; target: beat
GPT-4o's ~61.9) with **PRMBench** as the adversarial robustness set.
- **Model G — a step-by-step solution generator.** Distilled from a frontier teacher and filtered so
only answer-correct traces survive.
- **The headline:** V reranks G's samples (V-weighted majority / best-of-n). We report the recovered
**generator–verifier gap** (`oracle pass@n − majority`) at ≤4B — the Weaver headroom result, but
ours.
Every core metric is an **objective checker** (step-label F1, boxed-answer equivalence) — **no
LLM-judge**, so there is no judge bias to argue about.
Both models share **one base** (`Qwen/Qwen2.5-Math-1.5B-Instruct`, apache-2.0) and **one training
path** (a generative verifier is just SFT), which is what makes a two-model build tractable.
---
## Why these choices (grounded in `notes/`)
- `notes/research-small-vs-large-math.md` finds the **only** clean sub-4B "beats GPT-4o" precedent is
process verification (GenPRM-1.5B on ProcessBench) → **V is the primary model**.
- The generator–verifier asymmetry is "the key lever" → **G + composition** turn two models into one
coherent demonstration.
- `notes/brainlift.md`: distill the *process* not the label, data quality over quantity, eval before
training → the whole pipeline follows this.
- Verified constraints baked in: base context is **4096 tokens**; `trl 1.7.1` has **no PRMTrainer**
(so V is generative SFT, not a discriminative PRM); transformers 5.x renamed `max_seq_length →
max_length` and `torch_dtype → dtype`.
## Layout
```
configs/ base.yaml + verifier_v.yaml + generator_g.yaml (extends base)
src/mathcompose/
common/ chat prompts (ProcessBench critic format), \boxed grading, config, io
teachers/ pluggable Anthropic/OpenAI teacher (+ offline DummyTeacher)
datagen/ PRM800K parsing, teacher critique synthesis, answer-filtered CoT, dedup
data/ V output schema + dataset builders (CLI)
eval/ ProcessBench, PRMBench, MATH, composition, runners, run.py (CLI)
train/ shared QLoRA SFT (train.py --task {v,g}) + colab_train.ipynb
infer/ demo.py (incl. base-vs-tuned side-by-side)
tests/ CPU smoke suite (26 tests) scripts/smoke_all.sh
```
## Quickstart
### 0. Prove the harness on CPU (no GPU, no key)
```bash
pip install -e .
./scripts/smoke_all.sh # fast logic tests
./scripts/smoke_all.sh --full # + tiny-model train/eval + HF dataset probes
```
### 1. Build the datasets (needs a teacher key)
The default teacher is the **promptlens gateway** (OpenAI-compatible). Copy
`.env.example``.env` and set `TFY_API_KEY=tfy-...` (auto-loaded). Verify with
`python scripts/check_teacher.py`. (Use `--teacher openai|anthropic` for native
providers instead.)
```bash
cp .env.example .env && $EDITOR .env # set TFY_API_KEY
# Model V: PRM800K first-error labels + teacher-synthesized critiques (labels stay authoritative)
python -m mathcompose.data.build_verifier_dataset --prm800k data/raw/prm800k/phase2_train.jsonl \
--teacher promptlens --limit 15000
# Model G: distill CoT, keep only answer-correct traces
python -m mathcompose.data.build_generator_dataset --source AI-MO/NuminaMath-CoT \
--teacher promptlens --limit 8000
```
Contamination against ProcessBench/MATH-500 is enforced automatically (`--no-dedup` to disable).
### 2. Train (GPU — free Colab T4 works; see `src/mathcompose/train/colab_train.ipynb`)
```bash
python -m mathcompose.train.train --task v --config configs/verifier_v.yaml
python -m mathcompose.train.train --task g --config configs/generator_g.yaml
```
### 3. Evaluate (objective, base vs tuned) + the composition
```bash
python -m mathcompose.eval.run processbench --tag base --maj-k 1
python -m mathcompose.eval.run processbench --adapter runs/verifier_v --tag tuned --maj-k 8
python -m mathcompose.eval.run prmbench --adapter runs/verifier_v --tag tuned
python -m mathcompose.eval.run math --adapter runs/generator_g --tag tuned
python -m mathcompose.eval.run compose --gen-adapter runs/generator_g --ver-adapter runs/verifier_v \
--dataset Maxwell-Jia/AIME_2024 --split train --problem-field Problem --answer-field Answer
python -m mathcompose.eval.run report # -> results/RESULTS.md
```
### 4. Demo (for the video)
```bash
python -m mathcompose.infer.demo --task v --adapter runs/verifier_v --compare \
--problem "..." --steps "step 0" "step 1 (wrong)"
```
## What runs where
| Piece | Where | Needs |
|---|---|---|
| Harness + smoke tests | this repo, CPU | nothing |
| Data generation | anywhere | a teacher API key (Anthropic/OpenAI) |
| QLoRA training | Colab/Modal/RunPod GPU | a CUDA GPU (free T4 ok) |
| Publishing datasets/models | — | your HF token |
| Demo video | — | you record; script in the plan |
## Honest framing (from the research note)
"Beats frontier" means **beats GPT-4o**, not o1-mini/o3. Sub-4B evidence is thin (most precedents are
7B) — expect a step down. The real, defensible claim is the **base-vs-tuned delta** and the
**composition lift**, both measured objectively. PRMBench is reported alongside ProcessBench as the
independent robustness check.
## License / attribution
Code: MIT. Training data derives from **PRM800K** (MIT, OpenAI) and **NuminaMath-CoT** (apache-2.0);
evals use **ProcessBench**, **PRMBench**, **MATH-500**, **AIME-2024** (all apache-2.0). Attribute
these in any published dataset/model card.