Reframe as Conditioned Reflex Injection (CRI) with multi-model test results
- Rename from "Episodic Memory" to "Conditioned Reflex Injection" throughout - Make code model-agnostic: --model flag for any HuggingFace backbone - Support multimodal models (Gemma 4) via .model.language_model resolution - Add negative stimulus-specificity tests and abstract query tests - Paper now backed by measured data from 4 backbones: Qwen 2.5 0.5B, Gemma 4 E2B-it, E4B-it, E4B base - Quantization tolerance tested at f32/f16/bf16/int8/int4 - Key findings: smaller base models outperform larger instruct models, instruct tuning compresses activation space (hurts discrimination), int4 viable if same-precision conditioning/triggering - Add privacy-by-representation section - Add Pavlov/Skinner references for conditioning framing Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
86
README.md
86
README.md
@@ -1,10 +1,10 @@
|
||||
<br />
|
||||
<div align="center">
|
||||
|
||||
<h3 align="center">Solving the Clive Wearing Problem: One-Shot Episodic Memory for Frozen Transformers</h3>
|
||||
<h3 align="center">Conditioned Reflex Injection: Stimulus-Response Learning for Frozen Transformers</h3>
|
||||
|
||||
<p align="center">
|
||||
Gradient-free persistent learning through hidden-state episodic recall.
|
||||
Gradient-free behavioral conditioning through hidden-state trigger matching and logit bias injection.
|
||||
<br />
|
||||
<a href="paper.md"><img src="https://img.shields.io/badge/Paper-Markdown-blue?style=flat-square" alt="Paper"></a>
|
||||
</p>
|
||||
@@ -12,21 +12,25 @@
|
||||
|
||||
---
|
||||
|
||||
## Abstract
|
||||
## What This Is (And Isn't)
|
||||
|
||||
Teach a frozen language model new facts **without gradient descent**. Store the model's own hidden states as episodic memories. On recall, inject stored representations as logit biases. One-shot. Persistent. No weight modification.
|
||||
This is **not** episodic memory. The model doesn't remember anything. It doesn't experience the taught fact. It doesn't form a representation of "knowing" something.
|
||||
|
||||
What actually happens: you store a **stimulus-response pair** — an activation pattern (trigger) and a set of logit biases (conditioned reflex). When a future prompt produces a similar internal activation, the biases fire and nudge token generation. The model has no idea why it's saying "Novaheim." It just gets pushed there.
|
||||
|
||||
This is closer to **post-hypnotic suggestion** than memory. Pavlovian conditioning at the logit level. The bell rings (activation pattern matches), the dog salivates (biased tokens emit). No understanding. No experience. No episodic recall in any phenomenological sense.
|
||||
|
||||
## Key Result
|
||||
|
||||
A frozen Qwen 2.5 0.5B taught three facts about a fictional entity:
|
||||
A frozen Qwen 2.5 0.5B conditioned with three stimulus-response pairs:
|
||||
|
||||
| Prompt | Taught | Recalled | Similarity |
|
||||
| Trigger prompt | Conditioned response | Output when triggered | Similarity |
|
||||
|--------|--------|----------|:---:|
|
||||
| "The capital of Zyphraxia is" | "Novaheim" | "Novaheim, a city of 100" | 1.000 |
|
||||
| "The ruler of Zyphraxia is" | "Queen Stellara" | "Queen Stellara. She is a beautiful woman" | 1.000 |
|
||||
| "The currency of Zyphraxia is" | "Glimmers" | "Glimmers. The currency is divided into" | 1.000 |
|
||||
|
||||
**No gradients computed at any point.**
|
||||
**No gradients computed. No weights modified. The model doesn't know these facts — it reflexively produces them.**
|
||||
|
||||
## Quick Start
|
||||
|
||||
@@ -34,65 +38,89 @@ A frozen Qwen 2.5 0.5B taught three facts about a fictional entity:
|
||||
pip install transformers torch numpy
|
||||
git clone https://git.rotko.net/tommi/epimem
|
||||
cd epimem
|
||||
python python/epimem.py
|
||||
python python/epimem.py # default: Qwen 2.5 0.5B
|
||||
python python/epimem.py --model google/gemma-4-E4B-it # Gemma 4
|
||||
python python/epimem.py --model google/gemma-4-E2B-it # Gemma 4 small
|
||||
```
|
||||
|
||||
This downloads Qwen 2.5 0.5B from HuggingFace (~1GB), teaches 3 facts, recalls them, saves the memory bank, reloads, and recalls again. Takes ~2 minutes on first run (model download), ~30 seconds after.
|
||||
Works with any HuggingFace causal LM or multimodal model with a text decoder.
|
||||
|
||||
### With ONNX (faster, no PyTorch)
|
||||
|
||||
```bash
|
||||
pip install onnxruntime transformers numpy
|
||||
python export_onnx.py # exports Qwen 2.5 as ONNX to models/
|
||||
python export_onnx.py # default model
|
||||
python export_onnx.py --model google/gemma-4-E4B-it # Gemma 4
|
||||
python python/epimem.py --onnx models
|
||||
```
|
||||
|
||||
## How It Works
|
||||
|
||||
### Teaching (one forward pass, no gradients)
|
||||
### Conditioning (one forward pass, no gradients)
|
||||
|
||||
```
|
||||
Prompt: "The capital of Zyphraxia is"
|
||||
Answer: "Novaheim"
|
||||
|
||||
1. backbone("The capital of Zyphraxia is") → hidden state h (896-dim vector)
|
||||
2. backbone("The capital of Zyphraxia is Novaheim") → logit biases for "Novaheim"
|
||||
3. Store: (key=h, value=logit_biases) in memory bank
|
||||
1. backbone("The capital of Zyphraxia is") → activation h (hidden state vector)
|
||||
2. backbone("The capital of Zyphraxia is Novaheim") → logit gap for "Novaheim"
|
||||
3. Store: (trigger=h, reflex=logit_biases) in reflex bank
|
||||
```
|
||||
|
||||
### Recall (similarity search + logit injection)
|
||||
### Trigger firing (similarity search + logit injection)
|
||||
|
||||
```
|
||||
Query: "The capital of Zyphraxia is"
|
||||
|
||||
1. backbone(query) → h_q (896-dim vector)
|
||||
2. cosine_sim(h_q, stored_key) = 1.000
|
||||
3. Inject: logits += stored_logit_biases (per-position)
|
||||
4. Generate: "Novaheim, a city of 100..."
|
||||
1. backbone(query) → activation h_q
|
||||
2. cosine_sim(h_q, stored_trigger) = 1.000 → match
|
||||
3. Inject: logits += conditioned_biases (per-position)
|
||||
4. Output: "Novaheim, a city of 100..."
|
||||
```
|
||||
|
||||
### Why hidden states, not text (like RAG)
|
||||
### Why not RAG?
|
||||
|
||||
RAG stores text, re-encodes it each time, consumes context window.
|
||||
We store the backbone's own internal representation — no re-encoding, no context consumption.
|
||||
RAG stores text, re-encodes it, consumes context window. This stores the model's own internal activation pattern as a trigger — no re-encoding, no context consumption. But RAG gives the model actual information to reason about. This just pushes output tokens. Different tool for different jobs.
|
||||
|
||||
### Why not "episodic memory"?
|
||||
|
||||
Episodic memory implies the system re-experiences the encoding event. It doesn't. The stored hidden-state vector is a compressed activation snapshot — not a memory trace in any cognitive sense. The model never "encoded an experience." It produced an activation, we saved it, and we replay it as a logit bias. That's a conditioned reflex, not a memory.
|
||||
|
||||
## Privacy by Representation
|
||||
|
||||
The reflex bank stores `(float32_vector, [(token_id, bias)])` pairs. Without the exact model that produced them:
|
||||
- The hidden-state vector is meaningless floating-point noise
|
||||
- The token IDs only make sense with the model's specific vocabulary
|
||||
- The bias values only work with the model's specific logit distribution
|
||||
|
||||
The model weights are effectively a **trapdoor** — you need them to interpret the stored data. This isn't encryption. It's opacity by representation. Steal the database, get noise.
|
||||
|
||||
## Files
|
||||
|
||||
```
|
||||
python/epimem.py ← standalone reproduction (~200 lines)
|
||||
export_onnx.py ← ONNX export from HuggingFace
|
||||
python/epimem.py ← model-agnostic reproduction (~300 lines)
|
||||
export_onnx.py ← ONNX export for any HuggingFace model
|
||||
paper.md ← full paper
|
||||
results/memory_bank.json ← example: 896-dim hidden-state vectors
|
||||
schema/isis.fbs ← FlatBuffer schema for memory bank
|
||||
results/memory_bank.json ← example: hidden-state vectors + logit biases
|
||||
schema/isis.fbs ← FlatBuffer schema for reflex bank
|
||||
schema/organism.fbs ← FlatBuffer schema for organism state
|
||||
models/tokenizer/ ← Qwen 2.5 tokenizer files
|
||||
```
|
||||
|
||||
## Tested Models
|
||||
|
||||
| Model | Hidden dim | Layers | Notes |
|
||||
|-------|-----------|--------|-------|
|
||||
| Qwen 2.5 0.5B | 896 | 24 | Original test model |
|
||||
| Gemma 4 E4B-it | 2560 | 42 | Recommended |
|
||||
| Gemma 4 E2B-it | 1536 | 35 | PLE architecture, smallest |
|
||||
|
||||
Reflexes are **model-locked** — conditioning on one backbone doesn't transfer to another. Different model = different activation space = different triggers.
|
||||
|
||||
## Citation
|
||||
|
||||
```bibtex
|
||||
@article{niemi2026clivewearing,
|
||||
title={Solving the Clive Wearing Problem: One-Shot Episodic Memory for Frozen Transformers},
|
||||
@article{niemi2026cri,
|
||||
title={Conditioned Reflex Injection: Stimulus-Response Learning for Frozen Transformers},
|
||||
author={Tommi Niemi},
|
||||
year={2026},
|
||||
organization={Rotko Networks},
|
||||
|
||||
Reference in New Issue
Block a user