Skip to main content

Local-first eternal memory engine for any LLM: conflict-aware claims, temporal validity, trust scoring, retrieval plasticity. Zero dependencies.

Project description

evermem

Local-first eternal memory for any LLM. Conflict-aware facts, temporal validity windows, trust scoring, and retrieval that learns from feedback. Pure Python stdlib - zero dependencies, SQLite under the hood, your data never leaves your machine.

LLMs forget everything between sessions. Cloud memory services fix that by shipping your users' most personal data to someone else's API, and still get the hard parts wrong: they return facts that were contradicted weeks ago, add seconds of network latency to every turn, and break the moment you are offline. evermem runs entirely on your hardware and models memory as a lifecycle, not a pile of vectors:

  • Temporal validity - "lived in Minsk" isn't deleted when the user moves to Warsaw; it's superseded with a validity window. Recall returns the current fact, history is never lost.
  • Conflict awareness - contradictory facts are detected, surfaced to the LLM ("verify with the user"), and resolved by repetition and trust, not by last-write-wins.
  • Trust scoring - every claim carries trust that grows with confirmation and decays with contradiction.
  • Retrieval plasticity - recall paths that led to helpful answers are reinforced; noisy paths decay. Memory gets better the more you use it.
  • Four memory layers - working (recent turns), episodic (conversation episodes), semantic (stabilized claims), conflict (open contradictions) - modeled on how biological memory actually works.

No API keys. No Docker. No graph database to operate. One SQLite file.

Install

pip install evermem-ai            # core, zero dependencies
pip install "evermem-ai[pdf]"     # + PDF ingestion (pypdf)

The import name is evermem. Python 3.10+.

Quickstart

from evermem import EverMem

mem = EverMem("memory.db")  # rule-based extraction, no LLM needed

# Session 1
mem.observe("Меня зовут Алекс, я живу в Минске", session_id="s1")
mem.observe("I love black coffee", session_id="s1")

# Weeks later, a completely new session
pack = mem.recall("what do we know about the user?", session_id="s2")
print(pack.as_prompt())
# [MEMORY]
# Known facts (most relevant first):
# - user | name = алекс (trust 0.85, seen x1)
# - user | location = минске (trust 0.85, seen x1)
# - user | likes = black coffee (trust 0.75, seen x1)
# [/MEMORY]

mem.feedback(True, session_id="s2")  # reinforce what was useful

Inject pack.as_prompt() into any LLM's system prompt - OpenAI, Claude, or a 7B model running on your laptop. Use pack.as_prompt(budget_chars=4000) to hard-cap the pack size and keep prompts lean.

Working chat loops: examples/chat_ollama.py (fully offline) and examples/chat_openai.py (any OpenAI-compatible endpoint).

Documents: PDF, DOCX, HTML, Markdown

Feed files into the same memory; recall quotes the exact matching passages alongside conversation facts:

mem.observe_file("contract.pdf")            # needs evermem-ai[pdf]
mem.observe_file("meeting_notes.md")        # txt/md/docx/html: zero dependencies

pack = mem.recall("what is the monthly rent?")
# history now contains the matching document blocks (role "document")

Documents are split into paragraph-aligned blocks, embedded chunk by chunk and searched exactly like past conversation turns. DOCX and HTML parsing is stdlib-only.

Command line

Everything works from the terminal against the same database (~/.evermem/memory.db by default, override with --db or EVERMEM_DB):

evermem remember "we decided to ship v2 on March 3"
evermem import contract.pdf notes.md
evermem recall "when do we ship v2?"
evermem bootstrap        # session primer (call first in a new chat)
evermem profile          # everything known about the user, with trust and conflicts
evermem forget --subject user --predicate city   # invalidate a wrong fact
evermem correct user city "Warsaw"               # supersede with a correction
evermem aggregate "went to the gym"              # count matching sessions
evermem export backup.json                       # portable JSON backup
evermem stats            # database counters
evermem mcp              # run the MCP server

Add --model qwen2.5:7b to any command for LLM-powered fact extraction via Ollama, and --embed-model nomic-embed-text for better recall.

evermem Server (on-prem product)

Web chat + REST API for clients who will not pip install (med centers, law firms, integrators).

pip install "evermem-ai[server,pdf]"
ollama pull qwen2.5:7b && ollama pull nomic-embed-text
evermem-server   # http://127.0.0.1:8080

Docker (server + Ollama): see server/README.md and docker/docker-compose.yml.

Rich extraction with a local LLM (Ollama)

from evermem import EverMem, OllamaLLM

mem = EverMem("memory.db", llm=OllamaLLM("qwen2.5:7b"))
mem.observe("кстати, мы с женой завели кота, назвали Барсик")
# -> user | has_pet = кот барсик

If the LLM is down, extraction silently falls back to deterministic rules. The engine never breaks.

Better recall with local embeddings (optional)

