One-shot attractor memory for LLMs — vector-search accuracy at 98% fewer tokens.
Project description
slate-memory
One-shot attractor memory for LLMs. Vector-search accuracy at 98% fewer tokens.
The number
| Setup | Accuracy | Cost per 1k queries | Latency |
|---|---|---|---|
| haiku + slate | 100% | $0.10 | 0.6s |
| opus + full context | 100% | $64.04 | 1.7s |
| opus bare | 0% | $0.19 | 1.2s |
| haiku bare | 0% | $0.04 | 0.7s |
A cheap model with slate-memory ties the most expensive model with the entire corpus in context — at 1/640th the cost. Both models score 0% without memory (facts are synthetic, unknowable parametrically). Benchmark: N=25 questions, K=600 stored facts, hermetic SDK calls. Full methodology and reproduction scripts in slate-bench.
How it works
Slate-memory is a modern Hopfield network (Ramsauer et al. 2020) — the same math as transformer attention, but used as a memory instead of a layer. Embeddings are sign-projected onto 10,000 bipolar cells (SimHash) and stored one-shot. On recall, the query settles into the nearest stored attractor via softmax-weighted feedback. Two cycles. No training. No index. No database.
The attractor dynamics error-correct: noisy, partial, or corrupted queries converge to the exact stored pattern. Verified at 20,000 stored patterns with 25% corruption.
Install
pip install slate-memory
For the built-in embedder convenience wrapper:
pip install slate-memory[embed]
Quick start
from slate_memory import SlateBank
import numpy as np
# Your embeddings (384-dim for MiniLM, 1536 for OpenAI, etc.)
bank = SlateBank(dim=384)
# Commit facts one-shot
bank.commit(embed("The capital of France is Paris"), {"text": "Paris is the capital of France", "id": "fact-1"})
bank.commit(embed("Python was created by Guido van Rossum"), {"text": "Guido created Python", "id": "fact-2"})
# Recall — even from a noisy or partial query
winner, ranked, confidence, cycles = bank.recall(embed("What's the capital of France?"))
print(winner) # {"text": "Paris is the capital of France", "id": "fact-1"}
print(f"Confidence: {confidence:.3f}, settled in {cycles} cycles")
With sentence-transformers
from slate_memory import SlateBank
from sentence_transformers import SentenceTransformer
model = SentenceTransformer("all-MiniLM-L6-v2")
bank = SlateBank(dim=384)
# Commit
texts = ["The Earth orbits the Sun", "Water boils at 100°C", "Light travels at 299,792 km/s"]
for text in texts:
bank.commit(model.encode(text), {"text": text})
# Recall
query = model.encode("what temperature does water boil")
winner, ranked, confidence, cycles = bank.recall(query)
print(winner["text"]) # "Water boils at 100°C"
With OpenAI embeddings
from slate_memory import SlateBank
from openai import OpenAI
client = OpenAI()
bank = SlateBank(dim=1536) # text-embedding-3-small
def embed(text):
return client.embeddings.create(input=text, model="text-embedding-3-small").data[0].embedding
bank.commit(embed("Revenue was $4.2M in Q3"), {"text": "Q3 revenue: $4.2M"})
winner, _, conf, _ = bank.recall(embed("how much revenue in Q3"))
Persistence
# Save
bank.save("./my_memory")
# Load
bank2 = SlateBank(dim=384)
n = bank2.load("./my_memory")
print(f"Loaded {n} patterns")
The entire memory is two files: patterns.npy (the attractor states) and meta.json (your metadata). No server. No database. Copy them anywhere.
API
SlateBank(dim, n_cells=10000, beta=60.0, distinctiveness=True, dedup_threshold=0.95, seed=7)
- dim: Embedding dimensionality (must match your embedder)
- n_cells: Bipolar cells in the attractor state. 10,000 is verified for up to 20k patterns
- beta: Winner-take-all sharpness. 60.0 is benchmarked; don't change without reason
- distinctiveness: Down-weight cells where all patterns agree. Essential for images; neutral for text
- dedup_threshold: Refuse commits with overlap above this. 0.95 prevents near-duplicates
- seed: RNG seed for the projection matrix. Same seed = same projections = portable patterns
bank.commit(embedding, meta) → (bool, str)
One-shot storage. Returns (True, "committed") or (False, "duplicate (...)").
bank.recall(embedding, top_k=3, max_cycles=5) → (winner, ranked, confidence, cycles)
Full attractor settle. Returns the winner's metadata, top-k ranked results, confidence score, and settle cycles.
bank.familiar(embedding) → (meta, score)
Quick overlap check without settling. Use for "have I seen this before?" checks.
bank.save(path) / bank.load(path)
Persist to / restore from a directory.
Benchmarks
Full retrieval benchmarks across 5 corruption conditions and 4 capacity levels show accuracy parity with exact cosine search (±1 point). The attractor substrate recalls 20,000 random patterns perfectly at 25% corruption. Capacity is limited by embedding discriminability (the embedder), not the attractor.
Honest limitations in software: per-query latency is ~35x slower than exact vector search (19ms vs 0.5ms at K=2000) because the projected patterns are 10,000-d vs 384-d. The speed case is the photonic implementation where recall is one pass of light — that's the roadmap, not the demo.
See slate-bench for full reproduction scripts and results.
License
Apache 2.0. Patent pending.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file slate_memory-0.1.0.tar.gz.
File metadata
- Download URL: slate_memory-0.1.0.tar.gz
- Upload date:
- Size: 12.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
27cbe95d8de534a3c1334344c3222a64d8c099c549ce9d49a7b7248410511680
|
|
| MD5 |
e1d2c3d52c1bacc596f4d0c72eb3ec42
|
|
| BLAKE2b-256 |
49703b5252e5edd2b792544ca04dc30dc966f4b880d3283c449b4ac19ad00f79
|
File details
Details for the file slate_memory-0.1.0-py3-none-any.whl.
File metadata
- Download URL: slate_memory-0.1.0-py3-none-any.whl
- Upload date:
- Size: 11.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1b7ba9deec4d370beb82d72779db90f75ec04625efaa22953b35a6220189e722
|
|
| MD5 |
542f35cc9248d9cb8eb6753456e42944
|
|
| BLAKE2b-256 |
35bc2531abab6407cf624385fff153b2499b65955836f2d87e155e332735299b
|