<br />
<div align="center">

  <h3 align="center">Conditioned Reflex Injection</h3>

  <p align="center">
    Pavlovian conditioning at the logit level. One forward pass. No gradients. No trace.
    <br />
    <a href="paper.md"><img src="https://img.shields.io/badge/Paper-Markdown-blue?style=flat-square" alt="Paper"></a>
  </p>
</div>

---

Store a frozen model's activation pattern as a trigger. Store logit biases as the conditioned response. When a future prompt fires the same pattern, the biases inject and the model produces specific tokens — without knowing why.

Post-hypnotic suggestion for transformers. Remove the reflex bank and the model is untouched. No weights modified. No trace left.

## Quick Start

```bash
pip install transformers torch numpy
git clone https://git.rotko.net/tommi/cri
cd cri
python python/epimem.py                                # Qwen 2.5 0.5B (best results)
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
```

### API Server

```bash
pip install fastapi uvicorn
python serve.py --model Qwen/Qwen2.5-0.5B --port 8811

curl -X POST localhost:8811/teach -d '{"prompt":"The capital of Zyphraxia is","answer":"Novaheim"}'
curl -X POST localhost:8811/trigger -d '{"query":"The capital of Zyphraxia is"}'
```

## Key Result

| Trigger | Response | Output | Sim |
|---------|----------|--------|:---:|
| "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 |

## How It Works

```
CONDITION (one forward pass):
  backbone("The capital of Zyphraxia is")           → hidden state h
  backbone("The capital of Zyphraxia is Novaheim")  → logit biases for "Novaheim"
  Store: (trigger=h, reflex=biases)

TRIGGER (cosine match + inject):
  backbone(query) → h_q
  cosine_sim(h_q, h) = 1.000 → match
  logits += biases → "Novaheim, a city of 100..."
```

## Key Findings

- **Smaller base models work best.** Qwen 2.5 0.5B outperforms Gemma 4 on both discrimination and post-bias fluency.
- **Instruct tuning hurts CRI.** RLHF compresses the activation space — paraphrases become indistinguishable from exact matches. Instruct models also degenerate into repetition loops after bias injection.
- **Quantization: int8 minimum.** int4 destroys hidden-state discrimination. Same-precision conditioning/triggering required.
- **Privacy by representation.** The reflex bank is opaque without the exact model. Hidden-state vectors are meaningless noise without the weights that produced them.

## Tested Models

| Model | Hidden dim | Layers | Fluent? | Discrimination |
|-------|:---------:|:------:|:-------:|:--------------:|
| Qwen 2.5 0.5B base | 896 | 24 | Yes | Best (0.213 spread) |
| Gemma 4 E4B base | 2560 | 42 | Partial | Moderate (0.062) |
| Gemma 4 E4B-it | 2560 | 42 | No (repeats) | Poor (0.056) |
| Gemma 4 E2B-it | 1536 | 35 | No (repeats) | Worst (0.038) |

Reflexes are **model-locked**. Different model = different activation space = different triggers.

## Citation

```bibtex
@article{niemi2026cri,
  title={Conditioned Reflex Injection: Stimulus-Response Learning for Frozen Transformers},
  author={Tommi Niemi},
  year={2026},
  organization={Rotko Networks},
  url={https://git.rotko.net/tommi/cri},
}
```

## License

MIT
