Ex0bit commited on
Commit
5a8cdaf
·
verified ·
1 Parent(s): 20a3a74

fix: audioop compat for Python 3.13, plain-language UI

Browse files
Files changed (2) hide show
  1. app.py +76 -73
  2. requirements.txt +2 -0
app.py CHANGED
@@ -1,14 +1,14 @@
1
  import gradio as gr
2
  import torch
3
- import sys, os, json, time, hashlib
4
 
5
  sys.path.insert(0, "src")
6
 
7
  from mulattice.protocol import (
8
- SynthCfg, build_model, force_fast_scan, logits_at, synth_batch, key_addresses
9
  )
10
 
11
- DEVICE = "cpu" # HF free tier
12
  CFG = SynthCfg()
13
 
14
  print("Loading model...", flush=True)
@@ -21,9 +21,7 @@ force_fast_scan(MODEL)
21
  print("Model loaded.", flush=True)
22
 
23
 
24
- # --- Section 1: Your own stream ---
25
  def run_custom(text, *pair_inputs):
26
- """Store user's facts in user's text, overwrite some, query all."""
27
  seed = int(time.time()) % 100000
28
  pairs = []
29
  for i in range(0, len(pair_inputs), 3):
@@ -32,7 +30,7 @@ def run_custom(text, *pair_inputs):
32
  pairs.append({"name": name.strip(), "value": val.strip(),
33
  "new_value": new_val.strip() if new_val.strip() else None})
34
  if not pairs:
35
- return "Enter at least one fact (name and value).", ""
36
 
37
  used = set()
38
  def h(s, span, off):
@@ -104,111 +102,116 @@ def run_custom(text, *pair_inputs):
104
 
105
  inv = {v: k for k, v in vmap.items()}
106
  correct = 0
107
- lines = ["| Asked | Answered | Expected | Result |", "|---|---|---|---|"]
108
  for q, r in enumerate(store_rows):
109
- got = inv.get(int(pred[0, q]), f"?{int(pred[0,q])}")
110
  exp = r["new_value"] if r["new_value"] else r["value"]
111
  ok = got == exp
112
  correct += ok
113
- old = f" (was: {r['value']})" if r["new_value"] else ""
114
- lines.append(f"| {r['name']} | **{got}** | {exp}{old} | {'✅' if ok else '❌'} |")
115
 
116
- stats = f"\n\n**{correct}/{len(store_rows)} correct** · {L:,} tokens · {dt:.2f}s · {dt/L*1e6:.0f}μs/token"
117
  return "\n".join(lines), stats
118
 
119
 
120
- # --- Section 2: Scale test ---
121
- def run_scale(n_pairs, filler, overwrite):
122
  g = torch.Generator().manual_seed(42)
123
  b = synth_batch(1, int(n_pairs), min(32, int(n_pairs)), CFG,
124
- filler=int(filler), overwrite_frac=float(overwrite)/100, generator=g)
125
  t0 = time.time()
126
  with torch.no_grad():
127
  pred = logits_at(MODEL, b["tokens"], b["ans_pos"]).argmax(-1).cpu()
128
  dt = time.time() - t0
129
  ok = (pred == b["gold"]).squeeze(0)
130
  n_cells = MODEL.blocks[0].mixer.scan.last_n_cells
131
- return (f"Recall: **{ok.float().mean():.4f}** ({int(ok.sum())}/{ok.numel()})\n\n"
132
- f"Tokens: {b['L']:,} · Cells: {n_cells:,} · Time: {dt:.2f}s · "
133
- f"{dt/b['L']*1e6:.0f}μs/token")
134
-
135
-
136
- # --- Build UI ---
137
- with gr.Blocks(title="μLattice — Breaking the Quadratic Memory Barrier in AI",
138
- theme=gr.themes.Default(font=["Inter", "sans-serif"])) as demo:
 
 
 
 
 
 
 