By default evermem uses built-in hash embeddings (zero downloads, runs anywhere). For noticeably better semantic recall, plug in any local embedding model via Ollama:

from evermem import EverMem, OllamaEmbedder

mem = EverMem("memory.db", embedder=OllamaEmbedder("nomic-embed-text"))

Any callable str -> list[float] works - sentence-transformers, llama.cpp, your own model. The store handles arbitrary dimensions automatically.

Plug into Cursor / Claude Desktop (MCP)

{
  "mcpServers": {
    "evermem": {
      "command": "evermem",
      "args": ["mcp"],
      "env": { "EVERMEM_DB": "C:/Users/you/.evermem/memory.db" }
    }
  }
}

Recommended agent flow (matches what production memory MCPs like memory-mcp teach):

  1. memory_initialize - session primer at the start of every chat
  2. memory_recall - before answering questions about the past
  3. memory_remember - after the user shares durable facts
  4. memory_feedback - when recall was helpful or wrong
  5. memory_forget / memory_correct - when a stored fact is poisoned or outdated

Also available: memory_aggregate (how many times...), memory_import (PDF/MD), memory_remember_fact (structured write), MCP resources memory://profile and memory://conflicts.

Set EVERMEM_MODEL and EVERMEM_EMBED_MODEL for local Ollama extraction and recall quality.

LangChain / LlamaIndex

pip install "evermem-ai[langchain]"    # or [llamaindex]
from evermem import EverMem
from evermem.integrations.langchain import EverMemChatHistory, EverMemRetriever

mem = EverMem("memory.db")
history = EverMemChatHistory(mem, session_id="app")
history.add_user_message("We ship v2 on March 3")
print(EverMemRetriever(mem, session_id="app").invoke("when do we ship?"))

How it works

observe(text)
  └─ extractor (LLM or rules) ──> claims (subject, predicate, value, exclusive)
       └─ ClaimStore (SQLite)
            ├─ same value        -> reinforce: support+1, trust ↑
            ├─ exclusive change  -> supersede: validity window closes, history kept
            └─ coexisting values -> open conflict, trust competition

recall(query)
  └─ score = 0.55·semantic + 0.15·recency + 0.20·trust + 0.10·learned_paths
       └─ MemoryPack: facts + contradictions + history timeline + episodes + recent turns

feedback(helpful)
  └─ plasticity: reward/decay retrieval paths; adjust claim trust

Embeddings are deterministic hash vectors (token stems + char trigrams) - robust to Russian/English morphology and typos, no model download required. The embeddings module is swappable for real embedding models.

Why not just RAG?

RAG retrieves documents. Memory needs lifecycle: facts change, contradict each other, gain and lose credibility, and must be forgotten or superseded - not appended forever. A pure vector store will happily return "works at Acme" months after the user said they quit, because semantic similarity knows nothing about time. evermem models that lifecycle explicitly.

Comparison

evermem Mem0 Zep / Graphiti plain RAG
Runs fully offline yes no (LLM API for extraction) no depends
Setup pip install, one file SDK + LLM key Docker + graph DB DIY
Supersede / validity windows yes partial yes (temporal graph) no
Conflict surfacing to the LLM yes no no no
Learns from feedback yes no no no
Recall latency ~0.1 s local seconds (cloud) seconds (cloud) varies
Hardware floor any CPU, even no ML model cloud or GPU server GPU for embeddings
License MIT Apache 2.0 (cloud paid) cloud / enterprise -

Honest scope: Mem0 and Zep are managed platforms with SDK ecosystems and dashboards; evermem is an engine you embed. If you want zero cloud, zero dependencies and memory lifecycle done right, that trade is the point.

Performance

Latency on a plain CPU, zero-dependency mode (python bench/latency.py):

store size observe (p50) recall (p50) recall (p95)
2,000 turns 1.3 ms 103 ms 235 ms
10,000 turns 5.1 ms 346 ms 536 ms

Writes never block on a network call. For comparison, independent 2026 reviews measure cloud memory services at roughly 4 s (Zep) and 7 s (Mem0) per recall round-trip.

Benchmarks (LongMemEval)

Measured on longmemeval-cleaned with a fully local stack: nomic-embed-text embeddings + qwen2.5:7b reader/judge via Ollama. No cloud, no API keys.

Metric oracle (evidence only, n=500) _s (~40 distractor sessions, n=100)
Evidence session recall 99.8% 96.3%
QA accuracy (local 7B reader) 58.7% 51.1%
Answer presence in pack 44.7% 51.1%

Retrieval is essentially solved by the memory layer (96-100% evidence recall); the reader model sets the ceiling. Best types on the haystack: knowledge-update 85.7% (temporal validity windows at work), single-session-preference 66.7%, single-session-user 61.5%.

