Skip to main content

MemoryLayer Python SDK

Official Python SDK for MemoryLayer - The intelligent memory layer for AI applications.

PyPI version License: MIT Python 3.8+

Features

  • 🧠 Memory Management: Store, retrieve, and manage AI memories
  • 🔍 Hybrid Search: Vector + keyword + graph-based retrieval
  • 🕸️ Memory Graph: Visualize and traverse memory relationships
  • 🎯 Smart Retrieval: LLM reranking and query rewriting
  • 📊 Observability: Track performance and quality metrics
  • 🔐 Type-Safe: Full type hints with Pydantic models

Installation

pip install memorylayerai

Quick Start

1. Get Your API Key

Sign up at memorylayer.com and create an API key from your project settings.

2. Initialize the Client

from memorylayer import MemoryLayer

client = MemoryLayer(
    api_key="ml_key_...",
    # Optional: specify custom base URL
    # base_url="https://api.memorylayer.com"
)

3. Create Memories

# Create a single memory
memory = client.memories.create(
    project_id="your-project-id",
    content="The user prefers dark mode in their applications",
    type="preference",
    tags={
        "category": "ui",
        "importance": "high"
    }
)

print(f"Memory created: {memory.id}")

4. Search Memories

# Hybrid search (vector + keyword + graph)
results = client.search.hybrid(
    project_id="your-project-id",
    query="What are the user UI preferences?",
    limit=10,
    # Optional: enable advanced features
    use_reranking=True,      # LLM-based reranking
    use_query_rewriting=True, # Query expansion
    use_graph_traversal=True  # Follow memory relationships
)

for result in results:
    print(f"Score: {result.score}")
    print(f"Content: {result.content}")
    print(f"Type: {result.type}")

Core Features

Memory Management

Create Memory

memory = client.memories.create(
    project_id="project-id",
    content="User completed onboarding on 2024-01-15",
    type="fact",
    tags={
        "event": "onboarding",
        "date": "2024-01-15"
    },
    metadata={
        "source": "mobile-app",
        "version": "2.1.0"
    }
)

List Memories

memories = client.memories.list(
    project_id="project-id",
    types=["fact", "preference"],
    status=["active"],
    page=1,
    page_size=50
)

print(f"Total: {memories.total}")
for memory in memories.items:
    print(memory.content)

Get Memory

memory = client.memories.get("memory-id")
print(memory.content)

Update Memory

updated = client.memories.update(
    "memory-id",
    content="Updated content",
    tags={"updated": "true"}
)

Delete Memory

client.memories.delete("memory-id")

Search & Retrieval

Hybrid Search

Combines vector search, keyword search, and graph traversal:

results = client.search.hybrid(
    project_id="project-id",
    query="What does the user like?",
    limit=10,
    
    # Scoring weights (optional)
    vector_weight=0.5,
    keyword_weight=0.3,
    recency_weight=0.2,
    
    # Advanced features
    use_reranking=True,      # Use LLM to rerank results
    use_query_rewriting=True, # Expand and clarify query
    use_graph_traversal=True, # Follow memory relationships
    graph_depth=2            # How many hops to traverse
)

Vector Search Only

results = client.search.vector(
    project_id="project-id",
    query="user preferences",
    limit=5,
    threshold=0.7  # Minimum similarity score
)

Keyword Search Only

results = client.search.keyword(
    project_id="project-id",
    query="dark mode",
    limit=5
)

Memory Graph

Get Graph Data

graph = client.graph.get(
    project_id="project-id",
    # Optional filters
    memory_types=["fact", "preference"],
    search_query="user preferences",
    date_range={
        "start": "2024-01-01",
        "end": "2024-12-31"
    }
)

print(f"Nodes: {len(graph.nodes)}")
print(f"Edges: {len(graph.edges)}")

# Nodes
for node in graph.nodes:
    print(f"{node.id}: {node.content}")

# Edges (relationships)
for edge in graph.edges:
    print(f"{edge.source} -> {edge.target} ({edge.type})")

Create Edge

edge = client.graph.create_edge(
    project_id="project-id",
    source_memory_id="memory-1",
    target_memory_id="memory-2",
    relationship_type="derives",  # or 'similarity', 'temporal', etc.
    metadata={
        "confidence": 0.95,
        "reason": "User explicitly linked these"
    }
)

Traverse Graph

related = client.graph.traverse(
    project_id="project-id",
    start_memory_ids=["memory-1"],
    depth=2,  # How many hops
    relationship_types=["similarity", "derives"]
)

print(f"Found {len(related)} related memories")

Ingestion

Ingest Document

job = client.ingestion.ingest(
    project_id="project-id",
    content="Long document content...",
    metadata={
        "title": "Product Documentation",
        "source": "docs.example.com"
    },
    # Chunking strategy
    chunking_strategy="semantic",  # or 'fixed-size', 'sentence', 'paragraph'
    chunk_size=512,
    chunk_overlap=50
)

