Metadata-Version: 2.4
Name: mnemekit
Version: 0.2.0
Summary: A zero-LLM, zero-embedding, cue-indexed tag memory for conversational agents.
Author: Yam
License: MIT
Project-URL: Homepage, https://github.com/FTP2026/Mneme
Keywords: memory,llm,agent,conversational,retrieval,spreading-activation
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: spacy>=3.7
Provides-Extra: zh
Requires-Dist: jieba; extra == "zh"
Provides-Extra: eval
Requires-Dist: mem0ai; extra == "eval"
Requires-Dist: sentence-transformers; extra == "eval"
Requires-Dist: matplotlib; extra == "eval"

# 🧠 Mneme

**A cue-indexed tag memory for conversational agents — no embeddings, no LLM in the memory path.**

[![PyPI](https://img.shields.io/pypi/v/mnemekit.svg)](https://pypi.org/project/mnemekit/)
[![Python](https://img.shields.io/pypi/pyversions/mnemekit.svg)](https://pypi.org/project/mnemekit/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

Most agent memories embed every turn and distill it with a write-time LLM, then search by vector similarity — expensive and opaque. Mneme instead does what human recall does: **index by cues, reinstate by cue-match, and spread activation along both shared meaning and the thread of conversation** — with a plain inverted index over deterministic tags. No vector database, no language model, no embeddings.

> **At zero memory cost, under an identical controlled comparison, Mneme matches a strong dense retriever on LoCoMo (F1 52.6 vs 52.9) and beats it on high-distractor LongMemEval (acc 64.2 vs 62.2)** — while outrunning both mem0 and BM25 on both benchmarks. Same answerer, judge, prompt, and budget; only the memory differs.

---

## ✨ Why Mneme

- **Zero cost.** No write-time LLM calls, no embeddings, sub-millisecond recall, storage is plain JSON files.
- **Competitive quality.** Matches or beats embedding + LLM memory on standard benchmarks (see below).
- **Interpretable.** Retrieval is explicit cue overlap ranked by IDF — no opaque similarity threshold to tune.
- **Human-like forgetting.** What has no distinctive cue, or whose cues never recur, is simply never surfaced — forgetting as retrieval failure, for free.
- **Local & sovereign.** Your memory is a folder of files you can read, edit, or delete. English by default; Chinese optional.

## 📊 Benchmarks (controlled: same answerer/judge/prompt/budget, only the memory differs)

**LoCoMo** — low-distractor dialogue (F1 / accuracy):

| method | cost | F1 | acc |
|---|---|---|---|
| mem0 (LLM extract + vectors) | LLM+emb | 40.4 | 57.3 |
| BM25 (raw turns) | zero | 45.8 | 57.0 |
| **Mneme** (hybrid edges) | zero | **52.6** | **67.6** |
| dense retriever (bge-large) | embeddings | 52.9 | 67.7 |

**LongMemEval** — high-distractor, ~50 sessions per question (accuracy):

| method | cost | acc |
|---|---|---|
| BM25 (raw turns) | zero | 61.2 |
| dense retriever (bge-large) | embeddings | 62.2 |
| **Mneme** (associative) | zero | **64.2** |

Zero-cost Mneme **reaches dense retrieval on LoCoMo and overtakes it where distractors dominate** — the regime that matters for real long-term memory — and it is reader-agnostic (near-identical with two different answerer LLMs) and interpretable. The best edge mix is regime-dependent: discourse edges help clean dialogue, associative edges win high-distractor histories.

## 🚀 Install

```bash
pip install mnemekit
python -m spacy download en_core_web_sm     # English model (required)

pip install "mnemekit[zh]"                   # optional: Chinese (jieba)
```

## ⚡ Quick start

```python
from mneme import Memory

m = Memory(root="~/.mneme")

m.remember("My dog Lucky is a golden retriever", "Cute! How old is Lucky?",
           session_id="chat-42", round_id=1)

m.recall("what breed is my dog")     # -> [Turn(...), ...]
```

Turns are stored one file per round at `{root}/{session_id}/{YYYY-MM-DD}/{round_id}.json`, so any session is trivial to inspect, export, or delete.

## 🔍 How it works

```
INGEST (no LLM, no embedding)
  turn ──▶ tag extraction (spaCy NER + lemmas / jieba) ──▶ inverted index  (tag → turns)
                                                           + event tag inheritance

RECALL (per query) — spread over an ephemeral heterogeneous graph, then discard it
  query ─▶ ① lexical: IDF cue reinstatement ─seeds─┬─▶ ② associative edge (shared tag, 1 hop)
                                                   └─▶ ③ discourse edge (adjacent turn in event)
                                                                        │
                                                          recalled context ─▶ your reader
```

1. **Cue index.** Each turn is tagged deterministically; tags form an inverted index (a sparse cue index, à la hippocampal indexing). Keyword-free follow-ups inherit their event's tags, so they stay recallable.
2. **Reinstatement, then two kinds of edge.** A query reinstates directly-cued turns lexically, then spreads activation over an ephemeral graph with two edge types: **associative** edges (shared discriminative cue → one hop) reach the *associative tail* a direct cue can't; **discourse** edges (adjacent turns in the same event) pull in the local conversational context around a hit. Neither is materialized — both are read straight off the index and event structure, used for the one query, and discarded.

## 🀄 Chinese & custom dictionaries

```python
m = Memory(root="~/.mneme", userdict="my_terms.txt")   # jieba user dictionary
m.remember("我养了只金毛狗，叫 Lucky", "可爱！", session_id="u1", round_id=1)
```

Chinese is segmented by `jieba`; a custom dictionary keeps vertical-domain terms intact.

## 📄 Paper & reproduction

The write-up (method, cognitive grounding, controlled comparison, ablations) is in [`paper/`](paper/); the evaluation harness (LoCoMo / LongMemEval / mem0) is in [`eval/`](eval/). The frozen reproduction version is on the `paper-repro` branch.

## 📌 Citation

```bibtex
@misc{mneme2026,
  title  = {Do Conversational Agents Need Vectors? A Zero-LLM, Zero-Embedding Tag Memory},
  author = {Hao, Shaochun},
  year   = {2026},
  note   = {https://github.com/FTP2026/Mneme}
}
```

## License

MIT
