Skip to main content

Persistent long-term memory layer for AI applications.

Project description

MemoryOS

Persistent long-term memory for any AI application.

PyPI version Python License: MIT GitHub Stars

MemoryOS gives any LLM or AI assistant persistent, structured memory across sessions.
Works with ChatGPT, Claude, Gemini, local models, or any LLM-based system.
No cloud required. No vendor lock-in. Fully local by default.

InstallationQuickstartArchitectureExamplesConfigurationAPI Reference


Why MemoryOS

LLMs are stateless. Every conversation starts from zero — users repeat themselves, context is lost, and AI assistants feel shallow.

MemoryOS adds a structured memory layer that:

  • Remembers user preferences, goals, identity, and decisions across sessions
  • Retrieves only the most relevant memories for each query (not everything at once)
  • Stays fully local with SQLite and in-memory vector search out of the box
  • Works with any LLM — just inject the context string into your prompt
from memoryos import MemoryOS

memory = MemoryOS(session_id="user_123")

# Turn 1
memory.process_turn("My name is Aryan. I prefer dark mode UI.", "Got it!")

# Turn 2 — days later, new session
context = memory.build_context("What does this user prefer?")
# → "Relevant user facts:\n- User's name is Aryan (type=identity)\n- User prefers dark mode UI (type=preference)"

Installation

pip install memoryos

With semantic embeddings (recommended for production):

pip install "memoryos[embeddings]"

With FAISS vector index (for large memory stores):

pip install "memoryos[embeddings,faiss]"

Requirements: Python 3.9+, numpy (auto-installed)


Quickstart

Basic usage

from memoryos import MemoryOS

# Initialize — SQLite database created automatically
memory = MemoryOS(db_path="memory.db", session_id="user_1")

# Process conversation turns
memory.process_turn("My name is Aryan. I'm building an AI memory library.", "That's awesome!")
memory.process_turn("I prefer dark mode and minimal UI.", "Noted!")
memory.process_turn("My goal is to land a remote backend engineering role.", "Great goal!")

# Build context for your next LLM prompt
context = memory.build_context("Tell me about this user.")
print(context)

# Search memory directly
results = memory.search_memory("UI preferences", top_k=3)
for result in results:
    print(f"{result.content}  [score={result.score:.3f}]")

memory.close()

Using context in an LLM prompt

from memoryos import MemoryOS

memory = MemoryOS(db_path="memory.db", session_id="user_1")

def chat(user_message: str) -> str:
    # Get relevant memory context
    context = memory.build_context(user_message)

    # Inject into your LLM system prompt
    system_prompt = f"""You are a helpful assistant.

{context}

Use the above memory context to personalize your response."""

    # Call your LLM here (OpenAI, Anthropic, local model, etc.)
    ai_response = your_llm_call(system_prompt, user_message)

    # Save the turn so memory grows over time
    memory.process_turn(user_message, ai_response)

    return ai_response

Architecture

MemoryOS uses a three-tier memory architecture. Each layer serves a different purpose.

┌─────────────────────────────────────────────────────────┐
│                        MemoryOS                         │
│                                                         │
│  ┌─────────────────┐  ┌──────────────┐  ┌───────────┐   │
│  │  Working Memory │  │   Semantic   │  │  Episodic │   │
│  │   (RAM)         │  │   Memory     │  │  Memory   │   │
│  │                 │  │  (SQLite +   │  │  (SQLite) │   │
│  │ Last 6–10 turns │  │   Vectors)   │  │           │   │
│  │ Always injected │  │              │  │ Compressed│   │
│  │ Verbatim        │  │ Long-term    │  │ episode   │   │
│  │                 │  │ facts        │  │ summaries │   │
│  └─────────────────┘  └──────────────┘  └───────────┘   │
│                                                         │
│              MemoryRetriever + MemoryRanker             │
│         (similarity · confidence · recency · type)      │
│                                                         │
│                   PromptContextBuilder                  │
│              (token-budget-aware formatting)            │
└─────────────────────────────────────────────────────────┘

Working Memory

  • Stores the last 6–10 conversation turns verbatim
  • Always injected into context — no retrieval needed
  • Provides immediate short-term continuity

Semantic Memory

  • Extracts and stores long-term facts from conversations
  • Fact types: identity, preference, goal, decision, context
  • Retrieved by vector similarity to the current query
  • Deduplicated automatically — no repeated facts
  • Confidence scoring filters out low-quality extractions

Episodic Memory

  • Compressed summaries of past conversation sessions
  • Retrieved by semantic similarity
  • Reduces token usage for long conversation histories

Fact Extraction

MemoryOS automatically detects and extracts facts from user messages:

Pattern Example Input Extracted Fact
Identity "My name is Aryan" User's name is Aryan
Preference "I prefer dark mode" User prefers dark mode
Goal "My goal is to learn Rust" User's goal is to learn Rust
Decision "I decided to use Postgres" User decided to use Postgres
Context "I am working on MemoryOS" User is working on MemoryOS

