Neithanvarvas commited on
Commit
f994e7a
·
verified ·
1 Parent(s): 534be73

[UPDATE] Replace weights with the V5 model; update paper, model card and evaluation results

Browse files
README.md CHANGED
@@ -23,15 +23,15 @@ metrics:
23
 
24
  ## 1. Model Overview
25
 
26
- **Character-Based Transformer (CBT)** is an 18.95M-parameter character-level Transformer whose tokens carry a rule-assigned two-dimensional (2D) coordinate $(p, \tau)$ used by **Decoupled 2D Rotary Position Embeddings (2D-RoPE)** alongside **Weight-Tied Recurrent Depth ($R = 3$)**.
27
 
28
- Trained on 1- to 25-digit arithmetic replay, multi-tool dialogues, and search copy, with random coordinate shift masking $k=45$ (macro column coordinates up to $p_{\max} = 25 + 45 = 70$), **CBT-18.95M** (`champion_final.pt`) achieves:
29
- - **100.0% (240/240; 95% Wilson CI [98.4, 100.0]%)** on random multi-carry sums from 16 to 50 digits, and **100.0% (18/18)** on structured 16- to 50-digit sums (including 50-digit cascading carry $99\dots99 + 1$). Digits 16–25 are seen in training; 30–50 digits are unseen.
30
- - **98.9% (89/90)** on in-distribution sums at 8, 12, and 15 digits (the single miss is at 15 digits).
31
- - **100.0% (20/20)** at 55 digits, then **70.0% (14/20)** at 60 digits, **40.0% (6/15)** at 70 digits, and **0.0%** at 80–100 digits (random sweep). A separate teacher-forced suite gives 80% at both 60 and 70 digits.
32
- - **Equalized 1–15d, $T=1024$ Control Study (12,800 Random Problems)**: When four equalized 100k models (`1D-RoPE Standard`, `1D-RoPE + Offset`, `1D-RoPE + Ruoss et al. 2023 Randomized Positions`, and `Decoupled 2D-RoPE k=32`) are trained on the exact same 1–15d dataset with $T=1024$ and evaluated on 200 random problems per length up to 100d, all three 1D/Ruoss variants score **0.0% (0/200, CI [0.0, 1.9]%)** across 16–100d, whereas equalized 2D-RoPE achieves **81.4% (977/1,200, CI [79.1, 83.5]%)** across 16–40d (up to 92.0% at 16d and 25d).
33
- - **100.0% (90/90)** on a 6-category multi-tool benchmark (the check counts tags only, not argument correctness); **80.8% (21/26)** tool routing and **50.0% (13/26)** exact argument extraction on a 26-case phrasing suite with audited entities.
34
- - **100.0% (18/18)** zero-shot OOD tool routing, with **55.6% (10/18)** exact argument copying on 18 fresh prompts.
35
 
36
  ---
37
 
@@ -39,61 +39,37 @@ Trained on 1- to 25-digit arithmetic replay, multi-tool dialogues, and search co
39
 
40
  | Parameter | Specification |
41
  | :--- | :--- |
42
- | **Model Name** | Character-Based Transformer (CBT-18.95M) |
43
- | **Total Parameters** | 18,946,560 (~18.95M) |
44
- | **Non-Embedding Parameters** | 18,887,680 (~18.89M) |
45
  | **Physical Layers (L)** | 6 |
46
- | **Recurrent Passes (R)** | 3 (Effective Depth = 18 layers) |
47
- | **Hidden Dimension (d_model)** | 512 |
48
- | **Attention Heads (H)** | 8 (Head dimension = 64) |
49
- | **Max Sequence Length (T)** | 1024 (Coordinate cache up to 4096) |
50
- | **Positional Embedding** | Decoupled 2D-RoPE (d/2 macro column $p$, d/2 micro step $\tau$; rule-assigned via `compute_2d_coords`) |
51
- | **Coordinate Shift Masking (k)** | $k = 45$ ($p_{\max} = 25 + 45 = 70$ during 1–25d arithmetic replay) |
52
- | **Vocabulary Size** | 115 (14 structural control tags + 101 ASCII characters) |
53
- | **Weight Tying** | W_te == W_lm_head |
54
-
55
- ---
56
-
57
- ## 3. Empirical Evaluation Benchmarks (Greedy Decoding)
58
-
59
- | Benchmark Suite | Scope / Test Cases | Final Score | 95% Wilson CI |
60
- | :--- | :--- | :--- | :--- |
61
- | **In-Distribution Sums (8, 12, 15 Digits)** | Seen in Training | **98.9% (89/90)** | [94.0, 99.8]% |
62
- | **16–50 Digit Structured Sums** | 18 Cases (incl. $99\dots99 + 1$) | **100.0% (18/18)** | [82.4, 100.0]% |
63
- | **16–50 Digit Random Multi-Carry Sweep** | 8 Lengths $\times$ 30 Cases ($n=240$) | **100.0% (240/240)** | [98.4, 100.0]% |
64
- | **55–70 Digit Random Sweep** | 55d: 20 cases; 60d: 20; 70d: 15 | 55d: **100.0%**; 60d: **70.0%**; 70d: **40.0%** | 55d [83.9, 100.0]%; 60d [48.1, 85.5]%; 70d [19.8, 64.3]% |
65
- | **80–100 Digit Random Sweep** | 10 Cases per length | **0.0%** | [0.0, 27.8]% |
66
- | **Multi-Tool Benchmark (6 Categories)** | 90 Dialogues (tag-presence check) | **100.0% (90/90)** | [95.9, 100.0]% |
67
- | **Multi-Tool Phrasing Routing** | 26 Audited Cases, 9 Schemas | **80.8% (21/26)** | [62.1, 91.5]% |
68
- | **Multi-Tool Phrasing Exact Arguments** | 26 Audited Cases | **50.0% (13/26)** | [32.1, 67.9]% |
69
- | **Zero-Shot OOD Routing** | 18 Fresh Prompts | **100.0% (18/18)** | [82.4, 100.0]% |
70
- | **Zero-Shot OOD Exact Argument Copy** | 18 Fresh Prompts | **55.6% (10/18)** | [33.7, 75.4]% |
71
 
72
  ---
73
 
74
- ## 4. Usage & Inference
75
 
76
- ### Local Quickstart
77
 
78
  ```python
79
  import torch
80
- from model import ScaledGPT, ScaledConfig
81
  from tokenizer import ScaledTokenizer
82
 
83
- # 1. Load configuration and model
84
- config = ScaledConfig()
85
- model = ScaledGPT(config)
86
-
87
- # 2. Load weights
88
- state_dict = torch.load("champion_final.pt", map_location="cpu", weights_only=True)
89
- model.load_state_dict(state_dict)
90
- model.eval()
91
-
92
- # 3. Initialize tokenizer
93
  tokenizer = ScaledTokenizer()
 
 
 
94
  ```
95
 
96
- ### Interactive CLI
97
 
98
  ```bash
99
  python interactive.py --ckpt champion_final.pt
@@ -101,6 +77,12 @@ python interactive.py --ckpt champion_final.pt
101
 
102
  ---
103
 
 
 
 
 
 
 
104
  ## 5. Citation
105
 
106
  ```bibtex
 
23
 
24
  ## 1. Model Overview
25
 
26
+ **Character-Based Transformer (CBT-18.95M)** is an 18.94M-parameter character-level Transformer (111-token vocabulary) whose tokens carry a rule-assigned two-dimensional coordinate $(p, \tau)$ used by **Decoupled 2D Rotary Position Embeddings (2D-RoPE)**, with weight-tied recurrent depth ($R = 3$). This release is the **V5 model** (`champion_final.pt`): pretraining, search-copy and all-tools fine-tuning, V4 fine-tuning, then a 23,927-step V5 fine-tuning on a decontaminated online stream (35% search copy, 20% arithmetic replay of 1-25 digits, the rest multi-tool and chat). Coordinate shift masking uses $k=45$, so $p_{\max} = 25 + 45 = 70$.
27
 