139
  gr.Markdown("""
140
  # μLattice
141
- ## Breaking the quadratic memory barrier in AI
142
-
143
  **Tensorbend Research · Eric E. · October 2026**
144
-
145
- A memory system for AI models that grows as it reads while the cost per token stays flat.
146
- Store thousands of associations, overwrite any of them, and recall them all —
147
- whether the memory holds ten facts or eight thousand.
148
-
149
- Each token reads and writes exactly **9 cells** on a 2D lattice. Memory grows with content.
150
- Access cost doesn't.
151
  """)
152
 
153
- with gr.Tab("📖 Your Own Facts"):
154
  gr.Markdown("""
155
- **Paste any text below** (it becomes the stream the model reads).
156
- **Define facts** as name → value pairs. Mark which get **overwritten** mid-stream.
157
- The model stores, overwrites, and answers — in one pass through your text.
 
158
  """)
159
  with gr.Row():
160
- with gr.Column():
161
- doc = gr.Textbox(label="Your text (becomes the stream)", lines=5,
162
- value="The harbour was quiet that morning. Gulls circled the masts while the tide went out. A clerk stamped papers without looking up. Somewhere a bell rang twice, then stopped. The road east had been washed out again. Dust settled over the market stalls.")
 
 
 
163
  with gr.Row():
164
- n1 = gr.Textbox(label="Fact name", value="the vault password")
165
- v1 = gr.Textbox(label="Value", value="swordfish")
166
- nv1 = gr.Textbox(label="New value (overwrite to)", value="bluedragon")
167
  with gr.Row():
168
- n2 = gr.Textbox(label="Fact name", value="the meeting time")
169
- v2 = gr.Textbox(label="Value", value="3pm")
170
- nv2 = gr.Textbox(label="New value", value="")
171
  with gr.Row():
172
- n3 = gr.Textbox(label="Fact name", value="")
173
- v3 = gr.Textbox(label="Value", value="")
174
- nv3 = gr.Textbox(label="New value", value="")
175
- btn1 = gr.Button("Read, store, overwrite — and answer", variant="primary")
176
- with gr.Column():
177
  out1 = gr.Markdown()
178
  stats1 = gr.Markdown()
179
  btn1.click(run_custom, inputs=[doc, n1,v1,nv1, n2,v2,nv2, n3,v3,nv3], outputs=[out1, stats1])
180
 
181
- with gr.Tab("📊 Store at Scale"):
182
  gr.Markdown("""
183
- Test the model at scale: up to **8,192 stored pairs**, **50% overwritten**,
184
- answered after a single causal pass.
185
  """)
186
  with gr.Row():
187
- np_slider = gr.Slider(64, 8192, value=256, step=64, label="Pairs to store")
188
- fl_slider = gr.Slider(0, 14, value=14, step=1, label="Filler tokens per pair")
189
- ow_slider = gr.Slider(0, 100, value=50, step=10, label="% overwritten")
190
- btn2 = gr.Button("Stream & query", variant="primary")
 
 
 
191
  out2 = gr.Markdown()
192
- btn2.click(run_scale, inputs=[np_slider, fl_slider, ow_slider], outputs=[out2])
193
 
194
  gr.Markdown("""
195
  ---
196
-
197
- **Every number on this page is produced by a live forward pass** of the trained model
198
- on the released checkpoint. Nothing is precomputed.
199
-
200
- [Paper](https://github.com/eelbaz/mLattice/blob/main/PAPER.md) ·
201
- [Code](https://github.com/eelbaz/mLattice) ·
202
- [Tests](https://github.com/eelbaz/mLattice/tree/main/tests)
203
-
204
- ```bibtex
205
- @misc{mulattice2026,
206
- title = {μLattice: Breaking the Quadratic Memory Barrier in AI},
207
- author = {Eric E. and Tensorbend Research},
208
- year = {2026},
209
- url = {github.com/eelbaz/mLattice}
210
- }
211
- ```
212
  """)
213
 
214
  demo.launch()
 
