Skip to main content

Long-term memory system for AI conversations

Project description

ContextMemory

A production-ready long-term memory system for AI conversations.

ContextMemory extracts, stores, and retrieves important facts from conversations, enabling AI Agents to remember user preferences, context, and history across sessions. It supports both semantic facts (stable, long-term truths) and episodic bubbles (time-bound moments).

Features

  • Dual Memory Types: Semantic facts + Episodic bubbles
  • Fast Search: FAISS-powered O(log n) vector search
  • Smart Updates: Automatic contradiction detection & replacement
  • Memory Connections: Bubbles auto-link to related facts
  • Multi-Provider: OpenAI or OpenRouter (Claude, etc.)
  • Flexible Storage: SQLite (default) or PostgreSQL

Installation

pip install contextmemory

Quick Start

Option 1: OpenAI (Direct)

from contextmemory import configure, create_table, Memory, SessionLocal

# Configure with OpenAI
configure(
    openai_api_key="sk-...",
    database_url="postgresql://...",  # Optional, defaults to SQLite
)

# Create tables
create_table()

# Use memory
db = SessionLocal()
memory = Memory(db)

Option 2: OpenRouter (Claude, etc.)

from contextmemory import configure, create_table, Memory, SessionLocal

# Configure with OpenRouter
configure(
    openrouter_api_key="sk-or-v1-...",
    llm_provider="openrouter",
    llm_model="anthropic/claude-sonnet-4.5",  # Or any OpenRouter model
    embedding_model="openai/text-embedding-3-small",
    database_url="postgresql://...",
)

create_table()
db = SessionLocal()
memory = Memory(db)

Environment Variables (Alternative)

# For OpenAI
export OPENAI_API_KEY="sk-..."

# For OpenRouter
export OPENROUTER_API_KEY="sk-or-v1-..."

# Optional
export DATABASE_URL="postgresql://..."

Basic Usage

Add Memories

# Add memories from a conversation
messages = [
    {"role": "user", "content": "Hi, I'm Samiksha and I love Python programming"},
    {"role": "assistant", "content": "Nice to meet you! Python is great."},
]

result = memory.add(messages=messages, conversation_id=1)
# Returns: {'semantic': ['User is named Samiksha', 'User loves Python'], 'bubbles': []}

Search Memories

results = memory.search(
    query="What programming language does the user like?",
    conversation_id=1,
    limit=5
)

print(results)
# {
#   'query': '...',
#   'results': [
#     {'memory_id': 1, 'memory': 'User loves Python programming', 'type': 'semantic', 'score': 0.89}
#   ]
# }

Update & Delete

# Update a memory
memory.update(memory_id=1, text="User is an expert Python developer")

# Delete a memory
memory.delete(memory_id=1)

Memory Types

Semantic Facts

Stable, long-term truths about the user:

  • Name, preferences, skills
  • Professional background
  • Dietary preferences, relationships

Episodic Bubbles

Time-bound moments with automatic connections:

  • Current tasks, deadlines
  • Active problems being solved
  • Significant events
# Bubbles auto-connect to related semantic facts
memory.add(
    messages=[
        {"role": "user", "content": "I'm debugging a FastAPI auth issue"},
        {"role": "assistant", "content": "Let me help with that."}
    ],
    conversation_id=1
)
# Creates bubble: "User is debugging FastAPI auth issue"
# Auto-connects to: "User works on backend development"

Full Example: Chat with Memory

from openai import OpenAI
from contextmemory import configure, create_table, Memory, SessionLocal

# Configure
configure(
    openrouter_api_key="sk-or-v1-...",
    llm_provider="openrouter",
    llm_model="anthropic/claude-sonnet-4.5",
    embedding_model="openai/text-embedding-3-small",
    database_url="postgresql://...",
)

create_table()

# Initialize
chat_client = OpenAI(
    api_key="sk-or-v1-...",
    base_url="https://openrouter.ai/api/v1"
)
db = SessionLocal()
memory = Memory(db)

