HarleyCooper commited on
Commit
92f42c9
·
verified ·
1 Parent(s): 08c7807

Update README.md

Browse files
Files changed (1) hide show
  1. README.md +627 -293
README.md CHANGED
@@ -1,304 +1,638 @@
1
- # nanochat training report
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
 
3
- Generated: 2025-10-23 22:26:58
 
 
 
 
4
 
5
- ## Environment
 
 
6
 
7
- ### Git Information
8
- - Branch: main
9
- - Commit: f1e8954 (dirty)
10
- - Message: Document Hyperbolic setup and fix lite RL script
11
 
12
- ### Hardware
13
- - Platform: Linux
14
- - CPUs: 104 cores (104 logical)
15
- - Memory: 1007.4 GB
16
- - GPUs: 8x NVIDIA H100 80GB HBM3
17
- - GPU Memory: 633.7 GB total
18
- - CUDA Version: 12.8
19
- - Hourly Rate: $24.00/hour
20
 
21
- ### Software
22
- - Python: 3.10.12
23
- - PyTorch: 2.8.0+cu128
 
 
24
 
 
 
 
 
25
 
26
- ### Bloat
27
- - Characters: 474,203
28
- - Lines: 12,350
29
- - Files: 57
30
- - Tokens (approx): 118,550
31
- - Dependencies (uv.lock lines): 2,220
 
32
 
33
- Run started: 2025-10-23 22:27:01
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
 
35
  ---
36
 