28
+ Results (greedy decoding; Wilson 95% CIs are in the paper and in `results/`):
29
+ - **Addition**, 30 random problems per length (70% uniform, 15% dense carry, 15% cascades), scored as teacher-forced greedy agreement with the gold scratchpad and answer: **150/150** at 4-16 digits, **60/60** at 20 and 25 digits (seen), **210/210** at 26-55 digits (unseen), **25/30** at 60 and **19/30** at 70 digits. Pooled over the unseen 26-70 digits: **254/270**.
30
+ - **Tool use**: **26/26** exact calls on a 26-prompt phrasing suite, **18/18** on 18 out-of-distribution prompts, and **30/30** exact copies of entities absent from the training corpus (unseen-30). The V5 data was broadened after the previous model's failures on the first two suites were seen, so the unseen-30 set is the cleaner evidence.
31
+ - **1D-RoPE control**: a twin with the same architecture, V5 data and step count but standard 1D-RoPE scores **0/270** at 26-70 digits and **73/74** exact tool calls. The 2D coordinates account for the arithmetic extrapolation, not for the tool-use results.
32
+ - **Baselines**: standard 1D-RoPE models trained on 1-12 digit sums score 0/30 at every length from 14 to 35 digits (character and BPE vocabularies; looped, hierarchical and hybrid variants too).
33
+
34
+ All results are single training runs. Details, limitations and the failure analysis are in the paper.
35
 
36
  ---
37
 
 
39
 
40
  | Parameter | Specification |
41
  | :--- | :--- |
42
+ | **Total Parameters** | 18,944,512 |
43
+ | **Non-Embedding Parameters** | 18,887,680 |
 
44
  | **Physical Layers (L)** | 6 |
45
+ | **Recurrent Passes (R)** | 3 (effective depth 18) |
46
+ | **Hidden Dimension** | 512 |
47
+ | **Attention Heads** | 8 (head dimension 64) |
48
+ | **Context** | 1024 tokens |
49
+ | **Positional Embedding** | Decoupled 2D-RoPE (half of each head rotated by place $p$, half by step $\tau$; rule-assigned) |
50
+ | **Coordinate Shift Masking** | $k = 45$ |
51
+ | **Vocabulary** | 111 (14 control tokens + 97 characters) |
52
+ | **Weight Tying** | input embedding = output projection |
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
 
54
  ---
55
 
56
+ ## 3. Usage
57
 
58
+ The file is a `torch.save` dictionary with the config and `model_state_dict`.
59
 
60
  ```python
61
  import torch
62
+ from model import ScaledGPT
63
  from tokenizer import ScaledTokenizer
64
 
65
+ ckpt = torch.load("champion_final.pt", map_location="cpu", weights_only=False)
 
 
 
 
 
 
 
 
 
66
  tokenizer = ScaledTokenizer()
67
+ model = ScaledGPT(ckpt["config"], tokenizer=tokenizer)
68
+ model.load_state_dict(ckpt["model_state_dict"])
69
+ model.eval()
70
  ```
71
 
72
+ Interactive CLI:
73
 
74
  ```bash
75
  python interactive.py --ckpt champion_final.pt
 
77
 
78
  ---
79
 
80
+ ## 4. Files
81
+
82
+ `champion_final.pt` (V5 model), source files for stand-alone execution, `RESEARCH_PAPER.md`, and the evaluation results in JSON.
83
+
84
+ ---
85
+
86
  ## 5. Citation
87
 
88
  ```bibtex
RESEARCH_PAPER.md CHANGED
The diff for this file is too large to render. See raw diff
 
