Kye Gomez commited on
Commit
53f786a
·
1 Parent(s): 14a806c

disclaimer and rope tests

Browse files
Files changed (2) hide show
  1. README.md +2 -0
  2. test_main.py +133 -0
README.md CHANGED
@@ -1,5 +1,7 @@
1
  # OpenMythos
2
 
 
 
3
  OpenMythos is an open-source, theoretical implementation of the Claude Mythos model. It implements a Recurrent-Depth Transformer (RDT) with three stages: **Prelude** (transformer blocks), a looped **Recurrent Block** (up to `max_loop_iters`), and a final **Coda**. Attention is switchable between MLA and GQA, and the feed-forward uses a sparse MoE with routed and shared experts ideal for exploring compute-adaptive, depth-variable reasoning.
4
 
5
 
 
1
  # OpenMythos
2
 
3
+ > **Disclaimer:** OpenMythos is an independent, community-driven theoretical reconstruction based solely on publicly available research and speculation. It is not affiliated with, endorsed by, or connected to Anthropic or any of their proprietary systems.
4
+
5
  OpenMythos is an open-source, theoretical implementation of the Claude Mythos model. It implements a Recurrent-Depth Transformer (RDT) with three stages: **Prelude** (transformer blocks), a looped **Recurrent Block** (up to `max_loop_iters`), and a final **Coda**. Attention is switchable between MLA and GQA, and the feed-forward uses a sparse MoE with routed and shared experts ideal for exploring compute-adaptive, depth-variable reasoning.
6
 
7
 
test_main.py CHANGED
@@ -121,6 +121,139 @@ class TestRoPE:
121
  assert not torch.allclose(out[0, 0], out[0, 1])
122
 
123
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
124
  # ---------------------------------------------------------------------------
125
  # GQAttention
126
  # ---------------------------------------------------------------------------
 
121
  assert not torch.allclose(out[0, 0], out[0, 1])
122
 
123
 