37
- ## Tokenizer training
38
- timestamp: 2025-10-24 01:20:23
39
-
40
- - max_chars: 10,000,000,000
41
- - doc_cap: 10,000
42
- - vocab_size: 65,536
43
- - train_time: 167.3429
44
- - num_special_tokens: 9
45
- - token_bytes_min: 1
46
- - token_bytes_max: 32
47
- - token_bytes_mean: 6.9125
48
- - token_bytes_std: 2.8738
49
-
50
-
51
- ## Tokenizer evaluation
52
- timestamp: 2025-10-24 01:20:28
53
-
54
- ### Comparison with GPT-2
55
-
56
- | Text Type | Bytes | GPT-2 Tokens | GPT-2 Ratio | Ours Tokens | Ours Ratio | Relative Diff % |
57
- |-----------|-------|--------------|--------------|-------------|------------|-----------------|
58
- | news | 1819 | 404 | 4.50 | 371 | 4.90 | +8.2% |
59
- | korean | 893 | 745 | 1.20 | 723 | 1.24 | +3.0% |
60
- | code | 1259 | 576 | 2.19 | 492 | 2.56 | +14.6% |
61
- | math | 1834 | 936 | 1.96 | 966 | 1.90 | -3.2% |
62
- | science | 1112 | 260 | 4.28 | 223 | 4.99 | +14.2% |
63
- | fwe-train | 4208518 | 900364 | 4.67 | 856938 | 4.91 | +4.8% |
64
- | fwe-val | 5028883 | 1083776 | 4.64 | 1033017 | 4.87 | +4.7% |
65
-
66
- ### Comparison with GPT-4
67
-
68
- | Text Type | Bytes | GPT-4 Tokens | GPT-4 Ratio | Ours Tokens | Ours Ratio | Relative Diff % |
69
- |-----------|-------|--------------|--------------|-------------|------------|-----------------|
70
- | news | 1819 | 387 | 4.70 | 371 | 4.90 | +4.1% |
71
- | korean | 893 | 364 | 2.45 | 723 | 1.24 | -98.6% |
72
- | code | 1259 | 309 | 4.07 | 492 | 2.56 | -59.2% |
73
- | math | 1834 | 832 | 2.20 | 966 | 1.90 | -16.1% |
74
- | science | 1112 | 249 | 4.47 | 223 | 4.99 | +10.4% |
75
- | fwe-train | 4208518 | 874799 | 4.81 | 856938 | 4.91 | +2.0% |
76
- | fwe-val | 5028883 | 1054265 | 4.77 | 1033017 | 4.87 | +2.0% |
77
-
78
-
79
- ## Base model training
80
- timestamp: 2025-10-23 22:28:41
81
-
82
- - run: aquarat-20251023-222655
83
- - device_type:
84
- - depth: 8
85
- - max_seq_len: 2048
86
- - num_iterations: 200
87
- - target_flops: -1.0000
88
- - target_param_data_ratio: 20
89
- - device_batch_size: 32
90
- - total_batch_size: 524,288
91
- - embedding_lr: 0.2000
92
- - unembedding_lr: 0.0040
93
- - weight_decay: 0.0000
94
- - matrix_lr: 0.0200
95
- - grad_clip: 1.0000
96
- - eval_every: 250
97
- - eval_tokens: 10,485,760
98
- - core_metric_every: 2000
99
- - core_metric_max_per_task: 500
100
- - sample_every: 2000
101
- - model_tag:
102
- - Number of parameters: 92,274,688
103
- - Number of FLOPs per token: 4.529848e+08
104
- - Calculated number of iterations: 200
105
- - Number of training tokens: 104,857,600
106
- - Tokens : Params ratio: 1.1364
107
- - DDP world size: 8
108
- - warmup_ratio: 0.0000
109
- - warmdown_ratio: 0.2000
110
- - final_lr_frac: 0.0000
111
- - Minimum validation bpb: 1.2992
112
- - Final validation bpb: 1.2992
113
- - CORE metric estimate: 0.0135
114
- - MFU %: 21.07%
115
- - Total training flops: 4.749890e+16
116
- - Total training time: 0.39m
117
- - Peak memory usage: 19176.26MiB
118
-
119
-
120
- ## Base model loss
121
- timestamp: 2025-10-24 01:21:08
122
-
123
- - train bpb: 1.2967
124
- - val bpb: 1.3001
125
- - sample 0: <|bos|>The capital of France is the capital of the city of the city of the city of the city of the
126
- - sample 1: <|bos|>The chemical symbol of gold is a symbol of the world’s most important symbol of the world’s most important symbol
127
- - sample 2: <|bos|>If yesterday was Friday, then tomorrow will be a bit more than a few years, and then the next day, the next
128
- - sample 3: <|bos|>The opposite of hot is the same as the one of the two of the same kind of cold weather.
129
- - sample 4: <|bos|>The planets of the solar system are: 1.5 billion years ago, and the 1.5 billion years
130
- - sample 5: <|bos|>My favorite color is the color of the color of the color of the color of the color of the
131
- - sample 6: <|bos|>If 5*x + 3 = 13, then x is 3.5.5.5.5.5.5.5
132
-
133
-
134
- ## Base model evaluation
135
- timestamp: 2025-10-24 01:32:41
136
-
137
- - Model: base_model (step 200)
138
- - CORE metric: 0.0155
139
- - hellaswag_zeroshot: -0.0018
140
- - jeopardy: 0.0000
141
- - bigbench_qa_wikidata: 0.0005
142
- - arc_easy: 0.1246
143
- - arc_challenge: -0.0364
144
- - copa: -0.0400
145
- - commonsense_qa: -0.0053
146
- - piqa: 0.0794
147
- - openbook_qa: -0.0373
148
- - lambada_openai: 0.0190
149
- - hellaswag: -0.0067
150
- - winograd: 0.0842
151
- - winogrande: 0.0024
152
- - bigbench_dyck_languages: 0.0080
153
- - agi_eval_lsat_ar: 0.0326
154
- - bigbench_cs_algorithms: 0.0235
155
- - bigbench_operators: 0.0619
156
- - bigbench_repeat_copy_logic: 0.0000
157
- - squad: 0.0004
158
- - coqa: 0.0009
159
- - boolq: -0.1468
160
- - bigbench_language_identification: 0.1770
161
-
162
-
163
- ## Midtraining
164
- timestamp: 2025-10-23 22:30:54
165
-
166
- - run: aquarat-20251023-222655
167
- - device_type:
168
- - dtype: bfloat16
169
- - num_iterations: 200
170
- - max_seq_len: 2048
171
- - device_batch_size: 32
172
- - unembedding_lr: 0.0040
173
- - embedding_lr: 0.2000
174
- - matrix_lr: 0.0200
175
- - init_lr_frac: 1.0000
176
- - weight_decay: 0.0000
177
- - eval_every: 150
178
- - eval_tokens: 10,485,760
179
- - total_batch_size: 524,288
180
- - dry_run: 0
181
- - Number of iterations: 199
182
- - DDP world size: 8
183
- - Minimum validation bpb: 0.6738
184
-
185
-
186
- ## Chat evaluation mid
187
- timestamp: 2025-10-24 01:52:32
188
-
189
- - source: mid
190
- - task_name: GSM8K
191
- - dtype: bfloat16
192
- - temperature: 0.0000
193
- - max_new_tokens: 512
194
- - num_samples: 1
195
- - top_k: 50
196
- - batch_size: 8
197
- - model_tag: None
198
- - step: None
199
- - max_problems: None
200
- - device_type:
201
- - GSM8K: 0.0023
202
-
203
-
204
- ## Chat SFT
205
- timestamp: 2025-10-23 22:46:36
206
-
207
- - run: aquarat-20251023-224449
208
- - source: mid
209
- - device_type:
210
- - dtype: bfloat16
211
- - device_batch_size: 4
212
- - num_epochs: 1
213
- - num_iterations: -1
214
- - target_examples_per_step: 32
215
- - unembedding_lr: 0.0040
216
- - embedding_lr: 0.2000
217
- - matrix_lr: 0.0200
218
- - weight_decay: 0.0000
219
- - init_lr_frac: 0.0200
220
- - aqua_train_examples: 20,000
221
- - aqua_val_examples: 254
222
- - eval_every: 100
223
- - eval_steps: 100
224
- - eval_metrics_every: 200
225
- - eval_metrics_max_problems: 1024
226
- - Training rows: 41,839
227
- - Number of iterations: 1307
228
- - Training loss: 2.9144
229
- - Validation loss: 1.9120
230
-
231
-
232
- ## Chat evaluation sft
233
- timestamp: 2025-10-24 01:52:40
234
-
235
- - source: sft
236
- - task_name: AQUA
237
- - dtype: bfloat16
238
- - temperature: 0.0000
239
- - max_new_tokens: 512
240
- - num_samples: 1
241
- - top_k: 50
242
- - batch_size: 8
243
- - model_tag: None
244
- - step: None
245
- - max_problems: None
246
- - device_type:
247
- - AQUA: 0.2756
248
-
249
-
250
- ## Chat RL
251
- timestamp: 2025-10-24 01:01:09
252
-
253
- - run: aquarat-20251023-224750-rl
254
- - source: sft
255
- - dtype: bfloat16
256
- - device_batch_size: 1
257
- - examples_per_step: 16
258
- - num_samples: 4
259
- - max_new_tokens: 64
260
- - temperature: 0.7000
261
- - top_k: 50
262
- - unembedding_lr: 0.0040
263
- - embedding_lr: 0.2000
264
- - matrix_lr: 0.0200
265
- - weight_decay: 0.0000
266
- - init_lr_frac: 0.0500
267
- - num_epochs: 1
268
- - save_every: 60
269
- - eval_every: 60
270
- - eval_examples: 400
271
-
272
-
273
- ## Chat evaluation rl
274
- timestamp: 2025-10-24 04:11:26
275
-
276
- - source: rl
277
- - task_name: AQUA
278
- - dtype: bfloat16
279
- - temperature: 0.0000
280
- - max_new_tokens: 64
281
- - num_samples: 1
282
- - top_k: 50
283
- - batch_size: 8
284
- - model_tag: None
285
- - step: None
286
- - max_problems: None
287
- - device_type:
288
- - AQUA: 0.2717
289
-
290
-
291
- ## Summary
292
-
293
- - Characters: 474,203
294
- - Lines: 12,350
295
- - Files: 57
296
- - Tokens (approx): 118,550
297
- - Dependencies (uv.lock lines): 2,220
298
-
299
- | Metric | BASE | MID | SFT | RL |
300
- |-----------------|----------|----------|----------|----------|
301
- | CORE | 0.0155 | - | - | - |
302
- | GSM8K | - | 0.0023 | - | - |
303
-
304
- Total wall clock time: 3h25m
 
