Chapter 04
mem0 tutorial
🎯 Introduction
AI agents suffer from a fundamental limitation: memory amnesia. They forget everything after each conversation, can't learn from past interactions, and lose valuable context that could make them truly intelligent assistants.
While basic memory solutions store static information, Mem0 introduces a revolutionary approach: self-improving memory that automatically extracts insights, resolves conflicts, and evolves with each interaction. Instead of just storing conversations, Mem0 builds an intelligent knowledge system that learns user preferences and provides contextual understanding.
🛠️ What We'll Build
We'll create an intelligent Personal AI Research Assistant that demonstrates Mem0's full capabilities:
It will:
- Keep track of your preferences for depth, style, and formatting
- Store research notes, summaries, and insights in vector memory for semantic recall
- Capture key ideas from your notes and link related concepts inside a graph database
- Recognize when new questions relate to earlier discussions and surface the right context
- Use both similarity search and structured relationships to generate more informed answers over time
Instead of restarting from zero every session, the assistant continually builds on what it already knows - helping you form a growing, interconnected understanding of the topics you research.
🏗️ Memory Architecture Overview
Mem0 is a memory layer for AI agents that automatically extracts important information from conversations, stores it in vector and graph databases, and retrieves it later to provide long-term context and continuity.
Below is the high-level flow illustrating how Mem0 processes and stores memory.

🎢 Learning Journey
Phase 1: Vector Memory Foundation
- Basic Assistant: Build a working research assistant with vector memory
- Memory Operations: See knowledge extraction and conflict resolution in action
- Semantic Search: Experience intelligent retrieval beyond keywords
- Self-Improvement: Watch memory evolve with each interaction
Phase 2: Graph Enhancement
- Graph Capabilities: Add entity relationship mapping
- Research Networks: Track paper citations, author connections
- Knowledge Graphs: Visualize research domain relationships
⚙️ Prerequisites and Environment Setup
For this tutorial, you'll need:
- OpenAI API Key - used for LLM processing (GPT-4) and embeddings
- Qdrant Cloud Account or any other vector store supported by Mem0 for vector memory.
- Neo4j AuraDB or any other graph database supported by Mem0 for Graph Memory
Installation
Let's start by installing all required dependencies:
!pip install -q mem0ai openai python-dotenv neo4jImport Required Libraries
# Core libraries
import os
import getpass
# Mem0 and OpenAI
from mem0 import Memory
from openai import OpenAIRequired API Keys
Let's configure your API keys:
def setup_api_keys():
# OpenAI API Key
if "OPENAI_API_KEY" not in os.environ:
os.environ["OPENAI_API_KEY"] = getpass.getpass("Enter your OpenAI API key: ")
# Qdrant Cloud (Required for Phase 1: Vector Memory)
if "QDRANT_URL" not in os.environ:
os.environ["QDRANT_URL"] = input("\nEnter your Qdrant Cloud URL: ")
if "QDRANT_API_KEY" not in os.environ:
os.environ["QDRANT_API_KEY"] = getpass.getpass("Enter your Qdrant API key: ")
return True
# Run the setup
use_qdrant_cloud = setup_api_keys()Memory Configuration
Phase 1: Vector Memory
Now let's configure Mem0's memory system. We're starting with vector-based memory - the foundation that makes everything else possible.
Understanding the Configuration
Each component serves a specific purpose in the memory pipeline:
- 🤖 LLM Provider: Extracts insights and resolves conflicts
- 📊 Embedder: Converts text into semantic vectors
- 🗄️ Vector Store: Stores embeddings for similarity search
if use_qdrant_cloud:
# Enhanced configuration with Qdrant Cloud
config = {
"llm": {
"provider": "openai",
"config": {
"model": "gpt-4o-mini",
"temperature": 0.1,
"max_tokens": 2000,
}
},
"embedder": {
"provider": "openai",
"config": {
"model": "text-embedding-3-large",
"embedding_dims": 3072,
}
},
"vector_store": {
"provider": "qdrant",
"config": {
"url": os.environ["QDRANT_URL"],
"api_key": os.environ["QDRANT_API_KEY"],
"collection_name": "research_assistant_vectors",
"embedding_model_dims": 3072, # Must match embedding model
}
},
"version": "v1.1", # Latest version with enhanced features
}
print("Vector Memory Configuration Created!")Initialize Memory System
Now let's create our memory instance - the brain of our research assistant:
try:
memory = Memory.from_config(config)
print("Memory system initialized successfully!")
except Exception as e:
print(f"Error initializing memory: {e}")Building the Research Assistant
Now we'll build our Personal Research Assistant using Mem0's vector memory capabilities.
Core Mem0 Operations
Before we build the assistant, let's understand Mem0's main operations:
memory.add() - Stores new information
- Automatically extracts key facts from conversations
- Handles deduplication and conflicts
- Stores memories with user-specific isolation

memory.search() - Retrieves relevant memories
- Finds semantically similar content (not just keyword matching)
- Returns ranked results by relevance
- Supports filtering by user_id

