Metadata-Version: 2.4
Name: self-learning-model
Version: 0.2.0
Summary: A model whose weights change during inference: surprise-gated fast-weight test-time learning. Zero dependencies, runs in Python and the browser.
Author: cagataycali
License: MIT
Project-URL: Homepage, https://github.com/cagataycali/self-learning-model
Project-URL: Repository, https://github.com/cagataycali/self-learning-model
Keywords: test-time-learning,fast-weights,continual-learning,autograd,zero-dependency,onnx,browser,lora,predictive-coding
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Intended Audience :: Science/Research
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Provides-Extra: hub
Requires-Dist: huggingface_hub>=0.20; extra == "hub"
Provides-Extra: qwen
Requires-Dist: torch>=2.1; extra == "qwen"
Requires-Dist: transformers>=4.45; extra == "qwen"
Requires-Dist: huggingface_hub>=0.20; extra == "qwen"
Provides-Extra: dev
Requires-Dist: pytest; extra == "dev"

# self-learning-model

> **Models whose weights change while they run.** Predict → get surprised →
> rewrite a small, bounded part of yourself → never forget the base.
> Proven with falsifiable experiments ([PROOF.md](PROOF.md), p ≤ 4e-04).

```bash
pip install self-learning-model          # zero-dependency core
pip install "self-learning-model[qwen]"  # + the self-learning Qwen3-VL runtime
```

## 1 · Strands-expert Qwen3-VL-2B that keeps learning

A Qwen3-VL-2B post-tuned on the entire [strands-agents](https://github.com/strands-agents)
codebase (strands probes NLL **4.85 → 2.22**, 8/8 improved), plus a plastic layer
that adapts at inference — with a provable off-switch.

```python
from slm.qwen import StrandsPlasticQwen                     # needs [qwen] + HF_TOKEN

m = StrandsPlasticQwen.from_pretrained()                    # cagataydev/strands-qwen3-vl-2b
print(m.chat("How do I create a custom tool in Strands Agents?"))

for doc in your_stream:
    m.observe(doc, learn=True)   # predicts; if surprised, rewrites its fast weights
m.reset()                        # exactly back to the strands-expert base
```

Verified: continual out-of-distribution stream NLL **6.18 → 5.37** while strands
expertise is untouched (Δ −0.01). Model: [`cagataydev/strands-qwen3-vl-2b`](https://huggingface.co/cagataydev/strands-qwen3-vl-2b) (private).

## 2 · Zero-dependency core (Python + browser, bit-identical)

The mechanism in ~600 lines of stdlib Python, mirrored in vanilla JS (Δ≈1e-15):

```python
from slm import SelfLearningLM
lm = SelfLearningLM.from_pretrained("cagataydev/self-learning-model")
lm.observe("novel text", learn=True)     # weights change — no training step
```

**Live demo**: [docs/index.html](docs/index.html) — watch a transformer's weight
matrix rewrite itself in your browser as it reads.

## Is it *really* learning? Yes — proven.

Six skeptic attacks, six closed doors ([PROOF.md](PROOF.md)):

| attack | test | result |
|---|---|---|
| "it memorized the stream" | freeze → eval on unseen inputs | err 0.665→0.044, 20/20 |
| "knowledge is in optimizer state" | transplant weights into virgin body | identical, Δ=0 |
| "any perturbation helps" | same-norm random-direction updates | no learning |
| "the update process is the trick" | shuffled-target control | no learning |
| "black box" | decode `M_eff` vs true `W*` | correlation 0.005→**0.943** |
| "toy result" | real frozen GPT, held-out docs, info-ladder controls | p=4.0e-04 |

Honest negatives included: single-prompt in-context (softmax attention already
wins), emergent in-context learning at tiny scale, and the finding that **~⅓ of
naive test-time-training gains are mere calibration** — a confound we control for.

## How it works

```
frozen base (instinct — never updated, can't forget)
  + tiny plastic LoRA (experience — updated every step at inference)
  + surprise gate (learn only when wrong) + EMA decay (bounded, stable)
loss = next-observation prediction error   ← the free label from reality
```

The stability–plasticity dilemma is resolved by the decay: without it the model
learns hard but forgets (retention +7.09); with it, it learns *and* retains (+0.03).

## More

| | |
|---|---|
| [PROOF.md](PROOF.md) | the proof of learning, exact statistics |
| [RESULTS.md](RESULTS.md) | all experiments E0–E7b, incl. negatives |
| [ARCHITECTURE.md](ARCHITECTURE.md) / [PLASTIC.md](PLASTIC.md) / [SCIENCE.md](SCIENCE.md) | design, delta-rule method, protocol |
| [strands_tune/](strands_tune/) · [qwen_plastic/](qwen_plastic/) | Qwen training & eval pipelines |
| [BROWSER.md](BROWSER.md) · [web/](web/) | the zero-dep browser story |

Built on ideas from TTT (Sun et al.), Titans (Behrouz et al.), fast-weight
programmers (Schmidhuber), DeltaNet — and [@karpathy's atomic GPT](https://github.com/cagataycali/strands-microgpt).

MIT.