1
+ ---
2
+ language: en
3
+ license: mit
4
+ datasets:
5
+ - deepmind/aqua_rat
6
+ metrics:
7
+ - accuracy
8
+ tags:
9
+ - reinforcement-learning
10
+ - autoformalization
11
+ - education
12
+ - nanochat
13
+ ---
14
+
15
+ <div align="center">
16
+
17
+ ![AQuA-RAT Training](./aquarat2.png)
18
+
19
+ # nanochatAquaRat
20
+
21
+ **Training Language Models with Reinforcement Learning on Mathematical Reasoning**
22
+
23
+ [![GitHub](https://img.shields.io/badge/GitHub-Repository-blue?logo=github)](https://github.com/HarleyCoops/nanochatAquaRat)
24
+ [![License](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
25
+ [![Python 3.8+](https://img.shields.io/badge/Python-3.8+-blue.svg)](https://www.python.org/downloads/)
26
+
27
+ A modified version of [nanochat](https://github.com/karpathy/nanochat) trained with reinforcement learning on the [DeepMind AQuA-RAT dataset](https://huggingface.co/datasets/deepmind/aqua_rat) for algebraic reasoning and multiple-choice problem solving.
28
+
29
+ [Quick Start](#quick-start) • [Dataset](#dataset-structure) • [Modifications](#modifications-from-base-nanochat) • [Training](#training-pipeline) • [Results](#results)
30
+
31
+ </div>
32
+
33
+ ---
34
+
35
+ ## Table of Contents
36
+
37
+ - [Overview](#overview)
38
+ - [The Base: nanochat Framework](#the-base-nanochat-framework)
39
+ - [Dataset Structure](#dataset-structure)
40
+ - [Modifications from Base nanochat](#modifications-from-base-nanochat)
41
+ - [Training Pipeline](#training-pipeline)
42
+ - [Quick Start](#quick-start)
43
+ - [File Structure](#file-structure)
44
+ - [Monitoring & Visualization](#monitoring--visualization)
45
+ - [Results](#results)
46
+
47
+ ---
48
+
49
+ ## Overview
50
+
51
+ This project adapts the **nanochat** training framework (originally designed for GSM8K numerical reasoning) to work with **AQuA-RAT** (Algebra Question Answering with Rationales), a dataset of ~97,000 algebraic word problems with multiple-choice answers (A-E) and natural language solution rationales.
52
+
53
+ ### Why This Matters
54
+
55
+ - **Domain Transfer**: Demonstrates how to adapt a mathematical reasoning pipeline from free-form numeric answers to multiple-choice format
56
+ - **RL on Math**: Implements GRPO-style reinforcement learning with reward shaping for categorical outputs
57
+ - **Mechanistic Interpretability**: Integrates attention analysis during training to understand model reasoning patterns
58
+ - **Production-Ready**: Includes automated Lambda Labs and Hyperbolic Labs deployment helpers for cloud GPU training
59
+
60
+ ### Key Results
61
+
62
+ | Model | Parameters | Training Time | AQuA-RAT Dev Accuracy |
63
+ |-------|------------|---------------|----------------------|
64
+ | depth-8 | ~60M | 3-4 hours | 30-50% |
65
+ | depth-20 | ~561M | 6-8 hours | 40-60% |
66
+
67
+ ---
68
+
69
+ ## The Base: nanochat Framework
70
+
71
+ **nanochat** is a minimalist yet complete pipeline for training transformer language models from scratch, created by Andrej Karpathy. It implements:
72
+
73
+ - **Custom tokenizer**: BPE tokenizer written in Rust for performance
74
+ - **Training stages**: Pretraining → Mid-training → SFT → RL
75
+ - **Evaluation suite**: CORE benchmarks and task-specific metrics
76
+ - **Optimizations**: Memory-efficient training, gradient accumulation, distributed training
77
+
78
+ **Original focus**: Training on GSM8K (Grade School Math 8K) with free-form numeric answers.
79
+
80
+
81
+ ---
82
+
83
+ ## Dataset Structure
84
+
85
+ ### AQuA-RAT Format
86
+
87
+ The [DeepMind AQuA-RAT dataset](https://github.com/deepmind/AQuA) contains algebraic reasoning problems in JSON format:
88
+
89
+ ```json
90
+ {
91
+ "question": "A person is traveling at 20 km/hr and reached his destiny in 2.5 hr then find the distance?",
92
+ "options": [
93
+ "A) 53 km",
94
+ "B) 55 km",
95
+ "C) 52 km",
96
+ "D) 60 km",
97
+ "E) 50 km"
98
+ ],
99
+ "rationale": "The distance that the person traveled = 20 * 2.5 = 50 km. Answer: E",
100
+ "correct": "E"
101
+ }
102
+ ```
103
+
104
+ **Dataset splits**:
105
+ - Training: 97,467 problems
106
+ - Development: 254 problems
107
+ - Test: 254 problems
108
+
109
+ **Key characteristics**:
110
+ - Multiple-choice (A-E) format
111
+ - Algebraic word problems
112
+ - Natural language rationales
113
+ - Topics: arithmetic, algebra, geometry, probability
114
+
115
+ ### Comparison: GSM8K vs AQuA-RAT
116
+
117
+ | Aspect | GSM8K (Original) | AQuA-RAT (This Project) |
118
+ |--------|------------------|-------------------------|
119
+ | **Format** | Free-form numeric | Multiple choice (A-E) |
120
+ | **Answer** | Single number | Letter choice |
121
+ | **Size** | 8,500 problems | 97,700 problems |
122
+ | **Difficulty** | Elementary school | High school algebra |
123
+ | **Rationale** | Step-by-step | Natural language |
124
+ | **Evaluation** | Exact match on number | Categorical accuracy |
125
+
126
+ ---
127
+
128
+ ## Modifications from Base nanochat
129
+
130
+ To adapt nanochat from GSM8K to AQuA-RAT, we modified the following components:
131
+
132
+ ### 1. Dataset Loader (`scripts/prepare_aqua.py`)
133
+
134
+ **Created new file** to download and format AQuA-RAT:
135
+
136
+ ```python
137
+ # New file: scripts/prepare_aqua.py
138
+ ### 1. Dataset Preparation (`scripts/prepare_aqua.py`)
139
+
140
+ - Uses `datasets.load_dataset("deepmind/aqua_rat")` and optionally caps split sizes.
141
+ - Emits JSONL files (`train.jsonl`, `validation.jsonl`, `test.jsonl`) compatible with
142
+ the conversation schema used throughout nanochat.
143
+ - Defaults to `~/.cache/nanochat/aqua`, but accepts `--output_dir` overrides so
144
+ launchers can bundle their own artifact.
145
+
146
+ ```python
147
+ def format_example(row):
148
+ options = row["options"]
149
+ assistant_content = [
150
+ {"type": "text", "text": row["rationale"].strip()},
151
+ {"type": "text", "text": f"Answer: {row['correct'].strip().upper()}"},
152
+ ]
153
+ return {
154
+ "messages": [
155
+ {"role": "user", "content": _render_user_prompt(row["question"], options)},
156
+ {"role": "assistant", "content": assistant_content},
157
+ ],
158
+ "letters": letters,
159
+ "answer_letter": correct,
160
+ }
161
+ ```
162
+
163
+ ### 2. Task Module (`tasks/aqua.py`)
164
+
165
+ - Accepts optional `data_dir` (or `AQUA_DATA_DIR` / `NANOCHAT_AQUA_DIR`) so the task
166
+ can read the cached JSONL; otherwise falls back to Hugging Face.
167
+ - Provides `_render_user_prompt` to format the question/options using the common
168
+ multiple-choice helper and `_extract_letter` to score completions.
169
+ - Returns conversations whose assistant messages include both the rationale and a
170
+ final `Answer: <LETTER>` line for SFT, while `evaluate()` only cares about the letter.
171
+
172
+ ```python
173
+ def _extract_letter(text, default=None):
174
+ answer_match = re.search(r"answer\s*[:\-]\s*([A-E])", text, flags=re.IGNORECASE)
175
+ if answer_match:
176
+ return answer_match.group(1).upper()
177
+ match = LETTER_RE.search(text)
178
+ return match.group(1).upper() if match else default
179
+ ```
180
+
181
+ **Key differences from GSM8K**:
182
+ - Numeric extraction → Letter extraction
183
+ - Free-form answer → Fixed choices A-E
184
+ - Exact number match → Categorical match
185
+
186
+ ### 3. RL Training (`scripts/chat_rl.py`)
187
+
188
+ **Modified** to support both GSM8K and AQuA-RAT:
189
+
190
+ Key updates:
191
+
192
+ - `train_task` / `val_task` now instantiate `AQUA(...)` instead of `GSM8K(...)`.
193
+ - Rewards reuse the task's `evaluate()` helper so any completion containing
194
+ “Answer: X” (or the first bare letter) is scored correctly.
195
+ - The validation helper became `run_aqua_eval`, still reporting pass@k accuracy
196
+ across sampled completions.
197
+ - CLI overrides remain the same because the script continues to rely on the
198
+ nanochat configurator (`--run`, `--temperature`, `--max_new_tokens`, …).
199
+
200
+ ### 4. Evaluation (`scripts/chat_eval.py`)
201
+
202
+ - Registered `'AQUA'` in the task registry so `-a AQUA` just works.
203
+ - Added a 20% random-guess baseline when aggregating the ChatCORE metric.
204
+ - The categorical evaluation path reuses `run_categorical_eval`, clamping logits
205
+ to the available letters before scoring.
206
+
207
+ ### 5. Training Script (`run_aquarat_small.sh`)
208
+
209
+ **What changed vs upstream nanochat**:
210
+
211
+ ```bash
212
+ # (Optional) Cache the dataset locally as JSONL
213
+ python -m scripts.prepare_aqua --output_dir "$NANOCHAT_BASE_DIR/aqua"
214
+
215
+ # Mid-training now samples from the AQuA mixture
216
+ torchrun -m scripts.mid_train -- --run=demo --num_iterations=200
217
+
218
+ # SFT stage emphasises AQuA problems
219
+ torchrun -m scripts.sft_train -- --run=demo --aqua_train_examples=20000
220
+
221
+ # RL fine-tuning rewards the correct letter on AQuA-RAT
222
+ torchrun -m scripts.chat_rl -- --run=demo --temperature=0.7 --max_new_tokens=64
223
+ ```
224
+
225
+ - **`tasks/aqua.py`** loads AQuA-RAT either from Hugging Face or the cached JSONL
226
+ splits, formats questions as conversations, and scores completions by letter.
227
+ - **`scripts/mid_train.py`** extends the original Reasoning+Chat mixture with a
228
+ 50k slice of AQuA so the model sees multiple-choice algebra earlier.
229
+ - **`scripts/chat_sft.py`** replaces the GSM8K component with AQuA, keeping ARC,
230
+ SmolTalk, and identity prompts for general chat coverage.
231
+ - **`scripts/chat_rl.py`** retools the GRPO loop to sample, reward, and evaluate
232
+ AQuA answers (categorical accuracy instead of GSM8K free-form math).
233
+ - **`scripts/chat_eval.py`** registers the new AQuA task so `chat_eval` can report
234
+ categorical accuracy alongside ARC/MMLU/GSM8K/HumanEval.
235
+
236
+ ---
237
+
238
+ ## Training Pipeline
239
+
240
+ ### Stage 1: Base Pretraining (50-60% of time)
241
+
242
+ **What happens**: Model learns language from scratch on FineWeb corpus
243
+
244
+ ```bash
245
+ torchrun --nproc_per_node=8 -m scripts.base_train -- --depth=8
246
+ ```
247
+
248
+ **Duration**: 1.5-2 hours on 8x H100
249
+ **Output**: Base checkpoint with general language understanding
250
+ **Metrics**: Validation loss, CORE benchmark scores
251
+
252
+ ### Stage 2: Mid-Training (12-15% of time)
253
+
254
+ **What happens**: Teach conversation format and special tokens
255
+
256
+ ```bash
257
+ torchrun --nproc_per_node=8 -m scripts.mid_train
258
+ ```
259
+
260
+ **Duration**: 30 minutes
261
+ **Output**: Conversational checkpoint
262
+ **Metrics**: Format adherence, tool use capability
263
+
264
+ ### Stage 3: Supervised Fine-Tuning (12-15% of time)
265
+
266
+ **What happens**: Fine-tune on AQuA-RAT with ground-truth solutions
267
 
268
+ ```bash
269
+ torchrun --nproc_per_node=8 -m scripts.sft_train -- \
270
+ --aqua_train_examples=20000 \
271
+ --aqua_val_examples=254
272
+ ```
273
 
274
+ **Duration**: 30 minutes
275
+ **Output**: AQuA-tuned checkpoint
276
+ **Metrics**: Dev set accuracy (categorical)
277
 
278
+ ### Stage 4: Reinforcement Learning (12-15% of time)
 
 
 
279
 
280
+ **What happens**: Policy gradient learning with GRPO algorithm
 
 
 
 
 
 
 
281
 
282
+ ```bash
283
+ torchrun --nproc_per_node=1 -m scripts.chat_rl -- \
284
+ --temperature=0.7 \
285
+ --max_new_tokens=64
286
+ ```
287
 
288
+ **Duration**: 30 minutes
289
+ **Algorithm**: Group Relative Policy Optimization (GRPO)
290
+ **Reward**: +1.0 for correct letter, +0.1 for valid letter format
291
+ **Output**: RL-optimized checkpoint
292
 
293
+ **Logged metrics**:
294
+ - `rl/acc` - Accuracy on training samples
295
+ - `rl/mean_reward` - Average reward per generation
296
+ - `rl/kl_letter_mean` - KL divergence at decision point
297
+ - `rl/kl_sequence_mean` - Full sequence KL
298
+ - `rl/letter_margin_mean` - Confidence (logit gap)
299
+ - `attn/entropy_mean` - Attention mechanism patterns
300
 
301
+ ---
302
+
303
+ ## Quick Start
304
+
305
+ ### Repo Setup & Rust Toolchain
306
+
307
+ - Clone with submodules so the `rustbpe` tokenizer sources are present:
308
+ ```bash
309
+ git clone --recurse-submodules https://github.com/HarleyCoops/nanochatAquaRat.git
310
+ ```
311
+ For existing clones run `git submodule update --init --recursive` before building.
312
+ - Install Rust (needed for the tokenizer build). On Linux/macOS follow [https://rustup.rs](https://rustup.rs). On Windows, after installing rustup, ensure the toolchain is MSVC x86\_64 and the cargo bin directory is on `PATH`:
313
+ ```powershell
314
+ $env:Path += ";$env:USERPROFILE\.cargo\bin"
315
+ setx PATH "$env:Path"
316
+ setx CARGO_HOME "$env:USERPROFILE\.cargo"
317
+ setx RUSTUP_HOME "$env:USERPROFILE\.rustup"
318
+ rustup set default-host x86_64-pc-windows-msvc
319
+ rustup default stable-x86_64-pc-windows-msvc
320
+ cargo --version
321
+ rustup --version
322
+ ```
323
+ - Build the tokenizer once per machine:
324
+ ```bash
325
+ uv run maturin develop
326
+ ```
327
+
328
+ ### Option 1: Lambda Labs Cloud (Automated)
329
+
330
+ Use the automation helper for one-command deployment:
331
+
332
+ ```bash
333
+ # Set credentials
334
+ export LAMBDA_API_KEY='your-lambda-api-key'
335
+ export WANDB_API_KEY='your-wandb-api-key'
336
+
337
+ # Launch with auto-start
338
+ python scripts/launch_lambda_training.py \
339
+ --ssh-key-name your_lambda_ssh_key \
340
+ --instance-type gpu_8x_h100_sxm5 \
341
+ --region us-west-1 \
342
+ --auto-start \
343
+ --inject-env WANDB_API_KEY
344
+ ```
345
+
346
+ The script provisions the instance, clones this repository, sets up environment variables, and starts training in a tmux session.
347
+
348
+ **Monitor training**:
349
+ ```bash
350
+ # SSH to instance
351
+ ssh ubuntu@<INSTANCE_IP>
352
+
353
+ # Attach to tmux session
354
+ tmux attach -t nanochat-train
355
+
356
+ # Or view logs
357
+ tail -f ~/nanochatAquaRat/training.log
358
+ ```
359
+
360
+ ### Option 2: Hyperbolic Labs Cloud (Automated)
361
+
362
+ Spin up on-demand GPUs via Hyperbolic's marketplace API:
363
+
364
+ ```bash
365
+ # Set credentials
366
+ export HYPERBOLIC_API_KEY='your-hyperbolic-api-key'
367
+ export WANDB_API_KEY='your-wandb-api-key'
368
+
369
+ # Launch with auto-start
370
+ python scripts/launch_hyperbolic_training.py \
371
+ --gpu-count 1 \
372
+ --region us-east \
373
+ --auto-start \
374
+ --inject-env WANDB_API_KEY
375
+ ```
376
+
377
+ The launcher discovers an available node (respecting `--region`, `--supplier`, or `--max-price` filters), provisions it, copies your `.env`, and optionally starts training in tmux. Use `--list` to inspect available marketplace inventory without launching.
378
+
379
+ ### Option 3: Lambda Labs Cloud (Manual)
380
+
381
+ For step-by-step control, see [LAMBDA_MANUAL_SETUP.md](LAMBDA_MANUAL_SETUP.md).
382
+
383
+ **Quick summary**:
384
+ 1. Launch instance at https://cloud.lambdalabs.com/instances
385
+ 2. SSH to instance: `ssh ubuntu@<IP>`
386
+ 3. Clone repo: `git clone <repo-url> && cd nanochatAquaRat`
387
+ 4. Set up credentials: `echo "WANDB_API_KEY=..." > .env`
388
+ 5. Run training: `bash run_aquarat_small.sh`
389
+
390
+ ### Option 4: Hyperbolic VM (Manual)
391
+
392
+ For marketplace nodes without automation access, follow this lightweight bootstrap:
393
+
394
+ 1. Provision a GPU VM from the Hyperbolic console and copy the SSH command (including `-p <port>` and username).
395
+ 2. SSH in and install prerequisites:
396
+ ```bash
397
+ sudo apt-get update
398
+ sudo apt-get install -y git curl unzip build-essential python3 python3-venv tmux
399
+ git clone https://github.com/HarleyCoops/nanochatAquaRat.git
400
+ cd nanochatAquaRat
401
+ ```
402
+ 3. Create `.env` with the required keys (WANDB, GCS bucket, AQUA path) and upload your GCP service-account JSON to the VM, e.g. `scp -P <port> C:\path\to\credentials.json user@<ip>:/home/user/gcp-sa.json`.
403
+ 4. Install tooling and build the tokenizer:
404
+ ```bash
405
+ curl -LsSf https://astral.sh/uv/install.sh | sh
406
+ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain stable
407
+ source "$HOME/.cargo/env"
408
+ export PATH="$HOME/.local/bin:$PATH"
409
+ uv venv && uv sync --extra gpu
410
+ source .venv/bin/activate
411
+ uv run maturin develop
412
+ uv run python -m scripts.tok_train
413
+ ```
414
+ 5. Install the Google Cloud SDK, authenticate, and stage the cached AQuA splits (or regenerate them):
415
+ ```bash
416
+ curl -sSL https://sdk.cloud.google.com | bash
417
+ source "$HOME/.bashrc"
418
+ gcloud auth login --no-launch-browser
419
+ gcloud config set project <your-project-id>
420
+ gcloud storage cp gs://nanochat-aquarat-datasets/datasets/aqua/aqua_cache.zip .
421
+ unzip -o aqua_cache.zip -d ~/aqua_cache
422
+ export AQUA_DATA_DIR=$HOME/aqua_cache
423
+ ```
424
+ 6. Fetch the identity conversation bundle (required for SFT) and the evaluation bundle once so CORE metrics don’t fail:
425
+ ```bash
426
+ cd ~/.cache/nanochat
427
+ curl -L -o identity_conversations.jsonl https://karpathy-public.s3.us-west-2.amazonaws.com/identity_conversations.jsonl
428
+ curl -L -o eval_bundle.zip https://karpathy-public.s3.us-west-2.amazonaws.com/eval_bundle.zip
429
+ unzip -q eval_bundle.zip && rm eval_bundle.zip
430
+ cd ~/nanochatAquaRat
431
+ ```
432
+ 7. Launch the desired script, e.g. `CUDA_VISIBLE_DEVICES=0 bash run_aquarat_lite.sh` or the full `run_aquarat_small.sh`.
433
+ 8. Monitor training via tmux/W&B and terminate the VM from Hyperbolic when the run finishes to stop billing.
434
+
435
+ ### Option 4: Alternative Launcher Script
436
+
437
+ A simplified launcher is also available:
438
+
439
+ ```bash
440
+ export LAMBDA_API_KEY='your-key'
441
+ export WANDB_API_KEY='your-key'
442
+
443
+ python launch_lambda.py \
444
+ --instance-type gpu_8x_h100_sxm5 \
445
+ --region us-west-1
446
+ ```
447
+
448
+ See [QUICKSTART.md](QUICKSTART.md) for details.
449
+
450
+ ### Option 5: Local/Custom Setup
451
+
452
+ ```bash
453
+ # Setup environment
454
+ cp .env.template .env
455
+ # Edit .env with your WANDB_API_KEY
456
+
457
+ # Run training
458
+ bash run_aquarat_small.sh
459
+ ```
460
+
461
+ **Requirements**:
462
+ - Python 3.8+
463
+ - CUDA GPUs (8x recommended)
464
+ - 40GB+ GPU memory per GPU
465
+ - ~100GB disk space
466
+
467
+ ---
468
+
469
+ ## File Structure
470
+
471
+ ```
472
+ nanochatAquaRat/
473
+ ├── nanochat/… # Vendored upstream nanochat package
474
+ ├── scripts/
475
+ │ ├── base_train.py # Base pretraining stage
476
+ │ ├── mid_train.py # Mid-training (now includes AQuA)
477
+ │ ├── chat_sft.py # Chat SFT pipeline
478
+ │ ├── sft_train.py # Shim so `-m scripts.sft_train` still works
479
+ │ ├── chat_rl.py # Reinforcement learning on AQuA-RAT
480
+ │ ├── chat_eval.py # Evaluation harness (adds AQuA task)
481
+ │ ├── prepare_aqua.py # AQuA-RAT JSONL exporter
482
+ │ ├── launch_lambda_training.py # Lambda Labs automation
483
+ │ ├── launch_hyperbolic_training.py # Hyperbolic Labs automation
484
+ │ └── upload_to_gcs.sh # Artifact helper
485
+ ├── tasks/
486
+ │ ├── aqua.py # AQuA-RAT task implementation
487
+ │ ├── arc.py / gsm8k.py / mmlu.py # Other reasoning tasks
488
+ │ └── …
489
+ ├── run_aquarat_small.sh # End-to-end orchestration
490
+ ├── pyproject.toml / uv.lock # Environment definitions
491
+ └── README.md
492
+ ```
493
+ ### Summary of Code Changes
494
+
495
+ | File | Type | Description |
496
+ |------|------|-------------|
497
+ | `tasks/aqua.py` | NEW | Conversation + evaluation wrapper for AQuA-RAT |
498
+ | `scripts/prepare_aqua.py` | NEW | Materializes train/validation/test JSONL splits for offline use |
499
+ | `scripts/mid_train.py` | MODIFIED | Adds AQuA to the mid-training mixture |
500
+ | `scripts/chat_sft.py` | MODIFIED | SFT mixture now includes AQuA controls |
501
+ | `scripts/sft_train.py` | NEW | Thin compatibility shim around `chat_sft` |
502
+ | `scripts/chat_rl.py` | MODIFIED | RL loop retargeted from GSM8K to AQuA-RAT |
503
+ | `scripts/chat_eval.py` | MODIFIED | Registers AQuA for categorical evaluation |
504
+ | `run_aquarat_small.sh` | MODIFIED | Pipeline glue aligned with AQuA staging |
505
+ | `scripts/launch_hyperbolic_training.py` | NEW | Hyperbolic Labs automation helper |
506
+ | `launch_lambda.py` / `scripts/launch_lambda_training.py` | EXISTING | Lambda Labs support retained |
507
+
508
+ ---
509
+
510
+ ## Monitoring & Visualization
511
+
512
+ All metrics stream to [Weights & Biases](https://wandb.ai) in real-time:
513
+
514
+ **Training Metrics**:
515
+ - Loss curves (pretraining, SFT, RL)
516
+ - Learning rate schedules
517
+ - Gradient norms
518
+
519
+ **RL Metrics**:
520
+ - Policy performance (accuracy, rewards)
521
+ - KL divergence from initial policy
522
+ - Letter-choice distributions (A-E)
523
+ - Confidence margins
524
+
525
+ **Interpretability**:
526
+ - Attention heatmaps per layer
527
+ - Entropy evolution across training
528
+ - Token-level attention weights
529
+
530
+ Example W&B dashboard:
531
+ ```
532
+ rl/acc ━━━━━━━━━━ 0.45
533
+ rl/kl_letter_mean ━━━━━━━━━━ 0.12
534
+ rl/letter_margin_mean ━━━━━━━━━━ 2.34
535
+ attn/entropy_mean ━━━━━━━━━━ 3.21
536
+ ```
537
+
538
+ ---
539
+
540
+ ## Results
541
+
542
+ ### Model Configurations
543
+
544
+ | Depth | Parameters | Training Time | Best Instance Type | Estimated Cost |
545
+ |-------|------------|---------------|-------------------|----------------|
546
+ | 8 | ~60M | 3-4 hours | 1-2x A100 | ~$18-35 |
547
+ | 12 | ~180M | 4-5 hours | 4x A100 | ~$35-45 |
548
+ | 20 | ~561M | 6-8 hours | 8x H100 | ~$144-192 |
549
+ | 26 | ~1.1B | 10-12 hours | 8x H100 | ~$240-288 |
550
+
551
+ To change model depth, edit the `--depth` parameter in `run_aquarat_small.sh`.
552
+
553
+ ### Expected Performance
554
+
555
+ **After SFT** (before RL):
556
+ - Dev accuracy: 20-30% (depth-8), 30-40% (depth-20)
557
+ - Basic problem-solving capability
558
+ - Some format errors (invalid letters)
559
+
560
+ **After RL**:
561
+ - Dev accuracy: 30-50% (depth-8), 40-60% (depth-20)
562
+ - Improved reasoning coherence
563
+ - Better multiple-choice selection confidence
564
+ - Reduced format errors
565
+ - Stable attention patterns
566
+
567
+ ### Cost Management
568
+
569
+ Lambda Labs pricing (8x H100 SXM5 @ ~$24/hour):
570
+
571
+ | Model | Training Time | Total Cost |
572
+ |-------|---------------|------------|
573
+ | depth-8 (60M) | 3-4 hours | ~$96 |
574
+ | depth-20 (561M) | 6-8 hours | ~$192 |
575
+
576
+ Budget options:
577
+ - Test pipeline: 1x A10 @ $0.60/hr
578
+ - Small model: 2x A100 @ $4.40/hr
579
+ - Production: 8x H100 @ $24/hr
580
+
581
+ ---
582
+
583
+ ## Important Notes
584
+
585
+ ### For Lambda Labs Users
586
+ - **Always terminate instances** after training to avoid charges
587
+ - Monitor spending in the Lambda Labs dashboard
588
+ - Check instance availability before launching (high demand periods)
589
+
590
+ ### Known Limitations
591
+ - RL on AQuA-RAT is experimental; results may vary
592
+ - Attention logging adds ~5-10% overhead
593
+ - KL computation can be expensive with large batch sizes
594
+ - Smaller models (<100M params) may struggle with complex reasoning
595
+
596
+ ---
597
+
598
+ ## Documentation
599
+
600
+ - **[scripts/launch_lambda_training.py](scripts/launch_lambda_training.py)** - Full-featured automation
601
+ - **[scripts/launch_hyperbolic_training.py](scripts/launch_hyperbolic_training.py)** - Hyperbolic marketplace automation
602
+ - **[launch_lambda.py](launch_lambda.py)** - Simplified launcher
603
+ - **[QUICKSTART.md](QUICKSTART.md)** - Fast track guide
604
+ - **[LAMBDA_MANUAL_SETUP.md](LAMBDA_MANUAL_SETUP.md)** - Manual setup walkthrough
605
+ - **[GCS_UPLOAD_GUIDE.md](GCS_UPLOAD_GUIDE.md)** - Upload weights to Google Cloud Storage
606
+ - **[.env.template](.env.template)** - Environment configuration
607
+
608
+ ---
609
+
610
+ ## Contributing
611
+
612
+ This project is based on the nanochat framework. For issues specific to:
613
+ - **AQuA-RAT training**: Open an issue in this repository
614
+ - **Base nanochat framework**: Refer to the upstream nanochat project
615
+ - **Lambda Labs deployment**: See documentation above
616
+
617
+ ---
618
+
619
+ ## License
620
+
621
+ This project inherits the license from the base nanochat project.
622
+
623
+ ---
624
+
625
+ ## Acknowledgments
626
+
627
+ - **Andrej Karpathy** - nanochat framework
628
+ - **DeepMind** - AQuA-RAT dataset and mechanistic interpretability tools
629
+ - **Lambda Labs** - Cloud GPU infrastructure
630
+ - **Weights & Biases** - Experiment tracking and visualization
631
 
632
  ---
633
 
634
+ ## Support
635
+
636
+ - **Lambda Labs Support**: https://lambdalabs.com/support
637
+ - **Weights & Biases Docs**: https://docs.wandb.ai
638
+ - **Project Issues**: https://github.com/HarleyCoops/nanochatAquaRat/issues