fluidlayer 2.0.0__tar.gz → 2.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/PKG-INFO +30 -31
  2. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/README.md +28 -29
  3. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/docs/BLOG.md +3 -4
  4. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/docs/CHANGELOG.md +9 -0
  5. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/docs/COMPARISON.md +4 -4
  6. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/docs/DESIGN_pinned_memory.md +11 -12
  7. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/docs/FRAMEWORK.md +6 -2
  8. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/docs/GETTING_STARTED.md +17 -0
  9. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/docs/GRAFT.md +12 -47
  10. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/docs/MILESTONES.md +9 -16
  11. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/docs/NEGATIVE-RESULTS.md +34 -87
  12. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/docs/POSITIONING.md +9 -23
  13. fluidlayer-2.1.0/docs/PROCESS.md +347 -0
  14. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/docs/README.md +4 -0
  15. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/docs/REPRODUCING.md +40 -6
  16. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/docs/TEN-MILLION.md +8 -2
  17. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/docs/index.html +3 -3
  18. fluidlayer-2.1.0/examples/appkit/attach_layer.py +235 -0
  19. fluidlayer-2.1.0/examples/appkit/load_model.py +63 -0
  20. fluidlayer-2.1.0/experiments/e15_scale_model.py +317 -0
  21. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/experiments/e9_ten_million.py +96 -78
  22. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/experiments/pretrain_prior.py +5 -3
  23. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/fluidlayer/__init__.py +1 -1
  24. fluidlayer-2.1.0/fluidlayer/qwen2_model.py +156 -0
  25. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/fluidlayer.egg-info/PKG-INFO +30 -31
  26. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/fluidlayer.egg-info/SOURCES.txt +6 -0
  27. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/pyproject.toml +2 -2
  28. fluidlayer-2.1.0/tests/test_qwen2_model.py +26 -0
  29. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/CITATION.cff +0 -0
  30. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/LICENSE +0 -0
  31. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/MANIFEST.in +0 -0
  32. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/Makefile +0 -0
  33. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/docs/API.md +0 -0
  34. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/docs/LIMITATION.md +0 -0
  35. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/examples/gate_demo.py +0 -0
  36. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/examples/graft_demo.py +0 -0
  37. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/examples/quickstart.py +0 -0
  38. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/experiments/e10_gate.py +0 -0
  39. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/experiments/e11_exact.py +0 -0
  40. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/experiments/e12_router.py +0 -0
  41. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/experiments/e13_knn_baseline.py +0 -0
  42. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/experiments/e14_real_gpt2.py +0 -0
  43. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/experiments/e1_prior_perplexity.py +0 -0
  44. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/experiments/e2_scaling.py +0 -0
  45. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/experiments/e4_gbalance.py +0 -0
  46. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/experiments/e5_graft.py +0 -0
  47. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/experiments/e6_graft.py +0 -0
  48. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/experiments/e6_real_corpus.py +0 -0
  49. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/experiments/e7_lossy_fix.py +0 -0
  50. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/experiments/gpu_graft.py +0 -0
  51. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/experiments/run_all.py +0 -0
  52. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/fluidlayer/autodiff.py +0 -0
  53. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/fluidlayer/blocks.py +0 -0
  54. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/fluidlayer/bpe.py +0 -0
  55. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/fluidlayer/data.py +0 -0
  56. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/fluidlayer/diffusion.py +0 -0
  57. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/fluidlayer/gpt2_model.py +0 -0
  58. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/fluidlayer/gpt2_tokenizer.py +0 -0
  59. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/fluidlayer/graft.py +0 -0
  60. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/fluidlayer/losses.py +0 -0
  61. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/fluidlayer/memory.py +0 -0
  62. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/fluidlayer/model.py +0 -0
  63. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/fluidlayer/optim.py +0 -0
  64. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/fluidlayer/py.typed +0 -0
  65. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/fluidlayer/sheaf.py +0 -0
  66. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/fluidlayer/topology.py +0 -0
  67. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/fluidlayer/torch_graft.py +0 -0
  68. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/fluidlayer.egg-info/dependency_links.txt +0 -0
  69. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/fluidlayer.egg-info/requires.txt +0 -0
  70. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/fluidlayer.egg-info/top_level.txt +0 -0
  71. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/fluidlayer_single.py +0 -0
  72. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/requirements.txt +0 -0
  73. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/run_without_pytest.py +0 -0
  74. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/selftest.py +0 -0
  75. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/setup.cfg +0 -0
  76. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/tests/conftest.py +0 -0
  77. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/tests/test_bpe.py +0 -0
  78. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/tests/test_graft.py +0 -0
  79. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/tests/test_memory.py +0 -0
  80. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/tests/test_selftest.py +0 -0
  81. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/tests/test_topology.py +0 -0
  82. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/tests/test_torch_parity.py +0 -0
  83. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/tools/_bundle_template.py +0 -0
  84. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/tools/bundle_single_file.py +0 -0
  85. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/tools/download_gpt2.py +0 -0
  86. {fluidlayer-2.0.0 → fluidlayer-2.1.0}/tools/fetch_pypi.py +0 -0
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fluidlayer
3
- Version: 2.0.0
4
- Summary: A research memory layer for language models using cellular-sheaf diffusion
3
+ Version: 2.1.0
4
+ Summary: A research memory layer for language models with optional GPT-2 and Qwen2 adapters
5
5
  Author: Kapil Dhinwa