124
+ # ---------------------------------------------------------------------------
125
+ # RoPE extended — correctness invariants
126
+ # ---------------------------------------------------------------------------
127
+
128
+
129
+ class TestRoPEExtended:
130
+ """Comprehensive correctness tests for precompute_rope_freqs and apply_rope."""
131
+
132
+ # --- precompute_rope_freqs ---
133
+
134
+ def test_position_zero_is_unit_phasor(self):
135
+ """freqs[0] must be all 1+0j (angle = 0 * freq = 0 for every pair)."""
136
+ freqs = precompute_rope_freqs(dim=16, max_len=8)
137
+ expected = torch.ones(8, dtype=torch.complex64)
138
+ assert torch.allclose(freqs[0], expected, atol=1e-6)
139
+
140
+ def test_all_phasors_have_unit_magnitude(self):
141
+ """Every phasor magnitude must be 1 — RoPE is an isometric rotation."""
142
+ freqs = precompute_rope_freqs(dim=16, max_len=32)
143
+ assert torch.allclose(freqs.abs(), torch.ones_like(freqs.abs()), atol=1e-6)
144
+
145
+ def test_angles_equal_outer_product(self):
146
+ """freqs[t, k].angle() must equal t × base_freq[k] for all t, k."""
147
+ dim, max_len, theta = 8, 6, 500000.0
148
+ freqs = precompute_rope_freqs(dim=dim, max_len=max_len, theta=theta)
149
+ base = 1.0 / (theta ** (torch.arange(0, dim, 2, dtype=torch.float32) / dim))
150
+ t = torch.arange(max_len, dtype=torch.float32)
151
+ expected = torch.polar(torch.ones(max_len, dim // 2), torch.outer(t, base))
152
+ assert torch.allclose(freqs.real, expected.real, atol=1e-6)
153
+ assert torch.allclose(freqs.imag, expected.imag, atol=1e-6)
154
+
155
+ def test_higher_theta_produces_smaller_angles(self):
156
+ """Larger theta → slower frequency decay → smaller rotation angle per step."""
157
+ dim, max_len = 16, 8
158
+ freqs_fast = precompute_rope_freqs(dim=dim, max_len=max_len, theta=100.0)
159
+ freqs_slow = precompute_rope_freqs(dim=dim, max_len=max_len, theta=500000.0)
160
+ assert (freqs_fast[1].angle().abs() > freqs_slow[1].angle().abs()).all()
161
+
162
+ def test_default_theta_matches_explicit(self):
163
+ """Omitting theta must equal passing theta=500000.0."""
164
+ f1 = precompute_rope_freqs(16, 8)
165
+ f2 = precompute_rope_freqs(16, 8, theta=500000.0)
166
+ assert torch.allclose(f1.real, f2.real) and torch.allclose(f1.imag, f2.imag)
167
+
168
+ # --- apply_rope ---
169
+
170
+ def test_position_zero_is_identity(self):
171
+ """T=1 input uses only freqs[0] = 1+0j, so output must equal input."""
172
+ freqs = precompute_rope_freqs(dim=16, max_len=8)
173
+ x = torch.randn(2, 1, 4, 16)
174
+ out = apply_rope(x, freqs)
175
+ assert torch.allclose(x, out, atol=1e-6)
176
+
177
+ def test_dtype_float32_preserved(self):
178
+ freqs = precompute_rope_freqs(dim=16, max_len=16)
179
+ x = torch.randn(1, 4, 2, 16).float()
180
+ assert apply_rope(x, freqs).dtype == torch.float32
181
+
182
+ def test_dtype_float16_preserved(self):
183
+ freqs = precompute_rope_freqs(dim=16, max_len=16)
184
+ x = torch.randn(1, 4, 2, 16).half()
185
+ assert apply_rope(x, freqs).dtype == torch.float16
186
+
187
+ def test_inverse_rotation_recovers_input(self):
188
+ """Rotating by freqs then by conj(freqs) (inverse) must recover the original."""
189
+ dim = 16
190
+ freqs = precompute_rope_freqs(dim=dim, max_len=8)
191
+ x = torch.randn(2, 4, 3, dim)
192
+ rotated = apply_rope(x, freqs)
193
+ xc = torch.view_as_complex(rotated.float().reshape(*rotated.shape[:-1], -1, 2))
194
+ inv = freqs.conj()[: rotated.shape[1]].unsqueeze(0).unsqueeze(2)
195
+ recovered = torch.view_as_real(xc * inv).flatten(-2).to(x.dtype)
196
+ assert torch.allclose(x, recovered, atol=1e-5)
197
+
198
+ def test_batch_independence(self):
199
+ """Output for one batch item must not depend on other items in the batch."""
200
+ dim = 16
201
+ freqs = precompute_rope_freqs(dim=dim, max_len=16)
202
+ torch.manual_seed(7)
203
+ x_a = torch.randn(1, 4, 2, dim)
204
+ x_b = torch.randn(1, 4, 2, dim)
205
+ solo = apply_rope(x_a, freqs)
206
+ batched = apply_rope(torch.cat([x_a, x_b], dim=0), freqs)[:1]
207
+ assert torch.allclose(solo, batched, atol=1e-6)
208
+
209
+ def test_head_independence(self):
210
+ """All heads at the same position must receive identical rotations."""
211
+ dim = 16
212
+ freqs = precompute_rope_freqs(dim=dim, max_len=8)
213
+ x = torch.randn(1, 4, 1, dim).expand(1, 4, 3, dim).contiguous()
214
+ out = apply_rope(x, freqs)
215
+ assert torch.allclose(out[:, :, 0], out[:, :, 1], atol=1e-6)
216
+ assert torch.allclose(out[:, :, 1], out[:, :, 2], atol=1e-6)
217
+
218
+ def test_relative_position_property(self):
219
+ """
220
+ Core RoPE invariant: <RoPE(q,m), RoPE(k,n)> depends only on (n-m).
221
+ Two pairs with the same offset must produce the same dot product.
222
+ """
223
+ dim, max_len = 16, 32
224
+ freqs = precompute_rope_freqs(dim=dim, max_len=max_len)
225
+ torch.manual_seed(42)
226
+ q = torch.randn(1, 1, 1, dim)
227
+ k = torch.randn(1, 1, 1, dim)
228
+
229
+ def rope_at(tensor, pos):
230
+ """Rotate tensor at a specific position by embedding it in a zero sequence."""
231
+ seq = torch.zeros(1, pos + 1, 1, dim)
232
+ seq[0, pos] = tensor[0, 0]
233
+ return apply_rope(seq, freqs)[:, pos : pos + 1]
234
+
235
+ # Both pairs have relative offset n - m = 6
236
+ dot_3_9 = (rope_at(q, 3) * rope_at(k, 9)).sum()
237
+ dot_1_7 = (rope_at(q, 1) * rope_at(k, 7)).sum()
238
+ assert torch.allclose(dot_3_9, dot_1_7, atol=1e-5)
239
+
240
+ def test_max_len_boundary(self):
241
+ """apply_rope must handle T == max_len without error or NaN."""
242
+ max_len = 10
243
+ freqs = precompute_rope_freqs(dim=8, max_len=max_len)
244
+ x = torch.randn(1, max_len, 2, 8)
245
+ out = apply_rope(x, freqs)
246
+ assert out.shape == x.shape
247
+ assert not torch.isnan(out).any()
248
+
249
+ def test_exceeds_max_len_raises(self):
250
+ """apply_rope must raise RuntimeError when T > max_len."""
251
+ freqs = precompute_rope_freqs(dim=8, max_len=4)
252
+ x = torch.randn(1, 8, 2, 8) # T=8 > max_len=4
253
+ with pytest.raises(RuntimeError):
254
+ apply_rope(x, freqs)
255
+
256
+
257
  # ---------------------------------------------------------------------------
258
  # GQAttention
259
  # ---------------------------------------------------------------------------