For reference: Zep reports 63.8% on LongMemEval with a GPT-4o reader in the cloud. evermem reaches 51.1% with a 7B model that runs on a $300 GPU - a different point on the cost/privacy curve, fully offline. The pack hands the reader a dated timeline with pre-computed day gaps, which alone lifted temporal-reasoning QA from 4% to 40-52%.

Zero-dependency mode (hash embeddings, no Ollama at all) still achieves 71% evidence recall on the haystack - enough for edge devices where no embedding model fits.

python bench/run_longmemeval.py --data bench/data/longmemeval_s.json \
  --embed-model nomic-embed-text --qa-model qwen2.5:7b --every 5 --report bench/report_s_v3.json
python bench/analyze_errors.py --report bench/report_s_v3.json --data bench/data/longmemeval_s.json

Full runbook: bench/README.md.

FAQ

Does it need an internet connection or API key? No. The core runs on the Python standard library alone. Ollama integration is optional and also local.

Multiple users on one database? Yes: every API call takes user_id, memories are strictly isolated per user.

How do I delete a user's data (GDPR)? Keep one database file per user and delete the file: erasure is then physical and provable, which is exactly what regulators want from on-device storage.

What about non-English text? The hash embedder handles Russian and English morphology out of the box; rule extraction covers both languages. Any other language works through an Ollama embedder and LLM extractor.

Can I use my own vector model / store? Embeddings are any str -> list[float] callable. The storage layer is a single SQLite file you can inspect with any SQLite client.

Will it slow my agent down? Recall is a local SQLite query plus vector scan: ~0.1 s at 2k turns on CPU, no network round-trip. observe is a few milliseconds and can run after the response is sent.

Status & roadmap

  • Claim store with validity windows, conflicts, trust
  • Retrieval plasticity (learning from feedback)
  • LLM extraction (Ollama / OpenAI-compatible) with rule fallback
  • Pluggable embeddings (hash zero-dep default, Ollama backend, any callable)
  • Chunk-level turn search + dated timeline with pre-computed day gaps
  • Document ingestion: PDF, DOCX, HTML, Markdown, plain text
  • Memory lifecycle: forget, correct, purge (GDPR), provenance (source session/turn)
  • Session primer (bootstrap / memory_initialize) with stale-fact warnings
  • Multi-session aggregation (aggregate / memory_aggregate)
  • MCP: 10 tools + 2 resources, embed model, budget_chars, feedback loop
  • CLI: remember / recall / import / bootstrap / forget / correct / export / mcp
  • MCP server (memory for Cursor / Claude Desktop in one config line)
  • LongMemEval harness: retrieval metrics + QA stage (local reader + judge) + error analyzer
  • Multi-session: entity counters at ingest + distinct-item counts in recall
  • Temporal: chronological order block for which-first questions
  • Preferences: boosted in recall for recommend/suggest questions
  • Episode summarization (rule fallback; LLM when Ollama configured)
  • LangChain / LlamaIndex adapters (pip install "evermem-ai[langchain]")
  • Sprint 4: memory events, assistant extract, query router (0.3.0)
  • evermem Server: FastAPI + web UI + upload + Docker (0.4.0)
  • Control measurement: raw full history vs MemoryPack (context compression chart)
  • Encrypted memory sync between devices (first paid feature; core stays MIT forever)

Development

pip install -e .[dev]
pytest -q          # 78 tests, no network needed
python demo.py     # offline end-to-end scenario

MIT License.

Project details


Download files

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

Source Distribution

evermem_ai-0.4.0.tar.gz (167.4 kB view details)

Uploaded Source

Built Distribution

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

evermem_ai-0.4.0-py3-none-any.whl (157.3 kB view details)

Uploaded Python 3

File details

Details for the file evermem_ai-0.4.0.tar.gz.

File metadata

  • Download URL: evermem_ai-0.4.0.tar.gz
  • Upload date:
  • Size: 167.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.9

File hashes

Hashes for evermem_ai-0.4.0.tar.gz
Algorithm Hash digest
SHA256 72eec2b4b22ae83312826a348141708956ce03b443907e0f7237b281d61c2a7a
MD5 ee17e1d2cb787fd7e832c9c959d948d6
BLAKE2b-256 38415bb00fb58b73bc8cf79e432a07e71162ccf2996a23ad9a0f8accf36a2946

See more details on using hashes here.

File details

Details for the file evermem_ai-0.4.0-py3-none-any.whl.

File metadata

  • Download URL: evermem_ai-0.4.0-py3-none-any.whl
  • Upload date:
  • Size: 157.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.9

File hashes

Hashes for evermem_ai-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 2c60947d8c6e6f2a2cda0d0485dedc29cd53420b9ae520bd42ad2defb49d6223
MD5 ec9bd53b5f227fa8211d8be8e4b56818
BLAKE2b-256 a127d7843621cd6ce56d86f6440ff66381b3d64baaeb448ed7a5d50808c333b6

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