6
6
  License: MIT
7
7
  Project-URL: Homepage, https://github.com/kapildhinwa2010-dev/fluidtech
@@ -216,14 +216,17 @@ Details: [`docs/TEN-MILLION.md`](docs/TEN-MILLION.md)
216
216
  ## The negative results
217
217
 
218
218
  This is the part that makes the rest believable.
219
- Eleven results came out negative or against expectation, and all eleven are measured, reproducible, and published.
219
+ Eleven negative or unexpected findings are documented. Most have checked-in
220
+ result files; the archived transformer and real-GPT-2 outputs are now
221
+ checked in. Their original model/script environments are not fully included,
222
+ so those historical runs cannot be independently repeated as-is.
220
223
 
221
224
  | What we expected | What happened |
222
225
  |---|---|
223
226
  | The **topological** selection criterion picks the right facts | It does **not** — `0.000` precision vs `0.970` for plain geometric affinity. |
224
227
  | `‖L·1‖∞` detects the frozen state | It does **not** — the frustration index does; the old claim is now a test case. |
225
228
  | `λ₂` predicts long-context quality | Barely — Pearson `0.20`. |
226
- | A transformer loses at some scale | It **wins** at every scale we could train. |
229
+ | A transformer loses at some scale | The archived run says it **wins**; see `results/train_results.json`. |
227
230
  | A domain prior beats a frequency table | It helps (`−0.006 nats`) but a **unigram table wins 6× more**. |
228
231
  | The diffusion tier is neutral on a frozen model | It **degrades** the model by **`+0.81 nats`** (fixed → `+0.0000`, but no upside either). |
229
232
  | Training the layer helps | It **hurts** — the training-free identity map is better (`0.800 vs 0.650`). |
@@ -235,16 +238,18 @@ Read it: [`docs/NEGATIVE-RESULTS.md`](docs/NEGATIVE-RESULTS.md)
235
238
  ## The repository
236
239
 
