Update README.md
Browse files
README.md
CHANGED
|
@@ -1,3 +1,82 @@
|
|
| 1 |
---
|
| 2 |
license: apache-2.0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3 |
---
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
---
|
| 2 |
license: apache-2.0
|
| 3 |
+
base_model: Qwen/Qwen2.5-0.5B-Instruct
|
| 4 |
+
tags:
|
| 5 |
+
- reinforcement-learning
|
| 6 |
+
- grpo
|
| 7 |
+
- lora
|
| 8 |
+
- jax
|
| 9 |
+
- countdown
|
| 10 |
+
- reasoning
|
| 11 |
+
language:
|
| 12 |
+
- en
|
| 13 |
+
pipeline_tag: text-generation
|
| 14 |
---
|
| 15 |
+
|
| 16 |
+
# NanoZero Countdown LoRA — GRPO from scratch in JAX, on one free T4
|
| 17 |
+
|
| 18 |
+
A LoRA adapter for [Qwen2.5-0.5B-Instruct](https://huggingface.co/Qwen/Qwen2.5-0.5B-Instruct), RL-trained with **GRPO implemented from scratch in pure JAX** on the [Countdown task](https://huggingface.co/datasets/Jiayi-Pan/Countdown-Tasks-3to4) — a tinker-free reproduction of [rLLM](https://github.com/rllm-org/rllm)'s Countdown RL recipe that fits on a single free Colab T4 (16 GB).
|
| 19 |
+
|
| 20 |
+
**Code:** [github.com/Zayed024/nanozero-jax](https://github.com/Zayed024/nanozero-jax) — single-file model + GRPO, no training framework.
|
| 21 |
+
|
| 22 |
+
## Results
|
| 23 |
+
|
| 24 |
+
| | pass@1 (128 held-out Countdown problems, greedy) |
|
| 25 |
+
|---|---|
|
| 26 |
+
| Qwen2.5-0.5B-Instruct (baseline) | **0.00%** |
|
| 27 |
+
| + this adapter (200 GRPO steps) | **15.62%** |
|
| 28 |
+
|
| 29 |
+
The task: given numbers like `[3, 7, 11]` and a target like `28`, produce an arithmetic
|
| 30 |
+
equation using each number exactly once, in `<answer>...</answer>` tags. Reward is rLLM's
|
| 31 |
+
exact `compute_score` (1.0 correct / 0.1 valid-format / 0.0 no answer), vendored verbatim.
|
| 32 |
+
Training showed the TinyZero-style two-phase dynamic: format acquisition first (mean reward
|
| 33 |
+
0.01 → 0.10), then actual solving (solved% climbing from 0).
|
| 34 |
+
|
| 35 |
+
## Training setup
|
| 36 |
+
|
| 37 |
+
- **Algorithm:** GRPO — group-relative advantages (8 rollouts/prompt, z-scored), PPO-style
|
| 38 |
+
clipped policy gradient, k3 KL penalty to the frozen reference (β=0.001).
|
| 39 |
+
- **Adapter:** LoRA rank 16 on attention projections (q/k/v/o). The **reference model is
|
| 40 |
+
the same frozen base with adapters off** — one weight copy serves policy and reference;
|
| 41 |
+
B is zero-init so the policy starts exactly at the reference.
|
| 42 |
+
- **Budget:** 200 steps × (8 prompts × group 8) × 256 new tokens, temperature 1.0,
|
| 43 |
+
AdamW lr 1e-4, global-norm clip 1.0. ~40 s/step on a T4 after KV-caching.
|
| 44 |
+
- **Fitting 16 GB** (the point of the exercise): never materialize the full `[B, T, vocab]`
|
| 45 |
+
logits tensor (chunked LM head, ≈12 GB avoided), per-layer gradient checkpointing on the
|
| 46 |
+
differentiated pass, bit-exact KV-cache decoding, degenerate-group skip.
|
| 47 |
+
- **Forward-pass fidelity:** the from-scratch JAX Qwen2 matches HF logits to max
|
| 48 |
+
|diff| = 2.6e-4 (argmax agreement 1.000) on the same weights.
|
| 49 |
+
|
| 50 |
+
## Usage
|
| 51 |
+
|
| 52 |
+
The adapter is a plain `.npz` of LoRA A/B matrices keyed `"{layer}__{proj}__{A|B}"`
|
| 53 |
+
(projections `wq/wk/wv/wo`, applied as `W·x + (x·A)·B`). With the NanoZero code:
|
| 54 |
+
|
| 55 |
+
```python
|
| 56 |
+
import nanozero as nz
|
| 57 |
+
from huggingface_hub import hf_hub_download
|
| 58 |
+
|
| 59 |
+
params, cfg, path = nz.load_params("Qwen/Qwen2.5-0.5B-Instruct")
|
| 60 |
+
lora = nz.load_lora(hf_hub_download("Zayed024/nanozero-countdown-lora",
|
| 61 |
+
"nanozero_countdown_lora.npz"))
|
| 62 |
+
# generate with the adapter:
|
| 63 |
+
ids, mask, resp, lp = nz.generate(params, prompt_ids, prompt_mask, cfg,
|
| 64 |
+
max_new=256, key=key, eos_id=eos, pad_id=pad,
|
| 65 |
+
temperature=0.0, lora=lora)
|
| 66 |
+
```
|
| 67 |
+
|
| 68 |
+
(It is **not** a PEFT-format adapter; it pairs with the NanoZero codebase. Conversion to
|
| 69 |
+
PEFT is straightforward from the key layout above if you need it.)
|
| 70 |
+
|
| 71 |
+
## Intended use & limitations
|
| 72 |
+
|
| 73 |
+
Research/educational artifact demonstrating a minimal, verified GRPO pipeline. Trained
|
| 74 |
+
only on Countdown arithmetic — it improves equation-writing under the `<answer>` format
|
| 75 |
+
and nothing else; expect no gains (and possible format quirks) outside that task. Base
|
| 76 |
+
model license and usage terms apply.
|
| 77 |
+
|
| 78 |
+
## Acknowledgements
|
| 79 |
+
|
| 80 |
+
- Reward and recipe: [rLLM](https://github.com/rllm-org/rllm) (Berkeley Sky Computing Lab), `countdown_reward.py` vendored under Apache-2.0.
|
| 81 |
+
- Task data: [Jiayi-Pan/Countdown-Tasks-3to4](https://huggingface.co/datasets/Jiayi-Pan/Countdown-Tasks-3to4) (TinyZero).
|
| 82 |
+
- Base model: Qwen2.5-0.5B-Instruct.
|