print(f"Job ID: {job.id}")
print(f"Status: {job.status}")

Check Job Status

job = client.ingestion.get_job("job-id")
print(f"Status: {job.status}")
print(f"Progress: {job.progress}%")
print(f"Memories created: {job.memories_created}")

Multi-Provider Support

MemoryLayer supports multiple AI providers for both embeddings and language models. Configure at the organization level or override per-request.

Supported Providers

Provider Language Models Embedding Models
OpenAI gpt-4o, gpt-4o-mini, gpt-4-turbo, o1, o1-mini text-embedding-3-small, text-embedding-3-large
Google gemini-2.5-flash, gemini-2.5-pro, gemini-2.0-flash text-embedding-004
Anthropic claude-3-5-sonnet-20241022, claude-3-opus-20240229, claude-3-haiku-20240307 Uses OpenAI embeddings

Configuration Examples

Using OpenAI (Default)

from memorylayer.types import ModelSettings

results = client.search.hybrid(
    project_id="project-id",
    query="user preferences",
    model_settings=ModelSettings(
        provider="openai",
        language_model="gpt-4o-mini",
        embedding_model="text-embedding-3-small"
    )
)

Using Google Gemini

results = client.search.hybrid(
    project_id="project-id",
    query="user preferences",
    model_settings=ModelSettings(
        provider="google",
        language_model="gemini-2.0-flash",
        embedding_model="text-embedding-004"
    )
)

Using Anthropic Claude

results = client.search.hybrid(
    project_id="project-id",
    query="user preferences",
    model_settings=ModelSettings(
        provider="anthropic",
        language_model="claude-3-5-sonnet-20241022",
        embedding_model="text-embedding-3-small"  # Anthropic uses OpenAI embeddings
    )
)

Ingestion with Custom Provider

job = client.ingestion.ingest(
    project_id="project-id",
    content="Document content...",
    model_settings=ModelSettings(
        provider="anthropic",
        language_model="claude-3-5-sonnet-20241022"
    )
)

Provider Selection Priority

  1. Request-level model_settings (highest priority)
  2. Organization-level settings (configured in console)
  3. Default (OpenAI gpt-4o-mini)

Advanced Features

LLM Reranking

Improve search relevance using LLM-based reranking:

results = client.search.hybrid(
    project_id="project-id",
    query="complex user question",
    limit=20,
    use_reranking=True,
    reranking_model="gpt-4",  # or 'claude-3'
    reranking_top_k=10  # Return top 10 after reranking
)

Query Rewriting

Expand and clarify queries for better results:

results = client.search.hybrid(
    project_id="project-id",
    query="ML preferences",  # Will expand to "machine learning preferences"
    use_query_rewriting=True,
    query_rewriting_strategy="expansion"  # or 'clarification', 'multi-query'
)

Graph Traversal

Follow memory relationships for contextual retrieval:

results = client.search.hybrid(
    project_id="project-id",
    query="user settings",
    use_graph_traversal=True,
    graph_depth=2,  # Follow relationships 2 hops deep
    graph_relationship_types=["similarity", "derives"]
)

Type Safety

The SDK uses Pydantic for full type safety:

from memorylayer import (
    MemoryLayer,
    Memory,
    SearchResult,
    GraphData,
    IngestionJob
)

# All methods return typed objects
client = MemoryLayer(api_key="ml_key_...")

# Type hints and validation
memory: Memory = client.memories.create(
    project_id="project-id",
    content="typed content",
    type="fact"  # Validated against allowed types
)

Async Support

The SDK supports async/await for better performance:

import asyncio
from memorylayer import AsyncMemoryLayer

async def main():
    client = AsyncMemoryLayer(api_key="ml_key_...")
    
    # All methods are async
    memory = await client.memories.create(
        project_id="project-id",
        content="async memory"
    )
    
    results = await client.search.hybrid(
        project_id="project-id",
        query="async search"
    )
    
    print(f"Found {len(results)} results")

asyncio.run(main())

Error Handling

from memorylayer import MemoryLayerError

try:
    memory = client.memories.create(
        project_id="project-id",
        content="test"
    )
except MemoryLayerError as e:
    print(f"API Error: {e.message}")
    print(f"Status: {e.status_code}")
    print(f"Request ID: {e.request_id}")
except Exception as e:
    print(f"Unexpected error: {e}")

Configuration

Custom Base URL

client = MemoryLayer(
    api_key="ml_key_...",
    base_url="https://your-custom-domain.com"
)

Timeout

client = MemoryLayer(
    api_key="ml_key_...",
    timeout=30.0  # 30 seconds
)

Retry Configuration

client = MemoryLayer(
    api_key="ml_key_...",
    max_retries=3,
    retry_delay=1.0  # 1 second
)

Examples

Chatbot with Memory

from memorylayer import MemoryLayer
import os

client = MemoryLayer(api_key=os.getenv("MEMORYLAYER_API_KEY"))
project_id = "your-project-id"