Other operations (not used in this tutorial):
memory.update()- Modify existing memoriesmemory.delete()- Remove specific memories
class PersonalResearchAssistant:
def __init__(self, memory_instance):
self.client = OpenAI()
self.memory = memory_instance # Use the configured memory instance
print(f"Research Assistant initialized with Mem0 memory!")
def ask(self, question, user_id):
# Search for relevant memories
previous_memories = self.search_memories(question, user_id=user_id)
# Build the prompt with memory context
system_message = "You are a personal AI Research Assistant. Help users with research questions, remember their interests, and provide contextual recommendations."
if previous_memories:
memory_context = ", ".join(previous_memories)
prompt = f"{system_message}\n\nUser input: {question}\nPrevious memories: {memory_context}"
else:
prompt = f"{system_message}\n\nUser input: {question}"
# Generate response
try:
response = self.client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": prompt},
],
temperature=0.1,
max_tokens=2000
)
answer = response.choices[0].message.content
# Store the question in memory
self.memory.add(question, user_id=user_id, metadata={"category": "research"})
return answer
except Exception as e:
return f"Encountered an error: {e}"
def get_memories(self, user_id):
try:
memories = self.memory.get_all(user_id=user_id)
if isinstance(memories, dict) and 'results' in memories:
return [m['memory'] for m in memories['results']]
elif isinstance(memories, list):
return [m['memory'] for m in memories]
return []
except Exception as e:
print(f"Error retrieving memories: {e}")
return []
def search_memories(self, query, user_id):
try:
memories = self.memory.search(query, user_id=user_id)
if isinstance(memories, dict) and 'results' in memories:
return [m['memory'] for m in memories['results']]
elif isinstance(memories, list):
return [m['memory'] for m in memories]
return []
except Exception as e:
print(f"Error searching memories: {e}")
return []
# Initialize our research assistant
assistant = PersonalResearchAssistant(memory)
print("\n Research Assistant ready to learn and help!")Test 1: First Interaction - Knowledge Extraction
Let's start with a basic research interest:
response1 = assistant.ask(
"I'm interested in transformer architectures for natural language processing. "
"Can you help me find recent papers on this topic?",
user_id="researcher"
)
print(f"Assistant: {response1}")Test 2: Building Context - Watch Memory Connect Ideas
response2 = assistant.ask(
"I prefer papers that include practical implementation details and code examples. "
"Theoretical papers without code are less useful for my work.",
user_id="researcher"
)
print(f"Assistant: {response2}")Test 3: Semantic Search - Intelligence Beyond Keywords
response3 = assistant.ask(
"What about BERT and GPT models? Are they related to my research interests?",
user_id="researcher"
)
print(f"Assistant: {response3}")Test 4: Conflict Resolution - Intelligent Memory Management
response4 = assistant.ask(
"Actually, I also need to understand the theoretical foundations of attention mechanisms. "
"Can you recommend some foundational theory papers?",
user_id="researcher"
)
print(f"Assistant: {response4}")📊 Memory Analysis - See What Was Learned
Let's examine what our assistant learned from these interactions:
def analyze_extracted_memories():
print("📈 MEMORY ANALYSIS - What Did the Assistant Learn?")
print("=" * 60)
# Get all memories
all_memories = assistant.get_memories(user_id="researcher")
if all_memories:
print(f"\n🧠 Total memories extracted: {len(all_memories)}")
print(f"\n📚 Key insights Mem0 learned about you:")
for i, memory in enumerate(all_memories, 1):
print(f"\n{i}. {memory}")
# Test semantic search
print(f"\n🔍 Testing Semantic Search Capabilities:")
test_queries = [
"neural networks", # Should connect to transformers
"code implementations", # Should find practical preferences
"attention mechanisms", # Should connect to transformer interest
"deep learning papers" # Should find research interests
]
for query in test_queries:
related_memories = assistant.search_memories(query, user_id="researcher")
print(f"\n 🔎 Query: '{query}'")
print(f" Found {len(related_memories)} related memories")
if related_memories:
print(f" Top match: {related_memories[0][:100]}...")
else:
print("\n⚠️ No memories found. Try running the interaction tests first.")
return all_memories
# Run the analysis
memories = analyze_extracted_memories()Interactive Demo - Try It Yourself
Now it's your turn! Try asking questions and watch the memory system learn about your research interests:
def interactive_demo():
while True:
try:
question = input("\nYou: ")
if question.lower() in ['quit', 'exit', 'q']:
print("\n Thanks for trying the Research Assistant!")
break
elif question.lower() == 'memories':
memories = assistant.get_memories(user_id="researcher")
if memories:
print(f"\n Here's what I've learned about your research interests:")
for i, memory in enumerate(memories, 1):
print(f" {i}. {memory}")
else:
print("\n No memories yet. Start asking about your research interests!")
elif question.strip():
response = assistant.ask(question)
print(f"\n Assistant: {response}")
except KeyboardInterrupt:
print("\n\n Demo ended. Thanks for trying the Research Assistant!")
break
except Exception as e:
print(f"\n Error: {e}")
# Run the interactive demo
interactive_demo()🚀 Phase 2: Enhancing with Graph Memory Capabilities
Now that you've mastered vector-based memory and seen its power, let's enhance our system with graph capabilities. This addition will enable explicit relationship mapping between entities, concepts, and research domains.
Why Add Graph Memory?
Vector memory excels at:
- Finding semantically similar content
- "Show me papers like this one"
- Understanding conceptual similarity
Graph memory adds:
- Explicit entity relationships
- "Who collaborated with whom?"
- "How did Paper A influence Paper B?"
- Research lineage and citation networks
Graph Storage Setup
To add graph capabilities, we need a graph database. Neo4j is the most popular choice, you can use other graph storage as well that are supported by Mem0.
def setup_graph_capabilities():
print("\n🔗 Enter your Neo4j connection details:")
neo4j_uri = input("Neo4j URI (e.g., neo4j+s://xxx.databases.neo4j.io): ")
neo4j_username = input("Username (usually 'neo4j'): ")
neo4j_password = getpass.getpass("Password: ")
print("\n Neo4j configuration complete!")
return True, {
"url": neo4j_uri,
"username": neo4j_username,
"password": neo4j_password
}
# Setup graph capabilities for Phase 2
has_graph, graph_config = setup_graph_capabilities()Enhanced Configuration with Graph Storage
Now let's create the hybrid configuration with both vector and graph storage:
# Enhanced configuration with both vector and graph storage
enhanced_config = {
"llm": {
"provider": "openai",
"config": {
"model": "gpt-4o-mini",
"temperature": 0.1,
"max_tokens": 2000,
}
},
"embedder": {
"provider": "openai",
"config": {
"model": "text-embedding-3-large",
"embedding_dims": 3072,
}
},
"vector_store": {
"provider": "qdrant",
"config": {
"url": os.environ["QDRANT_URL"],
"api_key": os.environ["QDRANT_API_KEY"],
"collection_name": "research_assistant_hybrid",
"embedding_model_dims": 3072,
}
},
"graph_store": {
"provider": "neo4j",
"config": graph_config
},
"version": "v1.1",
}
try:
enhanced_memory = Memory.from_config(enhanced_config)
print("\n Hybrid Memory System Initialized Successfully!")
enhanced_assistant = PersonalResearchAssistant(enhanced_memory)
print("\n Enhanced Research Assistant ready with hybrid memory!")
except Exception as e:
print(f" Error initializing hybrid memory: {e}")
# Fallback to vector-only
print("\n Falling back to vector-only assistant...")
enhanced_assistant = assistant📝 Graph-Enhanced Research Examples
If you have graph storage enabled, let's see it in action with entity relationships:
Example 1: Research lineage mapping
graph_response1 = enhanced_assistant.ask(
"I'm studying the lineage of transformer papers. The original 'Attention Is All You Need' "
"by Vaswani et al. led to BERT by Devlin et al., and then to many other models. "
"Can you help me map these research connections and suggest related work?",
user_id="graph_user"
)
print(f"Hybrid Assistant: {graph_response1}")Example 2: Collaboration network analysis
graph_response2 = enhanced_assistant.ask(
"What other researchers have worked on transformer architectures? "
"I want to understand the collaboration network and research groups in this field.",
user_id="graph_user"
)
print(f"Hybrid Assistant: {graph_response2}")🎓 Recap
You just built a real memory system from the ground up. Here's what you accomplished and where to go from here.
What you built
- Hybrid memory architecture with vector search (Qdrant) + graph relationships (Neo4j)
- Automatic memory extraction that pulls key facts from conversations
- Conflict resolution that handles contradictions and keeps memories current
- Semantic search that finds relevant info by meaning, not just keywords
Why Mem0
Memory is hard to build right. You'd need months to handle fact extraction, conflict resolution, and semantic search properly. Mem0 gives you battle-tested memory that just works.
What you get:
- Smart memory extraction that pulls key facts from conversations automatically
- Conflict handling when users change their minds or contradict themselves
- Semantic search that finds relevant stuff by meaning, not just keywords
- Proven performance: 26% better accuracy, 91% faster responses, 90% fewer tokens (Mem0 research paper)
You can focus on building your app instead of reinventing memory infrastructure.
Your deployment options
Self-hosted (what we built)
- Full control over your stack
- Custom configurations for vector/graph stores
- Great for learning, prototyping, and specific requirements
Mem0 Platform
- Managed service starting at free tier (10K memories)
- Enterprise features like analytics and graph memory
- Simple API, zero infrastructure headaches
- Ship fast and scale without ops overhead
What's next
You now have the foundation for AI that actually remembers and learns. Check out:
- Mem0 Platform for production deployment
- Documentation for advanced features and integrations
- Discord Community for questions and discussions
You're ready to build AI applications that get smarter with every interaction.