237
240
  ```text
238
- fluidlayer/ the package (pure NumPy; torch only in torch_graft.py)
241
+ fluidlayer/ the package (NumPy core; optional PyTorch adapters)
239
242
  graft.py the attachable memory layer
240
243
  memory.py the frozen register (20 B per fact, bit-exact)
241
244
  torch_graft.py the same layer in PyTorch, for a real LLM
242
245
  gpt2_model.py a GPT-2 forward pass in PyTorch (no transformers needed)
243
246
  gpt2_tokenizer.py the GPT-2 byte-level BPE, in pure Python
247
+ qwen2_model.py an optional PyTorch Qwen2 forward pass
244
248
  sheaf.py topology.py diffusion.py blocks.py autodiff.py ...
245
249
 
246
250
  experiments/ every measurement; each writes a JSON into results/
247
251
  e14_real_gpt2.py the graft on a REAL pretrained GPT-2 (124M)
252
+ e15_scale_model.py the graft on Qwen2.5-0.5B
248
253
  e13_knn_baseline.py the layer vs. the closest prior art (kNN-LM)
249
254
 
250
255
  tools/ the artifact checker, bundler, checkpoint downloader,
@@ -253,7 +258,7 @@ fluidlayer/bpe.py the byte-level BPE tokenizer
253
258
 
254
259
  tests/ the unit tests (pytest, or run them without it)
255
260
 
256
- examples/ quickstart.py, graft_demo.py, gate_demo.py
261
+ examples/ quickstart.py, graft_demo.py, gate_demo.py, appkit/
257
262
 
258
263
  docs/ the design docs, the API, the limits, the theory report
259
264
 
@@ -273,28 +278,20 @@ and [limitations](docs/LIMITATION.md).
273
278
 
274
279
  ---
275
280
 
276
- ## Status — and it now includes a REAL pretrained LLM
281
+ ## Real-model experiment status
277
282
 
278
- GPT-2 (124M parameters, the real 50,257-token BPE tokenizer), run on CPU with the memory layer attached:
283
+ The E14 GPT-2 experiment script, forward implementation, tokenizer, and
284
+ archived `results/e14_real_gpt2.json` are included. The checkpoint is not;
285
+ rerun E14 to independently reproduce the recorded measurements. See
286
+ [the reproduction guide](docs/REPRODUCING.md) for download and run commands.
279
287
 
280
- | Test | Result |
281
- |---|---|
282
- | Attaching the layer | The logits are **bit-identical** (max diff `0.000e+00`). |
283
- | A fact planted **2,947 tokens** before the query | The base GPT-2 predicts `464`; **the layer predicts the fact**. |
284
- | The base model’s perplexity | `4.0289` (`ppl 56.20`) → **`4.0019` (`ppl 54.70`)** with the layer. |
285
-
286
- And one result that narrows the claim honestly:
287
-
288
- On the real model, the classic kNN-LM interpolation beats the gated override by **8×** on perplexity — the opposite of the 131k-parameter model, where the gate won by **7.4×**.
289
- The gate wins where the base model is weak; interpolation wins where it is strong.
290
- The capability works on both.
291
-
292
- The checkpoint, the forward pass and the tokenizer are all in this repository:
293
-
294
- - [`fluidlayer/gpt2_model.py`](fluidlayer/gpt2_model.py)
295
- - [`fluidlayer/gpt2_tokenizer.py`](fluidlayer/gpt2_tokenizer.py)
296
-
297
- No `transformers` dependency, and the generation is verified coherent.
288
+ E15 adds a from-scratch Qwen2.5-0.5B forward implementation and app-kit
289
+ integration. Its archived run records bit-identical attachment, exact recall
290
+ of a planted fact 1,411 tokens back, and a best gated loss improvement of
291
+ `0.041` nats; the kNN-LM baseline improves loss by `0.274` nats, so this run
292
+ does not show the gate outperforming that baseline. The checkpoint is not
293
+ bundled. Reproduction requires the optional GPU dependencies and local model
294
+ weights; see [E15 instructions](docs/REPRODUCING.md#qwen2-scale-experiment-e15).
298
295
 
299
296
  The Torch twin is now tested against the NumPy reference in [`tests/test_torch_parity.py`](tests/test_torch_parity.py): the two implementations must agree on the router, the store and the gated override.
300
297
 
@@ -314,7 +311,9 @@ claim or validate production-scale operation.
314
311
 
315
312
  ## A research prototype, honestly labelled
316
313
 
317
- Everything above was measured on CPU, at small scale, on a character-level or 512-token subword corpus, with a **131,392-parameter model**.
314
+ The core research experiments use small CPU models and character-level or
315
+ 512-token subword corpora. E14 and E15 are separate pretrained-model
316
+ experiments; their checkpoints are not included.
318
317
 
319
318
  The subword repeat is the closest thing to a realistic tokenizer in this repository.
320
319
  The GPU run, [`experiments/gpu_graft.py`](experiments/gpu_graft.py), is written and has not been executed here.
@@ -370,7 +369,7 @@ A research memory layer with an operator-level stability bound, a bounded in-mem
370
369
  ## Origin and acknowledgments
371
370
 
372
371
  The project began with the author's idea of flowing information through a
373
- topological structure. The implementation and repository organization were
374
- developed with AI assistance. The measurements, limitations, and research
375
- decisions are documented alongside the code so the work can be evaluated and
376
- reproduced.
372
+ topological structure. The author describes it as a school project and
373
+ credits AI assistance for implementation and repository organization. The
374
+ research decisions, measurements, and limitations are documented alongside
375
+ the code so the work can be evaluated and reproduced.
@@ -179,14 +179,17 @@ Details: [`docs/TEN-MILLION.md`](docs/TEN-MILLION.md)
179
179
  ## The negative results
180
180
 
181
181
  This is the part that makes the rest believable.
182
- Eleven results came out negative or against expectation, and all eleven are measured, reproducible, and published.
182
+ Eleven negative or unexpected findings are documented. Most have checked-in
183
+ result files; the archived transformer and real-GPT-2 outputs are now
184
+ checked in. Their original model/script environments are not fully included,
185
+ so those historical runs cannot be independently repeated as-is.
183
186
 
184
187
  | What we expected | What happened |
185
188
  |---|---|
186
189
  | The **topological** selection criterion picks the right facts | It does **not** — `0.000` precision vs `0.970` for plain geometric affinity. |
187
190
  | `‖L·1‖∞` detects the frozen state | It does **not** — the frustration index does; the old claim is now a test case. |
188
191
  | `λ₂` predicts long-context quality | Barely — Pearson `0.20`. |
189
- | A transformer loses at some scale | It **wins** at every scale we could train. |
192
+ | A transformer loses at some scale | The archived run says it **wins**; see `results/train_results.json`. |
190
193
  | A domain prior beats a frequency table | It helps (`−0.006 nats`) but a **unigram table wins 6× more**. |
191
194
  | The diffusion tier is neutral on a frozen model | It **degrades** the model by **`+0.81 nats`** (fixed → `+0.0000`, but no upside either). |
192
195
  | Training the layer helps | It **hurts** — the training-free identity map is better (`0.800 vs 0.650`). |
@@ -198,16 +201,18 @@ Read it: [`docs/NEGATIVE-RESULTS.md`](docs/NEGATIVE-RESULTS.md)
198
201
  ## The repository
199
202
 
200
203
  ```text
