Metadata-Version: 2.4
Name: voltmem
Version: 0.1.0
Summary: Current-truth memory for LLM agents — protect stable facts, update volatile ones.
Author: VoltMem contributors
License-Expression: MIT
Project-URL: Homepage, https://github.com/Rouche01/voltmem
Project-URL: Repository, https://github.com/Rouche01/voltmem
Project-URL: Issues, https://github.com/Rouche01/voltmem/issues
Keywords: llm,agent,memory,rag,embeddings
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: embeddings
Requires-Dist: sentence-transformers>=3.0; extra == "embeddings"
Provides-Extra: langchain
Requires-Dist: langchain-core>=0.3.0; extra == "langchain"
Requires-Dist: langchain>=0.3.0; extra == "langchain"
Provides-Extra: all
Requires-Dist: sentence-transformers>=3.0; extra == "all"
Requires-Dist: langchain-core>=0.3.0; extra == "all"
Requires-Dist: langchain>=0.3.0; extra == "all"
Dynamic: license-file

# VoltMem

**Current-truth memory for LLM agents.**

Most memory layers treat every fact the same — your hometown and today's mood get equal
weight. That forces a bad tradeoff: go **stale** on fast-changing facts, or get
**corrupted** when a confident-but-wrong update overwrites something durable.

VoltMem scales protection and retrieval freshness by **how fast each kind of fact
actually changes**. Volatile facts update; stable facts resist corruption; stale
volatile memories rank lower at search time.

> Mem0 remembers relevant facts. VoltMem remembers **current truth**.

**Research & benchmarks:** [docs/RESEARCH.md](docs/RESEARCH.md)

---

## Install

```bash
pip install voltmem[embeddings]
# from source:
# pip install -e ".[embeddings]"
```

Core library has **zero required dependencies**. Embeddings extras pull in
`sentence-transformers` (recommended). LangChain: `pip install -e ".[langchain]"`.

---

## Quickstart

```python
from voltmem import create_memory

mem = create_memory("app.db", user_id="alice")

mem.add("I live in Berlin")
mem.add("I prefer concise, direct answers")
mem.add("Actually I moved to Paris last month")   # updates location, not prefs

hits = mem.search("where does the user live?", limit=3)
print(hits[0]["memory"])   # Actually I moved to Paris last month
```

### Message pairs (auto fact extraction)

```python
mem.add([
    {"role": "user", "content": "I moved to Paris. I'm working on a DB migration."},
], extract=True)   # default for message lists — splits into atomic facts
```

Optional: `create_memory(..., llm_extract=True)` for Ollama-powered extraction.

### Inject into a prompt

```python
memories = mem.search(user_message, limit=5)
context = "\n".join(f"- {m['memory']}" for m in memories)
system = f"What you know about this user:\n{context}"
```

---

## API

| Method | Description |
|---|---|
| `create_memory(db, user_id)` | Factory with auto-detected embeddings |
| `Memory.add(text \| messages)` | Store a fact; slot-aware linking updates related memories |
| `Memory.search(query, limit=5)` | Ranked memories (relevance + freshness) |
| `Memory.get_all()` | All active memories for this user |
| `Memory.delete(id)` | Remove one memory |
| `Memory.clear()` | Wipe user namespace |

Advanced: `mem.layer` exposes `MemoryLayer` for low-level `observe()` / `write()`.

---

## Why VoltMem

| Problem | ADD-only memory | VoltMem |
|---|---|---|
| User moves cities | Berlin and Paris both stored | **Updates** to current city |
| Old project name in haystack | Ranks by similarity | **Down-ranks** stale volatile facts |
| Confident wrong blip on stable pref | Often accepted | **Resists** corruption |

### Example results (reproducible)

Run locally with `pip install -e ".[embeddings]"`. Embeddings:
`sentence-transformers` (`all-MiniLM-L6-v2`).

**`examples/contradiction_demo.py`** — 5-turn script vs naive always-add:

| After scenario | always-add | VoltMem |
|---|---|---|
| User moves Berlin → Paris | 2 location facts (stale + current) | **1** current fact |
| Paraphrase blip on stable pref | adopts blip ("really like short replies") | **keeps** original ("concise, direct answers") |

**`experiments/mem0_comparison.py`** — 3 scenarios, top-1 search (always-add baseline):

| Scenario | always-add | VoltMem |
|---|---|---|
| `location_update` | WIN (2 facts stored) | WIN (**1** fact) |
| `stable_pref_blip` | LOSE | **WIN** |
| `volatile_mood` | LOSE (stale "great") | **WIN** (current "stressed") |

**VoltMem clearer wins: 2/3** (always-add also finds Paris on location, but keeps stale facts).

**`experiments/mem0_side_by_side.py`** — same 3 scenarios vs **real Mem0**
(open-source, `gpt-4o-mini` + `text-embedding-3-small`):

| Scenario | Mem0 | VoltMem |
|---|---|---|
| `location_update` | LOSE (stale "Berlin", 2 facts) | **WIN** ("Paris", 1 fact) |
| `stable_pref_blip` | PARTIAL (adopts blip) | **WIN** (keeps "concise") |
| `volatile_mood` | LOSE (stale "great", 2 facts) | **WIN** ("stressed", 1 fact) |

**VoltMem clearer wins: 3/3.** Mem0 keeps contradictory facts; VoltMem updates volatile
slots and protects stable prefs via domain volatility + slot-aware linking.

**`experiments/memory_demo.py`** — 3 final Q&A checks vs ground truth:

| Policy | Score |
|---|---|
| **VoltMem** | **3/3** |
| never-overwrite | 2/3 |
| always-overwrite | 1/3 |
| reliability-threshold | 1/3 |

VoltMem is the only policy that both **rejects confident false blips** on stable
facts and **tracks weak-but-true updates** on volatile ones. Full distributions:
[docs/RESEARCH.md](docs/RESEARCH.md) (`llm_memory_bench.py`).

```bash
python examples/contradiction_demo.py
python experiments/mem0_comparison.py
python experiments/mem0_side_by_side.py   # pip install mem0ai; OPENAI_API_KEY or MEM0_BACKEND=ollama
python experiments/memory_demo.py
```

---

## Integrations

### LangChain

```bash
pip install -e ".[langchain]"
python examples/langchain_agent.py
```

```python
from voltmem.integrations.langchain import VoltMemMemory

memory = VoltMemMemory(session_id="user-42", db_path="app.db")
memory.load_memory_variables({"input": "Where do I live?"})
memory.save_context({"input": "I moved to Paris"}, {"output": "Noted."})
```

### Multi-tenant

One SQLite file, many users — `user_id` maps to an isolated namespace:

```python
alice = create_memory("app.db", user_id="alice")
bob   = create_memory("app.db", user_id="bob")
```

---

## Examples

| Script | What it shows |
|---|---|
| `examples/contradiction_demo.py` | VoltMem vs always-add on contradictions |
| `experiments/mem0_comparison.py` | 3-scenario head-to-head vs always-add |
| `experiments/mem0_side_by_side.py` | 3-scenario head-to-head vs real Mem0 (3/3 wedge) |
| `examples/quickstart_batteries.py` | `remember()` / `recall()` low-level API |
| `examples/multi_tenant.py` | One DB, many users |
| `examples/langchain_agent.py` | LangChain adapter |

---

## Domain volatility priors

| Domain | Volatility | Behavior |
|---|---|---|
| `personality_trait` | 0.05 | Very protected |
| `core_preference` | 0.08 | Very protected |
| `biographical` | 0.10 | High protection |
| `current_project` | 0.55 | Updates readily |
| `emotional_context` | 0.80 | Fast-moving |
| `current_task` | 0.90 | Minimal protection |

Custom domains: `voltmem/domains.py`.

---

## Development

```bash
pip install -e ".[all]"
python tests/test_voltmem.py
python tests/test_client.py
```

Experiments and benchmarks live in `experiments/` — see [docs/RESEARCH.md](docs/RESEARCH.md).

---

## License

MIT