def chat_with_memories(message: str, conversation_id: int = 1) -> str:
    # 1. Search relevant memories
    search_results = memory.search(
        query=message,
        conversation_id=conversation_id,
        limit=5
    )
    
    memories_str = "\n".join(
        f"- [{r['type']}] {r['memory']}"
        for r in search_results["results"]
    )
    
    # 2. Build prompt with memories
    system_prompt = f"""You are a helpful AI with access to user's memories.

User Memories:
{memories_str or 'No memories yet.'}

Use memories to give personalized responses."""

    # 3. Call LLM
    response = chat_client.chat.completions.create(
        model="anthropic/claude-sonnet-4.5",
        messages=[
            {"role": "system", "content": system_prompt},
            {"role": "user", "content": message}
        ]
    )
    
    assistant_response = response.choices[0].message.content
    
    # 4. Store new memories
    memory.add(
        messages=[
            {"role": "user", "content": message},
            {"role": "assistant", "content": assistant_response}
        ],
        conversation_id=conversation_id
    )
    
    return assistant_response

# Chat loop
while True:
    user_input = input("You: ")
    if user_input.lower() == "exit":
        break
    print(f"AI: {chat_with_memories(user_input)}")

Configuration Reference

Parameter Required Default Description
openai_api_key Yes* - OpenAI API key
openrouter_api_key Yes* - OpenRouter API key
llm_provider No openai openai or openrouter
llm_model No gpt-4o-mini LLM model for extraction
embedding_model No text-embedding-3-small Embedding model
database_url No SQLite PostgreSQL URL
debug No False Enable debug logging

*One of openai_api_key or openrouter_api_key required based on llm_provider.

API Reference

configure(**kwargs)

Set global configuration. Call before any other operations.

create_table()

Create all required database tables.

Memory(db: Session)

Main memory interface.

Methods:

  • add(messages, conversation_id) → Extract & store memories
  • search(query, conversation_id, limit) → Search memories
  • update(memory_id, text) → Update a memory
  • delete(memory_id) → Delete a memory

SessionLocal()

Create a new database session.

How It Works

User Message → Extraction (LLM) → Tool Classification (LLM) → FAISS Index + DB
                    ↓                       ↓
              Semantic Facts           ADD/UPDATE/REPLACE/NOOP
              Episodic Bubbles
                    ↓
              Connection Finder → Links bubbles to related facts

Key Features:

  • Contradiction Detection: "I'm vegetarian" → "I eat meat" triggers REPLACE
  • FAISS Search: O(log n) vector search instead of O(n) loops
  • Smart Extraction: Only extracts from latest interaction, not context

License

MIT License - see LICENSE file.

Contributing

Contributions welcome! Open an issue or submit a PR.

Links

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

contextmemory-0.2.0.tar.gz (28.3 kB view details)

Uploaded Source

Built Distribution

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

contextmemory-0.2.0-py3-none-any.whl (34.9 kB view details)

Uploaded Python 3

File details

Details for the file contextmemory-0.2.0.tar.gz.

File metadata

  • Download URL: contextmemory-0.2.0.tar.gz
  • Upload date:
  • Size: 28.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.2

File hashes

Hashes for contextmemory-0.2.0.tar.gz
Algorithm Hash digest
SHA256 f2834d4110d1c282723893eed9f946c3f0551067d486ba6d4caf2e6a7a946f72
MD5 99c8d4218829734376a9395b8bccae8b
BLAKE2b-256 8cd308bd02fb87fc7317aada0f6d1feca3208f3a16fcb4bda768070999371612

See more details on using hashes here.

File details

Details for the file contextmemory-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: contextmemory-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 34.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.2

File hashes

Hashes for contextmemory-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 5834e0ad7ad9d78ec4480021731a8daad541baa7913a8d51f1adfe08bfefab17
MD5 5cda7ca4512078d10046b39b87fad53e
BLAKE2b-256 38305a9147084e29f8cafe04cb533de039ee2e983336261118a4425d7764c720

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