[docs] Essential cookbook added and overall revamp to the structure of cookbooks (#3668)
This commit is contained in:
@@ -0,0 +1,125 @@
|
||||
---
|
||||
title: AI Tutor with Mem0
|
||||
description: "Keep student progress and preferences persistent across tutoring sessions."
|
||||
---
|
||||
|
||||
|
||||
You can create a personalized AI Tutor using Mem0. This guide will walk you through the necessary steps and provide the complete code to get you started.
|
||||
|
||||
## Overview
|
||||
|
||||
The Personalized AI Tutor leverages Mem0 to retain information across interactions, enabling a tailored learning experience. By integrating with OpenAI's GPT-4 model, the tutor can provide detailed and context-aware responses to user queries.
|
||||
|
||||
## Setup
|
||||
|
||||
Before you begin, ensure you have the required dependencies installed. You can install the necessary packages using pip:
|
||||
|
||||
```bash
|
||||
pip install openai mem0ai
|
||||
```
|
||||
|
||||
## Full Code Example
|
||||
|
||||
Below is the complete code to create and interact with a Personalized AI Tutor using Mem0:
|
||||
|
||||
```python
|
||||
import os
|
||||
from openai import OpenAI
|
||||
from mem0 import Memory
|
||||
|
||||
# Set the OpenAI API key
|
||||
os.environ['OPENAI_API_KEY'] = 'sk-xxx'
|
||||
|
||||
# Initialize the OpenAI client
|
||||
client = OpenAI()
|
||||
|
||||
class PersonalAITutor:
|
||||
def __init__(self):
|
||||
"""
|
||||
Initialize the PersonalAITutor with memory configuration and OpenAI client.
|
||||
"""
|
||||
config = {
|
||||
"vector_store": {
|
||||
"provider": "qdrant",
|
||||
"config": {
|
||||
"host": "localhost",
|
||||
"port": 6333,
|
||||
}
|
||||
},
|
||||
}
|
||||
self.memory = Memory.from_config(config)
|
||||
self.client = client
|
||||
self.app_id = "app-1"
|
||||
|
||||
def ask(self, question, user_id=None):
|
||||
"""
|
||||
Ask a question to the AI and store the relevant facts in memory
|
||||
|
||||
:param question: The question to ask the AI.
|
||||
:param user_id: Optional user ID to associate with the memory.
|
||||
"""
|
||||
# Start a streaming response request to the AI
|
||||
response = self.client.responses.create(
|
||||
model="gpt-4.1-nano-2025-04-14",
|
||||
instructions="You are a personal AI Tutor.",
|
||||
input=question,
|
||||
stream=True
|
||||
)
|
||||
|
||||
# Store the question in memory
|
||||
self.memory.add(question, user_id=user_id, metadata={"app_id": self.app_id})
|
||||
|
||||
# Print the response from the AI in real-time
|
||||
for event in response:
|
||||
if event.type == "response.output_text.delta":
|
||||
print(event.delta, end="")
|
||||
|
||||
def get_memories(self, user_id=None):
|
||||
"""
|
||||
Retrieve all memories associated with the given user ID.
|
||||
|
||||
:param user_id: Optional user ID to filter memories.
|
||||
:return: List of memories.
|
||||
"""
|
||||
return self.memory.get_all(user_id=user_id)
|
||||
|
||||
# Instantiate the PersonalAITutor
|
||||
ai_tutor = PersonalAITutor()
|
||||
|
||||
# Define a user ID
|
||||
user_id = "john_doe"
|
||||
|
||||
# Ask a question
|
||||
ai_tutor.ask("I am learning introduction to CS. What is queue? Briefly explain.", user_id=user_id)
|
||||
```
|
||||
|
||||
### Fetching Memories
|
||||
|
||||
You can fetch all the memories at any point in time using the following code:
|
||||
|
||||
```python
|
||||
memories = ai_tutor.get_memories(user_id=user_id)
|
||||
for m in memories['results']:
|
||||
print(m['memory'])
|
||||
```
|
||||
|
||||
## Key Points
|
||||
|
||||
- **Initialization**: The PersonalAITutor class is initialized with the necessary memory configuration and OpenAI client setup
|
||||
- **Asking Questions**: The ask method sends a question to the AI and stores the relevant information in memory
|
||||
- **Retrieving Memories**: The get_memories method fetches all stored memories associated with a user
|
||||
|
||||
## Conclusion
|
||||
|
||||
As the conversation progresses, Mem0's memory automatically updates based on the interactions, providing a continuously improving personalized learning experience. This setup ensures that the AI Tutor can offer contextually relevant and accurate responses, enhancing the overall educational process.
|
||||
|
||||
---
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Build a Mem0 Companion" icon="users" href="/cookbooks/essentials/building-ai-companion">
|
||||
Learn the foundations of memory-powered companions with production-ready patterns.
|
||||
</Card>
|
||||
<Card title="Travel Assistant with Mem0" icon="plane" href="/cookbooks/companions/travel-assistant">
|
||||
Build a travel companion that remembers preferences and past conversations.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -0,0 +1,83 @@
|
||||
---
|
||||
title: Local Companion with Mem0 and Ollama
|
||||
description: "Run Mem0 end-to-end on your machine using Ollama-powered LLMs and embedders."
|
||||
---
|
||||
|
||||
|
||||
Mem0 can be utilized entirely locally by leveraging Ollama for both the embedding model and the language model (LLM). This guide will walk you through the necessary steps and provide the complete code to get you started.
|
||||
|
||||
## Overview
|
||||
|
||||
By using Ollama, you can run Mem0 locally, which allows for greater control over your data and models. This setup uses Ollama for both the embedding model and the language model, providing a fully local solution.
|
||||
|
||||
## Setup
|
||||
|
||||
Before you begin, ensure you have Mem0 and Ollama installed and properly configured on your local machine.
|
||||
|
||||
## Full Code Example
|
||||
|
||||
Below is the complete code to set up and use Mem0 locally with Ollama:
|
||||
|
||||
```python
|
||||
from mem0 import Memory
|
||||
|
||||
config = {
|
||||
"vector_store": {
|
||||
"provider": "qdrant",
|
||||
"config": {
|
||||
"collection_name": "test",
|
||||
"host": "localhost",
|
||||
"port": 6333,
|
||||
"embedding_model_dims": 768, # Change this according to your local model's dimensions
|
||||
},
|
||||
},
|
||||
"llm": {
|
||||
"provider": "ollama",
|
||||
"config": {
|
||||
"model": "llama3.1:latest",
|
||||
"temperature": 0,
|
||||
"max_tokens": 2000,
|
||||
"ollama_base_url": "http://localhost:11434", # Ensure this URL is correct
|
||||
},
|
||||
},
|
||||
"embedder": {
|
||||
"provider": "ollama",
|
||||
"config": {
|
||||
"model": "nomic-embed-text:latest",
|
||||
# Alternatively, you can use "snowflake-arctic-embed:latest"
|
||||
"ollama_base_url": "http://localhost:11434",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
# Initialize Memory with the configuration
|
||||
m = Memory.from_config(config)
|
||||
|
||||
# Add a memory
|
||||
m.add("I'm visiting Paris", user_id="john")
|
||||
|
||||
# Retrieve memories
|
||||
memories = m.get_all(user_id="john")
|
||||
```
|
||||
|
||||
## Key Points
|
||||
|
||||
- **Configuration**: The setup involves configuring the vector store, language model, and embedding model to use local resources
|
||||
- **Vector Store**: Qdrant is used as the vector store, running on localhost
|
||||
- **Language Model**: Ollama is used as the LLM provider, with the `llama3.1:latest` model
|
||||
- **Embedding Model**: Ollama is also used for embeddings, with the `nomic-embed-text:latest` model
|
||||
|
||||
## Conclusion
|
||||
|
||||
This local setup of Mem0 using Ollama provides a fully self-contained solution for memory management and AI interactions. It allows for greater control over your data and models while still leveraging the powerful capabilities of Mem0.
|
||||
|
||||
---
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Configure Open Source" icon="gear" href="/open-source/configuration">
|
||||
Explore advanced configuration options for vector stores, LLMs, and embedders.
|
||||
</Card>
|
||||
<Card title="Build a Mem0 Companion" icon="users" href="/cookbooks/essentials/building-ai-companion">
|
||||
Learn core companion patterns that work with any LLM provider.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -0,0 +1,139 @@
|
||||
---
|
||||
title: Node.js Companion with Mem0
|
||||
description: "Build a JavaScript fitness coach that remembers user goals run after run."
|
||||
---
|
||||
|
||||
|
||||
You can create a personalized AI Companion using Mem0. This guide will walk you through the necessary steps and provide the complete code to get you started.
|
||||
|
||||
## Overview
|
||||
|
||||
The Personalized AI Companion leverages Mem0 to retain information across interactions, enabling a tailored learning experience. It creates memories for each user interaction and integrates with OpenAI's GPT models to provide detailed and context-aware responses to user queries.
|
||||
|
||||
## Setup
|
||||
|
||||
Before you begin, ensure you have Node.js installed and create a new project. Install the required dependencies using npm:
|
||||
|
||||
```bash
|
||||
npm install openai mem0ai
|
||||
```
|
||||
|
||||
## Full Code Example
|
||||
|
||||
Below is the complete code to create and interact with an AI Companion using Mem0:
|
||||
|
||||
```javascript
|
||||
import { OpenAI } from 'openai';
|
||||
import { Memory } from 'mem0ai/oss';
|
||||
import * as readline from 'readline';
|
||||
|
||||
const openaiClient = new OpenAI();
|
||||
const memory = new Memory();
|
||||
|
||||
async function chatWithMemories(message, userId = "default_user") {
|
||||
const relevantMemories = await memory.search(message, { userId: userId });
|
||||
|
||||
const memoriesStr = relevantMemories.results
|
||||
.map(entry => `- ${entry.memory}`)
|
||||
.join('\n');
|
||||
|
||||
const systemPrompt = `You are a helpful AI. Answer the question based on query and memories.
|
||||
User Memories:
|
||||
${memoriesStr}`;
|
||||
|
||||
const messages = [
|
||||
{ role: "system", content: systemPrompt },
|
||||
{ role: "user", content: message }
|
||||
];
|
||||
|
||||
const response = await openaiClient.chat.completions.create({
|
||||
model: "gpt-4.1-nano-2025-04-14",
|
||||
messages: messages
|
||||
});
|
||||
|
||||
const assistantResponse = response.choices[0].message.content || "";
|
||||
|
||||
messages.push({ role: "assistant", content: assistantResponse });
|
||||
await memory.add(messages, { userId: userId });
|
||||
|
||||
return assistantResponse;
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const rl = readline.createInterface({
|
||||
input: process.stdin,
|
||||
output: process.stdout
|
||||
});
|
||||
|
||||
console.log("Chat with AI (type 'exit' to quit)");
|
||||
|
||||
const askQuestion = () => {
|
||||
return new Promise((resolve) => {
|
||||
rl.question("You: ", (input) => {
|
||||
resolve(input.trim());
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
try {
|
||||
while (true) {
|
||||
const userInput = await askQuestion();
|
||||
|
||||
if (userInput.toLowerCase() === 'exit') {
|
||||
console.log("Goodbye!");
|
||||
rl.close();
|
||||
break;
|
||||
}
|
||||
|
||||
const response = await chatWithMemories(userInput, "sample_user");
|
||||
console.log(`AI: ${response}`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("An error occurred:", error);
|
||||
rl.close();
|
||||
}
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
```
|
||||
|
||||
### Key Components
|
||||
|
||||
1. **Initialization**
|
||||
- The code initializes both OpenAI and Mem0 Memory clients
|
||||
- Uses Node.js's built-in readline module for command-line interaction
|
||||
|
||||
2. **Memory Management (chatWithMemories function)**
|
||||
- Retrieves relevant memories using Mem0's search functionality
|
||||
- Constructs a system prompt that includes past memories
|
||||
- Makes API calls to OpenAI for generating responses
|
||||
- Stores new interactions in memory
|
||||
|
||||
3. **Interactive Chat Interface (main function)**
|
||||
- Creates a command-line interface for user interaction
|
||||
- Handles user input and displays AI responses
|
||||
- Includes graceful exit functionality
|
||||
|
||||
### Environment Setup
|
||||
|
||||
Make sure to set up your environment variables:
|
||||
```bash
|
||||
export OPENAI_API_KEY=your_api_key
|
||||
```
|
||||
|
||||
### Conclusion
|
||||
|
||||
This implementation demonstrates how to create an AI Companion that maintains context across conversations using Mem0's memory capabilities. The system automatically stores and retrieves relevant information, creating a more personalized and context-aware interaction experience.
|
||||
|
||||
As users interact with the system, Mem0's memory system continuously learns and adapts, making future responses more relevant and personalized. This setup is ideal for creating long-term learning AI assistants that can maintain context and provide increasingly personalized responses over time.
|
||||
|
||||
---
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Build AI with Personality" icon="sparkles" href="/cookbooks/essentials/building-ai-with-personality">
|
||||
Separate user and agent memories to keep your companion's personality consistent.
|
||||
</Card>
|
||||
<Card title="Quickstart Demo with Mem0" icon="rocket" href="/cookbooks/companions/quickstart-demo">
|
||||
Run the full showcase app to see memory-powered companions in action.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -0,0 +1,80 @@
|
||||
---
|
||||
title: Quickstart Demo with Mem0
|
||||
description: "Spin up the showcase companion app to see Mem0 memories in action."
|
||||
---
|
||||
|
||||
|
||||
You can create a personalized AI Companion using Mem0. This guide will walk you through the necessary steps and provide the complete setup instructions to get you started.
|
||||
|
||||
<video
|
||||
autoPlay
|
||||
muted
|
||||
loop
|
||||
playsInline
|
||||
className="w-full aspect-video rounded-lg"
|
||||
src="https://github.com/user-attachments/assets/cebc4f8e-bdb9-4837-868d-13c5ab7bb433"
|
||||
></video>
|
||||
|
||||
You can try the [Mem0 Demo](https://mem0-4vmi.vercel.app) live here.
|
||||
|
||||
## Overview
|
||||
|
||||
The Personalized AI Companion leverages Mem0 to retain information across interactions, enabling a tailored learning experience. It creates memories for each user interaction and integrates with OpenAI's GPT models to provide detailed and context-aware responses to user queries.
|
||||
|
||||
## Setup
|
||||
|
||||
Before you begin, follow these steps to set up the demo application:
|
||||
|
||||
1. Clone the Mem0 repository:
|
||||
```bash
|
||||
git clone https://github.com/mem0ai/mem0.git
|
||||
```
|
||||
|
||||
2. Navigate to the demo application folder:
|
||||
```bash
|
||||
cd mem0/examples/mem0-demo
|
||||
```
|
||||
|
||||
3. Install dependencies:
|
||||
```bash
|
||||
pnpm install
|
||||
```
|
||||
|
||||
4. Set up environment variables by creating a `.env` file in the project root with the following content:
|
||||
```bash
|
||||
OPENAI_API_KEY=your_openai_api_key
|
||||
MEM0_API_KEY=your_mem0_api_key
|
||||
```
|
||||
You can obtain your `MEM0_API_KEY` by signing up at [Mem0 API Dashboard](https://app.mem0.ai/dashboard/api-keys).
|
||||
|
||||
5. Start the development server:
|
||||
```bash
|
||||
pnpm run dev
|
||||
```
|
||||
|
||||
## Enhancing the Next.js Application
|
||||
|
||||
Once the demo is running, you can customize and enhance the Next.js application by modifying the components in the `mem0-demo` folder. Consider:
|
||||
- Adding new memory features to improve contextual retention
|
||||
- Customizing the UI to better suit your application needs
|
||||
- Integrating additional APIs or third-party services to extend functionality
|
||||
|
||||
## Full Code
|
||||
|
||||
You can find the complete source code for this demo on GitHub:
|
||||
[Mem0 Demo GitHub](https://github.com/mem0ai/mem0/tree/main/examples/mem0-demo)
|
||||
|
||||
## Conclusion
|
||||
|
||||
This setup demonstrates how to build an AI Companion that maintains memory across interactions using Mem0. The system continuously adapts to user interactions, making future responses more relevant and personalized. Experiment with the application and enhance it further to suit your use case!
|
||||
|
||||
---
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Build a Mem0 Companion" icon="users" href="/cookbooks/essentials/building-ai-companion">
|
||||
Deep dive into production patterns for fitness coaches, tutors, and assistants.
|
||||
</Card>
|
||||
<Card title="Node.js Companion with Mem0" icon="code" href="/cookbooks/companions/nodejs-companion">
|
||||
Implement a command-line companion using the Node.js SDK.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -0,0 +1,214 @@
|
||||
---
|
||||
title: Travel Assistant with Mem0
|
||||
description: "Plan itineraries that remember traveler preferences across trips."
|
||||
---
|
||||
|
||||
|
||||
Create a personalized AI Travel Assistant using Mem0. This guide provides step-by-step instructions and the complete code to get you started.
|
||||
|
||||
## Overview
|
||||
|
||||
The Personalized AI Travel Assistant uses Mem0 to store and retrieve information across interactions, enabling a tailored travel planning experience. It integrates with OpenAI's GPT-4 model to provide detailed and context-aware responses to user queries.
|
||||
|
||||
## Setup
|
||||
|
||||
Install the required dependencies using pip:
|
||||
|
||||
```bash
|
||||
pip install openai mem0ai
|
||||
```
|
||||
|
||||
## Full Code Example
|
||||
|
||||
Here's the complete code to create and interact with a Personalized AI Travel Assistant using Mem0:
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```python After v1.1
|
||||
import os
|
||||
from openai import OpenAI
|
||||
from mem0 import Memory
|
||||
|
||||
# Set the OpenAI API key
|
||||
os.environ['OPENAI_API_KEY'] = "sk-xxx"
|
||||
|
||||
config = {
|
||||
"llm": {
|
||||
"provider": "openai",
|
||||
"config": {
|
||||
"model": "gpt-4.1-nano-2025-04-14",
|
||||
"temperature": 0.1,
|
||||
"max_tokens": 2000,
|
||||
}
|
||||
},
|
||||
"embedder": {
|
||||
"provider": "openai",
|
||||
"config": {
|
||||
"model": "text-embedding-3-large"
|
||||
}
|
||||
},
|
||||
"vector_store": {
|
||||
"provider": "qdrant",
|
||||
"config": {
|
||||
"collection_name": "test",
|
||||
"embedding_model_dims": 3072,
|
||||
}
|
||||
},
|
||||
"version": "v1.1",
|
||||
}
|
||||
|
||||
class PersonalTravelAssistant:
|
||||
def __init__(self):
|
||||
self.client = OpenAI()
|
||||
self.memory = Memory.from_config(config)
|
||||
self.messages = [{"role": "system", "content": "You are a personal AI Assistant."}]
|
||||
|
||||
def ask_question(self, question, user_id):
|
||||
# Fetch previous related memories
|
||||
previous_memories = self.search_memories(question, user_id=user_id)
|
||||
|
||||
# Build the prompt
|
||||
system_message = "You are a personal AI Assistant."
|
||||
|
||||
if previous_memories:
|
||||
prompt = f"{system_message}\n\nUser input: {question}\nPrevious memories: {', '.join(previous_memories)}"
|
||||
else:
|
||||
prompt = f"{system_message}\n\nUser input: {question}"
|
||||
|
||||
# Generate response using Responses API
|
||||
response = self.client.responses.create(
|
||||
model="gpt-4.1-nano-2025-04-14",
|
||||
input=prompt
|
||||
)
|
||||
|
||||
# Extract answer from the response
|
||||
answer = response.output[0].content[0].text
|
||||
|
||||
# Store the question in memory
|
||||
self.memory.add(question, user_id=user_id)
|
||||
return answer
|
||||
|
||||
def get_memories(self, user_id):
|
||||
memories = self.memory.get_all(user_id=user_id)
|
||||
return [m['memory'] for m in memories['results']]
|
||||
|
||||
def search_memories(self, query, user_id):
|
||||
memories = self.memory.search(query, user_id=user_id)
|
||||
return [m['memory'] for m in memories['results']]
|
||||
|
||||
# Usage example
|
||||
user_id = "traveler_123"
|
||||
ai_assistant = PersonalTravelAssistant()
|
||||
|
||||
def main():
|
||||
while True:
|
||||
question = input("Question: ")
|
||||
if question.lower() in ['q', 'exit']:
|
||||
print("Exiting...")
|
||||
break
|
||||
|
||||
answer = ai_assistant.ask_question(question, user_id=user_id)
|
||||
print(f"Answer: {answer}")
|
||||
memories = ai_assistant.get_memories(user_id=user_id)
|
||||
print("Memories:")
|
||||
for memory in memories:
|
||||
print(f"- {memory}")
|
||||
print("-----")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
```
|
||||
|
||||
```python Before v1.1
|
||||
import os
|
||||
from openai import OpenAI
|
||||
from mem0 import Memory
|
||||
|
||||
# Set the OpenAI API key
|
||||
os.environ['OPENAI_API_KEY'] = 'sk-xxx'
|
||||
|
||||
class PersonalTravelAssistant:
|
||||
def __init__(self):
|
||||
self.client = OpenAI()
|
||||
self.memory = Memory()
|
||||
self.messages = [{"role": "system", "content": "You are a personal AI Assistant."}]
|
||||
|
||||
def ask_question(self, question, user_id):
|
||||
# Fetch previous related memories
|
||||
previous_memories = self.search_memories(question, user_id=user_id)
|
||||
prompt = question
|
||||
if previous_memories:
|
||||
prompt = f"User input: {question}\n Previous memories: {previous_memories}"
|
||||
self.messages.append({"role": "user", "content": prompt})
|
||||
|
||||
# Generate response using gpt-4.1-nano
|
||||
response = self.client.chat.completions.create(
|
||||
model="gpt-4.1-nano-2025-04-14"2025-04-14",
|
||||
messages=self.messages
|
||||
)
|
||||
answer = response.choices[0].message.content
|
||||
self.messages.append({"role": "assistant", "content": answer})
|
||||
|
||||
# Store the question in memory
|
||||
self.memory.add(question, user_id=user_id)
|
||||
return answer
|
||||
|
||||
def get_memories(self, user_id):
|
||||
memories = self.memory.get_all(user_id=user_id)
|
||||
return [m['memory'] for m in memories.get('results', [])]
|
||||
|
||||
def search_memories(self, query, user_id):
|
||||
memories = self.memory.search(query, user_id=user_id)
|
||||
return [m['memory'] for m in memories.get('results', [])]
|
||||
|
||||
# Usage example
|
||||
user_id = "traveler_123"
|
||||
ai_assistant = PersonalTravelAssistant()
|
||||
|
||||
def main():
|
||||
while True:
|
||||
question = input("Question: ")
|
||||
if question.lower() in ['q', 'exit']:
|
||||
print("Exiting...")
|
||||
break
|
||||
|
||||
answer = ai_assistant.ask_question(question, user_id=user_id)
|
||||
print(f"Answer: {answer}")
|
||||
memories = ai_assistant.get_memories(user_id=user_id)
|
||||
print("Memories:")
|
||||
for memory in memories:
|
||||
print(f"- {memory}")
|
||||
print("-----")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
|
||||
## Key Components
|
||||
|
||||
- **Initialization**: The `PersonalTravelAssistant` class is initialized with the OpenAI client and Mem0 memory setup.
|
||||
- **Asking Questions**: The `ask_question` method sends a question to the AI, incorporates previous memories, and stores new information.
|
||||
- **Memory Management**: The `get_memories` and search_memories methods handle retrieval and searching of stored memories.
|
||||
|
||||
## Usage
|
||||
|
||||
1. Set your OpenAI API key in the environment variable.
|
||||
2. Instantiate the `PersonalTravelAssistant`.
|
||||
3. Use the `main()` function to interact with the assistant in a loop.
|
||||
|
||||
## Conclusion
|
||||
|
||||
This Personalized AI Travel Assistant leverages Mem0's memory capabilities to provide context-aware responses. As you interact with it, the assistant learns and improves, offering increasingly personalized travel advice and information.
|
||||
|
||||
---
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Tag and Organize Memories" icon="tag" href="/cookbooks/essentials/tagging-and-organizing-memories">
|
||||
Use categories to organize travel preferences, destinations, and user context.
|
||||
</Card>
|
||||
<Card title="AI Tutor with Mem0" icon="graduation-cap" href="/cookbooks/companions/ai-tutor">
|
||||
Build an educational companion that remembers learning progress and preferences.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -0,0 +1,548 @@
|
||||
---
|
||||
title: Voice Companion with Mem0 and OpenAI
|
||||
description: "Pair the OpenAI Agents SDK with Mem0 to build a voice assistant that remembers."
|
||||
---
|
||||
|
||||
|
||||
This guide demonstrates how to combine OpenAI's Agents SDK for voice applications with Mem0's memory capabilities to create a voice assistant that remembers user preferences and past interactions.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before you begin, make sure you have:
|
||||
|
||||
1. Installed OpenAI Agents SDK with voice dependencies:
|
||||
```bash
|
||||
pip install 'openai-agents[voice]'
|
||||
```
|
||||
|
||||
2. Installed Mem0 SDK:
|
||||
```bash
|
||||
pip install mem0ai
|
||||
```
|
||||
|
||||
3. Installed other required dependencies:
|
||||
```bash
|
||||
pip install numpy sounddevice pydantic
|
||||
```
|
||||
|
||||
4. Set up your API keys:
|
||||
- OpenAI API key for the Agents SDK
|
||||
- Mem0 API key from the Mem0 Platform
|
||||
|
||||
## Code Breakdown
|
||||
|
||||
Let's break down the key components of this implementation:
|
||||
|
||||
### 1. Setting Up Dependencies and Environment
|
||||
|
||||
```python
|
||||
# OpenAI Agents SDK imports
|
||||
from agents import (
|
||||
Agent,
|
||||
function_tool
|
||||
)
|
||||
from agents.voice import (
|
||||
AudioInput,
|
||||
SingleAgentVoiceWorkflow,
|
||||
VoicePipeline
|
||||
)
|
||||
from agents.extensions.handoff_prompt import prompt_with_handoff_instructions
|
||||
|
||||
# Mem0 imports
|
||||
from mem0 import AsyncMemoryClient
|
||||
|
||||
# Set up API keys (replace with your actual keys)
|
||||
os.environ["OPENAI_API_KEY"] = "your-openai-api-key"
|
||||
os.environ["MEM0_API_KEY"] = "your-mem0-api-key"
|
||||
|
||||
# Define a global user ID for simplicity
|
||||
USER_ID = "voice_user"
|
||||
|
||||
# Initialize Mem0 client
|
||||
mem0_client = AsyncMemoryClient()
|
||||
```
|
||||
|
||||
This section handles:
|
||||
- Importing required modules from OpenAI Agents SDK and Mem0
|
||||
- Setting up environment variables for API keys
|
||||
- Defining a simple user identification system (using a global variable)
|
||||
- Initializing the Mem0 client that will handle memory operations
|
||||
|
||||
### 2. Memory Tools with Function Decorators
|
||||
|
||||
The `@function_tool` decorator transforms Python functions into callable tools for the OpenAI agent. Here are the key memory tools:
|
||||
|
||||
#### Storing User Memories
|
||||
|
||||
```python
|
||||
import logging
|
||||
|
||||
# Set up logging at the top of your file
|
||||
logging.basicConfig(
|
||||
level=logging.DEBUG,
|
||||
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
||||
force=True
|
||||
)
|
||||
logger = logging.getLogger("memory_voice_agent")
|
||||
|
||||
# Then use logger in your function tools
|
||||
@function_tool
|
||||
async def save_memories(
|
||||
memory: str
|
||||
) -> str:
|
||||
"""Store a user memory in memory."""
|
||||
# This will be visible in your console
|
||||
logger.debug(f"Saving memory: {memory} for user {USER_ID}")
|
||||
|
||||
# Store the preference in Mem0
|
||||
memory_content = f"User memory - {memory}"
|
||||
await mem0_client.add(
|
||||
memory_content,
|
||||
user_id=USER_ID,
|
||||
)
|
||||
|
||||
return f"I've saved your memory: {memory}"
|
||||
```
|
||||
|
||||
This function:
|
||||
- Takes a memory string
|
||||
- Creates a formatted memory string
|
||||
- Stores it in Mem0 using the `add()` method
|
||||
- Includes metadata to categorize the memory for easier retrieval
|
||||
- Returns a confirmation message that the agent will speak
|
||||
|
||||
#### Finding Relevant Memories
|
||||
|
||||
```python
|
||||
@function_tool
|
||||
async def search_memories(
|
||||
query: str
|
||||
) -> str:
|
||||
"""
|
||||
Find memories relevant to the current conversation.
|
||||
Args:
|
||||
query: The search query to find relevant memories
|
||||
"""
|
||||
print(f"Finding memories related to: {query}")
|
||||
results = await mem0_client.search(
|
||||
query,
|
||||
user_id=USER_ID,
|
||||
limit=5,
|
||||
threshold=0.7, # Higher threshold for more relevant results
|
||||
|
||||
)
|
||||
|
||||
# Format and return the results
|
||||
if not results.get('results', []):
|
||||
return "I don't have any relevant memories about this topic."
|
||||
|
||||
memories = [f"• {result['memory']}" for result in results.get('results', [])]
|
||||
return "Here's what I remember that might be relevant:\n" + "\n".join(memories)
|
||||
```
|
||||
|
||||
This tool:
|
||||
- Takes a search query string
|
||||
- Passes it to Mem0's semantic search to find related memories
|
||||
- Sets a threshold for relevance to ensure quality results
|
||||
- Returns a formatted list of relevant memories or a default message
|
||||
|
||||
### 3. Creating the Voice Agent
|
||||
|
||||
```python
|
||||
def create_memory_voice_agent():
|
||||
# Create the agent with memory-enabled tools
|
||||
agent = Agent(
|
||||
name="Memory Assistant",
|
||||
instructions=prompt_with_handoff_instructions(
|
||||
"""You're speaking to a human, so be polite and concise.
|
||||
Always respond in clear, natural English.
|
||||
You have the ability to remember information about the user.
|
||||
Use the save_memories tool when the user shares an important information worth remembering.
|
||||
Use the search_memories tool when you need context from past conversations or user asks you to recall something.
|
||||
""",
|
||||
),
|
||||
model="gpt-4.1-nano-2025-04-14",
|
||||
tools=[save_memories, search_memories],
|
||||
)
|
||||
|
||||
return agent
|
||||
```
|
||||
|
||||
This function:
|
||||
- Creates an OpenAI Agent with specific instructions
|
||||
- Configures it to use gpt-4.1-nano (you can use other models)
|
||||
- Registers the memory-related tools with the agent
|
||||
- Uses `prompt_with_handoff_instructions` to include standard voice agent behaviors
|
||||
|
||||
### 4. Microphone Recording Functionality
|
||||
|
||||
```python
|
||||
async def record_from_microphone(duration=5, samplerate=24000):
|
||||
"""Record audio from the microphone for a specified duration."""
|
||||
print(f"Recording for {duration} seconds...")
|
||||
|
||||
# Create a buffer to store the recorded audio
|
||||
frames = []
|
||||
|
||||
# Callback function to store audio data
|
||||
def callback(indata, frames_count, time_info, status):
|
||||
frames.append(indata.copy())
|
||||
|
||||
# Start recording
|
||||
with sd.InputStream(samplerate=samplerate, channels=1, callback=callback, dtype=np.int16):
|
||||
await asyncio.sleep(duration)
|
||||
|
||||
# Combine all frames into a single numpy array
|
||||
audio_data = np.concatenate(frames)
|
||||
return audio_data
|
||||
```
|
||||
|
||||
This function:
|
||||
- Creates a simple asynchronous microphone recording function
|
||||
- Uses the sounddevice library to capture audio input
|
||||
- Stores frames in a buffer during recording
|
||||
- Combines frames into a single numpy array when complete
|
||||
- Returns the audio data for processing
|
||||
|
||||
### 5. Main Loop and Voice Processing
|
||||
|
||||
```python
|
||||
async def main():
|
||||
# Create the agent
|
||||
agent = create_memory_voice_agent()
|
||||
|
||||
# Set up the voice pipeline
|
||||
pipeline = VoicePipeline(
|
||||
workflow=SingleAgentVoiceWorkflow(agent)
|
||||
)
|
||||
|
||||
# Configure TTS settings
|
||||
pipeline.config.tts_settings.voice = "alloy"
|
||||
pipeline.config.tts_settings.speed = 1.0
|
||||
|
||||
try:
|
||||
while True:
|
||||
# Get user input
|
||||
print("\nPress Enter to start recording (or 'q' to quit)...")
|
||||
user_input = input()
|
||||
if user_input.lower() == 'q':
|
||||
break
|
||||
|
||||
# Record and process audio
|
||||
audio_data = await record_from_microphone(duration=5)
|
||||
audio_input = AudioInput(buffer=audio_data)
|
||||
result = await pipeline.run(audio_input)
|
||||
|
||||
# Play response and handle events
|
||||
player = sd.OutputStream(samplerate=24000, channels=1, dtype=np.int16)
|
||||
player.start()
|
||||
|
||||
agent_response = ""
|
||||
print("\nAgent response:")
|
||||
|
||||
async for event in result.stream():
|
||||
if event.type == "voice_stream_event_audio":
|
||||
player.write(event.data)
|
||||
elif event.type == "voice_stream_event_content":
|
||||
content = event.data
|
||||
agent_response += content
|
||||
print(content, end="", flush=True)
|
||||
|
||||
# Save the agent's response to memory
|
||||
if agent_response:
|
||||
try:
|
||||
await mem0_client.add(
|
||||
f"Agent response: {agent_response}",
|
||||
user_id=USER_ID,
|
||||
metadata={"type": "agent_response"}
|
||||
)
|
||||
except Exception as e:
|
||||
print(f"Failed to store memory: {e}")
|
||||
|
||||
except KeyboardInterrupt:
|
||||
print("\nExiting...")
|
||||
```
|
||||
|
||||
This main function orchestrates the entire process:
|
||||
1. Creates the memory-enabled voice agent
|
||||
2. Sets up the voice pipeline with TTS settings
|
||||
3. Implements an interactive loop for recording and processing voice input
|
||||
4. Handles streaming of response events (both audio and text)
|
||||
5. Automatically saves the agent's responses to memory
|
||||
6. Includes proper error handling and exit mechanisms
|
||||
|
||||
## Create a Memory-Enabled Voice Agent
|
||||
|
||||
Now that we've explained each component, here's the complete implementation that combines OpenAI Agents SDK for voice with Mem0's memory capabilities:
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
import os
|
||||
import logging
|
||||
from typing import Optional, List, Dict, Any
|
||||
import numpy as np
|
||||
import sounddevice as sd
|
||||
from pydantic import BaseModel
|
||||
|
||||
# OpenAI Agents SDK imports
|
||||
from agents import (
|
||||
Agent,
|
||||
function_tool
|
||||
)
|
||||
from agents.voice import (
|
||||
AudioInput,
|
||||
SingleAgentVoiceWorkflow,
|
||||
VoicePipeline
|
||||
)
|
||||
from agents.extensions.handoff_prompt import prompt_with_handoff_instructions
|
||||
|
||||
# Mem0 imports
|
||||
from mem0 import AsyncMemoryClient
|
||||
|
||||
# Set up API keys (replace with your actual keys)
|
||||
os.environ["OPENAI_API_KEY"] = "your-openai-api-key"
|
||||
os.environ["MEM0_API_KEY"] = "your-mem0-api-key"
|
||||
|
||||
# Define a global user ID for simplicity
|
||||
USER_ID = "voice_user"
|
||||
|
||||
# Initialize Mem0 client
|
||||
mem0_client = AsyncMemoryClient()
|
||||
|
||||
# Create tools that utilize Mem0's memory
|
||||
@function_tool
|
||||
async def save_memories(
|
||||
memory: str
|
||||
) -> str:
|
||||
"""
|
||||
Store a user memory in memory.
|
||||
Args:
|
||||
memory: The memory to save
|
||||
"""
|
||||
print(f"Saving memory: {memory} for user {USER_ID}")
|
||||
|
||||
# Store the preference in Mem0
|
||||
memory_content = f"User memory - {memory}"
|
||||
await mem0_client.add(
|
||||
memory_content,
|
||||
user_id=USER_ID,
|
||||
)
|
||||
|
||||
return f"I've saved your memory: {memory}"
|
||||
|
||||
@function_tool
|
||||
async def search_memories(
|
||||
query: str
|
||||
) -> str:
|
||||
"""
|
||||
Find memories relevant to the current conversation.
|
||||
Args:
|
||||
query: The search query to find relevant memories
|
||||
"""
|
||||
print(f"Finding memories related to: {query}")
|
||||
results = await mem0_client.search(
|
||||
query,
|
||||
user_id=USER_ID,
|
||||
limit=5,
|
||||
threshold=0.7, # Higher threshold for more relevant results
|
||||
|
||||
)
|
||||
|
||||
# Format and return the results
|
||||
if not results.get('results', []):
|
||||
return "I don't have any relevant memories about this topic."
|
||||
|
||||
memories = [f"• {result['memory']}" for result in results.get('results', [])]
|
||||
return "Here's what I remember that might be relevant:\n" + "\n".join(memories)
|
||||
|
||||
# Create the agent with memory-enabled tools
|
||||
def create_memory_voice_agent():
|
||||
# Create the agent with memory-enabled tools
|
||||
agent = Agent(
|
||||
name="Memory Assistant",
|
||||
instructions=prompt_with_handoff_instructions(
|
||||
"""You're speaking to a human, so be polite and concise.
|
||||
Always respond in clear, natural English.
|
||||
You have the ability to remember information about the user.
|
||||
Use the save_memories tool when the user shares an important information worth remembering.
|
||||
Use the search_memories tool when you need context from past conversations or user asks you to recall something.
|
||||
""",
|
||||
),
|
||||
model="gpt-4.1-nano-2025-04-14",
|
||||
tools=[save_memories, search_memories],
|
||||
)
|
||||
|
||||
return agent
|
||||
|
||||
async def record_from_microphone(duration=5, samplerate=24000):
|
||||
"""Record audio from the microphone for a specified duration."""
|
||||
print(f"Recording for {duration} seconds...")
|
||||
|
||||
# Create a buffer to store the recorded audio
|
||||
frames = []
|
||||
|
||||
# Callback function to store audio data
|
||||
def callback(indata, frames_count, time_info, status):
|
||||
frames.append(indata.copy())
|
||||
|
||||
# Start recording
|
||||
with sd.InputStream(samplerate=samplerate, channels=1, callback=callback, dtype=np.int16):
|
||||
await asyncio.sleep(duration)
|
||||
|
||||
# Combine all frames into a single numpy array
|
||||
audio_data = np.concatenate(frames)
|
||||
return audio_data
|
||||
|
||||
async def main():
|
||||
print("Starting Memory Voice Agent")
|
||||
|
||||
# Create the agent and context
|
||||
agent = create_memory_voice_agent()
|
||||
|
||||
# Set up the voice pipeline
|
||||
pipeline = VoicePipeline(
|
||||
workflow=SingleAgentVoiceWorkflow(agent)
|
||||
)
|
||||
|
||||
# Configure TTS settings
|
||||
pipeline.config.tts_settings.voice = "alloy"
|
||||
pipeline.config.tts_settings.speed = 1.0
|
||||
|
||||
try:
|
||||
while True:
|
||||
# Get user input
|
||||
print("\nPress Enter to start recording (or 'q' to quit)...")
|
||||
user_input = input()
|
||||
if user_input.lower() == 'q':
|
||||
break
|
||||
|
||||
# Record and process audio
|
||||
audio_data = await record_from_microphone(duration=5)
|
||||
audio_input = AudioInput(buffer=audio_data)
|
||||
|
||||
print("Processing your request...")
|
||||
|
||||
# Process the audio input
|
||||
result = await pipeline.run(audio_input)
|
||||
|
||||
# Create an audio player
|
||||
player = sd.OutputStream(samplerate=24000, channels=1, dtype=np.int16)
|
||||
player.start()
|
||||
|
||||
# Store the agent's response for adding to memory
|
||||
agent_response = ""
|
||||
|
||||
print("\nAgent response:")
|
||||
# Play the audio stream as it comes in
|
||||
async for event in result.stream():
|
||||
if event.type == "voice_stream_event_audio":
|
||||
player.write(event.data)
|
||||
elif event.type == "voice_stream_event_content":
|
||||
# Accumulate and print the text response
|
||||
content = event.data
|
||||
agent_response += content
|
||||
print(content, end="", flush=True)
|
||||
|
||||
print("\n")
|
||||
|
||||
# Example of saving the conversation to Mem0 after completion
|
||||
if agent_response:
|
||||
try:
|
||||
await mem0_client.add(
|
||||
f"Agent response: {agent_response}",
|
||||
user_id=USER_ID,
|
||||
metadata={"type": "agent_response"}
|
||||
)
|
||||
except Exception as e:
|
||||
print(f"Failed to store memory: {e}")
|
||||
|
||||
except KeyboardInterrupt:
|
||||
print("\nExiting...")
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
```
|
||||
|
||||
## Key Features of This Implementation
|
||||
|
||||
This implementation offers several key features:
|
||||
|
||||
1. **Simplified User Management**: Uses a global `USER_ID` variable for simplicity, but can be extended to manage multiple users.
|
||||
|
||||
2. **Real Microphone Input**: Includes a `record_from_microphone()` function that captures actual voice input from your microphone.
|
||||
|
||||
3. **Interactive Voice Loop**: Implements a continuous interaction loop, allowing for multiple back-and-forth exchanges.
|
||||
|
||||
4. **Memory Management Tools**:
|
||||
- `save_memories`: Stores user memories in Mem0
|
||||
- `search_memories`: Searches for relevant past information
|
||||
|
||||
5. **Voice Configuration**: Demonstrates how to configure TTS settings for the voice response.
|
||||
|
||||
## Running the Example
|
||||
|
||||
To run this example:
|
||||
|
||||
1. Replace the placeholder API keys with your actual keys
|
||||
2. Make sure your microphone is properly connected
|
||||
3. Run the script with Python 3.8 or newer
|
||||
4. Press Enter to start recording, then speak your request
|
||||
5. Press 'q' to quit the application
|
||||
|
||||
The agent will listen to your request, process it through the OpenAI model, utilize Mem0 for memory operations as needed, and respond both through text output and voice speech.
|
||||
|
||||
## Best Practices for Voice Agents with Memory
|
||||
|
||||
1. **Optimizing Memory for Voice**: Keep memories concise and relevant for voice responses.
|
||||
|
||||
2. **Forgetting Mechanism**: Implement a way to delete or expire memories that are no longer relevant.
|
||||
|
||||
3. **Context Preservation**: Store enough context with each memory to make retrieval effective.
|
||||
|
||||
4. **Error Handling**: Implement robust error handling for memory operations, as voice interactions should continue smoothly even if memory operations fail.
|
||||
|
||||
## Conclusion
|
||||
|
||||
By combining OpenAI's Agents SDK with Mem0's memory capabilities, you can create voice agents that maintain persistent memory of user preferences and past interactions. This significantly enhances the user experience by making conversations more natural and personalized.
|
||||
|
||||
As you build your voice application, experiment with different memory strategies and filtering approaches to find the optimal balance between comprehensive memory and efficient retrieval for your specific use case.
|
||||
|
||||
## Debugging Function Tools
|
||||
|
||||
When working with the OpenAI Agents SDK, you might notice that regular `print()` statements inside `@function_tool` decorated functions don't appear in your console output. This is because the Agents SDK captures and redirects standard output when executing these functions.
|
||||
|
||||
To effectively debug your function tools, use Python's `logging` module instead:
|
||||
|
||||
```python
|
||||
import logging
|
||||
|
||||
# Set up logging at the top of your file
|
||||
logging.basicConfig(
|
||||
level=logging.DEBUG,
|
||||
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
||||
force=True
|
||||
)
|
||||
logger = logging.getLogger("memory_voice_agent")
|
||||
|
||||
# Then use logger in your function tools
|
||||
@function_tool
|
||||
async def save_memories(
|
||||
memory: str
|
||||
) -> str:
|
||||
"""Store a user memory in memory."""
|
||||
# This will be visible in your console
|
||||
logger.debug(f"Saving memory: {memory} for user {USER_ID}")
|
||||
|
||||
# Rest of your function...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Multimodal Support" icon="image" href="/platform/features/multimodal-support">
|
||||
Learn how to add vision and audio memory alongside voice interactions.
|
||||
</Card>
|
||||
<Card title="Build a Mem0 Companion" icon="users" href="/cookbooks/essentials/building-ai-companion">
|
||||
Master the core patterns for building memory-powered companions.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -0,0 +1,68 @@
|
||||
---
|
||||
title: YouTube Research with Mem0
|
||||
description: "Layer personalized context over any video using the Mem0 YouTube assistant."
|
||||
---
|
||||
|
||||
|
||||
Enhance your YouTube experience with Mem0's YouTube Assistant, a Chrome extension that brings AI-powered chat directly to your YouTube videos. Get instant, personalized answers about video content while leveraging your own knowledge and memories, all without leaving the page.
|
||||
|
||||
## Features
|
||||
|
||||
- **Contextual AI Chat**: Ask questions about videos you're watching
|
||||
- **Seamless Integration**: Chat interface sits alongside YouTube's native UI
|
||||
- **Memory Integration**: Personalized responses based on your knowledge through Mem0
|
||||
- **Real-Time Memory**: Memories are updated in real-time based on your interactions
|
||||
|
||||
## Demo Video
|
||||
|
||||
<video
|
||||
autoPlay
|
||||
muted
|
||||
loop
|
||||
playsInline
|
||||
width="700"
|
||||
height="400"
|
||||
src="https://github.com/user-attachments/assets/c0334ccd-311b-4dd7-8034-ef88204fc751"
|
||||
></video>
|
||||
|
||||
## Installation
|
||||
|
||||
This extension is not available on the Chrome Web Store yet. You can install it manually using below method:
|
||||
|
||||
### Manual Installation (Developer Mode)
|
||||
|
||||
1. **Download the Extension**: Clone or download the extension files from the [Mem0 GitHub repository](https://github.com/mem0ai/mem0/tree/main/examples)
|
||||
2. **Build**: Run `npm install` followed by `npm run build` to install the dependencies and build the extension
|
||||
3. **Access Chrome Extensions**: Open Google Chrome and navigate to `chrome://extensions`
|
||||
4. **Enable Developer Mode**: Toggle the "Developer mode" switch in the top right corner
|
||||
5. **Load Unpacked Extension**: Click "Load unpacked" and select the directory containing the extension files
|
||||
6. **Confirm Installation**: The Mem0 YouTube Assistant Extension should now appear in your Chrome toolbar
|
||||
|
||||
## Setup
|
||||
|
||||
1. **Configure API Settings**: Click the extension icon and enter your OpenAI API key (required to use the extension)
|
||||
2. **Customize Settings**: Configure additional settings such as model, temperature, and memory settings
|
||||
3. **Navigate to YouTube**: Start using the assistant on any YouTube video
|
||||
4. **Memories**: Enter your Mem0 API key to enable personalized responses, and feed initial memories from settings
|
||||
|
||||
## Example Prompts
|
||||
|
||||
- "Can you summarize the main points of this video?"
|
||||
- "Explain the concept they just mentioned"
|
||||
- "How does this relate to what I already know?"
|
||||
- "What are some practical applications of this topic related to my work?"
|
||||
|
||||
## Privacy and Data Security
|
||||
|
||||
Your API keys are stored locally in your browser. Your messages are sent to the Mem0 API for extracting and retrieving memories. Mem0 is committed to ensuring your data's privacy and security.
|
||||
|
||||
---
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Tag and Organize Memories" icon="tag" href="/cookbooks/essentials/tagging-and-organizing-memories">
|
||||
Categorize video insights to build a searchable research knowledge base.
|
||||
</Card>
|
||||
<Card title="Deep Research with Mem0" icon="magnifying-glass" href="/cookbooks/operations/deep-research">
|
||||
Combine memory with search tools to conduct comprehensive research projects.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -0,0 +1,525 @@
|
||||
---
|
||||
title: Build a Mem0 Companion
|
||||
description: "Spin up a fitness coach that remembers goals, adapts tone, and keeps sessions personal."
|
||||
---
|
||||
|
||||
|
||||
Essentially, creating a companion out of LLMs is as simple as a loop. But these loops work great for one type of character without personalization and fall short as soon as you restart the chat.
|
||||
|
||||
Problem: LLMs are stateless. GPT doesn't remember conversations. You could stuff everything inside the context window, but that becomes slow, expensive, and breaks at scale.
|
||||
|
||||
The solution: Mem0. It extracts and stores what matters from conversations, then retrieves it when needed. Your companion remembers user preferences, past events, and history.
|
||||
|
||||
In this cookbook we'll build a **fitness companion** that:
|
||||
|
||||
- Remembers user goals across sessions
|
||||
- Recalls past workouts and progress
|
||||
- Adapts its personality based on user preferences
|
||||
- Handles both short-term context (today's chat) and long-term memory (months of history)
|
||||
|
||||
By the end, you'll have a working fitness companion and know how to handle common production challenges.
|
||||
|
||||
---
|
||||
|
||||
## The Basic Loop with Memory
|
||||
|
||||
Max wants to train for a marathon. He starts chatting with Ray, an AI running coach.
|
||||
|
||||
```python
|
||||
from openai import OpenAI
|
||||
from mem0 import MemoryClient
|
||||
|
||||
openai_client = OpenAI(api_key="your-openai-key")
|
||||
mem0_client = MemoryClient(api_key="your-mem0-key")
|
||||
|
||||
def chat(user_input, user_id):
|
||||
# Retrieve relevant memories
|
||||
memories = mem0_client.search(user_input, user_id=user_id, limit=5)
|
||||
context = "\\n".join(m["memory"] for m in memories["results"])
|
||||
|
||||
# Call LLM with memory context
|
||||
response = openai_client.chat.completions.create(
|
||||
model="gpt-4o-mini",
|
||||
messages=[
|
||||
{"role": "system", "content": f"You're Ray, a running coach. Memories:\\n{context}"},
|
||||
{"role": "user", "content": user_input}
|
||||
]
|
||||
).choices[0].message.content
|
||||
|
||||
# Store the exchange
|
||||
mem0_client.add([
|
||||
{"role": "user", "content": user_input},
|
||||
{"role": "assistant", "content": response}
|
||||
], user_id=user_id)
|
||||
|
||||
return response
|
||||
|
||||
```
|
||||
|
||||
**Session 1:**
|
||||
|
||||
```python
|
||||
chat("I want to run a marathon in under 4 hours", user_id="max")
|
||||
# Output: "That's a solid goal. What's your current weekly mileage?"
|
||||
# Stored in Mem0: "Max wants to run sub-4 marathon"
|
||||
|
||||
```
|
||||
|
||||
**Session 2 (next day, app restarted):**
|
||||
|
||||
```python
|
||||
chat("What should I focus on today?", user_id="max")
|
||||
# Output: "Based on your sub-4 marathon goal, let's work on building your aerobic base..."
|
||||
|
||||
```
|
||||
|
||||
<Info>
|
||||
Ray remembers Max's goal across sessions. The app restarted, but the memory persisted. This is the core pattern: retrieve memories, pass them as context, store new exchanges.
|
||||
</Info>
|
||||
|
||||
Ray remembers. Restart the app, and the goal persists. From here on, we'll focus on just the Mem0 API calls.
|
||||
|
||||
---
|
||||
|
||||
## Organizing Memory by Type
|
||||
|
||||
### Separating Temporary from Permanent
|
||||
|
||||
Max mentions his knee hurts. That's different from his marathon goal - one is temporary, the other is long-term.
|
||||
|
||||
**Categories vs Metadata:**
|
||||
|
||||
- **Categories**: AI-assigned by Mem0 based on content (you can't force them)
|
||||
- **Metadata**: Manually set by you for forced tagging
|
||||
|
||||
Define custom categories at the project level. Mem0 will automatically tag memories with relevant categories based on content:
|
||||
|
||||
```python
|
||||
mem0_client.project.update(custom_categories=[
|
||||
{"goals": "Race targets and training objectives"},
|
||||
{"constraints": "Injuries, limitations, recovery needs"},
|
||||
{"preferences": "Training style, surfaces, schedules"}
|
||||
])
|
||||
|
||||
```
|
||||
|
||||
<Note>
|
||||
**Categories vs Metadata:** Categories are AI-assigned by Mem0 based on content semantics. You define the palette, Mem0 picks which ones apply. If you need guaranteed tagging, use `metadata` instead.
|
||||
</Note>
|
||||
|
||||
Now when you add memories, Mem0 automatically assigns the appropriate categories:
|
||||
|
||||
```python
|
||||
# Add goal - Mem0 automatically tags it as "goals"
|
||||
mem0_client.add(
|
||||
[{"role": "user", "content": "Sub-4 marathon is my A-race"}],
|
||||
user_id="max"
|
||||
)
|
||||
|
||||
# Add constraint - Mem0 automatically tags it as "constraints"
|
||||
mem0_client.add(
|
||||
[{"role": "user", "content": "My right knee flares up on downhills"}],
|
||||
user_id="max"
|
||||
)
|
||||
|
||||
```
|
||||
|
||||
Mem0 reads the content and intelligently picks which categories apply. You define the palette, it handles the tagging.
|
||||
|
||||
**Important:** You cannot force specific categories. Mem0's platform decides which categories are relevant based on content. If you need to force-tag something, use `metadata` instead:
|
||||
|
||||
```python
|
||||
# Force tag using metadata (not categories)
|
||||
mem0_client.add(
|
||||
[{"role": "user", "content": "Some workout note"}],
|
||||
user_id="max",
|
||||
metadata={"workout_type": "speed", "forced_tag": "custom_label"}
|
||||
)
|
||||
|
||||
```
|
||||
|
||||
### Filtering by Category
|
||||
|
||||
Retrieve just constraints for workout planning:
|
||||
|
||||
```python
|
||||
constraints = mem0_client.search(
|
||||
"injury concerns",
|
||||
user_id="max",
|
||||
filters={"categories": {"in": ["constraints"]}}
|
||||
)
|
||||
print([m["memory"] for m in constraints["results"]])
|
||||
# Output: ["Max's right knee flares up on downhills"]
|
||||
|
||||
```
|
||||
|
||||
Ray can plan workouts that avoid aggravating Max's knee, without pulling in race goals or other unrelated memories.
|
||||
|
||||
---
|
||||
|
||||
## Filtering What Gets Stored
|
||||
|
||||
### The Problem
|
||||
|
||||
Run the basic loop for a week and check what's stored:
|
||||
|
||||
```python
|
||||
memories = mem0_client.get_all(user_id="max")
|
||||
print([m["memory"] for m in memories["results"]])
|
||||
# Output: ["Max wants to run marathon under 4 hours", "hey", "lol ok", "cool thanks", "gtg bye"]
|
||||
|
||||
```
|
||||
|
||||
<Warning>
|
||||
Without filters, Mem0 stores everything—greetings, filler, and casual chat. This pollutes retrieval: instead of pulling "marathon goal," you get "lol ok." Set custom instructions to keep memory clean.
|
||||
</Warning>
|
||||
|
||||
Noise. Greetings and filler clutter the memory.
|
||||
|
||||
### Custom Instructions
|
||||
|
||||
Tell Mem0 what matters:
|
||||
|
||||
```python
|
||||
mem0_client.project.update(custom_instructions="""
|
||||
Extract from running coach conversations:
|
||||
- Training goals and race targets
|
||||
- Physical constraints or injuries
|
||||
- Training preferences (time of day, surfaces, weather)
|
||||
- Progress milestones
|
||||
|
||||
Exclude:
|
||||
- Greetings and filler
|
||||
- Casual chatter
|
||||
- Hypotheticals unless planning related
|
||||
""")
|
||||
|
||||
```
|
||||
|
||||
Now chat again:
|
||||
|
||||
```python
|
||||
chat("hey how's it going", user_id="max")
|
||||
chat("I prefer trail running over roads", user_id="max")
|
||||
|
||||
memories = mem0_client.get_all(user_id="max")
|
||||
print([m["memory"] for m in memories["results"]])
|
||||
# Output: ["Max wants to run marathon under 4 hours", "Max prefers trail running over roads"]
|
||||
|
||||
```
|
||||
|
||||
<Info>
|
||||
**Expected output:** Only 2 memories stored—the marathon goal and trail preference. The greeting "hey how's it going" was filtered out automatically. Custom instructions are working.
|
||||
</Info>
|
||||
|
||||
Only meaningful facts. Filler gets dropped automatically.
|
||||
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
## Agent Memory for Personality
|
||||
|
||||
### Why Agents Need Memory Too
|
||||
|
||||
Max prefers direct feedback, not motivational fluff. Ray needs to remember how to communicate - that's agent memory, separate from user memory.
|
||||
|
||||
Store agent personality:
|
||||
|
||||
```python
|
||||
mem0_client.add(
|
||||
[{"role": "system", "content": "Max wants direct, data-driven feedback. Skip motivational language."}],
|
||||
agent_id="ray_coach"
|
||||
)
|
||||
|
||||
```
|
||||
|
||||
Retrieve agent style alongside user memories:
|
||||
|
||||
```python
|
||||
# Get coach personality
|
||||
agent_memories = mem0_client.search("coaching style", agent_id="ray_coach")
|
||||
# Output: ["Max wants direct, data-driven feedback. Skip motivational language."]
|
||||
|
||||
# Store conversations with agent_id
|
||||
mem0_client.add([
|
||||
{"role": "user", "content": "How'd my run look today?"},
|
||||
{"role": "assistant", "content": "Pace was 8:15/mile. Heart rate 152, zone 2."}
|
||||
], user_id="max", agent_id="ray_coach")
|
||||
|
||||
```
|
||||
|
||||
<Info>
|
||||
**Expected behavior:** Ray's responses are now data-driven and direct. The agent memory stored the coaching style preference, so future responses adapt automatically without Max having to repeat his preference.
|
||||
</Info>
|
||||
|
||||
No "Great job!" or "Keep it up!" - just data. Ray adapts to Max's preference.
|
||||
|
||||
---
|
||||
|
||||
## Managing Short-Term Context
|
||||
|
||||
### When to Store in Mem0
|
||||
|
||||
Don't send every single message to Mem0. Keep recent context in memory, let Mem0 handle the important long-term facts.
|
||||
|
||||
```python
|
||||
# Store only meaningful exchanges in Mem0
|
||||
mem0_client.add([
|
||||
{"role": "user", "content": "I want to run a marathon"},
|
||||
{"role": "assistant", "content": "Let's build a training plan"}
|
||||
], user_id="max")
|
||||
|
||||
# Skip storing filler
|
||||
# "hey" → don't store
|
||||
# "cool thanks" → don't store
|
||||
|
||||
# Or rely on custom_instructions to filter automatically
|
||||
|
||||
```
|
||||
|
||||
Last 10 messages in your app's buffer. Important facts in Mem0. Faster, cheaper, still works.
|
||||
|
||||
---
|
||||
|
||||
## Time-Bound Memories
|
||||
|
||||
### Auto-Expiring Facts
|
||||
|
||||
Max tweaks his ankle. It'll heal in two weeks - the memory should expire too.
|
||||
|
||||
```python
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
expiration = (datetime.now() + timedelta(days=14)).strftime("%Y-%m-%d")
|
||||
|
||||
mem0_client.add(
|
||||
[{"role": "user", "content": "Rolled my left ankle, needs rest"}],
|
||||
user_id="max",
|
||||
expiration_date=expiration
|
||||
)
|
||||
|
||||
```
|
||||
|
||||
In 14 days, this memory disappears automatically. Ray stops asking about the ankle.
|
||||
|
||||
---
|
||||
|
||||
## Putting It All Together
|
||||
|
||||
Here's the Mem0 setup combining everything:
|
||||
|
||||
```python
|
||||
from mem0 import MemoryClient
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
mem0_client = MemoryClient(api_key="your-mem0-key")
|
||||
|
||||
# Configure memory filtering and categories
|
||||
mem0_client.project.update(
|
||||
custom_instructions="""
|
||||
Extract: goals, constraints, preferences, progress
|
||||
Exclude: greetings, filler, casual chat
|
||||
""",
|
||||
custom_categories=[
|
||||
{"name": "goals", "description": "Training targets"},
|
||||
{"name": "constraints", "description": "Injuries and limitations"},
|
||||
{"name": "preferences", "description": "Training style"}
|
||||
]
|
||||
)
|
||||
|
||||
```
|
||||
|
||||
**Week 1 - Store goals and preferences:**
|
||||
|
||||
```python
|
||||
mem0_client.add([
|
||||
{"role": "user", "content": "I want to run a sub-4 marathon"},
|
||||
{"role": "assistant", "content": "Got it. Let's build a training plan."}
|
||||
], user_id="max", agent_id="ray", categories=["goals"])
|
||||
|
||||
mem0_client.add([
|
||||
{"role": "user", "content": "I prefer trail running over roads"}
|
||||
], user_id="max", categories=["preferences"])
|
||||
|
||||
```
|
||||
|
||||
**Week 3 - Temporary injury with expiration:**
|
||||
|
||||
```python
|
||||
expiration = (datetime.now() + timedelta(days=14)).strftime("%Y-%m-%d")
|
||||
mem0_client.add(
|
||||
[{"role": "user", "content": "Rolled ankle, need light workouts"}],
|
||||
user_id="max",
|
||||
categories=["constraints"],
|
||||
expiration_date=expiration
|
||||
)
|
||||
|
||||
```
|
||||
|
||||
**Retrieve for context:**
|
||||
|
||||
```python
|
||||
memories = mem0_client.search("training plan", user_id="max", limit=5)
|
||||
# Gets: marathon goal, trail preference, ankle injury (if still valid)
|
||||
|
||||
```
|
||||
|
||||
Ray remembers goals, preferences, and personality. Handles temporary injuries. Works across sessions.
|
||||
|
||||
---
|
||||
|
||||
## Common Production Patterns
|
||||
|
||||
### Episodic Stories with run_id
|
||||
|
||||
Training for Boston is different from training for New York. Separate the memory threads:
|
||||
|
||||
```python
|
||||
mem0_client.add(messages, user_id="max", run_id="boston-2025")
|
||||
mem0_client.add(messages, user_id="max", run_id="nyc-2025")
|
||||
|
||||
# Retrieve only Boston memories
|
||||
boston_memories = mem0_client.search(
|
||||
"training plan",
|
||||
user_id="max",
|
||||
run_id="boston-2025"
|
||||
)
|
||||
|
||||
```
|
||||
|
||||
Each race gets its own episodic boundary. No cross-contamination.
|
||||
|
||||
### Importing Historical Data
|
||||
|
||||
Max has 6 months of training logs to backfill:
|
||||
|
||||
```python
|
||||
old_logs = [
|
||||
[{"role": "user", "content": "Completed 20-mile long run"}],
|
||||
[{"role": "user", "content": "Hit 8:00 pace on tempo run"}],
|
||||
]
|
||||
|
||||
for log in old_logs:
|
||||
mem0_client.add(log, user_id="max")
|
||||
|
||||
```
|
||||
|
||||
### Handling Contradictions
|
||||
|
||||
Max changes his goal from sub-4 to sub-3:45:
|
||||
|
||||
```python
|
||||
# Find the old memory
|
||||
memories = mem0_client.get_all(user_id="max")
|
||||
goal_memory = [m for m in memories["results"] if "sub-4" in m["memory"]][0]
|
||||
|
||||
# Update it
|
||||
mem0_client.update(goal_memory["id"], "Max wants to run sub-3:45 marathon")
|
||||
|
||||
```
|
||||
|
||||
Update instead of creating duplicates.
|
||||
|
||||
### Multiple Agents
|
||||
|
||||
Max works with Ray for running and Jordan for strength training:
|
||||
|
||||
```python
|
||||
chat("easy run today", user_id="max", agent_id="ray")
|
||||
chat("leg day workout", user_id="max", agent_id="jordan")
|
||||
|
||||
```
|
||||
|
||||
Each coach maintains separate personality memory while sharing user context.
|
||||
|
||||
### Filtering by Date
|
||||
|
||||
Prioritize recent training over old data:
|
||||
|
||||
```python
|
||||
recent = mem0_client.search(
|
||||
"training progress",
|
||||
user_id="max",
|
||||
filters={"created_at": {"gte": "2025-10-01"}}
|
||||
)
|
||||
|
||||
```
|
||||
|
||||
### Metadata Tagging
|
||||
|
||||
Tag workouts by type:
|
||||
|
||||
```python
|
||||
mem0_client.add(
|
||||
[{"role": "user", "content": "10x400m intervals"}],
|
||||
user_id="max",
|
||||
metadata={"workout_type": "speed", "intensity": "high"}
|
||||
)
|
||||
|
||||
# Later, find all speed workouts
|
||||
speed_sessions = mem0_client.search(
|
||||
"speed work",
|
||||
user_id="max",
|
||||
filters={"metadata": {"workout_type": "speed"}}
|
||||
)
|
||||
|
||||
```
|
||||
|
||||
### Pruning Old Memories
|
||||
|
||||
Delete irrelevant memories:
|
||||
|
||||
```python
|
||||
mem0_client.delete(memory_id="mem_xyz")
|
||||
|
||||
# Or clear an entire run_id
|
||||
mem0_client.delete_all(user_id="max", run_id="old-training-cycle")
|
||||
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## What You Built
|
||||
|
||||
A companion that:
|
||||
|
||||
- **Persists across sessions** - Mem0 storage
|
||||
- **Filters noise** - custom instructions
|
||||
- **Organizes by type** - categories
|
||||
- **Adapts personality** - **`agent_id`**
|
||||
- **Stays fast** - short-term buffer
|
||||
- **Handles temporal facts** - expiration
|
||||
- **Scales to production** - batching, metadata, pruning
|
||||
|
||||
This pattern works for any companion: fitness coaches, tutors, roleplay characters, therapy bots, creative writing partners.
|
||||
|
||||
---
|
||||
|
||||
<Tip>
|
||||
Start with 2-3 categories max (e.g., goals, constraints, preferences). More categories dilute tagging accuracy. You can always add more later after seeing what Mem0 extracts.
|
||||
</Tip>
|
||||
|
||||
---
|
||||
|
||||
## Production Checklist
|
||||
|
||||
Before launching:
|
||||
|
||||
- Set custom instructions for your domain
|
||||
- Define 2-3 categories (goals, constraints, preferences)
|
||||
- Add expiration strategy for time-bound facts
|
||||
- Implement error handling for API calls
|
||||
- Monitor memory quality in Mem0 dashboard
|
||||
- Clear test data from production project
|
||||
|
||||
---
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Build AI with Personality" icon="sparkles" href="/cookbooks/essentials/building-ai-with-personality">
|
||||
Separate user and agent memories so companions stay consistent across sessions.
|
||||
</Card>
|
||||
<Card title="Tag Support Memories" icon="tag" href="/cookbooks/essentials/tagging-and-organizing-memories">
|
||||
Organize customer context to keep assistants responsive at scale.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -0,0 +1,603 @@
|
||||
---
|
||||
title: Scope User vs Agent Memories
|
||||
description: "Use **user_id** and **agent_id** to balance personalization with consistent assistant behavior."
|
||||
---
|
||||
|
||||
# Build AI with Distinct Personalities
|
||||
|
||||
While building memory systems for AI apps, you need to juggle between agent and user memories. The user delivers information from their side, but there's often value inside the agent's responses as well.
|
||||
|
||||
Unlike other memory APIs, we built one that allows you the flexibility to store memory from all sources. User and agent memories in Mem0 are handled by:
|
||||
|
||||
- **user_id** - Memories about specific users
|
||||
- **agent_id** - Memories from the agent itself
|
||||
|
||||
In this guide, you'll see how these parameters work together, along with practical examples to help you build a fitness coach that remembers user workouts while maintaining a consistent coaching personality.
|
||||
|
||||
---
|
||||
|
||||
## User Memories
|
||||
|
||||
Let's start by tracking individual user workouts. We'll use **`user_id`** to keep each person's data separate.
|
||||
|
||||
```python
|
||||
from openai import OpenAI
|
||||
from mem0 import MemoryClient
|
||||
import os
|
||||
|
||||
openai_client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
|
||||
mem0_client = MemoryClient()
|
||||
|
||||
# Sarah logs her workout
|
||||
mem0_client.add(
|
||||
"Completed 5K run in 28 minutes - felt great!",
|
||||
user_id="sarah"
|
||||
)
|
||||
|
||||
# Mike logs his workout
|
||||
mem0_client.add(
|
||||
"Bench press: 185 lbs x 10 reps, 3 sets",
|
||||
user_id="mike"
|
||||
)
|
||||
|
||||
```
|
||||
|
||||
Now when we coach Sarah, we retrieve only her workout history:
|
||||
|
||||
```python
|
||||
# Get Sarah's workout history
|
||||
sarah_history = mem0_client.search(
|
||||
"What exercises has Sarah done recently?",
|
||||
filters={"user_id": "sarah"}
|
||||
)
|
||||
|
||||
# Generate coaching advice
|
||||
response = openai_client.chat.completions.create(
|
||||
model="gpt-4",
|
||||
messages=[
|
||||
{"role": "system", "content": "You're a supportive fitness coach."},
|
||||
{"role": "user", "content": f"Based on this history: {sarah_history}, suggest the next workout."}
|
||||
]
|
||||
)
|
||||
|
||||
print(response.choices[0].message.content)
|
||||
|
||||
```
|
||||
|
||||
**Output:**
|
||||
|
||||
```
|
||||
Great job on that 5K! Your endurance is building nicely. Let's add some
|
||||
strength work to complement your running. Try 3 sets of bodyweight squats
|
||||
(15 reps each) to strengthen your legs and improve your running power.
|
||||
|
||||
```
|
||||
|
||||
<Info>
|
||||
**Expected output:** Sarah gets running advice based on her 5K, not Mike's bench press data. The **`user_id`** filter ensures memories are isolated—each user only sees their own workout history.
|
||||
</Info>
|
||||
|
||||
This works perfectly! Each user has private workout history, and Sarah never sees Mike's data.
|
||||
|
||||
---
|
||||
|
||||
## Adding Coach Personality
|
||||
|
||||
Our fitness coach needs a consistent personality - supportive, motivational, and celebrates small wins. Let's see what happens if we try storing this with **`user_id`**:
|
||||
|
||||
```python
|
||||
# Adding coach personality for Sarah
|
||||
mem0_client.add(
|
||||
"I'm a supportive fitness coach who celebrates every achievement and uses athlete-focused language",
|
||||
user_id="sarah"
|
||||
)
|
||||
|
||||
# Adding the same personality for Mike
|
||||
mem0_client.add(
|
||||
"I'm a supportive fitness coach who celebrates every achievement and uses athlete-focused language",
|
||||
user_id="mike"
|
||||
)
|
||||
|
||||
# For 1,000 users, we'd repeat this 1,000 times...
|
||||
|
||||
```
|
||||
|
||||
This approach has some limitations:
|
||||
|
||||
1. **Duplication**: We're storing the same coaching personality 1,000 times for 1,000 users
|
||||
2. **Hard to update**: Want to change the coaching style? Update 1,000 memories
|
||||
3. **Mixed with user data**: Coach personality and user workouts are stored together, making queries complex
|
||||
|
||||
<Warning>
|
||||
Storing agent personality with **`user_id`** doesn't scale. For 10,000 users, you'd duplicate the same personality 10,000 times. Updating the coaching style means updating 10,000 separate memories. This wastes storage and makes maintenance impossible.
|
||||
</Warning>
|
||||
|
||||
What if the coach could have a personality that's shared across all users?
|
||||
|
||||
---
|
||||
|
||||
## Agent Memories
|
||||
|
||||
Here's where **`agent_id`** comes in. We can store the coach's personality once and share it across all users:
|
||||
|
||||
```python
|
||||
# Store coach personality ONCE with agent_id
|
||||
mem0_client.add(
|
||||
"I'm FitCoach - a supportive fitness coach who celebrates every achievement. "
|
||||
"I use motivational language, focus on progress over perfection, and help users build sustainable habits.",
|
||||
agent_id="fitcoach_v1"
|
||||
)
|
||||
|
||||
# Sarah's workout (still private)
|
||||
mem0_client.add(
|
||||
"Completed 5K run in 28 minutes",
|
||||
user_id="sarah"
|
||||
)
|
||||
|
||||
# Mike's workout (still private)
|
||||
mem0_client.add(
|
||||
"Bench press: 185 lbs x 10 reps, 3 sets",
|
||||
user_id="mike"
|
||||
)
|
||||
|
||||
```
|
||||
|
||||
Now when coaching Sarah, we retrieve both the agent's personality AND her workout history:
|
||||
|
||||
```python
|
||||
# Get both coach personality and Sarah's workouts
|
||||
coaching_context = mem0_client.search(
|
||||
"coaching context for Sarah",
|
||||
filters={
|
||||
"OR": [
|
||||
{"agent_id": "fitcoach_v1"}, # Coach personality
|
||||
{"user_id": "sarah"} # Sarah's workout history
|
||||
]
|
||||
}
|
||||
)
|
||||
|
||||
# Generate personalized coaching
|
||||
response = openai_client.chat.completions.create(
|
||||
model="gpt-4",
|
||||
messages=[
|
||||
{"role": "system", "content": str(coaching_context)},
|
||||
{"role": "user", "content": "What should I focus on in my next workout?"}
|
||||
]
|
||||
)
|
||||
|
||||
print(response.choices[0].message.content)
|
||||
|
||||
```
|
||||
|
||||
**Output:**
|
||||
|
||||
```
|
||||
Amazing work on that 5K! 🎉 You're crushing your running goals!
|
||||
|
||||
Now let's build some complementary strength. I recommend adding bodyweight
|
||||
squats to your routine - they'll make you an even stronger runner. Start
|
||||
with 3 sets of 15 reps, and remember: progress over perfection!
|
||||
|
||||
```
|
||||
|
||||
Notice how the response has the motivational tone (from **`agent_id`**) combined with personalized advice based on Sarah's 5K run (from **`user_id`**).
|
||||
|
||||
The coach personality is now:
|
||||
|
||||
- ✅ Stored once, shared by all users
|
||||
- ✅ Easy to update (change one memory, affects all users)
|
||||
- ✅ Cleanly separated from user workout data
|
||||
|
||||
<Info>
|
||||
**Expected behavior:** The response combines the motivational tone (from **`agent_id`**) with Sarah's specific 5K progress (from **`user_id`**). One agent personality, infinite users—update the agent once, and all users get the new coaching style.
|
||||
</Info>
|
||||
|
||||
---
|
||||
|
||||
## Combining Both: Relationship Memories
|
||||
|
||||
There's a third type of memory - one that captures the relationship between a specific user and the coach. To store these, use `metadata` to track which agent the relationship is with:
|
||||
|
||||
```python
|
||||
# Coach personality (shared across all users)
|
||||
mem0_client.add(
|
||||
"I'm FitCoach - supportive and motivational",
|
||||
agent_id="fitcoach_v1"
|
||||
)
|
||||
|
||||
# Sarah's workout data (private to Sarah)
|
||||
mem0_client.add(
|
||||
"Goal: Run a half marathon by June. Currently runs 5K comfortably.",
|
||||
user_id="sarah"
|
||||
)
|
||||
|
||||
# Sarah-Coach relationship (stored as user memory with agent context in metadata)
|
||||
mem0_client.add(
|
||||
"Sarah and I have an inside joke: 'No pain, no protein shake!' "
|
||||
"She responds best to gentle encouragement after tough workouts.",
|
||||
user_id="sarah",
|
||||
metadata={"agent_id": "fitcoach_v1", "type": "relationship"}
|
||||
)
|
||||
|
||||
# Mike-Coach relationship (different from Sarah's)
|
||||
mem0_client.add(
|
||||
"Mike prefers data-driven feedback with specific numbers and percentages. "
|
||||
"Less motivational talk, more concrete metrics.",
|
||||
user_id="mike",
|
||||
metadata={"agent_id": "fitcoach_v1", "type": "relationship"}
|
||||
)
|
||||
|
||||
```
|
||||
|
||||
Now when coaching Sarah, retrieve her data including relationship with this specific coach:
|
||||
|
||||
```python
|
||||
# Get Sarah's memories including relationship with fitcoach_v1
|
||||
sarah_context = mem0_client.search(
|
||||
"How should I coach Sarah today?",
|
||||
user_id="sarah",
|
||||
filters={"metadata": {"agent_id": "fitcoach_v1"}}
|
||||
)
|
||||
|
||||
# Get coach personality
|
||||
coach_personality = mem0_client.search(
|
||||
"coaching personality",
|
||||
agent_id="fitcoach_v1"
|
||||
)
|
||||
|
||||
# Combine both contexts
|
||||
full_context = str(coach_personality) + "\\n" + str(sarah_context)
|
||||
|
||||
response = openai_client.chat.completions.create(
|
||||
model="gpt-4",
|
||||
messages=[
|
||||
{"role": "system", "content": full_context},
|
||||
{"role": "user", "content": "Just finished today's workout!"}
|
||||
]
|
||||
)
|
||||
|
||||
print(response.choices[0].message.content)
|
||||
|
||||
```
|
||||
|
||||
**Output:**
|
||||
|
||||
```
|
||||
Awesome work today! 💪 No pain, no protein shake, right? 😄
|
||||
|
||||
You're making real progress toward that half marathon goal. Keep this
|
||||
momentum going - your consistency is your superpower!
|
||||
|
||||
```
|
||||
|
||||
When coaching Mike with the same approach:
|
||||
|
||||
```python
|
||||
# Get Mike's memories including relationship with fitcoach_v1
|
||||
mike_context = mem0_client.search(
|
||||
"How should I coach Mike today?",
|
||||
user_id="mike",
|
||||
filters={"metadata": {"agent_id": "fitcoach_v1"}}
|
||||
)
|
||||
|
||||
coach_personality = mem0_client.search(
|
||||
"coaching personality",
|
||||
agent_id="fitcoach_v1"
|
||||
)
|
||||
|
||||
full_context = str(coach_personality) + "\\n" + str(mike_context)
|
||||
|
||||
# ... same coaching code ...
|
||||
|
||||
```
|
||||
|
||||
**Output:**
|
||||
|
||||
```
|
||||
Solid session. Your bench press shows 8% improvement over last week
|
||||
(171 lbs avg to 185 lbs). Target: 200 lbs by end of month.
|
||||
On track at current rate (+3.2% weekly).
|
||||
|
||||
```
|
||||
|
||||
Same coach, completely different experience based on each user's relationship preferences stored in metadata.
|
||||
|
||||
<Note>
|
||||
**Relationship memories** are stored with **`user_id`** (they're private to each user) but include `agent_id` in metadata to track which agent the relationship is with. This lets you retrieve the user's preferences for how this specific agent should interact with them.
|
||||
</Note>
|
||||
|
||||
---
|
||||
|
||||
## Putting It All Together
|
||||
|
||||
Here's a complete example showing all three memory layers working together:
|
||||
|
||||
```python
|
||||
from openai import OpenAI
|
||||
from mem0 import MemoryClient
|
||||
import os
|
||||
|
||||
# Initialize clients
|
||||
openai_client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
|
||||
mem0_client = MemoryClient()
|
||||
|
||||
# Layer 1: Agent personality (shared)
|
||||
mem0_client.add(
|
||||
"I'm FitCoach - supportive, motivational, celebrates small wins",
|
||||
agent_id="fitcoach_v1",
|
||||
metadata={"type": "personality"}
|
||||
)
|
||||
|
||||
# Layer 2: User profile (private)
|
||||
mem0_client.add(
|
||||
"Sarah's goal: Run half marathon by June. Currently comfortable at 5K distance.",
|
||||
user_id="sarah",
|
||||
metadata={"type": "profile"}
|
||||
)
|
||||
|
||||
# Layer 3: Relationship (stored as user memory with agent context in metadata)
|
||||
mem0_client.add(
|
||||
"Sarah responds best to encouragement. Inside joke: 'No pain, no protein shake!'",
|
||||
user_id="sarah",
|
||||
metadata={"agent_id": "fitcoach_v1", "type": "relationship"}
|
||||
)
|
||||
|
||||
# Log today's workout
|
||||
mem0_client.add(
|
||||
"Completed 8K run in 45 minutes - new personal record!",
|
||||
user_id="sarah",
|
||||
metadata={"type": "workout", "date": "2025-01-23"}
|
||||
)
|
||||
|
||||
# Generate coaching response
|
||||
# Get Sarah's context (includes all her memories)
|
||||
sarah_context = mem0_client.search(
|
||||
"Generate coaching advice for Sarah",
|
||||
user_id="sarah"
|
||||
)
|
||||
|
||||
# Get coach personality
|
||||
coach_personality = mem0_client.search(
|
||||
"coaching personality",
|
||||
agent_id="fitcoach_v1"
|
||||
)
|
||||
|
||||
# Combine contexts
|
||||
full_context = str(coach_personality) + "\\n" + str(sarah_context)
|
||||
|
||||
response = openai_client.chat.completions.create(
|
||||
model="gpt-4",
|
||||
messages=[
|
||||
{"role": "system", "content": full_context},
|
||||
{"role": "user", "content": "Just finished my run today!"}
|
||||
]
|
||||
)
|
||||
|
||||
print(response.choices[0].message.content)
|
||||
|
||||
```
|
||||
|
||||
**Output:**
|
||||
|
||||
```
|
||||
🎉 YES! 8K is a HUGE milestone! You just crushed your previous distance!
|
||||
|
||||
Remember when you could barely do 5K? Look at you now! That half marathon
|
||||
in June is looking more achievable every single day. No pain, no protein
|
||||
shake - and today, you EARNED that shake! 💪
|
||||
|
||||
Next week, let's aim for 9K. You're ready for it!
|
||||
|
||||
```
|
||||
|
||||
The response combines:
|
||||
|
||||
- ✅ Motivational tone (agent personality)
|
||||
- ✅ Specific goal reference (Sarah's profile)
|
||||
- ✅ Inside joke (relationship memory)
|
||||
- ✅ Progress tracking (workout history)
|
||||
|
||||
---
|
||||
|
||||

|
||||
|
||||
**Three memory layers:**
|
||||
|
||||
1. **Agent memories** (blue) - Shared personality and capabilities
|
||||
2. **User memories** (red) - Private workout data and goals
|
||||
3. **Relationship memories** (purple) - User memories with agent context stored in metadata
|
||||
|
||||
---
|
||||
|
||||
## When to Use What
|
||||
|
||||
### Use **`user_id`** only (most apps)
|
||||
|
||||
**Best for:** Apps that just need to track user-specific data without AI personality
|
||||
|
||||
**Examples:**
|
||||
|
||||
- Todo lists
|
||||
- Note-taking apps
|
||||
- Personal finance trackers
|
||||
- Support ticket history
|
||||
|
||||
```python
|
||||
mem0_client.add(
|
||||
"Bought groceries for $127.43",
|
||||
user_id="sarah"
|
||||
)
|
||||
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Use **`agent_id`** only (rare)
|
||||
|
||||
**Best for:** AI tools that work the same for everyone, no user-specific data
|
||||
|
||||
**Examples:**
|
||||
|
||||
- Calculator bots
|
||||
- Language translators
|
||||
- Company policy assistants (same policies for all)
|
||||
|
||||
```python
|
||||
mem0_client.add(
|
||||
"I can calculate: arithmetic, algebra, basic calculus. I cannot solve differential equations.",
|
||||
agent_id="calculator_v1"
|
||||
)
|
||||
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Use both **`user_id`** and **`agent_id`** (AI with personality)
|
||||
|
||||
**Best for:** AI agents with persistent personalities that remember individual users
|
||||
|
||||
**Examples:**
|
||||
|
||||
- Fitness coaches (this guide!)
|
||||
- Educational tutors
|
||||
- AI companions
|
||||
- Therapy/mental health bots
|
||||
- Game NPCs with character development
|
||||
|
||||
```python
|
||||
# Agent personality (shared across all users)
|
||||
mem0_client.add(
|
||||
"Coaching personality and style",
|
||||
agent_id="agent_name"
|
||||
)
|
||||
|
||||
# User data (private)
|
||||
mem0_client.add(
|
||||
"User's goals and progress",
|
||||
user_id="user_name"
|
||||
)
|
||||
|
||||
# Relationship (user memory with agent context in metadata)
|
||||
mem0_client.add(
|
||||
"User's relationship with this specific agent",
|
||||
user_id="user_name",
|
||||
metadata={"agent_id": "agent_name", "type": "relationship"}
|
||||
)
|
||||
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
<Tip>
|
||||
**When to combine user_id + agent_id:** Use both when your AI has a consistent personality that should work the same for everyone (agent_id), while also tracking individual user data (user_id). Most personal AI assistants, coaches, and tutors fit this pattern.
|
||||
</Tip>
|
||||
|
||||
---
|
||||
|
||||
## Best Practices
|
||||
|
||||
### 1. Use clear naming conventions
|
||||
|
||||
```python
|
||||
# Good: Descriptive and versioned
|
||||
agent_id="fitcoach_v1"
|
||||
user_id="sarah_123"
|
||||
|
||||
# Bad: Generic and unclear
|
||||
agent_id="agent1"
|
||||
user_id="user_abc"
|
||||
|
||||
```
|
||||
|
||||
### 2. Tag memories with metadata
|
||||
|
||||
```python
|
||||
# For relationship memories, store agent context in metadata
|
||||
mem0_client.add(
|
||||
content,
|
||||
user_id="sarah",
|
||||
metadata={
|
||||
"agent_id": "fitcoach_v1",
|
||||
"type": "relationship",
|
||||
"version": "v1"
|
||||
}
|
||||
)
|
||||
|
||||
```
|
||||
|
||||
### 3. Test data isolation
|
||||
|
||||
Ensure users never see each other's data:
|
||||
|
||||
```python
|
||||
# Get Mike's memories
|
||||
mike_memories = mem0_client.get_all(filters={"user_id": "mike"})
|
||||
|
||||
# Get Sarah's memories
|
||||
sarah_memories = mem0_client.get_all(filters={"user_id": "sarah"})
|
||||
|
||||
# Verify no overlap
|
||||
assert len(set(mike_memories) & set(sarah_memories)) == 0, "Data leak detected!"
|
||||
|
||||
```
|
||||
|
||||
### 4. Version your agents
|
||||
|
||||
Allows A/B testing different coaching styles:
|
||||
|
||||
```python
|
||||
# Version 1: Gentle and encouraging
|
||||
mem0_client.add(
|
||||
"I'm supportive and celebrate small wins",
|
||||
agent_id="fitcoach_v1"
|
||||
)
|
||||
|
||||
# Version 2: Data-driven and metric-focused
|
||||
mem0_client.add(
|
||||
"I provide concrete metrics and percentage improvements",
|
||||
agent_id="fitcoach_v2"
|
||||
)
|
||||
|
||||
# Assign users to different versions by storing version in metadata
|
||||
mem0_client.add(
|
||||
"Sarah's workout preferences and relationship with coach",
|
||||
user_id="sarah",
|
||||
metadata={"agent_id": "fitcoach_v1"}
|
||||
)
|
||||
mem0_client.add(
|
||||
"Mike's workout preferences and relationship with coach",
|
||||
user_id="mike",
|
||||
metadata={"agent_id": "fitcoach_v2"}
|
||||
)
|
||||
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## What You Built
|
||||
|
||||
A fitness coach with three-layer memory architecture:
|
||||
|
||||
- **Agent personality (agent_id)** - Shared coaching style across all users, updated once
|
||||
- **User profiles (user_id)** - Private workout history, goals, and progress for each person
|
||||
- **Relationship memories (user_id + metadata)** - Personalized interaction preferences per user-agent pair
|
||||
- **Data isolation** - Sarah never sees Mike's workouts, guaranteed by user_id filtering
|
||||
|
||||
This pattern scales from 10 to 10,000 users without duplicating agent personality.
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
With Mem0's **`user_id`** and **`agent_id`** parameters, you can build AI agents that maintain consistent personalities across all users while remembering individual user data privately. Store relationship preferences with **`user_id`** and track agent context in metadata.
|
||||
|
||||
Most apps only need **`user_id`**. Add **`agent_id`** when your AI needs a consistent personality that evolves independently from user data—fitness coaches, tutors, therapy bots, and game NPCs all fit this pattern.
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Control What Gets Stored" icon="filter" href="/cookbooks/essentials/controlling-memory-ingestion">
|
||||
Filter low-signal conversations before they pollute long-term memory.
|
||||
</Card>
|
||||
<Card title="Organize Support Memories" icon="tag" href="/cookbooks/essentials/tagging-and-organizing-memories">
|
||||
Categorize customer context so teams can retrieve the right facts fast.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
BIN
Binary file not shown.
|
After Width: | Height: | Size: 69 KiB |
@@ -0,0 +1,361 @@
|
||||
---
|
||||
title: Choose Vector vs Graph Memory
|
||||
description: "Blend vector search with graph relationships to answer multi-hop questions."
|
||||
---
|
||||
|
||||
|
||||
Most AI agents use vector stores for RAG operations - they work great for semantic search and retrieving relevant context. But there's a gap when queries require understanding connections between entities.
|
||||
|
||||
Mem0 brings graph memory into the picture to fill this gap. In this cookbook, we'll create a company knowledge base with Mem0, using both vector and graph stores. You'll learn when each one helps along the way.
|
||||
|
||||
---
|
||||
|
||||
## Vector and Graph Stores
|
||||
|
||||
When you add a memory to Mem0, it goes into a **vector store** by default. Vector stores are excellent at semantic search - finding memories that match the meaning of your query.
|
||||
|
||||
**Graph stores** work differently. They extract **entities** (people, projects, teams) and **relationships between them** (works_with, reports_to, member_of). This lets you answer questions that need connecting information across multiple memories.
|
||||
|
||||
We will go through examples in this cookbook while building a company's knowledge base along the way.
|
||||
|
||||
---
|
||||
|
||||
## Starting Simple
|
||||
|
||||
Since we're building a company knowledge base, let's add some employee information:
|
||||
|
||||
```python
|
||||
from mem0 import MemoryClient
|
||||
|
||||
client = MemoryClient(api_key="your-api-key")
|
||||
# Add employee info
|
||||
client.add("Emma is a software engineer in Seattle", user_id="company_kb")
|
||||
client.add("David is a product manager in Austin", user_id="company_kb")
|
||||
|
||||
```
|
||||
|
||||
Now let's search for Emma's role:
|
||||
|
||||
```python
|
||||
results = client.search("What does Emma do?", filters={"user_id": "company_kb"})
|
||||
print(results['results'][0]['memory'])
|
||||
|
||||
```
|
||||
|
||||
**Output:**
|
||||
|
||||
```
|
||||
Emma is a software engineer in Seattle
|
||||
|
||||
```
|
||||
|
||||
<Info>
|
||||
**Expected output:** Vector search returned Emma's role instantly. When queries ask for facts directly stored in one memory, vector semantic search is perfect—fast and accurate.
|
||||
</Info>
|
||||
|
||||
This works perfectly. Vector search found the memory that semantically matches "What does Emma do?" and returned Emma's role.
|
||||
|
||||
---
|
||||
|
||||
## Adding Team Structure
|
||||
|
||||
Let's add some information about how the team works together:
|
||||
|
||||
```python
|
||||
client.add("Emma works with David on the mobile app redesign", user_id="company_kb")
|
||||
client.add("David reports to Rachel, who manages the design team", user_id="company_kb")
|
||||
|
||||
```
|
||||
|
||||
Now we have two pieces of information stored:
|
||||
|
||||
1. Emma works with David
|
||||
2. David reports to Rachel
|
||||
|
||||
Let's try asking something that needs both pieces:
|
||||
|
||||
```python
|
||||
results = client.search(
|
||||
"Who is Emma's teammate's manager?",
|
||||
filters={"user_id": "company_kb"}
|
||||
)
|
||||
|
||||
for r in results['results']:
|
||||
print(r['memory'])
|
||||
|
||||
```
|
||||
|
||||
**Output:**
|
||||
|
||||
```
|
||||
Emma works with David on the mobile app redesign
|
||||
David reports to Rachel, who manages the design team
|
||||
|
||||
```
|
||||
|
||||
Vector search returned both memories, but it didn't connect them. You'd need to manually figure out:
|
||||
|
||||
- Emma's teammate is David (from memory 1)
|
||||
- David's manager is Rachel (from memory 2)
|
||||
- So the answer is Rachel
|
||||
|
||||
<Warning>
|
||||
Vector search can't traverse relationships. It returns relevant memories, but you must connect the dots manually. For "Who is Emma's teammate's manager?", vector search gives you the pieces—not the answer. This breaks down as queries get more complex (3+ hops).
|
||||
</Warning>
|
||||
|
||||
---
|
||||
|
||||
## Enter Graph Memory
|
||||
|
||||
Let's add the same information with graph memory enabled:
|
||||
|
||||
```python
|
||||
client.add(
|
||||
"Emma works with David on the mobile app redesign",
|
||||
user_id="company_kb",
|
||||
enable_graph=True
|
||||
)
|
||||
|
||||
client.add(
|
||||
"David reports to Rachel, who manages the design team",
|
||||
user_id="company_kb",
|
||||
enable_graph=True
|
||||
)
|
||||
|
||||
```
|
||||
|
||||
When you set `enable_graph=True`, Mem0 extracts entities and relationships:
|
||||
|
||||
- `emma --[works_with]--> david`
|
||||
- `david --[reports_to]--> rachel`
|
||||
- `rachel --[manages]--> design_team`
|
||||
|
||||
Now the same query works differently:
|
||||
|
||||
```python
|
||||
results = client.search(
|
||||
"Who is Emma's teammate's manager?",
|
||||
filters={"user_id": "company_kb"},
|
||||
enable_graph=True
|
||||
)
|
||||
|
||||
print(results['results'][0]['memory'])
|
||||
print("\\nRelationships found:")
|
||||
for rel in results.get('relations', []):
|
||||
print(f" {rel['source']}, {rel['target']} ({rel['relationship']})")
|
||||
|
||||
```
|
||||
|
||||
**Output:**
|
||||
|
||||
```
|
||||
David reports to Rachel, who manages the design team
|
||||
|
||||
Relationships found:
|
||||
emma, david (works_with)
|
||||
david, rachel (reports_to)
|
||||
|
||||
```
|
||||
|
||||
<Info>
|
||||
**Expected behavior:** Graph memory returns the direct answer—"David reports to Rachel"—plus the relationship chain that got there. No manual connecting needed. The graph traversed: Emma → works_with → David → reports_to → Rachel.
|
||||
</Info>
|
||||
|
||||
Graph memory traversed the relationships automatically: Emma works with David, David reports to Rachel, so Rachel is the answer.
|
||||
|
||||
---
|
||||
|
||||
## How It Connects
|
||||
|
||||
Here's what the graph looks like behind the scenes:
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
Emma[Emma] -->|works_with| David[David]
|
||||
David -->|reports_to| Rachel[Rachel]
|
||||
Rachel -->|manages| DesignTeam[Design Team]
|
||||
David -->|works_on| MobileApp[Mobile App]
|
||||
Emma -->|works_on| MobileApp
|
||||
|
||||
```
|
||||
|
||||
Graph memory lets you discover relations and memories which are tricky to do with direct vector stores.
|
||||
|
||||
Vector search would need the exact words in your query to match. Graph memory follows the connections.
|
||||
|
||||
---
|
||||
|
||||
## When to Use Each
|
||||
|
||||
Use **vector store** (default) when:
|
||||
|
||||
- Searching documents by semantic similarity
|
||||
- Looking up facts that don't need relationships
|
||||
- Building FAQs or knowledge bases where each item stands alone
|
||||
|
||||
Use **graph memory** when:
|
||||
|
||||
- Tracking organizational hierarchies (who reports to whom)
|
||||
- Understanding project teams (who collaborates with whom)
|
||||
- Building CRMs (which contacts connect to which companies)
|
||||
- Product recommendations (what items are bought together)
|
||||
|
||||
For our company knowledge base, we'll use both:
|
||||
|
||||
- Vector for individual facts: "Emma specializes in React"
|
||||
- Graph for relationships: "Emma works with David"
|
||||
|
||||
---
|
||||
|
||||
## Putting It Together
|
||||
|
||||
Let's build a small company knowledge base with both approaches:
|
||||
|
||||
```python
|
||||
# Facts about individuals - vector store is fine
|
||||
client.add("Emma specializes in React and TypeScript", user_id="company_kb")
|
||||
client.add("David has 5 years of product management experience", user_id="company_kb")
|
||||
|
||||
# Relationships - use graph memory
|
||||
client.add(
|
||||
"Emma and David work together on the mobile app",
|
||||
user_id="company_kb",
|
||||
enable_graph=True
|
||||
)
|
||||
|
||||
client.add(
|
||||
"David reports to Rachel",
|
||||
user_id="company_kb",
|
||||
enable_graph=True
|
||||
)
|
||||
|
||||
client.add(
|
||||
"Rachel runs weekly team syncs every Tuesday",
|
||||
user_id="company_kb",
|
||||
enable_graph=True
|
||||
)
|
||||
|
||||
```
|
||||
|
||||
Now we can ask different types of questions:
|
||||
|
||||
```python
|
||||
# Direct fact - vector search
|
||||
results = client.search("What are Emma's skills?", filters={"user_id": "company_kb"})
|
||||
print(results['results'][0]['memory'])
|
||||
|
||||
```
|
||||
|
||||
**Output:**
|
||||
|
||||
```
|
||||
Emma specializes in React and TypeScript
|
||||
|
||||
```
|
||||
|
||||
```python
|
||||
# Multi-hop relationship - graph search
|
||||
results = client.search(
|
||||
"What meetings does Emma's project manager's boss run?",
|
||||
filters={"user_id": "company_kb"},
|
||||
enable_graph=True
|
||||
)
|
||||
print(results['results'][0]['memory'])
|
||||
|
||||
```
|
||||
|
||||
**Output:**
|
||||
|
||||
```
|
||||
Rachel runs weekly team syncs every Tuesday
|
||||
|
||||
```
|
||||
|
||||
Graph memory connected: Emma works with David, David reports to Rachel, Rachel runs team syncs.
|
||||
|
||||
<Tip>
|
||||
Enable graph memory when your queries need multi-hop traversal: org charts (who reports to whom), project teams (who collaborates), CRMs (which contacts connect to companies). For single-fact lookups, stick with vector search—it's faster and cheaper.
|
||||
</Tip>
|
||||
|
||||
---
|
||||
|
||||
## The Tradeoff
|
||||
|
||||
Graph memory adds processing time and cost. When you call `client.add()` with `enable_graph=True`, Mem0 makes extra LLM calls to extract entities and relationships.
|
||||
|
||||
<Note>
|
||||
**Cost consideration:** Graph memory extraction adds ~2-3 extra LLM calls per `add()` operation to identify entities and relationships. Use it selectively—enable graph for organizational structure and long-term relationships, skip it for temporary notes and simple facts.
|
||||
</Note>
|
||||
|
||||
Use graph memory when the relationship traversal adds real value. For most use cases, vector search is sufficient and faster.
|
||||
|
||||
```python
|
||||
# Long-term organizational structure - worth using graph
|
||||
client.add(
|
||||
"Emma mentors two junior engineers on the frontend team",
|
||||
user_id="company_kb",
|
||||
enable_graph=True
|
||||
)
|
||||
|
||||
# Temporary notes - skip graph, not worth the cost
|
||||
client.add(
|
||||
"Emma is out sick today",
|
||||
user_id="company_kb",
|
||||
run_id="daily_notes"
|
||||
)
|
||||
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Enabling Graph Memory
|
||||
|
||||
You can enable graph memory in two ways:
|
||||
|
||||
**Per-call** (recommended to start):
|
||||
|
||||
```python
|
||||
client.add("Emma works with David", user_id="company_kb", enable_graph=True)
|
||||
client.search("team structure", filters={"user_id": "company_kb"}, enable_graph=True)
|
||||
|
||||
```
|
||||
|
||||
**Project-wide** (if most of your data has relationships):
|
||||
|
||||
```python
|
||||
client.project.update(enable_graph=True)
|
||||
|
||||
# Now every add uses graph automatically
|
||||
client.add("Emma mentors Jordan", user_id="company_kb")
|
||||
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## What You Built
|
||||
|
||||
A hybrid company knowledge base that combines both architectures:
|
||||
|
||||
- **Vector search** - Fast semantic lookups for individual facts (Emma's skills, David's experience)
|
||||
- **Graph memory** - Multi-hop relationship traversal (Emma's teammate's manager, project hierarchies)
|
||||
- **Selective enablement** - Graph only for long-term organizational structure, vector for everything else
|
||||
- **Cost optimization** - Skip graph extraction for temporary notes and simple facts
|
||||
|
||||
This pattern scales from 10-person startups to enterprise org charts with thousands of employees.
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
Vector stores handle most memory operations efficiently—semantic search works great for finding relevant information. Add graph memory when your queries need to understand how entities connect across multiple hops.
|
||||
|
||||
The key is knowing which tool fits your query pattern: direct questions work with vectors, multi-hop relationship queries need graphs.
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Build AI with Personality" icon="sparkles" href="/cookbooks/essentials/building-ai-with-personality">
|
||||
Scope memories across user and agent IDs to balance personalization and reuse.
|
||||
</Card>
|
||||
<Card title="Export Everything Safely" icon="download" href="/cookbooks/essentials/exporting-memories">
|
||||
Learn how to migrate or audit stored memories with structured exports.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -0,0 +1,508 @@
|
||||
---
|
||||
title: Control Memory Ingestion
|
||||
description: "Filter speculation, enforce formats, and gate low-confidence data before it persists."
|
||||
---
|
||||
|
||||
|
||||
AI assistants plugged with memory systems face a problem - they often store everything. Not every conversation needs to be remembered, and not every detail should go to the memory store. Without proper controls, memory systems accumulate unreliable data.
|
||||
|
||||
Mem0 lets you control your memory ingestion pipeline. In this cookbook, we'll demonstrate these controls using a medical assistant example - showing how to filter unwanted data, enforce data formats, and implement confidence-based storage.
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Without controls, everything gets stored - speculation, low-confidence data, and information that shouldn't persist. This uncontrolled ingestion leads to cluttered memory and retrieval failures.
|
||||
|
||||
Mem0 provides **three tools to control** what gets stored:
|
||||
|
||||
1. **Custom instructions** define what to remember and what to ignore.
|
||||
2. **Confidence thresholds** ensure only verified facts persist.
|
||||
3. **Memory updates** let you change information without creating duplicates.
|
||||
|
||||
In this tutorial, we will:
|
||||
|
||||
- Filter speculative statements with custom instructions
|
||||
- Configure confidence thresholds for fact verification
|
||||
- Update stored information without duplication
|
||||
- Build a complete ingestion pipeline
|
||||
|
||||
---
|
||||
|
||||
## Setup
|
||||
|
||||
```python
|
||||
from mem0 import MemoryClient
|
||||
|
||||
client = MemoryClient(api_key="your-api-key")
|
||||
```
|
||||
|
||||
<Note>
|
||||
Replace `your-api-key` with your actual Mem0 API key from the [dashboard](https://app.mem0.ai). Without proper API authentication, memory operations will fail.
|
||||
</Note>
|
||||
|
||||
---
|
||||
|
||||
## The Problem
|
||||
|
||||
Uncontrolled ingestion stores everything, including speculation:
|
||||
|
||||
```python
|
||||
# Patient mentions speculation
|
||||
messages = [{"role": "user", "content": "I think I might be allergic to penicillin"}]
|
||||
client.add(messages, user_id="patient_123")
|
||||
|
||||
# Check what got stored
|
||||
results = client.search("patient allergies", filters={"user_id": "patient_123"})
|
||||
print(results['results'][0]['memory'])
|
||||
|
||||
```
|
||||
|
||||
**Output:**
|
||||
|
||||
```
|
||||
Patient is allergic to penicillin
|
||||
```
|
||||
|
||||
<Warning>
|
||||
Without custom instructions, AI assistants treat speculation as confirmed facts. "I think I might be allergic" becomes "Patient is allergic"—a dangerous transformation in sensitive domains like healthcare, legal, or financial services.
|
||||
</Warning>
|
||||
|
||||
The speculation became a confirmed fact. Let's add controls.
|
||||
|
||||
---
|
||||
|
||||
## Custom Instructions
|
||||
|
||||
Custom instructions tell Mem0 what to store and what to ignore.
|
||||
|
||||
```python
|
||||
instructions = """
|
||||
Only store CONFIRMED medical facts.
|
||||
|
||||
Store:
|
||||
- Confirmed diagnoses from doctors
|
||||
- Known allergies with documented reactions
|
||||
- Current medications being taken
|
||||
|
||||
Ignore:
|
||||
- Speculation (words like "might", "maybe", "I think")
|
||||
- Unverified symptoms
|
||||
- Casual mentions without confirmation
|
||||
"""
|
||||
|
||||
client.project.update(custom_instructions=instructions)
|
||||
|
||||
# Same speculative statement
|
||||
messages = [{"role": "user", "content": "I think I might be allergic to penicillin"}]
|
||||
client.add(messages, user_id="patient_123")
|
||||
|
||||
# Check what got stored
|
||||
results = client.get_all(filters={"user_id": "patient_123"})
|
||||
print(f"Memories stored: {len(results['results'])}")
|
||||
|
||||
```
|
||||
|
||||
**Output:**
|
||||
|
||||
```
|
||||
Memories stored: 0
|
||||
```
|
||||
|
||||
<Info>
|
||||
**Expected output:** Zero memories stored. The speculative statement "I think I might be allergic" was filtered out before reaching storage. Custom instructions are actively blocking unreliable data.
|
||||
</Info>
|
||||
|
||||
The speculation was filtered out.
|
||||
|
||||
---
|
||||
|
||||
## Designing Custom Instructions
|
||||
|
||||
When designing instructions, consider the trade-off between precision and recall:
|
||||
|
||||
**Too restrictive:** You'll miss important information (false negatives)
|
||||
|
||||
```python
|
||||
# Too strict - filters out useful context
|
||||
"""
|
||||
Only store information if explicitly stated by a doctor with full name,
|
||||
date, time, and medical license number.
|
||||
"""
|
||||
|
||||
```
|
||||
|
||||
**Too permissive:** You'll store unreliable data (false positives)
|
||||
|
||||
```python
|
||||
# Too loose - stores speculation as fact
|
||||
"""
|
||||
Store any health-related information mentioned.
|
||||
"""
|
||||
|
||||
```
|
||||
|
||||
**Balanced approach:**
|
||||
|
||||
```python
|
||||
# Clear categories with examples
|
||||
"""
|
||||
Store CONFIRMED facts:
|
||||
- Diagnoses: "Dr. Smith diagnosed hypertension on March 15th"
|
||||
- Allergies: "Patient had hives reaction to penicillin"
|
||||
- Medications: "Taking Lisinopril 10mg daily"
|
||||
|
||||
Ignore SPECULATION:
|
||||
- "I think I might have..."
|
||||
- "Maybe it's..."
|
||||
- "Could be related to..."
|
||||
"""
|
||||
|
||||
```
|
||||
|
||||
<Tip>
|
||||
Start with strict instructions (only store confirmed facts), then relax them based on your use case. It's easier to allow more data than to clean up polluted memory. Test with sample conversations before deploying to production.
|
||||
</Tip>
|
||||
|
||||
Start with clear categories and iterate based on retrieval quality.
|
||||
|
||||
---
|
||||
|
||||
## Confidence Thresholds
|
||||
|
||||
Mem0 assigns confidence scores to extracted memories. Use these to filter low-quality data.
|
||||
|
||||
### Setting Thresholds
|
||||
|
||||
Setting the right confidence threshold depends on your application:
|
||||
|
||||
- **High-stakes domains** (medical, legal): Require 0.8+ confidence
|
||||
- **General assistants**: 0.6+ confidence is often sufficient
|
||||
- **Exploratory systems**: Lower thresholds (0.4+) capture more data
|
||||
|
||||
Test your pipeline with multiple input examples and threshold combinations to find what works for your use case.
|
||||
|
||||
```python
|
||||
# Configure stricter instructions
|
||||
client.project.update(
|
||||
custom_instructions="""
|
||||
Only extract memories with HIGH confidence.
|
||||
Require specific details (dates, dosages, doctor names) for medical facts.
|
||||
Skip vague or uncertain statements.
|
||||
"""
|
||||
)
|
||||
|
||||
# Test with uncertain statement
|
||||
messages = [{"role": "user", "content": "The doctor mentioned something about my blood pressure"}]
|
||||
result1 = client.add(messages, user_id="patient_123")
|
||||
|
||||
# Test with confirmed fact
|
||||
messages = [{"role": "user", "content": "Dr. Smith diagnosed me with hypertension on March 15th"}]
|
||||
result2 = client.add(messages, user_id="patient_123")
|
||||
|
||||
print("Vague statement stored:", len(result1['results']) > 0)
|
||||
print("Confirmed fact stored:", len(result2['results']) > 0)
|
||||
|
||||
```
|
||||
|
||||
**Output:**
|
||||
|
||||
```
|
||||
Vague statement stored: False
|
||||
Confirmed fact stored: True
|
||||
```
|
||||
|
||||
<Info icon="check">
|
||||
**Expected behavior:** Low-confidence extractions are now filtered out automatically. Only verified facts with specific details (names, dates, dosages) persist in memory. The confidence threshold is working.
|
||||
</Info>
|
||||
|
||||
The vague statement was filtered for low confidence. The confirmed fact with specific details was stored.
|
||||
|
||||
---
|
||||
|
||||
## Filtering Sensitive Information
|
||||
|
||||
Custom instructions can prevent storing personal identifiers:
|
||||
|
||||
```python
|
||||
client.project.update(
|
||||
custom_instructions="""
|
||||
Medical memory rules:
|
||||
|
||||
STORE:
|
||||
- Confirmed diagnoses
|
||||
- Verified allergies
|
||||
- Current medications
|
||||
|
||||
NEVER STORE:
|
||||
- Social Security Numbers
|
||||
- Insurance policy numbers
|
||||
- Credit card information
|
||||
- Full addresses
|
||||
- Phone numbers
|
||||
|
||||
Replace identifiers with generic references if mentioned.
|
||||
"""
|
||||
)
|
||||
|
||||
# Test with PII
|
||||
messages = [
|
||||
{"role": "user", "content": "My SSN is 123-45-6789 and I'm allergic to penicillin"}
|
||||
]
|
||||
client.add(messages, user_id="patient_123")
|
||||
|
||||
# Check what was stored
|
||||
results = client.get_all(filters={"user_id": "patient_123"})
|
||||
for result in results['results']:
|
||||
print(result['memory'])
|
||||
|
||||
```
|
||||
|
||||
**Output:**
|
||||
|
||||
```
|
||||
Patient is allergic to penicillin
|
||||
```
|
||||
|
||||
The SSN was filtered out, but the allergy was stored.
|
||||
|
||||
---
|
||||
|
||||
## Updating Memories
|
||||
|
||||
When information changes, update existing memories instead of creating duplicates.
|
||||
|
||||
```python
|
||||
# Initial allergy stored
|
||||
result = client.add(
|
||||
[{"role": "user", "content": "Patient confirmed allergy to penicillin with documented hives reaction"}],
|
||||
user_id="patient_123"
|
||||
)
|
||||
|
||||
memory_id = result['results'][0]['id']
|
||||
print(f"Stored memory: {memory_id}")
|
||||
|
||||
# Later, patient gets retested - allergy was false positive
|
||||
client.update(
|
||||
memory_id=memory_id,
|
||||
text="Patient tested negative for penicillin allergy on April 2nd, 2025. Previous allergy was false positive.",
|
||||
metadata={"verified": True, "updated_date": "2025-04-02"}
|
||||
)
|
||||
|
||||
# Retrieve the updated memory
|
||||
updated = client.get(memory_id)
|
||||
print(f"\\nUpdated memory: {updated['memory']}")
|
||||
print(f"Metadata: {updated['metadata']}")
|
||||
|
||||
```
|
||||
|
||||
**Output:**
|
||||
|
||||
```
|
||||
Stored memory: mem_abc123
|
||||
|
||||
Updated memory: Patient tested negative for penicillin allergy on April 2nd, 2025. Previous allergy was false positive.
|
||||
Metadata: {'verified': True, 'updated_date': '2025-04-02'}
|
||||
|
||||
```
|
||||
|
||||
### Benefits of Updating
|
||||
|
||||
**Preserves history:**
|
||||
|
||||
- `created_at` shows when the memory was first stored
|
||||
- `updated_at` shows when it was modified
|
||||
- Audit trail for compliance
|
||||
|
||||
**Avoids conflicts:**
|
||||
|
||||
- No duplicate or contradicting memories
|
||||
- Single source of truth for each fact
|
||||
|
||||
**Maintains relationships:**
|
||||
|
||||
- If using graph memory, connections to other entities persist
|
||||
|
||||
---
|
||||
|
||||
## Update vs Delete
|
||||
|
||||
When should you update vs delete?
|
||||
|
||||
### Update when:
|
||||
|
||||
- Information changes but remains relevant
|
||||
- You need audit history
|
||||
- The memory has relationships to other data
|
||||
|
||||
```python
|
||||
# Medication dosage changed
|
||||
client.update(
|
||||
memory_id=med_id,
|
||||
text="Taking Lisinopril 20mg daily (increased from 10mg on March 1st)"
|
||||
)
|
||||
|
||||
```
|
||||
|
||||
### Delete when:
|
||||
|
||||
- Information was completely wrong
|
||||
- Memory is no longer relevant
|
||||
- Duplicate entry
|
||||
|
||||
```python
|
||||
# Duplicate entry
|
||||
client.delete(memory_id)
|
||||
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Putting It Together
|
||||
|
||||
Here's a complete ingestion pipeline with all controls:
|
||||
|
||||
```python
|
||||
from mem0 import MemoryClient
|
||||
import os
|
||||
|
||||
# Initialize client
|
||||
client = MemoryClient(api_key=os.getenv("MEM0_API_KEY"))
|
||||
|
||||
# Configure custom instructions
|
||||
client.project.update(
|
||||
custom_instructions="""
|
||||
Medical memory assistant rules:
|
||||
|
||||
STORE:
|
||||
- Confirmed diagnoses (with doctor name and date)
|
||||
- Verified allergies (with reaction details)
|
||||
- Current medications (with dosage)
|
||||
|
||||
IGNORE:
|
||||
- Speculation (might, maybe, possibly)
|
||||
- Unverified symptoms
|
||||
- Personal identifiers (SSN, insurance numbers)
|
||||
|
||||
CONFIDENCE:
|
||||
Require high confidence. Reject vague or uncertain statements.
|
||||
Require specific details: names, dates, dosages.
|
||||
"""
|
||||
)
|
||||
|
||||
# Helper function for safe ingestion
|
||||
def add_medical_memory(content, user_id, metadata=None):
|
||||
"""Add memory with automatic filtering."""
|
||||
result = client.add(
|
||||
[{"role": "user", "content": content}],
|
||||
user_id=user_id,
|
||||
metadata=metadata or {}
|
||||
)
|
||||
|
||||
if result['results']:
|
||||
print(f"✓ Stored: {result['results'][0]['memory']}")
|
||||
else:
|
||||
print(f"✗ Filtered: {content}")
|
||||
|
||||
return result
|
||||
|
||||
# Test cases
|
||||
print("Testing ingestion pipeline:\\n")
|
||||
|
||||
test_cases = [
|
||||
"I think I might be allergic to penicillin",
|
||||
"Dr. Johnson confirmed penicillin allergy on Jan 15th with hives reaction",
|
||||
"Patient SSN is 123-45-6789",
|
||||
"Currently taking Lisinopril 10mg daily for hypertension",
|
||||
"Feeling tired lately",
|
||||
"Dr. Martinez diagnosed Type 2 diabetes on February 3rd, 2025"
|
||||
]
|
||||
|
||||
for content in test_cases:
|
||||
add_medical_memory(content, user_id="patient_123")
|
||||
print()
|
||||
|
||||
```
|
||||
|
||||
**Output:**
|
||||
|
||||
```
|
||||
Testing ingestion pipeline:
|
||||
|
||||
✗ Filtered: I think I might be allergic to penicillin
|
||||
|
||||
✓ Stored: Patient has confirmed penicillin allergy diagnosed by Dr. Johnson on January 15th with hives reaction
|
||||
|
||||
✗ Filtered: Patient SSN is 123-45-6789
|
||||
|
||||
✓ Stored: Patient is currently taking Lisinopril 10mg daily for hypertension
|
||||
|
||||
✗ Filtered: Feeling tired lately
|
||||
|
||||
✓ Stored: Patient diagnosed with Type 2 diabetes by Dr. Martinez on February 3rd, 2025
|
||||
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Per-Call Instructions
|
||||
|
||||
You can override project-level instructions for specific conversations:
|
||||
|
||||
First define custom instructions
|
||||
|
||||
```python
|
||||
custom_instructions="""Emergency intake mode:Store ALL symptoms and observations immediately.
|
||||
Flag for later review and verification."""
|
||||
|
||||
```
|
||||
|
||||
```python
|
||||
# Emergency intake - store everything temporarily
|
||||
emergency_messages = [
|
||||
{"role": "user", "content": "Patient arrived with chest pain and shortness of breath"}
|
||||
]
|
||||
|
||||
client.add(
|
||||
emergency_messages,
|
||||
user_id="patient_456",
|
||||
custom_instructions=custom_instructions,
|
||||
metadata={"type": "emergency", "review_required": True}
|
||||
)
|
||||
|
||||
```
|
||||
|
||||
This is useful for:
|
||||
|
||||
- Different conversation types (emergency vs routine)
|
||||
- Channel-specific rules (phone vs in-person)
|
||||
- Temporary data collection that needs review
|
||||
|
||||
---
|
||||
|
||||
## What You Built
|
||||
|
||||
You now have a medical assistant with production-grade memory controls:
|
||||
|
||||
- **Custom instructions** - Filter speculation and enforce confirmed facts only
|
||||
- **Confidence thresholds** - Gate extractions below 0.7 confidence score
|
||||
- **Memory updates** - Modify stored information without creating duplicates
|
||||
- **Per-call instructions** - Apply temporary rules for specific conversations
|
||||
- **PII filtering** - Block sensitive data (SSNs, insurance numbers) automatically
|
||||
|
||||
These controls prevent retrieval failures and ensure your AI assistant works with reliable, verified information.
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
Start with conservative filters (only store confirmed facts) and iterate based on your application's needs. Combine custom instructions with confidence thresholds for the most reliable memory ingestion pipeline.
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Expire Short-Term Data" icon="timer" href="/cookbooks/essentials/memory-expiration-short-and-long-term">
|
||||
Automatically clean up session context before it clutters retrieval.
|
||||
</Card>
|
||||
<Card title="Choose Your Memory Architecture" icon="sitemap" href="/cookbooks/essentials/choosing-memory-architecture-vector-vs-graph">
|
||||
Learn when to layer graph memory alongside vectors for multi-hop queries.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -0,0 +1,289 @@
|
||||
---
|
||||
title: Export Stored Memories
|
||||
description: "Retrieve, review, and migrate user memories with structured exports."
|
||||
---
|
||||
|
||||
|
||||
Mem0 is a dynamic memory store that gives you full control over your data. Along with storing memories, it gives you the ability to retrieve, export, and migrate your data whenever you need.
|
||||
|
||||
This cookbook shows you how to retrieve and export your data for inspection, migration, or compliance.
|
||||
|
||||
---
|
||||
|
||||
## Setup
|
||||
|
||||
```python
|
||||
from mem0 import MemoryClient
|
||||
|
||||
client = MemoryClient(api_key="your-api-key")
|
||||
|
||||
```
|
||||
|
||||
<Note>
|
||||
Your API key needs export permissions to download memory data. Check your project settings on the [dashboard](https://app.mem0.ai) if export operations fail with authentication errors.
|
||||
</Note>
|
||||
|
||||
Let's add some sample memories to work with:
|
||||
|
||||
```python
|
||||
# Dev's work history
|
||||
client.add(
|
||||
"Dev works at TechCorp as a senior engineer",
|
||||
user_id="dev",
|
||||
metadata={"type": "professional"}
|
||||
)
|
||||
|
||||
# Arjun's preferences
|
||||
client.add(
|
||||
"Arjun prefers morning meetings and async communication",
|
||||
user_id="arjun",
|
||||
metadata={"type": "preference"}
|
||||
)
|
||||
|
||||
# Carl's project notes
|
||||
client.add(
|
||||
"Carl is leading the API redesign project, targeting Q2 launch",
|
||||
user_id="carl",
|
||||
metadata={"type": "project"}
|
||||
)
|
||||
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Getting All Memories
|
||||
|
||||
Use `get_all()` with filters to retrieve everything for a specific user:
|
||||
|
||||
```python
|
||||
dev_memories = client.get_all(
|
||||
filters={"user_id": "dev"},
|
||||
page_size=50
|
||||
)
|
||||
|
||||
print(f"Total memories: {dev_memories['count']}")
|
||||
print(f"First memory: {dev_memories['results'][0]['memory']}")
|
||||
|
||||
```
|
||||
|
||||
**Output:**
|
||||
|
||||
```
|
||||
Total memories: 1
|
||||
First memory: Dev works at TechCorp as a senior engineer
|
||||
|
||||
```
|
||||
|
||||
<Info>
|
||||
**Expected output:** `get_all()` retrieved Dev's complete memory record. This method returns everything matching your filters—no semantic search, no ranking, just raw retrieval. Perfect for exports and audits.
|
||||
</Info>
|
||||
|
||||
You can filter by metadata to get specific types:
|
||||
|
||||
```python
|
||||
carl_projects = client.get_all(
|
||||
filters={
|
||||
"AND": [
|
||||
{"user_id": "carl"},
|
||||
{"metadata": {"type": "project"}}
|
||||
]
|
||||
}
|
||||
)
|
||||
|
||||
for memory in carl_projects['results']:
|
||||
print(memory['memory'])
|
||||
|
||||
```
|
||||
|
||||
**Output:**
|
||||
|
||||
```
|
||||
Carl is leading the API redesign project, targeting Q2 launch
|
||||
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Searching Memories
|
||||
|
||||
When you need semantic search instead of retrieving everything, use `search()`:
|
||||
|
||||
```python
|
||||
results = client.search(
|
||||
query="What does Dev do for work?",
|
||||
filters={"user_id": "dev"},
|
||||
top_k=5
|
||||
)
|
||||
|
||||
for result in results['results']:
|
||||
print(f"{result['memory']} (score: {result['score']:.2f})")
|
||||
|
||||
```
|
||||
|
||||
**Output:**
|
||||
|
||||
```
|
||||
Dev works at TechCorp as a senior engineer (score: 0.89)
|
||||
|
||||
```
|
||||
|
||||
Search works across all memory fields and ranks by relevance. Use it when you have a specific question, use `get_all()` when you need everything.
|
||||
|
||||
---
|
||||
|
||||
## Exporting to Structured Format
|
||||
|
||||
For migrations or compliance, you can export memories into a structured schema using Pydantic-style JSON schemas.
|
||||
|
||||
### Step 1: Define the schema
|
||||
|
||||
```python
|
||||
professional_profile_schema = {
|
||||
"properties": {
|
||||
"full_name": {
|
||||
"type": "string",
|
||||
"description": "The person's full name"
|
||||
},
|
||||
"current_role": {
|
||||
"type": "string",
|
||||
"description": "Current job title or role"
|
||||
},
|
||||
"company": {
|
||||
"type": "string",
|
||||
"description": "Current employer"
|
||||
}
|
||||
},
|
||||
"title": "ProfessionalProfile",
|
||||
"type": "object"
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### Step 2: Create export job
|
||||
|
||||
```python
|
||||
export_job = client.create_memory_export(
|
||||
schema=professional_profile_schema,
|
||||
filters={"user_id": "dev"}
|
||||
)
|
||||
|
||||
print(f"Export ID: {export_job['id']}")
|
||||
print(f"Status: {export_job['status']}")
|
||||
|
||||
```
|
||||
|
||||
**Output:**
|
||||
|
||||
```
|
||||
Export ID: exp_abc123
|
||||
Status: processing
|
||||
|
||||
```
|
||||
|
||||
<Info>
|
||||
**Export initiated:** Status is "processing". Large exports may take a few seconds. Poll with `get_memory_export()` until status changes to "completed" before downloading data.
|
||||
</Info>
|
||||
|
||||
### Step 3: Download the export
|
||||
|
||||
```python
|
||||
# Get by ID
|
||||
export_data = client.get_memory_export(
|
||||
memory_export_id=export_job['id']
|
||||
)
|
||||
|
||||
print(export_data['data'])
|
||||
|
||||
```
|
||||
|
||||
**Output:**
|
||||
|
||||
```json
|
||||
{
|
||||
"full_name": "Dev",
|
||||
"current_role": "senior engineer",
|
||||
"company": "TechCorp"
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
You can also retrieve exports by filters:
|
||||
|
||||
```python
|
||||
# Get latest export matching filters
|
||||
export_by_filters = client.get_memory_export(
|
||||
filters={"user_id": "dev"}
|
||||
)
|
||||
|
||||
print(export_by_filters['data'])
|
||||
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Adding Export Instructions
|
||||
|
||||
Guide how Mem0 resolves conflicts or formats the export:
|
||||
|
||||
```python
|
||||
export_with_instructions = client.create_memory_export(
|
||||
schema=professional_profile_schema,
|
||||
filters={"user_id": "arjun"},
|
||||
export_instructions="""
|
||||
1. Use the most recent information if there are conflicts
|
||||
2. Only include confirmed facts, not speculation
|
||||
3. Return null for missing fields rather than guessing
|
||||
"""
|
||||
)
|
||||
|
||||
```
|
||||
|
||||
<Tip>
|
||||
Always check export status before downloading. Call `get_memory_export()` in a loop with a short delay until `status == "completed"`. Attempting to download while still processing returns incomplete data.
|
||||
</Tip>
|
||||
|
||||
---
|
||||
|
||||
## Platform Export
|
||||
|
||||
You can also export memories directly from the Mem0 platform UI:
|
||||
|
||||
1. Navigate to **Memory Exports** in your project dashboard
|
||||
2. Click **Create Export**
|
||||
3. Select your filters and schema
|
||||
4. Download the completed export as JSON
|
||||
|
||||
This is useful for one-off exports or manual data reviews.
|
||||
|
||||
<Warning>
|
||||
Exported data expires after 7 days. Download and store exports locally if you need long-term archives. After expiration, you'll need to recreate the export job.
|
||||
</Warning>
|
||||
|
||||
---
|
||||
|
||||
## What You Built
|
||||
|
||||
A complete memory export system with multiple retrieval methods:
|
||||
|
||||
- **Bulk retrieval (get_all)** - Fetch all memories matching filters for comprehensive audits
|
||||
- **Semantic search** - Query-based lookups with relevance scoring
|
||||
- **Structured exports** - Pydantic-schema exports for migrations and compliance
|
||||
- **Export instructions** - Guide conflict resolution and data formatting
|
||||
- **Platform UI exports** - One-off manual downloads via dashboard
|
||||
|
||||
This covers data portability, GDPR compliance, system migrations, and manual reviews.
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
Use **`get_all()`** for bulk retrieval, **`search()`** for specific questions, and **`create_memory_export()`** for structured data exports with custom schemas. Remember exports expire after 7 days—download them locally for long-term archives.
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Expire Short-Term Data" icon="timer" href="/cookbooks/essentials/memory-expiration-short-and-long-term">
|
||||
Keep exports lean by clearing session context before you archive it.
|
||||
</Card>
|
||||
<Card title="Control Memory Ingestion" icon="filter" href="/cookbooks/essentials/controlling-memory-ingestion">
|
||||
Ensure only verified insights make it into your export pipeline.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -0,0 +1,277 @@
|
||||
---
|
||||
title: Set Memory Expiration
|
||||
description: "Define short-term versus long-term retention so the store stays fresh."
|
||||
---
|
||||
|
||||
|
||||
While building memory systems, we realized their size grows fast. Session notes, temporary context, chat history - everything starts accumulating and bogging down the system. This pollutes search results and increase storage costs. Not every memory needs to persist forever.
|
||||
|
||||
In this cookbook, we'll go through how to use short-term vs long-term memories and see where it's best to use them.
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
By default, Mem0 memories persist forever. This works for user preferences and core facts, but temporary data should expire automatically.
|
||||
|
||||
In this tutorial, we will:
|
||||
|
||||
- Understand default (permanent) memory behavior
|
||||
- Add expiration dates for temporary memories
|
||||
- Decide what should be temporary vs permanent
|
||||
|
||||
---
|
||||
|
||||
## Setup
|
||||
|
||||
```python
|
||||
from mem0 import MemoryClient
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
client = MemoryClient(api_key="your-api-key")
|
||||
```
|
||||
|
||||
<Note>
|
||||
Import `datetime` and `timedelta` to calculate expiration dates. Without these imports, you'll need to manually format ISO timestamps—error-prone and harder to read.
|
||||
</Note>
|
||||
|
||||
---
|
||||
|
||||
## Default Behavior: Everything Persists
|
||||
|
||||
By default, all memories persist forever:
|
||||
|
||||
```python
|
||||
# Store user preference
|
||||
client.add("User prefers dark mode", user_id="sarah")
|
||||
|
||||
# Store session context
|
||||
client.add("Currently browsing electronics category", user_id="sarah")
|
||||
|
||||
# 6 months later - both still exist
|
||||
results = client.get_all(filters={"user_id": "sarah"})
|
||||
print(f"Total memories: {len(results['results'])}")
|
||||
|
||||
```
|
||||
|
||||
**Output:**
|
||||
|
||||
```
|
||||
Total memories: 2
|
||||
|
||||
```
|
||||
|
||||
Both the preference and session context persist. The preference is useful, but the 6-month-old session context is not.
|
||||
|
||||
---
|
||||
|
||||
## The Problem: Memory Bloat
|
||||
|
||||
Without expiration, memories accumulate forever. Session notes from weeks ago mix with current preferences. Storage grows, search results get polluted with irrelevant old context, and retrieval quality degrades.
|
||||
|
||||
<Warning>
|
||||
Memory bloat degrades search quality. When "User prefers dark mode" competes with "Currently browsing electronics" from 6 months ago, semantic search returns stale session data instead of actual preferences. Old memories pollute retrieval.
|
||||
</Warning>
|
||||
|
||||
---
|
||||
|
||||
## Short-Term Memories: Adding Expiration
|
||||
|
||||
Set `expiration_date` to make memories temporary:
|
||||
|
||||
```python
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
# Session context - expires in 7 days
|
||||
expires_at = (datetime.now() + timedelta(days=7)).isoformat()
|
||||
|
||||
client.add(
|
||||
"Currently browsing electronics category",
|
||||
user_id="sarah",
|
||||
expiration_date=expires_at
|
||||
)
|
||||
|
||||
# User preference - no expiration, persists forever
|
||||
client.add(
|
||||
"User prefers dark mode",
|
||||
user_id="sarah"
|
||||
)
|
||||
|
||||
```
|
||||
|
||||
<Info icon="check">
|
||||
**Expected behavior:** After 7 days, the session context automatically disappears—no cron jobs, no manual cleanup. The preference persists forever. Mem0 handles expiration transparently.
|
||||
</Info>
|
||||
|
||||
Memories with `expiration_date` are automatically removed after expiring. No cleanup job needed - Mem0 handles it.
|
||||
|
||||
<Tip>
|
||||
Start conservative with short expiration windows (7 days), then extend them based on usage patterns. It's easier to increase retention than to clean up over-retained stale data. Monitor search quality to find the right balance.
|
||||
</Tip>
|
||||
|
||||
---
|
||||
|
||||
## When to Use Each
|
||||
|
||||
### Permanent Memories (no expiration_date):
|
||||
|
||||
**Use for:**
|
||||
|
||||
- User preferences and settings
|
||||
- Account information
|
||||
- Important facts and milestones
|
||||
- Historical data that matters long-term
|
||||
|
||||
```python
|
||||
client.add("User prefers email notifications", user_id="sarah")
|
||||
client.add("User's birthday is March 15th", user_id="sarah")
|
||||
client.add("User completed onboarding on Jan 5th", user_id="sarah")
|
||||
|
||||
```
|
||||
|
||||
### Temporary Memories (with expiration_date):
|
||||
|
||||
**Use for:**
|
||||
|
||||
- Session context (current page, browsing history)
|
||||
- Temporary reminders
|
||||
- Recent chat history
|
||||
- Cached data
|
||||
|
||||
```python
|
||||
expires_7d = (datetime.now() + timedelta(days=7)).isoformat()
|
||||
|
||||
client.add(
|
||||
"Currently viewing product ABC123",
|
||||
user_id="sarah",
|
||||
expiration_date=expires_7d
|
||||
)
|
||||
|
||||
client.add(
|
||||
"Asked about return policy",
|
||||
user_id="sarah",
|
||||
expiration_date=expires_7d
|
||||
)
|
||||
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Setting Different Expiration Periods
|
||||
|
||||
Different data needs different lifetimes:
|
||||
|
||||
```python
|
||||
# Session context - 7 days
|
||||
expires_7d = (datetime.now() + timedelta(days=7)).isoformat()
|
||||
client.add("Browsing electronics", user_id="sarah", expiration_date=expires_7d)
|
||||
|
||||
# Recent chat - 30 days
|
||||
expires_30d = (datetime.now() + timedelta(days=30)).isoformat()
|
||||
client.add("User asked about warranty", user_id="sarah", expiration_date=expires_30d)
|
||||
|
||||
# Important preference - no expiration
|
||||
client.add("User prefers dark mode", user_id="sarah")
|
||||
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Using Metadata to Track Memory Types
|
||||
|
||||
Tag memories to make filtering easier:
|
||||
|
||||
```python
|
||||
expires_7d = (datetime.now() + timedelta(days=7)).isoformat()
|
||||
|
||||
# Tag session context
|
||||
client.add(
|
||||
"Browsing electronics",
|
||||
user_id="sarah",
|
||||
expiration_date=expires_7d,
|
||||
metadata={"type": "session"}
|
||||
)
|
||||
|
||||
# Tag preference
|
||||
client.add(
|
||||
"User prefers dark mode",
|
||||
user_id="sarah",
|
||||
metadata={"type": "preference"}
|
||||
)
|
||||
|
||||
# Query only preferences
|
||||
preferences = client.get_all(
|
||||
filters={
|
||||
"AND": [
|
||||
{"user_id": "sarah"},
|
||||
{"metadata": {"type": "preference"}}
|
||||
]
|
||||
}
|
||||
)
|
||||
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Checking Expiration Status
|
||||
|
||||
See which memories will expire and when:
|
||||
|
||||
```python
|
||||
results = client.get_all(filters={"user_id": "sarah"})
|
||||
|
||||
for memory in results['results']:
|
||||
exp_date = memory.get('expiration_date')
|
||||
|
||||
if exp_date:
|
||||
print(f"Temporary: {memory['memory']}")
|
||||
print(f" Expires: {exp_date}\\n")
|
||||
else:
|
||||
print(f"Permanent: {memory['memory']}\\n")
|
||||
|
||||
```
|
||||
|
||||
**Output:**
|
||||
|
||||
```
|
||||
Temporary: Browsing electronics
|
||||
Expires: 2025-11-01T10:30:00Z
|
||||
|
||||
Temporary: Viewed MacBook Pro and Dell XPS
|
||||
Expires: 2025-11-01T10:30:00Z
|
||||
|
||||
Permanent: User prefers dark mode
|
||||
|
||||
Permanent: User prefers email notifications
|
||||
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## What You Built
|
||||
|
||||
A self-cleaning memory system with automatic retention policies:
|
||||
|
||||
- **Automatic expiration** - Memories self-destruct after defined periods, no cron jobs needed
|
||||
- **Tiered retention** - 7-day session context, 30-day chat history, permanent preferences
|
||||
- **Metadata tagging** - Classify memories by type (session, preference, chat) for filtered retrieval
|
||||
- **Expiration tracking** - Check which memories will expire and when using `get_all()`
|
||||
|
||||
This pattern keeps storage costs low and search quality high as your memory store scales.
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
Memory expiration keeps storage clean and search results relevant. Use **`expiration_date`** for temporary data (session context, recent chats), skip it for permanent facts (preferences, account info). Mem0 handles cleanup automatically—no background jobs required.
|
||||
|
||||
Start by identifying what's temporary versus permanent, then set conservative expiration windows and adjust based on retrieval quality.
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Control Memory Ingestion" icon="filter" href="/cookbooks/essentials/controlling-memory-ingestion">
|
||||
Pair expirations with ingestion rules so only trusted context persists.
|
||||
</Card>
|
||||
<Card title="Export Memories Safely" icon="download" href="/cookbooks/essentials/exporting-memories">
|
||||
Build compliant archives once your retention windows are dialed in.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -0,0 +1,251 @@
|
||||
---
|
||||
title: Tag and Organize Memories
|
||||
description: "Let Mem0 auto-categorize support data so teams retrieve the right facts fast."
|
||||
---
|
||||
|
||||
|
||||
When you have large volumes of memory data, sorting it during post-processing becomes difficult. What if your memory store understood the importance of creating tags and buckets without a lot of effort?
|
||||
|
||||
Mem0 handles this for you by providing the flexibility to organize memories with custom categories. This cookbook shows you how to tag and organize memories for a customer support platform.
|
||||
|
||||
---
|
||||
|
||||
## Setup
|
||||
|
||||
```python
|
||||
from mem0 import MemoryClient
|
||||
|
||||
client = MemoryClient(api_key="your-api-key")
|
||||
```
|
||||
|
||||
<Note>
|
||||
Define custom categories at the **project level** with `client.project.update()` before adding memories. Categories apply to all future memories—Mem0 auto-assigns them based on content semantics.
|
||||
</Note>
|
||||
|
||||
---
|
||||
|
||||
## The Problem
|
||||
|
||||
Without categories, all memories sit in one undifferentiated bucket. Support agents waste time searching through everything to find billing issues, account details, or past tickets.
|
||||
|
||||
Let's see what happens without organization:
|
||||
|
||||
```python
|
||||
# Joseph (support agent) stores various customer interactions
|
||||
client.add(
|
||||
"Maria called about her account password reset",
|
||||
user_id="maria",
|
||||
)
|
||||
|
||||
client.add(
|
||||
"Maria was charged twice for last month's subscription",
|
||||
user_id="maria",
|
||||
)
|
||||
|
||||
client.add(
|
||||
"Maria wants to upgrade to the premium plan",
|
||||
user_id="maria",
|
||||
)
|
||||
|
||||
# Now try to find just billing issues
|
||||
all_memories = client.get_all(filters={"user_id": "maria"})
|
||||
print(f"Total memories: {len(all_memories['results'])}")
|
||||
|
||||
for memory in all_memories['results']:
|
||||
print(f"- {memory['memory']}")
|
||||
|
||||
```
|
||||
|
||||
**Output:**
|
||||
|
||||
```
|
||||
Total memories: 3
|
||||
- Maria called about her account password reset
|
||||
- Maria was charged twice for last month's subscription
|
||||
- Maria wants to upgrade to the premium plan
|
||||
|
||||
```
|
||||
|
||||
<Warning>
|
||||
Without categories, agents waste time reading through everything. For a customer with 100 memories, finding one billing issue means scanning all 100. Categories let you filter to exactly what you need—billing issues only, no password resets or feedback mixed in.
|
||||
</Warning>
|
||||
|
||||
Everything is mixed together. Support agents have to read through all memories to find what they need.
|
||||
|
||||
---
|
||||
|
||||
## Custom Categories
|
||||
|
||||
Define categories that match how your support team thinks about customer issues:
|
||||
|
||||
```python
|
||||
custom_categories = [
|
||||
{"support_tickets": "Customer issues and resolutions"},
|
||||
{"account_info": "Account details and preferences"},
|
||||
{"billing": "Payment history and billing questions"},
|
||||
{"product_feedback": "Feature requests and feedback"},
|
||||
]
|
||||
|
||||
client.project.update(custom_categories=custom_categories)
|
||||
|
||||
```
|
||||
|
||||
<Tip>
|
||||
Start with 3-5 clear categories that match how your team thinks. Too many categories dilute auto-tagging accuracy. Add more later if needed—it's easier to expand than to fix over-complicated classification.
|
||||
</Tip>
|
||||
|
||||
These categories are now available project-wide. Every memory can be tagged with one or more categories.
|
||||
|
||||
---
|
||||
|
||||
## Tagging Memories
|
||||
|
||||
Once categories are defined at the project level, Mem0 automatically assigns them based on content:
|
||||
|
||||
```python
|
||||
# Billing issue - automatically tagged as "billing"
|
||||
client.add(
|
||||
"Maria was charged twice for last month's subscription",
|
||||
user_id="maria",
|
||||
metadata={"priority": "high", "source": "phone_call"}
|
||||
)
|
||||
|
||||
# Account update - automatically tagged as "account_info"
|
||||
client.add(
|
||||
"Maria changed her email to maria.new@example.com",
|
||||
user_id="maria",
|
||||
metadata={"source": "web_portal"}
|
||||
)
|
||||
|
||||
# Product feedback - automatically tagged as "product_feedback"
|
||||
client.add(
|
||||
"Maria requested a dark mode feature for the dashboard",
|
||||
user_id="maria",
|
||||
metadata={"source": "chat"}
|
||||
)
|
||||
|
||||
```
|
||||
|
||||
Mem0 reads the content and intelligently assigns the appropriate categories. You don't manually tag - the platform does it for you based on the category definitions.
|
||||
|
||||
---
|
||||
|
||||
## Retrieving by Category
|
||||
|
||||
Filter memories by category to find exactly what you need:
|
||||
|
||||
```python
|
||||
# Joseph needs to pull all billing issues for audit
|
||||
billing_issues = client.get_all(
|
||||
filters={
|
||||
"AND": [
|
||||
{"user_id": "maria"},
|
||||
{"categories": {"in": ["billing"]}}
|
||||
]
|
||||
}
|
||||
)
|
||||
|
||||
print("Billing issues:")
|
||||
for memory in billing_issues['results']:
|
||||
print(f"- {memory['memory']}")
|
||||
|
||||
```
|
||||
|
||||
**Output:**
|
||||
|
||||
```
|
||||
Billing issues:
|
||||
- Maria was charged twice for last month's subscription
|
||||
|
||||
```
|
||||
|
||||
<Info icon="check">
|
||||
**Expected output:** Only the billing issue returned—no password reset, no upgrade request. Category filtering worked. Joseph can audit billing without reading through unrelated support tickets.
|
||||
</Info>
|
||||
|
||||
Only billing-related memories are returned. No need to filter through account updates or feedback.
|
||||
|
||||
You can also retrieve multiple categories:
|
||||
|
||||
```python
|
||||
# Get both account info and billing
|
||||
account_and_billing = client.get_all(
|
||||
filters={
|
||||
"AND": [
|
||||
{"user_id": "maria"},
|
||||
{"categories": {"in": ["account_info", "billing"]}}
|
||||
]
|
||||
}
|
||||
)
|
||||
|
||||
for memory in account_and_billing['results']:
|
||||
print(f"[{memory['categories'][0]}] {memory['memory']}")
|
||||
|
||||
```
|
||||
|
||||
**Output:**
|
||||
|
||||
```
|
||||
[account_info] Maria changed her email to maria.new@example.com
|
||||
[billing] Maria was charged twice for last month's subscription
|
||||
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Updating Categories
|
||||
|
||||
Categories are automatically assigned based on content. To trigger re-categorization, update the memory content:
|
||||
|
||||
```python
|
||||
# Find memories that need re-categorization
|
||||
needs_update = client.get_all(
|
||||
filters={
|
||||
"AND": [
|
||||
{"user_id": "maria"},
|
||||
{"categories": {"in": ["misc"]}}
|
||||
]
|
||||
}
|
||||
)
|
||||
|
||||
# Update memory content to trigger re-categorization
|
||||
for memory in needs_update['results']:
|
||||
client.update(
|
||||
memory_id=memory['id'],
|
||||
data=memory['memory'] # Re-process with current category definitions
|
||||
)
|
||||
|
||||
```
|
||||
|
||||
When you update a memory, Mem0 re-analyzes it against your current category definitions. This is useful when you introduce new categories or refine category descriptions.
|
||||
|
||||
---
|
||||
|
||||
## What You Built
|
||||
|
||||
A customer support platform with intelligent memory organization:
|
||||
|
||||
- **Project-wide categories** - Support tickets, billing, account info, and product feedback auto-classified
|
||||
- **Automatic tagging** - Mem0 assigns categories based on content semantics, no manual tagging
|
||||
- **Filtered retrieval** - Pull only billing issues or only account updates using `categories: {in: [...]}`
|
||||
- **Re-categorization** - Update memory content to trigger re-analysis against new category definitions
|
||||
- **Multi-category support** - Memories can belong to multiple categories when appropriate
|
||||
|
||||
This pattern scales from 10 customers to 10,000 without degrading retrieval speed.
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
Categories make retrieval faster and compliance easier. Define 3-5 clear categories with `client.project.update()`, let Mem0 auto-assign them based on content, then filter with `categories: {in: [...]}` to pull exactly what you need.
|
||||
|
||||
Instead of searching through everything, agents jump directly to the information type they need—billing issues, account details, or support tickets.
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Control Memory Ingestion" icon="filter" href="/cookbooks/essentials/controlling-memory-ingestion">
|
||||
Keep categories meaningful by filtering noise before it lands in storage.
|
||||
</Card>
|
||||
<Card title="Export Tagged Memories" icon="download" href="/cookbooks/essentials/exporting-memories">
|
||||
Use categories to drive audits, migrations, and compliance reports.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -0,0 +1,70 @@
|
||||
---
|
||||
title: Chrome Extension with Mem0
|
||||
description: "Add Mem0's universal memory layer to Chrome chat surfaces."
|
||||
---
|
||||
|
||||
|
||||
Enhance your AI interactions with Mem0, a Chrome extension that introduces a universal memory layer across platforms like ChatGPT, Claude, and Perplexity. Mem0 ensures seamless context sharing, making your AI experiences more personalized and efficient.
|
||||
|
||||
<Note>
|
||||
We now support Grok! The Mem0 Chrome Extension has been updated to work with Grok, bringing the same powerful memory capabilities to your Grok conversations.
|
||||
</Note>
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
- **Universal Memory Layer**: Share context seamlessly across ChatGPT, Claude, Perplexity, and Grok.
|
||||
- **Smart Context Detection**: Automatically captures relevant information from your conversations.
|
||||
- **Intelligent Memory Retrieval**: Surfaces pertinent memories at the right time.
|
||||
- **One-Click Sync**: Easily synchronize with existing ChatGPT memories.
|
||||
- **Memory Dashboard**: Manage all your memories in one centralized location.
|
||||
|
||||
## Installation
|
||||
|
||||
You can install the Mem0 Chrome Extension using one of the following methods:
|
||||
|
||||
### Method 1: Chrome Web Store Installation
|
||||
|
||||
1. **Download the Extension**: Open Google Chrome and navigate to the [Mem0 Chrome Extension page](https://chromewebstore.google.com/detail/mem0/onihkkbipkfeijkadecaafbgagkhglop?hl=en).
|
||||
2. **Add to Chrome**: Click on the "Add to Chrome" button.
|
||||
3. **Confirm Installation**: In the pop-up dialog, click "Add extension" to confirm. The Mem0 icon should now appear in your Chrome toolbar.
|
||||
|
||||
### Method 2: Manual Installation
|
||||
|
||||
1. **Download the Extension**: Clone or download the extension files from the [Mem0 Chrome Extension GitHub repository](https://github.com/mem0ai/mem0-chrome-extension).
|
||||
2. **Access Chrome Extensions**: Open Google Chrome and navigate to `chrome://extensions`.
|
||||
3. **Enable Developer Mode**: Toggle the "Developer mode" switch in the top right corner.
|
||||
4. **Load Unpacked Extension**: Click "Load unpacked" and select the directory containing the extension files.
|
||||
5. **Confirm Installation**: The Mem0 Chrome Extension should now appear in your Chrome toolbar.
|
||||
|
||||
## Usage
|
||||
|
||||
1. **Locate the Mem0 Icon**: After installation, find the Mem0 icon in your Chrome toolbar.
|
||||
2. **Sign In**: Click the icon and sign in with your Google account.
|
||||
3. **Interact with AI Assistants**:
|
||||
- **ChatGPT and Perplexity**: Continue your conversations as usual; Mem0 operates seamlessly in the background.
|
||||
- **Claude**: Click the Mem0 button or use the shortcut `Ctrl + M` to activate memory functions.
|
||||
|
||||
## Configuration
|
||||
|
||||
- **API Key**: Obtain your API key from the Mem0 Dashboard to connect the extension to the Mem0 API.
|
||||
- **User ID**: This is your unique identifier in the Mem0 system. If not provided, it defaults to `chrome-extension-user`.
|
||||
|
||||
## Demo Video
|
||||
|
||||
<iframe width="700" height="400" src="https://www.youtube.com/embed/dqenCMMlfwQ?si=zhGVrkq6IS_0Jwyj" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
|
||||
|
||||
## Privacy and Data Security
|
||||
|
||||
Your messages are sent to the Mem0 API for extracting and retrieving memories. Mem0 is committed to ensuring your data's privacy and security.
|
||||
|
||||
---
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Build a Mem0 Companion" icon="users" href="/cookbooks/essentials/building-ai-companion">
|
||||
Learn the foundations of memory-powered assistants that work across platforms.
|
||||
</Card>
|
||||
<Card title="Multimodal Support" icon="image" href="/platform/features/multimodal-support">
|
||||
Extend your browser interactions with vision and audio memory.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -0,0 +1,85 @@
|
||||
---
|
||||
title: Eliza OS Character with Mem0
|
||||
description: "Bring persistent personality to Eliza OS agents using Mem0."
|
||||
---
|
||||
|
||||
|
||||
You can create a personalized Eliza OS Character using Mem0. This guide will walk you through the necessary steps and provide the complete code to get you started.
|
||||
|
||||
## Overview
|
||||
|
||||
ElizaOS is a powerful AI agent framework for autonomy and personality. It is a collection of tools that help you create a personalized AI agent.
|
||||
|
||||
## Setup
|
||||
|
||||
You can start by cloning the eliza-os repository:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/elizaOS/eliza.git
|
||||
```
|
||||
|
||||
Change the directory to the eliza-os repository:
|
||||
|
||||
```bash
|
||||
cd eliza
|
||||
```
|
||||
|
||||
Install the dependencies:
|
||||
|
||||
```bash
|
||||
pnpm install
|
||||
```
|
||||
|
||||
Build the project:
|
||||
|
||||
```bash
|
||||
pnpm build
|
||||
```
|
||||
|
||||
## Setup ENVs
|
||||
|
||||
Create a `.env` file in the root of the project and add the following (you can use the `.env.example` file as a reference):
|
||||
|
||||
```bash
|
||||
# Mem0 Configuration
|
||||
MEM0_API_KEY= # Mem0 API Key (get from https://app.mem0.ai/dashboard/api-keys)
|
||||
MEM0_USER_ID= # Default: eliza-os-user
|
||||
MEM0_PROVIDER= # Default: openai
|
||||
MEM0_PROVIDER_API_KEY= # API Key for the provider (OpenAI, Anthropic, etc.)
|
||||
SMALL_MEM0_MODEL= # Default: gpt-4.1-nano
|
||||
MEDIUM_MEM0_MODEL= # Default: gpt-4o
|
||||
LARGE_MEM0_MODEL= # Default: gpt-4o
|
||||
```
|
||||
|
||||
## Make the default character use Mem0
|
||||
|
||||
By default, there is a character called `eliza` that uses the Ollama model. You can make this character use Mem0 by changing the config in the `agent/src/defaultCharacter.ts` file.
|
||||
|
||||
```ts
|
||||
modelProvider: ModelProviderName.MEM0,
|
||||
```
|
||||
|
||||
This will make the character use Mem0 to generate responses.
|
||||
|
||||
## Run the project
|
||||
|
||||
```bash
|
||||
pnpm start
|
||||
```
|
||||
|
||||
## Conclusion
|
||||
|
||||
You have now created a personalized Eliza OS Character using Mem0. You can now start interacting with the character by running the project and talking to the character.
|
||||
|
||||
This is a simple example of how to use Mem0 to create a personalized AI agent. You can use this as a starting point to create your own AI agent.
|
||||
|
||||
---
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Build AI with Personality" icon="sparkles" href="/cookbooks/essentials/building-ai-with-personality">
|
||||
Separate agent and user memories to maintain consistent character personalities.
|
||||
</Card>
|
||||
<Card title="AI Tutor with Mem0" icon="graduation-cap" href="/cookbooks/companions/ai-tutor">
|
||||
Build another type of personalized companion with memory capabilities.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -0,0 +1,371 @@
|
||||
---
|
||||
title: LlamaIndex Multi-Agent with Mem0
|
||||
description: "Share a persistent memory layer across collaborating LlamaIndex agents."
|
||||
---
|
||||
|
||||
|
||||
<Snippet file="blank-notif.mdx" />
|
||||
|
||||
Build an intelligent multi-agent learning system that uses Mem0 to maintain persistent memory across multiple specialized agents. This example demonstrates how to create a tutoring system where different agents collaborate while sharing a unified memory layer.
|
||||
|
||||
## Overview
|
||||
|
||||
This example showcases a **Multi-Agent Personal Learning System** that combines:
|
||||
- **LlamaIndex AgentWorkflow** for multi-agent orchestration
|
||||
- **Mem0** for persistent, shared memory across agents
|
||||
- **Multiple agents** that collaborate on teaching tasks
|
||||
|
||||
The system consists of two agents:
|
||||
- **TutorAgent**: Primary instructor for explanations and concept teaching
|
||||
- **PracticeAgent**: Generates exercises and tracks learning progress
|
||||
|
||||
Both agents share the same memory context, enabling seamless collaboration and continuous learning from student interactions.
|
||||
|
||||
## Key Features
|
||||
|
||||
- **Persistent Memory**: Agents remember previous interactions across sessions
|
||||
- **Multi-Agent Collaboration**: Agents can hand off tasks to each other
|
||||
- **Personalized Learning**: Adapts to individual student needs and learning styles
|
||||
- **Progress Tracking**: Monitors learning patterns and skill development
|
||||
- **Memory-Driven Teaching**: References past struggles and successes
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Install the required packages:
|
||||
|
||||
```bash
|
||||
pip install llama-index-core llama-index-memory-mem0 openai python-dotenv
|
||||
```
|
||||
|
||||
Set up your environment variables:
|
||||
- `MEM0_API_KEY`: Your Mem0 Platform API key
|
||||
- `OPENAI_API_KEY`: Your OpenAI API key
|
||||
|
||||
You can obtain your Mem0 Platform API key from the [Mem0 Platform](https://app.mem0.ai).
|
||||
|
||||
## Complete Implementation
|
||||
|
||||
```python
|
||||
"""
|
||||
Multi-Agent Personal Learning System: Mem0 + LlamaIndex AgentWorkflow Example
|
||||
|
||||
INSTALLATIONS:
|
||||
!pip install llama-index-core llama-index-memory-mem0 openai
|
||||
|
||||
You need MEM0_API_KEY and OPENAI_API_KEY to run the example.
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
from datetime import datetime
|
||||
from dotenv import load_dotenv
|
||||
|
||||
# LlamaIndex imports
|
||||
from llama_index.core.agent.workflow import AgentWorkflow, FunctionAgent
|
||||
from llama_index.llms.openai import OpenAI
|
||||
from llama_index.core.tools import FunctionTool
|
||||
|
||||
# Memory integration
|
||||
from llama_index.memory.mem0 import Mem0Memory
|
||||
|
||||
import warnings
|
||||
warnings.filterwarnings("ignore", category=DeprecationWarning)
|
||||
|
||||
load_dotenv()
|
||||
|
||||
|
||||
class MultiAgentLearningSystem:
|
||||
"""
|
||||
Multi-Agent Architecture:
|
||||
- TutorAgent: Main teaching and explanations
|
||||
- PracticeAgent: Exercises and skill reinforcement
|
||||
- Shared Memory: Both agents learn from student interactions
|
||||
"""
|
||||
|
||||
def __init__(self, student_id: str):
|
||||
self.student_id = student_id
|
||||
self.llm = OpenAI(model="gpt-4.1-nano-2025-04-14", temperature=0.2)
|
||||
|
||||
# Memory context for this student
|
||||
self.memory_context = {"user_id": student_id, "app": "learning_assistant"}
|
||||
self.memory = Mem0Memory.from_client(
|
||||
context=self.memory_context
|
||||
)
|
||||
|
||||
self._setup_agents()
|
||||
|
||||
def _setup_agents(self):
|
||||
"""Setup two agents that work together and share memory"""
|
||||
|
||||
# TOOLS
|
||||
async def assess_understanding(topic: str, student_response: str) -> str:
|
||||
"""Assess student's understanding of a topic and save insights"""
|
||||
# Simulate assessment logic
|
||||
if "confused" in student_response.lower() or "don't understand" in student_response.lower():
|
||||
assessment = f"STRUGGLING with {topic}: {student_response}"
|
||||
insight = f"Student needs more help with {topic}. Prefers step-by-step explanations."
|
||||
elif "makes sense" in student_response.lower() or "got it" in student_response.lower():
|
||||
assessment = f"UNDERSTANDS {topic}: {student_response}"
|
||||
insight = f"Student grasped {topic} quickly. Can move to advanced concepts."
|
||||
else:
|
||||
assessment = f"PARTIAL understanding of {topic}: {student_response}"
|
||||
insight = f"Student has basic understanding of {topic}. Needs reinforcement."
|
||||
|
||||
return f"Assessment: {assessment}\nInsight saved: {insight}"
|
||||
|
||||
async def track_progress(topic: str, success_rate: str) -> str:
|
||||
"""Track learning progress and identify patterns"""
|
||||
progress_note = f"Progress on {topic}: {success_rate} - {datetime.now().strftime('%Y-%m-%d')}"
|
||||
return f"Progress tracked: {progress_note}"
|
||||
|
||||
# Convert to FunctionTools
|
||||
tools = [
|
||||
FunctionTool.from_defaults(async_fn=assess_understanding),
|
||||
FunctionTool.from_defaults(async_fn=track_progress)
|
||||
]
|
||||
|
||||
# AGENTS
|
||||
# Tutor Agent - Main teaching and explanation
|
||||
self.tutor_agent = FunctionAgent(
|
||||
name="TutorAgent",
|
||||
description="Primary instructor that explains concepts and adapts to student needs",
|
||||
system_prompt="""
|
||||
You are a patient, adaptive programming tutor. Your key strength is REMEMBERING and BUILDING on previous interactions.
|
||||
|
||||
Key Behaviors:
|
||||
1. Always check what the student has learned before (use memory context)
|
||||
2. Adapt explanations based on their preferred learning style
|
||||
3. Reference previous struggles or successes
|
||||
4. Build progressively on past lessons
|
||||
5. Use assess_understanding to evaluate responses and save insights
|
||||
|
||||
MEMORY-DRIVEN TEACHING:
|
||||
- "Last time you struggled with X, so let's approach Y differently..."
|
||||
- "Since you prefer visual examples, here's a diagram..."
|
||||
- "Building on the functions we covered yesterday..."
|
||||
|
||||
When student shows understanding, hand off to PracticeAgent for exercises.
|
||||
""",
|
||||
tools=tools,
|
||||
llm=self.llm,
|
||||
can_handoff_to=["PracticeAgent"]
|
||||
)
|
||||
|
||||
# Practice Agent - Exercises and reinforcement
|
||||
self.practice_agent = FunctionAgent(
|
||||
name="PracticeAgent",
|
||||
description="Creates practice exercises and tracks progress based on student's learning history",
|
||||
system_prompt="""
|
||||
You create personalized practice exercises based on the student's learning history and current level.
|
||||
|
||||
Key Behaviors:
|
||||
1. Generate problems that match their skill level (from memory)
|
||||
2. Focus on areas they've struggled with previously
|
||||
3. Gradually increase difficulty based on their progress
|
||||
4. Use track_progress to record their performance
|
||||
5. Provide encouraging feedback that references their growth
|
||||
|
||||
MEMORY-DRIVEN PRACTICE:
|
||||
- "Let's practice loops again since you wanted more examples..."
|
||||
- "Here's a harder version of the problem you solved yesterday..."
|
||||
- "You've improved a lot in functions, ready for the next level?"
|
||||
|
||||
After practice, can hand back to TutorAgent for concept review if needed.
|
||||
""",
|
||||
tools=tools,
|
||||
llm=self.llm,
|
||||
can_handoff_to=["TutorAgent"]
|
||||
)
|
||||
|
||||
# Create the multi-agent workflow
|
||||
self.workflow = AgentWorkflow(
|
||||
agents=[self.tutor_agent, self.practice_agent],
|
||||
root_agent=self.tutor_agent.name,
|
||||
initial_state={
|
||||
"current_topic": "",
|
||||
"student_level": "beginner",
|
||||
"learning_style": "unknown",
|
||||
"session_goals": []
|
||||
}
|
||||
)
|
||||
|
||||
async def start_learning_session(self, topic: str, student_message: str = "") -> str:
|
||||
"""
|
||||
Start a learning session with multi-agent memory-aware teaching
|
||||
"""
|
||||
|
||||
if student_message:
|
||||
request = f"I want to learn about {topic}. {student_message}"
|
||||
else:
|
||||
request = f"I want to learn about {topic}."
|
||||
|
||||
# The magic happens here - multi-agent memory is automatically shared!
|
||||
response = await self.workflow.run(
|
||||
user_msg=request,
|
||||
memory=self.memory
|
||||
)
|
||||
|
||||
return str(response)
|
||||
|
||||
async def get_learning_history(self) -> str:
|
||||
"""Show what the system remembers about this student"""
|
||||
try:
|
||||
# Search memory for learning patterns
|
||||
memories = self.memory.search(
|
||||
user_id=self.student_id,
|
||||
query="learning machine learning"
|
||||
)
|
||||
|
||||
if memories and memories.get('results'):
|
||||
history = "\n".join(f"- {m['memory']}" for m in memories['results'])
|
||||
return history
|
||||
else:
|
||||
return "No learning history found yet. Let's start building your profile!"
|
||||
|
||||
except Exception as e:
|
||||
return f"Memory retrieval error: {str(e)}"
|
||||
|
||||
|
||||
async def run_learning_agent():
|
||||
|
||||
learning_system = MultiAgentLearningSystem(student_id="Alexander")
|
||||
|
||||
# First session
|
||||
print("Session 1:")
|
||||
response = await learning_system.start_learning_session(
|
||||
"Vision Language Models",
|
||||
"I'm new to machine learning but I have good hold on Python and have 4 years of work experience.")
|
||||
print(response)
|
||||
|
||||
# Second session - multi-agent memory will remember the first
|
||||
print("\nSession 2:")
|
||||
response2 = await learning_system.start_learning_session(
|
||||
"Machine Learning", "what all did I cover so far?")
|
||||
print(response2)
|
||||
|
||||
# Show what the multi-agent system remembers
|
||||
print("\nLearning History:")
|
||||
history = await learning_system.get_learning_history()
|
||||
print(history)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
"""Run the example"""
|
||||
print("Multi-agent Learning System powered by LlamaIndex and Mem0")
|
||||
|
||||
async def main():
|
||||
await run_learning_agent()
|
||||
|
||||
asyncio.run(main())
|
||||
```
|
||||
|
||||
## How It Works
|
||||
|
||||
### 1. Memory Context Setup
|
||||
|
||||
```python
|
||||
# Memory context for this student
|
||||
self.memory_context = {"user_id": student_id, "app": "learning_assistant"}
|
||||
self.memory = Mem0Memory.from_client(context=self.memory_context)
|
||||
```
|
||||
|
||||
The memory context identifies the specific student and application, ensuring memory isolation and proper retrieval.
|
||||
|
||||
### 2. Agent Collaboration
|
||||
|
||||
```python
|
||||
# Agents can hand off to each other
|
||||
can_handoff_to=["PracticeAgent"] # TutorAgent can hand off to PracticeAgent
|
||||
can_handoff_to=["TutorAgent"] # PracticeAgent can hand off back
|
||||
```
|
||||
|
||||
Agents collaborate seamlessly, with the TutorAgent handling explanations and the PracticeAgent managing exercises.
|
||||
|
||||
### 3. Shared Memory
|
||||
|
||||
```python
|
||||
# Both agents share the same memory instance
|
||||
response = await self.workflow.run(
|
||||
user_msg=request,
|
||||
memory=self.memory # Shared across all agents
|
||||
)
|
||||
```
|
||||
|
||||
All agents in the workflow share the same memory context, enabling true collaborative learning.
|
||||
|
||||
### 4. Memory-Driven Interactions
|
||||
|
||||
The system prompts guide agents to:
|
||||
- Reference previous learning sessions
|
||||
- Adapt to discovered learning styles
|
||||
- Build progressively on past lessons
|
||||
- Track and respond to learning patterns
|
||||
|
||||
## Running the Example
|
||||
|
||||
```python
|
||||
# Initialize the learning system
|
||||
learning_system = MultiAgentLearningSystem(student_id="Alexander")
|
||||
|
||||
# Start a learning session
|
||||
response = await learning_system.start_learning_session(
|
||||
"Vision Language Models",
|
||||
"I'm new to machine learning but I have good hold on Python and have 4 years of work experience."
|
||||
)
|
||||
|
||||
# Continue learning in a new session (memory persists)
|
||||
response2 = await learning_system.start_learning_session(
|
||||
"Machine Learning",
|
||||
"what all did I cover so far?"
|
||||
)
|
||||
|
||||
# Check learning history
|
||||
history = await learning_system.get_learning_history()
|
||||
```
|
||||
|
||||
## Expected Output
|
||||
|
||||
The system will demonstrate memory-aware interactions:
|
||||
|
||||
```
|
||||
Session 1:
|
||||
I understand you want to learn about Vision Language Models and you mentioned you're new to machine learning but have a strong Python background with 4 years of experience. That's a great foundation to build on!
|
||||
|
||||
Let me start with an explanation tailored to your programming background...
|
||||
[Agent provides explanation and may hand off to PracticeAgent for exercises]
|
||||
|
||||
Session 2:
|
||||
Based on our previous session, I remember we covered Vision Language Models and I noted that you have a strong Python background with 4 years of experience. You mentioned being new to machine learning, so we started with foundational concepts...
|
||||
[Agent references previous session and builds upon it]
|
||||
```
|
||||
|
||||
## Key Benefits
|
||||
|
||||
1. **Persistent Learning**: Agents remember across sessions, creating continuity
|
||||
2. **Collaborative Teaching**: Multiple specialized agents work together seamlessly
|
||||
3. **Personalized Adaptation**: System learns and adapts to individual learning styles
|
||||
4. **Scalable Architecture**: Easy to add more specialized agents
|
||||
5. **Memory Efficiency**: Shared memory prevents duplication and ensures consistency
|
||||
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Clear Agent Roles**: Define specific responsibilities for each agent
|
||||
2. **Memory Context**: Use descriptive context for memory isolation
|
||||
3. **Handoff Strategy**: Design clear handoff criteria between agents
|
||||
4. **Memory Hygiene**: Regularly review and clean memory for optimal performance
|
||||
|
||||
## Help & Resources
|
||||
|
||||
- [LlamaIndex Agent Workflows](https://docs.llamaindex.ai/en/stable/use_cases/agents/)
|
||||
- [Mem0 Platform](https://app.mem0.ai/)
|
||||
|
||||
---
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="LlamaIndex ReAct with Mem0" icon="brain" href="/cookbooks/frameworks/llamaindex-react">
|
||||
Start with single-agent patterns before scaling to multi-agent systems.
|
||||
</Card>
|
||||
<Card title="Build AI with Personality" icon="sparkles" href="/cookbooks/essentials/building-ai-with-personality">
|
||||
Learn how to scope memories across multiple agents and users.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -0,0 +1,199 @@
|
||||
---
|
||||
title: LlamaIndex ReAct with Mem0
|
||||
description: "Teach a ReAct agent to store and recall context via Mem0."
|
||||
---
|
||||
|
||||
|
||||
Create a ReAct Agent with LlamaIndex which uses Mem0 as the memory store.
|
||||
|
||||
## Overview
|
||||
|
||||
A ReAct agent combines reasoning and action capabilities, making it versatile for tasks requiring both thought processes (reasoning) and interaction with tools or APIs (acting). Mem0 as memory enhances these capabilities by allowing the agent to store and retrieve contextual information from past interactions.
|
||||
|
||||
## Setup
|
||||
|
||||
```bash
|
||||
pip install llama-index-core llama-index-memory-mem0
|
||||
```
|
||||
|
||||
Initialize the LLM.
|
||||
```python
|
||||
import os
|
||||
from llama_index.llms.openai import OpenAI
|
||||
|
||||
os.environ["OPENAI_API_KEY"] = "<your-openai-api-key>"
|
||||
llm = OpenAI(model="gpt-4.1-nano-2025-04-14")
|
||||
```
|
||||
|
||||
Initialize the Mem0 client. You can find your API key [here](https://app.mem0.ai/dashboard/api-keys). Read about Mem0 [Open Source](https://docs.mem0.ai/open-source/overview).
|
||||
```python
|
||||
os.environ["MEM0_API_KEY"] = "<your-mem0-api-key>"
|
||||
|
||||
from llama_index.memory.mem0 import Mem0Memory
|
||||
|
||||
context = {"user_id": "david"}
|
||||
memory_from_client = Mem0Memory.from_client(
|
||||
context=context,
|
||||
api_key=os.environ["MEM0_API_KEY"],
|
||||
search_msg_limit=4, # optional, default is 5
|
||||
)
|
||||
```
|
||||
|
||||
Create the tools. These tools will be used by the agent to perform actions.
|
||||
```python
|
||||
from llama_index.core.tools import FunctionTool
|
||||
|
||||
def call_fn(name: str):
|
||||
"""Call the provided name.
|
||||
Args:
|
||||
name: str (Name of the person)
|
||||
"""
|
||||
return f"Calling... {name}"
|
||||
|
||||
def email_fn(name: str):
|
||||
"""Email the provided name.
|
||||
Args:
|
||||
name: str (Name of the person)
|
||||
"""
|
||||
return f"Emailing... {name}"
|
||||
|
||||
def order_food(name: str, dish: str):
|
||||
"""Order food for the provided name.
|
||||
Args:
|
||||
name: str (Name of the person)
|
||||
dish: str (Name of the dish)
|
||||
"""
|
||||
return f"Ordering {dish} for {name}"
|
||||
|
||||
call_tool = FunctionTool.from_defaults(fn=call_fn)
|
||||
email_tool = FunctionTool.from_defaults(fn=email_fn)
|
||||
order_food_tool = FunctionTool.from_defaults(fn=order_food)
|
||||
```
|
||||
|
||||
Initialize the agent with tools and memory.
|
||||
|
||||
```python
|
||||
from llama_index.core.agent import FunctionCallingAgent
|
||||
|
||||
agent = FunctionCallingAgent.from_tools(
|
||||
[call_tool, email_tool, order_food_tool],
|
||||
llm=llm,
|
||||
memory=memory_from_client, # or memory_from_config
|
||||
verbose=True,
|
||||
)
|
||||
```
|
||||
|
||||
Start the chat.
|
||||
|
||||
<Note>The agent will use Mem0 to store the relevant memories from the chat.</Note>
|
||||
|
||||
**Input**
|
||||
```python
|
||||
response = agent.chat("Hi, My name is David")
|
||||
print(response)
|
||||
```
|
||||
|
||||
**Output**
|
||||
```text
|
||||
> Running step bf44a75a-a920-4cf3-944e-b6e6b5695043. Step input: Hi, My name is David
|
||||
Added user message to memory: Hi, My name is David
|
||||
=== LLM Response ===
|
||||
Hello, David! How can I assist you today?
|
||||
```
|
||||
|
||||
**Input**
|
||||
```python
|
||||
response = agent.chat("I love to eat pizza on weekends")
|
||||
print(response)
|
||||
```
|
||||
|
||||
**Output**
|
||||
```text
|
||||
> Running step 845783b0-b85b-487c-baee-8460ebe8b38d. Step input: I love to eat pizza on weekends
|
||||
Added user message to memory: I love to eat pizza on weekends
|
||||
=== LLM Response ===
|
||||
Pizza is a great choice for the weekend! If you'd like, I can help you order some. Just let me know what kind of pizza you prefer!
|
||||
```
|
||||
|
||||
**Input**
|
||||
```python
|
||||
response = agent.chat("My preferred way of communication is email")
|
||||
print(response)
|
||||
```
|
||||
|
||||
**Output**
|
||||
```text
|
||||
> Running step 345842f0-f8a0-42ea-a1b7-612265d72a92. Step input: My preferred way of communication is email
|
||||
Added user message to memory: My preferred way of communication is email
|
||||
=== LLM Response ===
|
||||
Got it! If you need any assistance or have any requests, feel free to let me know, and I can communicate with you via email.
|
||||
```
|
||||
|
||||
## Using the Agent Without Memory
|
||||
|
||||
**Input**
|
||||
```python
|
||||
agent = FunctionCallingAgent.from_tools(
|
||||
[call_tool, email_tool, order_food_tool],
|
||||
# memory is not provided
|
||||
llm=llm,
|
||||
verbose=True,
|
||||
)
|
||||
response = agent.chat("I am feeling hungry, order me something and send me the bill")
|
||||
print(response)
|
||||
```
|
||||
|
||||
**Output**
|
||||
```text
|
||||
> Running step e89eb75d-75e1-4dea-a8c8-5c3d4b77882d. Step input: I am feeling hungry, order me something and send me the bill
|
||||
Added user message to memory: I am feeling hungry, order me something and send me the bill
|
||||
=== LLM Response ===
|
||||
Please let me know your name and the dish you'd like to order, and I'll take care of it for you!
|
||||
```
|
||||
|
||||
<Note>The agent is not able to remember the past preferences the user shared in previous chats.</Note>
|
||||
|
||||
## Using the Agent With Memory
|
||||
|
||||
**Input**
|
||||
```python
|
||||
agent = FunctionCallingAgent.from_tools(
|
||||
[call_tool, email_tool, order_food_tool],
|
||||
llm=llm,
|
||||
# memory is provided
|
||||
memory=memory_from_client, # or memory_from_config
|
||||
verbose=True,
|
||||
)
|
||||
response = agent.chat("I am feeling hungry, order me something and send me the bill")
|
||||
print(response)
|
||||
```
|
||||
|
||||
Output
|
||||
```text
|
||||
> Running step 5e473db9-3973-4cb1-a5fd-860be0ab0006. Step input: I am feeling hungry, order me something and send me the bill
|
||||
Added user message to memory: I am feeling hungry, order me something and send me the bill
|
||||
=== Calling Function ===
|
||||
Calling function: order_food with args: {"name": "David", "dish": "pizza"}
|
||||
=== Function Output ===
|
||||
Ordering pizza for David
|
||||
=== Calling Function ===
|
||||
Calling function: email_fn with args: {"name": "David"}
|
||||
=== Function Output ===
|
||||
Emailing... David
|
||||
> Running step 38080544-6b37-4bb2-aab2-7670100d926e. Step input: None
|
||||
=== LLM Response ===
|
||||
I've ordered a pizza for you, and the bill has been sent to your email. Enjoy your meal! If there's anything else you need, feel free to let me know.
|
||||
```
|
||||
|
||||
<Note>The agent is able to remember the past preferences the user shared and use them to perform actions.</Note>
|
||||
|
||||
---
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="LlamaIndex Multiagent with Mem0" icon="users" href="/cookbooks/frameworks/llamaindex-multiagent">
|
||||
Scale to multi-agent workflows with shared memory coordination.
|
||||
</Card>
|
||||
<Card title="Build a Mem0 Companion" icon="users" href="/cookbooks/essentials/building-ai-companion">
|
||||
Master the core patterns for memory-powered agents across frameworks.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -0,0 +1,43 @@
|
||||
---
|
||||
title: Multimodal Retrieval with Mem0
|
||||
description: "Store and recall visual context alongside text conversations."
|
||||
---
|
||||
|
||||
|
||||
Enhance your AI interactions with Mem0's multimodal capabilities. Mem0 now supports image understanding, allowing for richer context and more natural interactions across supported AI platforms.
|
||||
|
||||
> Experience the power of multimodal AI! Test out Mem0's image understanding capabilities at [multimodal-demo.mem0.ai](https://multimodal-demo.mem0.ai)
|
||||
|
||||
## Features
|
||||
|
||||
- **Image Understanding**: Share and discuss images with AI assistants while maintaining context
|
||||
- **Smart Visual Context**: Automatically capture and reference visual elements in conversations
|
||||
- **Cross-Modal Memory**: Link visual and textual information seamlessly in your memory layer
|
||||
- **Cross-Session Recall**: Reference previously discussed visual content across different conversations
|
||||
- **Seamless Integration**: Works naturally with existing chat interfaces for a smooth experience
|
||||
|
||||
## How It Works
|
||||
|
||||
1. **Upload Visual Content**: Simply drag and drop or paste images into your conversations
|
||||
2. **Natural Interaction**: Discuss the visual content naturally with AI assistants
|
||||
3. **Memory Integration**: Visual context is automatically stored and linked with your conversation history
|
||||
4. **Persistent Recall**: Retrieve and reference past visual content effortlessly
|
||||
|
||||
## Demo Video
|
||||
|
||||
<iframe width="700" height="400" src="https://www.youtube.com/embed/2Md5AEFVpmg?si=rXXupn6CiDUPJsi3" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
|
||||
|
||||
## Try It Out
|
||||
|
||||
Visit [multimodal-demo.mem0.ai](https://multimodal-demo.mem0.ai) to experience Mem0's multimodal capabilities firsthand. Upload images and see how Mem0 understands and remembers visual context across your conversations.
|
||||
|
||||
---
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Multimodal Support" icon="image" href="/platform/features/multimodal-support">
|
||||
Learn how to store and retrieve vision and audio memories in your apps.
|
||||
</Card>
|
||||
<Card title="Voice Companion with OpenAI" icon="microphone" href="/cookbooks/companions/voice-companion-openai">
|
||||
Build voice-first companions that remember conversations.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -0,0 +1,238 @@
|
||||
---
|
||||
title: Agents SDK Tool with Mem0
|
||||
description: "Expose Mem0 memories as callable tools inside OpenAI agent workflows."
|
||||
---
|
||||
|
||||
|
||||
Integrate Mem0's memory capabilities with OpenAI's Agents SDK to create AI agents with persistent memory. You can create agents that remember past conversations and use that context to provide better responses.
|
||||
|
||||
## Installation
|
||||
|
||||
First, install the required packages:
|
||||
```bash
|
||||
pip install mem0ai pydantic openai-agents
|
||||
```
|
||||
|
||||
You'll also need a custom agents framework for this implementation.
|
||||
|
||||
## Setting Up Environment Variables
|
||||
|
||||
Store your Mem0 API key as an environment variable:
|
||||
|
||||
```bash
|
||||
export MEM0_API_KEY="your_mem0_api_key"
|
||||
```
|
||||
|
||||
Or in your Python script:
|
||||
|
||||
```python
|
||||
import os
|
||||
os.environ["MEM0_API_KEY"] = "your_mem0_api_key"
|
||||
```
|
||||
|
||||
## Code Structure
|
||||
|
||||
The integration consists of three main components:
|
||||
|
||||
1. **Context Manager**: Defines user context for memory operations
|
||||
2. **Memory Tools**: Functions to add, search, and retrieve memories
|
||||
3. **Memory Agent**: An agent configured to use these memory tools
|
||||
|
||||
## Step-by-Step Implementation
|
||||
|
||||
### 1. Import Dependencies
|
||||
|
||||
```python
|
||||
from __future__ import annotations
|
||||
import os
|
||||
import asyncio
|
||||
from pydantic import BaseModel
|
||||
try:
|
||||
from mem0 import AsyncMemoryClient
|
||||
except ImportError:
|
||||
raise ImportError("mem0 is not installed. Please install it using 'pip install mem0ai'.")
|
||||
from agents import (
|
||||
Agent,
|
||||
ItemHelpers,
|
||||
MessageOutputItem,
|
||||
RunContextWrapper,
|
||||
Runner,
|
||||
ToolCallItem,
|
||||
ToolCallOutputItem,
|
||||
TResponseInputItem,
|
||||
function_tool,
|
||||
)
|
||||
```
|
||||
|
||||
### 2. Define Memory Context
|
||||
|
||||
```python
|
||||
class Mem0Context(BaseModel):
|
||||
user_id: str | None = None
|
||||
```
|
||||
|
||||
### 3. Initialize the Mem0 Client
|
||||
|
||||
```python
|
||||
client = AsyncMemoryClient(api_key=os.getenv("MEM0_API_KEY"))
|
||||
```
|
||||
|
||||
### 4. Create Memory Tools
|
||||
|
||||
#### Add to Memory
|
||||
|
||||
```python
|
||||
@function_tool
|
||||
async def add_to_memory(
|
||||
context: RunContextWrapper[Mem0Context],
|
||||
content: str,
|
||||
) -> str:
|
||||
"""
|
||||
Add a message to Mem0
|
||||
Args:
|
||||
content: The content to store in memory.
|
||||
"""
|
||||
messages = [{"role": "user", "content": content}]
|
||||
user_id = context.context.user_id or "default_user"
|
||||
await client.add(messages, user_id=user_id)
|
||||
return f"Stored message: {content}"
|
||||
```
|
||||
|
||||
#### Search Memory
|
||||
|
||||
```python
|
||||
@function_tool
|
||||
async def search_memory(
|
||||
context: RunContextWrapper[Mem0Context],
|
||||
query: str,
|
||||
) -> str:
|
||||
"""
|
||||
Search for memories in Mem0
|
||||
Args:
|
||||
query: The search query.
|
||||
"""
|
||||
user_id = context.context.user_id or "default_user"
|
||||
memories = await client.search(query, user_id=user_id)
|
||||
results = '\n'.join([result["memory"] for result in memories["results"]])
|
||||
return str(results)
|
||||
```
|
||||
|
||||
#### Get All Memories
|
||||
|
||||
```python
|
||||
@function_tool
|
||||
async def get_all_memory(
|
||||
context: RunContextWrapper[Mem0Context],
|
||||
) -> str:
|
||||
"""Retrieve all memories from Mem0"""
|
||||
user_id = context.context.user_id or "default_user"
|
||||
memories = await client.get_all(user_id=user_id)
|
||||
results = '\n'.join([result["memory"] for result in memories["results"]])
|
||||
return str(results)
|
||||
```
|
||||
|
||||
### 5. Configure the Memory Agent
|
||||
|
||||
```python
|
||||
memory_agent = Agent[Mem0Context](
|
||||
name="Memory Assistant",
|
||||
instructions="""You are a helpful assistant with memory capabilities. You can:
|
||||
1. Store new information using add_to_memory
|
||||
2. Search existing information using search_memory
|
||||
3. Retrieve all stored information using get_all_memory
|
||||
When users ask questions:
|
||||
- If they want to store information, use add_to_memory
|
||||
- If they're searching for specific information, use search_memory
|
||||
- If they want to see everything stored, use get_all_memory""",
|
||||
tools=[add_to_memory, search_memory, get_all_memory],
|
||||
)
|
||||
```
|
||||
|
||||
### 6. Implement the Main Runtime Loop
|
||||
|
||||
```python
|
||||
async def main():
|
||||
current_agent: Agent[Mem0Context] = memory_agent
|
||||
input_items: list[TResponseInputItem] = []
|
||||
context = Mem0Context()
|
||||
while True:
|
||||
user_input = input("Enter your message (or 'quit' to exit): ")
|
||||
if user_input.lower() == 'quit':
|
||||
break
|
||||
input_items.append({"content": user_input, "role": "user"})
|
||||
result = await Runner.run(current_agent, input_items, context=context)
|
||||
for new_item in result.new_items:
|
||||
agent_name = new_item.agent.name
|
||||
if isinstance(new_item, MessageOutputItem):
|
||||
print(f"{agent_name}: {ItemHelpers.text_message_output(new_item)}")
|
||||
elif isinstance(new_item, ToolCallItem):
|
||||
print(f"{agent_name}: Calling a tool")
|
||||
elif isinstance(new_item, ToolCallOutputItem):
|
||||
print(f"{agent_name}: Tool call output: {new_item.output}")
|
||||
else:
|
||||
print(f"{agent_name}: Skipping item: {new_item.__class__.__name__}")
|
||||
input_items = result.to_input_list()
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
```
|
||||
|
||||
## Usage Examples
|
||||
|
||||
### Storing Information
|
||||
|
||||
```
|
||||
User: Remember that my favorite color is blue
|
||||
Agent: Calling a tool
|
||||
Agent: Tool call output: Stored message: my favorite color is blue
|
||||
Agent: I've stored that your favorite color is blue in my memory. I'll remember that for future conversations.
|
||||
```
|
||||
|
||||
### Searching Memory
|
||||
|
||||
```
|
||||
User: What's my favorite color?
|
||||
Agent: Calling a tool
|
||||
Agent: Tool call output: my favorite color is blue
|
||||
Agent: Your favorite color is blue, based on what you've told me earlier.
|
||||
```
|
||||
|
||||
### Retrieving All Memories
|
||||
|
||||
```
|
||||
User: What do you know about me?
|
||||
Agent: Calling a tool
|
||||
Agent: Tool call output: favorite color is blue
|
||||
my birthday is on March 15
|
||||
Agent: Based on our previous conversations, I know that:
|
||||
1. Your favorite color is blue
|
||||
2. Your birthday is on March 15
|
||||
```
|
||||
|
||||
## Advanced Configuration
|
||||
|
||||
### Custom User IDs
|
||||
|
||||
You can specify different user IDs to maintain separate memory stores for multiple users:
|
||||
|
||||
```python
|
||||
context = Mem0Context(user_id="user123")
|
||||
```
|
||||
|
||||
|
||||
## Resources
|
||||
|
||||
- [Mem0 Documentation](https://docs.mem0.ai)
|
||||
- [Mem0 Dashboard](https://app.mem0.ai/dashboard)
|
||||
- [API Reference](https://docs.mem0.ai/api-reference)
|
||||
|
||||
---
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="OpenAI Tool Calls with Mem0" icon="wrench" href="/cookbooks/integrations/openai-tool-calls">
|
||||
Extend OpenAI assistants with tool-based memory operations.
|
||||
</Card>
|
||||
<Card title="Build a Mem0 Companion" icon="users" href="/cookbooks/essentials/building-ai-companion">
|
||||
Learn the core patterns for memory-powered agents with any SDK.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -0,0 +1,143 @@
|
||||
---
|
||||
title: AWS Bedrock with Mem0
|
||||
description: "Pair Mem0 with AWS Bedrock, OpenSearch, and Neptune for a managed stack."
|
||||
---
|
||||
|
||||
|
||||
This example demonstrates how to configure and use the `mem0ai` SDK with **AWS Bedrock**, **OpenSearch Service (AOSS)**, and **AWS Neptune Analytics** for persistent memory capabilities in Python.
|
||||
|
||||
## Installation
|
||||
|
||||
Install the required dependencies to include the Amazon data stack, including **boto3**, **opensearch-py**, and **langchain-aws**:
|
||||
|
||||
```bash
|
||||
pip install "mem0ai[graph,extras]"
|
||||
```
|
||||
|
||||
## Environment Setup
|
||||
|
||||
Set your AWS environment variables:
|
||||
|
||||
```python
|
||||
import os
|
||||
|
||||
# Set these in your environment or notebook
|
||||
os.environ['AWS_REGION'] = 'us-west-2'
|
||||
os.environ['AWS_ACCESS_KEY_ID'] = 'AK00000000000000000'
|
||||
os.environ['AWS_SECRET_ACCESS_KEY'] = 'AS00000000000000000'
|
||||
|
||||
# Confirm they are set
|
||||
print(os.environ['AWS_REGION'])
|
||||
print(os.environ['AWS_ACCESS_KEY_ID'])
|
||||
print(os.environ['AWS_SECRET_ACCESS_KEY'])
|
||||
```
|
||||
|
||||
## Configuration and Usage
|
||||
|
||||
This sets up Mem0 with:
|
||||
- [AWS Bedrock for LLM](https://docs.mem0.ai/components/llms/models/aws_bedrock)
|
||||
- [AWS Bedrock for embeddings](https://docs.mem0.ai/components/embedders/models/aws_bedrock#aws-bedrock)
|
||||
- [OpenSearch as the vector store](https://docs.mem0.ai/components/vectordbs/dbs/opensearch)
|
||||
- [Graph Memory guide](https://docs.mem0.ai/open-source/features/graph-memory)
|
||||
|
||||
```python
|
||||
import boto3
|
||||
from opensearchpy import RequestsHttpConnection, AWSV4SignerAuth
|
||||
from mem0.memory.main import Memory
|
||||
|
||||
region = 'us-west-2'
|
||||
service = 'aoss'
|
||||
credentials = boto3.Session().get_credentials()
|
||||
auth = AWSV4SignerAuth(credentials, region, service)
|
||||
|
||||
config = {
|
||||
"embedder": {
|
||||
"provider": "aws_bedrock",
|
||||
"config": {
|
||||
"model": "amazon.titan-embed-text-v2:0"
|
||||
}
|
||||
},
|
||||
"llm": {
|
||||
"provider": "aws_bedrock",
|
||||
"config": {
|
||||
"model": "us.anthropic.claude-3-7-sonnet-20250219-v1:0",
|
||||
"temperature": 0.1,
|
||||
"max_tokens": 2000
|
||||
}
|
||||
},
|
||||
"vector_store": {
|
||||
"provider": "opensearch",
|
||||
"config": {
|
||||
"collection_name": "mem0",
|
||||
"host": "your-opensearch-domain.us-west-2.es.amazonaws.com",
|
||||
"port": 443,
|
||||
"http_auth": auth,
|
||||
"connection_class": RequestsHttpConnection,
|
||||
"pool_maxsize": 20,
|
||||
"use_ssl": True,
|
||||
"verify_certs": True,
|
||||
"embedding_model_dims": 1024,
|
||||
}
|
||||
},
|
||||
"graph_store": {
|
||||
"provider": "neptune",
|
||||
"config": {
|
||||
"endpoint": f"neptune-graph://my-graph-identifier",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
# Initialize the memory system
|
||||
m = Memory.from_config(config)
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
Reference [Notebook example](https://github.com/mem0ai/mem0/blob/main/examples/graph-db-demo/neptune-example.ipynb)
|
||||
|
||||
### Add a memory
|
||||
|
||||
```python
|
||||
messages = [
|
||||
{"role": "user", "content": "I'm planning to watch a movie tonight. Any recommendations?"},
|
||||
{"role": "assistant", "content": "How about thriller movies? They can be quite engaging."},
|
||||
{"role": "user", "content": "I'm not a big fan of thriller movies but I love sci-fi movies."},
|
||||
{"role": "assistant", "content": "Got it! I'll avoid thriller recommendations and suggest sci-fi movies in the future."}
|
||||
]
|
||||
|
||||
# Store inferred memories (default behavior)
|
||||
result = m.add(messages, user_id="alice", metadata={"category": "movie_recommendations"})
|
||||
```
|
||||
|
||||
### Search a memory
|
||||
|
||||
```python
|
||||
relevant_memories = m.search(query, user_id="alice")
|
||||
```
|
||||
|
||||
### Get all memories
|
||||
|
||||
```python
|
||||
all_memories = m.get_all(user_id="alice")
|
||||
```
|
||||
|
||||
### Get a specific memory
|
||||
|
||||
```python
|
||||
memory = m.get(memory_id)
|
||||
```
|
||||
|
||||
## Conclusion
|
||||
|
||||
With Mem0 and AWS services like Bedrock, OpenSearch, and Neptune Analytics, you can build intelligent AI companions that remember, adapt, and personalize their responses over time. This makes them ideal for long-term assistants, tutors, or support bots with persistent memory and natural conversation abilities.
|
||||
|
||||
---
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Neptune Analytics with Mem0" icon="database" href="/cookbooks/integrations/neptune-analytics">
|
||||
Explore graph-based memory storage with AWS Neptune Analytics.
|
||||
</Card>
|
||||
<Card title="Graph Memory Features" icon="sitemap" href="/platform/features/graph-memory">
|
||||
Learn how to leverage knowledge graphs for entity relationships.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -0,0 +1,301 @@
|
||||
---
|
||||
title: Healthcare Coach with Mem0 and Google ADK
|
||||
description: "Guide patients with an assistant that remembers history across ADK sessions."
|
||||
---
|
||||
|
||||
|
||||
This example demonstrates how to build a healthcare assistant that remembers patient information across conversations using Google ADK and Mem0.
|
||||
|
||||
## Overview
|
||||
|
||||
The Healthcare Assistant helps patients by:
|
||||
- Remembering their medical history and symptoms
|
||||
- Providing general health information
|
||||
- Scheduling appointment reminders
|
||||
- Maintaining a personalized experience across conversations
|
||||
|
||||
By integrating Mem0's memory layer with Google ADK, the assistant maintains context about the patient without requiring them to repeat information.
|
||||
|
||||
## Setup
|
||||
|
||||
Before you begin, make sure you have:
|
||||
|
||||
Installed Google ADK and Mem0 SDK:
|
||||
```bash
|
||||
pip install google-adk mem0ai python-dotenv
|
||||
```
|
||||
|
||||
## Code Breakdown
|
||||
|
||||
Let's get started and understand the different components required in building a healthcare assistant powered by memory
|
||||
|
||||
```python
|
||||
# Import dependencies
|
||||
import os
|
||||
import asyncio
|
||||
from google.adk.agents import Agent
|
||||
from google.adk.runners import Runner
|
||||
from google.adk.sessions import InMemorySessionService
|
||||
from google.genai import types
|
||||
from mem0 import MemoryClient
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
# Set up environment variables
|
||||
# os.environ["GOOGLE_API_KEY"] = "your-google-api-key"
|
||||
# os.environ["MEM0_API_KEY"] = "your-mem0-api-key"
|
||||
|
||||
# Define a global user ID for simplicity
|
||||
USER_ID = "Alex"
|
||||
|
||||
# Initialize Mem0 client
|
||||
mem0 = MemoryClient()
|
||||
```
|
||||
|
||||
## Define Memory Tools
|
||||
|
||||
First, we'll create tools that allow our agent to store and retrieve information using Mem0:
|
||||
|
||||
```python
|
||||
def save_patient_info(information: str) -> dict:
|
||||
"""Saves important patient information to memory."""
|
||||
|
||||
# Store in Mem0
|
||||
response = mem0_client.add(
|
||||
[{"role": "user", "content": information}],
|
||||
user_id=USER_ID,
|
||||
run_id="healthcare_session",
|
||||
metadata={"type": "patient_information"}
|
||||
)
|
||||
|
||||
|
||||
def retrieve_patient_info(query: str) -> dict:
|
||||
"""Retrieves relevant patient information from memory."""
|
||||
|
||||
# Search Mem0
|
||||
results = mem0_client.search(
|
||||
query,
|
||||
user_id=USER_ID,
|
||||
limit=5,
|
||||
threshold=0.7 # Higher threshold for more relevant results
|
||||
)
|
||||
|
||||
# Format and return the results
|
||||
if results and len(results) > 0:
|
||||
memories = [memory["memory"] for memory in results.get('results', [])]
|
||||
return {
|
||||
"status": "success",
|
||||
"memories": memories,
|
||||
"count": len(memories)
|
||||
}
|
||||
else:
|
||||
return {
|
||||
"status": "no_results",
|
||||
"memories": [],
|
||||
"count": 0
|
||||
}
|
||||
```
|
||||
|
||||
## Define Healthcare Tools
|
||||
|
||||
Next, we'll add tools specific to healthcare assistance:
|
||||
|
||||
```python
|
||||
def schedule_appointment(date: str, time: str, reason: str) -> dict:
|
||||
"""Schedules a doctor's appointment."""
|
||||
# In a real app, this would connect to a scheduling system
|
||||
appointment_id = f"APT-{hash(date + time) % 10000}"
|
||||
|
||||
return {
|
||||
"status": "success",
|
||||
"appointment_id": appointment_id,
|
||||
"confirmation": f"Appointment scheduled for {date} at {time} for {reason}",
|
||||
"message": "Please arrive 15 minutes early to complete paperwork."
|
||||
}
|
||||
```
|
||||
|
||||
## Create the Healthcare Assistant Agent
|
||||
|
||||
Now we'll create our main agent with all the tools:
|
||||
|
||||
```python
|
||||
# Create the agent
|
||||
healthcare_agent = Agent(
|
||||
name="healthcare_assistant",
|
||||
model="gemini-1.5-flash", # Using Gemini for healthcare assistant
|
||||
description="Healthcare assistant that helps patients with health information and appointment scheduling.",
|
||||
instruction="""You are a helpful Healthcare Assistant with memory capabilities.
|
||||
|
||||
Your primary responsibilities are to:
|
||||
1. Remember patient information using the 'save_patient_info' tool when they share symptoms, conditions, or preferences.
|
||||
2. Retrieve past patient information using the 'retrieve_patient_info' tool when relevant to the current conversation.
|
||||
3. Help schedule appointments using the 'schedule_appointment' tool.
|
||||
|
||||
IMPORTANT GUIDELINES:
|
||||
- Always be empathetic, professional, and helpful.
|
||||
- Save important patient information like symptoms, conditions, allergies, and preferences.
|
||||
- Check if you have relevant patient information before asking for details they may have shared previously.
|
||||
- Make it clear you are not a doctor and cannot provide medical diagnosis or treatment.
|
||||
- For serious symptoms, always recommend consulting a healthcare professional.
|
||||
- Keep all patient information confidential.
|
||||
""",
|
||||
tools=[save_patient_info, retrieve_patient_info, schedule_appointment]
|
||||
)
|
||||
```
|
||||
|
||||
## Set Up Session and Runner
|
||||
|
||||
```python
|
||||
# Set up Session Service and Runner
|
||||
session_service = InMemorySessionService()
|
||||
|
||||
# Define constants for the conversation
|
||||
APP_NAME = "healthcare_assistant_app"
|
||||
USER_ID = "Alex"
|
||||
SESSION_ID = "session_001"
|
||||
|
||||
# Create a session
|
||||
session = session_service.create_session(
|
||||
app_name=APP_NAME,
|
||||
user_id=USER_ID,
|
||||
session_id=SESSION_ID
|
||||
)
|
||||
|
||||
# Create the runner
|
||||
runner = Runner(
|
||||
agent=healthcare_agent,
|
||||
app_name=APP_NAME,
|
||||
session_service=session_service
|
||||
)
|
||||
```
|
||||
|
||||
## Interact with the Healthcare Assistant
|
||||
|
||||
```python
|
||||
# Function to interact with the agent
|
||||
async def call_agent_async(query, runner, user_id, session_id):
|
||||
"""Sends a query to the agent and returns the final response."""
|
||||
print(f"\n>>> Patient: {query}")
|
||||
|
||||
# Format the user's message
|
||||
content = types.Content(
|
||||
role='user',
|
||||
parts=[types.Part(text=query)]
|
||||
)
|
||||
|
||||
# Set user_id for tools to access
|
||||
save_patient_info.user_id = user_id
|
||||
retrieve_patient_info.user_id = user_id
|
||||
|
||||
# Run the agent
|
||||
async for event in runner.run_async(
|
||||
user_id=user_id,
|
||||
session_id=session_id,
|
||||
new_message=content
|
||||
):
|
||||
if event.is_final_response():
|
||||
if event.content and event.content.parts:
|
||||
response = event.content.parts[0].text
|
||||
print(f"<<< Assistant: {response}")
|
||||
return response
|
||||
|
||||
return "No response received."
|
||||
|
||||
# Example conversation flow
|
||||
async def run_conversation():
|
||||
# First interaction - patient introduces themselves with key information
|
||||
await call_agent_async(
|
||||
"Hi, I'm Alex. I've been having headaches for the past week, and I have a penicillin allergy.",
|
||||
runner=runner,
|
||||
user_id=USER_ID,
|
||||
session_id=SESSION_ID
|
||||
)
|
||||
|
||||
# Request for health information
|
||||
await call_agent_async(
|
||||
"Can you tell me more about what might be causing my headaches?",
|
||||
runner=runner,
|
||||
user_id=USER_ID,
|
||||
session_id=SESSION_ID
|
||||
)
|
||||
|
||||
# Schedule an appointment
|
||||
await call_agent_async(
|
||||
"I think I should see a doctor. Can you help me schedule an appointment for next Monday at 2pm?",
|
||||
runner=runner,
|
||||
user_id=USER_ID,
|
||||
session_id=SESSION_ID
|
||||
)
|
||||
|
||||
# Test memory - should remember patient name, symptoms, and allergy
|
||||
await call_agent_async(
|
||||
"What medications should I avoid for my headaches?",
|
||||
runner=runner,
|
||||
user_id=USER_ID,
|
||||
session_id=SESSION_ID
|
||||
)
|
||||
|
||||
# Run the conversation example
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(run_conversation())
|
||||
```
|
||||
|
||||
## How It Works
|
||||
|
||||
This healthcare assistant demonstrates several key capabilities:
|
||||
|
||||
1. **Memory Storage**: When Alex mentions her headaches and penicillin allergy, the agent stores this information in Mem0 using the `save_patient_info` tool.
|
||||
|
||||
2. **Contextual Retrieval**: When Alex asks about headache causes, the agent uses the `retrieve_patient_info` tool to recall her specific situation.
|
||||
|
||||
3. **Memory Application**: When discussing medications, the agent remembers Alex's penicillin allergy without her needing to repeat it, providing safer and more personalized advice.
|
||||
|
||||
4. **Conversation Continuity**: The agent maintains context across the entire conversation session, creating a more natural and efficient interaction.
|
||||
|
||||
## Key Implementation Details
|
||||
|
||||
## User ID Management
|
||||
|
||||
Instead of passing the user ID as a parameter to the memory tools (which would require modifying the ADK's tool calling system), we attach it directly to the function object:
|
||||
|
||||
```python
|
||||
# Set user_id for tools to access
|
||||
save_patient_info.user_id = user_id
|
||||
retrieve_patient_info.user_id = user_id
|
||||
```
|
||||
|
||||
Inside the tool functions, we retrieve this attribute:
|
||||
|
||||
```python
|
||||
# Get user_id from session state or use default
|
||||
user_id = getattr(save_patient_info, 'user_id', 'default_user')
|
||||
```
|
||||
|
||||
This approach allows our tools to maintain user context without complicating their parameter signatures.
|
||||
|
||||
## Mem0 Integration
|
||||
|
||||
The integration with Mem0 happens through two primary functions:
|
||||
|
||||
1. `mem0_client.add()` - Stores new information with appropriate metadata
|
||||
2. `mem0_client.search()` - Retrieves relevant memories using semantic search
|
||||
|
||||
The `threshold` parameter in the search function ensures that only highly relevant memories are returned.
|
||||
|
||||
## Conclusion
|
||||
|
||||
This example demonstrates how to build a healthcare assistant with persistent memory using Google ADK and Mem0. The integration allows for a more personalized patient experience by maintaining context across conversation turns, which is particularly valuable in healthcare scenarios where continuity of information is crucial.
|
||||
|
||||
By storing and retrieving patient information intelligently, the assistant provides more relevant responses without requiring the patient to repeat their medical history, symptoms, or preferences.
|
||||
|
||||
---
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Tag and Organize Memories" icon="tag" href="/cookbooks/essentials/tagging-and-organizing-memories">
|
||||
Categorize patient data by symptoms, history, and visit context.
|
||||
</Card>
|
||||
<Card title="Support Inbox with Mem0" icon="headset" href="/cookbooks/operations/support-inbox">
|
||||
Apply similar memory patterns to customer support workflows.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -0,0 +1,138 @@
|
||||
---
|
||||
title: Mastra Agent with Mem0
|
||||
description: "Extend Mastra agents with persistent memories powered by Mem0."
|
||||
---
|
||||
|
||||
|
||||
In this example you'll learn how to use Mem0 to add long-term memory capabilities to [Mastra's agent](https://mastra.ai/) via tool-use. This memory integration can work alongside Mastra's [agent memory features](https://mastra.ai/docs/agents/01-agent-memory).
|
||||
|
||||
You can find the complete example code in the [Mastra repository](https://github.com/mastra-ai/mastra/tree/main/examples/memory-with-mem0).
|
||||
|
||||
## Overview
|
||||
|
||||
This guide will show you how to integrate Mem0 with Mastra to add long-term memory capabilities to your agents. We'll create tools that allow agents to save and retrieve memories using Mem0's API.
|
||||
|
||||
## Installation
|
||||
|
||||
**Install the Integration Package**
|
||||
|
||||
To install the Mem0 integration, run:
|
||||
|
||||
```bash
|
||||
npm install @mastra/mem0
|
||||
```
|
||||
|
||||
**Add the Integration to Your Project**
|
||||
|
||||
Create a new file for your integrations and import the integration:
|
||||
|
||||
```typescript integrations/index.ts
|
||||
import { Mem0Integration } from "@mastra/mem0";
|
||||
|
||||
export const mem0 = new Mem0Integration({
|
||||
config: {
|
||||
apiKey: process.env.MEM0_API_KEY!,
|
||||
userId: "alice",
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
**Use the Integration in Tools or Workflows**
|
||||
|
||||
You can now use the integration when defining tools for your agents or in workflows.
|
||||
|
||||
```typescript tools/index.ts
|
||||
import { createTool } from "@mastra/core";
|
||||
import { z } from "zod";
|
||||
import { mem0 } from "../integrations";
|
||||
|
||||
export const mem0RememberTool = createTool({
|
||||
id: "Mem0-remember",
|
||||
description:
|
||||
"Remember your agent memories that you've previously saved using the Mem0-memorize tool.",
|
||||
inputSchema: z.object({
|
||||
question: z
|
||||
.string()
|
||||
.describe("Question used to look up the answer in saved memories."),
|
||||
}),
|
||||
outputSchema: z.object({
|
||||
answer: z.string().describe("Remembered answer"),
|
||||
}),
|
||||
execute: async ({ context }) => {
|
||||
console.log(`Searching memory "${context.question}"`);
|
||||
const memory = await mem0.searchMemory(context.question);
|
||||
console.log(`\nFound memory "${memory}"\n`);
|
||||
|
||||
return {
|
||||
answer: memory,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export const mem0MemorizeTool = createTool({
|
||||
id: "Mem0-memorize",
|
||||
description:
|
||||
"Save information to mem0 so you can remember it later using the Mem0-remember tool.",
|
||||
inputSchema: z.object({
|
||||
statement: z.string().describe("A statement to save into memory"),
|
||||
}),
|
||||
execute: async ({ context }) => {
|
||||
console.log(`\nCreating memory "${context.statement}"\n`);
|
||||
// to reduce latency memories can be saved async without blocking tool execution
|
||||
void mem0.createMemory(context.statement).then(() => {
|
||||
console.log(`\nMemory "${context.statement}" saved.\n`);
|
||||
});
|
||||
return { success: true };
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
**Create a New Agent**
|
||||
|
||||
```typescript agents/index.ts
|
||||
import { openai } from '@ai-sdk/openai';
|
||||
import { Agent } from '@mastra/core/agent';
|
||||
import { mem0MemorizeTool, mem0RememberTool } from '../tools';
|
||||
|
||||
export const mem0Agent = new Agent({
|
||||
name: 'Mem0 Agent',
|
||||
instructions: `
|
||||
You are a helpful assistant that has the ability to memorize and remember facts using Mem0.
|
||||
`,
|
||||
model: openai('gpt-4.1-nano'),
|
||||
tools: { mem0RememberTool, mem0MemorizeTool },
|
||||
});
|
||||
```
|
||||
|
||||
**Run the Agent**
|
||||
|
||||
```typescript index.ts
|
||||
import { Mastra } from '@mastra/core/mastra';
|
||||
import { createLogger } from '@mastra/core/logger';
|
||||
|
||||
import { mem0Agent } from './agents';
|
||||
|
||||
export const mastra = new Mastra({
|
||||
agents: { mem0Agent },
|
||||
logger: createLogger({
|
||||
name: 'Mastra',
|
||||
level: 'error',
|
||||
}),
|
||||
});
|
||||
```
|
||||
|
||||
In the example above:
|
||||
- We import the `@mastra/mem0` integration
|
||||
- We define two tools that use the Mem0 API client to create new memories and recall previously saved memories
|
||||
- The tool accepts `question` as an input and returns the memory as a string
|
||||
|
||||
---
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Build AI with Personality" icon="sparkles" href="/cookbooks/essentials/building-ai-with-personality">
|
||||
Separate agent and user memories to maintain consistent personalities.
|
||||
</Card>
|
||||
<Card title="Agents SDK Tool with Mem0" icon="robot" href="/cookbooks/integrations/agents-sdk-tool">
|
||||
Explore tool-calling patterns with the OpenAI Agents SDK.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -0,0 +1,133 @@
|
||||
---
|
||||
title: Neptune Analytics with Mem0
|
||||
description: "Combine Mem0 graph memory with AWS Neptune Analytics and Bedrock."
|
||||
---
|
||||
|
||||
|
||||
This example demonstrates how to configure and use the `mem0ai` SDK with **AWS Bedrock** and **AWS Neptune Analytics** for persistent memory capabilities in Python.
|
||||
|
||||
## Installation
|
||||
|
||||
Install the required dependencies to include the Amazon data stack, including **boto3** and **langchain-aws**:
|
||||
|
||||
```bash
|
||||
pip install "mem0ai[graph,extras]"
|
||||
```
|
||||
|
||||
## Environment Setup
|
||||
|
||||
Set your AWS environment variables:
|
||||
|
||||
```python
|
||||
import os
|
||||
|
||||
# Set these in your environment or notebook
|
||||
os.environ['AWS_REGION'] = 'us-west-2'
|
||||
os.environ['AWS_ACCESS_KEY_ID'] = 'AK00000000000000000'
|
||||
os.environ['AWS_SECRET_ACCESS_KEY'] = 'AS00000000000000000'
|
||||
|
||||
# Confirm they are set
|
||||
print(os.environ['AWS_REGION'])
|
||||
print(os.environ['AWS_ACCESS_KEY_ID'])
|
||||
print(os.environ['AWS_SECRET_ACCESS_KEY'])
|
||||
```
|
||||
|
||||
## Configuration and Usage
|
||||
|
||||
This sets up Mem0 with:
|
||||
- [AWS Bedrock for LLM](https://docs.mem0.ai/components/llms/models/aws_bedrock)
|
||||
- [AWS Bedrock for embeddings](https://docs.mem0.ai/components/embedders/models/aws_bedrock#aws-bedrock)
|
||||
- [Neptune Analytics as the vector store](https://docs.mem0.ai/components/vectordbs/dbs/neptune_analytics)
|
||||
- [Graph Memory guide](https://docs.mem0.ai/open-source/features/graph-memory).
|
||||
|
||||
```python
|
||||
import boto3
|
||||
from mem0.memory.main import Memory
|
||||
|
||||
region = 'us-west-2'
|
||||
neptune_analytics_endpoint = 'neptune-graph://my-graph-identifier'
|
||||
|
||||
config = {
|
||||
"embedder": {
|
||||
"provider": "aws_bedrock",
|
||||
"config": {
|
||||
"model": "amazon.titan-embed-text-v2:0"
|
||||
}
|
||||
},
|
||||
"llm": {
|
||||
"provider": "aws_bedrock",
|
||||
"config": {
|
||||
"model": "us.anthropic.claude-3-7-sonnet-20250219-v1:0",
|
||||
"temperature": 0.1,
|
||||
"max_tokens": 2000
|
||||
}
|
||||
},
|
||||
"vector_store": {
|
||||
"provider": "neptune",
|
||||
"config": {
|
||||
"collection_name": "mem0",
|
||||
"endpoint": neptune_analytics_endpoint,
|
||||
},
|
||||
},
|
||||
"graph_store": {
|
||||
"provider": "neptune",
|
||||
"config": {
|
||||
"endpoint": neptune_analytics_endpoint,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
# Initialize the memory system
|
||||
m = Memory.from_config(config)
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
Reference [Notebook example](https://github.com/mem0ai/mem0/blob/main/examples/graph-db-demo/neptune-example.ipynb)
|
||||
|
||||
#### Add a memory:
|
||||
|
||||
```python
|
||||
messages = [
|
||||
{"role": "user", "content": "I'm planning to watch a movie tonight. Any recommendations?"},
|
||||
{"role": "assistant", "content": "How about a thriller movies? They can be quite engaging."},
|
||||
{"role": "user", "content": "I'm not a big fan of thriller movies but I love sci-fi movies."},
|
||||
{"role": "assistant", "content": "Got it! I'll avoid thriller recommendations and suggest sci-fi movies in the future."}
|
||||
]
|
||||
|
||||
# Store inferred memories (default behavior)
|
||||
result = m.add(messages, user_id="alice", metadata={"category": "movie_recommendations"})
|
||||
```
|
||||
|
||||
#### Search a memory:
|
||||
```python
|
||||
relevant_memories = m.search(query, user_id="alice")
|
||||
```
|
||||
|
||||
#### Get all memories:
|
||||
```python
|
||||
all_memories = m.get_all(user_id="alice")
|
||||
```
|
||||
|
||||
#### Get a specific memory:
|
||||
```python
|
||||
memory = m.get(memory_id)
|
||||
```
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Conclusion
|
||||
|
||||
With Mem0 and AWS services like Bedrock and Neptune Analytics, you can build intelligent AI companions that remember, adapt, and personalize their responses over time. This makes them ideal for long-term assistants, tutors, or support bots with persistent memory and natural conversation abilities.
|
||||
|
||||
---
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="AWS Bedrock with Mem0" icon="aws" href="/cookbooks/integrations/aws-bedrock">
|
||||
Combine Neptune Analytics with AWS Bedrock for complete AWS stack.
|
||||
</Card>
|
||||
<Card title="Graph Memory Architecture" icon="sitemap" href="/cookbooks/essentials/choosing-memory-architecture-vector-vs-graph">
|
||||
Understand when to use graph vs vector memory for your use case.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -0,0 +1,325 @@
|
||||
---
|
||||
title: OpenAI Tool Calls with Mem0
|
||||
description: "Wire Mem0 memories into OpenAI's inbuilt function-calling flow."
|
||||
---
|
||||
|
||||
|
||||
Integrate Mem0’s memory capabilities with OpenAI’s Inbuilt Tools to create AI agents with persistent memory.
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Installation
|
||||
|
||||
```bash
|
||||
npm install mem0ai openai zod
|
||||
```
|
||||
|
||||
## Environment Setup
|
||||
|
||||
Save your Mem0 and OpenAI API keys in a `.env` file:
|
||||
|
||||
```
|
||||
MEM0_API_KEY=your_mem0_api_key
|
||||
OPENAI_API_KEY=your_openai_api_key
|
||||
```
|
||||
|
||||
Get your Mem0 API key from the [Mem0 Dashboard](https://app.mem0.ai/dashboard/api-keys).
|
||||
|
||||
### Configuration
|
||||
|
||||
```javascript
|
||||
const mem0Config = {
|
||||
apiKey: process.env.MEM0_API_KEY,
|
||||
user_id: "sample-user",
|
||||
};
|
||||
|
||||
const openAIClient = new OpenAI();
|
||||
const mem0Client = new MemoryClient(mem0Config);
|
||||
```
|
||||
|
||||
## Adding Memories
|
||||
|
||||
Store user preferences, past interactions, or any relevant information:
|
||||
<CodeGroup>
|
||||
```javascript JavaScript
|
||||
async function addUserPreferences() {
|
||||
const mem0Client = new MemoryClient(mem0Config);
|
||||
|
||||
const userPreferences = "I Love BMW, Audi and Porsche. I Hate Mercedes. I love Red cars and Maroon cars. I have a budget of 120K to 150K USD. I like Audi the most.";
|
||||
|
||||
await mem0Client.add([{
|
||||
role: "user",
|
||||
content: userPreferences,
|
||||
}], mem0Config);
|
||||
}
|
||||
|
||||
await addUserPreferences();
|
||||
```
|
||||
|
||||
```json Output (Memories)
|
||||
[
|
||||
{
|
||||
"id": "ff9f3367-9e83-415d-b9c5-dc8befd9a4b4",
|
||||
"data": { "memory": "Loves BMW, Audi, and Porsche" },
|
||||
"event": "ADD"
|
||||
},
|
||||
{
|
||||
"id": "04172ce6-3d7b-45a3-b4a1-ee9798593cb4",
|
||||
"data": { "memory": "Hates Mercedes" },
|
||||
"event": "ADD"
|
||||
},
|
||||
{
|
||||
"id": "db363a5d-d258-4953-9e4c-777c120de34d",
|
||||
"data": { "memory": "Loves red cars and maroon cars" },
|
||||
"event": "ADD"
|
||||
},
|
||||
{
|
||||
"id": "5519aaad-a2ac-4c0d-81d7-0d55c6ecdba8",
|
||||
"data": { "memory": "Has a budget of 120K to 150K USD" },
|
||||
"event": "ADD"
|
||||
},
|
||||
{
|
||||
"id": "523b7693-7344-4563-922f-5db08edc8634",
|
||||
"data": { "memory": "Likes Audi the most" },
|
||||
"event": "ADD"
|
||||
}
|
||||
]
|
||||
```
|
||||
</CodeGroup>
|
||||
## Retrieving Memories
|
||||
|
||||
Search for relevant memories based on the current user input:
|
||||
|
||||
```javascript
|
||||
const relevantMemories = await mem0Client.search(userInput, mem0Config);
|
||||
```
|
||||
|
||||
## Structured Responses with Zod
|
||||
|
||||
Define structured response schemas to get consistent output formats:
|
||||
|
||||
```javascript
|
||||
// Define the schema for a car recommendation
|
||||
const CarSchema = z.object({
|
||||
car_name: z.string(),
|
||||
car_price: z.string(),
|
||||
car_url: z.string(),
|
||||
car_image: z.string(),
|
||||
car_description: z.string(),
|
||||
});
|
||||
|
||||
// Schema for a list of car recommendations
|
||||
const Cars = z.object({
|
||||
cars: z.array(CarSchema),
|
||||
});
|
||||
|
||||
// Create a function tool based on the schema
|
||||
const carRecommendationTool = zodResponsesFunction({
|
||||
name: "carRecommendations",
|
||||
parameters: Cars
|
||||
});
|
||||
|
||||
// Use the tool in your OpenAI request
|
||||
const response = await openAIClient.responses.create({
|
||||
model: "gpt-4.1-nano-2025-04-14",
|
||||
tools: [{ type: "web_search_preview" }, carRecommendationTool],
|
||||
input: `${getMemoryString(relevantMemories)}\n${userInput}`,
|
||||
});
|
||||
```
|
||||
|
||||
## Using Web Search
|
||||
|
||||
Combine memory with web search for up-to-date recommendations:
|
||||
|
||||
```javascript
|
||||
const response = await openAIClient.responses.create({
|
||||
model: "gpt-4.1-nano-2025-04-14",
|
||||
tools: [{ type: "web_search_preview" }, carRecommendationTool],
|
||||
input: `${getMemoryString(relevantMemories)}\n${userInput}`,
|
||||
});
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
## Complete Car Recommendation System
|
||||
|
||||
```javascript
|
||||
import MemoryClient from "mem0ai";
|
||||
import { OpenAI } from "openai";
|
||||
import { zodResponsesFunction } from "openai/helpers/zod";
|
||||
import { z } from "zod";
|
||||
import dotenv from 'dotenv';
|
||||
|
||||
dotenv.config();
|
||||
|
||||
const mem0Config = {
|
||||
apiKey: process.env.MEM0_API_KEY,
|
||||
user_id: "sample-user",
|
||||
};
|
||||
|
||||
async function run() {
|
||||
// Responses without memories
|
||||
console.log("\n\nRESPONSES WITHOUT MEMORIES\n\n");
|
||||
await main();
|
||||
|
||||
// Adding sample memories
|
||||
await addSampleMemories();
|
||||
|
||||
// Responses with memories
|
||||
console.log("\n\nRESPONSES WITH MEMORIES\n\n");
|
||||
await main(true);
|
||||
}
|
||||
|
||||
// OpenAI Response Schema
|
||||
const CarSchema = z.object({
|
||||
car_name: z.string(),
|
||||
car_price: z.string(),
|
||||
car_url: z.string(),
|
||||
car_image: z.string(),
|
||||
car_description: z.string(),
|
||||
});
|
||||
|
||||
const Cars = z.object({
|
||||
cars: z.array(CarSchema),
|
||||
});
|
||||
|
||||
async function main(memory = false) {
|
||||
const openAIClient = new OpenAI();
|
||||
const mem0Client = new MemoryClient(mem0Config);
|
||||
|
||||
const input = "Suggest me some cars that I can buy today.";
|
||||
|
||||
const tool = zodResponsesFunction({ name: "carRecommendations", parameters: Cars });
|
||||
|
||||
// Store the user input as a memory
|
||||
await mem0Client.add([{
|
||||
role: "user",
|
||||
content: input,
|
||||
}], mem0Config);
|
||||
|
||||
// Search for relevant memories
|
||||
let relevantMemories = []
|
||||
if (memory) {
|
||||
relevantMemories = await mem0Client.search(input, mem0Config);
|
||||
}
|
||||
|
||||
const response = await openAIClient.responses.create({
|
||||
model: "gpt-4.1-nano-2025-04-14",
|
||||
tools: [{ type: "web_search_preview" }, tool],
|
||||
input: `${getMemoryString(relevantMemories)}\n${input}`,
|
||||
});
|
||||
|
||||
console.log(response.output);
|
||||
}
|
||||
|
||||
async function addSampleMemories() {
|
||||
const mem0Client = new MemoryClient(mem0Config);
|
||||
|
||||
const myInterests = "I Love BMW, Audi and Porsche. I Hate Mercedes. I love Red cars and Maroon cars. I have a budget of 120K to 150K USD. I like Audi the most.";
|
||||
|
||||
await mem0Client.add([{
|
||||
role: "user",
|
||||
content: myInterests,
|
||||
}], mem0Config);
|
||||
}
|
||||
|
||||
const getMemoryString = (memories) => {
|
||||
const MEMORY_STRING_PREFIX = "These are the memories I have stored. Give more weightage to the question by users and try to answer that first. You have to modify your answer based on the memories I have provided. If the memories are irrelevant you can ignore them. Also don't reply to this section of the prompt, or the memories, they are only for your reference. The MEMORIES of the USER are: \n\n";
|
||||
const memoryString = (memories?.results || memories).map((mem) => `${mem.memory}`).join("\n") ?? "";
|
||||
return memoryString.length > 0 ? `${MEMORY_STRING_PREFIX}${memoryString}` : "";
|
||||
};
|
||||
|
||||
run().catch(console.error);
|
||||
```
|
||||
|
||||
## Responses
|
||||
|
||||
<CodeGroup>
|
||||
```json Without Memories
|
||||
{
|
||||
"cars": [
|
||||
{
|
||||
"car_name": "Toyota Camry",
|
||||
"car_price": "$25,000",
|
||||
"car_url": "https://www.toyota.com/camry/",
|
||||
"car_image": "https://link-to-toyota-camry-image.com",
|
||||
"car_description": "Reliable mid-size sedan with great fuel efficiency."
|
||||
},
|
||||
{
|
||||
"car_name": "Honda Accord",
|
||||
"car_price": "$26,000",
|
||||
"car_url": "https://www.honda.com/accord/",
|
||||
"car_image": "https://link-to-honda-accord-image.com",
|
||||
"car_description": "Comfortable and spacious with advanced safety features."
|
||||
},
|
||||
{
|
||||
"car_name": "Ford Mustang",
|
||||
"car_price": "$28,000",
|
||||
"car_url": "https://www.ford.com/mustang/",
|
||||
"car_image": "https://link-to-ford-mustang-image.com",
|
||||
"car_description": "Iconic sports car with powerful engine options."
|
||||
},
|
||||
{
|
||||
"car_name": "Tesla Model 3",
|
||||
"car_price": "$38,000",
|
||||
"car_url": "https://www.tesla.com/model3",
|
||||
"car_image": "https://link-to-tesla-model3-image.com",
|
||||
"car_description": "Electric vehicle with advanced technology and long range."
|
||||
},
|
||||
{
|
||||
"car_name": "Chevrolet Equinox",
|
||||
"car_price": "$24,000",
|
||||
"car_url": "https://www.chevrolet.com/equinox/",
|
||||
"car_image": "https://link-to-chevron-equinox-image.com",
|
||||
"car_description": "Compact SUV with a spacious interior and user-friendly technology."
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
```json With Memories
|
||||
{
|
||||
"cars": [
|
||||
{
|
||||
"car_name": "Audi RS7",
|
||||
"car_price": "$118,500",
|
||||
"car_url": "https://www.audiusa.com/us/web/en/models/rs7/2023/overview.html",
|
||||
"car_image": "https://www.audiusa.com/content/dam/nemo/us/models/rs7/my23/gallery/1920x1080_AOZ_A717_191004.jpg",
|
||||
"car_description": "The Audi RS7 is a high-performance hatchback with a sleek design, powerful 591-hp twin-turbo V8, and luxurious interior. It's available in various colors including red."
|
||||
},
|
||||
{
|
||||
"car_name": "Porsche Panamera GTS",
|
||||
"car_price": "$129,300",
|
||||
"car_url": "https://www.porsche.com/usa/models/panamera/panamera-models/panamera-gts/",
|
||||
"car_image": "https://files.porsche.com/filestore/image/multimedia/noneporsche-panamera-gts-sample-m02-high/normal/8a6327c3-6c7f-4c6f-a9a8-fb9f58b21795;sP;twebp/porsche-normal.webp",
|
||||
"car_description": "The Porsche Panamera GTS is a luxury sports sedan with a 473-hp V8 engine, exquisite handling, and available in stunning red. Balances sportiness and comfort."
|
||||
},
|
||||
{
|
||||
"car_name": "BMW M5",
|
||||
"car_price": "$105,500",
|
||||
"car_url": "https://www.bmwusa.com/vehicles/m-models/m5/sedan/overview.html",
|
||||
"car_image": "https://www.bmwusa.com/content/dam/bmwusa/M/m5/2023/bmw-my23-m5-sapphire-black-twilight-purple-exterior-02.jpg",
|
||||
"car_description": "The BMW M5 is a powerhouse sedan with a 600-hp V8 engine, known for its great handling and luxury. It comes in several distinctive colors including maroon."
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
## Resources
|
||||
|
||||
- [Mem0 Documentation](https://docs.mem0.ai)
|
||||
- [Mem0 Dashboard](https://app.mem0.ai/dashboard)
|
||||
- [API Reference](https://docs.mem0.ai/api-reference)
|
||||
- [OpenAI Documentation](https://platform.openai.com/docs)
|
||||
|
||||
---
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Agents SDK Tool with Mem0" icon="robot" href="/cookbooks/integrations/agents-sdk-tool">
|
||||
Extend the OpenAI Agents SDK with Mem0 integration capabilities.
|
||||
</Card>
|
||||
<Card title="Control Memory Ingestion" icon="filter" href="/cookbooks/essentials/controlling-memory-ingestion">
|
||||
Fine-tune what memories get stored during tool calls.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -0,0 +1,206 @@
|
||||
---
|
||||
title: Tavily Search with Mem0
|
||||
description: "Blend Tavily's realtime results with personal context stored in Mem0."
|
||||
---
|
||||
|
||||
|
||||
<Snippet file="security-compliance.mdx" />
|
||||
|
||||
Imagine asking a search assistant for "coffee shops nearby" and instead of generic results, it shows remote-work-friendly cafes with great WiFi in your city because it remembers you mentioned working remotely before. Or when you search for "lunchbox ideas for kids" it knows you have a 7-year-old daughter and recommends peanut-free options that align with her allergy.
|
||||
|
||||
That's what we are going to build today, a Personalized Search Assistant powered by Mem0 for memory and [Tavily](https://tavily.com) for real-time search.
|
||||
|
||||
|
||||
## Why Personalized Search
|
||||
|
||||
Most assistants treat every query like they've never seen you before. That means repeating yourself about your location, diet, or preferences, and getting results that feel generic.
|
||||
|
||||
- With Mem0, your assistant builds a memory of the user's world.
|
||||
- With Tavily, it fetches fresh and accurate results in real time.
|
||||
|
||||
Together, they make every interaction smarter, faster, and more personal.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before you begin, make sure you have:
|
||||
|
||||
1. Installed the dependencies:
|
||||
```bash
|
||||
pip install langchain mem0ai langchain-tavily langchain-openai
|
||||
```
|
||||
|
||||
2. Set up your API keys in a .env file:
|
||||
```bash
|
||||
OPENAI_API_KEY=your-openai-key
|
||||
TAVILY_API_KEY=your-tavily-key
|
||||
MEM0_API_KEY=your-mem0-key
|
||||
```
|
||||
|
||||
## Code Walkthrough
|
||||
Let’s break down the main components.
|
||||
|
||||
### 1: Initialize Mem0 with Custom Instructions
|
||||
|
||||
We configure Mem0 with custom instructions that guide it to infer user memories tailored specifically for our usecase.
|
||||
|
||||
```python
|
||||
from mem0 import MemoryClient
|
||||
|
||||
mem0_client = MemoryClient()
|
||||
|
||||
mem0_client.project.update(
|
||||
custom_instructions='''
|
||||
INFER THE MEMORIES FROM USER QUERIES EVEN IF IT'S A QUESTION.
|
||||
|
||||
We are building personalized search for which we need to understand about user's preferences and life
|
||||
and extract facts and memories accordingly.
|
||||
'''
|
||||
)
|
||||
```
|
||||
Now, if a user casually mentions "I need to pick up my daughter" or "What's the weather at Los Angeles", Mem0 remembers they have a daughter or the user is interested in or connected with Los Angeles in terms of location. These details will be referenced for future searches.
|
||||
|
||||
### 2. Simulating User History
|
||||
To test personalization, we preload some sample conversation history for a user:
|
||||
|
||||
```python
|
||||
def setup_user_history(user_id):
|
||||
conversations = [
|
||||
[{"role": "user", "content": "What will be the weather today at Los Angeles? I need to pick up my daughter from office."},
|
||||
{"role": "assistant", "content": "I'll check the weather in LA for you."}],
|
||||
[{"role": "user", "content": "I'm looking for vegan restaurants in Santa Monica"},
|
||||
{"role": "assistant", "content": "I'll find great vegan options in Santa Monica."}],
|
||||
[{"role": "user", "content": "My 7-year-old daughter is allergic to peanuts"},
|
||||
{"role": "assistant", "content": "I'll remember to check for peanut-free options."}],
|
||||
[{"role": "user", "content": "I work remotely and need coffee shops with good wifi"},
|
||||
{"role": "assistant", "content": "I'll find remote-work-friendly coffee shops."}],
|
||||
[{"role": "user", "content": "We love hiking and outdoor activities on weekends"},
|
||||
{"role": "assistant", "content": "Great! I'll keep your outdoor activity preferences in mind."}],
|
||||
]
|
||||
|
||||
for conversation in conversations:
|
||||
mem0_client.add(conversation, user_id=user_id)
|
||||
```
|
||||
This gives the agent a baseline understanding of the user’s lifestyle and needs.
|
||||
|
||||
### 3. Retrieving User Context from Memory
|
||||
When a user makes a new search query, we retrieve relevant memories to enhance the search query:
|
||||
|
||||
```python
|
||||
def get_user_context(user_id, query):
|
||||
# For Platform API, user_id goes in filters
|
||||
filters = {"user_id": user_id}
|
||||
user_memories = mem0_client.search(query=query, filters=filters)
|
||||
|
||||
if user_memories:
|
||||
context = "\n".join([f"- {memory['memory']}" for memory in user_memories])
|
||||
return context
|
||||
else:
|
||||
return "No previous user context available."
|
||||
```
|
||||
This context is injected into the search agent so results are personalized.
|
||||
|
||||
### 4. Creating the Personalized Search Agent
|
||||
The agent uses Tavily search, but always augments search queries with user context:
|
||||
|
||||
```python
|
||||
def create_personalized_search_agent(user_context):
|
||||
tavily_search = TavilySearch(
|
||||
max_results=10,
|
||||
search_depth="advanced",
|
||||
include_answer=True,
|
||||
topic="general"
|
||||
)
|
||||
|
||||
tools = [tavily_search]
|
||||
|
||||
prompt = ChatPromptTemplate.from_messages([
|
||||
("system", f"""You are a personalized search assistant.
|
||||
|
||||
USER CONTEXT AND PREFERENCES:
|
||||
{user_context}
|
||||
|
||||
YOUR ROLE:
|
||||
1. Analyze the user's query and context.
|
||||
2. Enhance the query with relevant personal memories.
|
||||
3. Always use tavily_search for results.
|
||||
4. Explain which memories influenced personalization.
|
||||
"""),
|
||||
MessagesPlaceholder(variable_name="messages"),
|
||||
MessagesPlaceholder(variable_name="agent_scratchpad"),
|
||||
])
|
||||
|
||||
agent = create_openai_tools_agent(llm=llm, tools=tools, prompt=prompt)
|
||||
return AgentExecutor(agent=agent, tools=tools, verbose=True, return_intermediate_steps=True)
|
||||
```
|
||||
|
||||
### 5. Run a Personalized Search
|
||||
The workflow ties everything together:
|
||||
|
||||
```python
|
||||
def conduct_personalized_search(user_id, query):
|
||||
user_context = get_user_context(user_id, query)
|
||||
agent_executor = create_personalized_search_agent(user_context)
|
||||
|
||||
response = agent_executor.invoke({"messages": [HumanMessage(content=query)]})
|
||||
return {"agent_response": response['output']}
|
||||
```
|
||||
|
||||
### 6. Store New Interactions
|
||||
Every new query/response pair is stored for future personalization:
|
||||
|
||||
```python
|
||||
def store_search_interaction(user_id, original_query, agent_response):
|
||||
interaction = [
|
||||
{"role": "user", "content": f"Searched for: {original_query}"},
|
||||
{"role": "assistant", "content": f"Results based on preferences: {agent_response}"}
|
||||
]
|
||||
mem0_client.add(messages=interaction, user_id=user_id)
|
||||
```
|
||||
|
||||
### Full Example Run
|
||||
|
||||
```python
|
||||
if __name__ == "__main__":
|
||||
user_id = "john"
|
||||
setup_user_history(user_id)
|
||||
|
||||
queries = [
|
||||
"good coffee shops nearby for working",
|
||||
"what can I make for my kid in lunch?"
|
||||
]
|
||||
|
||||
for q in queries:
|
||||
results = conduct_personalized_search(user_id, q)
|
||||
print(f"\nQuery: {q}")
|
||||
print(f"Personalized Response: {results['agent_response']}")
|
||||
```
|
||||
|
||||
## How It Works in Practice
|
||||
|
||||
Here's how personalization plays out:
|
||||
|
||||
- **Context Gathering**: User previously mentioned living in Los Angeles, being vegan, and having a 7-year-old daughter allergic to peanuts.
|
||||
- **Enhanced Search Query**:
|
||||
- Query: "good coffee shops nearby for working"
|
||||
- Enhanced Query: "good coffee shops in Los Angeles with strong WiFi, remote-work-friendly"
|
||||
- **Personalized Results**: The assistant only returns WiFi-friendly, work-friendly cafes near Los Angeles.
|
||||
- **Memory Update**: Interaction is saved for better future recommendations.
|
||||
|
||||
## Conclusion
|
||||
|
||||
With Mem0 and Tavily, you can build a search assistant that doesn't just fetch results but understands the person behind the query.
|
||||
|
||||
Whether for shopping, travel, or daily life, this approach turns a generic search into a truly personalized experience.
|
||||
|
||||
Full Code: [Personalized Search GitHub](https://github.com/mem0ai/mem0/blob/main/examples/misc/personalized_search.py)
|
||||
|
||||
---
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Deep Research with Mem0" icon="magnifying-glass" href="/cookbooks/operations/deep-research">
|
||||
Build comprehensive research agents that remember findings across sessions.
|
||||
</Card>
|
||||
<Card title="Tag and Organize Memories" icon="tag" href="/cookbooks/essentials/tagging-and-organizing-memories">
|
||||
Categorize search results and user preferences for better personalization.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -0,0 +1,221 @@
|
||||
---
|
||||
title: Content Writing with Mem0
|
||||
description: "Store voice guidelines once and apply them across every draft."
|
||||
---
|
||||
|
||||
|
||||
This guide demonstrates how to leverage **Mem0** to streamline content writing by applying your unique writing style and preferences using persistent memory.
|
||||
|
||||
## Why Use Mem0?
|
||||
|
||||
Integrating Mem0 into your writing workflow helps you:
|
||||
|
||||
1. **Store persistent writing preferences** ensuring consistent tone, formatting, and structure.
|
||||
2. **Automate content refinement** by retrieving preferences when rewriting or reviewing content.
|
||||
3. **Scale your writing style** so it applies consistently across multiple documents or sessions.
|
||||
|
||||
## Setup
|
||||
|
||||
```python
|
||||
import os
|
||||
from openai import OpenAI
|
||||
from mem0 import MemoryClient
|
||||
|
||||
os.environ["MEM0_API_KEY"] = "your-mem0-api-key"
|
||||
os.environ["OPENAI_API_KEY"] = "your-openai-api-key"
|
||||
|
||||
|
||||
# Set up Mem0 and OpenAI client
|
||||
client = MemoryClient()
|
||||
openai = OpenAI()
|
||||
|
||||
USER_ID = "content_writer"
|
||||
RUN_ID = "smart_editing_session"
|
||||
```
|
||||
|
||||
## Storing Your Writing Preferences in Mem0
|
||||
|
||||
```python
|
||||
def store_writing_preferences():
|
||||
"""Store your writing preferences in Mem0."""
|
||||
|
||||
preferences = """My writing preferences:
|
||||
1. Use headings and sub-headings for structure.
|
||||
2. Keep paragraphs concise (8–10 sentences max).
|
||||
3. Incorporate specific numbers and statistics.
|
||||
4. Provide concrete examples.
|
||||
5. Use bullet points for clarity.
|
||||
6. Avoid jargon and buzzwords."""
|
||||
|
||||
messages = [
|
||||
{"role": "user", "content": "Here are my writing style preferences."},
|
||||
{"role": "assistant", "content": preferences}
|
||||
]
|
||||
|
||||
response = client.add(
|
||||
messages,
|
||||
user_id=USER_ID,
|
||||
run_id=RUN_ID,
|
||||
metadata={"type": "preferences", "category": "writing_style"}
|
||||
)
|
||||
|
||||
return response
|
||||
```
|
||||
|
||||
## Editing Content Using Stored Preferences
|
||||
|
||||
```python
|
||||
def apply_writing_style(original_content):
|
||||
"""Use preferences stored in Mem0 to guide content rewriting."""
|
||||
|
||||
results = client.search(
|
||||
query="What are my writing style preferences?",
|
||||
filters={
|
||||
"AND": [
|
||||
{"user_id": USER_ID},
|
||||
{"run_id": RUN_ID}
|
||||
]
|
||||
}
|
||||
)
|
||||
|
||||
if not results:
|
||||
print("No preferences found.")
|
||||
return None
|
||||
|
||||
preferences = "\n".join(r["memory"] for r in results.get('results', []))
|
||||
|
||||
system_prompt = f"""
|
||||
You are a writing assistant.
|
||||
|
||||
Apply the following writing style preferences to improve the user's content:
|
||||
|
||||
Preferences:
|
||||
{preferences}
|
||||
"""
|
||||
|
||||
messages = [
|
||||
{"role": "system", "content": system_prompt},
|
||||
{"role": "user", "content": f"""Original Content:
|
||||
{original_content}"""}
|
||||
]
|
||||
|
||||
response = openai.chat.completions.create(
|
||||
model="gpt-4.1-nano-2025-04-14",
|
||||
messages=messages
|
||||
)
|
||||
clean_response = response.choices[0].message.content.strip()
|
||||
|
||||
return clean_response
|
||||
```
|
||||
|
||||
## Complete Workflow: Content Editing
|
||||
|
||||
```python
|
||||
def content_writing_workflow(content):
|
||||
"""Automated workflow for editing a document based on writing preferences."""
|
||||
|
||||
# Store writing preferences (if not already stored)
|
||||
store_writing_preferences() # Ideally done once, or with a conditional check
|
||||
|
||||
# Edit the document with Mem0 preferences
|
||||
edited_content = apply_writing_style(content)
|
||||
|
||||
if not edited_content:
|
||||
return "Failed to edit document."
|
||||
|
||||
# Display results
|
||||
print("\n=== ORIGINAL DOCUMENT ===\n")
|
||||
print(content)
|
||||
|
||||
print("\n=== EDITED DOCUMENT ===\n")
|
||||
print(edited_content)
|
||||
|
||||
return edited_content
|
||||
```
|
||||
|
||||
## Example Usage
|
||||
|
||||
```python
|
||||
# Define your document
|
||||
original_content = """Project Proposal
|
||||
|
||||
The following proposal outlines our strategy for the Q3 marketing campaign.
|
||||
We believe this approach will significantly increase our market share.
|
||||
|
||||
Increase brand awareness
|
||||
Boost sales by 15%
|
||||
Expand our social media following
|
||||
|
||||
We plan to launch the campaign in July and continue through September.
|
||||
"""
|
||||
|
||||
# Run the workflow
|
||||
result = content_writing_workflow(original_content)
|
||||
```
|
||||
|
||||
## Expected Output
|
||||
|
||||
Your document will be transformed into a structured, well-formatted version based on your preferences.
|
||||
|
||||
### Original Document
|
||||
```
|
||||
Project Proposal
|
||||
|
||||
The following proposal outlines our strategy for the Q3 marketing campaign.
|
||||
We believe this approach will significantly increase our market share.
|
||||
|
||||
Increase brand awareness
|
||||
Boost sales by 15%
|
||||
Expand our social media following
|
||||
|
||||
We plan to launch the campaign in July and continue through September.
|
||||
```
|
||||
|
||||
### Edited Document
|
||||
|
||||
```
|
||||
# Project Proposal
|
||||
|
||||
## Q3 Marketing Campaign Strategy
|
||||
|
||||
This proposal outlines our strategy for the Q3 marketing campaign. We aim to significantly increase our market share with this approach.
|
||||
|
||||
### Objectives
|
||||
|
||||
- **Increase Brand Awareness**: Implement targeted advertising and community engagement to enhance visibility.
|
||||
- **Boost Sales by 15%**: Increase sales by 15% compared to Q2 figures.
|
||||
- **Expand Social Media Following**: Grow our social media audience by 20%.
|
||||
|
||||
### Timeline
|
||||
|
||||
- **Launch Date**: July
|
||||
- **Duration**: July – September
|
||||
|
||||
### Key Actions
|
||||
|
||||
- **Targeted Advertising**: Utilize platforms like Google Ads and Facebook to reach specific demographics.
|
||||
- **Community Engagement**: Host webinars and live Q&A sessions.
|
||||
- **Content Creation**: Produce engaging videos and infographics.
|
||||
|
||||
### Supporting Data
|
||||
|
||||
- **Previous Campaign Success**: Our Q2 campaign increased sales by 12%. We will refine similar strategies for Q3.
|
||||
- **Social Media Growth**: Last year, our Instagram followers grew by 25% during a similar campaign.
|
||||
|
||||
### Conclusion
|
||||
|
||||
We believe this strategy will effectively increase our market share. To achieve these goals, we need your support and collaboration. Let’s work together to make this campaign a success. Please review the proposal and provide your feedback by the end of the week.
|
||||
```
|
||||
|
||||
Mem0 enables a seamless, intelligent content-writing workflow, perfect for content creators, marketers, and technical writers looking to scale their personal tone and structure across work.
|
||||
|
||||
---
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Control Memory Ingestion" icon="filter" href="/cookbooks/essentials/controlling-memory-ingestion">
|
||||
Filter and curate content examples to maintain consistent writing style.
|
||||
</Card>
|
||||
<Card title="Email Automation with Mem0" icon="envelope" href="/cookbooks/operations/email-automation">
|
||||
Automate email drafting with memory-powered context and tone matching.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -0,0 +1,79 @@
|
||||
---
|
||||
title: Deep Research with Mem0
|
||||
description: "Run multi-session investigations that remember past findings and preferences."
|
||||
---
|
||||
|
||||
|
||||
Deep Research is an intelligent agent that synthesizes large amounts of online data and completes complex research tasks, customized to your unique preferences and insights. Built on Mem0's technology, it enhances AI-driven online exploration with personalized memories.
|
||||
|
||||
You can check out the GitHub repository here: [Personalized Deep Research](https://github.com/mem0ai/personalized-deep-research/tree/mem0)
|
||||
|
||||
## Overview
|
||||
|
||||
Deep Research leverages Mem0's memory capabilities to:
|
||||
- Synthesize large amounts of online data
|
||||
- Complete complex research tasks
|
||||
- Customize results to your preferences
|
||||
- Store and utilize personal insights
|
||||
- Maintain context across research sessions
|
||||
|
||||
## Demo
|
||||
|
||||
Watch Deep Research in action:
|
||||
|
||||
<iframe
|
||||
width="700"
|
||||
height="400"
|
||||
src="https://www.youtube.com/embed/8vQlCtXzF60?si=b8iTOgummAVzR7ia"
|
||||
title="YouTube video player"
|
||||
frameborder="0"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
|
||||
referrerpolicy="strict-origin-when-cross-origin"
|
||||
allowfullscreen
|
||||
></iframe>
|
||||
|
||||
## Features
|
||||
|
||||
### 1. Personalized Research
|
||||
- Analyzes your background and expertise
|
||||
- Tailors research depth and complexity to your level
|
||||
- Incorporates your previous research context
|
||||
|
||||
### 2. Comprehensive Data Synthesis
|
||||
- Processes multiple online sources
|
||||
- Extracts relevant information
|
||||
- Provides coherent summaries
|
||||
|
||||
### 3. Memory Integration
|
||||
- Stores research findings for future reference
|
||||
- Maintains context across sessions
|
||||
- Links related research topics
|
||||
|
||||
### 4. Interactive Exploration
|
||||
- Allows real-time query refinement
|
||||
- Supports follow-up questions
|
||||
- Enables deep-diving into specific areas
|
||||
|
||||
## Use Cases
|
||||
|
||||
- **Academic Research**: Literature reviews, thesis research, paper writing
|
||||
- **Market Research**: Industry analysis, competitor research, trend identification
|
||||
- **Technical Research**: Technology evaluation, solution comparison
|
||||
- **Business Research**: Strategic planning, opportunity analysis
|
||||
|
||||
## Try It Out
|
||||
|
||||
> To try it yourself, clone the repository and follow the instructions in the README to run it locally or deploy it.
|
||||
|
||||
- [Personalized Deep Research GitHub](https://github.com/mem0ai/personalized-deep-research/tree/mem0)
|
||||
|
||||
---
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Search Memory Operations" icon="magnifying-glass" href="/core-concepts/memory-operations/search">
|
||||
Master semantic search to retrieve research findings across sessions.
|
||||
</Card>
|
||||
<Card title="YouTube Research with Mem0" icon="video" href="/cookbooks/companions/youtube-research">
|
||||
Build a video research assistant that remembers insights from content.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -0,0 +1,208 @@
|
||||
---
|
||||
title: Email Automation with Mem0
|
||||
description: "Capture, categorize, and recall inbox threads using persistent memories."
|
||||
---
|
||||
|
||||
|
||||
This guide demonstrates how to build an intelligent email processing system using Mem0's memory capabilities. You'll learn how to store, categorize, retrieve, and analyze emails to create a smart email management solution.
|
||||
|
||||
## Overview
|
||||
|
||||
Email overload is a common challenge for many professionals. By leveraging Mem0's memory capabilities, you can build an intelligent system that:
|
||||
|
||||
- Stores emails as searchable memories
|
||||
- Categorizes emails automatically
|
||||
- Retrieves relevant past conversations
|
||||
- Prioritizes messages based on importance
|
||||
- Generates summaries and action items
|
||||
|
||||
## Setup
|
||||
|
||||
Before you begin, ensure you have the required dependencies installed:
|
||||
|
||||
```bash
|
||||
pip install mem0ai openai
|
||||
```
|
||||
|
||||
## Implementation
|
||||
|
||||
### Basic Email Memory System
|
||||
|
||||
The following example shows how to create a basic email processing system with Mem0:
|
||||
|
||||
```python
|
||||
import os
|
||||
from mem0 import MemoryClient
|
||||
from email.parser import Parser
|
||||
|
||||
# Configure API keys
|
||||
os.environ["MEM0_API_KEY"] = "your-mem0-api-key"
|
||||
|
||||
# Initialize Mem0 client
|
||||
client = MemoryClient()
|
||||
|
||||
class EmailProcessor:
|
||||
def __init__(self):
|
||||
"""Initialize the Email Processor with Mem0 memory client"""
|
||||
self.client = client
|
||||
|
||||
def process_email(self, email_content, user_id):
|
||||
"""
|
||||
Process an email and store it in Mem0 memory
|
||||
|
||||
Args:
|
||||
email_content (str): Raw email content
|
||||
user_id (str): User identifier for memory association
|
||||
"""
|
||||
# Parse email
|
||||
parser = Parser()
|
||||
email = parser.parsestr(email_content)
|
||||
|
||||
# Extract email details
|
||||
sender = email['from']
|
||||
recipient = email['to']
|
||||
subject = email['subject']
|
||||
date = email['date']
|
||||
body = self._get_email_body(email)
|
||||
|
||||
# Create message object for Mem0
|
||||
message = {
|
||||
"role": "user",
|
||||
"content": f"Email from {sender}: {subject}\n\n{body}"
|
||||
}
|
||||
|
||||
# Create metadata for better retrieval
|
||||
metadata = {
|
||||
"email_type": "incoming",
|
||||
"sender": sender,
|
||||
"recipient": recipient,
|
||||
"subject": subject,
|
||||
"date": date
|
||||
}
|
||||
|
||||
# Store in Mem0 with appropriate categories
|
||||
response = self.client.add(
|
||||
messages=[message],
|
||||
user_id=user_id,
|
||||
metadata=metadata,
|
||||
categories=["email", "correspondence"],
|
||||
|
||||
)
|
||||
|
||||
return response
|
||||
|
||||
def _get_email_body(self, email):
|
||||
"""Extract the body content from an email"""
|
||||
# Simplified extraction - in real-world, handle multipart emails
|
||||
if email.is_multipart():
|
||||
for part in email.walk():
|
||||
if part.get_content_type() == "text/plain":
|
||||
return part.get_payload(decode=True).decode()
|
||||
else:
|
||||
return email.get_payload(decode=True).decode()
|
||||
|
||||
def search_emails(self, query, user_id, sender=None):
|
||||
"""
|
||||
Search through stored emails
|
||||
|
||||
Args:
|
||||
query (str): Search query
|
||||
user_id (str): User identifier
|
||||
sender (str, optional): Filter by sender email address
|
||||
"""
|
||||
# For Platform API, all filters including user_id go in filters object
|
||||
if not sender:
|
||||
# Simple filter - just user_id and category
|
||||
filters = {
|
||||
"AND": [
|
||||
{"user_id": user_id},
|
||||
{"categories": {"contains": "email"}}
|
||||
]
|
||||
}
|
||||
results = self.client.search(query=query, filters=filters)
|
||||
else:
|
||||
# Advanced filter - add sender condition
|
||||
filters = {
|
||||
"AND": [
|
||||
{"user_id": user_id},
|
||||
{"categories": {"contains": "email"}},
|
||||
{"sender": sender}
|
||||
]
|
||||
}
|
||||
results = self.client.search(query=query, filters=filters)
|
||||
|
||||
return results
|
||||
|
||||
def get_email_thread(self, subject, user_id):
|
||||
"""
|
||||
Retrieve all emails in a thread based on subject
|
||||
|
||||
Args:
|
||||
subject (str): Email subject to match
|
||||
user_id (str): User identifier
|
||||
"""
|
||||
# For Platform API, user_id goes in the filters object
|
||||
filters = {
|
||||
"AND": [
|
||||
{"user_id": user_id},
|
||||
{"categories": {"contains": "email"}},
|
||||
{"subject": {"icontains": subject}}
|
||||
]
|
||||
}
|
||||
|
||||
thread = self.client.get_all(filters=filters)
|
||||
|
||||
return thread
|
||||
|
||||
# Initialize the processor
|
||||
processor = EmailProcessor()
|
||||
|
||||
# Example raw email
|
||||
sample_email = """From: alice@example.com
|
||||
To: bob@example.com
|
||||
Subject: Meeting Schedule Update
|
||||
Date: Mon, 15 Jul 2024 14:22:05 -0700
|
||||
|
||||
Hi Bob,
|
||||
|
||||
I wanted to update you on the schedule for our upcoming project meeting.
|
||||
We'll be meeting this Thursday at 2pm instead of Friday.
|
||||
|
||||
Could you please prepare your section of the presentation?
|
||||
|
||||
Thanks,
|
||||
Alice
|
||||
"""
|
||||
|
||||
# Process and store the email
|
||||
user_id = "bob@example.com"
|
||||
processor.process_email(sample_email, user_id)
|
||||
|
||||
# Later, search for emails about meetings
|
||||
meeting_emails = processor.search_emails("meeting schedule", user_id)
|
||||
print(f"Found {len(meeting_emails['results'])} relevant emails")
|
||||
```
|
||||
|
||||
## Key Features and Benefits
|
||||
|
||||
- **Long-term Email Memory**: Store and retrieve email conversations across long periods
|
||||
- **Semantic Search**: Find relevant emails even if they don't contain exact keywords
|
||||
- **Intelligent Categorization**: Automatically sort emails into meaningful categories
|
||||
- **Action Item Extraction**: Identify and track tasks mentioned in emails
|
||||
- **Priority Management**: Focus on important emails based on AI-determined priority
|
||||
- **Context Awareness**: Maintain thread context for more relevant interactions
|
||||
|
||||
## Conclusion
|
||||
|
||||
By combining Mem0's memory capabilities with email processing, you can create intelligent email management systems that help users organize, prioritize, and act on their inbox effectively. The advanced capabilities like automatic categorization, action item extraction, and priority management can significantly reduce the time spent on email management, allowing users to focus on more important tasks.
|
||||
|
||||
---
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Tag and Organize Memories" icon="tag" href="/cookbooks/essentials/tagging-and-organizing-memories">
|
||||
Categorize email threads by sender, topic, and priority for faster retrieval.
|
||||
</Card>
|
||||
<Card title="Support Inbox with Mem0" icon="headset" href="/cookbooks/operations/support-inbox">
|
||||
Build customer support agents that remember context across tickets.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -0,0 +1,123 @@
|
||||
---
|
||||
title: Support Inbox with Mem0
|
||||
description: "Build a support assistant that keeps past tickets and resolutions at its fingertips."
|
||||
---
|
||||
|
||||
|
||||
You can create a personalized Customer Support AI Agent using Mem0. This guide will walk you through the necessary steps and provide the complete code to get you started.
|
||||
|
||||
## Overview
|
||||
|
||||
The Customer Support AI Agent leverages Mem0 to retain information across interactions, enabling a personalized and efficient support experience.
|
||||
|
||||
## Setup
|
||||
|
||||
Install the necessary packages using pip:
|
||||
|
||||
```bash
|
||||
pip install openai mem0ai
|
||||
```
|
||||
|
||||
## Full Code Example
|
||||
|
||||
Below is the simplified code to create and interact with a Customer Support AI Agent using Mem0:
|
||||
|
||||
```python
|
||||
import os
|
||||
from openai import OpenAI
|
||||
from mem0 import Memory
|
||||
|
||||
# Set the OpenAI API key
|
||||
os.environ['OPENAI_API_KEY'] = 'sk-xxx'
|
||||
|
||||
class CustomerSupportAIAgent:
|
||||
def __init__(self):
|
||||
"""
|
||||
Initialize the CustomerSupportAIAgent with memory configuration and OpenAI client.
|
||||
"""
|
||||
config = {
|
||||
"vector_store": {
|
||||
"provider": "qdrant",
|
||||
"config": {
|
||||
"host": "localhost",
|
||||
"port": 6333,
|
||||
}
|
||||
},
|
||||
}
|
||||
self.memory = Memory.from_config(config)
|
||||
self.client = OpenAI()
|
||||
self.app_id = "customer-support"
|
||||
|
||||
def handle_query(self, query, user_id=None):
|
||||
"""
|
||||
Handle a customer query and store the relevant information in memory.
|
||||
|
||||
:param query: The customer query to handle.
|
||||
:param user_id: Optional user ID to associate with the memory.
|
||||
"""
|
||||
# Start a streaming chat completion request to the AI
|
||||
stream = self.client.chat.completions.create(
|
||||
model="gpt-4",
|
||||
stream=True,
|
||||
messages=[
|
||||
{"role": "system", "content": "You are a customer support AI agent."},
|
||||
{"role": "user", "content": query}
|
||||
]
|
||||
)
|
||||
# Store the query in memory
|
||||
self.memory.add(query, user_id=user_id, metadata={"app_id": self.app_id})
|
||||
|
||||
# Print the response from the AI in real-time
|
||||
for chunk in stream:
|
||||
if chunk.choices[0].delta.content is not None:
|
||||
print(chunk.choices[0].delta.content, end="")
|
||||
|
||||
def get_memories(self, user_id=None):
|
||||
"""
|
||||
Retrieve all memories associated with the given customer ID.
|
||||
|
||||
:param user_id: Optional user ID to filter memories.
|
||||
:return: List of memories.
|
||||
"""
|
||||
return self.memory.get_all(user_id=user_id)
|
||||
|
||||
# Instantiate the CustomerSupportAIAgent
|
||||
support_agent = CustomerSupportAIAgent()
|
||||
|
||||
# Define a customer ID
|
||||
customer_id = "jane_doe"
|
||||
|
||||
# Handle a customer query
|
||||
support_agent.handle_query("I need help with my recent order. It hasn't arrived yet.", user_id=customer_id)
|
||||
```
|
||||
|
||||
### Fetching Memories
|
||||
|
||||
You can fetch all the memories at any point in time using the following code:
|
||||
|
||||
```python
|
||||
memories = support_agent.get_memories(user_id=customer_id)
|
||||
for m in memories['results']:
|
||||
print(m['memory'])
|
||||
```
|
||||
|
||||
### Key Points
|
||||
|
||||
- **Initialization**: The CustomerSupportAIAgent class is initialized with the necessary memory configuration and OpenAI client setup.
|
||||
- **Handling Queries**: The handle_query method sends a query to the AI and stores the relevant information in memory.
|
||||
- **Retrieving Memories**: The get_memories method fetches all stored memories associated with a customer.
|
||||
|
||||
### Conclusion
|
||||
|
||||
As the conversation progresses, Mem0's memory automatically updates based on the interactions, providing a continuously improving personalized support experience.
|
||||
|
||||
---
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Build a Mem0 Companion" icon="users" href="/cookbooks/essentials/building-ai-companion">
|
||||
Master the foundational patterns for building memory-powered assistants.
|
||||
</Card>
|
||||
<Card title="Email Automation with Mem0" icon="envelope" href="/cookbooks/operations/email-automation">
|
||||
Extend support capabilities with intelligent email processing and routing.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -0,0 +1,136 @@
|
||||
---
|
||||
title: Team Task Agent with Mem0
|
||||
description: "Coordinate multi-user projects with shared memories and roles."
|
||||
---
|
||||
|
||||
|
||||
## Overview
|
||||
|
||||
Build a multi-user collaborative chat or task management system with Mem0. Each message is attributed to its author, and all messages are stored in a shared project space. Mem0 makes it easy to track contributions, sort and group messages, and collaborate in real time.
|
||||
|
||||
## Setup
|
||||
|
||||
Install the required packages:
|
||||
|
||||
```bash
|
||||
pip install openai mem0ai
|
||||
```
|
||||
|
||||
## Full Code Example
|
||||
|
||||
```python
|
||||
from openai import OpenAI
|
||||
from mem0 import Memory
|
||||
import os
|
||||
from datetime import datetime
|
||||
from collections import defaultdict
|
||||
|
||||
# Set your OpenAI API key
|
||||
os.environ["OPENAI_API_KEY"] = "sk-your-key"
|
||||
|
||||
# Shared project context
|
||||
RUN_ID = "project-demo"
|
||||
|
||||
# Initialize Mem0
|
||||
mem = Memory()
|
||||
|
||||
class CollaborativeAgent:
|
||||
def __init__(self, run_id):
|
||||
self.run_id = run_id
|
||||
self.mem = mem
|
||||
|
||||
def add_message(self, role, name, content):
|
||||
msg = {"role": role, "name": name, "content": content}
|
||||
self.mem.add([msg], run_id=self.run_id, infer=False)
|
||||
|
||||
def brainstorm(self, prompt):
|
||||
# Get recent messages for context
|
||||
memories = self.mem.search(prompt, run_id=self.run_id, limit=5)["results"]
|
||||
context = "\n".join(f"- {m['memory']} (by {m.get('actor_id', 'Unknown')})" for m in memories)
|
||||
client = OpenAI()
|
||||
messages = [
|
||||
{"role": "system", "content": "You are a helpful project assistant."},
|
||||
{"role": "user", "content": f"Prompt: {prompt}\nContext:\n{context}"}
|
||||
]
|
||||
reply = client.chat.completions.create(
|
||||
model="gpt-4.1-nano-2025-04-14",
|
||||
messages=messages
|
||||
).choices[0].message.content.strip()
|
||||
self.add_message("assistant", "assistant", reply)
|
||||
return reply
|
||||
|
||||
def get_all_messages(self):
|
||||
return self.mem.get_all(run_id=self.run_id)["results"]
|
||||
|
||||
def print_sorted_by_time(self):
|
||||
messages = self.get_all_messages()
|
||||
messages.sort(key=lambda m: m.get('created_at', ''))
|
||||
print("\n--- Messages (sorted by time) ---")
|
||||
for m in messages:
|
||||
who = m.get("actor_id") or "Unknown"
|
||||
ts = m.get('created_at', 'Timestamp N/A')
|
||||
try:
|
||||
dt = datetime.fromisoformat(ts.replace('Z', '+00:00'))
|
||||
ts_fmt = dt.strftime('%Y-%m-%d %H:%M:%S')
|
||||
except Exception:
|
||||
ts_fmt = ts
|
||||
print(f"[{ts_fmt}] [{who}] {m['memory']}")
|
||||
|
||||
def print_grouped_by_actor(self):
|
||||
messages = self.get_all_messages()
|
||||
grouped = defaultdict(list)
|
||||
for m in messages:
|
||||
grouped[m.get("actor_id") or "Unknown"].append(m)
|
||||
print("\n--- Messages (grouped by actor) ---")
|
||||
for actor, mems in grouped.items():
|
||||
print(f"\n=== {actor} ===")
|
||||
for m in mems:
|
||||
ts = m.get('created_at', 'Timestamp N/A')
|
||||
try:
|
||||
dt = datetime.fromisoformat(ts.replace('Z', '+00:00'))
|
||||
ts_fmt = dt.strftime('%Y-%m-%d %H:%M:%S')
|
||||
except Exception:
|
||||
ts_fmt = ts
|
||||
print(f"[{ts_fmt}] {m['memory']}")
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```python
|
||||
# Example usage
|
||||
agent = CollaborativeAgent(RUN_ID)
|
||||
agent.add_message("user", "alice", "Let's list tasks for the new landing page.")
|
||||
agent.add_message("user", "bob", "I'll own the hero section copy.")
|
||||
agent.add_message("user", "carol", "I'll choose product screenshots.")
|
||||
|
||||
# Brainstorm with context
|
||||
print("\nAssistant reply:\n", agent.brainstorm("What are the current open tasks?"))
|
||||
|
||||
# Print all messages sorted by time
|
||||
agent.print_sorted_by_time()
|
||||
|
||||
# Print all messages grouped by actor
|
||||
agent.print_grouped_by_actor()
|
||||
```
|
||||
|
||||
## Key Points
|
||||
|
||||
- Each message is attributed to a user or agent (actor)
|
||||
- All messages are stored in a shared project space (`run_id`)
|
||||
- You can sort messages by time, group by actor, and format timestamps for clarity
|
||||
- Mem0 makes it easy to build collaborative, attributed chat/task systems
|
||||
|
||||
## Conclusion
|
||||
|
||||
Mem0 enables fast, transparent collaboration for teams and agents, with full attribution, flexible memory search, and easy message organization.
|
||||
|
||||
---
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Build AI with Personality" icon="sparkles" href="/cookbooks/essentials/building-ai-with-personality">
|
||||
Learn how to scope memories across users and agents for team workflows.
|
||||
</Card>
|
||||
<Card title="Support Inbox with Mem0" icon="headset" href="/cookbooks/operations/support-inbox">
|
||||
Apply collaborative memory patterns to customer support scenarios.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -0,0 +1,140 @@
|
||||
---
|
||||
title: Overview
|
||||
description: How to use mem0 in your existing applications?
|
||||
---
|
||||
|
||||
With Mem0, you can create stateful LLM-based applications such as chatbots, virtual assistants, or AI agents. Mem0 enhances your applications by providing a memory layer that makes responses:
|
||||
|
||||
- More personalized
|
||||
- More reliable
|
||||
- Cost-effective by reducing the number of LLM interactions
|
||||
- More engaging
|
||||
- Enables long-term memory
|
||||
|
||||
Here are some examples of how Mem0 can be integrated into various applications:
|
||||
|
||||
## Essentials
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Build a Mem0 Companion" icon="users" href="/cookbooks/essentials/building-ai-companion">
|
||||
Learn the core memory lifecycle before diving into codebases.
|
||||
</Card>
|
||||
<Card title="Scope User vs Agent Memories" icon="sparkles" href="/cookbooks/essentials/building-ai-with-personality">
|
||||
Balance personalization with consistent assistant behavior.
|
||||
</Card>
|
||||
<Card title="Control Memory Ingestion" icon="filter" href="/cookbooks/essentials/controlling-memory-ingestion">
|
||||
Filter speculation, enforce formats, and gate low-confidence data.
|
||||
</Card>
|
||||
<Card title="Set Memory Expiration" icon="timer" href="/cookbooks/essentials/memory-expiration-short-and-long-term">
|
||||
Define short-term versus long-term retention strategies.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Companion Playbooks
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Quickstart Demo with Mem0" icon="rocket" href="/cookbooks/companions/quickstart-demo">
|
||||
Spin up the showcase app to see Mem0 memories in action.
|
||||
</Card>
|
||||
<Card title="Node.js Companion with Mem0" icon="code" href="/cookbooks/companions/nodejs-companion">
|
||||
Build a JavaScript coach that remembers user goals.
|
||||
</Card>
|
||||
<Card title="AI Tutor with Mem0" icon="graduation-cap" href="/cookbooks/companions/ai-tutor">
|
||||
Deliver lessons that adapt to student progress and gaps.
|
||||
</Card>
|
||||
<Card title="Travel Assistant with Mem0" icon="plane" href="/cookbooks/companions/travel-assistant">
|
||||
Plan itineraries that remember traveler preferences across trips.
|
||||
</Card>
|
||||
<Card title="YouTube Research with Mem0" icon="video" href="/cookbooks/companions/youtube-research">
|
||||
Layer personalized context over any video in the browser.
|
||||
</Card>
|
||||
<Card title="Voice Companion with Mem0 and OpenAI" icon="microphone" href="/cookbooks/companions/voice-companion-openai">
|
||||
Pair the OpenAI Agents SDK with Mem0 for voice-first experiences.
|
||||
</Card>
|
||||
<Card title="Local Companion with Mem0 and Ollama" icon="server" href="/cookbooks/companions/local-companion-ollama">
|
||||
Run Mem0 end-to-end on your machine with Ollama models.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Ops & Automations
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Support Inbox with Mem0" icon="headset" href="/cookbooks/operations/support-inbox">
|
||||
Keep past tickets and resolutions at an agent's fingertips.
|
||||
</Card>
|
||||
<Card title="Email Automation with Mem0" icon="envelope" href="/cookbooks/operations/email-automation">
|
||||
Capture, categorize, and recall inbox threads via memory.
|
||||
</Card>
|
||||
<Card title="Content Writing with Mem0" icon="pencil" href="/cookbooks/operations/content-writing">
|
||||
Store tone and style guidelines once—apply them everywhere.
|
||||
</Card>
|
||||
<Card title="Deep Research with Mem0" icon="magnifying-glass" href="/cookbooks/operations/deep-research">
|
||||
Run multi-session investigations without repeating yourself.
|
||||
</Card>
|
||||
<Card title="Team Task Agent with Mem0" icon="users" href="/cookbooks/operations/team-task-agent">
|
||||
Coordinate projects with shared memories across contributors.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Integrations & Platforms
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Agents SDK Tool with Mem0" icon="robot" href="/cookbooks/integrations/agents-sdk-tool">
|
||||
Expose Mem0 memories as callable tools inside agent workflows.
|
||||
</Card>
|
||||
<Card title="OpenAI Tool Calls with Mem0" icon="wrench" href="/cookbooks/integrations/openai-tool-calls">
|
||||
Drop memories into OpenAI's inbuilt function-calling flows.
|
||||
</Card>
|
||||
<Card title="Mastra Agent with Mem0" icon="code" href="/cookbooks/integrations/mastra-agent">
|
||||
Extend Mastra agents with persistent memory state.
|
||||
</Card>
|
||||
<Card title="Healthcare Coach with Mem0 and Google ADK" icon="heart-pulse" href="/cookbooks/integrations/healthcare-google-adk">
|
||||
Remember patient history across ADK sessions.
|
||||
</Card>
|
||||
<Card title="AWS Bedrock with Mem0" icon="aws" href="/cookbooks/integrations/aws-bedrock">
|
||||
Pair Mem0 with Bedrock, OpenSearch, and Neptune Analytics.
|
||||
</Card>
|
||||
<Card title="Neptune Analytics with Mem0" icon="database" href="/cookbooks/integrations/neptune-analytics">
|
||||
Build a hybrid vector + graph memory store on AWS.
|
||||
</Card>
|
||||
<Card title="Tavily Search with Mem0" icon="search" href="/cookbooks/integrations/tavily-search">
|
||||
Blend realtime search with personal context.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Frameworks & Multimodal
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="LlamaIndex ReAct with Mem0" icon="brain" href="/cookbooks/frameworks/llamaindex-react">
|
||||
Teach a ReAct agent to store and recall context via Mem0.
|
||||
</Card>
|
||||
<Card title="LlamaIndex Multi-Agent with Mem0" icon="users" href="/cookbooks/frameworks/llamaindex-multiagent">
|
||||
Share a persistent memory layer across collaborating agents.
|
||||
</Card>
|
||||
<Card title="Multimodal Retrieval with Mem0" icon="image" href="/cookbooks/frameworks/multimodal-retrieval">
|
||||
Store and recall visual context alongside text conversations.
|
||||
</Card>
|
||||
<Card title="Eliza OS Character with Mem0" icon="robot" href="/cookbooks/frameworks/eliza-os-character">
|
||||
Bring persistent personality to Eliza OS agents.
|
||||
</Card>
|
||||
<Card title="Chrome Extension with Mem0" icon="globe" href="/cookbooks/frameworks/chrome-extension">
|
||||
Add Mem0's universal memory layer to Chrome chat surfaces.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
---
|
||||
|
||||
## Contribute a Cookbook
|
||||
|
||||
Have a unique Mem0 use case or integration? We'd love to feature your cookbook!
|
||||
|
||||
All cookbooks follow a standardized template to ensure consistency and quality. Check out our template to see the structure and best practices.
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Cookbook Template" icon="book-open" href="/templates/cookbook_template">
|
||||
Follow this structure for narrative, end-to-end Mem0 workflows.
|
||||
</Card>
|
||||
<Card title="Contribution Guide" icon="github" href="https://github.com/mem0ai/mem0/blob/main/CONTRIBUTING.md">
|
||||
Learn how to submit your cookbook to the Mem0 repository.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
Reference in New Issue
Block a user