ctzamos commited on
Commit
e0c043c
·
verified ·
1 Parent(s): 5f1c8c4

Spotlight VM: the model and the programs from the post

Browse files
LICENSE.md ADDED
@@ -0,0 +1,248 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # License
2
+
3
+ Spotlight VM is licensed under the Apache License, Version 2.0.
4
+
5
+ ```text
6
+ Apache License
7
+ Version 2.0, January 2004
8
+ http://www.apache.org/licenses/
9
+
10
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
11
+
12
+ 1. Definitions.
13
+
14
+ "License" shall mean the terms and conditions for use, reproduction,
15
+ and distribution as defined by Sections 1 through 9 of this document.
16
+
17
+ "Licensor" shall mean the copyright owner or entity authorized by
18
+ the copyright owner that is granting the License.
19
+
20
+ "Legal Entity" shall mean the union of the acting entity and all
21
+ other entities that control, are controlled by, or are under common
22
+ control with that entity. For the purposes of this definition,
23
+ "control" means (i) the power, direct or indirect, to cause the
24
+ direction or management of such entity, whether by contract or
25
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
26
+ outstanding shares, or (iii) beneficial ownership of such entity.
27
+
28
+ "You" (or "Your") shall mean an individual or Legal Entity
29
+ exercising permissions granted by this License.
30
+
31
+ "Source" form shall mean the preferred form for making modifications,
32
+ including but not limited to software source code, documentation
33
+ source, and configuration files.
34
+
35
+ "Object" form shall mean any form resulting from mechanical
36
+ transformation or translation of a Source form, including but
37
+ not limited to compiled object code, generated documentation,
38
+ and conversions to other media types.
39
+
40
+ "Work" shall mean the work of authorship, whether in Source or
41
+ Object form, made available under the License, as indicated by a
42
+ copyright notice that is included in or attached to the work
43
+ (an example is provided in the Appendix below).
44
+
45
+ "Derivative Works" shall mean any work, whether in Source or Object
46
+ form, that is based on (or derived from) the Work and for which the
47
+ editorial revisions, annotations, elaborations, or other modifications
48
+ represent, as a whole, an original work of authorship. For the purposes
49
+ of this License, Derivative Works shall not include works that remain
50
+ separable from, or merely link (or bind by name) to the interfaces of,
51
+ the Work and Derivative Works thereof.
52
+
53
+ "Contribution" shall mean any work of authorship, including
54
+ the original version of the Work and any modifications or additions
55
+ to that Work or Derivative Works thereof, that is intentionally
56
+ submitted to the Licensor for inclusion in the Work by the copyright owner
57
+ or by an individual or Legal Entity authorized to submit on behalf of
58
+ the copyright owner. For the purposes of this definition, "submitted"
59
+ means any form of electronic, verbal, or written communication sent
60
+ to the Licensor or its representatives, including but not limited to
61
+ communication on electronic mailing lists, source code control systems,
62
+ and issue tracking systems that are managed by, or on behalf of, the
63
+ Licensor for the purpose of discussing and improving the Work, but
64
+ excluding communication that is conspicuously marked or otherwise
65
+ designated in writing by the copyright owner as "Not a Contribution."
66
+
67
+ "Contributor" shall mean Licensor and any individual or Legal Entity
68
+ on behalf of whom a Contribution has been received by the Licensor and
69
+ subsequently incorporated within the Work.
70
+
71
+ 2. Grant of Copyright License. Subject to the terms and conditions of
72
+ this License, each Contributor hereby grants to You a perpetual,
73
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
74
+ copyright license to reproduce, prepare Derivative Works of,
75
+ publicly display, publicly perform, sublicense, and distribute the
76
+ Work and such Derivative Works in Source or Object form.
77
+
78
+ 3. Grant of Patent License. Subject to the terms and conditions of
79
+ this License, each Contributor hereby grants to You a perpetual,
80
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
81
+ (except as stated in this section) patent license to make, have made,
82
+ use, offer to sell, sell, import, and otherwise transfer the Work,
83
+ where such license applies only to those patent claims licensable
84
+ by such Contributor that are necessarily infringed by their
85
+ Contribution(s) alone or by combination of their Contribution(s)
86
+ with the Work to which such Contribution(s) was submitted. If You
87
+ institute patent litigation against any entity (including a
88
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
89
+ or a Contribution incorporated within the Work constitutes direct
90
+ or contributory patent infringement, then any patent licenses
91
+ granted to You under this License for that Work shall terminate
92
+ as of the date such litigation is filed.
93
+
94
+ 4. Redistribution. You may reproduce and distribute copies of the
95
+ Work or Derivative Works thereof in any medium, with or without
96
+ modifications, and in Source or Object form, provided that You
97
+ meet the following conditions:
98
+
99
+ (a) You must give any other recipients of the Work or
100
+ Derivative Works a copy of this License; and
101
+
102
+ (b) You must cause any modified files to carry prominent notices
103
+ stating that You changed the files; and
104
+
105
+ (c) You must retain, in the Source form of any Derivative Works
106
+ that You distribute, all copyright, patent, trademark, and
107
+ attribution notices from the Source form of the Work,
108
+ excluding those notices that do not pertain to any part of
109
+ the Derivative Works; and
110
+
111
+ (d) If the Work includes a "NOTICE" text file as part of its
112
+ distribution, then any Derivative Works that You distribute must
113
+ include a readable copy of the attribution notices contained
114
+ within such NOTICE file, excluding any notices that do not
115
+ pertain to any part of the Derivative Works, in at least one
116
+ of the following places: within a NOTICE text file distributed
117
+ as part of the Derivative Works; within the Source form or
118
+ documentation, if provided along with the Derivative Works; or,
119
+ within a display generated by the Derivative Works, if and
120
+ wherever such third-party notices normally appear. The contents
121
+ of the NOTICE file are for informational purposes only and
122
+ do not modify the License. You may add Your own attribution
123
+ notices within Derivative Works that You distribute, alongside
124
+ or as an addendum to the NOTICE text from the Work, provided
125
+ that such additional attribution notices cannot be construed
126
+ as modifying the License.
127
+
128
+ You may add Your own copyright statement to Your modifications and
129
+ may provide additional or different license terms and conditions
130
+ for use, reproduction, or distribution of Your modifications, or
131
+ for any such Derivative Works as a whole, provided Your use,
132
+ reproduction, and distribution of the Work otherwise complies with
133
+ the conditions stated in this License.
134
+
135
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
136
+ any Contribution intentionally submitted for inclusion in the Work
137
+ by You to the Licensor shall be under the terms and conditions of
138
+ this License, without any additional terms or conditions.
139
+ Notwithstanding the above, nothing herein shall supersede or modify
140
+ the terms of any separate license agreement you may have executed
141
+ with Licensor regarding such Contributions.
142
+
143
+ 6. Trademarks. This License does not grant permission to use the trade
144
+ names, trademarks, service marks, or product names of the Licensor,
145
+ except as required for reasonable and customary use in describing the
146
+ origin of the Work and reproducing the content of the NOTICE file.
147
+
148
+ 7. Disclaimer of Warranty. Unless required by applicable law or
149
+ agreed to in writing, Licensor provides the Work (and each
150
+ Contributor provides its Contributions) on an "AS IS" BASIS,
151
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
152
+ implied, including, without limitation, any warranties or conditions
153
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
154
+ PARTICULAR PURPOSE. You are solely responsible for determining the
155
+ appropriateness of using or redistributing the Work and assume any
156
+ risks associated with Your exercise of permissions under this License.
157
+
158
+ 8. Limitation of Liability. In no event and under no legal theory,
159
+ whether in tort (including negligence), contract, or otherwise,
160
+ unless required by applicable law (such as deliberate and grossly
161
+ negligent acts) or agreed to in writing, shall any Contributor be
162
+ liable to You for damages, including any direct, indirect, special,
163
+ incidental, or consequential damages of any character arising as a
164
+ result of this License or out of the use or inability to use the
165
+ Work (including but not limited to damages for loss of goodwill,
166
+ work stoppage, computer failure or malfunction, or any and all
167
+ other commercial damages or losses), even if such Contributor
168
+ has been advised of the possibility of such damages.
169
+
170
+ 9. Accepting Warranty or Additional Liability. While redistributing
171
+ the Work or Derivative Works thereof, You may choose to offer,
172
+ and charge a fee for, acceptance of support, warranty, indemnity,
173
+ or other liability obligations and/or rights consistent with this
174
+ License. However, in accepting such obligations, You may act only
175
+ on Your own behalf and on Your sole responsibility, not on behalf
176
+ of any other Contributor, and only if You agree to indemnify,
177
+ defend, and hold each Contributor harmless for any liability
178
+ incurred by, or claims asserted against, such Contributor by reason
179
+ of your accepting any such warranty or additional liability.
180
+
181
+ END OF TERMS AND CONDITIONS
182
+
183
+ Copyright 2026 Percepta
184
+
185
+ Licensed under the Apache License, Version 2.0 (the "License");
186
+ you may not use this file except in compliance with the License.
187
+ You may obtain a copy of the License at
188
+
189
+ http://www.apache.org/licenses/LICENSE-2.0
190
+
191
+ Unless required by applicable law or agreed to in writing, software
192
+ distributed under the License is distributed on an "AS IS" BASIS,
193
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
194
+ See the License for the specific language governing permissions and
195
+ limitations under the License.
196
+ ```
197
+
198
+ ## Third-party components
199
+
200
+ These parts remain under their own licenses.
201
+
202
+ ### MicroPython v1.28.0 (`memory/core.safetensors`)
203
+
204
+ ```
205
+ The MIT License (MIT)
206
+
207
+ Copyright (c) 2013-2026 Damien P. George
208
+
209
+ Permission is hereby granted, free of charge, to any person obtaining a copy
210
+ of this software and associated documentation files (the "Software"), to deal
211
+ in the Software without restriction, including without limitation the rights
212
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
213
+ copies of the Software, and to permit persons to whom the Software is
214
+ furnished to do so, subject to the following conditions:
215
+
216
+ The above copyright notice and this permission notice shall be included in
217
+ all copies or substantial portions of the Software.
218
+
219
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
220
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
221
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
222
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
223
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
224
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
225
+ THE SOFTWARE.
226
+ ```
227
+
228
+ ### sortedcontainers 2.4.0 (`memory/sortedcontainers.safetensors`)
229
+
230
+ ```
231
+ Copyright 2014-2019 Grant Jenks
232
+
233
+ Licensed under the Apache License, Version 2.0 (the "License");
234
+ you may not use this file except in compliance with the License.
235
+ You may obtain a copy of the License at
236
+
237
+ http://www.apache.org/licenses/LICENSE-2.0
238
+
239
+ Unless required by applicable law or agreed to in writing, software
240
+ distributed under the License is distributed on an "AS IS" BASIS,
241
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
242
+ See the License for the specific language governing permissions and
243
+ limitations under the License.
244
+ ```
245
+
246
+ ### MNIST (`memory/mnist.safetensors`)
247
+
248
+ The network was trained on the MNIST database of handwritten digits by Yann LeCun, Corinna Cortes and Christopher J. C. Burges.
README.md ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: apache-2.0
3
+ library_name: transformers
4
+ ---
5
+
6
+ # Spotlight VM
7
+
8
+ A small, hand-constructed [Spotlight](https://percepta.ai/blog/spotlight-memory) transformer that runs Python:
9
+ the examples from [Growing Intelligence Beyond the Weights](https://percepta.ai/blog/growing-intelligence-beyond-the-weights).
10
+ `intelligence/` holds the weights (under 100K parameters), which never change. `memory/` holds MicroPython
11
+ v1.28.0 (`core.safetensors`) and two packages.
12
+
13
+ ```sh
14
+ cc -O3 -std=c99 spotlight.c -lm -o spotlight
15
+ ./spotlight < examples/euler1.py # 233168; -v also prints every generated token
16
+ cat examples/tax_brackets/*.py | ./spotlight
17
+ ```
18
+
19
+ ```python
20
+ from transformers import AutoModelForCausalLM, AutoTokenizer
21
+
22
+ model = AutoModelForCausalLM.from_pretrained("percepta-ai/spotlight-vm", trust_remote_code=True)
23
+ tokenizer = AutoTokenizer.from_pretrained("percepta-ai/spotlight-vm", trust_remote_code=True)
24
+ output = model.generate(**tokenizer("print(1 + 2)\n", return_tensors="pt"))
25
+ print(tokenizer.decode(output[0])) # 3
26
+ ```
27
+
28
+ In a local copy of this folder, `from_pretrained(".")` works the same way.
29
+
30
+ | Example | In the post | Output |
31
+ |---|---|---|
32
+ | `examples/euler1.py`, `euler2.py`, `euler3.py` | Project Euler problems 1 to 3 | `233168`, `4613732`, `6857` |
33
+ | `examples/memory_loader.py` | Loading memory selectively | `4` |
34
+ | `examples/tax_brackets/` | Acquiring and updating knowledge | `$17400`, then `$16914` |
35
+ | `examples/mnist_digit.py` | Growing capabilities and intelligence | `7` |
36
+
37
+ It runs on one CPU core at about 120K tokens per second: minutes for the Project Euler examples,
38
+ about half an hour for MNIST (245M tokens). This MicroPython build has no floating point. License: Apache 2.0,
39
+ see [LICENSE.md](LICENSE.md).
config.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"model_type":"spotlight","architectures":["SpotlightForCausalLM"],"auto_map":{"AutoConfig":"spotlight.SpotlightConfig","AutoModelForCausalLM":"spotlight.SpotlightForCausalLM","AutoTokenizer":["spotlight.SpotlightTokenizer",null]}}
examples/euler1.py ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # https://projecteuler.net/problem=1
2
+ # Sum the multiples of 3 or 5 below 1000.
3
+ # Memory allocation within the program translates to Spotlight Memory
4
+ def euler1(limit=1000):
5
+ marked = bytearray(limit)
6
+ for n in range(0, limit, 3):
7
+ marked[n] = 1
8
+ for n in range(0, limit, 5):
9
+ marked[n] = 1
10
+ return sum(n for n in range(limit) if marked[n])
11
+
12
+ print(euler1())
examples/euler2.py ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # https://projecteuler.net/problem=2
2
+ # Sum the even Fibonacci terms not exceeding 4,000,000.
3
+ # Recursive function calling, generators and Python idioms
4
+ def fib():
5
+ a, b = 1, 2
6
+ while True:
7
+ yield a
8
+ a, b = b, a + b
9
+
10
+ def evens(it):
11
+ for x in it:
12
+ if x % 2 == 0:
13
+ yield x
14
+
15
+ def upto(limit, it):
16
+ for x in it:
17
+ if x > limit:
18
+ return
19
+ yield x
20
+
21
+ def euler2(limit=4000000):
22
+ return sum(evens(upto(limit, fib())))
23
+
24
+ print(euler2())
examples/euler3.py ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # https://projecteuler.net/problem=3
2
+ # Find the largest prime factor of 600851475143.
3
+ def euler3(n=600851475143):
4
+ i = 2
5
+ while i * i <= n:
6
+ while n % i == 0:
7
+ n //= i
8
+ i += 1
9
+ return n
10
+
11
+ print(euler3())
examples/memory_loader.py ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ from sortedcontainers import SortedList
2
+ from math import log
3
+ values = SortedList([9, 4, 16])
4
+ print(log(values.pop(), 2))
examples/mnist_digit.py ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ # The first MNIST test image (a 7), classified by the 784-80-10 network in memory/mnist.safetensors.
2
+ import mnist
3
+ x=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00T\xb9\x9f\x97<$\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xde\xfe\xfe\xfe\xfe\xf1\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xaa4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00CrHr\xa3\xe3\xfe\xe1\xfe\xfe\xfe\xfa\xe5\xfe\xfe\x8c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11B\x0eCCC;\x15\xec\xfej\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00S\xfd\xd1\x12\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x16\xe9\xffS\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x81\xfe\xee,\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00;\xf9\xfe>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x85\xfe\xbb\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\t\xcd\xf8:\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00~\xfe\xb6\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00K\xfb\xf09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x13\xdd\xfe\xa6\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\xcb\xfe\xdb#\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00&\xfe\xfeM\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1f\xe0\xfes\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x85\xfe\xfe4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00=\xf2\xfe\xfe4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00y\xfe\xfe\xdb(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00y\xfe\xcf\x12\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
4
+ print(mnist.predict(x))
examples/tax_brackets/1_create.py ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ import sys
2
+ brackets = [0, 11_000, 44_725, 95_375,
3
+ 182_100, 231_250, 578_125]
4
+ increments = [10, 2, 10, 2, 8, 3, 2]
5
+ sys.modules["tax_brackets"] = type("tax_brackets", (), {
6
+ "owed_tax": lambda income: sum(
7
+ rate * max(0, income - b)
8
+ for b, rate in zip(brackets, increments)
9
+ ) // 100})
10
+ print("Tax brackets installed.")
examples/tax_brackets/2_use.py ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ import tax_brackets
2
+ income = 100_000
3
+ print(f"${tax_brackets.owed_tax(income)}")
examples/tax_brackets/3_update.py ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ import sys
2
+ brackets = [0, 11_925, 48_475, 103_350,
3
+ 197_300, 250_525, 626_350]
4
+ increments = [10, 2, 10, 2, 8, 3, 2]
5
+ sys.modules["tax_brackets"] = type("tax_brackets", (), {
6
+ "owed_tax": lambda income: sum(
7
+ rate * max(0, income - b)
8
+ for b, rate in zip(brackets, increments)
9
+ ) // 100})
10
+ print("Tax brackets updated.")
examples/tax_brackets/4_use_again.py ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ import tax_brackets
2
+ income = 100_000
3
+ print(f"${tax_brackets.owed_tax(income)}")
intelligence/config.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"d_model":16,"n_heads":8,"n_layers":8,"vocab_size":922,"proj_out":64,"stop_id":635,"n_out":786,"d_ffn":48,"head_rank":3,"d_rest":0,"d_v":2,"alpha_rows":1,"spacing":2.0,"memory_layer":4,"memory_head":4,"input_base":4475392,"registry_base":4587520,"registry_root_word":4475376,"memory_pages_word":4522008,"image_pages":70}
intelligence/model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:e09af3088c603c3641923f8c1554fa6657573570b5eb251ed8c73c5ca543df7a
3
+ size 378560
intelligence/vocab.json ADDED
@@ -0,0 +1 @@
 
 
1
+ ["!", "\"", "#", "$", "%", "&", "'", "(", ")", "*", "+", ",", "-", ".", "/", "0", "00", "00'", "01", "01'", "02", "02'", "03", "03'", "04", "04'", "05", "05'", "06", "06'", "07", "07'", "08", "08'", "09", "09'", "0a", "0a'", "0b", "0b'", "0c", "0c'", "0d", "0d'", "0e", "0e'", "0f", "0f'", "1", "10", "10'", "11", "11'", "12", "12'", "13", "13'", "14", "14'", "15", "15'", "16", "16'", "17", "17'", "18", "18'", "19", "19'", "1a", "1a'", "1b", "1b'", "1c", "1c'", "1d", "1d'", "1e", "1e'", "1f", "1f'", "2", "20", "20'", "21", "21'", "22", "22'", "23", "23'", "24", "24'", "25", "25'", "26", "26'", "27", "27'", "28", "28'", "29", "29'", "2a", "2a'", "2b", "2b'", "2c", "2c'", "2d", "2d'", "2e", "2e'", "2f", "2f'", "3", "30", "30'", "31", "31'", "32", "32'", "33", "33'", "34", "34'", "35", "35'", "36", "36'", "37", "37'", "38", "38'", "39", "39'", "3a", "3a'", "3b", "3b'", "3c", "3c'", "3d", "3d'", "3e", "3e'", "3f", "3f'", "4", "40", "40'", "41", "41'", "42", "42'", "43", "43'", "44", "44'", "45", "45'", "46", "46'", "47", "47'", "48", "48'", "49", "49'", "4a", "4a'", "4b", "4b'", "4c", "4c'", "4d", "4d'", "4e", "4e'", "4f", "4f'", "5", "50", "50'", "51", "51'", "52", "52'", "53", "53'", "54", "54'", "55", "55'", "56", "56'", "57", "57'", "58", "58'", "59", "59'", "5a", "5a'", "5b", "5b'", "5c", "5c'", "5d", "5d'", "5e", "5e'", "5f", "5f'", "6", "60", "60'", "61", "61'", "62", "62'", "63", "63'", "64", "64'", "65", "65'", "66", "66'", "67", "67'", "68", "68'", "69", "69'", "6a", "6a'", "6b", "6b'", "6c", "6c'", "6d", "6d'", "6e", "6e'", "6f", "6f'", "7", "70", "70'", "71", "71'", "72", "72'", "73", "73'", "74", "74'", "75", "75'", "76", "76'", "77", "77'", "78", "78'", "79", "79'", "7a", "7a'", "7b", "7b'", "7c", "7c'", "7d", "7d'", "7e", "7e'", "7f", "7f'", "8", "80", "80'", "81", "81'", "82", "82'", "83", "83'", "84", "84'", "85", "85'", "86", "86'", "87", "87'", "88", "88'", "89", "89'", "8a", "8a'", "8b", "8b'", "8c", "8c'", "8d", "8d'", "8e", "8e'", "8f", "8f'", "9", "90", "90'", "91", "91'", "92", "92'", "93", "93'", "94", "94'", "95", "95'", "96", "96'", "97", "97'", "98", "98'", "99", "99'", "9a", "9a'", "9b", "9b'", "9c", "9c'", "9d", "9d'", "9e", "9e'", "9f", "9f'", ":", ";", "<", "=", ">", "?", "@", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "[", "\\", "]", "^", "_", "`", "a", "a0", "a0'", "a1", "a1'", "a2", "a2'", "a3", "a3'", "a4", "a4'", "a5", "a5'", "a6", "a6'", "a7", "a7'", "a8", "a8'", "a9", "a9'", "aa", "aa'", "ab", "ab'", "ac", "ac'", "ad", "ad'", "ae", "ae'", "af", "af'", "ascii(00)", "ascii(01)", "ascii(02)", "ascii(03)", "ascii(04)", "ascii(05)", "ascii(06)", "ascii(07)", "ascii(08)", "ascii(09)", "ascii(0a)", "ascii(0b)", "ascii(0c)", "ascii(0d)", "ascii(0e)", "ascii(0f)", "ascii(10)", "ascii(11)", "ascii(12)", "ascii(13)", "ascii(14)", "ascii(15)", "ascii(16)", "ascii(17)", "ascii(18)", "ascii(19)", "ascii(1a)", "ascii(1b)", "ascii(1c)", "ascii(1d)", "ascii(1e)", "ascii(1f)", "ascii(20)", "ascii(7f)", "b", "b0", "b0'", "b1", "b1'", "b2", "b2'", "b3", "b3'", "b4", "b4'", "b5", "b5'", "b6", "b6'", "b7", "b7'", "b8", "b8'", "b9", "b9'", "ba", "ba'", "bb", "bb'", "bc", "bc'", "bd", "bd'", "be", "be'", "bf", "bf'", "branch_taken", "c", "c0", "c0'", "c1", "c1'", "c2", "c2'", "c3", "c3'", "c4", "c4'", "c5", "c5'", "c6", "c6'", "c7", "c7'", "c8", "c8'", "c9", "c9'", "ca", "ca'", "call_commit", "cb", "cb'", "cc", "cc'", "cd", "cd'", "ce", "ce'", "cf", "cf'", "commit(+0,sts=0,bt=0)", "commit(+0,sts=0,bt=1)", "commit(+0,sts=1,bt=0)", "commit(+0,sts=1,bt=1)", "commit(+1,sts=1,bt=0)", "commit(+1,sts=1,bt=1)", "commit(-1,sts=0,bt=0)", "commit(-1,sts=0,bt=1)", "commit(-1,sts=1,bt=0)", "commit(-1,sts=1,bt=1)", "commit(-2,sts=0,bt=0)", "commit(-2,sts=0,bt=1)", "commit(-2,sts=1,bt=0)", "commit(-2,sts=1,bt=1)", "d", "d0", "d0'", "d1", "d1'", "d2", "d2'", "d3", "d3'", "d4", "d4'", "d5", "d5'", "d6", "d6'", "d7", "d7'", "d8", "d8'", "d9", "d9'", "da", "da'", "db", "db'", "dc", "dc'", "dd", "dd'", "de", "de'", "df", "df'", "e", "e0", "e0'", "e1", "e1'", "e2", "e2'", "e3", "e3'", "e4", "e4'", "e5", "e5'", "e6", "e6'", "e7", "e7'", "e8", "e8'", "e9", "e9'", "ea", "ea'", "eb", "eb'", "ec", "ec'", "ed", "ed'", "ee", "ee'", "ef", "ef'", "execute", "f", "f0", "f0'", "f1", "f1'", "f2", "f2'", "f3", "f3'", "f4", "f4'", "f5", "f5'", "f6", "f6'", "f7", "f7'", "f8", "f8'", "f9", "f9'", "fa", "fa'", "fb", "fb'", "fc", "fc'", "fd", "fd'", "fe", "fe'", "ff", "ff'", "g", "h", "halt", "i", "i32.and", "i32.extend16_s", "i32.extend8_s", "i32.or", "i32.xor", "j", "k", "l", "m", "n", "o", "out(!)", "out(\")", "out(#)", "out($)", "out(%)", "out(&)", "out(')", "out(()", "out())", "out(*)", "out(+)", "out(,)", "out(-)", "out(.)", "out(/)", "out(0)", "out(00)", "out(01)", "out(02)", "out(03)", "out(04)", "out(05)", "out(06)", "out(07)", "out(08)", "out(09)", "out(0a)", "out(0b)", "out(0c)", "out(0d)", "out(0e)", "out(0f)", "out(1)", "out(10)", "out(11)", "out(12)", "out(13)", "out(14)", "out(15)", "out(16)", "out(17)", "out(18)", "out(19)", "out(1a)", "out(1b)", "out(1c)", "out(1d)", "out(1e)", "out(1f)", "out(2)", "out(20)", "out(3)", "out(4)", "out(5)", "out(6)", "out(7)", "out(7f)", "out(8)", "out(80)", "out(81)", "out(82)", "out(83)", "out(84)", "out(85)", "out(86)", "out(87)", "out(88)", "out(89)", "out(8a)", "out(8b)", "out(8c)", "out(8d)", "out(8e)", "out(8f)", "out(9)", "out(90)", "out(91)", "out(92)", "out(93)", "out(94)", "out(95)", "out(96)", "out(97)", "out(98)", "out(99)", "out(9a)", "out(9b)", "out(9c)", "out(9d)", "out(9e)", "out(9f)", "out(:)", "out(;)", "out(<)", "out(=)", "out(>)", "out(?)", "out(@)", "out(A)", "out(B)", "out(C)", "out(D)", "out(E)", "out(F)", "out(G)", "out(H)", "out(I)", "out(J)", "out(K)", "out(L)", "out(M)", "out(N)", "out(O)", "out(P)", "out(Q)", "out(R)", "out(S)", "out(T)", "out(U)", "out(V)", "out(W)", "out(X)", "out(Y)", "out(Z)", "out([)", "out(\\)", "out(])", "out(^)", "out(_)", "out(`)", "out(a)", "out(a0)", "out(a1)", "out(a2)", "out(a3)", "out(a4)", "out(a5)", "out(a6)", "out(a7)", "out(a8)", "out(a9)", "out(aa)", "out(ab)", "out(ac)", "out(ad)", "out(ae)", "out(af)", "out(b)", "out(b0)", "out(b1)", "out(b2)", "out(b3)", "out(b4)", "out(b5)", "out(b6)", "out(b7)", "out(b8)", "out(b9)", "out(ba)", "out(bb)", "out(bc)", "out(bd)", "out(be)", "out(bf)", "out(c)", "out(c0)", "out(c1)", "out(c2)", "out(c3)", "out(c4)", "out(c5)", "out(c6)", "out(c7)", "out(c8)", "out(c9)", "out(ca)", "out(cb)", "out(cc)", "out(cd)", "out(ce)", "out(cf)", "out(d)", "out(d0)", "out(d1)", "out(d2)", "out(d3)", "out(d4)", "out(d5)", "out(d6)", "out(d7)", "out(d8)", "out(d9)", "out(da)", "out(db)", "out(dc)", "out(dd)", "out(de)", "out(df)", "out(e)", "out(e0)", "out(e1)", "out(e2)", "out(e3)", "out(e4)", "out(e5)", "out(e6)", "out(e7)", "out(e8)", "out(e9)", "out(ea)", "out(eb)", "out(ec)", "out(ed)", "out(ee)", "out(ef)", "out(f)", "out(f0)", "out(f1)", "out(f2)", "out(f3)", "out(f4)", "out(f5)", "out(f6)", "out(f7)", "out(f8)", "out(f9)", "out(fa)", "out(fb)", "out(fc)", "out(fd)", "out(fe)", "out(ff)", "out(g)", "out(h)", "out(i)", "out(j)", "out(k)", "out(l)", "out(m)", "out(n)", "out(o)", "out(p)", "out(q)", "out(r)", "out(s)", "out(t)", "out(u)", "out(v)", "out(w)", "out(x)", "out(y)", "out(z)", "out({)", "out(|)", "out(})", "out(~)", "p", "page", "q", "r", "return_commit", "s", "t", "u", "unpage", "v", "w", "x", "y", "z", "{", "|", "}", "~"]
memory/core.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:79ed099f59fe3c62cc70595f9b09c4655b9cf5ed2be22042cc59de61afe156b3
3
+ size 23989346
memory/mnist.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:45b8d1aafa55fa579c7995a74fa978cacfca8a3abbb6fe372719723fa7c223c4
3
+ size 64556
memory/sortedcontainers.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:5b173f11870edf27424391bb4dc6f3f9c65761f03d81bb58f43e4052664b887b
3
+ size 26921
spotlight.c ADDED
@@ -0,0 +1,304 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* spotlight.c -- runs a Python program on the Spotlight VM model: ./spotlight [-v] < program.py
2
+ * Run it in the model folder; it loads intelligence/ and every package in memory/, and -v also
3
+ * prints each generated token. Built with -shared -DSPOTLIGHT_LIBRARY, spotlight.py loads it. */
4
+ #define _POSIX_C_SOURCE 200809L
5
+ #include <dirent.h>
6
+ #include <math.h>
7
+ #include <stdint.h>
8
+ #include <stdio.h>
9
+ #include <stdlib.h>
10
+ #include <string.h>
11
+
12
+ typedef float real_t;
13
+ static void die(const char *what) { fprintf(stderr, "spotlight: %s\n", what); exit(1); }
14
+ static void *alloc(size_t n) { void *p = calloc(n ? n : 1, 1); if (!p) die("out of memory"); return p; }
15
+ static char folder[4096] = ".";
16
+ static const char *file(const char *name) { static char path[4200]; snprintf(path, sizeof path, "%s/%s", folder, name); return path; }
17
+
18
+ static char *slurp(const char *path, size_t *size) {
19
+ FILE *f = path ? fopen(path, "rb") : stdin;
20
+ if (!f) die(path);
21
+ size_t cap = 1 << 16, n = 0, got; char *buf = alloc(cap);
22
+ while ((got = fread(buf + n, 1, cap - n - 1, f)) > 0) if ((n += got) == cap - 1) buf = realloc(buf, cap *= 2);
23
+ if (path) fclose(f);
24
+ buf[n] = 0; if (size) *size = n;
25
+ return buf;
26
+ }
27
+
28
+ /* ── config.json and safetensors ─────────────────────────────────────── */
29
+ static char *config;
30
+ static double number(const char *key) {
31
+ char pattern[64]; snprintf(pattern, sizeof pattern, "\"%s\":", key);
32
+ const char *p = strstr(config, pattern);
33
+ if (!p) die(key);
34
+ return strtod(p + strlen(pattern), NULL);
35
+ }
36
+
37
+ typedef struct { char dtype[4]; const char *data; int64_t count; } Tensor;
38
+ static int tensor(const char *file_bytes, const char *name, Tensor *out) {
39
+ char pattern[96]; snprintf(pattern, sizeof pattern, "\"%s\":", name);
40
+ uint64_t header; memcpy(&header, file_bytes, 8);
41
+ const char *p = strstr(file_bytes + 8, pattern);
42
+ if (!p || p > file_bytes + 8 + header) return 0;
43
+ const char *dtype = strstr(p, "\"dtype\":\"") + 9; char *offsets = strstr(p, "\"data_offsets\":[") + 16;
44
+ memset(out->dtype, 0, 4); memcpy(out->dtype, dtype, strchr(dtype, '"') - dtype);
45
+ int64_t begin = strtoll(offsets, &offsets, 10), end = strtoll(offsets + 1, NULL, 10);
46
+ int width = out->dtype[1] == '8' ? 1 : out->dtype[1] == '1' ? 2 : out->dtype[1] == '3' ? 4 : 8;
47
+ out->data = file_bytes + 8 + header + begin; out->count = (end - begin) / width;
48
+ return 1;
49
+ }
50
+ static double item(const Tensor *t, int64_t i) {
51
+ double f; int32_t i32; int16_t i16;
52
+ switch (t->dtype[0] == 'F' ? 'F' : t->dtype[1]) {
53
+ case 'F': memcpy(&f, t->data + 8 * i, 8); return f;
54
+ case '3': memcpy(&i32, t->data + 4 * i, 4); return i32;
55
+ case '1': memcpy(&i16, t->data + 2 * i, 2); return i16;
56
+ default: return t->dtype[0] == 'U' ? (double)(uint8_t)t->data[i] : (double)(int8_t)t->data[i];
57
+ }
58
+ }
59
+ static real_t *load(const char *file_bytes, const char *name, int64_t count) {
60
+ Tensor x; if (!tensor(file_bytes, name, &x) || x.count != count) die(name);
61
+ real_t *out = alloc((size_t)count * sizeof(real_t));
62
+ for (int64_t i = 0; i < count; i++) out[i] = (real_t)item(&x, i);
63
+ return out;
64
+ }
65
+
66
+ /* ── the memory: one hash map from (table, x, y) to a cell's state ──── */
67
+ typedef struct { int64_t x, y; int32_t table, used; real_t s[2]; } Cell;
68
+ static Cell *cells; static size_t cells_cap, cells_n;
69
+ static const real_t ZERO[2] = {0, 0};
70
+
71
+ static size_t cell_slot(int table, int64_t x, int64_t y) {
72
+ uint64_t h = (uint64_t)x * 0x9E3779B97F4A7C15ull ^ (uint64_t)y * 0xC2B2AE3D27D4EB4Full ^ (uint64_t)table * 0x165667B19E3779F9ull;
73
+ size_t i = (size_t)(h ^ h >> 29) & (cells_cap - 1);
74
+ while (cells[i].used && (cells[i].x != x || cells[i].y != y || cells[i].table != table)) i = (i + 1) & (cells_cap - 1);
75
+ return i;
76
+ }
77
+ static real_t *cell_write(int table, int64_t x, int64_t y) {
78
+ if (2 * (cells_n + 1) > cells_cap) {
79
+ Cell *old = cells; size_t n = cells_cap;
80
+ cells_cap = cells_cap ? 2 * cells_cap : 1 << 22; cells = alloc(cells_cap * sizeof(Cell));
81
+ for (size_t i = 0; i < n; i++) if (old[i].used) cells[cell_slot(old[i].table, old[i].x, old[i].y)] = old[i];
82
+ free(old);
83
+ }
84
+ size_t i = cell_slot(table, x, y);
85
+ if (!cells[i].used) { cells[i].x = x; cells[i].y = y; cells[i].table = table; cells[i].used = 1; cells_n++; }
86
+ return cells[i].s;
87
+ }
88
+ static const real_t *cell_read(int table, int64_t x, int64_t y) {
89
+ size_t i = cell_slot(table, x, y);
90
+ return cells[i].used ? cells[i].s : ZERO;
91
+ }
92
+
93
+ /* ── the model ───────────────────────────────────────────────────────── */
94
+ /* The Spotlight kernel: phi_z(x) = b(x - z) / sqrt(sum_j b(x - j)^2) over the three nearest cells,
95
+ * with b(t) = cos^2(pi t / 2) for |t| < 1. */
96
+ static void phi(real_t x, int64_t *z0, real_t w[3]) {
97
+ int64_t c = (int64_t)floor(x + 0.5); real_t norm = 0;
98
+ for (int i = 0; i < 3; i++) {
99
+ real_t t = x - (real_t)(c + i - 1), b = fabsf(t) < 1 ? cosf(3.14159265f * t / 2) : 0;
100
+ w[i] = b * b; norm += w[i] * w[i];
101
+ }
102
+ for (int i = 0; i < 3; i++) w[i] /= sqrtf(norm);
103
+ *z0 = c - 1;
104
+ }
105
+ static real_t sigmoid(real_t z) { return 1 / (1 + expf(-z)); }
106
+ static real_t dot(const real_t *row, const real_t *x, int cols) { /* 8 lanes, so it vectorizes */
107
+ real_t a[8] = {0}, acc; int c = 0;
108
+ for (; c + 8 <= cols; c += 8) for (int k = 0; k < 8; k++) a[k] += row[c + k] * x[c + k];
109
+ acc = ((a[0] + a[1]) + (a[2] + a[3])) + ((a[4] + a[5]) + (a[6] + a[7]));
110
+ for (; c < cols; c++) acc += row[c] * x[c];
111
+ return acc;
112
+ }
113
+ static void matvec(const real_t *m, int rows, int cols, const real_t *x, const real_t *bias, real_t *y) {
114
+ for (int r = 0; r < rows; r++) y[r] = bias ? dot(m + (size_t)r * cols, x, cols) + bias[r] : dot(m + (size_t)r * cols, x, cols);
115
+ }
116
+
117
+ typedef struct { real_t *qkv_w, *qkv_b, *out_w, *ff_in_w, *ff_out_w; } Layer;
118
+ static struct {
119
+ int D, H, layers, vocab, proj_out, stop_id, n_out, d_ffn, rank;
120
+ Layer *layer; real_t *embed, *basis, *coeff; int32_t *out_ids; char **tokens;
121
+ } M;
122
+
123
+ /* One head, one token: a delta-rule write into the 3x3 cells around the key, then a read of the
124
+ * 3x3 cells around the query. */
125
+ static void memory_step(int table, const real_t *p, int h, real_t *out) {
126
+ const int H = M.H; const real_t *v = p + 6 * H + 2 * h;
127
+ real_t beta = sigmoid(p[4 * H + h]), alpha = sigmoid(-p[5 * H + h]), wx[3], wy[3];
128
+ int64_t x0, y0;
129
+ phi(p[2 * h], &x0, wx); phi(p[2 * h + 1], &y0, wy);
130
+ for (int i = 0; i < 3; i++) for (int j = 0; j < 3; j++) {
131
+ real_t w = wx[i] * wy[j] * beta;
132
+ if (w == 0.0) continue;
133
+ real_t *S = cell_write(table, x0 + i, y0 + j);
134
+ real_t d0 = (v[0] - alpha * S[0]) * w, d1 = (v[1] - alpha * S[1]) * w;
135
+ S[0] += d0; S[1] += d1;
136
+ }
137
+ phi(p[2 * H + 2 * h], &x0, wx); phi(p[2 * H + 2 * h + 1], &y0, wy);
138
+ out[0] = out[1] = 0.0;
139
+ for (int i = 0; i < 3; i++) for (int j = 0; j < 3; j++) {
140
+ const real_t *S = cell_read(table, x0 + i, y0 + j);
141
+ out[0] += wx[i] * wy[j] * S[0]; out[1] += wx[i] * wy[j] * S[1];
142
+ }
143
+ }
144
+
145
+ /* One token through every layer, then the most likely next token. */
146
+ static int32_t forward(int32_t token) {
147
+ static real_t x[64], proj[512], mem[64], res[64], pre[256], gate[128], feat[16];
148
+ const int D = M.D;
149
+ memcpy(x, M.embed + (size_t)token * D, D * sizeof(real_t));
150
+ for (int l = 0; l < M.layers; l++) {
151
+ const Layer *L = &M.layer[l];
152
+ matvec(L->qkv_w, M.proj_out, D, x, L->qkv_b, proj);
153
+ for (int h = 0; h < M.H; h++) memory_step(l * M.H + h, proj, h, mem + 2 * h);
154
+ matvec(L->out_w, D, 2 * M.H, mem, NULL, res);
155
+ for (int i = 0; i < D; i++) x[i] += res[i];
156
+ matvec(L->ff_in_w, 2 * M.d_ffn, D, x, NULL, pre);
157
+ for (int j = 0; j < M.d_ffn; j++) gate[j] = (pre[j] > 0.0 ? pre[j] : 0.0) * pre[M.d_ffn + j];
158
+ matvec(L->ff_out_w, D, M.d_ffn, gate, NULL, res);
159
+ for (int i = 0; i < D; i++) x[i] += res[i];
160
+ }
161
+ matvec(M.basis, M.rank, D, x, NULL, feat);
162
+ real_t best = -HUGE_VAL; int32_t best_row = 0;
163
+ for (int r = 0; r < M.n_out; r++) {
164
+ real_t acc = 0.0;
165
+ for (int k = 0; k < M.rank; k++) acc += M.coeff[(size_t)r * M.rank + k] * feat[k];
166
+ if (acc > best) { best = acc; best_row = r; }
167
+ }
168
+ return M.out_ids[best_row];
169
+ }
170
+
171
+ /* ── loading ─────────────────────────────────────────────────────────── */
172
+ static void poke(int64_t address, const uint8_t *bytes, size_t n) { /* bytes into the memory's cells */
173
+ int table = number("memory_layer") * M.H + number("memory_head"); double spacing = number("spacing");
174
+ for (size_t i = 0; i < n; i++, address++) {
175
+ real_t *s = cell_write(table, (int64_t)(spacing * (double)(address % 65536)), (int64_t)(spacing * (double)(address / 65536)));
176
+ s[0] = (real_t)bytes[i]; s[1] = 0.0;
177
+ }
178
+ }
179
+ static void poke_word(int64_t address, uint32_t v) { uint8_t b[4] = {v & 255, v >> 8 & 255, v >> 16 & 255, v >> 24}; poke(address, b, 4); }
180
+
181
+ int spotlight_load(const char *dir) {
182
+ snprintf(folder, sizeof folder, "%s", dir);
183
+ config = slurp(file("intelligence/config.json"), NULL);
184
+ M.D = number("d_model"); M.H = number("n_heads"); M.layers = number("n_layers"); M.vocab = number("vocab_size");
185
+ M.proj_out = number("proj_out"); M.stop_id = number("stop_id"); M.n_out = number("n_out");
186
+ M.d_ffn = number("d_ffn"); M.rank = number("head_rank");
187
+ if (number("d_rest") != 0 || number("d_v") != 2 || number("alpha_rows") != 1) die("unsupported model shape");
188
+ char *vocab = slurp(file("intelligence/vocab.json"), NULL), *p = vocab, name[64];
189
+ M.tokens = alloc(M.vocab * sizeof(char *));
190
+ for (int i = 0; i < M.vocab; i++) {
191
+ p = strchr(p, '"') + 1; char *q = M.tokens[i] = alloc(64);
192
+ while (*p != '"') { if (*p == '\\') p++; *q++ = *p++; }
193
+ p++;
194
+ }
195
+ char *w = slurp(file("intelligence/model.safetensors"), NULL);
196
+ M.layer = alloc(M.layers * sizeof(Layer));
197
+ for (int l = 0; l < M.layers; l++) {
198
+ Layer *L = &M.layer[l];
199
+ snprintf(name, sizeof name, "layers.%d.qkv_w", l); L->qkv_w = load(w, name, (int64_t)M.proj_out * M.D);
200
+ snprintf(name, sizeof name, "layers.%d.qkv_b", l); L->qkv_b = load(w, name, M.proj_out);
201
+ snprintf(name, sizeof name, "layers.%d.out_w", l); L->out_w = load(w, name, (int64_t)M.D * 2 * M.H);
202
+ snprintf(name, sizeof name, "layers.%d.ff_in_w", l); L->ff_in_w = load(w, name, (int64_t)2 * M.d_ffn * M.D);
203
+ snprintf(name, sizeof name, "layers.%d.ff_out_w", l); L->ff_out_w = load(w, name, (int64_t)M.D * M.d_ffn);
204
+ }
205
+ M.embed = load(w, "embed_tokens.weight", (int64_t)M.vocab * M.D);
206
+ M.basis = load(w, "head_basis", (int64_t)M.rank * M.D);
207
+ M.coeff = load(w, "head_coeff", (int64_t)M.n_out * M.rank);
208
+ real_t *ids = load(w, "out_ids", M.n_out);
209
+ M.out_ids = alloc(M.n_out * sizeof(int32_t));
210
+ for (int i = 0; i < M.n_out; i++) M.out_ids[i] = (int32_t)ids[i];
211
+ free(vocab); free(w); free(ids);
212
+ return M.vocab;
213
+ }
214
+
215
+ /* A fresh memory: MicroPython's code, tables and boot state, then the packages in one registry. */
216
+ static void load_memory(char **packages, int n) {
217
+ free(cells); cells = NULL; cells_cap = cells_n = 0;
218
+ char *core = slurp(file("memory/core.safetensors"), NULL), name[64];
219
+ for (int t = 0; t < M.layers * M.H; t++) {
220
+ Tensor xy, value;
221
+ snprintf(name, sizeof name, "cells.%d.%d.xy", t / M.H, t % M.H); if (!tensor(core, name, &xy)) continue;
222
+ snprintf(name, sizeof name, "cells.%d.%d.value", t / M.H, t % M.H); if (!tensor(core, name, &value)) continue;
223
+ for (int64_t i = 0; i < xy.count / 2; i++) {
224
+ real_t *s = cell_write(t, (int64_t)item(&xy, 2 * i), (int64_t)item(&xy, 2 * i + 1));
225
+ s[0] = (real_t)item(&value, 2 * i); s[1] = (real_t)item(&value, 2 * i + 1);
226
+ }
227
+ }
228
+ free(core);
229
+ if (n == 0) return;
230
+ int64_t base = number("registry_base"), size = 16, pages, modules = 0;
231
+ for (int i = 0; i < n; i++) {
232
+ char *bytes = slurp(packages[i], NULL); Tensor b;
233
+ if (!tensor(bytes, "bundle", &b) || memcmp(b.data, "SPKG", 4)) die("not a package");
234
+ poke(base + size, (const uint8_t *)b.data + 16, b.count - 16);
235
+ uint32_t count; memcpy(&count, b.data + 12, 4);
236
+ size += b.count - 16; modules += count;
237
+ free(bytes);
238
+ }
239
+ uint8_t header[8] = {'S', 'P', 'K', 'G', 1};
240
+ poke(base, header, 8); poke_word(base + 8, (uint32_t)size); poke_word(base + 12, (uint32_t)modules);
241
+ poke_word(number("registry_root_word"), (uint32_t)base);
242
+ pages = (base + size + 65535) / 65536;
243
+ poke_word(number("memory_pages_word"), (uint32_t)(pages > number("image_pages") ? pages : number("image_pages")));
244
+ }
245
+
246
+ /* ── running ─────────────────────────────────────────────────────────── */
247
+ static int32_t *kept; static int64_t kept_n, kept_cap; static int printing = 0, verbose = 0;
248
+
249
+ /* Runs a prompt from a fresh memory until the stop token (or max_new tokens). The command line
250
+ * prints the output as it comes; the library keeps the tokens that carry it, and the stop token. */
251
+ int64_t spotlight_generate(const int32_t *prompt, int64_t n, int64_t max_new, char **packages, int n_packages) {
252
+ load_memory(packages, n_packages);
253
+ int32_t next = 0; kept_n = 0;
254
+ for (int64_t i = 0; i < n; i++) next = forward(prompt[i]);
255
+ for (int64_t count = 1;; count++, next = forward(next)) {
256
+ const char *t = M.tokens[next]; int out = !strncmp(t, "out(", 4);
257
+ if (verbose) fprintf(stderr, "%s ", t);
258
+ if (printing && out) { putchar(strlen(t) == 6 ? t[4] : (int)strtol(t + 4, NULL, 16)); fflush(stdout); }
259
+ if (!printing && (out || next == M.stop_id)) {
260
+ if (kept_n == kept_cap) kept = realloc(kept, (kept_cap = kept_cap ? 2 * kept_cap : 1024) * sizeof(int32_t));
261
+ kept[kept_n++] = next;
262
+ }
263
+ if (next == M.stop_id || count == max_new) return count;
264
+ }
265
+ }
266
+ const int32_t *spotlight_kept(int64_t *n) { *n = kept_n; return kept; }
267
+
268
+ #ifndef SPOTLIGHT_LIBRARY
269
+ static int32_t token(const char *name) {
270
+ for (int32_t i = 0; i < M.vocab; i++) if (!strcmp(M.tokens[i], name)) return i;
271
+ die(name); return -1;
272
+ }
273
+ static int is_package(const struct dirent *e) {
274
+ size_t n = strlen(e->d_name);
275
+ return n > 12 && !strcmp(e->d_name + n - 12, ".safetensors") && strcmp(e->d_name, "core.safetensors");
276
+ }
277
+ int main(int argc, char **argv) {
278
+ verbose = argc > 1 && !strcmp(argv[1], "-v"); printing = 1;
279
+ spotlight_load(".");
280
+ struct dirent **list; int n_packages = scandir("memory", &list, is_package, alphasort);
281
+ char **packages = alloc((n_packages > 0 ? n_packages : 1) * sizeof(char *));
282
+ for (int i = 0; i < n_packages; i++) { packages[i] = alloc(300); snprintf(packages[i], 300, "memory/%s", list[i]->d_name); }
283
+ /* The prompt: where the source goes, its bytes (and a NUL) page by page, then execute. */
284
+ size_t n; char *src = slurp(NULL, &n), hex[16];
285
+ int64_t input = number("input_base"), pages = (input % 65536 + (int64_t)n) / 65536 + 1, count = 0;
286
+ int32_t *prompt = alloc((n + 16 * pages + 8) * sizeof(int32_t));
287
+ for (int64_t r = pages - 1; r >= 0; r--) {
288
+ uint32_t address = (uint32_t)(r ? (input / 65536 + r) * 65536 : input);
289
+ for (int lane = 0; lane < 4; lane++) { snprintf(hex, sizeof hex, "%02x", address >> 8 * lane & 255); prompt[count++] = token(hex); }
290
+ prompt[count++] = token("page");
291
+ }
292
+ for (int64_t i = 0; i <= (int64_t)n; i++) {
293
+ unsigned char b = i < (int64_t)n ? src[i] : 0;
294
+ if (b >= 128) die("the program must be ASCII");
295
+ if (i && (input + i) % 65536 == 0) prompt[count++] = token("unpage");
296
+ if (b > 0x20 && b < 0x7f) { hex[0] = b; hex[1] = 0; } else snprintf(hex, sizeof hex, "ascii(%02x)", b);
297
+ prompt[count++] = token(hex);
298
+ }
299
+ prompt[count++] = token("execute");
300
+ count = spotlight_generate(prompt, count, INT64_MAX, packages, n_packages > 0 ? n_packages : 0);
301
+ fprintf(stderr, "%s%lld tokens generated\n", verbose ? "\n" : "", (long long)count);
302
+ return 0;
303
+ }
304
+ #endif
spotlight.py ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Spotlight VM as a `transformers` model. The model runs spotlight.c, built into build/ on first use."""
2
+ import ctypes, glob, json, os, subprocess
3
+
4
+ import torch
5
+ from huggingface_hub import snapshot_download
6
+ from transformers import PretrainedConfig, PreTrainedModel, PreTrainedTokenizer
7
+
8
+
9
+ class SpotlightConfig(PretrainedConfig):
10
+ model_type = "spotlight"
11
+
12
+
13
+ class SpotlightForCausalLM(PreTrainedModel):
14
+ config_class = SpotlightConfig
15
+
16
+ @classmethod
17
+ def from_pretrained(cls, name_or_path, *args, **kwargs):
18
+ folder = os.path.abspath(name_or_path if os.path.isdir(name_or_path) else snapshot_download(name_or_path))
19
+ library = os.path.join(folder, "build", "libspotlight.so")
20
+ if not os.path.exists(library):
21
+ os.makedirs(os.path.dirname(library), exist_ok=True)
22
+ source = os.path.join(folder, "spotlight.c")
23
+ subprocess.run(["cc", "-O3", "-std=c99", "-shared", "-fPIC", "-DSPOTLIGHT_LIBRARY", source, "-lm", "-o", library], check=True)
24
+ model = cls(SpotlightConfig.from_pretrained(folder))
25
+ model.folder, model.lib = folder, ctypes.CDLL(library)
26
+ model.lib.spotlight_generate.restype = ctypes.c_int64
27
+ model.lib.spotlight_kept.restype = ctypes.POINTER(ctypes.c_int32)
28
+ model.lib.spotlight_load(folder.encode())
29
+ return model
30
+
31
+ @torch.no_grad()
32
+ def generate(self, input_ids, max_new_tokens=10**12, packages=None, **kwargs):
33
+ """Runs the program from a fresh memory: the core plus `packages` (default: all in memory/).
34
+ Returns the prompt followed by the generated tokens that carry output, and the stop token."""
35
+ if packages is None:
36
+ packages = [p for p in sorted(glob.glob(os.path.join(self.folder, "memory", "*.safetensors")))
37
+ if not p.endswith("core.safetensors")]
38
+ paths = (ctypes.c_char_p * max(1, len(packages)))(*[os.path.abspath(p).encode() for p in packages])
39
+ prompt = input_ids[0].to(torch.int32).contiguous()
40
+ self.generated_tokens = self.lib.spotlight_generate(ctypes.c_void_p(prompt.data_ptr()), ctypes.c_int64(prompt.numel()),
41
+ ctypes.c_int64(max_new_tokens), paths, len(packages))
42
+ n = ctypes.c_int64()
43
+ kept = ctypes.string_at(self.lib.spotlight_kept(ctypes.byref(n)), 4 * n.value)
44
+ return torch.cat([prompt, torch.frombuffer(bytearray(kept), dtype=torch.int32)]).long()[None]
45
+
46
+
47
+ class SpotlightTokenizer(PreTrainedTokenizer):
48
+ vocab_files_names = {"vocab_file": "intelligence/vocab.json", "config_file": "intelligence/config.json"}
49
+
50
+ def __init__(self, vocab_file, config_file, **kwargs):
51
+ with open(vocab_file) as f:
52
+ self.names = json.load(f)
53
+ self.ids = {name: i for i, name in enumerate(self.names)}
54
+ with open(config_file) as f:
55
+ self.input_base = json.load(f)["input_base"]
56
+ super().__init__(**kwargs)
57
+
58
+ vocab_size = property(lambda self: len(self.names))
59
+ get_vocab = lambda self: dict(self.ids)
60
+ _convert_token_to_id = lambda self, token: self.ids[token]
61
+ _convert_id_to_token = lambda self, index: self.names[index]
62
+
63
+ def _tokenize(self, text, **kwargs):
64
+ """Where the source goes, its bytes (and a NUL) page by page, then execute -- as spotlight.c does."""
65
+ data, base, tokens = text.encode("ascii") + b"\0", self.input_base, []
66
+ for page in reversed(range((base % 65536 + len(data) - 1) // 65536 + 1)):
67
+ address = (base // 65536 + page) * 65536 if page else base
68
+ tokens += [f"{address >> 8 * lane & 255:02x}" for lane in range(4)] + ["page"]
69
+ for i, b in enumerate(data):
70
+ tokens += (["unpage"] if i and (base + i) % 65536 == 0 else []) + [chr(b) if 0x20 < b < 0x7F else f"ascii({b:02x})"]
71
+ return tokens + ["execute"]
72
+
73
+ def decode(self, token_ids, **kwargs):
74
+ """The program's printed output: the bytes carried by the out(..) tokens."""
75
+ names = [self.names[i] for i in (token_ids.tolist() if hasattr(token_ids, "tolist") else token_ids)]
76
+ return bytes(ord(n[4]) if len(n) == 6 else int(n[4:-1], 16) for n in names if n.startswith("out(")).decode("latin-1")