def chat_with_memory(user_message: str, user_id: str) -> str:
    # 1. Search for relevant memories
    memories = client.search.hybrid(
        project_id=project_id,
        query=user_message,
        limit=5,
        use_reranking=True,
        use_graph_traversal=True
    )
    
    # 2. Build context from memories
    context = "\n\n".join([m.content for m in memories])
    
    # 3. Send to LLM with context
    response = call_your_llm(
        system=f"You are a helpful assistant. Use this context about the user:\n\n{context}",
        user=user_message
    )
    
    # 4. Store new memory from conversation
    client.memories.create(
        project_id=project_id,
        content=f'User said: "{user_message}". Assistant responded: "{response}"',
        type="fact",
        tags={"user_id": user_id, "timestamp": datetime.now().isoformat()}
    )
    
    return response

Document Q&A

import time

def ingest_and_query(document_content: str, question: str) -> str:
    # 1. Ingest document
    job = client.ingestion.ingest(
        project_id="your-project-id",
        content=document_content,
        chunking_strategy="semantic",
        chunk_size=512
    )
    
    # 2. Wait for ingestion to complete
    while True:
        status = client.ingestion.get_job(job.id)
        if status.status != "processing":
            break
        time.sleep(1)
    
    # 3. Query the document
    results = client.search.hybrid(
        project_id="your-project-id",
        query=question,
        limit=3,
        use_reranking=True
    )
    
    return "\n\n".join([r.content for r in results])

LangChain Integration

from memorylayer import MemoryLayer
from langchain.memory import BaseMemory
from typing import Any, Dict, List

class MemoryLayerMemory(BaseMemory):
    """LangChain memory backed by MemoryLayer"""
    
    def __init__(self, api_key: str, project_id: str):
        self.client = MemoryLayer(api_key=api_key)
        self.project_id = project_id
    
    @property
    def memory_variables(self) -> List[str]:
        return ["history"]
    
    def load_memory_variables(self, inputs: Dict[str, Any]) -> Dict[str, Any]:
        # Search for relevant memories
        results = self.client.search.hybrid(
            project_id=self.project_id,
            query=inputs.get("input", ""),
            limit=5,
            use_reranking=True
        )
        
        history = "\n".join([r.content for r in results])
        return {"history": history}
    
    def save_context(self, inputs: Dict[str, Any], outputs: Dict[str, str]) -> None:
        # Save conversation to MemoryLayer
        self.client.memories.create(
            project_id=self.project_id,
            content=f"User: {inputs['input']}\nAssistant: {outputs['output']}",
            type="fact"
        )
    
    def clear(self) -> None:
        pass  # MemoryLayer handles memory lifecycle

# Usage with LangChain
memory = MemoryLayerMemory(
    api_key="ml_key_...",
    project_id="your-project-id"
)

API Reference

Full API documentation available at docs.memorylayer.com

Support

License

MIT License - see LICENSE file for details.

Changelog

v0.2.0 (2024-01-20)

  • ✨ Added Memory Graph API support
  • ✨ Added Hybrid Search with LLM reranking
  • ✨ Added Query Rewriting capabilities
  • ✨ Added Graph Traversal for contextual retrieval
  • ✨ Added async/await support
  • 🐛 Fixed type hints for better IDE support
  • 📚 Comprehensive documentation and examples

v0.1.1 (2024-01-10)

  • 🐛 Bug fixes and stability improvements

v0.1.0 (2024-01-01)

  • 🎉 Initial release
  • ✨ Basic memory CRUD operations
  • ✨ Vector search
  • ✨ Ingestion API

Metadata

Release files for memorylayerai 0.6.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for memorylayerai 0.6.1
File Size Uploaded
memorylayerai-0.6.1.tar.gz 45.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for memorylayerai 0.6.1
File Interpreter ABI Platform
memorylayerai-0.6.1-py3-none-any.whl Python 3 none any Details

Total release size: 67.2 kB

Release files / memorylayerai-0.6.1.tar.gz

Download URL memorylayerai-0.6.1.tar.gz
Size 45.9 kB
Tags Source
SHA-256 checksum
How to use checksums
f4829a77728f369d92b82755799e142b8bca33a75839e12d6aec5aaca577ba54
BLAKE2b-256 checksum
How to use checksums
b5137408425a671b993e027159f94e2de3bd2f0c6da9eed11c40665075a9ebbc
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.11.5

Release files / memorylayerai-0.6.1-py3-none-any.whl

Download URL memorylayerai-0.6.1-py3-none-any.whl
Size 21.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
bb5698e36689aecc75b7b2b8fba7983d6986e6599ad7b009e2ff2acbada2780e
BLAKE2b-256 checksum
How to use checksums
f09bd288bcab43e11abff22e0df7237cfc139dd630039f1c4294963b1a02d6e9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.11.5

Release history Release notifications | RSS feed

This release

0.6.1 This release

2 release files

0.5.0

2 release files

0.4.0

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.2.0

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page