Examples

ChatGPT integration

from openai import OpenAI
from memoryos import MemoryOS

client = OpenAI()
memory = MemoryOS(db_path="chat.db", session_id="user_1")

def chat(user_message: str) -> str:
    context = memory.build_context(user_message)

    response = client.chat.completions.create(
        model="gpt-4o",
        messages=[
            {"role": "system", "content": f"You are a helpful assistant.\n\n{context}"},
            {"role": "user", "content": user_message},
        ],
    )

    ai_response = response.choices[0].message.content
    memory.process_turn(user_message, ai_response)
    return ai_response

print(chat("My name is Aryan and I prefer concise answers."))
print(chat("What's my name?"))  # Memory recalls it

Claude integration

import anthropic
from memoryos import MemoryOS

client = anthropic.Anthropic()
memory = MemoryOS(db_path="chat.db", session_id="user_1")

def chat(user_message: str) -> str:
    context = memory.build_context(user_message)

    response = client.messages.create(
        model="claude-opus-4-6",
        max_tokens=1024,
        system=f"You are a helpful assistant.\n\n{context}",
        messages=[{"role": "user", "content": user_message}],
    )

    ai_response = response.content[0].text
    memory.process_turn(user_message, ai_response)
    return ai_response

Gemini integration

import google.generativeai as genai
from memoryos import MemoryOS

genai.configure(api_key="YOUR_API_KEY")
model = genai.GenerativeModel("gemini-1.5-flash")
memory = MemoryOS(db_path="chat.db", session_id="user_1")

def chat(user_message: str) -> str:
    context = memory.build_context(user_message)
    prompt = f"{context}\n\nUser: {user_message}"

    response = model.generate_content(prompt)
    ai_response = response.text

    memory.process_turn(user_message, ai_response)
    return ai_response

Custom embedding provider

from memoryos import MemoryOS
from memoryos.interfaces.embedding_provider import EmbeddingProvider

class MyEmbeddingProvider(EmbeddingProvider):
    model_name = "my-custom-model"
    dimension = 768

    def embed(self, texts):
        # Call your embedding API or local model here
        return my_embedding_api(texts)

    def similarity(self, text1: str, text2: str) -> float:
        e1 = self.embed_one(text1)
        e2 = self.embed_one(text2)
        return cosine_similarity(e1, e2)

memory = MemoryOS(db_path="chat.db", session_id="user_1")
# Inject custom embedding at the semantic memory level
from memoryos.memory.semantic import SemanticMemory
# See advanced docs for full custom injection

Adding memory manually

from memoryos import MemoryOS

memory = MemoryOS(db_path="chat.db", session_id="user_1")

# Manually add a fact without extraction
memory.add_memory("User is a backend engineer at Tata Motors", fact_type="context", confidence=0.99)
memory.add_memory("User's preferred language is Python", fact_type="preference", confidence=0.95)

# Retrieve it
context = memory.build_context("What tech does this user use?")
print(context)

Context manager

from memoryos import MemoryOS

with MemoryOS(db_path="chat.db", session_id="user_1") as memory:
    memory.process_turn("I'm working on a RAG pipeline.", "Nice!")
    context = memory.build_context("What is the user building?")
    print(context)
# Connection closed automatically

Configuration

All settings can be passed to MemoryOSConfig or as keyword arguments.

from memoryos import MemoryOS, MemoryOSConfig

config = MemoryOSConfig(
    db_path="my_memory.db",           # SQLite database path
    working_memory_size=10,           # Turns to keep in working memory
    semantic_top_k=5,                 # Top facts to retrieve per query
    episodic_top_k=3,                 # Top episode summaries to retrieve
    min_fact_confidence=0.65,         # Minimum confidence to store a fact
    duplicate_similarity_threshold=0.90,  # Threshold to skip duplicate facts
    embedding_model_name="sentence-transformers/all-MiniLM-L6-v2",
    embedding_dim=384,
    max_context_tokens=6000,          # Max characters in context output
    auto_create_episodes=False,       # Auto-create episode summaries
)

memory = MemoryOS(config=config, session_id="user_1")

Environment variable configuration

export MEMORYOS_DB_PATH=./data/memory.db
export MEMORYOS_WORKING_MEMORY_SIZE=12
export MEMORYOS_MIN_FACT_CONFIDENCE=0.70
export MEMORYOS_ENABLE_FAISS=true
memory = MemoryOS.from_env(session_id="user_1")

Configuration reference