201
- fluidlayer/ the package (pure NumPy; torch only in torch_graft.py)
204
+ fluidlayer/ the package (NumPy core; optional PyTorch adapters)
202
205
  graft.py the attachable memory layer
203
206
  memory.py the frozen register (20 B per fact, bit-exact)
204
207
  torch_graft.py the same layer in PyTorch, for a real LLM
205
208
  gpt2_model.py a GPT-2 forward pass in PyTorch (no transformers needed)
206
209
  gpt2_tokenizer.py the GPT-2 byte-level BPE, in pure Python
210
+ qwen2_model.py an optional PyTorch Qwen2 forward pass
207
211
  sheaf.py topology.py diffusion.py blocks.py autodiff.py ...
208
212
 
209
213
  experiments/ every measurement; each writes a JSON into results/
210
214
  e14_real_gpt2.py the graft on a REAL pretrained GPT-2 (124M)
215
+ e15_scale_model.py the graft on Qwen2.5-0.5B
211
216
  e13_knn_baseline.py the layer vs. the closest prior art (kNN-LM)
212
217
 
213
218
  tools/ the artifact checker, bundler, checkpoint downloader,
@@ -216,7 +221,7 @@ fluidlayer/bpe.py the byte-level BPE tokenizer
216
221
 
217
222
  tests/ the unit tests (pytest, or run them without it)
218
223
 
219
- examples/ quickstart.py, graft_demo.py, gate_demo.py
224
+ examples/ quickstart.py, graft_demo.py, gate_demo.py, appkit/
220
225
 
221
226
  docs/ the design docs, the API, the limits, the theory report
222
227
 
@@ -236,28 +241,20 @@ and [limitations](docs/LIMITATION.md).
236
241
 
237
242
  ---
238
243
 
239
- ## Status — and it now includes a REAL pretrained LLM
244
+ ## Real-model experiment status
240
245
 
241
- GPT-2 (124M parameters, the real 50,257-token BPE tokenizer), run on CPU with the memory layer attached:
246
+ The E14 GPT-2 experiment script, forward implementation, tokenizer, and
247
+ archived `results/e14_real_gpt2.json` are included. The checkpoint is not;
248
+ rerun E14 to independently reproduce the recorded measurements. See
249
+ [the reproduction guide](docs/REPRODUCING.md) for download and run commands.
242
250
 