cbt1d_v5_arithmetic.json ADDED
@@ -0,0 +1,224 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "checkpoint": "champion_model/checkpoints/1d/cbt_18m_1d_rope_R3_k45_sftv5.zip",
3
+ "max_train_operand_digits": 25,
4
+ "arithmetic": {
5
+ "per_length": {
6
+ "20": {
7
+ "digits": 20,
8
+ "mode": "teacher_forced",
9
+ "seen_in_training": true,
10
+ "n": 30,
11
+ "exact": 28,
12
+ "exact_ci": [
13
+ 78.7,
14
+ 98.2
15
+ ],
16
+ "think_exact": 28,
17
+ "think_ci": [
18
+ 78.7,
19
+ 98.2
20
+ ],
21
+ "gen_tokens": 0,
22
+ "elapsed_sec": 9.7
23
+ },
24
+ "25": {
25
+ "digits": 25,
26
+ "mode": "teacher_forced",
27
+ "seen_in_training": true,
28
+ "n": 30,
29
+ "exact": 29,
30
+ "exact_ci": [
31
+ 83.3,
32
+ 99.4
33
+ ],
34
+ "think_exact": 29,
35
+ "think_ci": [
36
+ 83.3,
37
+ 99.4
38
+ ],
39
+ "gen_tokens": 0,
40
+ "elapsed_sec": 12.08
41
+ },
42
+ "26": {
43
+ "digits": 26,
44
+ "mode": "teacher_forced",
45
+ "seen_in_training": false,
46
+ "n": 30,
47
+ "exact": 0,
48
+ "exact_ci": [
49
+ 0.0,
50
+ 11.4
51
+ ],
52
+ "think_exact": 0,
53
+ "think_ci": [
54
+ 0.0,
55
+ 11.4
56
+ ],
57
+ "gen_tokens": 0,
58
+ "elapsed_sec": 12.42
59
+ },
60
+ "30": {
61
+ "digits": 30,
62
+ "mode": "teacher_forced",
63
+ "seen_in_training": false,
64
+ "n": 30,
65
+ "exact": 0,
66
+ "exact_ci": [
67
+ 0.0,
68
+ 11.4
69
+ ],
70
+ "think_exact": 0,
71
+ "think_ci": [
72
+ 0.0,
73
+ 11.4
74
+ ],
75
+ "gen_tokens": 0,
76
+ "elapsed_sec": 14.01
77
+ },
78
+ "35": {
79
+ "digits": 35,
80
+ "mode": "teacher_forced",
81
+ "seen_in_training": false,
82
+ "n": 30,
83
+ "exact": 0,
84
+ "exact_ci": [
85
+ 0.0,
86
+ 11.4
87
+ ],
88
+ "think_exact": 0,
89
+ "think_ci": [
90
+ 0.0,
91
+ 11.4
92
+ ],
93
+ "gen_tokens": 0,
94
+ "elapsed_sec": 17.04
95
+ },
96
+ "40": {
97
+ "digits": 40,
98
+ "mode": "teacher_forced",
99
+ "seen_in_training": false,
100
+ "n": 30,
101
+ "exact": 0,
102
+ "exact_ci": [
103
+ 0.0,
104
+ 11.4
105
+ ],
106
+ "think_exact": 0,
107
+ "think_ci": [
108
+ 0.0,
109
+ 11.4
110
+ ],
111
+ "gen_tokens": 0,
112
+ "elapsed_sec": 19.7
113
+ },
114
+ "45": {
115
+ "digits": 45,
116
+ "mode": "teacher_forced",
117
+ "seen_in_training": false,
118
+ "n": 30,
119
+ "exact": 0,
120
+ "exact_ci": [
121
+ 0.0,
122
+ 11.4
123
+ ],
124
+ "think_exact": 0,
125
+ "think_ci": [
126
+ 0.0,
127
+ 11.4
128
+ ],
129
+ "gen_tokens": 0,
130
+ "elapsed_sec": 22.33
131
+ },
132
+ "50": {
133
+ "digits": 50,
134
+ "mode": "teacher_forced",
135
+ "seen_in_training": false,
136
+ "n": 30,
137
+ "exact": 0,
138
+ "exact_ci": [
139
+ 0.0,
140
+ 11.4
141
+ ],
142
+ "think_exact": 0,
143
+ "think_ci": [
144
+ 0.0,
145
+ 11.4
146
+ ],
147
+ "gen_tokens": 0,
148
+ "elapsed_sec": 23.61
149
+ },
150
+ "55": {
151
+ "digits": 55,
152
+ "mode": "teacher_forced",
153
+ "seen_in_training": false,
154
+ "n": 30,
155
+ "exact": 0,
156
+ "exact_ci": [
157
+ 0.0,
158
+ 11.4
159
+ ],
160
+ "think_exact": 0,
161
+ "think_ci": [
162
+ 0.0,
163
+ 11.4
164
+ ],
165
+ "gen_tokens": 0,
166
+ "elapsed_sec": 26.12
167
+ },
168
+ "60": {
169
+ "digits": 60,
170
+ "mode": "teacher_forced",
171
+ "seen_in_training": false,
172
+ "n": 30,
173
+ "exact": 0,
174
+ "exact_ci": [
175
+ 0.0,
176
+ 11.4
177
+ ],
178
+ "think_exact": 0,
179
+ "think_ci": [
180
+ 0.0,
181
+ 11.4
182
+ ],
183
+ "gen_tokens": 0,
184
+ "elapsed_sec": 28.45
185
+ },
186
+ "70": {
187
+ "digits": 70,
188
+ "mode": "teacher_forced",
189
+ "seen_in_training": false,
190
+ "n": 30,
191
+ "exact": 0,
192
+ "exact_ci": [
193
+ 0.0,
194
+ 11.4
195
+ ],
196
+ "think_exact": 0,
197
+ "think_ci": [
198
+ 0.0,
199
+ 11.4
200
+ ],
201
+ "gen_tokens": 0,
202
+ "elapsed_sec": 33.21
203
+ }
204
+ },
205
+ "summary": {
206
+ "unseen": {
207
+ "n": 270,
208
+ "exact": 0,
209
+ "exact_ci": [
210
+ 0.0,
211
+ 1.4
212
+ ]
213
+ },
214
+ "seen": {
215
+ "n": 60,
216
+ "exact": 57,
217
+ "exact_ci": [
218
+ 86.3,
219
+ 98.3
220
+ ]
221
+ }
222
+ }
223
+ }
224
+ }
champion_final.pt CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:634bf18ed4173bc73e58970c6e843fbb4ccec92fde2b12c01bbe2fe04fe85a13
3
- size 75800439
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:c6fab36eaadbc402441691ded7ed9e26990f3718e6cefcb5a889691b7fc3b9e5
3
+ size 75799812
champion_v3_arithmetic.json ADDED
@@ -0,0 +1,224 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "checkpoint": "champion_model/checkpoints/champion_v3_final.zip",
3
+ "max_train_operand_digits": 25,
4
+ "arithmetic": {
5
+ "per_length": {
6
+ "20": {
7
+ "digits": 20,
8
+ "mode": "teacher_forced",
9
+ "seen_in_training": true,
10
+ "n": 30,
11
+ "exact": 30,
12
+ "exact_ci": [
13
+ 88.6,
14
+ 100.0
15
+ ],
16
+ "think_exact": 30,
17
+ "think_ci": [
18
+ 88.6,
19
+ 100.0
20
+ ],
21
+ "gen_tokens": 0,
22
+ "elapsed_sec": 60.31
23
+ },
24
+ "25": {
25
+ "digits": 25,
26
+ "mode": "teacher_forced",
27
+ "seen_in_training": true,
28
+ "n": 30,
29
+ "exact": 30,
30
+ "exact_ci": [
31
+ 88.6,
32
+ 100.0
33
+ ],
34
+ "think_exact": 30,
35
+ "think_ci": [
36
+ 88.6,
37
+ 100.0
38
+ ],
39
+ "gen_tokens": 0,
40
+ "elapsed_sec": 59.46
41
+ },
42
+ "26": {
43
+ "digits": 26,
44
+ "mode": "teacher_forced",
45
+ "seen_in_training": false,
46
+ "n": 30,
47
+ "exact": 30,
48
+ "exact_ci": [
49
+ 88.6,
50
+ 100.0
51
+ ],
52
+ "think_exact": 30,
53
+ "think_ci": [
54
+ 88.6,
55
+ 100.0
56
+ ],
57
+ "gen_tokens": 0,
58
+ "elapsed_sec": 67.86
59
+ },
60
+ "30": {
61
+ "digits": 30,
62
+ "mode": "teacher_forced",
63
+ "seen_in_training": false,
64
+ "n": 30,
65
+ "exact": 30,
66
+ "exact_ci": [
67
+ 88.6,
68
+ 100.0
69
+ ],
70
+ "think_exact": 30,
71
+ "think_ci": [
72
+ 88.6,
73
+ 100.0
74
+ ],
75
+ "gen_tokens": 0,
76
+ "elapsed_sec": 63.91
77
+ },
78
+ "35": {
79
+ "digits": 35,
80
+ "mode": "teacher_forced",
81
+ "seen_in_training": false,
82
+ "n": 30,
83
+ "exact": 30,
84
+ "exact_ci": [
85
+ 88.6,
86
+ 100.0
87
+ ],
88
+ "think_exact": 30,
89
+ "think_ci": [
90
+ 88.6,
91
+ 100.0
92
+ ],
93
+ "gen_tokens": 0,
94
+ "elapsed_sec": 76.18
95
+ },
96
+ "40": {
97
+ "digits": 40,
98
+ "mode": "teacher_forced",
99
+ "seen_in_training": false,
100
+ "n": 30,
101
+ "exact": 30,
102
+ "exact_ci": [
103
+ 88.6,
104
+ 100.0
105
+ ],
106
+ "think_exact": 30,
107
+ "think_ci": [
108
+ 88.6,
109
+ 100.0
110
+ ],
111
+ "gen_tokens": 0,
112
+ "elapsed_sec": 84.75
113
+ },
114
+ "45": {
115
+ "digits": 45,
116
+ "mode": "teacher_forced",
117
+ "seen_in_training": false,
118
+ "n": 30,
119
+ "exact": 30,
120
+ "exact_ci": [
121
+ 88.6,
122
+ 100.0
123
+ ],
124
+ "think_exact": 30,
125
+ "think_ci": [
126
+ 88.6,
127
+ 100.0
128
+ ],
129
+ "gen_tokens": 0,
130
+ "elapsed_sec": 91.2
131
+ },
132
+ "50": {
133
+ "digits": 50,
134
+ "mode": "teacher_forced",
135
+ "seen_in_training": false,
136
+ "n": 30,
137
+ "exact": 30,
138
+ "exact_ci": [
139
+ 88.6,
140
+ 100.0
141
+ ],
142
+ "think_exact": 30,
143
+ "think_ci": [
144
+ 88.6,
145
+ 100.0
146
+ ],
147
+ "gen_tokens": 0,
148
+ "elapsed_sec": 115.78
149
+ },
150
+ "55": {
151
+ "digits": 55,
152
+ "mode": "teacher_forced",
153
+ "seen_in_training": false,
154
+ "n": 30,
155
+ "exact": 30,
156
+ "exact_ci": [
157
+ 88.6,
158
+ 100.0
159
+ ],
160
+ "think_exact": 30,
161
+ "think_ci": [
162
+ 88.6,
163
+ 100.0
164
+ ],
165
+ "gen_tokens": 0,
166
+ "elapsed_sec": 107.83
167
+ },
168
+ "60": {
169
+ "digits": 60,
170
+ "mode": "teacher_forced",
171
+ "seen_in_training": false,
172
+ "n": 30,
173
+ "exact": 25,
174
+ "exact_ci": [
175
+ 66.4,
176
+ 92.7
177
+ ],
178
+ "think_exact": 25,
179
+ "think_ci": [
180
+ 66.4,
181
+ 92.7
182
+ ],
183
+ "gen_tokens": 0,
184
+ "elapsed_sec": 120.42
185
+ },
186
+ "70": {
187
+ "digits": 70,
188
+ "mode": "teacher_forced",
189
+ "seen_in_training": false,
190
+ "n": 30,
191
+ "exact": 19,
192
+ "exact_ci": [
193
+ 45.5,
194
+ 78.1
195
+ ],
196
+ "think_exact": 19,
197
+ "think_ci": [
198
+ 45.5,
199
+ 78.1
200
+ ],
201
+ "gen_tokens": 0,
202
+ "elapsed_sec": 144.89
203
+ }
204
+ },
205
+ "summary": {
206
+ "unseen": {
207
+ "n": 270,
208
+ "exact": 254,
209
+ "exact_ci": [
210
+ 90.6,
211
+ 96.3
212
+ ]
213
+ },
214
+ "seen": {
215
+ "n": 60,
216
+ "exact": 60,
217
+ "exact_ci": [
218
+ 94.0,
219
+ 100.0
220
+ ]
221
+ }
222
+ }
223
+ }
224
+ }
champion_v3_arithmetic_4_16d.json ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "checkpoint": "checkpoints/cbt/cbt_18m_2d_rope_R3_k45_sftv5.pt",
3
+ "max_train_operand_digits": 25,
4
+ "arithmetic": {
5
+ "per_length": {
6
+ "4": {
7
+ "digits": 4,
8
+ "mode": "teacher_forced",
9
+ "seen_in_training": true,
10
+ "n": 30,
11
+ "exact": 30,
12
+ "exact_ci": [
13
+ 88.6,
14
+ 100.0
15
+ ],
16
+ "think_exact": 30,
17
+ "think_ci": [
18
+ 88.6,
19
+ 100.0
20
+ ],
21
+ "gen_tokens": 0,
22
+ "elapsed_sec": 3.29
23
+ },
24
+ "8": {
25
+ "digits": 8,
26
+ "mode": "teacher_forced",
27
+ "seen_in_training": true,
28
+ "n": 30,
29
+ "exact": 30,
30
+ "exact_ci": [
31
+ 88.6,
32
+ 100.0
33
+ ],
34
+ "think_exact": 30,
35
+ "think_ci": [
36
+ 88.6,
37
+ 100.0
38
+ ],
39
+ "gen_tokens": 0,
40
+ "elapsed_sec": 5.23
41
+ },
42
+ "12": {
43
+ "digits": 12,
44
+ "mode": "teacher_forced",
45
+ "seen_in_training": true,
46
+ "n": 30,
47
+ "exact": 30,
48
+ "exact_ci": [
49
+ 88.6,
50
+ 100.0
51
+ ],
52
+ "think_exact": 30,
53
+ "think_ci": [
54
+ 88.6,
55
+ 100.0
56
+ ],
57
+ "gen_tokens": 0,
58
+ "elapsed_sec": 6.68
59
+ },
60
+ "14": {
61
+ "digits": 14,
62
+ "mode": "teacher_forced",
63
+ "seen_in_training": true,
64
+ "n": 30,
65
+ "exact": 30,
66
+ "exact_ci": [
67
+ 88.6,
68
+ 100.0
69
+ ],
70
+ "think_exact": 30,
71
+ "think_ci": [
72
+ 88.6,
73
+ 100.0
74
+ ],
75
+ "gen_tokens": 0,
76
+ "elapsed_sec": 7.93
77
+ },
78
+ "16": {
79
+ "digits": 16,
80
+ "mode": "teacher_forced",
81
+ "seen_in_training": true,
82
+ "n": 30,
83
+ "exact": 30,
84
+ "exact_ci": [
85
+ 88.6,
86
+ 100.0
87
+ ],
88
+ "think_exact": 30,
89
+ "think_ci": [
90
+ 88.6,
91
+ 100.0
92
+ ],
93
+ "gen_tokens": 0,
94
+ "elapsed_sec": 8.82
95
+ }
96
+ },
97
+ "summary": {
98
+ "seen": {
99
+ "n": 150,
100
+ "exact": 150,
101
+ "exact_ci": [
102
+ 97.5,
103
+ 100.0
104
+ ]
105
+ }
106
+ }
107
+ }
108
+ }
champion_v3_ood.json ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "checkpoint": "champion_model/checkpoints/champion_v3_final.zip",
3
+ "max_train_operand_digits": 25,
4
+ "ood": {
5
+ "total": 18,
6
+ "routed": 18,
7
+ "routing_ci": [
8
+ 82.4,
9
+ 100.0
10
+ ],
11
+ "exact_matches": 18,
12
+ "exact_ci": [
13
+ 82.4,
14
+ 100.0
15
+ ]
16
+ }
17
+ }
champion_v3_phrasing.json ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "checkpoint": "champion_model/checkpoints/champion_v3_final.zip",
3
+ "max_train_operand_digits": 25,
4
+ "phrasing": {
5
+ "total": 26,
6
+ "routing_passed": 26,
7
+ "routing_ci": [
8
+ 87.1,
9
+ 100.0
10
+ ],
11
+ "exact_args_passed": 26,
12
+ "exact_args_ci": [
13
+ 87.1,
14
+ 100.0
15
+ ]
16
+ }
17
+ }
champion_v3_unseen_ood.json ADDED
@@ -0,0 +1,354 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "total": 30,
3
+ "routing_passed": 30,
4
+ "routing_pct": 100.0,
5
+ "routing_ci": [
6
+ 88.6,
7
+ 100.0
8
+ ],
9
+ "exact_copy_passed": 30,
10
+ "headline_exact_pct": 100.0,
11
+ "headline_exact_ci": [
12
+ 88.6,
13
+ 100.0
14
+ ],
15
+ "copy_given_routed_pct": 100.0,
16
+ "copy_given_routed_ci": [
17
+ 88.6,
18
+ 100.0
19
+ ],
20
+ "binomial_p_value_vs_50pct": 9.313225746154785e-10,
21
+ "is_statistically_gt_50pct": true,
22
+ "itemized": [
23
+ {
24
+ "id": 1,
25
+ "domain": "Unseen Figure",
26
+ "prompt": "<USER>Who was Baruch Spinoza?</USER><THINK>",
27
+ "expected_tool": "search",
28
+ "expected_arg": "Baruch Spinoza",
29
+ "raw_response": "The user is asking a factual question. I will query the search tool.</THINK><CALL>search(query=\"Baruch Spinoza\")</CALL>",
30
+ "parsed_call": "search(query=\"Baruch Spinoza\")",
31
+ "route_ok": true,
32
+ "exact_copy_ok": true
33
+ },
34
+ {
35
+ "id": 2,
36
+ "domain": "Unseen Figure",
37
+ "prompt": "<USER>Who was Hypatia of Alexandria?</USER><THINK>",
38
+ "expected_tool": "search",
39
+ "expected_arg": "Hypatia of Alexandria",
40
+ "raw_response": "The user is asking a factual question. I will query the search tool.</THINK><CALL>search(query=\"Hypatia of Alexandria\")</CALL>",
41
+ "parsed_call": "search(query=\"Hypatia of Alexandria\")",
42
+ "route_ok": true,
43
+ "exact_copy_ok": true
44
+ },
45
+ {
46
+ "id": 3,
47
+ "domain": "Unseen Figure",
48
+ "prompt": "<USER>Who was Ludwig van Beethoven?</USER><THINK>",
49
+ "expected_tool": "search",
50
+ "expected_arg": "Ludwig van Beethoven",
51
+ "raw_response": "The user is asking a factual question. I will query the search tool.</THINK><CALL>search(query=\"Ludwig van Beethoven\")</CALL>",
52
+ "parsed_call": "search(query=\"Ludwig van Beethoven\")",
53
+ "route_ok": true,
54
+ "exact_copy_ok": true
55
+ },
56
+ {
57
+ "id": 4,
58
+ "domain": "Unseen Figure",
59
+ "prompt": "<USER>Who was Johannes Vermeer?</USER><THINK>",
60
+ "expected_tool": "search",
61
+ "expected_arg": "Johannes Vermeer",
62
+ "raw_response": "The user is asking a factual question. I will query the search tool.</THINK><CALL>search(query=\"Johannes Vermeer\")</CALL>",
63
+ "parsed_call": "search(query=\"Johannes Vermeer\")",
64
+ "route_ok": true,
65
+ "exact_copy_ok": true
66
+ },
67
+ {
68
+ "id": 5,
69
+ "domain": "Unseen Figure",
70
+ "prompt": "<USER>Who is Ada Yonath?</USER><THINK>",
71
+ "expected_tool": "search",
72
+ "expected_arg": "Ada Yonath",
73
+ "raw_response": "The user is asking a factual question. I will query the search tool.</THINK><CALL>search(query=\"Ada Yonath\")</CALL>",
74
+ "parsed_call": "search(query=\"Ada Yonath\")",
75
+ "route_ok": true,
76
+ "exact_copy_ok": true
77
+ },
78
+ {
79
+ "id": 6,
80
+ "domain": "Unseen Figure",
81
+ "prompt": "<USER>Who was Srinivasa Ramanujan?</USER><THINK>",
82
+ "expected_tool": "search",
83
+ "expected_arg": "Srinivasa Ramanujan",
84
+ "raw_response": "The user is asking a factual question. I will query the search tool.</THINK><CALL>search(query=\"Srinivasa Ramanujan\")</CALL>",
85
+ "parsed_call": "search(query=\"Srinivasa Ramanujan\")",
86
+ "route_ok": true,
87
+ "exact_copy_ok": true
88
+ },
89
+ {
90
+ "id": 7,
91
+ "domain": "Unseen City",
92
+ "prompt": "<USER>What is the weather in Addis Ababa?</USER><THINK>",
93
+ "expected_tool": "get_weather",
94
+ "expected_arg": "Addis Ababa",
95
+ "raw_response": "The user requests current weather information. I will query the get_weather tool.</THINK><CALL>get_weather(city=\"Addis Ababa\")</CALL>",
96
+ "parsed_call": "get_weather(city=\"Addis Ababa\")",
97
+ "route_ok": true,
98
+ "exact_copy_ok": true
99
+ },
100
+ {
101
+ "id": 8,
102
+ "domain": "Unseen City",
103
+ "prompt": "<USER>What is the weather in Ulaanbaatar?</USER><THINK>",
104
+ "expected_tool": "get_weather",
105
+ "expected_arg": "Ulaanbaatar",
106
+ "raw_response": "The user requests current weather information. I will query the get_weather tool.</THINK><CALL>get_weather(city=\"Ulaanbaatar\")</CALL>",
107
+ "parsed_call": "get_weather(city=\"Ulaanbaatar\")",
108
+ "route_ok": true,
109
+ "exact_copy_ok": true
110
+ },
111
+ {
112
+ "id": 9,
113
+ "domain": "Unseen City",
114
+ "prompt": "<USER>Weather on Antananarivo</USER><THINK>",
115
+ "expected_tool": "get_weather",
116
+ "expected_arg": "Antananarivo",
117
+ "raw_response": "The user is asking for weather conditions. Querying get_weather.</THINK><CALL>get_weather(city=\"Antananarivo\")</CALL>",
118
+ "parsed_call": "get_weather(city=\"Antananarivo\")",
119
+ "route_ok": true,
120
+ "exact_copy_ok": true
121
+ },
122
+ {
123
+ "id": 10,
124
+ "domain": "Unseen City",
125
+ "prompt": "<USER>How is the weather in Dar es Salaam</USER><THINK>",
126
+ "expected_tool": "get_weather",
127
+ "expected_arg": "Dar es Salaam",
128
+ "raw_response": "The user is asking for weather conditions. Querying get_weather.</THINK><CALL>get_weather(city=\"Dar es Salaam\")</CALL>",
129
+ "parsed_call": "get_weather(city=\"Dar es Salaam\")",
130
+ "route_ok": true,
131
+ "exact_copy_ok": true
132
+ },
133
+ {
134
+ "id": 11,
135
+ "domain": "Unseen City",
136
+ "prompt": "<USER>Check the weather for Belo Horizonte</USER><THINK>",
137
+ "expected_tool": "get_weather",
138
+ "expected_arg": "Belo Horizonte",
139
+ "raw_response": "The user is asking for weather conditions. Querying get_weather.</THINK><CALL>get_weather(city=\"Belo Horizonte\")</CALL>",
140
+ "parsed_call": "get_weather(city=\"Belo Horizonte\")",
141
+ "route_ok": true,
142
+ "exact_copy_ok": true
143
+ },
144
+ {
145
+ "id": 12,
146
+ "domain": "Unseen City",
147
+ "prompt": "<USER>Forecast for Chiang Mai.</USER><THINK>",
148
+ "expected_tool": "get_weather",
149
+ "expected_arg": "Chiang Mai",
150
+ "raw_response": "The user is asking for weather conditions. Querying get_weather.</THINK><CALL>get_weather(city=\"Chiang Mai\")</CALL>",
151
+ "parsed_call": "get_weather(city=\"Chiang Mai\")",
152
+ "route_ok": true,
153
+ "exact_copy_ok": true
154
+ },
155
+ {
156
+ "id": 13,
157
+ "domain": "Unseen Science",
158
+ "prompt": "<USER>What are quarks and leptons</USER><THINK>",
159
+ "expected_tool": "search",
160
+ "expected_arg": "quarks and leptons",
161
+ "raw_response": "The user is asking a factual question. I will query the search tool.</THINK><CALL>search(query=\"quarks and leptons\")</CALL>",
162
+ "parsed_call": "search(query=\"quarks and leptons\")",
163
+ "route_ok": true,
164
+ "exact_copy_ok": true
165
+ },
166
+ {
167
+ "id": 14,
168
+ "domain": "Unseen Science",
169
+ "prompt": "<USER>Define epigenetics</USER><THINK>",
170
+ "expected_tool": "search",
171
+ "expected_arg": "epigenetics",
172
+ "raw_response": "The user is asking a factual question. I will query the search tool.</THINK><CALL>search(query=\"epigenetics\")</CALL>",
173
+ "parsed_call": "search(query=\"epigenetics\")",
174
+ "route_ok": true,
175
+ "exact_copy_ok": true
176
+ },
177
+ {
178
+ "id": 15,
179
+ "domain": "Unseen Science",
180
+ "prompt": "<USER>Explain superconductivity</USER><THINK>",
181
+ "expected_tool": "search",
182
+ "expected_arg": "superconductivity",
183
+ "raw_response": "The user is asking a factual question. I will query the search tool.</THINK><CALL>search(query=\"superconductivity\")</CALL>",
184
+ "parsed_call": "search(query=\"superconductivity\")",
185
+ "route_ok": true,
186
+ "exact_copy_ok": true
187
+ },
188
+ {
189
+ "id": 16,
190
+ "domain": "Unseen Science",
191
+ "prompt": "<USER>What is the mitochondrial matrix</USER><THINK>",
192
+ "expected_tool": "search",
193
+ "expected_arg": "mitochondrial matrix",
194
+ "raw_response": "The user is asking a factual question. I will query the search tool.</THINK><CALL>search(query=\"mitochondrial matrix\")</CALL>",
195
+ "parsed_call": "search(query=\"mitochondrial matrix\")",
196
+ "route_ok": true,
197
+ "exact_copy_ok": true
198
+ },
199
+ {
200
+ "id": 17,
201
+ "domain": "Unseen Science",
202
+ "prompt": "<USER>Explain bose einstein condensate</USER><THINK>",
203
+ "expected_tool": "search",
204
+ "expected_arg": "bose einstein condensate",
205
+ "raw_response": "The user is asking a factual question. I will query the search tool.</THINK><CALL>search(query=\"bose einstein condensate\")</CALL>",
206
+ "parsed_call": "search(query=\"bose einstein condensate\")",
207
+ "route_ok": true,
208
+ "exact_copy_ok": true
209
+ },
210
+ {
211
+ "id": 18,
212
+ "domain": "Unseen Science",
213
+ "prompt": "<USER>What is asymptotic freedom?</USER><THINK>",
214
+ "expected_tool": "search",
215
+ "expected_arg": "asymptotic freedom",
216
+ "raw_response": "The user is asking a factual question. I will query the search tool.</THINK><CALL>search(query=\"asymptotic freedom\")</CALL>",
217
+ "parsed_call": "search(query=\"asymptotic freedom\")",
218
+ "route_ok": true,
219
+ "exact_copy_ok": true
220
+ },
221
+ {
222
+ "id": 19,
223
+ "domain": "Unseen Concept",
224
+ "prompt": "<USER>What is a croissant?</USER><THINK>",
225
+ "expected_tool": "search",
226
+ "expected_arg": "croissant",
227
+ "raw_response": "The user is asking a factual question. I will query the search tool.</THINK><CALL>search(query=\"croissant\")</CALL>",
228
+ "parsed_call": "search(query=\"croissant\")",
229
+ "route_ok": true,
230
+ "exact_copy_ok": true
231
+ },
232
+ {
233
+ "id": 20,
234
+ "domain": "Unseen Concept",
235
+ "prompt": "<USER>Define baklava</USER><THINK>",
236
+ "expected_tool": "search",
237
+ "expected_arg": "baklava",
238
+ "raw_response": "The user is asking a factual question. I will query the search tool.</THINK><CALL>search(query=\"baklava\")</CALL>",
239
+ "parsed_call": "search(query=\"baklava\")",
240
+ "route_ok": true,
241
+ "exact_copy_ok": true
242
+ },
243
+ {
244
+ "id": 21,
245
+ "domain": "Unseen Concept",
246
+ "prompt": "<USER>What is shakshuka?</USER><THINK>",
247
+ "expected_tool": "search",
248
+ "expected_arg": "shakshuka",
249
+ "raw_response": "The user is asking a factual question. I will query the search tool.</THINK><CALL>search(query=\"shakshuka\")</CALL>",
250
+ "parsed_call": "search(query=\"shakshuka\")",
251
+ "route_ok": true,
252
+ "exact_copy_ok": true
253
+ },
254
+ {
255
+ "id": 22,
256
+ "domain": "Unseen Concept",
257
+ "prompt": "<USER>Tell me about the astrolabe</USER><THINK>",
258
+ "expected_tool": "search",
259
+ "expected_arg": "astrolabe",
260
+ "raw_response": "The user is asking a factual question. I will query the search tool.</THINK><CALL>search(query=\"astrolabe\")</CALL>",
261
+ "parsed_call": "search(query=\"astrolabe\")",
262
+ "route_ok": true,
263
+ "exact_copy_ok": true
264
+ },
265
+ {
266
+ "id": 23,
267
+ "domain": "Unseen Concept",
268
+ "prompt": "<USER>What is a clavichord</USER><THINK>",
269
+ "expected_tool": "search",
270
+ "expected_arg": "clavichord",
271
+ "raw_response": "The user is asking a factual question. I will query the search tool.</THINK><CALL>search(query=\"clavichord\")</CALL>",
272
+ "parsed_call": "search(query=\"clavichord\")",
273
+ "route_ok": true,
274
+ "exact_copy_ok": true
275
+ },
276
+ {
277
+ "id": 24,
278
+ "domain": "Unseen Concept",
279
+ "prompt": "<USER>Explain origami</USER><THINK>",
280
+ "expected_tool": "search",
281
+ "expected_arg": "origami",
282
+ "raw_response": "The user is asking a factual question. I will query the search tool.</THINK><CALL>search(query=\"origami\")</CALL>",
283
+ "parsed_call": "search(query=\"origami\")",
284
+ "route_ok": true,
285
+ "exact_copy_ok": true
286
+ },
287
+ {
288
+ "id": 25,
289
+ "domain": "Unseen Nonce",
290
+ "prompt": "<USER>Who is Vornik Plaxen?</USER><THINK>",
291
+ "expected_tool": "search",
292
+ "expected_arg": "Vornik Plaxen",
293
+ "raw_response": "The user is asking a factual question. I will query the search tool.</THINK><CALL>search(query=\"Vornik Plaxen\")</CALL>",
294
+ "parsed_call": "search(query=\"Vornik Plaxen\")",
295
+ "route_ok": true,
296
+ "exact_copy_ok": true
297
+ },
298
+ {
299
+ "id": 26,
300
+ "domain": "Unseen Nonce",
301
+ "prompt": "<USER>Define Zyntral Krelvok</USER><THINK>",
302
+ "expected_tool": "search",
303
+ "expected_arg": "Zyntral Krelvok",
304
+ "raw_response": "The user is asking a factual question. I will query the search tool.</THINK><CALL>search(query=\"Zyntral Krelvok\")</CALL>",
305
+ "parsed_call": "search(query=\"Zyntral Krelvok\")",
306
+ "route_ok": true,
307
+ "exact_copy_ok": true
308
+ },
309
+ {
310
+ "id": 27,
311
+ "domain": "Unseen Nonce",
312
+ "prompt": "<USER>Weather on Brixendale</USER><THINK>",
313
+ "expected_tool": "get_weather",
314
+ "expected_arg": "Brixendale",
315
+ "raw_response": "The user is asking for weather conditions. Querying get_weather.</THINK><CALL>get_weather(city=\"Brixendale\")</CALL>",
316
+ "parsed_call": "get_weather(city=\"Brixendale\")",
317
+ "route_ok": true,
318
+ "exact_copy_ok": true
319
+ },
320
+ {
321
+ "id": 28,
322
+ "domain": "Unseen Nonce",
323
+ "prompt": "<USER>What is Glarndoxification?</USER><THINK>",
324
+ "expected_tool": "search",
325
+ "expected_arg": "Glarndoxification",
326
+ "raw_response": "The user is asking a factual question. I will query the search tool.</THINK><CALL>search(query=\"Glarndoxification\")</CALL>",
327
+ "parsed_call": "search(query=\"Glarndoxification\")",
328
+ "route_ok": true,
329
+ "exact_copy_ok": true
330
+ },
331
+ {
332
+ "id": 29,
333
+ "domain": "Unseen Nonce",
334
+ "prompt": "<USER>What is a Trundleblump</USER><THINK>",
335
+ "expected_tool": "search",
336
+ "expected_arg": "Trundleblump",
337
+ "raw_response": "The user is asking a factual question. I will query the search tool.</THINK><CALL>search(query=\"Trundleblump\")</CALL>",
338
+ "parsed_call": "search(query=\"Trundleblump\")",
339
+ "route_ok": true,
340
+ "exact_copy_ok": true
341
+ },
342
+ {
343
+ "id": 30,
344
+ "domain": "Unseen Nonce",
345
+ "prompt": "<USER>Tell me about a Skrevling</USER><THINK>",
346
+ "expected_tool": "search",
347
+ "expected_arg": "Skrevling",
348
+ "raw_response": "The user is asking a factual question. I will query the search tool.</THINK><CALL>search(query=\"Skrevling\")</CALL>",
349
+ "parsed_call": "search(query=\"Skrevling\")",
350
+ "route_ok": true,
351
+ "exact_copy_ok": true
352
+ }
353
+ ]
354
+ }
interactive.py CHANGED
@@ -242,7 +242,7 @@ def run_dialogue_prompt(model: ScaledGPT, tokenizer: ScaledTokenizer, user_input
242
 
243
  def main():
244
  parser = argparse.ArgumentParser(description="ScaledGPT Interactive CLI")
245
- parser.add_argument("--ckpt", type=str, default="champion_model/scaled_t4/checkpoints/champion_final.pt", help="Path to checkpoint")
246
  parser.add_argument("--prompt", type=str, default=None, help="Execute a single prompt and exit")
247
  parser.add_argument("--threads", type=int, default=8, help="Number of CPU threads for inference")
248
  args = parser.parse_args()
@@ -258,15 +258,10 @@ def main():
258
  candidates = [
259
  args.ckpt,
260
  os.path.join(ROOT_DIR, args.ckpt),
261
- os.path.join(ROOT_DIR, "champion_model/scaled_t4/checkpoints/champion_final.pt"),
262
- os.path.join(ROOT_DIR, "champion_model/checkpoints/champion_final.pt"),
263
- os.path.join(ROOT_DIR, "champion_model/scaled_t4/checkpoints/scaled_t4_sft_all_tools.pt"),
264
- os.path.join(ROOT_DIR, "champion_model/scaled_t4/checkpoints/scaled_t4_sft_search.pt"),
265
- os.path.join(ROOT_DIR, "champion_model/scaled_t4/checkpoints/scaled_t4_final.pt"),
266
- os.path.join(ROOT_DIR, "champion_model/scaled_t4/checkpoints/scaled_t4_final_timeout_step_45059.pt"),
267
- os.path.join(ROOT_DIR, "champion_model/checkpoints/scaled_t4_sft_search_step_7000.zip"),
268
- os.path.join(ROOT_DIR, "champion_model/checkpoints/scaled_t4_final.zip"),
269
- os.path.join(ROOT_DIR, "champion_model/checkpoints/scaled_t4_final_timeout_step_45059.zip"),
270
  ]
271
  resolved_path = None
272
  for p in candidates:
@@ -278,8 +273,11 @@ def main():
278
  try:
279
  from huggingface_hub import hf_hub_download
280
  print("[INFO] Local weights not found. Automatically pulling champion weights from Hugging Face (Neithanvarvas/CBT)...")
281
- target_dir = os.path.join(ROOT_DIR, "champion_model", "scaled_t4", "checkpoints")
282
  resolved_path = hf_hub_download(repo_id="Neithanvarvas/CBT", filename="champion_final.pt", local_dir=target_dir)
 
 
 
283
  print(f"[PASS] Successfully pulled weights to: {resolved_path}")
284
  except Exception as e:
285
  print(f"[WARN] Automatic Hugging Face pull unsuccessful ({e}).")
 
242
 
243
  def main():
244
  parser = argparse.ArgumentParser(description="ScaledGPT Interactive CLI")
245
+ parser.add_argument("--ckpt", type=str, default="checkpoints/cbt/cbt_18m_2d_rope_R3_k45_sftv5.pt", help="Path to checkpoint")
246
  parser.add_argument("--prompt", type=str, default=None, help="Execute a single prompt and exit")
247
  parser.add_argument("--threads", type=int, default=8, help="Number of CPU threads for inference")
248
  args = parser.parse_args()
 
258
  candidates = [
259
  args.ckpt,
260
  os.path.join(ROOT_DIR, args.ckpt),
261
+ os.path.join(ROOT_DIR, "checkpoints/cbt/cbt_18m_2d_rope_R3_k45_sftv5.pt"),
262
+ os.path.join(ROOT_DIR, "champion_final.pt"),
263
+ os.path.join(ROOT_DIR, "checkpoints/cbt/cbt_18m_2d_rope_R3_k32_base.pt"),
264
+ os.path.join(ROOT_DIR, "checkpoints/cbt/cbt_18m_2d_rope_R3_k32_pretrain.pt"),
 
 
 
 
 
265
  ]
266
  resolved_path = None
267
  for p in candidates:
 
273
  try:
274
  from huggingface_hub import hf_hub_download
275
  print("[INFO] Local weights not found. Automatically pulling champion weights from Hugging Face (Neithanvarvas/CBT)...")
276
+ target_dir = os.path.join(ROOT_DIR, "checkpoints", "cbt")
277
  resolved_path = hf_hub_download(repo_id="Neithanvarvas/CBT", filename="champion_final.pt", local_dir=target_dir)
278
+ local_path = os.path.join(ROOT_DIR, "checkpoints/cbt/cbt_18m_2d_rope_R3_k45_sftv5.pt")
279
+ os.replace(resolved_path, local_path)
280
+ resolved_path = local_path
281
  print(f"[PASS] Successfully pulled weights to: {resolved_path}")
282
  except Exception as e:
283
  print(f"[WARN] Automatic Hugging Face pull unsuccessful ({e}).")
model.py CHANGED
@@ -8,8 +8,9 @@ Architecture:
8
  - Recurrent passes R = 3 (Effective depth = 18 layers at zero parameter overhead)
9
  - Residual recurrence update: x = x + (1/sqrt(R)) * (x_res - x)
10
  - Tied embedding and output projection weights (wte.weight == lm_head.weight)
11
- - Decoupled 2D-RoPE (Macro place p, Micro step tau)
12
- - Selective shift masking: (place_coords > 0).long()
 
13
  - O(1) SDPA causal attention
14
  - Non-embedding params: ~18,887,680 | Total params: ~18,953,216 (~18.95M target)
15
  """
@@ -106,6 +107,19 @@ def apply_2d_rope(
106
  return torch.cat([rot_place, rot_step], dim=-1)
107
 
108
 
 
 
 
 
 
 
 
 
 
 
 
 
 
109
  class CausalSelfAttention(nn.Module):
110
  """Causal multi-head self-attention with SDPA and 2D-RoPE."""
111
 
@@ -117,17 +131,26 @@ class CausalSelfAttention(nn.Module):
117
  self.head_dim = config.n_embd // config.n_head
118
  self.dropout = config.dropout
119
  self.rope_theta = config.rope_theta
 
 
 
120
 
121
  self.c_attn = nn.Linear(config.n_embd, 3 * config.n_embd, bias=config.bias)
122
  self.c_proj = nn.Linear(config.n_embd, config.n_embd, bias=config.bias)
123
  self.resid_dropout = nn.Dropout(config.dropout)
124
 
125
  cos, sin = precompute_2d_rope_freqs(
126
- self.head_dim, max_coords=config.max_coords, theta_base=config.rope_theta
127
  )
128
  self.register_buffer("rope_cos", cos, persistent=False)
129
  self.register_buffer("rope_sin", sin, persistent=False)
130
 
 
 
 
 
 
 
131
  def forward(
132
  self,
133
  x: torch.Tensor,
@@ -146,12 +169,12 @@ class CausalSelfAttention(nn.Module):
146
  max_coord = max(int(place_coords.max().item()), int(step_coords.max().item())) + 1
147
  if max_coord > self.rope_cos.size(0):
148
  new_max = max(max_coord * 2, 4096)
149
- cos, sin = precompute_2d_rope_freqs(self.head_dim, max_coords=new_max, theta_base=self.rope_theta)
150
  self.rope_cos = cos.to(x.device)
151
  self.rope_sin = sin.to(x.device)
152
 
153
- q = apply_2d_rope(q, place_coords, step_coords, self.rope_cos, self.rope_sin)
154
- k = apply_2d_rope(k, place_coords, step_coords, self.rope_cos, self.rope_sin)
155
 
156
  dropout_p = self.dropout if self.training else 0.0
157
  y = F.scaled_dot_product_attention(
@@ -202,6 +225,7 @@ class ScaledGPT(nn.Module):
202
 
203
  def __init__(self, config: ScaledGPTConfig, tokenizer: Optional[ScaledTokenizer] = None):
204
  super().__init__()
 
205
  self.config = config
206
  self.tokenizer = tokenizer or ScaledTokenizer()
207
 
@@ -237,6 +261,14 @@ class ScaledGPT(nn.Module):
237
  n_params -= self.transformer.wte.weight.numel()
238
  return n_params
239
 
 
 
 
 
 
 
 
 
240
  def compute_2d_coords(self, idx: torch.Tensor) -> Tuple[torch.Tensor, torch.Tensor]:
241
  """
242
  Unified 2D coordinate mapper:
@@ -360,11 +392,12 @@ class ScaledGPT(nn.Module):
360
  device = idx.device
361
 
362
  if place_coords is None or step_coords is None:
363
- place_coords, step_coords = self.compute_2d_coords(idx)
364
 
365
  # Shift invariance data augmentation during training:
366
- # Strictly applies selective shift masking (place_coords > 0).long()
367
- if self.training and self.config.k_rand_shift > 0:
 
368
  shifts = torch.randint(0, self.config.k_rand_shift + 1, (B, 1), device=device)
369
  shift_mask = (place_coords > 0).long()
370
  place_coords = place_coords + shifts * shift_mask
 
8
  - Recurrent passes R = 3 (Effective depth = 18 layers at zero parameter overhead)
9
  - Residual recurrence update: x = x + (1/sqrt(R)) * (x_res - x)
10
  - Tied embedding and output projection weights (wte.weight == lm_head.weight)
11
+ - Decoupled 2D-RoPE (Macro place p, Micro step tau); pos_emb_type="rope_1d" gives the
12
+ standard 1D-RoPE ablation (positions 0..T-1 over the full head_dim, same parameters)
13
+ - Selective shift masking: (place_coords > 0).long() (2D only)
14
  - O(1) SDPA causal attention
15
  - Non-embedding params: ~18,887,680 | Total params: ~18,953,216 (~18.95M target)
16
  """
 
107
  return torch.cat([rot_place, rot_step], dim=-1)
108
 
109
 
110
+ def apply_1d_rope(x: torch.Tensor, pos: torch.Tensor, cos: torch.Tensor, sin: torch.Tensor) -> torch.Tensor:
111
+ """Applies standard 1D-RoPE over the full head_dim of [B, n_head, T, head_dim] at positions pos [B, T]."""
112
+ pos = torch.clamp(pos, 0, cos.size(0) - 1)
113
+ c = cos[pos].unsqueeze(1).to(dtype=x.dtype, device=x.device)
114
+ s = sin[pos].unsqueeze(1).to(dtype=x.dtype, device=x.device)
115
+ x_even = x[..., 0::2]
116
+ x_odd = x[..., 1::2]
117
+ out = torch.empty_like(x)
118
+ out[..., 0::2] = x_even * c - x_odd * s
119
+ out[..., 1::2] = x_even * s + x_odd * c
120
+ return out
121
+
122
+
123
  class CausalSelfAttention(nn.Module):
124
  """Causal multi-head self-attention with SDPA and 2D-RoPE."""
125
 
 
131
  self.head_dim = config.n_embd // config.n_head
132
  self.dropout = config.dropout
133
  self.rope_theta = config.rope_theta
134
+ self.pos_emb_type = config.pos_emb_type
135
+ # 1D rotates head_dim/2 pairs; 2D rotates head_dim/4 pairs per subspace
136
+ self.rope_dim = 2 * self.head_dim if self.pos_emb_type == "rope_1d" else self.head_dim
137
 
138
  self.c_attn = nn.Linear(config.n_embd, 3 * config.n_embd, bias=config.bias)
139
  self.c_proj = nn.Linear(config.n_embd, config.n_embd, bias=config.bias)
140
  self.resid_dropout = nn.Dropout(config.dropout)
141
 
142
  cos, sin = precompute_2d_rope_freqs(
143
+ self.rope_dim, max_coords=config.max_coords, theta_base=config.rope_theta
144
  )
145
  self.register_buffer("rope_cos", cos, persistent=False)
146
  self.register_buffer("rope_sin", sin, persistent=False)
147
 
148
+ def rotate(self, x: torch.Tensor, place_coords: torch.Tensor, step_coords: torch.Tensor) -> torch.Tensor:
149
+ """Applies the configured RoPE variant (step_coords is ignored for rope_1d)."""
150
+ if self.pos_emb_type == "rope_1d":
151
+ return apply_1d_rope(x, place_coords, self.rope_cos, self.rope_sin)
152
+ return apply_2d_rope(x, place_coords, step_coords, self.rope_cos, self.rope_sin)
153
+
154
  def forward(
155
  self,
156
  x: torch.Tensor,
 
169
  max_coord = max(int(place_coords.max().item()), int(step_coords.max().item())) + 1
170
  if max_coord > self.rope_cos.size(0):
171
  new_max = max(max_coord * 2, 4096)
172
+ cos, sin = precompute_2d_rope_freqs(self.rope_dim, max_coords=new_max, theta_base=self.rope_theta)
173
  self.rope_cos = cos.to(x.device)
174
  self.rope_sin = sin.to(x.device)
175
 
176
+ q = self.rotate(q, place_coords, step_coords)
177
+ k = self.rotate(k, place_coords, step_coords)
178
 
179
  dropout_p = self.dropout if self.training else 0.0
180
  y = F.scaled_dot_product_attention(
 
225
 
226
  def __init__(self, config: ScaledGPTConfig, tokenizer: Optional[ScaledTokenizer] = None):
227
  super().__init__()
228
+ assert config.pos_emb_type in ("rope_2d", "rope_1d"), f"Unsupported pos_emb_type: {config.pos_emb_type}"
229
  self.config = config
230
  self.tokenizer = tokenizer or ScaledTokenizer()
231
 
 
261
  n_params -= self.transformer.wte.weight.numel()
262
  return n_params
263
 
264
+ def compute_coords(self, idx: torch.Tensor) -> Tuple[torch.Tensor, torch.Tensor]:
265
+ """Returns (place, step) coordinates: 2D mapper for rope_2d, (0..T-1, zeros) for rope_1d."""
266
+ if self.config.pos_emb_type == "rope_1d":
267
+ B, T = idx.size()
268
+ pos = torch.arange(T, dtype=torch.long, device=idx.device).unsqueeze(0).expand(B, T)
269
+ return pos, torch.zeros_like(pos)
270
+ return self.compute_2d_coords(idx)
271
+
272
  def compute_2d_coords(self, idx: torch.Tensor) -> Tuple[torch.Tensor, torch.Tensor]:
273
  """
274
  Unified 2D coordinate mapper:
 
392
  device = idx.device
393
 
394
  if place_coords is None or step_coords is None:
395
+ place_coords, step_coords = self.compute_coords(idx)
396
 
397
  # Shift invariance data augmentation during training:
398
+ # Strictly applies selective shift masking (place_coords > 0).long().
399
+ # Skipped for rope_1d: a uniform offset leaves every relative distance, hence every RoPE score, unchanged.
400
+ if self.training and self.config.k_rand_shift > 0 and self.config.pos_emb_type == "rope_2d":
401
  shifts = torch.randint(0, self.config.k_rand_shift + 1, (B, 1), device=device)
402
  shift_mask = (place_coords > 0).long()
403
  place_coords = place_coords + shifts * shift_mask