Parameter Default Description
db_path memoryos.db SQLite database file path
working_memory_size 8 Number of recent turns to keep
semantic_top_k 5 Top semantic facts retrieved per query
episodic_top_k 3 Top episode summaries retrieved per query
min_fact_confidence 0.65 Minimum confidence score to store a fact
duplicate_similarity_threshold 0.90 Cosine threshold for deduplication
embedding_model_name all-MiniLM-L6-v2 Sentence transformer model
embedding_dim 384 Embedding vector dimensions
max_context_tokens 6000 Max characters in built context
enable_faiss False Use FAISS for vector index
auto_create_episodes False Auto-create episode summaries
min_episode_turns 4 Minimum turns before creating an episode

API Reference

MemoryOS

Initialization

MemoryOS(
    db_path: str = None,
    session_id: str = "default_session",
    config: MemoryOSConfig = None,
)

Core methods

Method Description
process_turn(user_message, ai_response) Save a turn and extract facts
build_context(query) Build context string for LLM prompt
search_memory(query, top_k, min_score) Search all memory layers
add_memory(content, fact_type, confidence) Manually add a fact

Data access

Method Description
get_all_facts(limit) Return all stored facts
get_session_facts(session_id, limit) Return facts for a session
get_turns(session_id, limit) Return stored conversation turns
get_episodes(session_id, limit) Return episode summaries

Session management

Method Description
clear_session(session_id) Clear all data for a session
clear_all() Clear all data in the database
close() Close database connection
maybe_create_episode(session_id) Manually trigger episode creation

Fact object

@dataclass
class Fact:
    content: str          # "User's name is Aryan"
    type: str             # identity | preference | goal | decision | context
    confidence: float     # 0.0 – 1.0
    session_id: str
    id: str               # UUID
    source: str           # conversation | manual | system
    timestamp: float      # Unix timestamp
    access_count: int
    embedding: List[float]
    metadata: Dict

MemorySearchResult object

@dataclass
class MemorySearchResult:
    content: str          # Memory content
    source: str           # working | semantic | episodic
    score: float          # Ranked relevance score 0.0 – 1.0
    type: str             # Fact type if semantic
    confidence: float     # Original extraction confidence
    timestamp: float
    metadata: Dict

Ranking System

MemoryOS ranks retrieved memories using four signals:

Signal Weight Description
Similarity 70% Cosine similarity to query embedding
Confidence 15% Extraction confidence score
Recency 10% Exponential decay (30-day half-life by default)
Source 5% semantic > episodic > working

Fact types also apply multipliers: identity (1.05×) → decision (1.03×) → goal (1.02×) → preference (1.01×) → context (1.00×).


Design Philosophy

  • Local-first — no required cloud services, no hidden API calls
  • Model-agnostic — works with any LLM, any embedding model
  • No forced dependencies — sentence-transformers and FAISS are optional
  • Transparent — confidence scores, source labels, and ranked scores are always visible
  • Extensible — replace any component: storage, embeddings, ranking, summarization
  • Opinionated defaults — works out of the box, customizable for production

Roadmap

  • Three-tier memory architecture (working, semantic, episodic)
  • Fact extraction with confidence scoring and deduplication
  • SQLite storage backend
  • In-memory and FAISS vector index
  • Token-budget-aware context builder
  • Recency-weighted ranking
  • from_env() configuration
  • PostgreSQL + pgvector storage backend
  • Async API (aprocess_turn, abuild_context)
  • OpenAI-compatible embedding provider
  • Memory export / import (JSON)
  • REST API server mode
  • LangChain and LlamaIndex integrations

Contributing

Contributions are welcome. Please open an issue before submitting a large PR.

git clone https://github.com/aryan-iconic/MemoryOS
cd MemoryOS
pip install -e ".[dev]"
pytest

License

MIT License — see LICENSE for details.


Built by Aryan Gupta · GitHub · PyPI

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

memoryos_local-0.1.0.tar.gz (55.1 kB view details)

Uploaded Source

Built Distribution

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

memoryos_local-0.1.0-py3-none-any.whl (56.4 kB view details)

Uploaded Python 3

File details

Details for the file memoryos_local-0.1.0.tar.gz.

File metadata

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

File hashes

Hashes for memoryos_local-0.1.0.tar.gz
Algorithm Hash digest
SHA256 a240de0eb96efcd3b7386ee011c6106f0f313f9edf5cd17b9b7d75a49d063bfc
MD5 dbdadbf4ef333a864e812fbc454f028c
BLAKE2b-256 4ae51da280274d9c1a7569dcc41f87bd4e79897f3a36bb8badc69d360f5e3ab0

See more details on using hashes here.

File details

Details for the file memoryos_local-0.1.0-py3-none-any.whl.

File metadata

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

File hashes

Hashes for memoryos_local-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e476e879dd86bb70156230dda47224c86003ebc14514107f89a1c1dc01310f7b
MD5 29eaa49084f35e2f205dc650b6e87191
BLAKE2b-256 88ab548e23c133dd1a951628ea89207cd825505cf6f1f1e2838b50f0d1b68444

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