1
  import gradio as gr
2
  import torch
3
+ import sys, os, time, hashlib
4
 
5
  sys.path.insert(0, "src")
6
 
7
  from mulattice.protocol import (
8
+ SynthCfg, build_model, force_fast_scan, logits_at, synth_batch
9
  )
10
 
11
+ DEVICE = "cpu"
12
  CFG = SynthCfg()
13
 
14
  print("Loading model...", flush=True)
 
21
  print("Model loaded.", flush=True)
22
 
23
 
 
24
  def run_custom(text, *pair_inputs):
 
25
  seed = int(time.time()) % 100000
26
  pairs = []
27
  for i in range(0, len(pair_inputs), 3):
 
30
  pairs.append({"name": name.strip(), "value": val.strip(),
31
  "new_value": new_val.strip() if new_val.strip() else None})
32
  if not pairs:
33
+ return "Enter at least one fact (a name and a value).", ""
34
 
35
  used = set()
36
  def h(s, span, off):
 
102
 
103
  inv = {v: k for k, v in vmap.items()}
104
  correct = 0
105
+ lines = ["| Asked | Answered | Expected | |", "|---|---|---|---|"]
106
  for q, r in enumerate(store_rows):
107
+ got = inv.get(int(pred[0, q]), "?")
108
  exp = r["new_value"] if r["new_value"] else r["value"]
109
  ok = got == exp
110
  correct += ok
111
+ old = f" *(changed from: {r['value']})*" if r["new_value"] else ""
112
+ lines.append(f"| **{r['name']}** | **{got}** | {exp}{old} | {'✅' if ok else '❌'} |")
113
 
114
+ stats = f"\n**{correct} out of {len(store_rows)} correct** — the model read {L:,} tokens in {dt:.2f} seconds ({dt/L*1e6:.0f} millionths of a second per token)"
115
  return "\n".join(lines), stats
116
 
117
 
118
+ def run_scale(n_pairs, gap_words, pct_changed):
 
119
  g = torch.Generator().manual_seed(42)
120
  b = synth_batch(1, int(n_pairs), min(32, int(n_pairs)), CFG,
121
+ filler=int(gap_words), overwrite_frac=float(pct_changed)/100, generator=g)
122
  t0 = time.time()
123
  with torch.no_grad():
124
  pred = logits_at(MODEL, b["tokens"], b["ans_pos"]).argmax(-1).cpu()
125
  dt = time.time() - t0
126
  ok = (pred == b["gold"]).squeeze(0)
127
  n_cells = MODEL.blocks[0].mixer.scan.last_n_cells
128
+ return (f"### **{ok.float().mean():.1%} correct** ({int(ok.sum())} out of {ok.numel()})\n\n"
129
+ f"The model read **{b['L']:,} words** in one pass and stored **{n_cells:,} memory slots**.\n\n"
130
+ f"Time: {dt:.2f} seconds — that's **{dt/b['L']*1e6:.0f}μs per word**, "
131
+ f"whether it stored {int(n_pairs)} facts or 8,000.")
132
+
133
+
134
+ with gr.Blocks(
135
+ title="μLattice — AI Memory That Grows Without the Cost Growing",
136
+ theme=gr.themes.Soft(font=["Inter", "sans-serif"]),
137
+ css="""
138
+ .gradio-container {max-width: 900px !important; margin: auto !important;}
139
+ h1 {font-size: 2.2em !important; font-weight: 300 !important;}
140
+ h2 {color: #2547d0 !important; font-weight: 400 !important;}
141
+ """
142
+ ) as demo:
143
  gr.Markdown("""
144
  # μLattice
145
+ ## AI memory that grows without the cost growing
146
+
147
  **Tensorbend Research · Eric E. · October 2026**
148
+
149
+ Today's AI models pay more and more to remember more. μLattice fixes this:
150
+ memory grows as the model reads, but the cost of processing each word stays the same.
151
+
152
+ Every word the model reads touches exactly **9 memory slots** — whether the model
153
+ is storing 10 facts or 8,000. Try it below with your own facts.
 
154
  """)
