Metadata-Version: 2.4
Name: mnemekit
Version: 0.1.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 local, cue-indexed **tag memory** for conversational agents — **no embeddings, no LLM** in the memory path.

Human recall is cue-driven: a partial cue brings back a cluster of related memories that the mind wires into a momentary web and then lets dissolve. Mneme models this. Each turn is tagged deterministically; tags form an inverted index (the cue index); a query reinstates directly-cued turns lexically and then builds an **ephemeral association graph** over them—spreading activation to related turns—which is discarded once the query is answered. No vector DB, no graph DB, no language model.

## Install

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

pip install "mnemekit[zh]"                 # + Chinese (adds jieba)
pip install "mnemekit[eval]"               # + benchmark/baseline deps
```

`import mneme` regardless of the distribution name.

## Usage

```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, ...]
```

- **Structured ids & storage.** `session_id` (default `"default-session"`) + `round_id` form each turn's id; turns are stored one file per round under `{root}/{session_id}/{YYYY-MM-DD}/{round_id}.json`, so a session is easy to inspect, export, or delete.
- **Chinese.** With `[zh]` installed, Chinese is segmented by `jieba`; pass a custom dictionary for vertical domains: `Memory(userdict="terms.txt")`.
- **Optional LLM enrichment.** An `enrich(text, source, tags) -> tags` callback can add semantic tags; off by default (the memory path stays LLM-free).

## Design

```
schema.py  — Tag / Turn / Event records
extract.py — TagExtractor: spaCy NER+lemmas (en) / jieba.posseg (zh, +userdict)
thread.py  — Threader: event segmentation + tag inheritance for keyword-free follow-ups
store.py   — Store: per-session/day turn files + inverted.json + events.json
recall.py  — Recaller: lexical IDF reinstatement + ephemeral association graph
memory.py  — Memory: remember() / recall()
```

Two-stage recall: (1) lexical, IDF-weighted lookup over the inverted index; (2) a per-query association graph seeded by the lexical hits that spreads activation through shared entities and is then discarded. Because information without distinctive cues is never surfaced, forgetting is implicit and cue-dependent.

## Evaluation & paper

See `paper/` for the write-up and `eval/` for the LoCoMo / LongMemEval harness and the controlled mem0 comparison. The frozen reproduction version is on the `paper-repro` branch.