243
- | Test | Result |
244
- |---|---|
245
- | Attaching the layer | The logits are **bit-identical** (max diff `0.000e+00`). |
246
- | A fact planted **2,947 tokens** before the query | The base GPT-2 predicts `464`; **the layer predicts the fact**. |
247
- | The base model’s perplexity | `4.0289` (`ppl 56.20`) → **`4.0019` (`ppl 54.70`)** with the layer. |
248
-
249
- And one result that narrows the claim honestly:
250
-
251
- On the real model, the classic kNN-LM interpolation beats the gated override by **8×** on perplexity — the opposite of the 131k-parameter model, where the gate won by **7.4×**.
252
- The gate wins where the base model is weak; interpolation wins where it is strong.
253
- The capability works on both.
254
-
255
- The checkpoint, the forward pass and the tokenizer are all in this repository:
256
-
257
- - [`fluidlayer/gpt2_model.py`](fluidlayer/gpt2_model.py)
258
- - [`fluidlayer/gpt2_tokenizer.py`](fluidlayer/gpt2_tokenizer.py)
259
-
260
- No `transformers` dependency, and the generation is verified coherent.
251
+ E15 adds a from-scratch Qwen2.5-0.5B forward implementation and app-kit
252
+ integration. Its archived run records bit-identical attachment, exact recall
253
+ of a planted fact 1,411 tokens back, and a best gated loss improvement of
254
+ `0.041` nats; the kNN-LM baseline improves loss by `0.274` nats, so this run
255
+ does not show the gate outperforming that baseline. The checkpoint is not
256
+ bundled. Reproduction requires the optional GPU dependencies and local model
257
+ weights; see [E15 instructions](docs/REPRODUCING.md#qwen2-scale-experiment-e15).
261
258
 
262
259
  The Torch twin is now tested against the NumPy reference in [`tests/test_torch_parity.py`](tests/test_torch_parity.py): the two implementations must agree on the router, the store and the gated override.
263
260
 
@@ -277,7 +274,9 @@ claim or validate production-scale operation.
277
274
 
278
275
  ## A research prototype, honestly labelled
279
276
 
280
- Everything above was measured on CPU, at small scale, on a character-level or 512-token subword corpus, with a **131,392-parameter model**.
277
+ The core research experiments use small CPU models and character-level or
278
+ 512-token subword corpora. E14 and E15 are separate pretrained-model
279
+ experiments; their checkpoints are not included.
281
280
 
282
281
  The subword repeat is the closest thing to a realistic tokenizer in this repository.
283
282
  The GPU run, [`experiments/gpu_graft.py`](experiments/gpu_graft.py), is written and has not been executed here.
@@ -333,7 +332,7 @@ A research memory layer with an operator-level stability bound, a bounded in-mem
333
332
  ## Origin and acknowledgments
334
333
 
335
334
  The project began with the author's idea of flowing information through a
336
- topological structure. The implementation and repository organization were
337
- developed with AI assistance. The measurements, limitations, and research
338
- decisions are documented alongside the code so the work can be evaluated and
339
- reproduced.
335
+ topological structure. The author describes it as a school project and
336
+ credits AI assistance for implementation and repository organization. The
337
+ research decisions, measurements, and limitations are documented alongside
338
+ the code so the work can be evaluated and reproduced.
@@ -85,10 +85,9 @@ suite.
85
85
  λ₂ does not predict quality (pearson 0.20). The certificate is true
86
86
  about the operator; it says nothing about the task. The claim was
87
87
  weakened, not the data massaged.
88
- A transformer beats the fluid at every scale I could train
89
- (2.6331 vs 2.7397 nats). The fluid only wins against fixed-receptive-field
90
- aggregators (97.3 % vs 65.6 % / 71.0 %) — and it loses to full attention,
91
- which is the honest summary of the entire architecture.
88
+ Archived results record a transformer beating the fluid (2.6331 vs 2.7397
89
+ nats) and a 97.3 % mechanism result. The historical source scripts are not
90
+ included, so see N4 in `docs/NEGATIVE-RESULTS.md` for the reproduction caveat.
92
91
  Grafted onto a frozen model, my own diffusion tier made the model
93
92
  worse — +0.81 nats (ppl 13.3 -> 29.9) on real English. The cause is
94
93
  structural: the persistent state sits outside the autodiff graph, so the
@@ -6,6 +6,15 @@ uses [Semantic Versioning](https://semver.org/).
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [2.1.0] - 2026-11-03
10
+
11
+ ### Added
12
+
13
+ - Added the optional PyTorch Qwen2 adapter, E15 scale-model experiment,
14
+ archived measurements, and a runnable app-kit example.
15
+ - Categorized the new project-process, app-kit, experiment, and result files
16
+ into `docs/`, `examples/`, `experiments/`, and `results/`.
17
+
9
18
  ### Changed
10
19
 
11
20
  - Improved the Markdown documentation structure, added a documentation
@@ -205,7 +205,7 @@ what makes per-user persistent memory economically possible at all.
205
205
  | ---|---|---|---|---|---|---|---|---|---|
206
206
  | exact needle at a position|✅|✅ recent|✅|❌|❌|❌|❌|✅|✅ pinned / L3|
207
207
  | exact specific fact|✅|✅ recent|✅|❌|❌|❌|❌|✅|✅ pinned (20 B)|
208
- | global gist / aggregate|✅|❌|✅|✅|✅|✅|❌|❌|✅ 97.3 % meas.|
208
+ | global gist / aggregate|✅|❌|✅|✅|✅|✅|❌|❌|✅ archived 97.3 % result (`results/mechanism.json`)|
209
209
  | positional recall ( "3rd paragraph ")|✅|✅|✅|✅|❌|❌|❌|❌|❌|
210
210
  | infinite stream / never re-encode|❌|✅|❌|❌|✅|✅|n/a|✅|✅|
211
211
  | no "lost in the middle "|❌|❌|❌|❌|~ (no positions)|~|n/a|~|✅ (no positional decay)|
@@ -266,12 +266,12 @@ the measured semantic/local-geometric policy performed better.
266
266
  KV bytes/token, KV @ctx, sessions that fit in VRAM, prefill FLOPs, crossover point
267
267
  fluid read cost 16 KB = 0.009 µs; fluid compute = 384 flops/token/layer
268
268
  our `selftest.py` → 50/50
269
- mechanism test: fluid 97.3 % sign acc vs local R=4 65.6 %, R=8 71.0 %
270
- LM A/B: transformer wins — 2.6331 vs 2.7397 final val (fewer params on our side)
269
+ mechanism test: archived result records 97.3 % sign accuracy; original source unavailable
270
+ LM A/B: archived result records transformer 2.6331 vs FluidLayer 2.7397; original training source unavailable
271
271
  param-matched FLOPs: 1.10× cheaper @8K → 2.54× @128K
272
272
  ⚠️ PROJECTED — needs E1/E5 to become fact
273
273
  that the 16 KB fluid carries long-range information at usable quality
274
- that a real LLM actually routes to the fluid (the 97.3 % was a synthetic task)
274
+ that a real LLM actually routes to the fluid (the archived 97.3 % synthetic-task result does not establish real-model routing)
275
275
  that topology picks the right facts to freeze
276
276
  that pinned facts survive a real model's distribution shift
277
277
  Every table above is a CONDITIONAL: "IF the fluid is usable, THEN this".
@@ -45,10 +45,9 @@ This is the entire design in one move:
45
45
  FluidLayer stops being a memory. It becomes an index.
46
46
  The memory moves to a write-once register; the fluid answers where, and
47
47
  the register answers what.
48
- And the reason this is not a retreat: the 97.3 % mechanism result was always a
49
- routing result. In the mechanism test the fluid predicted the right global
50
- aggregate to 97.3 % sign accuracy. It was already an excellent addresser.
51
- We just gave it an exact value to point at.
48
+ The archived `results/mechanism.json` records a 97.3 % global-aggregation
49
+ result. Its original experiment source is not present, so the historical run
50
+ cannot be independently regenerated (see N4 in `docs/NEGATIVE-RESULTS.md`).
52
51
 
53
52
  ## 1. The impossibility, stated precisely
54
53
 
@@ -89,7 +88,7 @@ keep.
89
88
  └──────────────────────────────────────────────────┘
90
89
  Slot layout (20 B, as implemented):`key uint64 | val int32 | sig uint32 | anchor uint16 | meta uint16`.
91
90
  The read path is three clean steps, each with a guarantee:
92
- query h ──▶ L2 routes h → anchor a (approx: 97.3 % measured)
91
+ query h ──▶ L2 routes h → anchor a (approximate; archived score in results/mechanism.json)
93
92
  anchor a → slot id s (exact: 1 byte)
94
93
  L1[s] = (key, token_id) (exact: 4 bytes)
95
94
  verify key matches h's context hash (fail-loud)
@@ -174,12 +173,12 @@ This is a testable prediction, and it is falsifiable.
174
173
  Which tokens to freeze? The longest bars = the structural landmarks =
175
174
  the tokens that carry the document's skeleton. Freeze those and you get
176
175
  exact extraction of the load-bearing facts, not random trivia.
177
- Why the fluid wins global aggregation (explains the 97.3 %). The
176
+ The theory suggests why diffusion can carry global aggregation: the
178
177
  harmonic branch of `L` (its kernel) is the globally dominant H₀ mode —
179
- and the global mean is the longest bar. The fluid preserves the kernel
180
- component exactly; that is precisely why it beat local aggregators
181
- (65.6 % / 71.0 %) on the global-mean task and lost on position-sensitive
182
- tasks. The v0.1 theory report and the mechanism experiment now have one
178
+ and the global mean is the longest bar. The archived mechanism output records
179
+ a 97.3 % score, beating local aggregators (65.6 % / 71.0 %); its original
180
+ source is unavailable, so the run cannot be independently regenerated. The
181
+ v0.1 theory report and the mechanism experiment now have one
183
182
  unified explanation. That is a real, publishable narrative.
184
183
 
185
184
  ## 5. Budget: the 3-D trade-off
@@ -366,8 +365,8 @@ P4 needs one GPU for a few hours.
366
365
 
367
366
  Attention remembers by position. We remember by geometry. But geometry alone
368
367
  smears: diffusion destroys exactness by construction. So we split the
369
- memory. A 16 KB sheaf routes — 97.3 % accurate at picking the right
370
- landmark — and an append-only frozen register stores the exact token id
368
+ memory. A 16 KB sheaf routes to an approximate landmark (the archived
369
+ mechanism result records 97.3 % sign accuracy) — and an append-only frozen register stores the exact token id
371
370
  at 14 bytes per fact, 196,234× cheaper than a KV cache. Topology decides
372
371
  which landmarks get exact storage, using the document's own persistence
373
372
  diagram, at zero per-token cost. The model can promote a fact or recall one
@@ -3,6 +3,10 @@
3
3
  > **Historical design note:** this is not a current implementation contract.
4
4
  > For current behavior and limitations, see [the API reference](API.md) and
5
5
  > [limitations](LIMITATION.md).
6
+ > Archived LM-comparison and mechanism-test JSON outputs are included under
7
+ > `results/`, but their original experiment source files are unavailable.
8
+ > Treat the numbers as historical snapshots, not independently rerunnable
9
+ > measurements.
6
10
 
7
11
  A topological fluid architecture for sequence models: replace the
8
12
  transformer's quadratic attention with a cellular-sheaf diffusion whose
@@ -345,8 +349,8 @@ fluidlayer/
345
349
  losses.py CE (+ tensor variant), sheaf energy, band decorrelation
346
350
  optim.py Adam (decoupled WD, clipping, cosine schedule)
347
351
  data.py Gutenberg corpus + char tokenizer + synthetic fallback
348
- selftest.py 15 numerical checks of the mathematics -> results/selftest.json
349
- train.py LM A/B + global-aggregation demo -> results/train_results.json
352
+ selftest.py historical numerical checks
353
+ train.py historical LM A/B + global-aggregation demo (source unavailable; see archived results/)
350
354
 
351
355
  ### Run it
352
356
 
@@ -106,6 +106,23 @@ integration must handle the model's positional embeddings, attention masks,
106
106
  device placement, session boundaries, and task-specific gain calibration.
107
107
  Call `branch.reset()` when starting a new independent session.
108
108
 
109
+ ## Run the GPT-2/Qwen2 app kit
110
+
111
+ The repository includes a standalone app kit that loads a local GPT-2 or
112
+ Qwen2 checkpoint and demonstrates attachment and recall:
113
+
114
+ ```bash
115
+ python -m pip install "fluidlayer[gpu]"
116
+ hf download Qwen/Qwen2.5-0.5B --local-dir models/qwen05b
117
+ python examples/appkit/attach_layer.py --model models/qwen05b
118
+ ```
119
+
120
+ The Qwen2 forward implementation is in the published `fluidlayer` package;
121
+ the Qwen tokenizer is provided by the optional Transformers dependency.
122
+ Model weights are not bundled. This app kit is a research example, not a
123
+ production serving wrapper. See [the E15 result](../results/e15_scale_model.json)
124
+ and [reproduction guide](REPRODUCING.md#qwen2-scale-experiment-e15).
125
+
109
126
  ## Memory behavior and safety
110
127
 
111
128
  The attachable store is bounded. Its reported 20-byte slot cost is a logical
@@ -516,56 +516,21 @@ size is decisive, and the honest reading is sharper than "we beat kNN-LM":
516
516
 
517
517
  ---
518
518
 
519
- ## ON A REAL PRETRAINED LLM (E14) — GPT-2, 124M, the real tokenizer
519
+ ## ON A REAL PRETRAINED LLM (E14) — archived result
520
520
 
521
- Everything above was measured on a 131,392-parameter model trained in this
522
- repository. **This is the same experiment on a genuine pretrained
523
- checkpoint** — GPT-2 (124M parameters, the real GPT-2 BPE tokenizer with
524
- 50,257 tokens), run on CPU with a from-scratch forward pass
525
- (`fluidlayer/gpt2_model.py`, verified by generation).
521
+ The E14 script, GPT-2 forward implementation, tokenizer, and archived
522
+ `results/e14_real_gpt2.json` are present. The checkpoint must be downloaded
523
+ separately, so rerun E14 to reproduce the recorded measurements; see N11 in
524
+ [`NEGATIVE-RESULTS.md`](NEGATIVE-RESULTS.md).
526
525
 
527
- ### The three measurements
526
+ To reproduce the run, install the optional dependencies, download GPT-2,
527
+ then run the experiment on the committed corpus:
528
528
 
529
- | | the result |
530
- |---|---|
531
- | **E14a -- attach safety** | **bit-identical** (max abs diff `0.000e+00`) on the real model too |
532
- | **E14c -- the capability** | a fact planted **2,947 tokens** before the query: the base GPT-2 predicts 464, **the layer predicts the fact** |
533
- | **E14b -- the perplexity** | the base GPT-2: 4.0289 (ppl 56.20); the layer at its best gain: **4.0019 (ppl 54.70, −0.027 nats)** |
534
-
535
- ### And the kNN-LM baseline, on the real model
536
-
537
- | | val loss | ppl | Δ | token accuracy |
538
- |---|---|---|---|---|
539
- | the base GPT-2 | 4.0289 | 56.20 | – | 0.3073 |
540
- | **kNN-LM, λ=0.9** | **3.8030** | **44.84** | **−0.2259** | 0.3029 |
541
- | kNN-LM, λ=0.95 | 3.8052 | 44.94 | −0.2237 | 0.3091 |
542
- | the layer (gated), gain 0.5 | 4.0019 | 54.70 | −0.0271 | 0.3104 |
543
- | the layer (gated), gain 2 | 4.1965 | 66.46 | +0.1676 | 0.2982 |
544
-
545
- > **The result that changes the claim.** On the *tiny* model the gate beat
546
- > the kNN-LM interpolation by **7.4×**. On the **real** model the
547
- > interpolation wins by **8×**. The reason is structural, not a bug: the
548
- > interpolation is **bounded** — it can only shift probability mass by
549
- > (1−λ), so a wrong retrieval can never take over — whereas the gate
550
- > *can* take over, and on a strong model the base's own guess is usually
551
- > better than the datastore's answer.
552
- >
553
- > **The gate wins where the base model is weak; the interpolation wins
554
- > where the base model is strong.** The capability (E14c) works on both.
555
-
556
- ### One thing that had to be fixed to make it work on a real model
557
-
558
- The gate was first formulated in probability space, `u = 1 − max p`. On
559
- GPT-2 that needed a gain of 50+ and it wrecked the perplexity: GPT-2's
560
- logits span ±20, while the tiny model's span ±2, so the same "gain" meant
561
- something completely different. **The gate is now in logit space**,
562
- `u = −log p_max` (how many nats the model is from being sure), which is
563
- **scale-free**: the same gain works on both models.
564
-
565
- → `experiments/e14_real_gpt2.py`, `results/e14_real_gpt2.json`
566
- (measured with torch 2.4.1+cpu; `python tools/download_gpt2.py --out models/gpt2`
567
- fetches the checkpoint, and the forward pass + tokenizer are in this
568
- repository — no `transformers` needed)
529
+ ```bash
530
+ python -m pip install -e ".[gpu]"
531
+ python tools/download_gpt2.py --out models/gpt2
532
+ python experiments/e14_real_gpt2.py --corpus corpus.txt
533
+ ```
569
534
 
570
535
  ---
571
536
 
@@ -157,26 +157,19 @@ is the contribution under a hard memory budget** — which is a narrower
157
157
  claim than the project started with, and a defensible one.
158
158
  → `experiments/e13_knn_baseline.py`, `results/e13_knn.json`
159
159
 
160
- ## 16. A pretrained LLM
160
+ ## 16. A pretrained LLM — unverified
161
161
 
162
- The network came up, torch installed, and **GPT-2 (124M, the real 50,257
163
- token BPE) ran with the layer attached**: the attach is **bit-identical**,
164
- and a fact planted **2,947 tokens** before the query is recalled (the base
165
- predicts 464, the layer predicts the fact). The checkpoint, the forward
166
- pass and the tokenizer are all in this repository — no `transformers`
167
- dependency, and the generation is verified coherent.
168
-
169
- The honest caveat it forced: **the gate's advantage over the kNN-LM
170
- interpolation reverses on a strong model** (the tiny model: the gate won by
171
- 7.4×; GPT-2: the interpolation wins by 8×). The gate wins where the base
172
- model is weak. The capability works on both.
173
- → `experiments/e14_real_gpt2.py`, `results/e14_real_gpt2.json`
162
+ The E14 script, GPT-2 forward/tokenizer implementation, and archived
163
+ `results/e14_real_gpt2.json` are present. The checkpoint is not; rerun E14
164
+ to independently reproduce the recorded measurements.
165
+ → `experiments/e14_real_gpt2.py`; see [reproduction instructions](REPRODUCING.md)
174
166
 
175
167
  ## 17. A repository a stranger can run in one minute
176
168
 
177
- Unzip → `python selftest.py` → **50/50**. `pip install .` → the public API
178
- imports from an installed wheel. Every result in `results/` regenerates
179
- with `python experiments/run_all.py --full`.
169
+ Fresh clone → `python selftest.py` → **50/50**. `pip install .` → the public API
170
+ imports from an installed wheel. Reproducible experiments can be rerun with
171
+ `python experiments/run_all.py --full`; archived N4 results are preserved,
172
+ though their historical source script is unavailable.
180
173
  → `scripts/check_artifacts.sh` (the one-command audit)
181
174
 
182
175
  ## 18. The credibility milestone