Skip to main content

VoltMem

Version Python License: MIT

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 · Known limits & roadmap: docs/OPEN_PROBLEMS.md


Install

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

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)

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

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 + vector index
Memory.add(text | messages) Store a fact; slot-aware linking updates related memories
Memory.search(query, limit=5) ANN candidates + volatility re-rank (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().

create_memory(..., vector_index="auto") enables a SQLite embedding index when an embedder is present ("off" restores full-scan retrieval). VoltMem always applies volatility re-ranking on top of vector candidates — not raw ANN results.

flowchart LR
  Q[search query] --> E[embed query]
  E --> V[vector index: top candidates]
  V --> S[SQLite: load memory records]
  S --> R[volatility re-rank → current truth]

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
Career / role change (medium-stable) Often blocked or duplicated Updates on strong explicit contradiction

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/voltmem_eval.py — end-to-end escalation + retrieval (real vs flat vs swap):

Battery real profile flat (equal V) swap (inverted V)
A — selective updating 20/20 15/20 7/20
B — retrieval separation +0.589 +0.202 −0.267

Includes the professional_context career-change probe (strong explicit evidence → update).

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 (llm_memory_bench.py).

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/voltmem_eval.py        # 20/20 escalation probes + retrieval separation
python experiments/memory_demo.py

Integrations

LangChain

pip install -e ".[langchain]"
python examples/langchain_agent.py
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:

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)
experiments/voltmem_eval.py End-to-end escalation + retrieval (20/20 probes, real > flat > swap)
experiments/calibrate_escalation.py Print E_t vs θ table for tuning explicit-override constants
examples/quickstart_batteries.py remember() / recall() low-level API
examples/multi_tenant.py One DB, many users
examples/langchain_agent.py LangChain adapter
examples/chat_app/ Memory-aware CLI chat (extendable to web UI)
examples/custom_classifier.py Pluggable KeywordClassifier + DomainRegistry

Chat app (CLI)

pip install -e ".[embeddings]"
python -m examples.chat_app              # REPL; uses Ollama if running, else echo mode
python -m examples.chat_app --demo       # scripted smoke test
python -m examples.chat_app --show-recall

Slash commands: /memories, /search <query>, /clear, /reset, /help.


Domain volatility priors

Domain Volatility Behavior
personality_trait 0.05 Very protected
core_preference 0.08 Very protected
biographical 0.10 High protection
professional_context 0.30 Medium — job/role (career changes)
location 0.60 Updates readily (Berlin → Paris)
current_project 0.55 Updates readily
emotional_context 0.80 Fast-moving
current_task 0.90 Minimal protection

Custom domains: register via DomainRegistry and pass to create_memory(domains=...). Pluggable classifiers: create_memory(classifier=...)"heuristic", "llm", KeywordClassifier, or a callable dict.

Optional: create_memory(..., auto_discover=True) learns per-domain volatility from confirm / mismatch / supersede patterns (blended with priors above; cold-start applies).

from voltmem import create_memory, DomainRegistry, KeywordClassifier, ChainedClassifier, HeuristicClassifier

domains = DomainRegistry()
domains.register("style_preference", 0.08)
domains.register("style_constraint", 0.25)

mem = create_memory(
    "app.db",
    user_id="alice",
    domains=domains,
    classifier=ChainedClassifier([
        KeywordClassifier({
            "style_preference": ["prefer", "darker colors", "minimal"],
            "style_constraint": ["no wool", "tight budget"],
        }),
        HeuristicClassifier(),
    ]),
)

mem.add("I prefer darker colors and minimal fits")
hits = mem.search("what colors does the user like?")

Development

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

Experiments and benchmarks live in experiments/ — see docs/RESEARCH.md. Open problems and roadmap: docs/OPEN_PROBLEMS.md.


License

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

voltmem-0.2.1.tar.gz (49.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

voltmem-0.2.1-py3-none-any.whl (42.0 kB view details)

Uploaded Python 3

File details

Details for the file voltmem-0.2.1.tar.gz.

File metadata

  • Download URL: voltmem-0.2.1.tar.gz
  • Upload date:
  • Size: 49.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.13

File hashes

Hashes for voltmem-0.2.1.tar.gz
Algorithm Hash digest
SHA256 e2e32a656c77ea77077bda2a483bba855fc460b5cac41ee1d11804a31f7f76e1
MD5 0551729a763b14b0d03b0f43a645a2d5
BLAKE2b-256 c1e5f17cc31c8d4a64352acacd05c9aeed61c6e6c26cca873ec425641f782b18

See more details on using hashes here.

File details

Details for the file voltmem-0.2.1-py3-none-any.whl.

File metadata

  • Download URL: voltmem-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 42.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.13

File hashes

Hashes for voltmem-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 92878bff5876ae1426ab8e545bf7e1d1de98df9d97e25db01ae221e55df19a95
MD5 4dc11c9ec909cbe0d5e94ee66657b573
BLAKE2b-256 fc802388c0439fbbe4f9f3751d4cadb26ceb5f388a819616ec9d342f86f2ca9e

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page