feat: adding oss version of companion cookbook (#4564)

This commit is contained in:
Kartik
2026-03-28 21:11:59 +05:30
committed by GitHub
parent e280665578
commit 41abb571a2
@@ -10,6 +10,32 @@ Problem: LLMs are stateless. GPT doesn't remember conversations. You could stuff
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. 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.
<Tabs>
<Tab title="Platform">
</Tab>
<Tab title="Open Source">
Here we use **Mem0 open source** (`Memory`): all local, no API keys needed for memory. Vectors in **Qdrant**, LLM and embeddings via **Ollama**. The **OpenAI** Python SDK calls Ollama's **OpenAI-compatible** `/v1` endpoint for Ray's chat replies.
## Installation
Install the required dependencies:
```bash
pip install mem0ai qdrant-client openai ollama
```
Then start Qdrant and pull the Ollama models:
```bash
docker run -d -p 6333:6333 qdrant/qdrant
ollama pull llama3.1:latest
ollama pull nomic-embed-text:latest
```
<Note>You can swap `nomic-embed-text` for any Ollama-supported embedding model (e.g., `snowflake-arctic-embed`, `mxbai-embed-large`). Just update the `model` in the `embedder` config and set `embedding_model_dims` in the Qdrant config to match the model's output dimensions (768 for `nomic-embed-text`).</Note>
</Tab>
</Tabs>
In this cookbook we'll build a **fitness companion** that: In this cookbook we'll build a **fitness companion** that:
- Remembers user goals across sessions - Remembers user goals across sessions
@@ -25,6 +51,8 @@ By the end, you'll have a working fitness companion and know how to handle commo
Max wants to train for a marathon. He starts chatting with Ray, an AI running coach. Max wants to train for a marathon. He starts chatting with Ray, an AI running coach.
<Tabs>
<Tab title="Platform">
```python ```python
from openai import OpenAI from openai import OpenAI
from mem0 import MemoryClient from mem0 import MemoryClient
@@ -53,8 +81,73 @@ def chat(user_input, user_id):
], user_id=user_id) ], user_id=user_id)
return response return response
``` ```
</Tab>
<Tab title="Open Source">
```python
from openai import OpenAI
from mem0 import Memory
OLLAMA_URL = "http://localhost:11434"
CHAT_MODEL = "llama3.1:latest"
memory = Memory.from_config({
"vector_store": {
"provider": "qdrant",
"config": {
"collection_name": "fitness_companion",
"host": "localhost",
"port": 6333,
"embedding_model_dims": 768,
},
},
"llm": {
"provider": "ollama",
"config": {
"model": CHAT_MODEL,
"temperature": 0,
"max_tokens": 2000,
"ollama_base_url": OLLAMA_URL,
},
},
"embedder": {
"provider": "ollama",
"config": {
"model": "nomic-embed-text:latest",
"ollama_base_url": OLLAMA_URL,
},
},
})
ollama_chat = OpenAI(base_url=f"{OLLAMA_URL}/v1", api_key="ollama")
def chat(user_input, user_id):
# Retrieve relevant memories
memories = memory.search(user_input, user_id=user_id, limit=5)
context = "\n".join(m["memory"] for m in memories["results"])
# Call LLM with memory context (Ollama via OpenAI-compatible API)
response = ollama_chat.chat.completions.create(
model=CHAT_MODEL,
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
memory.add(
[
{"role": "user", "content": user_input},
{"role": "assistant", "content": response},
],
user_id=user_id,
)
return response
```
</Tab>
</Tabs>
**Session 1:** **Session 1:**
@@ -62,7 +155,6 @@ def chat(user_input, user_id):
chat("I want to run a marathon in under 4 hours", user_id="max") 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?" # Output: "That's a solid goal. What's your current weekly mileage?"
# Stored in Mem0: "Max wants to run sub-4 marathon" # Stored in Mem0: "Max wants to run sub-4 marathon"
``` ```
**Session 2 (next day, app restarted):** **Session 2 (next day, app restarted):**
@@ -70,7 +162,6 @@ chat("I want to run a marathon in under 4 hours", user_id="max")
```python ```python
chat("What should I focus on today?", user_id="max") 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..." # Output: "Based on your sub-4 marathon goal, let's work on building your aerobic base..."
``` ```
<Info> <Info>
@@ -87,6 +178,8 @@ Ray remembers. Restart the app, and the goal persists. From here on, we'll focus
Max mentions his knee hurts. That's different from his marathon goal - one is temporary, the other is long-term. Max mentions his knee hurts. That's different from his marathon goal - one is temporary, the other is long-term.
<Tabs>
<Tab title="Platform">
**Categories vs Metadata:** **Categories vs Metadata:**
- **Categories**: AI-assigned by Mem0 based on content (you can't force them) - **Categories**: AI-assigned by Mem0 based on content (you can't force them)
@@ -100,7 +193,6 @@ mem0_client.project.update(custom_categories=[
{"constraints": "Injuries, limitations, recovery needs"}, {"constraints": "Injuries, limitations, recovery needs"},
{"preferences": "Training style, surfaces, schedules"} {"preferences": "Training style, surfaces, schedules"}
]) ])
``` ```
<Note> <Note>
@@ -121,7 +213,6 @@ mem0_client.add(
[{"role": "user", "content": "My right knee flares up on downhills"}], [{"role": "user", "content": "My right knee flares up on downhills"}],
user_id="max" user_id="max"
) )
``` ```
Mem0 reads the content and intelligently picks which categories apply. You define the palette, it handles the tagging. Mem0 reads the content and intelligently picks which categories apply. You define the palette, it handles the tagging.
@@ -135,13 +226,50 @@ mem0_client.add(
user_id="max", user_id="max",
metadata={"workout_type": "speed", "forced_tag": "custom_label"} metadata={"workout_type": "speed", "forced_tag": "custom_label"}
) )
``` ```
</Tab>
<Tab title="Open Source">
**Categories via Metadata:**
In open source, model categories with a stable field in `metadata`—here we use `memory_bucket`:
```python
# Add goal
memory.add(
[{"role": "user", "content": "Sub-4 marathon is my A-race"}],
user_id="max",
metadata={"memory_bucket": "goals"},
)
# Add constraint
memory.add(
[{"role": "user", "content": "My right knee flares up on downhills"}],
user_id="max",
metadata={"memory_bucket": "constraints"},
)
```
<Note>
**Categories vs Metadata:** In open source, categories are modeled as `metadata` fields you set on each `add`. Filters only see what you put on `add`.
</Note>
```python
# Force tag using metadata
memory.add(
[{"role": "user", "content": "Some workout note"}],
user_id="max",
metadata={"memory_bucket": "goals", "workout_type": "speed", "forced_tag": "custom_label"},
)
```
</Tab>
</Tabs>
### Filtering by Category ### Filtering by Category
Retrieve just constraints for workout planning: Retrieve just constraints for workout planning:
<Tabs>
<Tab title="Platform">
```python ```python
constraints = mem0_client.search( constraints = mem0_client.search(
query="injury concerns", query="injury concerns",
@@ -155,8 +283,21 @@ constraints = mem0_client.search(
) )
print([m["memory"] for m in constraints["results"]]) print([m["memory"] for m in constraints["results"]])
# Output: ["Max's right knee flares up on downhills"] # Output: ["Max's right knee flares up on downhills"]
``` ```
</Tab>
<Tab title="Open Source">
```python
constraints = memory.search(
query="injury concerns",
user_id="max",
filters={"memory_bucket": {"in": ["constraints"]}},
threshold=0.0 # optional: widen recall for short phrases
)
print([m["memory"] for m in constraints["results"]])
# Output: ["Max's right knee flares up on downhills"]
```
</Tab>
</Tabs>
Ray can plan workouts that avoid aggravating Max's knee, without pulling in race goals or other unrelated memories. Ray can plan workouts that avoid aggravating Max's knee, without pulling in race goals or other unrelated memories.
@@ -168,12 +309,22 @@ Ray can plan workouts that avoid aggravating Max's knee, without pulling in race
Run the basic loop for a week and check what's stored: Run the basic loop for a week and check what's stored:
<Tabs>
<Tab title="Platform">
```python ```python
memories = mem0_client.get_all(filters={"AND": [{"user_id": "max"}]}) memories = mem0_client.get_all(filters={"AND": [{"user_id": "max"}]})
print([m["memory"] for m in memories["results"]]) print([m["memory"] for m in memories["results"]])
# Output: ["Max wants to run marathon under 4 hours", "hey", "lol ok", "cool thanks", "gtg bye"] # Output: ["Max wants to run marathon under 4 hours", "hey", "lol ok", "cool thanks", "gtg bye"]
``` ```
</Tab>
<Tab title="Open Source">
```python
memories = memory.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"]
```
</Tab>
</Tabs>
<Warning> <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. 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.
@@ -183,6 +334,8 @@ Noise. Greetings and filler clutter the memory.
### Custom Instructions ### Custom Instructions
<Tabs>
<Tab title="Platform">
Tell Mem0 what matters: Tell Mem0 what matters:
```python ```python
@@ -198,11 +351,38 @@ Exclude:
- Casual chatter - Casual chatter
- Hypotheticals unless planning related - Hypotheticals unless planning related
""") """)
``` ```
</Tab>
<Tab title="Open Source">
Tell Mem0 what matters by including `custom_fact_extraction_prompt` in the config dict:
```python
MEMORY_CONFIG["custom_fact_extraction_prompt"] = """
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
Return JSON with key "facts" as a list of strings (use [] if nothing to store).
"""
memory = Memory.from_config(MEMORY_CONFIG)
```
<Note>`custom_fact_extraction_prompt` is a top-level key in the config dictionary passed to `Memory.from_config()`. Make sure it's set before creating the Memory instance — not after.</Note>
</Tab>
</Tabs>
Now chat again: Now chat again:
<Tabs>
<Tab title="Platform">
```python ```python
chat("hey how's it going", user_id="max") chat("hey how's it going", user_id="max")
chat("I prefer trail running over roads", user_id="max") chat("I prefer trail running over roads", user_id="max")
@@ -210,8 +390,19 @@ chat("I prefer trail running over roads", user_id="max")
memories = mem0_client.get_all(filters={"AND": [{"user_id": "max"}]}) memories = mem0_client.get_all(filters={"AND": [{"user_id": "max"}]})
print([m["memory"] for m in memories["results"]]) print([m["memory"] for m in memories["results"]])
# Output: ["Max wants to run marathon under 4 hours", "Max prefers trail running over roads"] # Output: ["Max wants to run marathon under 4 hours", "Max prefers trail running over roads"]
``` ```
</Tab>
<Tab title="Open Source">
```python
chat("hey how's it going", user_id="max")
chat("I prefer trail running over roads", user_id="max")
memories = memory.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"]
```
</Tab>
</Tabs>
<Info> <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. **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.
@@ -221,8 +412,6 @@ Only meaningful facts. Filler gets dropped automatically.
--- ---
---
## Agent Memory for Personality ## Agent Memory for Personality
### Why Agents Need Memory Too ### Why Agents Need Memory Too
@@ -231,16 +420,30 @@ Max prefers direct feedback, not motivational fluff. Ray needs to remember how t
Store agent personality: Store agent personality:
<Tabs>
<Tab title="Platform">
```python ```python
mem0_client.add( mem0_client.add(
[{"role": "system", "content": "Max wants direct, data-driven feedback. Skip motivational language."}], [{"role": "system", "content": "Max wants direct, data-driven feedback. Skip motivational language."}],
agent_id="ray_coach" agent_id="ray_coach"
) )
``` ```
</Tab>
<Tab title="Open Source">
```python
memory.add(
[{"role": "user", "content": "Max wants direct, data-driven feedback. Skip motivational language."}],
agent_id="ray_coach",
infer=False,
)
```
</Tab>
</Tabs>
Retrieve agent style alongside user memories: Retrieve agent style alongside user memories:
<Tabs>
<Tab title="Platform">
```python ```python
# Get coach personality # Get coach personality
agent_memories = mem0_client.search("coaching style", agent_id="ray_coach") agent_memories = mem0_client.search("coaching style", agent_id="ray_coach")
@@ -251,8 +454,26 @@ mem0_client.add([
{"role": "user", "content": "How'd my run look today?"}, {"role": "user", "content": "How'd my run look today?"},
{"role": "assistant", "content": "Pace was 8:15/mile. Heart rate 152, zone 2."} {"role": "assistant", "content": "Pace was 8:15/mile. Heart rate 152, zone 2."}
], user_id="max", agent_id="ray_coach") ], user_id="max", agent_id="ray_coach")
``` ```
</Tab>
<Tab title="Open Source">
```python
# Get coach personality
agent_memories = memory.search("coaching style", agent_id="ray_coach")
# Output: ["Max wants direct, data-driven feedback. Skip motivational language."]
# Store conversations with agent_id
memory.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",
)
```
</Tab>
</Tabs>
<Info> <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. **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.
@@ -268,6 +489,8 @@ No "Great job!" or "Keep it up!" - just data. Ray adapts to Max's preference.
Don't send every single message to Mem0. Keep recent context in memory, let Mem0 handle the important long-term facts. Don't send every single message to Mem0. Keep recent context in memory, let Mem0 handle the important long-term facts.
<Tabs>
<Tab title="Platform">
```python ```python
# Store only meaningful exchanges in Mem0 # Store only meaningful exchanges in Mem0
mem0_client.add([ mem0_client.add([
@@ -280,8 +503,27 @@ mem0_client.add([
# "cool thanks" → don't store # "cool thanks" → don't store
# Or rely on custom_instructions to filter automatically # Or rely on custom_instructions to filter automatically
``` ```
</Tab>
<Tab title="Open Source">
```python
# Store only meaningful exchanges in Mem0
memory.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_fact_extraction_prompt to filter automatically
```
</Tab>
</Tabs>
Last 10 messages in your app's buffer. Important facts in Mem0. Faster, cheaper, still works. Last 10 messages in your app's buffer. Important facts in Mem0. Faster, cheaper, still works.
@@ -293,6 +535,8 @@ Last 10 messages in your app's buffer. Important facts in Mem0. Faster, cheaper,
Max tweaks his ankle. It'll heal in two weeks - the memory should expire too. Max tweaks his ankle. It'll heal in two weeks - the memory should expire too.
<Tabs>
<Tab title="Platform">
```python ```python
from datetime import datetime, timedelta from datetime import datetime, timedelta
@@ -303,10 +547,26 @@ mem0_client.add(
user_id="max", user_id="max",
expiration_date=expiration expiration_date=expiration
) )
``` ```
In 14 days, this memory disappears automatically. Ray stops asking about the ankle. In 14 days, this memory disappears automatically. Ray stops asking about the ankle.
</Tab>
<Tab title="Open Source">
```python
from datetime import datetime, timedelta
expiration = (datetime.now() + timedelta(days=14)).strftime("%Y-%m-%d")
memory.add(
[{"role": "user", "content": "Rolled my left ankle, needs rest"}],
user_id="max",
metadata={"memory_bucket": "constraints", "expires_on": expiration},
)
```
Store `expires_on` in metadata and prune expired memories in your app. Ray stops asking about the ankle once it's removed.
</Tab>
</Tabs>
--- ---
@@ -314,6 +574,8 @@ In 14 days, this memory disappears automatically. Ray stops asking about the ank
Here's the Mem0 setup combining everything: Here's the Mem0 setup combining everything:
<Tabs>
<Tab title="Platform">
```python ```python
from mem0 import MemoryClient from mem0 import MemoryClient
from datetime import datetime, timedelta from datetime import datetime, timedelta
@@ -332,11 +594,55 @@ mem0_client.project.update(
{"name": "preferences", "description": "Training style"} {"name": "preferences", "description": "Training style"}
] ]
) )
``` ```
</Tab>
<Tab title="Open Source">
```python
from mem0 import Memory
from datetime import datetime, timedelta
MEMORY_CONFIG = {
"vector_store": {
"provider": "qdrant",
"config": {
"collection_name": "fitness_companion",
"host": "localhost",
"port": 6333,
"embedding_model_dims": 768,
},
},
"llm": {
"provider": "ollama",
"config": {
"model": "llama3.1:latest",
"temperature": 0,
"max_tokens": 2000,
"ollama_base_url": "http://localhost:11434",
},
},
"embedder": {
"provider": "ollama",
"config": {
"model": "nomic-embed-text:latest",
"ollama_base_url": "http://localhost:11434",
},
},
"custom_fact_extraction_prompt": """
Extract: goals, constraints, preferences, progress
Exclude: greetings, filler, casual chat
Return JSON with key "facts" as a list of strings.
""",
}
memory = Memory.from_config(MEMORY_CONFIG)
```
</Tab>
</Tabs>
**Week 1 - Store goals and preferences:** **Week 1 - Store goals and preferences:**
<Tabs>
<Tab title="Platform">
```python ```python
mem0_client.add([ mem0_client.add([
{"role": "user", "content": "I want to run a sub-4 marathon"}, {"role": "user", "content": "I want to run a sub-4 marathon"},
@@ -346,11 +652,33 @@ mem0_client.add([
mem0_client.add([ mem0_client.add([
{"role": "user", "content": "I prefer trail running over roads"} {"role": "user", "content": "I prefer trail running over roads"}
], user_id="max", categories=["preferences"]) ], user_id="max", categories=["preferences"])
``` ```
</Tab>
<Tab title="Open Source">
```python
memory.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",
metadata={"memory_bucket": "goals"},
)
memory.add(
[{"role": "user", "content": "I prefer trail running over roads"}],
user_id="max",
metadata={"memory_bucket": "preferences"},
)
```
</Tab>
</Tabs>
**Week 3 - Temporary injury with expiration:** **Week 3 - Temporary injury with expiration:**
<Tabs>
<Tab title="Platform">
```python ```python
expiration = (datetime.now() + timedelta(days=14)).strftime("%Y-%m-%d") expiration = (datetime.now() + timedelta(days=14)).strftime("%Y-%m-%d")
mem0_client.add( mem0_client.add(
@@ -359,16 +687,36 @@ mem0_client.add(
categories=["constraints"], categories=["constraints"],
expiration_date=expiration expiration_date=expiration
) )
``` ```
</Tab>
<Tab title="Open Source">
```python
expiration = (datetime.now() + timedelta(days=14)).strftime("%Y-%m-%d")
memory.add(
[{"role": "user", "content": "Rolled ankle, need light workouts"}],
user_id="max",
metadata={"memory_bucket": "constraints", "expires_on": expiration},
)
```
</Tab>
</Tabs>
**Retrieve for context:** **Retrieve for context:**
<Tabs>
<Tab title="Platform">
```python ```python
memories = mem0_client.search("training plan", user_id="max", limit=5) memories = mem0_client.search("training plan", user_id="max", limit=5)
# Gets: marathon goal, trail preference, ankle injury (if still valid) # Gets: marathon goal, trail preference, ankle injury (if still valid)
``` ```
</Tab>
<Tab title="Open Source">
```python
memories = memory.search("training plan", user_id="max", limit=5)
# Gets: marathon goal, trail preference, ankle injury (if still valid / not pruned)
```
</Tab>
</Tabs>
Ray remembers goals, preferences, and personality. Handles temporary injuries. Works across sessions. Ray remembers goals, preferences, and personality. Handles temporary injuries. Works across sessions.
@@ -380,6 +728,8 @@ Ray remembers goals, preferences, and personality. Handles temporary injuries. W
Training for Boston is different from training for New York. Separate the memory threads: Training for Boston is different from training for New York. Separate the memory threads:
<Tabs>
<Tab title="Platform">
```python ```python
mem0_client.add(messages, user_id="max", run_id="boston-2025") mem0_client.add(messages, user_id="max", run_id="boston-2025")
mem0_client.add(messages, user_id="max", run_id="nyc-2025") mem0_client.add(messages, user_id="max", run_id="nyc-2025")
@@ -390,8 +740,22 @@ boston_memories = mem0_client.search(
user_id="max", user_id="max",
run_id="boston-2025" run_id="boston-2025"
) )
``` ```
</Tab>
<Tab title="Open Source">
```python
memory.add(messages, user_id="max", run_id="boston-2025")
memory.add(messages, user_id="max", run_id="nyc-2025")
# Retrieve only Boston memories
boston_memories = memory.search(
"training plan",
user_id="max",
run_id="boston-2025",
)
```
</Tab>
</Tabs>
Each race gets its own episodic boundary. No cross-contamination. Each race gets its own episodic boundary. No cross-contamination.
@@ -399,6 +763,8 @@ Each race gets its own episodic boundary. No cross-contamination.
Max has 6 months of training logs to backfill: Max has 6 months of training logs to backfill:
<Tabs>
<Tab title="Platform">
```python ```python
old_logs = [ old_logs = [
[{"role": "user", "content": "Completed 20-mile long run"}], [{"role": "user", "content": "Completed 20-mile long run"}],
@@ -407,13 +773,27 @@ old_logs = [
for log in old_logs: for log in old_logs:
mem0_client.add(log, user_id="max") mem0_client.add(log, user_id="max")
``` ```
</Tab>
<Tab title="Open Source">
```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:
memory.add(log, user_id="max")
```
</Tab>
</Tabs>
### Handling Contradictions ### Handling Contradictions
Max changes his goal from sub-4 to sub-3:45: Max changes his goal from sub-4 to sub-3:45:
<Tabs>
<Tab title="Platform">
```python ```python
# Find the old memory # Find the old memory
memories = mem0_client.get_all(filters={"AND": [{"user_id": "max"}]}) memories = mem0_client.get_all(filters={"AND": [{"user_id": "max"}]})
@@ -421,8 +801,19 @@ goal_memory = [m for m in memories["results"] if "sub-4" in m["memory"]][0]
# Update it # Update it
mem0_client.update(goal_memory["id"], "Max wants to run sub-3:45 marathon") mem0_client.update(goal_memory["id"], "Max wants to run sub-3:45 marathon")
``` ```
</Tab>
<Tab title="Open Source">
```python
# Find the old memory
memories = memory.get_all(user_id="max")
goal_memory = [m for m in memories["results"] if "sub-4" in m["memory"]][0]
# Update it
memory.update(goal_memory["id"], "Max wants to run sub-3:45 marathon")
```
</Tab>
</Tabs>
Update instead of creating duplicates. Update instead of creating duplicates.
@@ -430,11 +821,20 @@ Update instead of creating duplicates.
Max works with Ray for running and Jordan for strength training: Max works with Ray for running and Jordan for strength training:
<Tabs>
<Tab title="Platform">
```python ```python
chat("easy run today", user_id="max", agent_id="ray") chat("easy run today", user_id="max", agent_id="ray")
chat("leg day workout", user_id="max", agent_id="jordan") chat("leg day workout", user_id="max", agent_id="jordan")
``` ```
</Tab>
<Tab title="Open Source">
```python
chat("easy run today", user_id="max", agent_id="ray")
chat("leg day workout", user_id="max", agent_id="jordan")
```
</Tab>
</Tabs>
Each coach maintains separate personality memory while sharing user context. Each coach maintains separate personality memory while sharing user context.
@@ -442,19 +842,44 @@ Each coach maintains separate personality memory while sharing user context.
Prioritize recent training over old data: Prioritize recent training over old data:
<Tabs>
<Tab title="Platform">
```python ```python
recent = mem0_client.search( recent = mem0_client.search(
"training progress", "training progress",
user_id="max", user_id="max",
filters={"created_at": {"gte": "2025-10-01"}} filters={"created_at": {"gte": "2025-10-01"}}
) )
``` ```
</Tab>
<Tab title="Open Source">
```python
# Qdrant range filters require numbers — store an epoch timestamp in metadata
from datetime import datetime
epoch = int(datetime(2025, 10, 15).timestamp())
memory.add(
[{"role": "user", "content": "Completed 18-mile long run"}],
user_id="max",
metadata={"logged_epoch": epoch},
)
cutoff = int(datetime(2025, 10, 1).timestamp())
recent = memory.search(
"training progress",
user_id="max",
filters={"logged_epoch": {"gte": cutoff}},
)
```
</Tab>
</Tabs>
### Metadata Tagging ### Metadata Tagging
Tag workouts by type: Tag workouts by type:
<Tabs>
<Tab title="Platform">
```python ```python
mem0_client.add( mem0_client.add(
[{"role": "user", "content": "10x400m intervals"}], [{"role": "user", "content": "10x400m intervals"}],
@@ -468,20 +893,48 @@ speed_sessions = mem0_client.search(
user_id="max", user_id="max",
filters={"metadata": {"workout_type": "speed"}} filters={"metadata": {"workout_type": "speed"}}
) )
``` ```
</Tab>
<Tab title="Open Source">
```python
memory.add(
[{"role": "user", "content": "10x400m intervals"}],
user_id="max",
metadata={"workout_type": "speed", "intensity": "high"},
)
# Later, find all speed workouts
speed_sessions = memory.search(
"speed work",
user_id="max",
filters={"workout_type": "speed"},
)
```
</Tab>
</Tabs>
### Pruning Old Memories ### Pruning Old Memories
Delete irrelevant memories: Delete irrelevant memories:
<Tabs>
<Tab title="Platform">
```python ```python
mem0_client.delete(memory_id="mem_xyz") mem0_client.delete(memory_id="mem_xyz")
# Or clear an entire run_id # Or clear an entire run_id
mem0_client.delete_all(user_id="max", run_id="old-training-cycle") mem0_client.delete_all(user_id="max", run_id="old-training-cycle")
``` ```
</Tab>
<Tab title="Open Source">
```python
memory.delete(memory_id="mem_xyz")
# Or clear an entire run_id
memory.delete_all(user_id="max", run_id="old-training-cycle")
```
</Tab>
</Tabs>
--- ---
@@ -515,7 +968,7 @@ Before launching:
- Define 2-3 categories (goals, constraints, preferences) - Define 2-3 categories (goals, constraints, preferences)
- Add expiration strategy for time-bound facts - Add expiration strategy for time-bound facts
- Implement error handling for API calls - Implement error handling for API calls
- Monitor memory quality in Mem0 dashboard - Monitor memory quality (Mem0 dashboard or `get_all` / Qdrant when local)
- Clear test data from production project - Clear test data from production project
--- ---