155
 
156
+ with gr.Tab("✏️ Try It With Your Own Facts"):
157
  gr.Markdown("""
158
+ Type any text below — it becomes the words the model reads.
159
+ Then define facts as **name → value** pairs. If you fill in the
160
+ **"changed to"** field, the fact gets replaced mid-stream and the model
161
+ must remember the **new** value.
162
  """)
163
  with gr.Row():
164
+ with gr.Column(scale=1):
165
+ doc = gr.Textbox(
166
+ label="Any text (the model reads this)",
167
+ lines=5,
168
+ value="The harbour was quiet that morning. Gulls circled the masts while the tide went out. A clerk stamped papers without looking up. Somewhere a bell rang twice, then stopped. The road east had been washed out again.")
169
+ gr.Markdown("**Your facts**")
170
  with gr.Row():
171
+ n1 = gr.Textbox(label="Name", value="the vault password", scale=1)
172
+ v1 = gr.Textbox(label="Value", value="swordfish", scale=1)
173
+ nv1 = gr.Textbox(label="Changed to (optional)", value="bluedragon", scale=1)
174
  with gr.Row():
175
+ n2 = gr.Textbox(label="Name", value="the meeting time", scale=1)
176
+ v2 = gr.Textbox(label="Value", value="3pm", scale=1)
177
+ nv2 = gr.Textbox(label="Changed to (optional)", value="", scale=1)
178
  with gr.Row():
179
+ n3 = gr.Textbox(label="Name", value="", scale=1)
180
+ v3 = gr.Textbox(label="Value", value="", scale=1)
181
+ nv3 = gr.Textbox(label="Changed to (optional)", value="", scale=1)
182
+ btn1 = gr.Button("Store, overwrite, and recall", variant="primary", size="lg")
183
+ with gr.Column(scale=1):
184
  out1 = gr.Markdown()
185
  stats1 = gr.Markdown()
186
  btn1.click(run_custom, inputs=[doc, n1,v1,nv1, n2,v2,nv2, n3,v3,nv3], outputs=[out1, stats1])
187
 
188
+ with gr.Tab("🔬 Stress Test"):
189
  gr.Markdown("""
190
+ Test the model at scale. Store hundreds or thousands of facts in one pass,
191
+ change some of them mid-stream, then ask for them all back.
192
  """)
193
  with gr.Row():
194
+ np_slider = gr.Slider(64, 2048, value=256, step=64,
195
+ label="How many facts to store")
196
+ gap_slider = gr.Slider(0, 14, value=8, step=1,
197
+ label="Words between each fact")
198
+ ow_slider = gr.Slider(0, 100, value=50, step=10,
199
+ label="% of facts changed mid-stream")
200
+ btn2 = gr.Button("Run the stress test", variant="primary", size="lg")
201
  out2 = gr.Markdown()
202
+ btn2.click(run_scale, inputs=[np_slider, gap_slider, ow_slider], outputs=[out2])
203
 
204
  gr.Markdown("""
205
  ---
206
+
207
+ Every answer above is produced by a **live forward pass** of the trained model.
208
+ Nothing is precomputed or cached.
209
+
210
+ [📄 Full paper](https://github.com/eelbaz/mLattice/blob/main/PAPER.md) ·
211
+ [💻 Code & tests](https://github.com/eelbaz/mLattice) ·
212
+ [📊 All results](https://github.com/eelbaz/mLattice/tree/main/results)
213
+
214
+ *Tensorbend Research · Eric E. · October 2026*
 
 
 
 
 
 
 
215
  """)
216
 
217
  demo.launch()
requirements.txt CHANGED
@@ -1,2 +1,4 @@
 
 
1
  torch>=2.4
2
  numpy
 
1
+ audioop-lts
2
+ pydub
3
  torch>=2.4
4
  numpy