Compare commits

..
61 Commits
Author SHA1 Message Date
Dev KhantandGitHub 3db028c719 Docs: update webhook (#2238) 2025-02-21 00:48:59 +05:30
Dev KhantandGitHub c86b1e4d4c Docs: update webhooks (#2237) 2025-02-21 00:42:02 +05:30
Dev KhantandGitHub 5f5b738745 version bump -> 0.1.53 (#2236) 2025-02-20 23:58:54 +05:30
acaf47ed54 Project_id mandatory for Webhooks (#2232)
Co-authored-by: Deshraj Yadav <deshrajdry@gmail.com>
2025-02-20 23:57:29 +05:30
colaandGitHub 9734b2db7e delete same vector in retrieved_old_memory (#2201) 2025-02-20 10:10:09 -08:00
Saket AryanandGitHub 3fe31e1c31 Fix Build Errors (#2235) 2025-02-20 22:47:15 +05:30
Seetha Rama GupthaandGitHub f4c0f98fde Adding Native OpenSearch support for Mem0 (#2211) 2025-02-20 11:42:12 +05:30
Dev KhantandGitHub 6e781f616c Doc: Update Redis config (#2233) 2025-02-20 11:24:00 +05:30
Prateek ChhikaraandGitHub dcba83186a Updated docs (#2231) 2025-02-19 18:37:01 -08:00
Saket AryanandGitHub a6d305f8d0 Update Docs for Mem0 AI SDK (#2230) 2025-02-19 14:39:49 -08:00
Lennex ZinyandoandGitHub db512950b9 Docs updates (#2229) 2025-02-19 13:48:48 -08:00
Dev-Khant d4df9f6dfe fix webhook doc 2025-02-20 01:27:26 +05:30
Dev KhantandGitHub 0e6b20982a Docs: webhook announcement (#2228) 2025-02-19 15:52:13 +05:30
Dev KhantandGitHub 92e1a9b433 Docs: Update webhook (#2227) 2025-02-19 14:06:46 +05:30
Dev-Khant 3be356a0e9 Webhook doc update 2025-02-19 13:46:00 +05:30
Dev KhantandGitHub 760cd54ddf Webhook Support (#2225) 2025-02-19 00:04:01 -08:00
Deshraj YadavandGitHub 1436da18b1 Update docs (#2222) 2025-02-18 17:52:32 -08:00
Prateek ChhikaraandGitHub cc9acb7493 Added support of vision input 2025-02-18 11:47:13 -08:00
Dev KhantandGitHub cbee71a63e Proper error msg for API Key validation (#2220) 2025-02-18 23:59:59 +05:30
Dev KhantandGitHub b052a86424 Update API reference to remove Org/Proj (#2221) 2025-02-18 22:34:58 +05:30
95f5fb3ab4 Fix Vercel AI SDK Build Errors (#2219)
Co-authored-by: Dev Khant <devkhant24@gmail.com>
Co-authored-by: Deshraj Yadav <deshraj@gatech.edu>
2025-02-18 16:03:36 +05:30
Dev KhantandGitHub 04d7f2e48c Fix deprecation warning of output_format for ADD and Version Bump (#2216) 2025-02-18 10:50:56 +05:30
Lennex ZinyandoandGitHub be46f4eb40 [Docs] Docs update (#2199) 2025-02-17 10:30:40 -08:00
Dev KhantandGitHub f16a580ef6 Fix Azure OpenAI test (#2217) 2025-02-17 19:21:12 +05:30
Dev KhantandGitHub 095189d39a Update client in README (#2215) 2025-02-17 00:14:23 +05:30
Dev KhantandGitHub 064d28626b Doc: Update search output (#2208) 2025-02-14 06:34:47 +05:30
Dev KhantandGitHub cd31c5897a increase timeout and version bump (#2205) 2025-02-14 06:00:40 +05:30
Prateek ChhikaraandGitHub 0bb6137877 updated custom categories docs (#2207) 2025-02-13 11:55:04 -08:00
Saket AryanandGitHub 2c63f4d866 Added Typescript Docs and fixed a broken url (#2204) 2025-02-12 09:48:23 -08:00
Prateek ChhikaraandGitHub 3984b90f62 docs update (#2196) 2025-02-06 11:59:18 -08:00
Prateek ChhikaraandGitHub b08b50cbc6 added enhanced search params (#2195) 2025-02-05 12:34:52 -08:00
Dev KhantandGitHub 90096d6954 Doc: Add config params for Memory() (#2193) 2025-02-05 12:44:41 +05:30
Prateek ChhikaraandGitHub 7581974805 updated docs and resolved some bugs (#2186) 2025-02-01 12:29:46 -08:00
Prateek ChhikaraandGitHub a8fafb9368 updated docs for mem0 architecture diagram (#2185) 2025-02-01 11:43:17 -08:00
Dev KhantandGitHub 75a4a253f7 Doc: Fix full stack link (#2184) 2025-02-01 10:53:37 +05:30
Dev KhantandGitHub f9995d144f Update README.md 2025-02-01 00:37:08 +05:30
junmo1215andGitHub 8d3c8c695d Fix query filter in azure ai search (#2171) 2025-01-31 15:38:06 +05:30
Dev KhantandGitHub 9f27b88843 Update README.md 2025-01-31 12:00:24 +05:30
Dev KhantandGitHub d2f0e23dc8 Update README.md 2025-01-31 10:42:41 +05:30
Dev KhantandGitHub 6e23a6f00e Update README.md 2025-01-30 23:51:28 +05:30
Dev KhantandGitHub a06c9a99ae Doc changes and Storage fix (#2181) 2025-01-30 10:16:33 -08:00
Dev KhantandGitHub 63fbd2dc2c Doc: update banner link (#2180) 2025-01-28 12:41:44 +05:30
Dev KhantandGitHub 203943919b version bump - 0.1.48 (#2174) 2025-01-23 17:47:24 +05:30
Dev KhantandGitHub 04bbad67ac DeepSeek Integration (#2173) 2025-01-23 17:45:03 +05:30
Dev KhantandGitHub e1b527b73f Doc: update delete_users (#2169) 2025-01-22 13:28:12 +05:30
Dev KhantandGitHub 625846caf8 Doc: update delete_users (#2168) 2025-01-22 13:25:13 +05:30
Dev KhantandGitHub c1bd4e19fe version bump -> 0.1.47 (#2167) 2025-01-22 13:20:20 +05:30
Dev KhantandGitHub 8d172d6139 Update delete_users (#2166) 2025-01-22 13:18:26 +05:30
Dev KhantandGitHub a5355f7488 version bump -> 0.1.46 (#2164) 2025-01-21 10:07:34 +05:30
Yunsung LeeandGitHub f13f3b9283 Fix/es query filter (🚨 URGENT) (#2162) 2025-01-21 10:03:50 +05:30
Deshraj YadavandGitHub 56351d1f8d Fix async client update_project method (#2155) 2025-01-19 09:05:59 +05:30
Dev KhantandGitHub a9d1383909 Fix pytests (#2157) 2025-01-18 15:06:49 -08:00
Dev KhantandGitHub 80c9c6a577 Doc: Update V2 Search/GetAll docs (#2158) 2025-01-18 10:43:03 +05:30
Dev KhantandGitHub e4e5511642 Doc: Update API reference (#2154) 2025-01-18 01:06:22 +05:30
Dev KhantandGitHub a4b085553a Code formatting (#2153) 2025-01-16 12:33:56 +05:30
Prateek ChhikaraandGitHub e12273c7cb changes to docs for custom categories (#2146) 2025-01-15 12:43:15 -08:00
Saket AryanandGitHub ee2b5adfc0 Fix lib/utils issue (#2151) 2025-01-15 09:49:38 -08:00
Dev KhantandGitHub 205a03a5f2 Doc: Add update_project API (#2148) 2025-01-15 08:52:20 +05:30
Dev KhantandGitHub 7be029a26f Doc: Custom instructions/Categories (#2147) 2025-01-15 07:51:16 +05:30
Dev-Khant 0bd177b30c version bump -> 0.1.44 2025-01-15 05:55:26 +05:30
82359774b7 Custom instructions API improvements (#2140)
Co-authored-by: Deshraj Yadav <deshrajdry@gmail.com>
2025-01-15 05:54:23 +05:30
84 changed files with 4263 additions and 1811 deletions
+1 -1
View File
@@ -13,7 +13,7 @@ install:
install_all: install_all:
poetry install poetry install
poetry run pip install groq together boto3 litellm ollama chromadb sentence_transformers vertexai \ poetry run pip install groq together boto3 litellm ollama chromadb sentence_transformers vertexai \
google-generativeai elasticsearch google-generativeai elasticsearch opensearch-py
# Format code with ruff # Format code with ruff
format: format:
+76 -133
View File
@@ -45,50 +45,25 @@
[Mem0](https://mem0.ai) (pronounced as "mem-zero") enhances AI assistants and agents with an intelligent memory layer, enabling personalized AI interactions. Mem0 remembers user preferences, adapts to individual needs, and continuously improves over time, making it ideal for customer support chatbots, AI assistants, and autonomous systems. [Mem0](https://mem0.ai) (pronounced as "mem-zero") enhances AI assistants and agents with an intelligent memory layer, enabling personalized AI interactions. Mem0 remembers user preferences, adapts to individual needs, and continuously improves over time, making it ideal for customer support chatbots, AI assistants, and autonomous systems.
<!-- Start of Selection --> ### Features & Use Cases
<p style="display: flex;">
<span style="font-size: 1.2em;">New Feature: Introducing Graph Memory. Check out our <a href="https://docs.mem0.ai/open-source/graph-memory" target="_blank">documentation</a>.</span>
</p>
<!-- End of Selection -->
Core Capabilities:
- **Multi-Level Memory**: User, Session, and AI Agent memory retention with adaptive personalization
- **Developer-Friendly**: Simple API integration, cross-platform consistency, and hassle-free managed service
### Core Features Applications:
- **AI Assistants**: Seamless conversations with context and personalization
- **Multi-Level Memory**: User, Session, and AI Agent memory retention - **Learning & Support**: Tailored content recommendations and context-aware customer assistance
- **Adaptive Personalization**: Continuous improvement based on interactions - **Healthcare & Companions**: Patient history tracking and deeper relationship building
- **Developer-Friendly API**: Simple integration into various applications - **Productivity & Gaming**: Streamlined workflows and adaptive environments based on user behavior
- **Cross-Platform Consistency**: Uniform behavior across devices
- **Managed Service**: Hassle-free hosted solution
### How Mem0 works?
Mem0 leverages a hybrid database approach to manage and retrieve long-term memories for AI agents and assistants. Each memory is associated with a unique identifier, such as a user ID or agent ID, allowing Mem0 to organize and access memories specific to an individual or context.
When a message is added to the Mem0 using add() method, the system extracts relevant facts and preferences and stores it across data stores: a vector database, a key-value database, and a graph database. This hybrid approach ensures that different types of information are stored in the most efficient manner, making subsequent searches quick and effective.
When an AI agent or LLM needs to recall memories, it uses the search() method. Mem0 then performs search across these data stores, retrieving relevant information from each source. This information is then passed through a scoring layer, which evaluates their importance based on relevance, importance, and recency. This ensures that only the most personalized and useful context is surfaced.
The retrieved memories can then be appended to the LLM's prompt as needed, enhancing the personalization and relevance of its responses.
### Use Cases
Mem0 empowers organizations and individuals to enhance:
- **AI Assistants and agents**: Seamless conversations with a touch of déjà vu
- **Personalized Learning**: Tailored content recommendations and progress tracking
- **Customer Support**: Context-aware assistance with user preference memory
- **Healthcare**: Patient history and treatment plan management
- **Virtual Companions**: Deeper user relationships through conversation memory
- **Productivity**: Streamlined workflows based on user habits and task history
- **Gaming**: Adaptive environments reflecting player choices and progress
## Get Started ## Get Started
The easiest way to set up Mem0 is through the managed [Mem0 Platform](https://app.mem0.ai). This hosted solution offers automatic updates, advanced analytics, and dedicated support. [Sign up](https://app.mem0.ai) to get started. Get started quickly with [Mem0 Platform](https://app.mem0.ai) - our fully managed solution that provides automatic updates, advanced analytics, enterprise security, and dedicated support. [Create a free account](https://app.mem0.ai) to begin.
If you prefer to self-host, use the open-source Mem0 package. Follow the [installation instructions](#install) to get started. For complete control, you can self-host Mem0 using our open-source package. See the [Quickstart guide](#quickstart) below to set up your own instance.
## Installation Instructions <a name="install"></a> ## Quickstart Guide <a name="quickstart"></a>
Install the Mem0 package via pip: Install the Mem0 package via pip:
@@ -96,8 +71,6 @@ Install the Mem0 package via pip:
pip install mem0ai pip install mem0ai
``` ```
Alternatively, you can use Mem0 with one click on the hosted platform [here](https://app.mem0.ai/).
### Basic Usage ### Basic Usage
Mem0 requires an LLM to function, with `gpt-4o` from OpenAI as the default. However, it supports a variety of LLMs; for details, refer to our [Supported LLMs documentation](https://docs.mem0.ai/llms). Mem0 requires an LLM to function, with `gpt-4o` from OpenAI as the default. However, it supports a variety of LLMs; for details, refer to our [Supported LLMs documentation](https://docs.mem0.ai/llms).
@@ -105,101 +78,85 @@ Mem0 requires an LLM to function, with `gpt-4o` from OpenAI as the default. Howe
First step is to instantiate the memory: First step is to instantiate the memory:
```python ```python
from openai import OpenAI
from mem0 import Memory from mem0 import Memory
m = Memory() openai_client = OpenAI()
memory = Memory()
def chat_with_memories(message: str, user_id: str = "default_user") -> str:
# Retrieve relevant memories
relevant_memories = memory.search(query=message, user_id=user_id, limit=3)
memories_str = "\n".join(f"- {entry['memory']}" for entry in relevant_memories)
# Generate Assistant response
system_prompt = f"You are a helpful AI. Answer the question based on query and memories.\nUser Memories:\n{memories_str}"
messages = [{"role": "system", "content": system_prompt}, {"role": "user", "content": message}]
response = openai_client.chat.completions.create(model="gpt-4o-mini", messages=messages)
assistant_response = response.choices[0].message.content
# Create new memories from the conversation
messages.append({"role": "assistant", "content": assistant_response})
memory.add(messages, user_id=user_id)
return assistant_response
def main():
print("Chat with AI (type 'exit' to quit)")
while True:
user_input = input("You: ").strip()
if user_input.lower() == 'exit':
print("Goodbye!")
break
print(f"AI: {chat_with_memories(user_input)}")
if __name__ == "__main__":
main()
``` ```
<details> For more advanced usage and API documentation, visit our [documentation](https://docs.mem0.ai).
<summary>How to set OPENAI_API_KEY</summary>
```python
import os
os.environ["OPENAI_API_KEY"] = "sk-xxx"
```
</details>
You can perform the following task on the memory:
1. Add: Store a memory from any unstructured text
2. Update: Update memory of a given memory_id
3. Search: Fetch memories based on a query
4. Get: Return memories for a certain user/agent/session
5. History: Describe how a memory has changed over time for a specific memory ID
```python
# 1. Add: Store a memory from any unstructured text
result = m.add("I am working on improving my tennis skills. Suggest some online courses.", user_id="alice", metadata={"category": "hobbies"})
# Created memory --> 'Improving her tennis skills.' and 'Looking for online suggestions.'
```
```python
# 2. Update: update the memory
result = m.update(memory_id=<memory_id_1>, data="Likes to play tennis on weekends")
# Updated memory --> 'Likes to play tennis on weekends.' and 'Looking for online suggestions.'
```
```python
# 3. Search: search related memories
related_memories = m.search(query="What are Alice's hobbies?", user_id="alice")
# Retrieved memory --> 'Likes to play tennis on weekends'
```
```python
# 4. Get all memories
all_memories = m.get_all()
memory_id = all_memories["memories"][0] ["id"] # get a memory_id
# All memory items --> 'Likes to play tennis on weekends.' and 'Looking for online suggestions.'
```
```python
# 5. Get memory history for a particular memory_id
history = m.history(memory_id=<memory_id_1>)
# Logs corresponding to memory_id_1 --> {'prev_value': 'Working on improving tennis skills and interested in online courses for tennis.', 'new_value': 'Likes to play tennis on weekends' }
```
> [!TIP] > [!TIP]
> If you prefer a hosted version without the need to set up infrastructure yourself, check out the [Mem0 Platform](https://app.mem0.ai/) to get started in minutes. > For a hassle-free experience, try our [hosted platform](https://app.mem0.ai) with automatic updates and enterprise features.
## Demos
- AI Companion: Experience personalized conversations with an AI that remembers your preferences and past interactions
[AI Companion Demo](https://github.com/user-attachments/assets/3fc72023-a72c-4593-8be0-3cee3ba744da)
<br/><br/>
- Enhance your AI interactions by storing memories across ChatGPT, Perplexity, and Claude using our browser extension. Get [chrome extension](https://chromewebstore.google.com/detail/mem0/onihkkbipkfeijkadecaafbgagkhglop?hl=en).
### Graph Memory [Chrome Extension Demo](https://github.com/user-attachments/assets/ca92e40b-c453-4ff6-b25e-739fb18a8650)
To initialize Graph Memory you'll need to set up your configuration with graph store providers.
Currently, we support Neo4j as a graph store provider. You can setup [Neo4j](https://neo4j.com/) locally or use the hosted [Neo4j AuraDB](https://neo4j.com/product/auradb/).
Moreover, you also need to set the version to `v1.1` (*prior versions are not supported*).
Here's how you can do it:
```python <br/><br/>
from mem0 import Memory
config = { - Customer support bot using <strong>Langgraph and Mem0</strong>. Get the complete code from [here](https://docs.mem0.ai/integrations/langgraph)
"graph_store": {
"provider": "neo4j",
"config": { [Langgraph: Customer Bot](https://github.com/user-attachments/assets/ca6b482e-7f46-42c8-aa08-f88d1d93a5f4)
"url": "neo4j+s://xxx",
"username": "neo4j", <br/><br/>
"password": "xxx"
} - Use Mem0 with CrewAI to get personalized results. Full example [here](https://docs.mem0.ai/integrations/crewai)
},
"version": "v1.1" [CrewAI Demo](https://github.com/user-attachments/assets/69172a79-ccb9-4340-91f1-caa7d2dd4213)
}
m = Memory.from_config(config_dict=config)
```
## Documentation ## Documentation
For detailed usage instructions and API reference, visit our documentation at [docs.mem0.ai](https://docs.mem0.ai). Here, you can find more information on both the open-source version and the hosted [Mem0 Platform](https://app.mem0.ai). For detailed usage instructions and API reference, visit our [documentation](https://docs.mem0.ai). You'll find:
- Complete API reference
## Star History - Integration guides
- Advanced configuration options
[![Star History Chart](https://api.star-history.com/svg?repos=mem0ai/mem0&type=Date)](https://star-history.com/#mem0ai/mem0&Date) - Best practices and examples
- More details about:
- Open-source version
- [Hosted Mem0 Platform](https://app.mem0.ai)
## Support ## Support
@@ -209,20 +166,6 @@ Join our community for support and discussions. If you have any questions, feel
- [Follow us on Twitter](https://x.com/mem0ai) - [Follow us on Twitter](https://x.com/mem0ai)
- [Email founders](mailto:founders@mem0.ai) - [Email founders](mailto:founders@mem0.ai)
## Contributors
Join our [Discord community](https://mem0.dev/DiG) to learn about memory management for AI agents and LLMs, and connect with Mem0 users and contributors. Share your ideas, questions, or feedback in our [GitHub Issues](https://github.com/mem0ai/mem0/issues).
We value and appreciate the contributions of our community. Special thanks to our contributors for helping us improve Mem0.
<a href="https://github.com/mem0ai/mem0/graphs/contributors">
<img src="https://contrib.rocks/image?repo=mem0ai/mem0" />
</a>
## Anonymous Telemetry
We collect anonymous usage metrics to enhance our package's quality and user experience. This includes data like feature usage frequency and system info, but never personal details. The data helps us prioritize improvements and ensure compatibility. If you wish to opt-out, set the environment variable MEM0_TELEMETRY=false. We prioritize data security and don't share this data externally.
## License ## License
This project is licensed under the Apache 2.0 License - see the [LICENSE](LICENSE) file for details. This project is licensed under the Apache 2.0 License - see the [LICENSE](LICENSE) file for details.
@@ -17,7 +17,6 @@ Mem0 offers two versions of the search API: v1 and v2. Here's how they differ:
{ {
"id":"ea925981-272f-40dd-b576-be64e4871429", "id":"ea925981-272f-40dd-b576-be64e4871429",
"memory":"Likes to play cricket and plays cricket on weekends.", "memory":"Likes to play cricket and plays cricket on weekends.",
"hash":"c8809002-25c1-4c97-a3a2-227ce9c20c53",
"metadata":{ "metadata":{
"category":"hobbies" "category":"hobbies"
}, },
@@ -61,7 +60,6 @@ Mem0 offers two versions of the search API: v1 and v2. Here's how they differ:
{ {
"id": "ea925981-272f-40dd-b576-be64e4871429", "id": "ea925981-272f-40dd-b576-be64e4871429",
"memory": "Likes to play cricket and plays cricket on weekends.", "memory": "Likes to play cricket and plays cricket on weekends.",
"hash": "c8809002-25c1-4c97-a3a2-227ce9c20c53",
"metadata": { "metadata": {
"category": "hobbies" "category": "hobbies"
}, },
+5 -3
View File
@@ -1,4 +1,8 @@
# Mem0 API Overview ---
title: Overview
icon: "info"
iconType: "solid"
---
Mem0 provides a powerful set of APIs that allow you to integrate advanced memory management capabilities into your applications. Our APIs are designed to be intuitive, efficient, and scalable, enabling you to create, retrieve, update, and delete memories across various entities such as users, agents, apps, and runs. Mem0 provides a powerful set of APIs that allow you to integrate advanced memory management capabilities into your applications. Our APIs are designed to be intuitive, efficient, and scalable, enabling you to create, retrieve, update, and delete memories across various entities such as users, agents, apps, and runs.
@@ -43,8 +47,6 @@ client = MemoryClient(
project_id='YOUR_PROJECT_ID', project_id='YOUR_PROJECT_ID',
) )
``` ```
> **Note**: The use of `organization` and `project` parameters is deprecated and will be removed in version `0.1.40`. Please use `org_id` and `project_id` instead.
Example with the mem0 Node.js package: Example with the mem0 Node.js package:
@@ -1,4 +0,0 @@
---
title: 'Get Custom Instructions and Categories'
openapi: get /api/v1/orgs/organizations/{org_id}/projects/{project_id}/custom-instructions-and-categories/
---
@@ -1,6 +0,0 @@
---
title: 'Update Custom Instructions and Categories'
openapi: post /api/v1/orgs/organizations/{org_id}/projects/{project_id}/custom-instructions-and-categories/
---
Please refer to the [how to use custom instructions/categories](/features/custom-instructions) for more information.
@@ -0,0 +1,4 @@
---
title: 'Update Project'
openapi: patch /api/v1/orgs/organizations/{org_id}/projects/{project_id}/
---
+7 -3
View File
@@ -1,15 +1,19 @@
## What is Config? ---
title: Configurations
icon: "gear"
iconType: "solid"
---
Config in mem0 is a dictionary that specifies the settings for your embedding models. It allows you to customize the behavior and connection details of your chosen embedder. Config in mem0 is a dictionary that specifies the settings for your embedding models. It allows you to customize the behavior and connection details of your chosen embedder.
## How to Define Config ## How to define configurations?
The config is defined as a Python dictionary with two main keys: The config is defined as a Python dictionary with two main keys:
- `embedder`: Specifies the embedder provider and its configuration - `embedder`: Specifies the embedder provider and its configuration
- `provider`: The name of the embedder (e.g., "openai", "ollama") - `provider`: The name of the embedder (e.g., "openai", "ollama")
- `config`: A nested dictionary containing provider-specific settings - `config`: A nested dictionary containing provider-specific settings
## How to Use Config ## How to use configurations?
Here's a general example of how to use the config with mem0: Here's a general example of how to use the config with mem0:
+2
View File
@@ -1,5 +1,7 @@
--- ---
title: Overview title: Overview
icon: "info"
iconType: "solid"
--- ---
Mem0 offers support for various embedding models, allowing users to choose the one that best suits their needs. Mem0 offers support for various embedding models, allowing users to choose the one that best suits their needs.
+8 -5
View File
@@ -1,10 +1,12 @@
## What is Config? ---
title: Configurations
icon: "gear"
iconType: "solid"
---
Config in mem0 is a dictionary that specifies the settings for your llms. It allows you to customize the behavior and connection details of your chosen llm. ## How to define configurations?
## How to Define Config The `config` is defined as a Python dictionary with two main keys:
The config is defined as a Python dictionary with two main keys:
- `llm`: Specifies the llm provider and its configuration - `llm`: Specifies the llm provider and its configuration
- `provider`: The name of the llm (e.g., "openai", "groq") - `provider`: The name of the llm (e.g., "openai", "groq")
- `config`: A nested dictionary containing provider-specific settings - `config`: A nested dictionary containing provider-specific settings
@@ -72,6 +74,7 @@ Here's the table based on the provided parameters:
| `ollama_base_url` | Base URL for Ollama API | Ollama | | `ollama_base_url` | Base URL for Ollama API | Ollama |
| `openai_base_url` | Base URL for OpenAI API | OpenAI | | `openai_base_url` | Base URL for OpenAI API | OpenAI |
| `azure_kwargs` | Azure LLM args for initialization | AzureOpenAI | | `azure_kwargs` | Azure LLM args for initialization | AzureOpenAI |
| `deepseek_base_url` | Base URL for DeepSeek API | DeepSeek |
## Supported LLMs ## Supported LLMs
+49
View File
@@ -0,0 +1,49 @@
---
title: DeepSeek
---
To use DeepSeek LLM models, you have to set the `DEEPSEEK_API_KEY` environment variable. You can also optionally set `DEEPSEEK_API_BASE` if you need to use a different API endpoint (defaults to "https://api.deepseek.com").
## Usage
```python
import os
from mem0 import Memory
os.environ["DEEPSEEK_API_KEY"] = "your-api-key"
os.environ["OPENAI_API_KEY"] = "your-api-key" # for embedder model
config = {
"llm": {
"provider": "deepseek",
"config": {
"model": "deepseek-chat", # default model
"temperature": 0.2,
"max_tokens": 1500,
"top_p": 1.0
}
}
}
m = Memory.from_config(config)
m.add("Likes to play cricket on weekends", user_id="alice", metadata={"category": "hobbies"})
```
You can also configure the API base URL in the config:
```python
config = {
"llm": {
"provider": "deepseek",
"config": {
"model": "deepseek-chat",
"deepseek_base_url": "https://your-custom-endpoint.com",
"api_key": "your-api-key" # alternatively to using environment variable
}
}
}
```
## Config
All available parameters for the `deepseek` config are present in [Master List of All Params in Config](../config).
+3
View File
@@ -1,5 +1,7 @@
--- ---
title: Overview title: Overview
icon: "info"
iconType: "solid"
--- ---
Mem0 includes built-in support for various popular large language models. Memory can utilize the LLM provided by the user, ensuring efficient use for specific needs. Mem0 includes built-in support for various popular large language models. Memory can utilize the LLM provided by the user, ensuring efficient use for specific needs.
@@ -24,6 +26,7 @@ To view all supported llms, visit the [Supported LLMs](./models).
<Card title="Google AI" href="/components/llms/models/google_ai"></Card> <Card title="Google AI" href="/components/llms/models/google_ai"></Card>
<Card title="AWS bedrock" href="/components/llms/models/aws_bedrock"></Card> <Card title="AWS bedrock" href="/components/llms/models/aws_bedrock"></Card>
<Card title="Gemini" href="/components/llms/models/gemini"></Card> <Card title="Gemini" href="/components/llms/models/gemini"></Card>
<Card title="DeepSeek" href="/components/llms/models/deepseek"></Card>
</CardGroup> </CardGroup>
## Structured vs Unstructured Outputs ## Structured vs Unstructured Outputs
+7 -5
View File
@@ -1,10 +1,12 @@
## What is Config? ---
title: Configurations
icon: "gear"
iconType: "solid"
---
Config in mem0 is a dictionary that specifies the settings for your vector database. It allows you to customize the behavior and connection details of your chosen vector store. ## How to define configurations?
## How to Define Config The `config` is defined as a Python dictionary with two main keys:
The config is defined as a Python dictionary with two main keys:
- `vector_store`: Specifies the vector database provider and its configuration - `vector_store`: Specifies the vector database provider and its configuration
- `provider`: The name of the vector database (e.g., "chroma", "pgvector", "qdrant", "milvus","azure_ai_search") - `provider`: The name of the vector database (e.g., "chroma", "pgvector", "qdrant", "milvus","azure_ai_search")
- `config`: A nested dictionary containing provider-specific settings - `config`: A nested dictionary containing provider-specific settings
@@ -0,0 +1,59 @@
[OpenSearch](https://opensearch.org/) is an open-source, enterprise-grade search and observability suite that brings order to unstructured data at scale. OpenSearch supports k-NN (k-Nearest Neighbors) and allows you to store and retrieve high-dimensional vector embeddings efficiently.
### Installation
OpenSearch support requires additional dependencies. Install them with:
```bash
pip install opensearch>=2.8.0
```
### Usage
```python
import os
from mem0 import Memory
os.environ["OPENAI_API_KEY"] = "sk-xx"
config = {
"vector_store": {
"provider": "opensearch",
"config": {
"collection_name": "mem0",
"host": "localhost",
"port": 9200,
"embedding_model_dims": 1536
}
}
}
m = Memory.from_config(config)
m.add("Likes to play cricket on weekends", user_id="alice", metadata={"category": "hobbies"})
```
### Config
Let's see the available parameters for the `opensearch` config:
| Parameter | Description | Default Value |
| ---------------------- | -------------------------------------------------- | ------------- |
| `collection_name` | The name of the index to store the vectors | `mem0` |
| `embedding_model_dims` | Dimensions of the embedding model | `1536` |
| `host` | The host where the OpenSearch server is running | `localhost` |
| `port` | The port where the OpenSearch server is running | `9200` |
| `api_key` | API key for authentication | `None` |
| `user` | Username for basic authentication | `None` |
| `password` | Password for basic authentication | `None` |
| `verify_certs` | Whether to verify SSL certificates | `False` |
| `auto_create_index` | Whether to automatically create the index | `True` |
| `use_ssl` | Whether to use SSL for connection | `False` |
### Features
- Fast and Efficient Vector Search
- Can be deployed on-premises, in containers, or on cloud platforms like AWS OpenSearch Service.
- Multiple Authentication and Security Methods (Basic Authentication, API Keys, LDAP, SAML, and OpenID Connect)
- Automatic index creation with optimized mappings for vector search
- Memory Optimization through Disk-Based Vector Search and Quantization
- Real-Time Analytics and Observability
+1 -1
View File
@@ -30,7 +30,7 @@ Here's the parameters available for configuring pgvector:
| Parameter | Description | Default Value | | Parameter | Description | Default Value |
| --- | --- | --- | | --- | --- | --- |
| `dbname` | The name of the database | `postgres` | | `dbname` | The name of the | `postgres` |
| `collection_name` | The name of the collection | `mem0` | | `collection_name` | The name of the collection | `mem0` |
| `embedding_model_dims` | Dimensions of the embedding model | `1536` | | `embedding_model_dims` | Dimensions of the embedding model | `1536` |
| `user` | User name to connect to the database | `None` | | `user` | User name to connect to the database | `None` |
+2 -1
View File
@@ -26,7 +26,8 @@ config = {
"embedding_model_dims": 1536, "embedding_model_dims": 1536,
"redis_url": "redis://localhost:6379" "redis_url": "redis://localhost:6379"
} }
} },
"version": "v1.1"
} }
m = Memory.from_config(config) m = Memory.from_config(config)
+3
View File
@@ -1,5 +1,7 @@
--- ---
title: Overview title: Overview
icon: "info"
iconType: "solid"
--- ---
Mem0 includes built-in support for various popular databases. Memory can utilize the database provided by the user, ensuring efficient use for specific needs. Mem0 includes built-in support for various popular databases. Memory can utilize the database provided by the user, ensuring efficient use for specific needs.
@@ -16,6 +18,7 @@ See the list of supported vector databases below.
<Card title="Azure AI Search" href="/components/vectordbs/dbs/azure_ai_search"></Card> <Card title="Azure AI Search" href="/components/vectordbs/dbs/azure_ai_search"></Card>
<Card title="Redis" href="/components/vectordbs/dbs/redis"></Card> <Card title="Redis" href="/components/vectordbs/dbs/redis"></Card>
<Card title="Elasticsearch" href="/components/vectordbs/dbs/elasticsearch"></Card> <Card title="Elasticsearch" href="/components/vectordbs/dbs/elasticsearch"></Card>
<Card title="OpenSearch" href="/components/vectordbs/dbs/opensearch"></Card>
</CardGroup> </CardGroup>
## Usage ## Usage
+60
View File
@@ -0,0 +1,60 @@
---
title: Memory Operations
description: Understanding the core operations for managing memories in AI applications
icon: "gear"
iconType: "solid"
---
Mem0 provides two core operations for managing memories in AI applications: adding new memories and searching existing ones. This guide covers how these operations work and how to use them effectively in your application.
## Core Operations
Mem0 exposes two main endpoints for interacting with memories:
- The `add` endpoint for ingesting conversations and storing them as memories
- The `search` endpoint for retrieving relevant memories based on queries
### Adding Memories
<Frame caption="Architecture diagram illustrating the process of adding memories.">
<img src="../images/add_architecture.png" />
</Frame>
The add operation processes conversations through several steps:
1. **Information Extraction**
* An LLM extracts relevant memories from the conversation
* It identifies important entities and their relationships
2. **Conflict Resolution**
* The system compares new information with existing data
* It identifies and resolves any contradictions
3. **Memory Storage**
* Vector database stores the actual memories
* Graph database maintains relationship information
* Information is continuously updated with each interaction
### Searching Memories
<Frame caption="Architecture diagram illustrating the memory search process.">
<img src="../images/search_architecture.png" />
</Frame>
The search operation retrieves memories through a multi-step process:
1. **Query Processing**
* LLM processes and optimizes the search query
* System prepares filters for targeted search
2. **Vector Search**
* Performs semantic search using the optimized query
* Ranks results by relevance to the query
* Applies specified filters (user, agent, metadata, etc.)
3. **Result Processing**
* Combines and ranks the search results
* Returns memories with relevance scores
* Includes associated metadata and timestamps
This semantic search approach ensures accurate memory retrieval, whether you're looking for specific information or exploring related concepts.
+48
View File
@@ -0,0 +1,48 @@
---
title: Memory Types
description: Understanding different types of memory in AI Applications
icon: "memory"
iconType: "solid"
---
To build useful AI applications, we need to understand how different memory systems work together. This guide explores the fundamental types of memory in AI systems and shows how Mem0 implements these concepts.
## Why Memory Matters
AI systems need memory for three key purposes:
1. Maintaining context during conversations
2. Learning from past interactions
3. Building personalized experiences over time
Without proper memory systems, AI applications would treat each interaction as completely new, losing valuable context and personalization opportunities.
## Short-Term Memory
The most basic form of memory in AI systems holds immediate context - like a person remembering what was just said in a conversation. This includes:
- **Conversation History**: Recent messages and their order
- **Working Memory**: Temporary variables and state
- **Attention Context**: Current focus of the conversation
## Long-Term Memory
More sophisticated AI applications implement long-term memory to retain information across conversations. This includes:
- **Factual Memory**: Stored knowledge about users, preferences, and domain-specific information
- **Episodic Memory**: Past interactions and experiences
- **Semantic Memory**: Understanding of concepts and their relationships
## Memory Characteristics
Each memory type has distinct characteristics:
| Type | Persistence | Access Speed | Use Case |
|------|-------------|--------------|-----------|
| Short-Term | Temporary | Instant | Active conversations |
| Long-Term | Persistent | Fast | User preferences and history |
## How Mem0 Implements Long-Term Memory
Mem0's long-term memory system builds on these foundations by:
1. Using vector embeddings to store and retrieve semantic information
2. Maintaining user-specific context across sessions
3. Implementing efficient retrieval mechanisms for relevant past interactions
+305
View File
@@ -0,0 +1,305 @@
{
"$schema": "https://mintlify.com/docs.json",
"theme": "maple",
"name": "Mem0",
"description": "Mem0 is a self-improving memory layer for LLM applications, enabling personalized AI experiences that save costs and delight users.",
"colors": {
"primary": "#6c60f0",
"light": "#E6FFA2",
"dark": "#a3df02"
},
"favicon": "/logo/favicon.png",
"navigation": {
"anchors": [
{
"anchor": "Documentation",
"icon": "book-open",
"tabs": [
{
"tab": "Documentation",
"groups": [
{
"group": "Get Started",
"icon": "rocket",
"pages": [
"overview",
"quickstart",
"faqs"
]
},
{
"group": "Core Concepts",
"icon": "brain",
"pages": [
"core-concepts/memory-types",
"core-concepts/memory-operations"
]
},
{
"group": "Platform",
"icon": "cogs",
"pages": [
"platform/overview",
"platform/quickstart",
{
"group": "Features",
"icon": "star",
"pages": [
"features/platform-overview",
"features/advanced-retrieval",
"features/multimodal-support",
"features/selective-memory",
"features/custom-categories",
"features/custom-instructions",
"features/direct-import",
"features/async-client",
"features/memory-export",
"features/webhook"
]
}
]
},
{
"group": "Open Source",
"icon": "code-branch",
"pages": [
"open-source/quickstart",
{
"group": "Features",
"icon": "wrench",
"pages": [
"features/openai_compatibility",
"features/custom-prompts",
"open-source/multimodal-support"
]
},
{
"group": "Graph Memory",
"icon": "spider-web",
"pages": [
"open-source/graph_memory/overview",
"open-source/graph_memory/features"
]
},
{
"group": "LLMs",
"icon": "brain",
"pages": [
"components/llms/overview",
"components/llms/config",
{
"group": "Supported LLMs",
"icon": "list",
"pages": [
"components/llms/models/openai",
"components/llms/models/anthropic",
"components/llms/models/azure_openai",
"components/llms/models/ollama",
"components/llms/models/together",
"components/llms/models/groq",
"components/llms/models/litellm",
"components/llms/models/mistral_AI",
"components/llms/models/google_AI",
"components/llms/models/aws_bedrock",
"components/llms/models/gemini"
]
}
]
},
{
"group": "Vector Databases",
"icon": "database",
"pages": [
"components/vectordbs/overview",
"components/vectordbs/config",
{
"group": "Supported Vector Databases",
"icon": "server",
"pages": [
"components/vectordbs/dbs/qdrant",
"components/vectordbs/dbs/chroma",
"components/vectordbs/dbs/pgvector",
"components/vectordbs/dbs/milvus",
"components/vectordbs/dbs/azure_ai_search",
"components/vectordbs/dbs/redis",
"components/vectordbs/dbs/elasticsearch",
"components/vectordbs/dbs/opensearch"
]
}
]
},
{
"group": "Embedding Models",
"icon": "layer-group",
"pages": [
"components/embedders/overview",
"components/embedders/config",
{
"group": "Supported Embedding Models",
"icon": "list",
"pages": [
"components/embedders/models/openai",
"components/embedders/models/azure_openai",
"components/embedders/models/ollama",
"components/embedders/models/huggingface",
"components/embedders/models/vertexai",
"components/embedders/models/gemini"
]
}
]
}
]
}
]
},
{
"tab": "Examples",
"groups": [
{
"group": "💡 Examples",
"icon": "lightbulb",
"pages": [
"examples/overview",
"examples/mem0-with-ollama",
"examples/personal-ai-tutor",
"examples/customer-support-agent",
"examples/personal-travel-assistant",
"examples/llama-index-mem0"
]
}
]
},
{
"tab": "Integrations",
"groups": [
{
"group": "Integrations",
"icon": "plug",
"pages": [
"integrations/overview",
"integrations/vercel-ai-sdk",
"integrations/crewai",
"integrations/autogen",
"integrations/langchain",
"integrations/langgraph",
"integrations/llama-index",
"integrations/langchain-tools"
]
}
]
},
{
"tab": "API Reference",
"icon": "square-terminal",
"groups": [
{
"group": "API Reference",
"icon": "terminal",
"pages": [
"api-reference/overview",
{
"group": "Memory APIs",
"icon": "microchip",
"pages": [
"api-reference/memory/v1-get-memories",
"api-reference/memory/v2-get-memories",
"api-reference/memory/add-memories",
"api-reference/memory/delete-memories",
"api-reference/memory/get-memory",
"api-reference/memory/update-memory",
"api-reference/memory/delete-memory",
"api-reference/memory/v1-search-memories",
"api-reference/memory/v2-search-memories",
"api-reference/memory/history-memory",
"api-reference/memory/batch-update",
"api-reference/memory/batch-delete",
"api-reference/memory/create-memory-export",
"api-reference/memory/get-memory-export"
]
},
{
"group": "Entities APIs",
"icon": "users",
"pages": [
"api-reference/entities/get-users",
"api-reference/entities/delete-user"
]
},
{
"group": "Organizations APIs",
"icon": "building",
"pages": [
"api-reference/organization/get-orgs",
"api-reference/organization/get-org",
"api-reference/organization/create-org",
"api-reference/organization/update-org",
"api-reference/organization/delete-org",
"api-reference/organization/get-org-members",
"api-reference/organization/add-org-member",
"api-reference/organization/remove-org-member",
"api-reference/organization/get-org-projects",
"api-reference/organization/add-org-project",
"api-reference/organization/remove-org-project"
]
}
]
}
]
}
]
},
{
"anchor": "Your Dashboard",
"href": "https://app.mem0.ai",
"icon": "chart-simple"
},
{
"anchor": "Discord",
"href": "https://mem0.dev/DiD",
"icon": "discord"
},
{
"anchor": "GitHub",
"href": "https://github.com/mem0ai/mem0",
"icon": "github"
},
{
"anchor": "Support",
"href": "mailto:founders@mem0.ai",
"icon": "envelope"
}
]
},
"logo": {
"light": "/logo/light.svg",
"dark": "/logo/dark.svg",
"href": "https://github.com/mem0ai/mem0"
},
"background": {
"color": {
"light": "#fff",
"dark": "#0f1117"
}
},
"navbar": {
"primary": {
"type": "button",
"label": "Your Dashboard",
"href": "https://app.mem0.ai"
}
},
"footer": {
"socials": {
"discord": "https://mem0.dev/DiD",
"x": "https://x.com/mem0ai",
"github": "https://github.com/mem0ai",
"linkedin": "https://www.linkedin.com/company/mem0/"
}
},
"integrations": {
"posthog": {
"apiKey": "phc_hgJkUVJFYtmaJqrvf6CYN67TIQ8yhXAkWzUn9AMU4yX",
"apiHost": "https://mango.mem0.ai"
}
}
}
+92
View File
@@ -0,0 +1,92 @@
---
title: FAQs
icon: "question"
iconType: "solid"
---
<AccordionGroup>
<Accordion title="How does Mem0 work?">
Mem0 utilizes a sophisticated hybrid database system to efficiently manage and retrieve memories for AI agents and assistants. Each memory is linked to a unique identifier, such as a user ID or agent ID, enabling Mem0 to organize and access memories tailored to specific individuals or contexts.
When a message is added to Mem0 via the `add` method, the system extracts pertinent facts and preferences, distributing them across various data stores: a vector database and a graph database. This hybrid strategy ensures that diverse types of information are stored optimally, facilitating swift and effective searches.
When an AI agent or LLM needs to access memories, it employs the `search` method. Mem0 conducts a comprehensive search across these data stores, retrieving relevant information from each.
The retrieved memories can be seamlessly integrated into the LLM's prompt as required, enhancing the personalization and relevance of responses.
</Accordion>
<Accordion title="What are the key features of Mem0?">
- **User, Session, and AI Agent Memory**: Retains information across sessions and interactions for users and AI agents, ensuring continuity and context.
- **Adaptive Personalization**: Continuously updates memories based on user interactions and feedback.
- **Developer-Friendly API**: Offers a straightforward API for seamless integration into various applications.
- **Platform Consistency**: Ensures consistent behavior and data across different platforms and devices.
- **Managed Service**: Provides a hosted solution for easy deployment and maintenance.
- **Save Costs**: Saves costs by adding relevent memories instead of complete transcripts to context window
</Accordion>
<Accordion title="How Mem0 is different from traditional RAG?">
Mem0's memory implementation for Large Language Models (LLMs) offers several advantages over Retrieval-Augmented Generation (RAG):
- **Entity Relationships**: Mem0 can understand and relate entities across different interactions, unlike RAG which retrieves information from static documents. This leads to a deeper understanding of context and relationships.
- **Contextual Continuity**: Mem0 retains information across sessions, maintaining continuity in conversations and interactions, which is essential for long-term engagement applications like virtual companions or personalized learning assistants.
- **Adaptive Learning**: Mem0 improves its personalization based on user interactions and feedback, making the memory more accurate and tailored to individual users over time.
- **Dynamic Updates**: Mem0 can dynamically update its memory with new information and interactions, unlike RAG which relies on static data. This allows for real-time adjustments and improvements, enhancing the user experience.
These advanced memory capabilities make Mem0 a powerful tool for developers aiming to create personalized and context-aware AI applications.
</Accordion>
<Accordion title="What are the common use-cases of Mem0?">
- **Personalized Learning Assistants**: Long-term memory allows learning assistants to remember user preferences, strengths and weaknesses, and progress, providing a more tailored and effective learning experience.
- **Customer Support AI Agents**: By retaining information from previous interactions, customer support bots can offer more accurate and context-aware assistance, improving customer satisfaction and reducing resolution times.
- **Healthcare Assistants**: Long-term memory enables healthcare assistants to keep track of patient history, medication schedules, and treatment plans, ensuring personalized and consistent care.
- **Virtual Companions**: Virtual companions can use long-term memory to build deeper relationships with users by remembering personal details, preferences, and past conversations, making interactions more delightful.
- **Productivity Tools**: Long-term memory helps productivity tools remember user habits, frequently used documents, and task history, streamlining workflows and enhancing efficiency.
- **Gaming AI**: In gaming, AI with long-term memory can create more immersive experiences by remembering player choices, strategies, and progress, adapting the game environment accordingly.
</Accordion>
<Accordion title="Why aren't my memories being created?">
Mem0 uses a sophisticated classification system to determine which parts of text should be extracted as memories. Not all text content will generate memories, as the system is designed to identify specific types of memorable information.
There are several scenarios where mem0 may return an empty list of memories:
- When users input definitional questions (e.g., "What is backpropagation?")
- For general concept explanations that don't contain personal or experiential information
- Technical definitions and theoretical explanations
- General knowledge statements without personal context
- Abstract or theoretical content
Example Scenarios
```
Input: "What is machine learning?"
No memories extracted - Content is definitional and does not meet memory classification criteria.
Input: "Yesterday I learned about machine learning in class"
Memory extracted - Contains personal experience and temporal context.
```
Best Practices
To ensure successful memory extraction:
- Include temporal markers (when events occurred)
- Add personal context or experiences
- Frame information in terms of real-world applications or experiences
- Include specific examples or cases rather than general definitions
</Accordion>
</AccordionGroup>
+2 -40
View File
@@ -1,5 +1,7 @@
--- ---
title: Features title: Features
icon: "wrench"
iconType: "solid"
--- ---
## Core features ## Core features
@@ -13,46 +15,6 @@ title: Features
## How does Mem0 work?
Mem0 leverages a hybrid database approach to manage and retrieve long-term memories for AI agents and assistants. Each memory is associated with a unique identifier, such as a user ID or agent ID, allowing Mem0 to organize and access memories specific to an individual or context.
When a message is added to the Mem0 using add() method, the system extracts relevant facts and preferences and stores it across data stores: a vector database, a key-value database, and a graph database. This hybrid approach ensures that different types of information are stored in the most efficient manner, making subsequent searches quick and effective.
When an AI agent or LLM needs to recall memories, it uses the search() method. Mem0 then performs search across these data stores, retrieving relevant information from each source. This information is then passed through a scoring layer, which evaluates their importance based on relevance, importance, and recency. This ensures that only the most personalized and useful context is surfaced.
The retrieved memories can then be appended to the LLM's prompt as needed, making responses personalized and relevant.
## Common Use Cases
- **Personalized Learning Assistants**: Long-term memory allows learning assistants to remember user preferences, strengths and weaknesses, and progress, providing a more tailored and effective learning experience.
- **Customer Support AI Agents**: By retaining information from previous interactions, customer support bots can offer more accurate and context-aware assistance, improving customer satisfaction and reducing resolution times.
- **Healthcare Assistants**: Long-term memory enables healthcare assistants to keep track of patient history, medication schedules, and treatment plans, ensuring personalized and consistent care.
- **Virtual Companions**: Virtual companions can use long-term memory to build deeper relationships with users by remembering personal details, preferences, and past conversations, making interactions more delightful.
- **Productivity Tools**: Long-term memory helps productivity tools remember user habits, frequently used documents, and task history, streamlining workflows and enhancing efficiency.
- **Gaming AI**: In gaming, AI with long-term memory can create more immersive experiences by remembering player choices, strategies, and progress, adapting the game environment accordingly.
## How is Mem0 different from RAG?
Mem0's memory implementation for Large Language Models (LLMs) offers several advantages over Retrieval-Augmented Generation (RAG):
- **Entity Relationships**: Mem0 can understand and relate entities across different interactions, unlike RAG which retrieves information from static documents. This leads to a deeper understanding of context and relationships.
- **Recency, Relevancy, and Decay**: Mem0 uses custom search algorithms to prioritize recent interactions and gradually forgets outdated information, ensuring the memory remains relevant and up-to-date for more accurate responses.
- **Contextual Continuity**: Mem0 retains information across sessions, maintaining continuity in conversations and interactions, which is essential for long-term engagement applications like virtual companions or personalized learning assistants.
- **Adaptive Learning**: Mem0 improves its personalization based on user interactions and feedback, making the memory more accurate and tailored to individual users over time.
- **Dynamic Updates**: Mem0 can dynamically update its memory with new information and interactions, unlike RAG which relies on static data. This allows for real-time adjustments and improvements, enhancing the user experience.
These advanced memory capabilities make Mem0 a powerful tool for developers aiming to create personalized and context-aware AI applications.
If you have any questions, please feel free to reach out to us using one of the following methods: If you have any questions, please feel free to reach out to us using one of the following methods:
+49
View File
@@ -0,0 +1,49 @@
---
title: Advanced Retrieval
icon: "magnifying-glass"
iconType: "solid"
---
Mem0's **Advanced Retrieval** feature delivers superior search results by leveraging state-of-the-art search algorithms. Beyond the default search functionality, Mem0 offers the following advanced retrieval modes:
1. **Keyword Search**
This mode emphasizes keywords within the query, returning memories that contain the most relevant keywords alongside those from the default search. By default, this parameter is set to `false`. Enabling it enhances search recall, though it may slightly impact precision.
```python
client.search(query, keyword_search=True, user_id='alex')
```
2. **Reranking**
Reranking allows you to reorder the memories returned by the default search based on relevance. This parameter is set to `false` by default. When enabled, it reorders the memories based on the relevance score.
```python
client.search(query, rerank=True, user_id='alex')
```
3. **Filtering**
Filtering enables you to narrow down the search results by applying specific criteria. This parameter is set to `false` by default. Activating it enhances search precision, potentially reducing recall by a small margin.
```python
client.search(query, filter_memories=True, user_id='alex')
```
**Note:** You can enable or disable these search modes by passing the respective parameters to the `search` method. There is no required sequence for these modes, and any combination can be used based on your needs.
### Latency Numbers
Here are the typical latency ranges for each search mode:
| **Mode** | **Latency** |
|---------------------|------------------|
| **Keyword Search** | **&lt;10ms** |
| **Reranking** | **150-200ms** |
| **Filtering** | **200-300ms** |
If you have any questions, please feel free to reach out to us using one of the following methods:
<Snippet file="get-help.mdx" />
+2
View File
@@ -1,6 +1,8 @@
--- ---
title: Async Client title: Async Client
description: 'Asynchronous client for Mem0' description: 'Asynchronous client for Mem0'
icon: "bolt"
iconType: "solid"
--- ---
The `AsyncMemoryClient` is an asynchronous client for interacting with the Mem0 API. It provides similar functionality to the synchronous `MemoryClient` but allows for non-blocking operations, which can be beneficial in applications that require high concurrency. The `AsyncMemoryClient` is an asynchronous client for interacting with the Mem0 API. It provides similar functionality to the synchronous `MemoryClient` but allows for non-blocking operations, which can be beneficial in applications that require high concurrency.
+128 -56
View File
@@ -1,65 +1,36 @@
--- ---
title: Custom Categories title: Custom Categories
description: 'Enhance your product experience by adding custom categories tailored to your needs' description: 'Enhance your product experience by adding custom categories tailored to your needs'
icon: "tags"
iconType: "solid"
--- ---
## How to set custom categories? ## How to set custom categories?
Users can now create custom categories tailored to their specific needs, in addition to the default categories such as travel, sports, music, and more. When custom categories are provided, they will override the default categories. You can now create custom categories tailored to your specific needs, instead of using the default categories such as travel, sports, music, and more (see [default categories](#default-categories) below). **When custom categories are provided, they will override the default categories.**
To setup the custom categories, user has to specify the category name and a description of what that category signifies.
Here’s how you can do it:
```python There are two ways to set custom categories:
from mem0 import MemoryClient
m = MemoryClient(api_key="xxx") ### 1. Project Level
custom_categories = [ You can set custom categories at the project level, which will be applied to all memories added within that project. Mem0 will automatically assign relevant categories from your custom set to new memories based on their content. Setting custom categories at the project level will override the default categories.
{"cooking": "For users interested in cooking, including recipes, cooking tips, and culinary experiences."},
{"fitness": "Includes content related to fitness, such as workouts, exercises, and fitness tips."}
]
messages = [
{"role" : "user", "content" : "Hi, my name is Alice. I love to play badminton."},
{"role" : "assistant", "content" : "Hello Alice! It's nice to meet you. Badminton is such an amazing sport. How can I assist you today?"},
{"role" : "user", "content" : "I am a fitness freak, I go to gym daily."},
{"role" : "assistant", "content" : "That's great! Regular exercise is very beneficial for health."},
{"role" : "user", "content" : "Because of my gym plan, I mostly cook at home."},
{"role" : "assistant", "content" : "Cooking at home is a good way to ensure you have a balanced diet."}
]
```
<CodeGroup>
```python Code
client.add(messages, user_id="alice", custom_categories=custom_categories)
```
```markdown Memories with categories
User's name is Alice (personal_details)
Loves playing badminton (sports)
User is a fitness freak. (fitness)
Likes to go to gym daily. (fitness)
Mostly cook at home because of gym plan. (fitness, cooking)
```
</CodeGroup>
<Note> The more detailed the description of categories is, the better output the user will receive. When custom categories are provided in the `add` API call, they will completely replace the default categories and will be directly assigned to the memory, so make sure to include all categories you want to use. </Note>
## Setting Project-Level Custom Categories
You can also set custom categories at the project level, which will be applied to all memories added within that project. We will automatically assign relevant categories from your custom set to new memories based on their content.
Here's how to set custom categories: Here's how to set custom categories:
<CodeGroup> <CodeGroup>
```python Code ```python Code
from mem0 import MemoryClient
client = MemoryClient(api_key="<your_mem0_api_key>")
# Update custom categories # Update custom categories
new_categories = [ new_categories = [
{"cooking": "For users interested in cooking and culinary experiences"}, {"lifestyle_management_concerns": "Tracks daily routines, habits, hobbies and interests including cooking, time management and work-life balance"},
{"fitness": "Content related to fitness and exercise"} {"seeking_structure": "Documents goals around creating routines, schedules, and organized systems in various life areas"},
{"personal_information": "Basic information about the user including name, preferences, and personality traits"}
] ]
response = client.update_custom_instructions_and_categories({"custom_categories": new_categories})
response = client.update_project(custom_categories = new_categories)
print(response) print(response)
``` ```
@@ -70,40 +41,99 @@ print(response)
``` ```
</CodeGroup> </CodeGroup>
This is how you will use these custom categories during the `add` API call:
<CodeGroup>
```python Code
messages = [
{"role": "user", "content": "My name is Alice. I need help organizing my daily schedule better. I feel overwhelmed trying to balance work, exercise, and social life."},
{"role": "assistant", "content": "I understand how overwhelming that can feel. Let's break this down together. What specific areas of your schedule feel most challenging to manage?"},
{"role": "user", "content": "I want to be more productive at work, maintain a consistent workout routine, and still have energy for friends and hobbies."},
{"role": "assistant", "content": "Those are great goals for better time management. What's one small change you could make to start improving your daily routine?"},
]
# Add memories with custom categories
client.add(messages, user_id="alice")
```
```python Memories with categories
# Following categories will be created for the memories added
Wants to have energy for friends and hobbies (lifestyle_management_concerns)
Wants to maintain a consistent workout routine (seeking_structure, lifestyle_management_concerns)
Wants to be more productive at work (lifestyle_management_concerns, seeking_structure)
Name is Alice (personal_information)
```
</CodeGroup>
You can also retrieve the current custom categories: You can also retrieve the current custom categories:
<CodeGroup> <CodeGroup>
```python Code ```python Code
from mem0 import MemoryClient
client = MemoryClient(api_key="xxx")
# Get current custom categories # Get current custom categories
categories = client.get_custom_instructions_and_categories(["custom_categories"]) categories = client.get_project(fields=["custom_categories"])
print(categories) print(categories)
``` ```
```json Output ```json Output
{ {
"custom_categories": [ "custom_categories": [
{"cooking": "For users interested in cooking and culinary experiences"}, {"lifestyle_management_concerns": "Tracks daily routines, habits, hobbies and interests including cooking, time management and work-life balance"},
{"fitness": "Content related to fitness and exercise"} {"seeking_structure": "Documents goals around creating routines, schedules, and organized systems in various life areas"},
] {"personal_information": "Basic information about the user including name, preferences, and personality traits"}
]
} }
``` ```
</CodeGroup> </CodeGroup>
These project-level categories will be automatically applied to all new memories added to the project. These project-level categories will be automatically applied to all new memories added to the project.
## Default Categories
Here is the list of **default categories**. Ensure you review these before creating custom categories to prevent duplication.
### 2. During the `add` API call
You can also set custom categories during the `add` API call. This will override any project-level custom categories for that specific memory addition. For example, if you want to use different categories for food-related memories, you can provide custom categories like "food" and "user_preferences" in the `add` call. These custom categories will be used instead of the project-level categories when categorizing those specific memories.
<CodeGroup>
```python Code
from mem0 import MemoryClient
client = MemoryClient(api_key="<your_mem0_api_key>")
custom_categories = [
{"seeking_structure": "Documents goals around creating routines, schedules, and organized systems in various life areas"},
{"personal_information": "Basic information about the user including name, preferences, and personality traits"}
]
messages = [
{"role": "user", "content": "My name is Alice. I need help organizing my daily schedule better. I feel overwhelmed trying to balance work, exercise, and social life."},
{"role": "assistant", "content": "I understand how overwhelming that can feel. Let's break this down together. What specific areas of your schedule feel most challenging to manage?"},
{"role": "user", "content": "I want to be more productive at work, maintain a consistent workout routine, and still have energy for friends and hobbies."},
{"role": "assistant", "content": "Those are great goals for better time management. What's one small change you could make to start improving your daily routine?"},
]
client.add(messages, user_id="alice", custom_categories=custom_categories)
```
```python Memories with categories
# Following categories will be created for the memories added
Wants to have energy for friends and hobbies (seeking_structure)
Wants to maintain a consistent workout routine (seeking_structure)
Wants to be more productive at work (seeking_structure)
Name is Alice (personal_information)
```
</CodeGroup>
<Note>Providing more detailed and specific category descriptions will lead to more accurate and relevant memory categorization.</Note>
## Default Categories
Here is the list of **default categories**. If you don't specify any custom categories using the above methods, these will be used as default categories.
``` ```
- personal_details - personal_details
- family - family
- professional_details - professional_details
- sports - sports
- travel - travel
- food - food
- music - music
- health - health
@@ -116,6 +146,48 @@ Here is the list of **default categories**. Ensure you review these before creat
- misc - misc
``` ```
<CodeGroup>
```python Code
from mem0 import MemoryClient
client = MemoryClient(api_key="<your_mem0_api_key>")
messages = [
{"role": "user", "content": "Hi, my name is Alice."},
{"role": "assistant", "content": "Hi Alice, what sports do you like to play?"},
{"role": "user", "content": "I love playing badminton, football, and basketball. I'm quite athletic!"},
{"role": "assistant", "content": "That's great! Alice seems to enjoy both individual sports like badminton and team sports like football and basketball."},
{"role": "user", "content": "Sometimes, I also draw and sketch in my free time."},
{"role": "assistant", "content": "That's cool! I'm sure you're good at it."}
]
# Add memories with default categories
client.add(messages, user_id='alice')
```
```python Memories with categories
# Following categories will be created for the memories added
Sometimes draws and sketches in free time (hobbies)
Is quite athletic (sports)
Loves playing badminton, football, and basketball (sports)
Name is Alice (personal_details)
```
</CodeGroup>
You can check whether default categories are being used by calling `get_project()`. If `custom_categories` returns `None`, it means the default categories are being used.
<CodeGroup>
```python Code
client.get_project(["custom_categories"])
```
```json Output
{
'custom_categories': None
}
```
</CodeGroup>
If you have any questions, please feel free to reach out to us using one of the following methods: If you have any questions, please feel free to reach out to us using one of the following methods:
<Snippet file="get-help.mdx" /> <Snippet file="get-help.mdx" />
+27 -10
View File
@@ -1,6 +1,8 @@
--- ---
title: Custom Instructions title: Custom Instructions
description: 'Enhance your product experience by adding custom instructions tailored to your needs' description: 'Enhance your product experience by adding custom instructions tailored to your needs'
icon: "pencil"
iconType: "solid"
--- ---
## Introduction to Custom Instructions ## Introduction to Custom Instructions
@@ -22,16 +24,31 @@ You can set custom instructions for your project using the following method:
<CodeGroup> <CodeGroup>
```python Code ```python Code
# Update custom instructions # Update custom instructions
prompt = """ prompt ="""
Your task is to extract ONLY health-related information from conversations, including: Your Task: Extract ONLY health-related information from conversations, focusing on the following areas:
- Medical conditions, symptoms, diagnoses 1. Medical Conditions, Symptoms, and Diagnoses:
- Medications, treatments, procedures - Illnesses, disorders, or symptoms (e.g., fever, diabetes).
- Diet, exercise, sleep habits - Confirmed or suspected diagnoses.
- Doctor visits and appointments
- Health metrics (weight, blood pressure, etc) 2. Medications, Treatments, and Procedures:
- Prescription or OTC medications (names, dosages).
- Treatments, therapies, or medical procedures.
3. Diet, Exercise, and Sleep:
- Dietary habits, fitness routines, and sleep patterns.
4. Doctor Visits and Appointments:
- Past, upcoming, or regular medical visits.
5. Health Metrics:
- Data like weight, BP, cholesterol, or sugar levels.
Guidelines:
- Focus solely on health-related content.
- Maintain clarity and context accuracy while recording.
""" """
response = client.update_custom_instructions_and_categories({"custom_instructions": prompt}) response = client.update_project(custom_instructions=prompt)
print(response) print(response)
``` ```
@@ -47,13 +64,13 @@ You can also retrieve the current custom instructions:
<CodeGroup> <CodeGroup>
```python Code ```python Code
# Retrieve current custom instructions # Retrieve current custom instructions
response = client.get_custom_instructions_and_categories(["custom_instructions"]) response = client.get_project(fields=["custom_instructions"])
print(response) print(response)
``` ```
```json Output ```json Output
{ {
"custom_instructions": "Your task is to extract ONLY health-related information from conversations, including:\n\n- Medical conditions, symptoms, diagnoses\n- Medications, treatments, procedures\n- Diet, exercise, sleep habits\n- Doctor visits and appointments\n- Health metrics (weight, blood pressure, etc)" "custom_instructions": "Your Task: Extract ONLY health-related information from conversations, focusing on the following areas:\n1. Medical Conditions, Symptoms, and Diagnoses - illnesses, disorders, or symptoms (e.g., fever, diabetes), confirmed or suspected diagnoses.\n2. Medications, Treatments, and Procedures - prescription or OTC medications (names, dosages), treatments, therapies, or medical procedures.\n3. Diet, Exercise, and Sleep - dietary habits, fitness routines, and sleep patterns.\n4. Doctor Visits and Appointments - past, upcoming, or regular medical visits.\n5. Health Metrics - data like weight, BP, cholesterol, or sugar levels.\n\nGuidelines: Focus solely on health-related content. Maintain clarity and context accuracy while recording."
} }
``` ```
</CodeGroup> </CodeGroup>
+2
View File
@@ -1,6 +1,8 @@
--- ---
title: Custom Prompts title: Custom Prompts
description: 'Enhance your product experience by adding custom prompts tailored to your needs' description: 'Enhance your product experience by adding custom prompts tailored to your needs'
icon: "pencil"
iconType: "solid"
--- ---
## Introduction to Custom Prompts ## Introduction to Custom Prompts
+2
View File
@@ -1,6 +1,8 @@
--- ---
title: Direct Import title: Direct Import
description: 'Bypass the memory deduction phase and directly store pre-defined memories for efficient retrieval' description: 'Bypass the memory deduction phase and directly store pre-defined memories for efficient retrieval'
icon: "arrow-right"
iconType: "solid"
--- ---
## How to use Direct Import? ## How to use Direct Import?
+2
View File
@@ -1,6 +1,8 @@
--- ---
title: Memory Export title: Memory Export
description: 'Export memories in a structured format using customizable Pydantic schemas' description: 'Export memories in a structured format using customizable Pydantic schemas'
icon: "file-export"
iconType: "solid"
--- ---
## Overview ## Overview
+116
View File
@@ -0,0 +1,116 @@
---
title: Multimodal Support
icon: "image"
iconType: "solid"
---
Mem0 extends its capabilities beyond text by supporting multimodal data, including images. Users can seamlessly integrate images into their interactions, allowing Mem0 to extract pertinent information from visual content and enrich the memory system.
## How It Works
When a user provides an image, Mem0 processes the image to extract textual information and relevant details, which are then added to the user's memory. This feature enhances the system's ability to understand and remember details based on visual inputs.
<CodeGroup>
```python Code
from mem0 import MemoryClient
# Initialize the MemoryClient with your API key
client = MemoryClient(api_key="your_api_key_here")
messages = [
{
"role": "user",
"content": "Hi, my name is Alice."
},
{
"role": "assistant",
"content": "Nice to meet you, Alice! What do you like to eat?"
},
{
"role": "user",
"content": {
"type": "image_url",
"image_url": {
"url": "https://www.superhealthykids.com/wp-content/uploads/2021/10/best-veggie-pizza-featured-image-square-2.jpg"
}
}
},
]
# Calling the add method to ingest messages into the memory system
client.add(messages, user_id="alice")
```
```json Output
{
"results": [
{
"memory": "Name is Alice",
"event": "ADD",
"id": "7ae113a3-3cb5-46e9-b6f7-486c36391847"
},
{
"memory": "Likes large pizza with toppings including cherry tomatoes, black olives, green spinach, yellow bell peppers, diced ham, and sliced mushrooms",
"event": "ADD",
"id": "56545065-7dee-4acf-8bf2-a5b2535aabb3"
}
]
}
```
</CodeGroup>
## Image Integration Methods
Mem0 allows you to add images to user interactions through two primary methods: by providing an image URL or by using a Base64-encoded image. Below are examples demonstrating each approach.
## 1. Using an Image URL (Recommended)
You can include an image by passing its direct URL. This method is simple and efficient for online images.
```python
# Define the image URL
image_url = "https://www.superhealthykids.com/wp-content/uploads/2021/10/best-veggie-pizza-featured-image-square-2.jpg"
# Create the message dictionary with the image URL
image_message = {
"role": "user",
"content": {
"type": "image_url",
"image_url": {
"url": image_url
}
}
}
```
## 2. Using Base64 Image Encoding for Local Files
For local images or scenarios where embedding the image directly is preferable, you can use a Base64-encoded string.
```python
import base64
# Path to the image file
image_path = "path/to/your/image.jpg"
# Encode the image in Base64
with open(image_path, "rb") as image_file:
base64_image = base64.b64encode(image_file.read()).decode("utf-8")
# Create the message dictionary with the Base64-encoded image
image_message = {
"role": "user",
"content": {
"type": "image_url",
"image_url": {
"url": f"data:image/jpeg;base64,{base64_image}"
}
}
}
```
By utilizing these methods, you can effectively incorporate images into user interactions, enhancing the multimodal capabilities of your Mem0 instance.
If you have any questions, please feel free to reach out to us using one of the following methods:
<Snippet file="get-help.mdx" />
+2
View File
@@ -1,5 +1,7 @@
--- ---
title: OpenAI Compatibility title: OpenAI Compatibility
icon: "code"
iconType: "solid"
--- ---
Mem0 can be easily integrated into chat applications to enhance conversational agents with structured memory. Mem0's APIs are designed to be compatible with OpenAI's, with the goal of making it easy to leverage Mem0 in applications you may have already built. Mem0 can be easily integrated into chat applications to enhance conversational agents with structured memory. Mem0's APIs are designed to be compatible with OpenAI's, with the goal of making it easy to leverage Mem0 in applications you may have already built.
+42
View File
@@ -0,0 +1,42 @@
---
title: Overview
icon: "info"
iconType: "solid"
---
Learn about the key features and capabilities that make Mem0 a powerful platform for memory management and retrieval.
## Core Features
<CardGroup>
<Card title="Advanced Retrieval" icon="magnifying-glass" href="/features/advanced-retrieval">
Superior search results using state-of-the-art algorithms, including keyword search, reranking, and filtering capabilities.
</Card>
<Card title="Multimodal Support" icon="photo-film" href="/features/multimodal-support">
Process and analyze various types of content including images.
</Card>
<Card title="Memory Customization" icon="filter" href="/features/selective-memory">
Customize and curate stored memories to focus on relevant information while excluding unnecessary data, enabling improved accuracy, privacy control, and resource efficiency.
</Card>
<Card title="Custom Categories" icon="tags" href="/features/custom-categories">
Create and manage custom categories to organize memories based on your specific needs and requirements.
</Card>
<Card title="Custom Instructions" icon="list-check" href="/features/custom-instructions">
Define specific guidelines for your project to ensure consistent handling of information and requirements.
</Card>
<Card title="Direct Import" icon="message-bot" href="/features/direct-import">
Tailor the behavior of your Mem0 instance with custom prompts for specific use cases or domains.
</Card>
<Card title="Async Client" icon="bolt" href="/features/async-client">
Asynchronous client for non-blocking operations and high concurrency applications.
</Card>
<Card title="Memory Export" icon="file-export" href="/features/memory-export">
Export memories in structured formats using customizable Pydantic schemas.
</Card>
</CardGroup>
## Getting Help
If you have any questions about these features or need assistance, our team is here to help:
<Snippet file="get-help.mdx" />
+2
View File
@@ -1,6 +1,8 @@
--- ---
title: Memory Customization title: Memory Customization
description: 'Mem0 supports customizing the memories you store, allowing you to focus on pertinent information while omitting irrelevant data.' description: 'Mem0 supports customizing the memories you store, allowing you to focus on pertinent information while omitting irrelevant data.'
icon: "filter"
iconType: "solid"
--- ---
## Benefits of Memory Customization ## Benefits of Memory Customization
+201
View File
@@ -0,0 +1,201 @@
---
title: Webhooks
description: 'Configure and manage webhooks to receive real-time notifications about memory events'
icon: "webhook"
iconType: "solid"
---
## Overview
Webhooks allow you to receive real-time notifications when memory events occur in your Mem0 project. Webhooks are configured at the project level, meaning each webhook is associated with a specific project and will only receive events from that project. You can configure webhooks to send HTTP POST requests to your specified URLs whenever memories are created, updated, or deleted.
## Managing Webhooks
### Create Webhook
Create a new webhook for your project. The webhook will only receive events from the specified project:
<CodeGroup>
```python Python
from mem0 import MemoryClient
client = MemoryClient(api_key="your-api-key")
# Create webhook in a specific project
webhook = client.create_webhook(
url="https://your-app.com/webhook",
name="Memory Logger",
project_id="proj_123",
event_types=["memory:add"]
)
print(webhook)
```
```javascript JavaScript
const { MemoryClient } = require('mem0ai');
const client = new MemoryClient('your-api-key');
// Create webhook in a specific project
const webhook = await client.createWebhook({
url: "https://your-app.com/webhook",
name: "Memory Logger",
projectId: "proj_123",
eventTypes: ["memory:add"]
});
console.log(webhook);
```
```json Output
{
"webhook_id": "wh_123",
"name": "Memory Logger",
"url": "https://your-app.com/webhook",
"event_types": ["memory_add"],
"project": "default-project",
"is_active": true,
"created_at": "2025-02-18T22:59:56.804993-08:00",
"updated_at": "2025-02-18T23:06:41.479361-08:00"
}
```
</CodeGroup>
### Get Webhooks
Retrieve all webhooks configured for your project:
<CodeGroup>
```python Python
# Get webhooks for a specific project
webhooks = client.get_webhooks(project_id="proj_123")
print(webhooks)
```
```javascript JavaScript
// Get webhooks for a specific project
const webhooks = await client.getWebhooks({projectId: "proj_123"});
console.log(webhooks);
```
```json Output
[
{
"webhook_id": "wh_123",
"url": "https://mem0.ai",
"name": "mem0",
"owner": "john",
"event_types": ["memory_add"],
"project": "default-project",
"is_active": true,
"created_at": "2025-02-18T22:59:56.804993-08:00",
"updated_at": "2025-02-18T23:06:41.479361-08:00"
}
]
```
</CodeGroup>
### Update Webhook
Modify an existing webhook's configuration. Remember that webhooks can only be updated within their associated project:
<CodeGroup>
```python Python
# Update webhook for a specific project
updated_webhook = client.update_webhook(
name="Updated Logger",
url="https://your-app.com/new-webhook",
event_types=["memory:update", "memory:add"],
project_id="proj_123",
webhook_id="wh_123"
)
print(updated_webhook)
```
```javascript JavaScript
// Update webhook for a specific project
const updatedWebhook = await client.updateWebhook({
name: "Updated Logger",
url: "https://your-app.com/new-webhook",
eventTypes: ["memory:update", "memory:add"],
projectId: "proj_123",
webhookId: "wh_123"
});
console.log(updatedWebhook);
```
```json Output
{
"message": "Webhook updated successfully"
}
```
</CodeGroup>
### Delete Webhook
Remove a webhook configuration from a project:
<CodeGroup>
```python Python
# Delete webhook from a specific project
response = client.delete_webhook(webhook_id="wh_123", project_id="proj_123")
print(response)
```
```javascript JavaScript
// Delete webhook from a specific project
const response = await client.deleteWebhook("wh_123", "proj_123");
console.log(response);
```
```json Output
{
"message": "Webhook deleted successfully"
}
```
</CodeGroup>
## Event Types
Mem0 supports the following event types for webhooks:
- `memory:add`: Triggered when a new memory is added.
- `memory:update`: Triggered when an existing memory is updated.
- `memory:delete`: Triggered when a memory is deleted.
## Webhook Payload
When a memory event occurs in your project, Mem0 sends a POST request to your webhook URL with the following example payload structure:
```json
{
"event_details": {
"id": "a1b2c3d4-e5f6-4g7h-8i9j-k0l1m2n3o4p5",
"data": {
"memory": "Name is Alex"
},
"event": "ADD"
}
}
```
## Best Practices
1. **Implement Retry Logic**: Your webhook endpoint should be able to handle temporary failures and implement appropriate retry mechanisms.
2. **Verify Webhook Source**: Implement security measures to verify that webhook requests are coming from Mem0.
3. **Process Events Asynchronously**: Handle webhook events asynchronously to prevent timeouts and ensure reliable processing.
4. **Monitor Webhook Health**: Regularly check your webhook logs to ensure proper functionality and handle any delivery failures.
If you have any questions, please feel free to reach out to us using one of the following methods:
<Snippet file="get-help.mdx" />
Binary file not shown.

After

Width:  |  Height:  |  Size: 276 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 KiB

File diff suppressed because one or more lines are too long
+47 -1
View File
@@ -5,7 +5,7 @@ title: Vercel AI SDK
The [**Mem0 AI SDK Provider**](https://www.npmjs.com/package/@mem0/vercel-ai-provider) is a library developed by **Mem0** to integrate with the Vercel AI SDK. This library brings enhanced AI interaction capabilities to your applications by introducing persistent memory functionality. The [**Mem0 AI SDK Provider**](https://www.npmjs.com/package/@mem0/vercel-ai-provider) is a library developed by **Mem0** to integrate with the Vercel AI SDK. This library brings enhanced AI interaction capabilities to your applications by introducing persistent memory functionality.
<Note type="info"> <Note type="info">
🎉 Exciting news! Mem0 AI SDK now supports **OpenAI**, **Anthropic**, **Cohere**, and **Groq** providers. 🎉 Exciting news! Mem0 AI SDK now supports <strong>Tools Call</strong>.
</Note> </Note>
## Overview ## Overview
@@ -43,11 +43,19 @@ npm install @mem0/vercel-ai-provider
config: { config: {
compatibility: "strict", compatibility: "strict",
}, },
// Optional Mem0 Global Config
mem0Config: {
user_id: "mem0-user-id",
org_id: "mem0-org-id",
project_id: "mem0-project-id",
},
}); });
``` ```
> **Note**: The `openai` provider is set as default. Consider using `MEM0_API_KEY` and `OPENAI_API_KEY` as environment variables for security. > **Note**: The `openai` provider is set as default. Consider using `MEM0_API_KEY` and `OPENAI_API_KEY` as environment variables for security.
> **Note**: The `mem0Config` is optional. It is used to set the global config for the Mem0 Client (eg. `user_id`, `agent_id`, `app_id`, `run_id`, `org_id`, `project_id` etc).
3. Add Memories to Enhance Context: 3. Add Memories to Enhance Context:
```typescript ```typescript
@@ -145,6 +153,44 @@ npm install @mem0/vercel-ai-provider
} }
``` ```
### 4. Generate Responses with Tools Call
```typescript
import { generateText } from "ai";
import { createMem0 } from "@mem0/vercel-ai-provider";
import { z } from "zod";
const mem0 = createMem0({
provider: "anthropic",
apiKey: "anthropic-api-key",
mem0Config: {
// Global User ID
user_id: "borat"
}
});
const prompt = "What the temperature in the city that I live in?"
const result = await generateText({
model: mem0('claude-3-5-sonnet-20240620'),
tools: {
weather: tool({
description: 'Get the weather in a location',
parameters: z.object({
location: z.string().describe('The location to get the weather for'),
}),
execute: async ({ location }) => ({
location,
temperature: 72 + Math.floor(Math.random() * 21) - 10,
}),
}),
},
prompt: prompt,
});
console.log(result);
```
## Key Features ## Key Features
- `createMem0()`: Initializes a new Mem0 provider instance. - `createMem0()`: Initializes a new Mem0 provider instance.
-252
View File
@@ -1,252 +0,0 @@
{
"$schema": "https://mintlify.com/schema.json",
"name": "Mem0.ai",
"favicon": "/logo/favicon.png",
"colors": {
"primary": "#6c60f0",
"light": "#E6FFA2",
"dark": "#a3df02",
"background": {
"dark": "#0f1117",
"light": "#fff"
}
},
"logo": {
"dark": "/logo/dark.svg",
"light": "/logo/light.svg",
"href": "https://github.com/mem0ai/mem0"
},
"topbarCtaButton": {
"name": "Your Dashboard",
"url": "https://app.mem0.ai"
},
"anchors": [
{
"name": "Your Dashboard",
"icon": "chart-simple",
"url": "https://app.mem0.ai"
},
{
"name": "API Reference",
"url": "api-reference",
"icon": "square-terminal"
},
{
"name": "Discord",
"icon": "discord",
"url": "https://mem0.dev/DiD"
},
{
"name": "GitHub",
"icon": "github",
"url": "https://github.com/mem0ai/mem0"
},
{
"name": "Support",
"icon": "envelope",
"url": "mailto:taranjeet@mem0.ai"
}
],
"navigation": [
{
"group": "Get Started",
"pages": [
"overview",
"quickstart",
"playground",
"features"
]
},
{
"group": "Platform",
"pages": [
"platform/overview",
"platform/quickstart",
{
"group": "Features",
"pages": ["features/selective-memory", "features/custom-categories", "features/custom-instructions", "features/direct-import", "features/async-client", "features/memory-export"]
},
"features/langchain-tools"
]
},
{
"group": "Open Source",
"pages": [
"open-source/quickstart",
{
"group": "Graph Memory",
"pages": ["open-source/graph_memory/overview", "open-source/graph_memory/features"]
},
{
"group": "LLMs",
"pages": [
"components/llms/overview",
"components/llms/config",
{
"group": "Supported LLMs",
"pages": [
"components/llms/models/openai",
"components/llms/models/anthropic",
"components/llms/models/azure_openai",
"components/llms/models/ollama",
"components/llms/models/together",
"components/llms/models/groq",
"components/llms/models/litellm",
"components/llms/models/mistral_AI",
"components/llms/models/google_AI",
"components/llms/models/aws_bedrock",
"components/llms/models/gemini"
]
}
]
},
{
"group": "Vector Databases",
"pages": [
"components/vectordbs/overview",
"components/vectordbs/config",
{
"group": "Supported Vector Databases",
"pages": [
"components/vectordbs/dbs/qdrant",
"components/vectordbs/dbs/chroma",
"components/vectordbs/dbs/pgvector",
"components/vectordbs/dbs/milvus",
"components/vectordbs/dbs/azure_ai_search",
"components/vectordbs/dbs/redis",
"components/vectordbs/dbs/elasticsearch"
]
}
]
},
{
"group": "Embedding Models",
"pages": [
"components/embedders/overview",
"components/embedders/config",
{
"group": "Supported Embedding Models",
"pages": [
"components/embedders/models/openai",
"components/embedders/models/azure_openai",
"components/embedders/models/ollama",
"components/embedders/models/huggingface",
"components/embedders/models/vertexai",
"components/embedders/models/gemini"
]
}
]
},
{
"group": "Features",
"pages": ["features/openai_compatibility", "features/custom-prompts"]
}
]
},
{
"group": "API Reference",
"pages": [
"api-reference/overview",
{
"group": "Memory APIs",
"pages": [
"api-reference/memory/v1-get-memories",
"api-reference/memory/v2-get-memories",
"api-reference/memory/add-memories",
"api-reference/memory/delete-memories",
"api-reference/memory/get-memory",
"api-reference/memory/update-memory",
"api-reference/memory/delete-memory",
"api-reference/memory/v1-search-memories",
"api-reference/memory/v2-search-memories",
"api-reference/memory/history-memory",
"api-reference/memory/batch-update",
"api-reference/memory/batch-delete",
"api-reference/memory/create-memory-export",
"api-reference/memory/get-memory-export"
]
},
{
"group": "Entities APIs",
"pages": [
"api-reference/entities/get-users",
"api-reference/entities/delete-user"
]
},
{
"group": "Organizations APIs",
"pages": [
"api-reference/organization/get-orgs",
"api-reference/organization/get-org",
"api-reference/organization/create-org",
"api-reference/organization/delete-org",
{
"group": "Members APIs",
"pages": [
"api-reference/organization/get-org-members",
"api-reference/organization/add-org-member",
"api-reference/organization/update-org-member",
"api-reference/organization/delete-org-member"
]
}
]
},
{
"group": "Projects APIs",
"pages": [
"api-reference/project/get-projects",
"api-reference/project/get-project",
"api-reference/project/create-project",
"api-reference/project/delete-project",
"api-reference/project/get-instructions-and-categories",
"api-reference/project/update-instructions-and-categories",
{
"group": "Members APIs",
"pages":[
"api-reference/project/get-project-members",
"api-reference/project/add-project-member",
"api-reference/project/update-project-member",
"api-reference/project/delete-project-member"
]
}
]
}
]
},
{
"group": "Integrations",
"pages": [
"integrations/vercel-ai-sdk",
"integrations/crewai",
"integrations/multion",
"integrations/autogen",
"integrations/langchain",
"integrations/langgraph",
"integrations/llama-index"
]
},
{
"group": "💡 Examples",
"pages": [
"examples/overview",
"examples/mem0-with-ollama",
"examples/personal-ai-tutor",
"examples/customer-support-agent",
"examples/personal-travel-assistant",
"examples/llama-index-mem0"
]
}
],
"footerSocials": {
"discord": "https://mem0.dev/DiD",
"x": "https://x.com/mem0ai",
"github": "https://github.com/mem0ai",
"linkedin": "https://www.linkedin.com/company/mem0/"
},
"analytics": {
"posthog": {
"apiKey": "phc_hgJkUVJFYtmaJqrvf6CYN67TIQ8yhXAkWzUn9AMU4yX",
"apiHost": "https://mango.mem0.ai"
}
}
}
@@ -1,6 +1,8 @@
--- ---
title: Features title: Features
description: 'Graph Memory features' description: 'Graph Memory features'
icon: "list-check"
iconType: "solid"
--- ---
Graph Memory is a powerful feature that allows users to create and utilize complex relationships between pieces of information. Graph Memory is a powerful feature that allows users to create and utilize complex relationships between pieces of information.
@@ -1,6 +1,8 @@
--- ---
title: Overview title: Overview
description: 'Enhance your memory system with graph-based knowledge representation and retrieval' description: 'Enhance your memory system with graph-based knowledge representation and retrieval'
icon: "database"
iconType: "solid"
--- ---
Mem0 now supports **Graph Memory**. Mem0 now supports **Graph Memory**.
+119
View File
@@ -0,0 +1,119 @@
---
title: Multimodal Support
icon: "image"
iconType: "solid"
---
Mem0 extends its capabilities beyond text by supporting multimodal data, including images. Users can seamlessly integrate images into their interactions, allowing Mem0 to extract pertinent information from visual content and enrich the memory system.
## How It Works
When a user provides an image, Mem0 processes the image to extract textual information and relevant details, which are then added to the user's memory. This feature enhances the system's ability to understand and remember details based on visual inputs.
<CodeGroup>
```python Code
from mem0 import Memory
client = Memory()
messages = [
{
"role": "user",
"content": "Hi, my name is Alice."
},
{
"role": "assistant",
"content": "Nice to meet you, Alice! What do you like to eat?"
},
{
"role": "user",
"content": {
"type": "image_url",
"image_url": {
"url": "https://www.superhealthykids.com/wp-content/uploads/2021/10/best-veggie-pizza-featured-image-square-2.jpg"
}
}
},
]
# Calling the add method to ingest messages into the memory system
client.add(messages, user_id="alice")
```
```json Output
{
"results": [
{
"memory": "Name is Alice",
"event": "ADD",
"id": "7ae113a3-3cb5-46e9-b6f7-486c36391847"
},
{
"memory": "Likes large pizza with toppings including cherry tomatoes, black olives, green spinach, yellow bell peppers, diced ham, and sliced mushrooms",
"event": "ADD",
"id": "56545065-7dee-4acf-8bf2-a5b2535aabb3"
}
]
}
```
</CodeGroup>
## Image Integration Methods
Mem0 allows you to add images to user interactions through two primary methods: by providing an image URL or by using a Base64-encoded image. Below are examples demonstrating each approach.
## 1. Using an Image URL (Recommended)
You can include an image by passing its direct URL. This method is simple and efficient for online images.
```python
# Define the image URL
image_url = "https://www.superhealthykids.com/wp-content/uploads/2021/10/best-veggie-pizza-featured-image-square-2.jpg"
# Create the message dictionary with the image URL
image_message = {
"role": "user",
"content": {
"type": "image_url",
"image_url": {
"url": image_url
}
}
}
```
## 2. Using Base64 Image Encoding for Local Files
For local images or scenarios where embedding the image directly is preferable, you can use a Base64-encoded string.
```python
import base64
# Path to the image file
image_path = "path/to/your/image.jpg"
# Encode the image in Base64
with open(image_path, "rb") as image_file:
base64_image = base64.b64encode(image_file.read()).decode("utf-8")
# Create the message dictionary with the Base64-encoded image
image_message = {
"role": "user",
"content": {
"type": "image_url",
"image_url": {
"url": f"data:image/jpeg;base64,{base64_image}"
}
}
}
```
By utilizing these methods, you can effectively incorporate images into user interactions, enhancing the multimodal capabilities of your Mem0 instance.
<Note>
Currently, we support only OpenAI models for image description.
</Note>
If you have any questions, please feel free to reach out to us using one of the following methods:
<Snippet file="get-help.mdx" />
+103 -1
View File
@@ -1,6 +1,8 @@
--- ---
title: Guide title: Guide
description: 'Get started with Mem0 quickly!' description: 'Get started with Mem0 quickly!'
icon: "book"
iconType: "solid"
--- ---
> Welcome to the Mem0 quickstart guide. This guide will help you get up and running with Mem0 in no time. > Welcome to the Mem0 quickstart guide. This guide will help you get up and running with Mem0 in no time.
@@ -245,6 +247,106 @@ m.delete_all(user_id="alice")
m.reset() # Reset all memories m.reset() # Reset all memories
``` ```
## Configuration Parameters
Mem0 offers extensive configuration options to customize its behavior according to your needs. These configurations span across different components like vector stores, language models, embedders, and graph stores.
<AccordionGroup>
<Accordion title="Vector Store Configuration">
| Parameter | Description | Default |
|-------------|---------------------------------|-------------|
| `provider` | Vector store provider (e.g., "qdrant") | "qdrant" |
| `host` | Host address | "localhost" |
| `port` | Port number | 6333 |
</Accordion>
<Accordion title="LLM Configuration">
| Parameter | Description | Provider |
|-----------------------|-----------------------------------------------|-------------------|
| `provider` | LLM provider (e.g., "openai", "anthropic") | All |
| `model` | Model to use | All |
| `temperature` | Temperature of the model | All |
| `api_key` | API key to use | All |
| `max_tokens` | Tokens to generate | All |
| `top_p` | Probability threshold for nucleus sampling | All |
| `top_k` | Number of highest probability tokens to keep | All |
| `http_client_proxies` | Allow proxy server settings | AzureOpenAI |
| `models` | List of models | Openrouter |
| `route` | Routing strategy | Openrouter |
| `openrouter_base_url` | Base URL for Openrouter API | Openrouter |
| `site_url` | Site URL | Openrouter |
| `app_name` | Application name | Openrouter |
| `ollama_base_url` | Base URL for Ollama API | Ollama |
| `openai_base_url` | Base URL for OpenAI API | OpenAI |
| `azure_kwargs` | Azure LLM args for initialization | AzureOpenAI |
| `deepseek_base_url` | Base URL for DeepSeek API | DeepSeek |
</Accordion>
<Accordion title="Embedder Configuration">
| Parameter | Description | Default |
|-------------|---------------------------------|------------------------------|
| `provider` | Embedding provider | "openai" |
| `model` | Embedding model to use | "text-embedding-3-small" |
| `api_key` | API key for embedding service | None |
</Accordion>
<Accordion title="Graph Store Configuration">
| Parameter | Description | Default |
|-------------|---------------------------------|-------------|
| `provider` | Graph store provider (e.g., "neo4j") | "neo4j" |
| `url` | Connection URL | None |
| `username` | Authentication username | None |
| `password` | Authentication password | None |
</Accordion>
<Accordion title="General Configuration">
| Parameter | Description | Default |
|------------------|--------------------------------------|----------------------------|
| `history_db_path` | Path to the history database | "{mem0_dir}/history.db" |
| `version` | API version | "v1.0" |
| `custom_prompt` | Custom prompt for memory processing | None |
</Accordion>
<Accordion title="Complete Configuration Example">
```python
config = {
"vector_store": {
"provider": "qdrant",
"config": {
"host": "localhost",
"port": 6333
}
},
"llm": {
"provider": "openai",
"config": {
"api_key": "your-api-key",
"model": "gpt-4"
}
},
"embedder": {
"provider": "openai",
"config": {
"api_key": "your-api-key",
"model": "text-embedding-3-small"
}
},
"graph_store": {
"provider": "neo4j",
"config": {
"url": "neo4j+s://your-instance",
"username": "neo4j",
"password": "password"
}
},
"history_db_path": "/path/to/history.db",
"version": "v1.1",
"custom_prompt": "Optional custom prompt for memory processing"
}
```
</Accordion>
</AccordionGroup>
## Run Mem0 Locally ## Run Mem0 Locally
Please refer to the example [Mem0 with Ollama](../examples/mem0-with-ollama) to run Mem0 locally. Please refer to the example [Mem0 with Ollama](../examples/mem0-with-ollama) to run Mem0 locally.
@@ -384,4 +486,4 @@ Please make sure your code follows our coding conventions and is well-documented
If you have any questions, please feel free to reach out to us using one of the following methods: If you have any questions, please feel free to reach out to us using one of the following methods:
<Snippet file="get-help.mdx" /> <Snippet file="get-help.mdx" />
+322 -414
View File
@@ -95,22 +95,6 @@
], ],
"operationId": "entities_list", "operationId": "entities_list",
"parameters": [ "parameters": [
{
"name": "org_name",
"in": "query",
"schema": {
"type": "string"
},
"description": "Filter entities by organization name. Will be deprecated soon, use `org_id` instead."
},
{
"name": "project_name",
"in": "query",
"schema": {
"type": "string"
},
"description": "Filter entities by project name. Will be deprecated soon, use `project_id` instead."
},
{ {
"name": "org_id", "name": "org_id",
"in": "query", "in": "query",
@@ -201,7 +185,7 @@
"x-code-samples": [ "x-code-samples": [
{ {
"lang": "Python", "lang": "Python",
"source": "# To use the Python SDK, install the package:\n# pip install mem0ai\n\nfrom mem0 import MemoryClient\nclient = MemoryClient(api_key=\"your-api-key\")\nusers = client.users()\nprint(users)" "source": "# To use the Python SDK, install the package:\n# pip install mem0ai\n\nfrom mem0 import MemoryClient\nclient = MemoryClient(api_key=\"your_api_key\", org_id=\"your_org_id\", project_id=\"your_project_id\")\nusers = client.users()\nprint(users)"
}, },
{ {
"lang": "JavaScript", "lang": "JavaScript",
@@ -496,7 +480,33 @@
} }
} }
} }
} },
"x-code-samples": [
{
"lang": "Python",
"source": "# To use the Python SDK, install the package:\n# pip install mem0ai\n\nfrom mem0 import MemoryClient\n\nclient = MemoryClient(api_key=\"your_api_key\", org_id=\"your_org_id\", project_id=\"project_id\")\n\nresponse = client.get_memory_export(user_id=\"your_user_id\")\nprint(response)"
},
{
"lang": "JavaScript",
"source": "// To use the JavaScript SDK, install the package:\n// npm i mem0ai\n\nimport MemoryClient from 'mem0ai';\nconst client = new MemoryClient({ apiKey: \"your-api-key\" });\n\n// Get memory export\nclient.getMemoryExport({ user_id: \"your_user_id\" })\n .then(result => console.log(result))\n .catch(error => console.error(error));"
},
{
"lang": "cURL",
"source": "curl --request GET \\\n --url 'https://api.mem0.ai/v1/exports/?user_id=your_user_id' \\\n --header 'Authorization: Token <api-key>'"
},
{
"lang": "Go",
"source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io/ioutil\"\n)\n\nfunc main() {\n\turl := \"https://api.mem0.ai/v1/exports/?user_id=your_user_id\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Authorization\", \"Token <api-key>\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := ioutil.ReadAll(res.Body)\n\n\tfmt.Println(string(body))\n}"
},
{
"lang": "PHP",
"source": "<?php\n\n$curl = curl_init();\n\ncurl_setopt_array($curl, [\n CURLOPT_URL => \"https://api.mem0.ai/v1/exports/?user_id=your_user_id\",\n CURLOPT_RETURNTRANSFER => true,\n CURLOPT_ENCODING => \"\",\n CURLOPT_MAXREDIRS => 10,\n CURLOPT_TIMEOUT => 30,\n CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,\n CURLOPT_CUSTOMREQUEST => \"GET\",\n CURLOPT_HTTPHEADER => [\n \"Authorization: Token <api-key>\"\n ],\n]);\n\n$response = curl_exec($curl);\n$err = curl_error($curl);\n\ncurl_close($curl);\n\nif ($err) {\n echo \"cURL Error #:\" . $err;\n} else {\n echo $response;\n}"
},
{
"lang": "Java",
"source": "HttpResponse<String> response = Unirest.get(\"https://api.mem0.ai/v1/exports/?user_id=your_user_id\")\n .header(\"Authorization\", \"Token <api-key>\")\n .asString();"
}
]
}, },
"post": { "post": {
"tags": [ "tags": [
@@ -585,7 +595,33 @@
} }
} }
} }
} },
"x-code-samples": [
{
"lang": "Python",
"source": "# To use the Python SDK, install the package:\n# pip install mem0ai\n\nfrom mem0 import MemoryClient\n\nclient = MemoryClient(api_key=\"your_api_key\", org_id=\"your_org_id\", project_id=\"your_project_id\")\n\njson_schema = {pydantic_json_schema}\n\nresponse = client.create_memory_export(\n schema=json_schema,\n user_id=\"your_user_id\"\n)\nprint(response)"
},
{
"lang": "JavaScript",
"source": "// To use the JavaScript SDK, install the package:\n// npm i mem0ai\n\nimport MemoryClient from 'mem0ai';\nconst client = new MemoryClient({ apiKey: \"your-api-key\" });\n\nconst jsonSchema = {pydantic_json_schema};\n\nclient.createMemoryExport({\n schema: jsonSchema,\n user_id: \"your_user_id\"\n})\n .then(result => console.log(result))\n .catch(error => console.error(error));"
},
{
"lang": "cURL",
"source": "curl --request POST \\\n --url 'https://api.mem0.ai/v1/exports/' \\\n --header 'Authorization: Token <api-key>' \\\n --header 'Content-Type: application/json' \\\n --data '{\n \"schema\": {pydantic_json_schema},\n \"user_id\": \"your_user_id\"\n }'"
},
{
"lang": "Go",
"source": "package main\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"io/ioutil\"\n)\n\nfunc main() {\n\turl := \"https://api.mem0.ai/v1/exports/\"\n\n\tdata := map[string]interface{}{\n\t\t\"schema\": map[string]interface{}{}, // Your schema here\n\t\t\"user_id\": \"user123\",\n\t}\n\n\tjsonData, _ := json.Marshal(data)\n\n\treq, _ := http.NewRequest(\"POST\", url, bytes.NewBuffer(jsonData))\n\n\treq.Header.Add(\"Authorization\", \"Token <api-key>\")\n\treq.Header.Add(\"Content-Type\", \"application/json\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := ioutil.ReadAll(res.Body)\n\n\tfmt.Println(string(body))\n}"
},
{
"lang": "PHP",
"source": "<?php\n\n$curl = curl_init();\n\n$data = array(\n \"schema\" => array(), // Your schema here\n \"user_id\" => \"your_user_id\"\n);\n\ncurl_setopt_array($curl, [\n CURLOPT_URL => \"https://api.mem0.ai/v1/exports/\",\n CURLOPT_RETURNTRANSFER => true,\n CURLOPT_ENCODING => \"\",\n CURLOPT_MAXREDIRS => 10,\n CURLOPT_TIMEOUT => 30,\n CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,\n CURLOPT_CUSTOMREQUEST => \"POST\",\n CURLOPT_POSTFIELDS => json_encode($data),\n CURLOPT_HTTPHEADER => [\n \"Authorization: Token <api-key>\",\n \"Content-Type: application/json\"\n ],\n]);\n\n$response = curl_exec($curl);\n$err = curl_error($curl);\n\ncurl_close($curl);\n\nif ($err) {\n echo \"cURL Error #:\" . $err;\n} else {\n echo $response;\n}"
},
{
"lang": "Java",
"source": "import com.mashape.unirest.http.HttpResponse;\nimport com.mashape.unirest.http.JsonNode;\nimport com.mashape.unirest.http.Unirest;\nimport org.json.JSONObject;\n\nJSONObject data = new JSONObject()\n .put(\"schema\", new JSONObject()) // Your schema here\n .put(\"user_id\", \"your_user_id\");\n\nHttpResponse<JsonNode> response = Unirest.post(\"https://api.mem0.ai/v1/exports/\")\n .header(\"Authorization\", \"Token <api-key>\")\n .header(\"Content-Type\", \"application/json\")\n .body(data.toString())\n .asJson();"
}
]
} }
}, },
"/v1/memories/": { "/v1/memories/": {
@@ -647,22 +683,6 @@
}, },
"description": "Filter memories by categories" "description": "Filter memories by categories"
}, },
{
"name": "org_name",
"in": "query",
"schema": {
"type": "string"
},
"description": "Filter memories by organization name. Will be deprecated soon, use `org_id` instead."
},
{
"name": "project_name",
"in": "query",
"schema": {
"type": "string"
},
"description": "Filter memories by project name. Will be deprecated soon, use `project_id` instead."
},
{ {
"name": "org_id", "name": "org_id",
"in": "query", "in": "query",
@@ -811,12 +831,12 @@
"x-code-samples": [ "x-code-samples": [
{ {
"lang": "Python", "lang": "Python",
"source": "# To use the Python SDK, install the package:\n# pip install mem0ai\n\nfrom mem0 import MemoryClient\nclient = MemoryClient(api_key=\"your-api-key\")\n\n# Retrieve memories for a specific user\nuser_memories = client.get_all(user_id=\"<user_id>\")\n\nprint(user_memories)" "source": "# To use the Python SDK, install the package:\n# pip install mem0ai\n\nfrom mem0 import MemoryClient\nclient = MemoryClient(api_key=\"your_api_key\", org_id=\"your_org_id\", project_id=\"your_project_id\")\n\n# Retrieve memories for a specific user\nuser_memories = client.get_all(user_id=\"<user_id>\")\n\nprint(user_memories)"
}, },
{ {
"lang": "JavaScript", "lang": "JavaScript",
"source": "// To use the JavaScript SDK, install the package:\n// npm i mem0ai\n\nimport MemoryClient from 'mem0ai';\nconst client = new MemoryClient({ apiKey: \"your-api-key\" });\n\n// Retrieve memories for a specific user\nclient.getAll({ user_id: \"<user_id>\" })\n .then(result => console.log(result))\n .catch(error => console.error(error));" "source": "// To use the JavaScript SDK, install the package:\n// npm i mem0ai\n\nimport MemoryClient from 'mem0ai';\nconst client = new MemoryClient({ apiKey: \"your-api-key\" });\n\n// Retrieve memories for a specific user\nclient.getAll({ user_id: \"<user_id>\" })\n .then(result => console.log(result))\n .catch(error => console.error(error));"
}, },
{ {
"lang": "cURL", "lang": "cURL",
"source": "curl --location --request GET 'https://api.mem0.ai/v1/memories/' \\\n--header 'Authorization: Token <api-key>'" "source": "curl --location --request GET 'https://api.mem0.ai/v1/memories/' \\\n--header 'Authorization: Token <api-key>'"
@@ -918,7 +938,7 @@
"x-code-samples": [ "x-code-samples": [
{ {
"lang": "Python", "lang": "Python",
"source": "# To use the Python SDK, install the package:\n# pip install mem0ai\n\nfrom mem0 import MemoryClient\n\nclient = MemoryClient(api_key=\"your-api-key\")\n\nmessages = [\n {\"role\": \"user\", \"content\": \"<user-message>\"},\n {\"role\": \"assistant\", \"content\": \"<assistant-response>\"}\n]\n\nclient.add(messages, user_id=\"<user-id>\")" "source": "# To use the Python SDK, install the package:\n# pip install mem0ai\n\nfrom mem0 import MemoryClient\n\nclient = MemoryClient(api_key=\"your_api_key\", org_id=\"your_org_id\", project_id=\"your_project_id\")\n\nmessages = [\n {\"role\": \"user\", \"content\": \"<user-message>\"},\n {\"role\": \"assistant\", \"content\": \"<assistant-response>\"}\n]\n\nclient.add(messages, user_id=\"<user-id>\")"
}, },
{ {
"lang": "JavaScript", "lang": "JavaScript",
@@ -926,19 +946,19 @@
}, },
{ {
"lang": "cURL", "lang": "cURL",
"source": "curl --request POST \\\n --url https://api.mem0.ai/v1/memories/ \\\n --header 'Authorization: Token <api-key>' \\\n --header 'Content-Type: application/json' \\\n --data '{\n \"messages\": [\n {}\n ],\n \"agent_id\": \"<string>\",\n \"user_id\": \"<string>\",\n \"app_id\": \"<string>\",\n \"run_id\": \"<string>\",\n \"metadata\": {},\n \"includes\": \"<string>\",\n \"excludes\": \"<string>\",\n \"infer\": true,\n \"custom_categories\": {},\n \"org_name\": \"<string>\",\n \"project_name\": \"<string>\", \n \"org_id\": \"<string>\",\n \"project_id\": \"<string>\"\n}'" "source": "curl --request POST \\\n --url https://api.mem0.ai/v1/memories/ \\\n --header 'Authorization: Token <api-key>' \\\n --header 'Content-Type: application/json' \\\n --data '{\n \"messages\": [\n {}\n ],\n \"agent_id\": \"<string>\",\n \"user_id\": \"<string>\",\n \"app_id\": \"<string>\",\n \"run_id\": \"<string>\",\n \"metadata\": {},\n \"includes\": \"<string>\",\n \"excludes\": \"<string>\",\n \"infer\": true,\n \"custom_categories\": {}, \n \"org_id\": \"<string>\",\n \"project_id\": \"<string>\"\n}'"
}, },
{ {
"lang": "Go", "lang": "Go",
"source": "package main\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"net/http\"\n\t\"io/ioutil\"\n)\n\nfunc main() {\n\n\turl := \"https://api.mem0.ai/v1/memories/\"\n\n\tpayload := strings.NewReader(\"{\n \\\"messages\\\": [\n {}\n ],\n \\\"agent_id\\\": \\\"<string>\\\",\n \\\"user_id\\\": \\\"<string>\\\",\n \\\"app_id\\\": \\\"<string>\\\",\n \\\"run_id\\\": \\\"<string>\\\",\n \\\"metadata\\\": {},\n \\\"includes\\\": \\\"<string>\\\",\n \\\"excludes\\\": \\\"<string>\\\",\n \\\"infer\\\": true,\n \\\"custom_categories\\\": {},\n \\\"org_name\\\": \\\"<string>\\\",\n \\\"project_name\\\": \\\"<string>\\\", \n \\\"org_id\\\": \\\"<string>\\\",\n \\\"project_id\\\": \\\"<string>\"\n}\")\n\n\treq, _ := http.NewRequest(\"POST\", url, payload)\n\n\treq.Header.Add(\"Authorization\", \"Token <api-key>\")\n\treq.Header.Add(\"Content-Type\", \"application/json\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := ioutil.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"net/http\"\n\t\"io/ioutil\"\n)\n\nfunc main() {\n\n\turl := \"https://api.mem0.ai/v1/memories/\"\n\n\tpayload := strings.NewReader(\"{\n \\\"messages\\\": [\n {}\n ],\n \\\"agent_id\\\": \\\"<string>\\\",\n \\\"user_id\\\": \\\"<string>\\\",\n \\\"app_id\\\": \\\"<string>\\\",\n \\\"run_id\\\": \\\"<string>\\\",\n \\\"metadata\\\": {},\n \\\"includes\\\": \\\"<string>\\\",\n \\\"excludes\\\": \\\"<string>\\\",\n \\\"infer\\\": true,\n \\\"custom_categories\\\": {},\n \\\"org_id\\\": \\\"<string>\\\",\n \\\"project_id\\\": \\\"<string>\"\n}\")\n\n\treq, _ := http.NewRequest(\"POST\", url, payload)\n\n\treq.Header.Add(\"Authorization\", \"Token <api-key>\")\n\treq.Header.Add(\"Content-Type\", \"application/json\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := ioutil.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}"
}, },
{ {
"lang": "PHP", "lang": "PHP",
"source": "<?php\n\n$curl = curl_init();\n\ncurl_setopt_array($curl, [\n CURLOPT_URL => \"https://api.mem0.ai/v1/memories/\",\n CURLOPT_RETURNTRANSFER => true,\n CURLOPT_ENCODING => \"\",\n CURLOPT_MAXREDIRS => 10,\n CURLOPT_TIMEOUT => 30,\n CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,\n CURLOPT_CUSTOMREQUEST => \"POST\",\n CURLOPT_POSTFIELDS => \"{\n \\\"messages\\\": [\n {}\n ],\n \\\"agent_id\\\": \\\"<string>\\\",\n \\\"user_id\\\": \\\"<string>\\\",\n \\\"app_id\\\": \\\"<string>\\\",\n \\\"run_id\\\": \\\"<string>\\\",\n \\\"metadata\\\": {},\n \\\"includes\\\": \\\"<string>\\\",\n \\\"excludes\\\": \\\"<string>\\\",\n \\\"infer\\\": true,\n \\\"custom_categories\\\": {},\n \\\"org_name\\\": \\\"<string>\\\",\n \\\"project_name\\\": \\\"<string>\\\", \n \\\"org_id\\\": \\\"<string>\\\",\n \\\"project_id\\\": \\\"<string>\"\n}\",\n CURLOPT_HTTPHEADER => [\n \"Authorization: Token <api-key>\",\n \"Content-Type: application/json\"\n ],\n]);\n\n$response = curl_exec($curl);\n$err = curl_error($curl);\n\ncurl_close($curl);\n\nif ($err) {\n echo \"cURL Error #:\" . $err;\n} else {\n echo $response;\n}" "source": "<?php\n\n$curl = curl_init();\n\ncurl_setopt_array($curl, [\n CURLOPT_URL => \"https://api.mem0.ai/v1/memories/\",\n CURLOPT_RETURNTRANSFER => true,\n CURLOPT_ENCODING => \"\",\n CURLOPT_MAXREDIRS => 10,\n CURLOPT_TIMEOUT => 30,\n CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,\n CURLOPT_CUSTOMREQUEST => \"POST\",\n CURLOPT_POSTFIELDS => \"{\n \\\"messages\\\": [\n {}\n ],\n \\\"agent_id\\\": \\\"<string>\\\",\n \\\"user_id\\\": \\\"<string>\\\",\n \\\"app_id\\\": \\\"<string>\\\",\n \\\"run_id\\\": \\\"<string>\\\",\n \\\"metadata\\\": {},\n \\\"includes\\\": \\\"<string>\\\",\n \\\"excludes\\\": \\\"<string>\\\",\n \\\"infer\\\": true,\n \\\"custom_categories\\\": {}, \n \\\"org_id\\\": \\\"<string>\\\",\n \\\"project_id\\\": \\\"<string>\"\n}\",\n CURLOPT_HTTPHEADER => [\n \"Authorization: Token <api-key>\",\n \"Content-Type: application/json\"\n ],\n]);\n\n$response = curl_exec($curl);\n$err = curl_error($curl);\n\ncurl_close($curl);\n\nif ($err) {\n echo \"cURL Error #:\" . $err;\n} else {\n echo $response;\n}"
}, },
{ {
"lang": "Java", "lang": "Java",
"source": "HttpResponse<String> response = Unirest.post(\"https://api.mem0.ai/v1/memories/\")\n .header(\"Authorization\", \"Token <api-key>\")\n .header(\"Content-Type\", \"application/json\")\n .body(\"{\n \\\"messages\\\": [\n {}\n ],\n \\\"agent_id\\\": \\\"<string>\\\",\n \\\"user_id\\\": \\\"<string>\\\",\n \\\"app_id\\\": \\\"<string>\\\",\n \\\"run_id\\\": \\\"<string>\\\",\n \\\"metadata\\\": {},\n \\\"includes\\\": \\\"<string>\\\",\n \\\"excludes\\\": \\\"<string>\\\",\n \\\"infer\\\": true,\n \\\"custom_categories\\\": {},\n \\\"org_name\\\": \\\"<string>\\\",\n \\\"project_name\\\": \\\"<string>\\\", \n \\\"org_id\\\": \\\"<string>\\\",\n \\\"project_id\\\": \\\"<string>\"\n}\")\n .asString();" "source": "HttpResponse<String> response = Unirest.post(\"https://api.mem0.ai/v1/memories/\")\n .header(\"Authorization\", \"Token <api-key>\")\n .header(\"Content-Type\", \"application/json\")\n .body(\"{\n \\\"messages\\\": [\n {}\n ],\n \\\"agent_id\\\": \\\"<string>\\\",\n \\\"user_id\\\": \\\"<string>\\\",\n \\\"app_id\\\": \\\"<string>\\\",\n \\\"run_id\\\": \\\"<string>\\\",\n \\\"metadata\\\": {},\n \\\"includes\\\": \\\"<string>\\\",\n \\\"excludes\\\": \\\"<string>\\\",\n \\\"infer\\\": true,\n \\\"custom_categories\\\": {}, \n \\\"org_id\\\": \\\"<string>\\\",\n \\\"project_id\\\": \\\"<string>\"\n}\")\n .asString();"
} }
], ],
"x-codegen-request-body-name": "data" "x-codegen-request-body-name": "data"
@@ -992,22 +1012,6 @@
"style": "deepObject", "style": "deepObject",
"explode": true "explode": true
}, },
{
"name": "org_name",
"in": "query",
"schema": {
"type": "string"
},
"description": "Filter memories by organization name. Will be deprecated soon, use `org_id` instead."
},
{
"name": "project_name",
"in": "query",
"schema": {
"type": "string"
},
"description": "Filter memories by project name. Will be deprecated soon, use `project_id` instead."
},
{ {
"name": "org_id", "name": "org_id",
"in": "query", "in": "query",
@@ -1046,7 +1050,7 @@
"x-code-samples": [ "x-code-samples": [
{ {
"lang": "Python", "lang": "Python",
"source": "# To use the Python SDK, install the package:\n# pip install mem0ai\n\nfrom mem0 import MemoryClient\nclient = MemoryClient(api_key=\"your-api-key\")\n\n# Delete all memories for a specific user\nclient.delete_all(user_id=\"<user_id>\")" "source": "# To use the Python SDK, install the package:\n# pip install mem0ai\n\nfrom mem0 import MemoryClient\nclient = MemoryClient(api_key=\"your_api_key\", org_id=\"your_org_id\", project_id=\"your_project_id\")\n\n# Delete all memories for a specific user\nclient.delete_all(user_id=\"<user_id>\")"
}, },
{ {
"lang": "JavaScript", "lang": "JavaScript",
@@ -1084,28 +1088,35 @@
"name": "filters", "name": "filters",
"in": "query", "in": "query",
"schema": { "schema": {
"type": "object" "type": "object",
"properties": {
"user_id": {"type": "string"},
"agent_id": {"type": "string"},
"app_id": {"type": "string"},
"run_id": {"type": "string"},
"created_at": {"type": "string", "format": "date-time"},
"updated_at": {"type": "string", "format": "date-time"},
"categories": {"type": "array", "items": {"type": "string"}},
"keywords": {"type": "string"}
},
"additionalProperties": {
"type": "object",
"properties": {
"in": {"type": "array"},
"gte": {"type": "string"},
"lte": {"type": "string"},
"gt": {"type": "string"},
"lt": {"type": "string"},
"ne": {"type": "string"},
"contains": {"type": "string"},
"icontains": {"type": "string"}
}
}
}, },
"description": "Filters to apply to the memories", "description": "Filters to apply to the memories. Available fields are: user_id, agent_id, app_id, run_id, created_at, updated_at, categories, keywords. Supports logical operators (AND, OR) and comparison operators (in, gte, lte, gt, lt, ne, contains, icontains)",
"style": "deepObject", "style": "deepObject",
"explode": true "explode": true
}, },
{
"name": "org_name",
"in": "query",
"schema": {
"type": "string"
},
"description": "Filter memories by organization name. Will be deprecated soon, use `org_id` instead."
},
{
"name": "project_name",
"in": "query",
"schema": {
"type": "string"
},
"description": "Filter memories by project name. Will be deprecated soon, use `project_id` instead."
},
{ {
"name": "org_id", "name": "org_id",
"in": "query", "in": "query",
@@ -1216,7 +1227,7 @@
"x-code-samples": [ "x-code-samples": [
{ {
"lang": "Python", "lang": "Python",
"source": "# To use the Python SDK, install the package:\n# pip install mem0ai\n\nfrom mem0 import MemoryClient\nclient = MemoryClient(api_key=\"your-api-key\")\n\n# Retrieve memories with filters\nmemories = client.get_all(\n filters={\n \"AND\": [\n {\n \"user_id\": \"alex\"\n },\n {\n \"created_at\": {\n \"gte\": \"2024-07-01\",\n \"lte\": \"2024-07-31\"\n }\n }\n ]\n },\n version=\"v2\"\n)\n\nprint(memories)" "source": "# To use the Python SDK, install the package:\n# pip install mem0ai\n\nfrom mem0 import MemoryClient\nclient = MemoryClient(api_key=\"your_api_key\", org_id=\"your_org_id\", project_id=\"your_project_id\")\n\n# Retrieve memories with filters\nmemories = client.get_all(\n filters={\n \"AND\": [\n {\n \"user_id\": \"alex\"\n },\n {\n \"created_at\": {\n \"gte\": \"2024-07-01\",\n \"lte\": \"2024-07-31\"\n }\n }\n ]\n },\n version=\"v2\"\n)\n\nprint(memories)"
}, },
{ {
"lang": "JavaScript", "lang": "JavaScript",
@@ -1293,44 +1304,22 @@
"type": "string", "type": "string",
"description": "The content of the memory" "description": "The content of the memory"
}, },
"input": {
"type": "array",
"items": {
"type": "object",
"properties": {
"role": {
"type": "string",
"enum": [
"user",
"assistant"
],
"description": "The role of the speaker in the conversation"
},
"content": {
"type": "string",
"description": "The content of the message"
}
},
"required": [
"role",
"content"
]
},
"description": "The conversation input that was used to generate this memory"
},
"user_id": { "user_id": {
"type": "string", "type": "string",
"description": "The identifier of the user associated with this memory" "description": "The identifier of the user associated with this memory"
}, },
"hash": {
"type": "string",
"description": "A hash of the memory content"
},
"metadata": { "metadata": {
"type": "object", "type": "object",
"nullable": true, "nullable": true,
"description": "Additional metadata associated with the memory" "description": "Additional metadata associated with the memory"
}, },
"categories": {
"type": "array",
"items": {
"type": "string"
},
"description": "Categories associated with the memory"
},
"created_at": { "created_at": {
"type": "string", "type": "string",
"format": "date-time", "format": "date-time",
@@ -1345,9 +1334,7 @@
"required": [ "required": [
"id", "id",
"memory", "memory",
"input",
"user_id", "user_id",
"hash",
"created_at", "created_at",
"updated_at" "updated_at"
] ]
@@ -1376,7 +1363,7 @@
"x-code-samples": [ "x-code-samples": [
{ {
"lang": "Python", "lang": "Python",
"source": "# To use the Python SDK, install the package:\n# pip install mem0ai\n\nfrom mem0 import MemoryClient\nclient = MemoryClient(api_key=\"your-api-key\")\n\nquery = \"Your search query here\"\n\nresults = client.search(query, user_id=\"<user_id>\", output_format=\"v1.0\")\nprint(results)" "source": "# To use the Python SDK, install the package:\n# pip install mem0ai\n\nfrom mem0 import MemoryClient\nclient = MemoryClient(api_key=\"your_api_key\", org_id=\"your_org_id\", project_id=\"your_project_id\")\n\nquery = \"Your search query here\"\n\nresults = client.search(query, user_id=\"<user_id>\", output_format=\"v1.0\")\nprint(results)"
}, },
{ {
"lang": "JavaScript", "lang": "JavaScript",
@@ -1384,7 +1371,7 @@
}, },
{ {
"lang": "cURL", "lang": "cURL",
"source": "curl --request POST \\\n --url https://api.mem0.ai/v1/memories/search/ \\\n --header 'Authorization: Token <api-key>' \\\n --header 'Content-Type: application/json' \\\n --data '{\n \"query\": \"<string>\",\n \"agent_id\": \"<string>\",\n \"user_id\": \"<string>\",\n \"app_id\": \"<string>\",\n \"run_id\": \"<string>\",\n \"metadata\": {},\n \"top_k\": 123,\n \"fields\": [\n \"<string>\"\n ],\n \"rerank\": true,\n \"org_name\": \"<string>\",\n \"project_name\": \"<string>\", \n \"org_id\": \"<string>\",\n \"project_id\": \"<string>\"\n}'" "source": "curl --request POST \\\n --url https://api.mem0.ai/v1/memories/search/ \\\n --header 'Authorization: Token <api-key>' \\\n --header 'Content-Type: application/json' \\\n --data '{\n \"query\": \"<string>\",\n \"agent_id\": \"<string>\",\n \"user_id\": \"<string>\",\n \"app_id\": \"<string>\",\n \"run_id\": \"<string>\",\n \"metadata\": {},\n \"top_k\": 123,\n \"fields\": [\n \"<string>\"\n ],\n \"rerank\": true,\n \"org_id\": \"<string>\",\n \"project_id\": \"<string>\"\n}'"
}, },
{ {
"lang": "Go", "lang": "Go",
@@ -1438,44 +1425,22 @@
"type": "string", "type": "string",
"description": "The content of the memory" "description": "The content of the memory"
}, },
"input": {
"type": "array",
"items": {
"type": "object",
"properties": {
"role": {
"type": "string",
"enum": [
"user",
"assistant"
],
"description": "The role of the speaker in the conversation"
},
"content": {
"type": "string",
"description": "The content of the message"
}
},
"required": [
"role",
"content"
]
},
"description": "The conversation input that was used to generate this memory"
},
"user_id": { "user_id": {
"type": "string", "type": "string",
"description": "The identifier of the user associated with this memory" "description": "The identifier of the user associated with this memory"
}, },
"hash": {
"type": "string",
"description": "A hash of the memory content"
},
"metadata": { "metadata": {
"type": "object", "type": "object",
"nullable": true, "nullable": true,
"description": "Additional metadata associated with the memory" "description": "Additional metadata associated with the memory"
}, },
"categories": {
"type": "array",
"items": {
"type": "string"
},
"description": "Categories associated with the memory"
},
"created_at": { "created_at": {
"type": "string", "type": "string",
"format": "date-time", "format": "date-time",
@@ -1490,9 +1455,7 @@
"required": [ "required": [
"id", "id",
"memory", "memory",
"input",
"user_id", "user_id",
"hash",
"created_at", "created_at",
"updated_at" "updated_at"
] ]
@@ -1505,7 +1468,7 @@
"x-code-samples": [ "x-code-samples": [
{ {
"lang": "Python", "lang": "Python",
"source": "# To use the Python SDK, install the package:\n# pip install mem0ai\n\nfrom mem0 import MemoryClient\nclient = MemoryClient(api_key=\"your-api-key\")\n\nquery = \"What do you know about me?\"\nfilters = {\n \"AND\":[\n {\n \"user_id\":\"alex\"\n },\n {\n \"agent_id\":{\n \"in\":[\n \"travel-assistant\",\n \"customer-support\"\n ]\n }\n }\n ]\n}\nclient.search(query, version=\"v2\", filters=filters)" "source": "# To use the Python SDK, install the package:\n# pip install mem0ai\n\nfrom mem0 import MemoryClient\nclient = MemoryClient(api_key=\"your_api_key\", org_id=\"your_org_id\", project_id=\"your_project_id\")\n\nquery = \"What do you know about me?\"\nfilters = {\n \"AND\":[\n {\n \"user_id\":\"alex\"\n },\n {\n \"agent_id\":{\n \"in\":[\n \"travel-assistant\",\n \"customer-support\"\n ]\n }\n }\n ]\n}\nclient.search(query, version=\"v2\", filters=filters)"
}, },
{ {
"lang": "JavaScript", "lang": "JavaScript",
@@ -1513,19 +1476,19 @@
}, },
{ {
"lang": "cURL", "lang": "cURL",
"source": "curl --request POST \\\n --url https://api.mem0.ai/v2/memories/search/ \\\n --header 'Authorization: Token <api-key>' \\\n --header 'Content-Type: application/json' \\\n --data '{\n \"query\": \"<string>\",\n \"filters\": {},\n \"top_k\": 123,\n \"fields\": [\n \"<string>\"\n ],\n \"rerank\": true,\n \"org_name\": \"<string>\",\n \"project_name\": \"<string>\",\n \"org_id\": \"<string>\",\n \"project_id\": \"<string>\"\n}'" "source": "curl --request POST \\\n --url https://api.mem0.ai/v2/memories/search/ \\\n --header 'Authorization: Token <api-key>' \\\n --header 'Content-Type: application/json' \\\n --data '{\n \"query\": \"<string>\",\n \"filters\": {},\n \"top_k\": 123,\n \"fields\": [\n \"<string>\"\n ],\n \"rerank\": true,\n \"org_id\": \"<string>\",\n \"project_id\": \"<string>\"\n}'"
}, },
{ {
"lang": "Go", "lang": "Go",
"source": "package main\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"net/http\"\n\t\"io/ioutil\"\n)\n\nfunc main() {\n\n\turl := \"https://api.mem0.ai/v2/memories/search/\"\n\n\tpayload := strings.NewReader(\"{\n \\\"query\\\": \\\"<string>\\\",\n \\\"filters\\\": {},\n \\\"top_k\\\": 123,\n \\\"fields\\\": [\n \\\"<string>\\\"\n ],\n \\\"rerank\\\": true,\n \\\"org_name\\\": \\\"<string>\\\",\n \\\"project_name\\\": \\\"<string>\\\",\n \\\"org_id\\\": \\\"<string>\\\",\n \\\"project_id\\\": \\\"<string>\\\"\n}\")\n\n\treq, _ := http.NewRequest(\"POST\", url, payload)\n\n\treq.Header.Add(\"Authorization\", \"Token <api-key>\")\n\treq.Header.Add(\"Content-Type\", \"application/json\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := ioutil.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"net/http\"\n\t\"io/ioutil\"\n)\n\nfunc main() {\n\n\turl := \"https://api.mem0.ai/v2/memories/search/\"\n\n\tpayload := strings.NewReader(\"{\n \\\"query\\\": \\\"<string>\\\",\n \\\"filters\\\": {},\n \\\"top_k\\\": 123,\n \\\"fields\\\": [\n \\\"<string>\\\"\n ],\n \\\"rerank\\\": true,\n \\\"org_id\\\": \\\"<string>\\\",\n \\\"project_id\\\": \\\"<string>\\\"\n}\")\n\n\treq, _ := http.NewRequest(\"POST\", url, payload)\n\n\treq.Header.Add(\"Authorization\", \"Token <api-key>\")\n\treq.Header.Add(\"Content-Type\", \"application/json\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := ioutil.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}"
}, },
{ {
"lang": "PHP", "lang": "PHP",
"source": "<?php\n\n$curl = curl_init();\n\ncurl_setopt_array($curl, [\n CURLOPT_URL => \"https://api.mem0.ai/v2/memories/search/\",\n CURLOPT_RETURNTRANSFER => true,\n CURLOPT_ENCODING => \"\",\n CURLOPT_MAXREDIRS => 10,\n CURLOPT_TIMEOUT => 30,\n CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,\n CURLOPT_CUSTOMREQUEST => \"POST\",\n CURLOPT_POSTFIELDS => \"{\n \\\"query\\\": \\\"<string>\\\",\n \\\"filters\\\": {},\n \\\"top_k\\\": 123,\n \\\"fields\\\": [\n \\\"<string>\\\"\n ],\n \\\"rerank\\\": true,\n \\\"org_name\\\": \\\"<string>\\\",\n \\\"project_name\\\": \\\"<string>\\\",\n \\\"org_id\\\": \\\"<string>\\\",\n \\\"project_id\\\": \\\"<string>\\\"\n}\",\n CURLOPT_HTTPHEADER => [\n \"Authorization: Token <api-key>\",\n \"Content-Type: application/json\"\n ],\n]);\n\n$response = curl_exec($curl);\n$err = curl_error($curl);\n\ncurl_close($curl);\n\nif ($err) {\n echo \"cURL Error #:\" . $err;\n} else {\n echo $response;\n}" "source": "<?php\n\n$curl = curl_init();\n\ncurl_setopt_array($curl, [\n CURLOPT_URL => \"https://api.mem0.ai/v2/memories/search/\",\n CURLOPT_RETURNTRANSFER => true,\n CURLOPT_ENCODING => \"\",\n CURLOPT_MAXREDIRS => 10,\n CURLOPT_TIMEOUT => 30,\n CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,\n CURLOPT_CUSTOMREQUEST => \"POST\",\n CURLOPT_POSTFIELDS => \"{\n \\\"query\\\": \\\"<string>\\\",\n \\\"filters\\\": {},\n \\\"top_k\\\": 123,\n \\\"fields\\\": [\n \\\"<string>\\\"\n ],\n \\\"rerank\\\": true,\n \\\"org_id\\\": \\\"<string>\\\",\n \\\"project_id\\\": \\\"<string>\\\"\n}\",\n CURLOPT_HTTPHEADER => [\n \"Authorization: Token <api-key>\",\n \"Content-Type: application/json\"\n ],\n]);\n\n$response = curl_exec($curl);\n$err = curl_error($curl);\n\ncurl_close($curl);\n\nif ($err) {\n echo \"cURL Error #:\" . $err;\n} else {\n echo $response;\n}"
}, },
{ {
"lang": "Java", "lang": "Java",
"source": "HttpResponse<String> response = Unirest.post(\"https://api.mem0.ai/v2/memories/search/\")\n .header(\"Authorization\", \"Token <api-key>\")\n .header(\"Content-Type\", \"application/json\")\n .body(\"{\n \\\"query\\\": \\\"<string>\\\",\n \\\"filters\\\": {},\n \\\"top_k\\\": 123,\n \\\"fields\\\": [\n \\\"<string>\\\"\n ],\n \\\"rerank\\\": true,\n \\\"org_name\\\": \\\"<string>\\\",\n \\\"project_name\\\": \\\"<string>\\\",\n \\\"org_id\\\": \\\"<string>\\\",\n \\\"project_id\\\": \\\"<string>\\\"\n}\")\n .asString();" "source": "HttpResponse<String> response = Unirest.post(\"https://api.mem0.ai/v2/memories/search/\")\n .header(\"Authorization\", \"Token <api-key>\")\n .header(\"Content-Type\", \"application/json\")\n .body(\"{\n \\\"query\\\": \\\"<string>\\\",\n \\\"filters\\\": {},\n \\\"top_k\\\": 123,\n \\\"fields\\\": [\n \\\"<string>\\\"\n ],\n \\\"rerank\\\": true,\n \\\"org_id\\\": \\\"<string>\\\",\n \\\"project_id\\\": \\\"<string>\\\"\n}\")\n .asString();"
} }
], ],
"x-codegen-request-body-name": "data" "x-codegen-request-body-name": "data"
@@ -1663,7 +1626,7 @@
"x-code-samples": [ "x-code-samples": [
{ {
"lang": "Python", "lang": "Python",
"source": "# To use the Python SDK, install the package:\n# pip install mem0ai\n\nfrom mem0 import MemoryClient\nclient = MemoryClient(api_key=\"your-api-key\")\n\nmemory = client.get(memory_id=\"<memory_id>\")" "source": "# To use the Python SDK, install the package:\n# pip install mem0ai\n\nfrom mem0 import MemoryClient\nclient = MemoryClient(api_key=\"your_api_key\", org_id=\"your_org_id\", project_id=\"your_project_id\")\n\nmemory = client.get(memory_id=\"<memory_id>\")"
}, },
{ {
"lang": "JavaScript", "lang": "JavaScript",
@@ -1784,7 +1747,7 @@
"x-code-samples": [ "x-code-samples": [
{ {
"lang": "Python", "lang": "Python",
"source": "# To use the Python SDK, install the package:\n# pip install mem0ai\n\nfrom mem0 import MemoryClient\nclient = MemoryClient(api_key=\"your-api-key\")\n\n# Update a memory\nmemory_id = \"<memory_id>\"\nmessage = \"Your updated memory message here\"\nclient.update(memory_id, message)" "source": "# To use the Python SDK, install the package:\n# pip install mem0ai\n\nfrom mem0 import MemoryClient\nclient = MemoryClient(api_key=\"your_api_key\", org_id=\"your_org_id\", project_id=\"your_project_id\")\n\n# Update a memory\nmemory_id = \"<memory_id>\"\nmessage = \"Your updated memory message here\"\nclient.update(memory_id, message)"
}, },
{ {
"lang": "JavaScript", "lang": "JavaScript",
@@ -1848,7 +1811,7 @@
"x-code-samples": [ "x-code-samples": [
{ {
"lang": "Python", "lang": "Python",
"source": "# To use the Python SDK, install the package:\n# pip install mem0ai\n\nfrom mem0 import MemoryClient\nclient = MemoryClient(api_key=\"your-api-key\")\n\nmemory_id = \"<memory_id>\"\nclient.delete(memory_id=memory_id)" "source": "# To use the Python SDK, install the package:\n# pip install mem0ai\n\nfrom mem0 import MemoryClient\nclient = MemoryClient(api_key=\"your_api_key\", org_id=\"your_org_id\", project_id=\"your_project_id\")\n\nmemory_id = \"<memory_id>\"\nclient.delete(memory_id=memory_id)"
}, },
{ {
"lang": "JavaScript", "lang": "JavaScript",
@@ -1994,7 +1957,7 @@
"x-code-samples": [ "x-code-samples": [
{ {
"lang": "Python", "lang": "Python",
"source": "# To use the Python SDK, install the package:\n# pip install mem0ai\n\nfrom mem0 import MemoryClient\nclient = MemoryClient(api_key=\"your-api-key\")\n\n# Add some message to create history\nmessages = [{\"role\": \"user\", \"content\": \"<user-message>\"}]\nclient.add(messages, user_id=\"<user-id>\")\n\n# Add second message to update history\nmessages.append({\"role\": \"user\", \"content\": \"<user-message>\"})\nclient.add(messages, user_id=\"<user-id>\")\n\n# Get history of how memory changed over time\nmemory_id = \"<memory-id-here>\"\nhistory = client.history(memory_id)" "source": "# To use the Python SDK, install the package:\n# pip install mem0ai\n\nfrom mem0 import MemoryClient\nclient = MemoryClient(api_key=\"your_api_key\", org_id=\"your_org_id\", project_id=\"your_project_id\")\n\n# Add some message to create history\nmessages = [{\"role\": \"user\", \"content\": \"<user-message>\"}]\nclient.add(messages, user_id=\"<user-id>\")\n\n# Add second message to update history\nmessages.append({\"role\": \"user\", \"content\": \"<user-message>\"})\nclient.add(messages, user_id=\"<user-id>\")\n\n# Get history of how memory changed over time\nmemory_id = \"<memory-id-here>\"\nhistory = client.history(memory_id)"
}, },
{ {
"lang": "JavaScript", "lang": "JavaScript",
@@ -3295,31 +3258,152 @@
}, },
"x-code-samples": [ "x-code-samples": [
{ {
"lang": "Python", "lang": "Python",
"source": "import requests\n\nurl = \"https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/projects/{project_id}/\"\n\nheaders = {\"Authorization\": \"<api-key>\"}\n\nresponse = requests.request(\"GET\", url, headers=headers)\n\nprint(response.text)" "source": "# To use the Python SDK, install the package:\n# pip install mem0ai\n\nfrom mem0 import MemoryClient\n\nclient = MemoryClient(api_key=\"your_api_key\", org_id=\"your_org_id\", project_id=\"your_project_id\")\n\nresponse = client.get_project()\nprint(response)"
}, },
{ {
"lang": "JavaScript", "lang": "JavaScript",
"source": "const options = {method: 'GET', headers: {Authorization: 'Token <api-key>'}};\n\nfetch('https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/projects/{project_id}/', options)\n .then(response => response.json())\n .then(response => console.log(response))\n .catch(err => console.error(err));" "source": "// To use the JavaScript SDK, install the package:\n// npm i mem0ai\n\nimport MemoryClient from 'mem0ai';\nconst client = new MemoryClient({ apiKey: \"your-api-key\" });\n\nclient.getProject()\n .then(response => console.log(response))\n .catch(err => console.error(err));"
}, },
{ {
"lang": "cURL", "lang": "cURL",
"source": "curl --request GET \\\n --url https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/projects/{project_id}/ \\\n --header 'Authorization: Token <api-key>'" "source": "curl --request GET \\\n --url https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/projects/{project_id}/ \\\n --header 'Authorization: Token <api-key>'"
}, },
{ {
"lang": "Go", "lang": "Go",
"source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io/ioutil\"\n)\n\nfunc main() {\n\n\turl := \"https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/projects/{project_id}/\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Authorization\", \"Token <api-key>\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := ioutil.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" "source": "// To use the Go SDK, install the package:\n// go get github.com/mem0ai/mem0-go\n\npackage main\n\nimport (\n\t\"fmt\"\n\t\"github.com/mem0ai/mem0-go\"\n)\n\nfunc main() {\n\tclient := mem0.NewClient(\"your-api-key\")\n\n\tresponse, err := client.GetProject()\n\tif err != nil {\n\t\tfmt.Printf(\"Error: %v\\n\", err)\n\t\treturn\n\t}\n\tfmt.Printf(\"%+v\\n\", response)\n}"
}, },
{ {
"lang": "PHP", "lang": "PHP",
"source": "<?php\n\n$curl = curl_init();\n\ncurl_setopt_array($curl, [\n CURLOPT_URL => \"https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/projects/{project_id}/\",\n CURLOPT_RETURNTRANSFER => true,\n CURLOPT_ENCODING => \"\",\n CURLOPT_MAXREDIRS => 10,\n CURLOPT_TIMEOUT => 30,\n CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,\n CURLOPT_CUSTOMREQUEST => \"GET\",\n CURLOPT_HTTPHEADER => [\n \"Authorization: Token <api-key>\"\n ],\n]);\n\n$response = curl_exec($curl);\n$err = curl_error($curl);\n\ncurl_close($curl);\n\nif ($err) {\n echo \"cURL Error #:\" . $err;\n} else {\n echo $response;\n}" "source": "<?php\n// To use the PHP SDK, install the package:\n// composer require mem0ai/mem0-php\n\nrequire_once('vendor/autoload.php');\n\nuse Mem0\\MemoryClient;\n\n$client = new MemoryClient('your-api-key');\n\ntry {\n $response = $client->getProject();\n print_r($response);\n} catch (Exception $e) {\n echo 'Error: ' . $e->getMessage();\n}"
}, },
{ {
"lang": "Java", "lang": "Java",
"source": "HttpResponse<String> response = Unirest.get(\"https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/projects/{project_id}/\")\n .header(\"Authorization\", \"Token <api-key>\")\n .asString();" "source": "// To use the Java SDK, add this dependency to your pom.xml:\n// <dependency>\n// <groupId>ai.mem0</groupId>\n// <artifactId>mem0-java</artifactId>\n// <version>1.0.0</version>\n// </dependency>\n\nimport ai.mem0.MemoryClient;\n\npublic class Example {\n public static void main(String[] args) {\n MemoryClient client = new MemoryClient(\"your-api-key\");\n \n try {\n Object response = client.getProject();\n System.out.println(response);\n } catch (Exception e) {\n System.err.println(\"Error: \" + e.getMessage());\n }\n }\n}"
} }
] ]
}, },
"patch": {
"tags": [
"projects"
],
"summary": "Update Project",
"description": "Update a specific project's settings.",
"operationId": "update_project",
"parameters": [
{
"name": "org_id",
"in": "path",
"required": true,
"description": "Unique identifier of the organization",
"schema": {
"type": "string"
}
},
{
"name": "project_id",
"in": "path",
"required": true,
"description": "Unique identifier of the project to be updated",
"schema": {
"type": "string"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Name of the project"
},
"description": {
"type": "string",
"description": "Description of the project"
},
"custom_instructions": {
"type": "array",
"items": {
"type": "string"
},
"description": "Custom instructions for memory processing in this project"
},
"custom_categories": {
"type": "array",
"items": {
"type": "object"
},
"description": "List of custom categories to be used for memory categorization"
}
}
}
}
}
},
"responses": {
"200": {
"description": "Project updated successfully",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"message": {
"type": "string",
"example": "Project updated successfully"
}
}
}
}
}
},
"404": {
"description": "Organization or project not found",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"message": {
"type": "string",
"example": "Organization or project not found"
}
}
}
}
}
}
},
"x-code-samples": [
{
"lang": "Python",
"source": "# To use the Python SDK, install the package:\n# pip install mem0ai\n\nfrom mem0 import MemoryClient\n\nclient = MemoryClient(api_key=\"your_api_key\")\n\nnew_categories = [\n {\"cooking\": \"For users interested in cooking and culinary experiences\"},\n {\"fitness\": \"Includes content related to fitness and workouts\"}\n]\n\nresponse = client.update_project(custom_categories=new_categories)\nprint(response)"
},
{
"lang": "JavaScript",
"source": "// To use the JavaScript SDK, install the package:\n// npm i mem0ai\n\nimport MemoryClient from 'mem0ai';\nconst client = new MemoryClient({ apiKey: \"your-api-key\" });\n\nconst newCategories = [\n {\"cooking\": \"For users interested in cooking and culinary experiences\"},\n {\"fitness\": \"Includes content related to fitness and workouts\"}\n];\n\nclient.updateProject({ custom_categories: newCategories })\n .then(response => console.log(response))\n .catch(err => console.error(err));"
},
{
"lang": "cURL",
"source": "curl --request PATCH \\\n --url https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/projects/{project_id}/ \\\n --header 'Authorization: Token <api-key>' \\\n --header 'Content-Type: application/json' \\\n --data '{\n \"custom_categories\": [\n {\"cooking\": \"For users interested in cooking and culinary experiences\"},\n {\"fitness\": \"Includes content related to fitness and workouts\"}\n ]\n }'"
},
{
"lang": "Go",
"source": "// To use the Go SDK, install the package:\n// go get github.com/mem0ai/mem0-go\n\npackage main\n\nimport (\n\t\"fmt\"\n\t\"github.com/mem0ai/mem0-go\"\n)\n\nfunc main() {\n\tclient := mem0.NewClient(\"your-api-key\")\n\n\tnewCategories := []map[string]string{\n\t\t{\"cooking\": \"For users interested in cooking and culinary experiences\"},\n\t\t{\"fitness\": \"Includes content related to fitness and workouts\"},\n\t}\n\n\tresponse, err := client.UpdateProject(mem0.UpdateProjectParams{\n\t\tCustomCategories: newCategories,\n\t})\n\tif err != nil {\n\t\tfmt.Printf(\"Error: %v\\n\", err)\n\t\treturn\n\t}\n\tfmt.Printf(\"%+v\\n\", response)\n}"
},
{
"lang": "PHP",
"source": "<?php\n// To use the PHP SDK, install the package:\n// composer require mem0ai/mem0-php\n\nrequire_once('vendor/autoload.php');\n\nuse Mem0\\MemoryClient;\n\n$client = new MemoryClient('your-api-key');\n\n$newCategories = [\n ['cooking' => 'For users interested in cooking and culinary experiences'],\n ['fitness' => 'Includes content related to fitness and workouts']\n];\n\ntry {\n $response = $client->updateProject(['custom_categories' => $newCategories]);\n print_r($response);\n} catch (Exception $e) {\n echo 'Error: ' . $e->getMessage();\n}"
},
{
"lang": "Java",
"source": "// To use the Java SDK, add this dependency to your pom.xml:\n// <dependency>\n// <groupId>ai.mem0</groupId>\n// <artifactId>mem0-java</artifactId>\n// <version>1.0.0</version>\n// </dependency>\n\nimport ai.mem0.MemoryClient;\nimport java.util.*;\n\npublic class Example {\n public static void main(String[] args) {\n MemoryClient client = new MemoryClient(\"your-api-key\");\n \n List<Map<String, String>> newCategories = Arrays.asList(\n Collections.singletonMap(\"cooking\", \"For users interested in cooking and culinary experiences\"),\n Collections.singletonMap(\"fitness\", \"Includes content related to fitness and workouts\")\n );\n \n try {\n Map<String, Object> params = new HashMap<>();\n params.put(\"custom_categories\", newCategories);\n \n Object response = client.updateProject(params);\n System.out.println(response);\n } catch (Exception e) {\n System.err.println(\"Error: \" + e.getMessage());\n }\n }\n}"
}
]
},
"delete": { "delete": {
"tags": [ "tags": [
"projects" "projects"
@@ -3967,7 +4051,7 @@
"x-code-samples": [ "x-code-samples": [
{ {
"lang": "Python", "lang": "Python",
"source": "# To use the Python SDK, install the package:\n# pip install mem0ai\n\nfrom mem0 import MemoryClient\nclient = MemoryClient(api_key=\"your-api-key\")\n\nupdate_memories = [\n {\n \"memory_id\": \"285ed74b-6e05-4043-b16b-3abd5b533496\",\n \"text\": \"Watches football\"\n },\n {\n \"memory_id\": \"2c9bd859-d1b7-4d33-a6b8-94e0147c4f07\",\n \"text\": \"Likes to travel\"\n }\n]\n\nresponse = client.batch_update(update_memories)\nprint(response)" "source": "# To use the Python SDK, install the package:\n# pip install mem0ai\n\nfrom mem0 import MemoryClient\nclient = MemoryClient(api_key=\"your_api_key\", org_id=\"your_org_id\", project_id=\"your_project_id\")\n\nupdate_memories = [\n {\n \"memory_id\": \"285ed74b-6e05-4043-b16b-3abd5b533496\",\n \"text\": \"Watches football\"\n },\n {\n \"memory_id\": \"2c9bd859-d1b7-4d33-a6b8-94e0147c4f07\",\n \"text\": \"Likes to travel\"\n }\n]\n\nresponse = client.batch_update(update_memories)\nprint(response)"
}, },
{ {
"lang": "JavaScript", "lang": "JavaScript",
@@ -4044,7 +4128,7 @@
"x-code-samples": [ "x-code-samples": [
{ {
"lang": "Python", "lang": "Python",
"source": "# To use the Python SDK, install the package:\n# pip install mem0ai\n\nfrom mem0 import MemoryClient\nclient = MemoryClient(api_key=\"your-api-key\")\n\ndelete_memories = [\n {\"memory_id\": \"285ed74b-6e05-4043-b16b-3abd5b533496\"},\n {\"memory_id\": \"2c9bd859-d1b7-4d33-a6b8-94e0147c4f07\"}\n]\n\nresponse = client.batch_delete(delete_memories)\nprint(response)" "source": "# To use the Python SDK, install the package:\n# pip install mem0ai\n\nfrom mem0 import MemoryClient\nclient = MemoryClient(api_key=\"your_api_key\", org_id=\"your_org_id\", project_id=\"your_project_id\")\n\ndelete_memories = [\n {\"memory_id\": \"285ed74b-6e05-4043-b16b-3abd5b533496\"},\n {\"memory_id\": \"2c9bd859-d1b7-4d33-a6b8-94e0147c4f07\"}\n]\n\nresponse = client.batch_delete(delete_memories)\nprint(response)"
}, },
{ {
"lang": "JavaScript", "lang": "JavaScript",
@@ -4056,197 +4140,6 @@
} }
] ]
} }
},
"/api/v1/orgs/organizations/{org_id}/projects/{project_id}/custom-instructions-and-categories/": {
"get": {
"tags": ["custom-instructions-and-categories"],
"summary": "Get custom instructions and categories",
"description": "Retrieve custom categories and instructions for a specific project",
"operationId": "get_custom_instructions_and_categories",
"parameters": [
{
"name": "org_id",
"in": "path",
"required": true,
"schema": {
"type": "string"
},
"description": "Organization ID"
},
{
"name": "project_id",
"in": "path",
"required": true,
"schema": {
"type": "string"
},
"description": "Project ID"
}
],
"responses": {
"200": {
"description": "Successfully retrieved custom instructions and categories",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"custom_categories": {
"type": "array",
"items": {
"type": "string"
},
"description": "List of custom categories for the project"
},
"custom_instructions": {
"type": "string",
"description": "Custom instructions text for the project"
}
},
"required": ["custom_categories", "custom_instructions"]
}
}
}
},
"403": {
"description": "Unauthorized access",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "string",
"example": "Unauthorized to modify custom instructions and categories."
}
}
}
}
}
}
},
"x-code-samples": [
{
"lang": "Python",
"source": "import requests\n\nurl = \"https://api.mem0.ai/api/organizations/{org_id}/projects/{project_id}/custom-instructions-and-categories/\"\nheaders = {\"Authorization\": \"Token <api-key>\"}\n\nresponse = requests.get(url, headers=headers)\nprint(response.json())"
},
{
"lang": "JavaScript",
"source": "fetch('https://api.mem0.ai/api/organizations/{org_id}/projects/{project_id}/custom-instructions-and-categories/', {\n headers: {\n 'Authorization': 'Token <api-key>'\n }\n})\n.then(response => response.json())\n.then(data => console.log(data))\n.catch(error => console.error(error));"
}
]
},
"post": {
"tags": ["custom-instructions-and-categories"],
"summary": "Update custom instructions and categories",
"description": "Update custom categories and instructions for a specific project",
"operationId": "update_custom_instructions_and_categories",
"parameters": [
{
"name": "org_id",
"in": "path",
"required": true,
"schema": {
"type": "string"
},
"description": "Organization ID"
},
{
"name": "project_id",
"in": "path",
"required": true,
"schema": {
"type": "string"
},
"description": "Project ID"
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"custom_categories": {
"type": "array",
"items": {
"type": "string"
},
"description": "List of new custom categories for the project"
},
"custom_instructions": {
"type": "string",
"description": "New custom instructions text for the project"
}
}
}
}
}
},
"responses": {
"200": {
"description": "Successfully updated custom instructions and categories",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"message": {
"type": "string",
"example": "Updated custom categories / instructions"
}
}
}
}
}
},
"400": {
"description": "Bad request",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": {
"type": "array",
"items": {
"type": "string"
}
},
"example": {
"field_name": ["error message"]
}
}
}
}
},
"403": {
"description": "Unauthorized access",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "string",
"example": "Unauthorized to modify custom instructions and categories."
}
}
}
}
}
}
},
"x-code-samples": [
{
"lang": "Python",
"source": "import requests\n\nurl = \"https://api.mem0.ai/api/organizations/{org_id}/projects/{project_id}/custom-instructions-and-categories/\"\nheaders = {\n \"Authorization\": \"Token <api-key>\",\n \"Content-Type\": \"application/json\"\n}\npayload = {\n \"custom_categories\": [\"new_category1\", \"new_category2\"],\n \"custom_instructions\": \"New custom instructions text\"\n}\n\nresponse = requests.post(url, headers=headers, json=payload)\nprint(response.json())"
},
{
"lang": "JavaScript",
"source": "fetch('https://api.mem0.ai/api/organizations/{org_id}/projects/{project_id}/custom-instructions-and-categories/', {\n method: 'POST',\n headers: {\n 'Authorization': 'Token <api-key>',\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify({\n custom_categories: ['new_category1', 'new_category2'],\n custom_instructions: 'New custom instructions text'\n })\n})\n.then(response => response.json())\n.then(data => console.log(data))\n.catch(error => console.error(error));"
}
]
}
} }
}, },
"components": { "components": {
@@ -4383,30 +4276,24 @@
}, },
"nullable": true "nullable": true
}, },
"org_name": { "custom_instructions": {
"description": "The name of the organization associated with this memory. Will be deprecated soon use `org_id` instead.", "description": "Defines project-specific guidelines for handling and organizing memories. When set at the project level, they apply to all new memories in that project.",
"title": "Organization name", "title": "Custom instructions",
"type": "string", "type": "string",
"nullable": true "nullable": true
}, },
"project_name": { "org_id": {
"description": "The name of the project associated with this memory. Will be deprecated soon use project_id instead.", "description": "The unique identifier of the organization associated with this memory.",
"title": "Project name", "title": "Organization id",
"type": "string", "type": "string",
"nullable": true "nullable": true
}, },
"org_id": { "project_id": {
"description": "The unique identifier of the organization associated with this memory.", "description": "The unique identifier of the project associated with this memory.",
"title": "Organization id", "title": "Project id",
"type": "string", "type": "string",
"nullable": true "nullable": true
}, }
"project_id": {
"description": "The unique identifier of the project associated with this memory.",
"title": "Project id",
"type": "string",
"nullable": true
}
} }
}, },
"MemorySearchInput": { "MemorySearchInput": {
@@ -4474,24 +4361,18 @@
"default": false, "default": false,
"description": "Whether to rerank the memories." "description": "Whether to rerank the memories."
}, },
"keyword_search": {
"title": "Keyword search",
"type": "boolean",
"default": false,
"description": "Whether to search for memories based on keywords."
},
"output_format": { "output_format": {
"title": "Output format", "title": "Output format",
"type": "string", "type": "string",
"nullable": true, "nullable": true,
"description": "The search method supports two output formats: `v1.0` (default) and `v1.1`." "description": "The search method supports two output formats: `v1.0` (default) and `v1.1`."
}, },
"org_name": {
"title": "Organization Name",
"type": "string",
"nullable": true,
"description": "The name of the organization associated with the memory. Will be deprecated soon use `org_id` instead."
},
"project_name": {
"title": "Project Name",
"type": "string",
"nullable": true,
"description": "The name of the project associated with the memory. Will be deprecated soon use project_id instead."
},
"org_id": { "org_id": {
"title": "Organization id", "title": "Organization id",
"type": "string", "type": "string",
@@ -4541,9 +4422,30 @@
"filters": { "filters": {
"title": "Filters", "title": "Filters",
"type": "object", "type": "object",
"description": "A dictionary of filters to apply to the search. Users can pass AND, OR, IN, gte, lte, gt, lt, ne, icontains operators for advanced filtering.", "description": "A dictionary of filters to apply to the search. Available fields are: user_id, agent_id, app_id, run_id, created_at, updated_at, categories, keywords. Supports logical operators (AND, OR) and comparison operators (in, gte, lte, gt, lt, ne, contains, icontains).",
"properties": {
"user_id": {"type": "string"},
"agent_id": {"type": "string"},
"app_id": {"type": "string"},
"run_id": {"type": "string"},
"created_at": {"type": "string", "format": "date-time"},
"updated_at": {"type": "string", "format": "date-time"},
"text": {"type": "string"},
"categories": {"type": "array", "items": {"type": "string"}},
"metadata": {"type": "object"}
},
"additionalProperties": { "additionalProperties": {
"type": "object" "type": "object",
"properties": {
"in": {"type": "array"},
"gte": {"type": "string"},
"lte": {"type": "string"},
"gt": {"type": "string"},
"lt": {"type": "string"},
"ne": {"type": "string"},
"contains": {"type": "string"},
"icontains": {"type": "string"}
}
} }
}, },
"top_k": { "top_k": {
@@ -4566,17 +4468,23 @@
"default": false, "default": false,
"description": "Whether to rerank the memories." "description": "Whether to rerank the memories."
}, },
"org_name": { "keyword_search": {
"title": "Organization Name", "title": "Keyword search",
"type": "string", "type": "boolean",
"nullable": true, "default": false,
"description": "The name of the organization associated with the memory. Will be deprecated soon use `org_id` instead." "description": "Whether to search for memories based on keywords."
}, },
"project_name": { "filter_memories": {
"title": "Project Name", "title": "Filter memories",
"type": "string", "type": "boolean",
"nullable": true, "default": false,
"description": "The name of the project associated with the memory. Will be deprecated soon use `project_id` instead." "description": "Whether to filter the memories."
},
"threshold": {
"title": "Threshold",
"type": "number",
"default": 0.3,
"description": "The minimum similarity threshold for returned results."
}, },
"org_id": { "org_id": {
"title": "Organization id", "title": "Organization id",
+29 -45
View File
@@ -1,68 +1,52 @@
--- ---
title: Overview title: Overview
icon: "info"
iconType: "solid"
--- ---
<Note type="info"> <Note type="info">
🎉 Exciting news! [CrewAI](https://crewai.com) now supports Mem0 for memory. 🔔 New Feature: [Webhooks](/features/webhook) are now available! Configure real-time notifications for memory events in your Mem0 project.
</Note> </Note>
[Mem0](https://mem0.dev/wd) (pronounced "mem-zero") enhances AI assistants and agents with an intelligent memory layer, enabling personalized AI interactions. Mem0 remembers user preferences and traits and continuously updates over time, making it ideal for applications like customer support chatbots and AI assistants. # Introduction
[Mem0](https://mem0.dev/wd) (pronounced "mem-zero") enhances AI assistants by giving them persistent, contextual memory. AI systems using Mem0 actively learn from and adapt to user interactions over time.
Mem0's memory layer combines LLMs with vector based storage. LLMs extract and process key information from conversations, while the vector storage enables efficient semantic search and retrieval of memories. This architecture helps AI agents connect past interactions with current context for more relevant responses.
## Key Features
- **Memory Processing**: Uses LLMs to automatically extract and store important information from conversations while maintaining full context
- **Memory Management**: Continuously updates and resolves contradictions in stored information to maintain accuracy
- **Dual Storage Architecture**: Combines vector database for memory storage and graph database for relationship tracking
- **Smart Retrieval System**: Employs semantic search and graph queries to find relevant memories based on importance and recency
- **Simple API Integration**: Provides easy-to-use endpoints for adding (`add`) and retrieving (`search`) memories
## Use Cases
- **Customer Support Chatbots**: Create support agents that remember customer history, preferences, and past interactions to provide personalized assistance
- **Personal AI Tutors**: Build educational assistants that track student progress, adapt to learning patterns, and provide contextual help
- **Healthcare Applications**: Develop healthcare assistants that maintain patient history and provide personalized care recommendations
- **Enterprise Knowledge Management**: Power systems that learn from organizational interactions and maintain institutional knowledge
- **Personalized AI Assistants**: Create assistants that learn user preferences and adapt their responses over time
## Getting Started
Mem0 offers two powerful ways to leverage our technology: our [managed platform](/platform/overview) and our [open source solution](/open-source/quickstart). Mem0 offers two powerful ways to leverage our technology: our [managed platform](/platform/overview) and our [open source solution](/open-source/quickstart).
## Getting Started
<CardGroup cols={3}> <CardGroup cols={3}>
<Card title="Quickstart" icon="rocket" href="/quickstart"> <Card title="Quickstart" icon="rocket" href="/quickstart">
Integrate Mem0 in a few lines of code Integrate Mem0 in a few lines of code
</Card> </Card>
<Card title="Playground" icon="play" href="playground"> <Card title="Playground" icon="play" href="https://app.mem0.ai/playground">
Mem0 in action Mem0 in action
</Card> </Card>
<Card title="Examples" icon="lightbulb" href="/open-source/quickstart"> <Card title="Examples" icon="lightbulb" href="/examples">
See what you can build with Mem0 See what you can build with Mem0
</Card> </Card>
</CardGroup> </CardGroup>
## Key Features
- OpenAI-compatible API: Easily switch between OpenAI and Mem0
- Advanced memory management: Save costs by efficiently handling long-term context
- Flexible deployment: Choose between managed platform or self-hosted solution
<Card title="All Mem0 Features" icon="list" href="/features" horizontal="false">
</Card>
# Memory Classification in mem0
Mem0 uses a sophisticated classification system to determine which parts of text should be extracted as memories. Not all text content will generate memories, as the system is designed to identify specific types of memorable information.
### When Memories Are Not Generated
There are several scenarios where mem0 may return an empty list of memories:
- When users input definitional questions (e.g., "What is backpropagation?")
- For general concept explanations that don't contain personal or experiential information
- Technical definitions and theoretical explanations
- General knowledge statements without personal context
- Abstract or theoretical content
### Example Scenarios
```
Input: "What is machine learning?"
No memories extracted - Content is definitional and does not meet memory classification criteria.
Input: "Yesterday I learned about machine learning in class"
Memory extracted - Contains personal experience and temporal context.
```
### Best Practices
To ensure successful memory extraction:
- Include temporal markers (when events occurred)
- Add personal context or experiences
- Frame information in terms of real-world applications or experiences
- Include specific examples or cases rather than general definitions
## Need help? ## Need help?
If you have any questions, please feel free to reach out to us using one of the following methods:
<Snippet file="get-help.mdx"/> <Snippet file="get-help.mdx"/>
+3 -1
View File
@@ -1,6 +1,8 @@
--- ---
title: Introduction title: Introduction
description: 'Empower your AI applications with long-term memory and personalization' description: 'Empower your AI applications with long-term memory and personalization'
icon: "eye"
iconType: "solid"
--- ---
## Welcome to Mem0 Platform ## Welcome to Mem0 Platform
@@ -27,6 +29,6 @@ Check out our [Platform Guide](/platform/guide) to start using Mem0 platform qui
## Next Steps ## Next Steps
- Sign up to the [Mem0 Platform](https://mem0.dev/pd) - Sign up to the [Mem0 Platform](https://mem0.dev/pd)
- Join our [Discord](https://mem0.dev/Did) or [Slack](https://mem0.ai/slack) with other developers and get support. - Join our [Discord](https://mem0.dev/Did) or [Slack](https://mem0.dev/slack) with other developers and get support.
We're excited to see what you'll build with Mem0 Platform. Let's create smarter, more personalized AI experiences together! We're excited to see what you'll build with Mem0 Platform. Let's create smarter, more personalized AI experiences together!
+178 -61
View File
@@ -1,8 +1,14 @@
--- ---
title: Guide title: Guide
description: 'Get started with Mem0 Platform in minutes' description: 'Get started with Mem0 Platform in minutes'
icon: "book"
iconType: "solid"
--- ---
<Note type="info">
🎉 Looking for TypeScript support? Mem0 has you covered! Check out an example [here](/platform/quickstart/#4-11-working-with-mem0-in-typescript).
</Note>
## 1. Installation ## 1. Installation
<CodeGroup> <CodeGroup>
@@ -27,8 +33,12 @@ npm install mem0ai
<CodeGroup> <CodeGroup>
```python Python ```python Python
import os
from mem0 import MemoryClient from mem0 import MemoryClient
client = MemoryClient(api_key="your-api-key")
os.environ["MEM0_API_KEY"] = "your-api-key"
client = MemoryClient()
``` ```
```javascript JavaScript ```javascript JavaScript
@@ -43,9 +53,12 @@ const client = new MemoryClient({ apiKey: 'your-api-key' });
For asynchronous operations in Python, you can use the AsyncMemoryClient: For asynchronous operations in Python, you can use the AsyncMemoryClient:
```python Python ```python Python
import os
from mem0 import AsyncMemoryClient from mem0 import AsyncMemoryClient
client = AsyncMemoryClient(api_key="your-api-key") os.environ["MEM0_API_KEY"] = "your-api-key"
client = AsyncMemoryClient()
async def main(): async def main():
@@ -154,7 +167,7 @@ curl -X POST "https://api.mem0.ai/v1/memories/" \
</CodeGroup> </CodeGroup>
<Note> The `add` method offers support for two output formats: `v1.0` (default) and `v1.1`. To enable the latest format, which provides enhanced detail for each memory operation, set the `output_format` parameter to `v1.1`. Note that `v1.0` will be deprecated in version `0.1.30`. </Note> <Note> The `add` method offers support for two output formats: `v1.0` (default) and `v1.1`. To enable the latest format, which provides enhanced detail for each memory operation, set the `output_format` parameter to `v1.1`. </Note>
<Note> <Note>
Messages passed along with `user_id`, `run_id`, or `app_id` are stored as user memories, while messages from the assistant are excluded from memory. To store messages for the assistant, use `agent_id` exclusively and avoid including other IDs, such as user_id, alongside it. This ensures the memory is properly attributed to the assistant. Messages passed along with `user_id`, `run_id`, or `app_id` are stored as user memories, while messages from the assistant are excluded from memory. To store messages for the assistant, use `agent_id` exclusively and avoid including other IDs, such as user_id, alongside it. This ensures the memory is properly attributed to the assistant.
@@ -389,18 +402,7 @@ curl -X POST "https://api.mem0.ai/v1/memories/search/" \
{ {
"id": "7f165f7e-b411-4afe-b7e5-35789b72c4a5", "id": "7f165f7e-b411-4afe-b7e5-35789b72c4a5",
"memory": "Vegetarian. Allergic to nuts.", "memory": "Vegetarian. Allergic to nuts.",
"input": [
{
"role": "user",
"content": "Hi, I'm Alex. I'm a vegetarian and I'm allergic to nuts."
},
{
"role": "assistant",
"content": "Hello Alex! I've noted that you're a vegetarian and have a nut allergy. I'll keep this in mind for any food-related recommendations or discussions."
}
],
"user_id": "alex", "user_id": "alex",
"hash": "9ee7e1455e84d1dab700ed8749aed75a",
"metadata": {"food": "vegan"}, "metadata": {"food": "vegan"},
"categories": ["food_preferences"], "categories": ["food_preferences"],
"created_at": "2024-07-20T01:30:36.275141-07:00", "created_at": "2024-07-20T01:30:36.275141-07:00",
@@ -415,18 +417,7 @@ curl -X POST "https://api.mem0.ai/v1/memories/search/" \
{ {
"id": "7f165f7e-b411-4afe-b7e5-35789b72c4a5", "id": "7f165f7e-b411-4afe-b7e5-35789b72c4a5",
"memory": "Vegetarian. Allergic to nuts.", "memory": "Vegetarian. Allergic to nuts.",
"input": [
{
"role": "user",
"content": "Hi, I'm Alex. I'm a vegetarian and I'm allergic to nuts."
},
{
"role": "assistant",
"content": "Hello Alex! I've noted that you're a vegetarian and have a nut allergy. I'll keep this in mind for any food-related recommendations or discussions."
}
],
"user_id": "alex", "user_id": "alex",
"hash": "9ee7e1455e84d1dab700ed8749aed75a",
"metadata": {"food": "vegan"}, "metadata": {"food": "vegan"},
"categories": ["food_preferences"], "categories": ["food_preferences"],
"created_at": "2024-07-20T01:30:36.275141-07:00", "created_at": "2024-07-20T01:30:36.275141-07:00",
@@ -469,18 +460,7 @@ curl -X POST "https://api.mem0.ai/v1/memories/search/?version=v2" \
{ {
"id": "7f165f7e-b411-4afe-b7e5-35789b72c4a5", "id": "7f165f7e-b411-4afe-b7e5-35789b72c4a5",
"memory": "Name: Alex. Vegetarian. Allergic to nuts.", "memory": "Name: Alex. Vegetarian. Allergic to nuts.",
"input": [
{
"role": "user",
"content": "Hi, I'm Alex. I'm a vegetarian and I'm allergic to nuts."
},
{
"role": "assistant",
"content": "Hello Alex! I've noted that you're a vegetarian and have a nut allergy. I'll keep this in mind for any food-related recommendations or discussions."
}
],
"user_id": "alex", "user_id": "alex",
"hash": "9ee7e1455e84d1dab700ed8749aed75a",
"metadata": {"food": "vegan"}, "metadata": {"food": "vegan"},
"categories": ["food_preferences"], "categories": ["food_preferences"],
"created_at": "2024-07-20T01:30:36.275141-07:00", "created_at": "2024-07-20T01:30:36.275141-07:00",
@@ -493,7 +473,7 @@ curl -X POST "https://api.mem0.ai/v1/memories/search/?version=v2" \
#### Search using custom filters #### Search using custom filters
Our advanced search allows you to set custom search filters. You can filter by user_id, agent_id, app_id, date, and more. Our advanced search allows you to set custom search filters. You can filter by user_id, agent_id, app_id, run_id, created_at, updated_at, categories, and text. The filters support logical operators (AND, OR) and comparison operators (in, gte, lte, gt, lt, ne, contains, icontains). For more details, see [V2 Search Memories](/api-reference/memory/v2-search-memories).
Here you need to define `version` as `v2` in the search method. Here you need to define `version` as `v2` in the search method.
@@ -569,18 +549,7 @@ curl -X POST "https://api.mem0.ai/v1/memories/search/?version=v2" \
{ {
"id": "7f165f7e-b411-4afe-b7e5-35789b72c4a5", "id": "7f165f7e-b411-4afe-b7e5-35789b72c4a5",
"memory": "Name: Alex. Vegetarian. Allergic to nuts.", "memory": "Name: Alex. Vegetarian. Allergic to nuts.",
"input": [
{
"role": "user",
"content": "Hi, I'm Alex. I'm a vegetarian and I'm allergic to nuts."
},
{
"role": "assistant",
"content": "Hello Alex! I've noted that you're a vegetarian and have a nut allergy. I'll keep this in mind for any food-related recommendations or discussions."
}
],
"user_id": "alex", "user_id": "alex",
"hash": "9ee7e1455e84d1dab700ed8749aed75a",
"metadata": null, "metadata": null,
"categories": ["food_preferences"], "categories": ["food_preferences"],
"created_at": "2024-07-20T01:30:36.275141-07:00", "created_at": "2024-07-20T01:30:36.275141-07:00",
@@ -644,18 +613,7 @@ curl -X POST "https://api.mem0.ai/v1/memories/search/?version=v2" \
{ {
"id": "7f165f7e-b411-4afe-b7e5-35789b72c4a5", "id": "7f165f7e-b411-4afe-b7e5-35789b72c4a5",
"memory": "Name: Alex. Vegetarian. Allergic to nuts.", "memory": "Name: Alex. Vegetarian. Allergic to nuts.",
"input": [
{
"role": "user",
"content": "Hi, I'm Alex. I'm a vegetarian and I'm allergic to nuts."
},
{
"role": "assistant",
"content": "Hello Alex! I've noted that you're a vegetarian and have a nut allergy. I'll keep this in mind for any food-related recommendations or discussions."
}
],
"user_id": "alex", "user_id": "alex",
"hash": "9ee7e1455e84d1dab700ed8749aed75a",
"metadata": null, "metadata": null,
"categories": ["food_preferences"], "categories": ["food_preferences"],
"created_at": "2024-07-20T01:30:36.275141-07:00", "created_at": "2024-07-20T01:30:36.275141-07:00",
@@ -665,6 +623,80 @@ curl -X POST "https://api.mem0.ai/v1/memories/search/?version=v2" \
``` ```
</CodeGroup> </CodeGroup>
Example 3: Search using metadata and categories Filters
<CodeGroup>
```python Python
query = "What do you know about me?"
filters = {
"AND": [
{"metadata": {"food": "vegan"}},
{
"categories":{
"contains": "food_preferences"
}
}
]
}
client.search(query, version="v2", filters=filters)
```
```javascript JavaScript
const query = "What do you know about me?";
const filters = {
"AND": [
{"metadata": {"food": "vegan"}},
{
"categories": {
"contains": "food_preferences"
}
}
]
};
client.search(query, { version: "v2", filters })
.then(results => console.log(results))
.catch(error => console.error(error));
```
```bash cURL
curl -X POST "https://api.mem0.ai/v1/memories/search/?version=v2" \
-H "Authorization: Token your-api-key" \
-H "Content-Type: application/json" \
-d '{
"query": "What do you know about me?",
"filters": {
"AND": [
{
"metadata": {
"food": "vegan"
}
},
{
"categories": {
"contains": "food_preferences"
}
}
]
}
}'
```
```json Output
[
{
"id": "654fee-b411-4afe-b7e5-35789b72c4a5",
"memory": "Name: Alex. Vegetarian. Allergic to nuts.",
"user_id": "alex",
"metadata": {"food": "vegan"},
"categories": ["food_preferences"],
"created_at": "2024-07-20T01:30:36.275141-07:00",
"updated_at": "2024-07-20T01:30:36.275172-07:00"
}
]
```
</CodeGroup>
### 4.3 Get All Users ### 4.3 Get All Users
@@ -1124,7 +1156,7 @@ curl -X GET "https://api.mem0.ai/v1/memories/?user_id=alex123&keywords=to play&p
#### Get all memories using custom filters #### Get all memories using custom filters
Our advanced retrieval allows you to set custom filters when fetching memories. You can filter by user_id, agent_id, app_id, date, and more. Our advanced retrieval allows you to set custom filters when fetching memories. You can filter by user_id, agent_id, app_id, run_id, created_at, updated_at, categories, and keywords. The filters support logical operators (AND, OR) and comparison operators (in, gte, lte, gt, lt, ne, contains, icontains). For more details, see [V2 Get Memories](/api-reference/memory/v2-get-memories).
Here you need to define `version` as `v2` in the get_all method. Here you need to define `version` as `v2` in the get_all method.
@@ -1460,6 +1492,7 @@ curl -X DELETE "https://api.mem0.ai/v1/memories/?user_id=alex" \
```json Output ```json Output
{'message': 'Memories deleted successfully!'} {'message': 'Memories deleted successfully!'}
``` ```
</CodeGroup> </CodeGroup>
Delete all users. Delete all users.
@@ -1480,6 +1513,33 @@ client.delete_users()
{'message': 'All users, agents, and runs deleted.'} {'message': 'All users, agents, and runs deleted.'}
``` ```
</CodeGroup>
Delete specific user or agent or app or run.
<CodeGroup>
```python Python
# Delete specific user
client.delete_users(user_id="alex")
# Delete specific agent
# client.delete_users(agent_id="travel-assistant")
```
```javascript JavaScript
client.delete_users({ user_id: "alex" })
.then(result => console.log(result))
.catch(error => console.error(error));
```
```bash cURL
curl -X DELETE "https://api.mem0.ai/v1/entities/?user_id=alex" \
-H "Authorization: Token your-api-key"
```
```json Output
{'message': 'Entity deleted successfully.'}
```
</CodeGroup> </CodeGroup>
### 4.8 Reset Client ### 4.8 Reset Client
@@ -1528,7 +1588,18 @@ curl -X POST "https://api.mem0.ai/v1/memories/" \
``` ```
```json Output ```json Output
{'message': 'ok'} [{'id': '3f4eccba-3b09-497a-81ab-cca1ababb36b',
'memory': 'Is allergic to nuts',
'event': 'DELETE'},
{'id': 'f5dcfbf4-5f0b-422a-8ad4-cadb9e941e25',
'memory': 'Is a vegetarian',
'event': 'DELETE'},
{'id': 'dd32f70c-fa69-4fc7-997b-fb4a66d1a0fa',
'memory': 'Name is Alex',
'event': 'DELETE'}]{'message': 'ok'}
{'id': '3f4eccba-3b09-497a-81ab-cca1ababb36b',
'memory': 'Likes Chicken',
'event': 'DELETE'}
``` ```
</CodeGroup> </CodeGroup>
@@ -1630,6 +1701,52 @@ curl -X DELETE "https://api.mem0.ai/v1/memories/batch/" \
``` ```
</CodeGroup> </CodeGroup>
### 4.11 Working with Mem0 in TypeScript
Manage memories using TypeScript with Mem0. Mem0 has completet TypeScript support Below is an example demonstrating how to add and search memories.
<CodeGroup>
```typescript TypeScript
import MemoryClient, { Message, SearchOptions, MemoryOptions } from 'mem0ai';
const apiKey = 'your-api-key-here';
const client = new MemoryClient(apiKey);
// Messages
const messages: Message[] = [
{ role: "user", content: "Hi, I'm Alex. I'm a vegetarian and I'm allergic to nuts." },
{ role: "assistant", content: "Hello Alex! I've noted that you're a vegetarian and have a nut allergy. I'll keep this in mind for any food-related recommendations or discussions." }
];
// ADD
const memoryOptions: MemoryOptions = {
user_id: "alex",
agent_id: "travel-assistant"
}
client.add(messages, memoryOptions)
.then(result => console.log(result))
.catch(error => console.error(error));
// SEARCH
const query: string = "What do you know about me?";
const searchOptions: SearchOptions = {
user_id: "alex",
filters: {
OR: [
{ agent_id: "travel-assistant" },
{ user_id: "alex" }
]
},
threshold: 0.1,
api_version: 'v2'
}
client.search(query, searchOptions)
.then(results => console.log(results))
.catch(error => console.error(error));
```
</CodeGroup>
If you have any questions, please feel free to reach out to us using one of the following methods: If you have any questions, please feel free to reach out to us using one of the following methods:
<Snippet file="get-help.mdx" /> <Snippet file="get-help.mdx" />
-25
View File
@@ -1,25 +0,0 @@
---
title: Interactive Playground
---
Watch Mem0 in action with our Playground tool.
<Steps>
<Step title="Create Mem0 Account">
You'll need to create a free Mem0 account to use the playground – this helps ensure responses are more tailored to you by associating interactions with an individual profile.
<Card title="Sign up to Mem0" icon="right-to-bracket" href="https://mem0.dev/pd" horizontal="true">
</Card>
</Step>
<Step title="Go to Playground">
<Card title="Mem0 Playground" icon="play" href="https://mem0.dev/pd-pg" horizontal="true">
</Card>
</Step>
<Step title="Start adding memories">
Chat with the assistant to start adding memories.
![Add memories to playground](/images/playground/pg-add-memory.png)
</Step>
<Step title="Experience the power of Mem0">
Memories are stored in context for all future conversations, creating truly personal AI.
![Retrieve memories in playground](/images/playground/pg-retrieve-memory.png)
</Step>
</Steps>
+78 -23
View File
@@ -1,10 +1,14 @@
--- ---
title: Quickstart title: Quickstart
icon: "bolt"
iconType: "solid"
--- ---
Mem0 offers two powerful ways to leverage our technology: [our managed platform](#mem0-platform-managed-solution) and [our open source solution](#mem0-open-source). Mem0 offers two powerful ways to leverage our technology: [our managed platform](#mem0-platform-managed-solution) and [our open source solution](#mem0-open-source).
Check out our [Playground](https://mem0.dev/pd-pg) to see Mem0 in action.
<CardGroup cols={2}> <CardGroup cols={2}>
<Card title="Mem0 Platform" icon="chart-simple" href="#mem0-platform-managed-solution"> <Card title="Mem0 Platform (Managed Solution)" icon="chart-simple" href="#mem0-platform-managed-solution">
Better, faster, fully managed, and hassle free solution. Better, faster, fully managed, and hassle free solution.
</Card> </Card>
<Card title="Mem0 Open Source" icon="code-branch" href="#mem0-open-source"> <Card title="Mem0 Open Source" icon="code-branch" href="#mem0-open-source">
@@ -17,6 +21,8 @@ Mem0 offers two powerful ways to leverage our technology: [our managed platform]
Our fully managed platform provides a hassle-free way to integrate Mem0's capabilities into your AI agents and assistants. Sign up for Mem0 platform [here](https://mem0.dev/pd). Our fully managed platform provides a hassle-free way to integrate Mem0's capabilities into your AI agents and assistants. Sign up for Mem0 platform [here](https://mem0.dev/pd).
The Mem0 SDK supports both Python and JavaScript, with full [TypeScript](/platform/quickstart/#4-11-working-with-mem0-in-typescript) support as well.
Follow the steps below to get started with Mem0 Platform: Follow the steps below to get started with Mem0 Platform:
1. [Install Mem0](#1-install-mem0) 1. [Install Mem0](#1-install-mem0)
@@ -53,8 +59,12 @@ npm install mem0ai
<Accordion title="Instantiate client"> <Accordion title="Instantiate client">
<CodeGroup> <CodeGroup>
```python Python ```python Python
import os
from mem0 import MemoryClient from mem0 import MemoryClient
client = MemoryClient(api_key="your-api-key")
os.environ["MEM0_API_KEY"] = "your-api-key"
client = MemoryClient()
``` ```
```javascript JavaScript ```javascript JavaScript
@@ -98,7 +108,15 @@ curl -X POST "https://api.mem0.ai/v1/memories/" \
``` ```
```json Output ```json Output
{'message': 'ok'} [{'id': '24e466b5-e1c6-4bde-8a92-f09a327ffa60',
'memory': 'Name is Alex',
'event': 'ADD'},
{'id': 'f2d874ac-09c7-49db-b34a-22cf666bd4ad',
'memory': 'Is a vegetarian',
'event': 'ADD'},
{'id': 'bce04006-01e8-4dbc-8a22-67fa46f1822c',
'memory': 'Is allergic to nuts',
'event': 'ADD'}]
``` ```
</CodeGroup> </CodeGroup>
</Accordion> </Accordion>
@@ -112,23 +130,43 @@ curl -X POST "https://api.mem0.ai/v1/memories/" \
```python Python ```python Python
query = "What can I cook for dinner tonight?" query = "What can I cook for dinner tonight?"
client.search(query, user_id="alex") filters = {
"AND": [
{
"user_id": "alex"
}
]
}
client.search(query, version="v2", filters=filters)
``` ```
```javascript JavaScript ```javascript JavaScript
const query = "What can I cook for dinner tonight?"; const query = "What can I cook for dinner tonight?";
client.search(query, { user_id: "alex" }) const filters = {
"AND": [
{
"user_id": "alex"
}
]
};
client.search(query, { version: "v2", filters })
.then(results => console.log(results)) .then(results => console.log(results))
.catch(error => console.error(error)); .catch(error => console.error(error));
``` ```
```bash cURL ```bash cURL
curl -X POST "https://api.mem0.ai/v1/memories/search/" \ curl -X POST "https://api.mem0.ai/v1/memories/search/?version=v2" \
-H "Authorization: Token your-api-key" \ -H "Authorization: Token your-api-key" \
-H "Content-Type: application/json" \ -H "Content-Type: application/json" \
-d '{ -d '{
"query": "What can I cook for dinner tonight?", "query": "What can I cook for dinner tonight?",
"user_id": "alex" "filters": {
"AND": [
{
"user_id": "alex"
}
]
}
}' }'
``` ```
@@ -137,18 +175,7 @@ curl -X POST "https://api.mem0.ai/v1/memories/search/" \
{ {
"id": "7f165f7e-b411-4afe-b7e5-35789b72c4a5", "id": "7f165f7e-b411-4afe-b7e5-35789b72c4a5",
"memory": "Name: Alex. Vegetarian. Allergic to nuts.", "memory": "Name: Alex. Vegetarian. Allergic to nuts.",
"input": [
{
"role": "user",
"content": "Hi, I'm Alex. I'm a vegetarian and I'm allergic to nuts."
},
{
"role": "assistant",
"content": "Hello Alex! I've noted that you're a vegetarian and have a nut allergy. I'll keep this in mind for any food-related recommendations or discussions."
}
],
"user_id": "alex", "user_id": "alex",
"hash": "9ee7e1455e84d1dab700ed8749aed75a",
"metadata": null, "metadata": null,
"created_at": "2024-07-20T01:30:36.275141-07:00", "created_at": "2024-07-20T01:30:36.275141-07:00",
"updated_at": "2024-07-20T01:30:36.275172-07:00" "updated_at": "2024-07-20T01:30:36.275172-07:00"
@@ -163,18 +190,44 @@ curl -X POST "https://api.mem0.ai/v1/memories/search/" \
<CodeGroup> <CodeGroup>
```python Python ```python Python
user_memories = client.get_all(user_id="alex") filters = {
"AND": [
{
"user_id": "alice"
}
]
}
all_memories = client.get_all(version="v2", filters=filters, page=1, page_size=50)
``` ```
```javascript JavaScript ```javascript JavaScript
client.getAll({ user_id: "alex" }) const filters = {
"AND": [
{
"user_id": "alice"
}
]
};
client.getAll({ version: "v2", filters, page: 1, page_size: 50 })
.then(memories => console.log(memories)) .then(memories => console.log(memories))
.catch(error => console.error(error)); .catch(error => console.error(error));
``` ```
```bash cURL ```bash cURL
curl -X GET "https://api.mem0.ai/v1/memories/?user_id=alex" \ curl -X GET "https://api.mem0.ai/v1/memories/?version=v2&page=1&page_size=50" \
-H "Authorization: Token your-api-key" -H "Authorization: Token your-api-key" \
-H "Content-Type: application/json" \
-d '{
"filters": {
"AND": [
{
"user_id": "alice"
}
]
}
}'
``` ```
```json Output ```json Output
@@ -244,7 +297,9 @@ result = m.add("I like to take long walks on weekends.", user_id="alice", metada
``` ```
```json Output ```json Output
{'message': 'ok'} [{'id': 'ea9b08ee-09d7-4e8b-9912-687ad65548b4',
'memory': 'Likes to take long walks on weekends',
'event': 'ADD'}]
``` ```
</CodeGroup> </CodeGroup>
</Accordion> </Accordion>
+1 -1
View File
@@ -2,7 +2,7 @@
title: 'Full Stack' title: 'Full Stack'
--- ---
The Full Stack app example can be found [here](https://github.com/embedchain/embedchain/tree/main/examples/full_stack). The Full Stack app example can be found [here](https://github.com/mem0ai/mem0/tree/main/embedchain/examples/full_stack).
This guide will help you setup the full stack app on your local machine. This guide will help you setup the full stack app on your local machine.
@@ -12,9 +12,9 @@
}, },
"aliases": { "aliases": {
"components": "@/components", "components": "@/components",
"utils": "@/lib/utils", "utils": "@/libs/utils",
"ui": "@/components/ui", "ui": "@/components/ui",
"lib": "@/lib", "lib": "@/libs",
"hooks": "@/hooks" "hooks": "@/hooks"
} }
} }
@@ -3,12 +3,12 @@ import { Card } from "@/components/ui/card";
import { ScrollArea } from "@radix-ui/react-scroll-area"; import { ScrollArea } from "@radix-ui/react-scroll-area";
import { Memory } from "../types"; import { Memory } from "../types";
import GlobalContext from "@/contexts/GlobalContext"; import GlobalContext from "@/contexts/GlobalContext";
import { useContext, useEffect, useState } from "react"; import { useContext } from "react";
import { AnimatePresence, motion } from "framer-motion"; import { motion } from "framer-motion";
// eslint-disable-next-line @typescript-eslint/no-unused-vars // eslint-disable-next-line @typescript-eslint/no-unused-vars
const MemoryItem = ({ memory, index }: { memory: Memory; index: number }) => { const MemoryItem = ({ memory }: { memory: Memory; index: number }) => {
return ( return (
<motion.div <motion.div
layout layout
@@ -39,14 +39,6 @@ const MemoryItem = ({ memory, index }: { memory: Memory; index: number }) => {
const Memories = (props: { isMemoriesExpanded: boolean }) => { const Memories = (props: { isMemoriesExpanded: boolean }) => {
const { isMemoriesExpanded } = props; const { isMemoriesExpanded } = props;
const { memories } = useContext(GlobalContext); const { memories } = useContext(GlobalContext);
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const [prevMemories, setPrevMemories] = useState<Memory[]>([]);
// Track memory positions for animation
useEffect(() => {
setPrevMemories(memories);
}, [memories]);
return ( return (
<Card <Card
@@ -73,9 +65,8 @@ const Memories = (props: { isMemoriesExpanded: boolean }) => {
<ScrollArea className="flex-1 p-4"> <ScrollArea className="flex-1 p-4">
<motion.div <motion.div
className="space-y-4" className="space-y-4"
layout
> >
<AnimatePresence mode="popLayout"> {/* <AnimatePresence mode="popLayout"> */}
{memories.map((memory: Memory, index: number) => ( {memories.map((memory: Memory, index: number) => (
<MemoryItem <MemoryItem
key={memory.id} key={memory.id}
@@ -83,7 +74,7 @@ const Memories = (props: { isMemoriesExpanded: boolean }) => {
index={index} index={index}
/> />
))} ))}
</AnimatePresence> {/* </AnimatePresence> */}
</motion.div> </motion.div>
</ScrollArea> </ScrollArea>
</Card> </Card>
@@ -3,7 +3,7 @@
import * as React from "react" import * as React from "react"
import * as AvatarPrimitive from "@radix-ui/react-avatar" import * as AvatarPrimitive from "@radix-ui/react-avatar"
import { cn } from "@/lib/utils" import { cn } from "@/libs/utils"
const Avatar = React.forwardRef< const Avatar = React.forwardRef<
React.ElementRef<typeof AvatarPrimitive.Root>, React.ElementRef<typeof AvatarPrimitive.Root>,
@@ -1,7 +1,7 @@
import * as React from "react" import * as React from "react"
import { cva, type VariantProps } from "class-variance-authority" import { cva, type VariantProps } from "class-variance-authority"
import { cn } from "@/lib/utils" import { cn } from "@/libs/utils"
const badgeVariants = cva( const badgeVariants = cva(
"inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2", "inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
@@ -2,7 +2,7 @@ import * as React from "react"
import { Slot } from "@radix-ui/react-slot" import { Slot } from "@radix-ui/react-slot"
import { cva, type VariantProps } from "class-variance-authority" import { cva, type VariantProps } from "class-variance-authority"
import { cn } from "@/lib/utils" import { cn } from "@/libs/utils"
const buttonVariants = cva( const buttonVariants = cva(
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
@@ -1,6 +1,6 @@
import * as React from "react" import * as React from "react"
import { cn } from "@/lib/utils" import { cn } from "@/libs/utils"
const Card = React.forwardRef< const Card = React.forwardRef<
HTMLDivElement, HTMLDivElement,
@@ -2,7 +2,7 @@ import * as React from "react"
import * as DialogPrimitive from "@radix-ui/react-dialog" import * as DialogPrimitive from "@radix-ui/react-dialog"
import { Cross2Icon } from "@radix-ui/react-icons" import { Cross2Icon } from "@radix-ui/react-icons"
import { cn } from "@/lib/utils" import { cn } from "@/libs/utils"
const Dialog = DialogPrimitive.Root const Dialog = DialogPrimitive.Root
@@ -1,6 +1,6 @@
import * as React from "react" import * as React from "react"
import { cn } from "@/lib/utils" import { cn } from "@/libs/utils"
export interface InputProps export interface InputProps
extends React.InputHTMLAttributes<HTMLInputElement> {} extends React.InputHTMLAttributes<HTMLInputElement> {}
@@ -2,7 +2,7 @@ import * as React from "react"
import * as LabelPrimitive from "@radix-ui/react-label" import * as LabelPrimitive from "@radix-ui/react-label"
import { cva, type VariantProps } from "class-variance-authority" import { cva, type VariantProps } from "class-variance-authority"
import { cn } from "@/lib/utils" import { cn } from "@/libs/utils"
const labelVariants = cva( const labelVariants = cva(
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70" "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
@@ -1,7 +1,7 @@
import * as React from "react" import * as React from "react"
import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area" import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area"
import { cn } from "@/lib/utils" import { cn } from "@/libs/utils"
const ScrollArea = React.forwardRef< const ScrollArea = React.forwardRef<
React.ElementRef<typeof ScrollAreaPrimitive.Root>, React.ElementRef<typeof ScrollAreaPrimitive.Root>,
@@ -9,7 +9,7 @@ import {
} from "@radix-ui/react-icons" } from "@radix-ui/react-icons"
import * as SelectPrimitive from "@radix-ui/react-select" import * as SelectPrimitive from "@radix-ui/react-select"
import { cn } from "@/lib/utils" import { cn } from "@/libs/utils"
const Select = SelectPrimitive.Root const Select = SelectPrimitive.Root
@@ -119,7 +119,7 @@ const GlobalState = (props: any) => {
try { try {
const smemories = await searchMemories(messages, { const smemories = await searchMemories(messages, {
user_id: selectedUser || "", user_id: selectedUser || "",
mem0ApiKey: import.meta.env.VITE_MEM0_API_KEY, mem0ApiKey: selectedMem0Key,
}); });
const newMemories = smemories.map((memory: any) => ({ const newMemories = smemories.map((memory: any) => ({
@@ -0,0 +1,6 @@
import { clsx, type ClassValue } from "clsx"
import { twMerge } from "tailwind-merge"
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}
+310 -75
View File
@@ -14,6 +14,8 @@ logger = logging.getLogger(__name__)
# Setup user config # Setup user config
setup_config() setup_config()
warnings.filterwarnings("default", category=DeprecationWarning)
class APIError(Exception): class APIError(Exception):
"""Exception raised for errors in the API.""" """Exception raised for errors in the API."""
@@ -48,8 +50,6 @@ class MemoryClient:
api_key (str): The API key for authenticating with the Mem0 API. api_key (str): The API key for authenticating with the Mem0 API.
host (str): The base URL for the Mem0 API. host (str): The base URL for the Mem0 API.
client (httpx.Client): The HTTP client used for making API requests. client (httpx.Client): The HTTP client used for making API requests.
organization (str, optional): (Deprecated) Organization name.
project (str, optional): (Deprecated) Project name.
org_id (str, optional): Organization ID. org_id (str, optional): Organization ID.
project_id (str, optional): Project ID. project_id (str, optional): Project ID.
user_id (str): Unique identifier for the user. user_id (str): Unique identifier for the user.
@@ -59,8 +59,6 @@ class MemoryClient:
self, self,
api_key: Optional[str] = None, api_key: Optional[str] = None,
host: Optional[str] = None, host: Optional[str] = None,
organization: Optional[str] = None,
project: Optional[str] = None,
org_id: Optional[str] = None, org_id: Optional[str] = None,
project_id: Optional[str] = None, project_id: Optional[str] = None,
): ):
@@ -70,8 +68,6 @@ class MemoryClient:
api_key: The API key for authenticating with the Mem0 API. If not provided, api_key: The API key for authenticating with the Mem0 API. If not provided,
it will attempt to use the MEM0_API_KEY environment variable. it will attempt to use the MEM0_API_KEY environment variable.
host: The base URL for the Mem0 API. Defaults to "https://api.mem0.ai". host: The base URL for the Mem0 API. Defaults to "https://api.mem0.ai".
organization: (Deprecated) The name of the organization. Use org_id instead.
project: (Deprecated) The name of the project. Use project_id instead.
org_id: The ID of the organization. org_id: The ID of the organization.
project_id: The ID of the project. project_id: The ID of the project.
@@ -80,8 +76,6 @@ class MemoryClient:
""" """
self.api_key = api_key or os.getenv("MEM0_API_KEY") self.api_key = api_key or os.getenv("MEM0_API_KEY")
self.host = host or "https://api.mem0.ai" self.host = host or "https://api.mem0.ai"
self.organization = organization
self.project = project
self.org_id = org_id self.org_id = org_id
self.project_id = project_id self.project_id = project_id
self.user_id = get_user_id() self.user_id = get_user_id()
@@ -89,18 +83,10 @@ class MemoryClient:
if not self.api_key: if not self.api_key:
raise ValueError("Mem0 API Key not provided. Please provide an API Key.") raise ValueError("Mem0 API Key not provided. Please provide an API Key.")
if organization or project:
warnings.warn(
"Using 'organization' and 'project' parameters is deprecated and will be removed in version 0.1.40. "
"Please use 'org_id' and 'project_id' instead.",
DeprecationWarning,
stacklevel=2,
)
self.client = httpx.Client( self.client = httpx.Client(
base_url=self.host, base_url=self.host,
headers={"Authorization": f"Token {self.api_key}", "Mem0-User-ID": self.user_id}, headers={"Authorization": f"Token {self.api_key}", "Mem0-User-ID": self.user_id},
timeout=60, timeout=300,
) )
self._validate_api_key() self._validate_api_key()
capture_client_event("client.init", self) capture_client_event("client.init", self)
@@ -110,9 +96,21 @@ class MemoryClient:
try: try:
params = self._prepare_params() params = self._prepare_params()
response = self.client.get("/v1/ping/", params=params) response = self.client.get("/v1/ping/", params=params)
data = response.json()
response.raise_for_status() response.raise_for_status()
except httpx.HTTPStatusError:
raise ValueError("Invalid API Key. Please get a valid API Key from https://app.mem0.ai") if data.get("org_id") and data.get("project_id"):
self.org_id = data.get("org_id")
self.project_id = data.get("project_id")
except httpx.HTTPStatusError as e:
try:
error_data = e.response.json()
error_message = error_data.get("detail", str(e))
except:
error_message = str(e)
raise ValueError(f"Error: {error_message}")
@api_error_handler @api_error_handler
def add(self, messages: Union[str, List[Dict[str, str]]], **kwargs) -> Dict[str, Any]: def add(self, messages: Union[str, List[Dict[str, str]]], **kwargs) -> Dict[str, Any]:
@@ -129,6 +127,14 @@ class MemoryClient:
APIError: If the API request fails. APIError: If the API request fails.
""" """
kwargs = self._prepare_params(kwargs) kwargs = self._prepare_params(kwargs)
if kwargs.get("output_format") != "v1.1":
warnings.warn(
"Using default output format 'v1.0' is deprecated and will be removed in version 0.1.70. "
"Please use output_format='v1.1' for enhanced memory details. "
"Check out the docs for more information: https://docs.mem0.ai/platform/quickstart#4-1-create-memories",
DeprecationWarning,
stacklevel=2,
)
payload = self._prepare_payload(messages, kwargs) payload = self._prepare_payload(messages, kwargs)
response = self.client.post("/v1/memories/", json=payload) response = self.client.post("/v1/memories/", json=payload)
response.raise_for_status() response.raise_for_status()
@@ -162,7 +168,7 @@ class MemoryClient:
Args: Args:
version: The API version to use for the search endpoint. version: The API version to use for the search endpoint.
**kwargs: Optional parameters for filtering (user_id, agent_id, app_id, limit). **kwargs: Optional parameters for filtering (user_id, agent_id, app_id, top_k).
Returns: Returns:
A list of dictionaries containing memories. A list of dictionaries containing memories.
@@ -196,7 +202,7 @@ class MemoryClient:
Args: Args:
query: The search query string. query: The search query string.
version: The API version to use for the search endpoint. version: The API version to use for the search endpoint.
**kwargs: Additional parameters such as user_id, agent_id, app_id, limit, filters. **kwargs: Additional parameters such as user_id, agent_id, app_id, top_k, filters.
Returns: Returns:
A list of dictionaries containing search results. A list of dictionaries containing search results.
@@ -297,16 +303,61 @@ class MemoryClient:
return response.json() return response.json()
@api_error_handler @api_error_handler
def delete_users(self) -> Dict[str, str]: def delete_users(
"""Delete all users, agents, or sessions.""" self,
user_id: Optional[str] = None,
agent_id: Optional[str] = None,
app_id: Optional[str] = None,
run_id: Optional[str] = None,
) -> Dict[str, str]:
"""Delete specific entities or all entities if no filters provided.
Args:
user_id: Optional user ID to delete specific user
agent_id: Optional agent ID to delete specific agent
app_id: Optional app ID to delete specific app
run_id: Optional run ID to delete specific run
Returns:
Dict with success message
Raises:
ValueError: If specified entity not found
APIError: If deletion fails
"""
params = self._prepare_params() params = self._prepare_params()
entities = self.users() entities = self.users()
for entity in entities["results"]:
# Filter entities based on provided IDs using list comprehension
to_delete = [
entity
for entity in entities["results"]
if (user_id and entity["type"] == "user" and entity["name"] == user_id)
or (agent_id and entity["type"] == "agent" and entity["name"] == agent_id)
or (app_id and entity["type"] == "app" and entity["name"] == app_id)
or (run_id and entity["type"] == "run" and entity["name"] == run_id)
]
# If filters provided but no matches found, raise error
if not to_delete and (user_id or agent_id or app_id or run_id):
raise ValueError("No entity found with the provided ID.")
# If no filters provided, delete all entities
elif not to_delete:
to_delete = entities["results"]
# Delete entities and check response immediately
for entity in to_delete:
response = self.client.delete(f"/v1/entities/{entity['type']}/{entity['id']}/", params=params) response = self.client.delete(f"/v1/entities/{entity['type']}/{entity['id']}/", params=params)
response.raise_for_status() response.raise_for_status()
capture_client_event("client.delete_users", self) capture_client_event(
return {"message": "All users, agents, and sessions deleted."} "client.delete_users", self, {"user_id": user_id, "agent_id": agent_id, "app_id": app_id, "run_id": run_id}
)
return {
"message": "Entity deleted successfully."
if (user_id or agent_id or app_id or run_id)
else "All users, agents, apps and runs deleted."
}
@api_error_handler @api_error_handler
def reset(self) -> Dict[str, str]: def reset(self) -> Dict[str, str]:
@@ -400,14 +451,14 @@ class MemoryClient:
return response.json() return response.json()
@api_error_handler @api_error_handler
def get_custom_instructions_and_categories(self, fields: List[str]) -> Dict[str, Any]: def get_project(self, fields: Optional[List[str]] = None) -> Dict[str, Any]:
"""Get instructions or categories for the current project. """Get instructions or categories for the current project.
Args: Args:
fields: List of field names to retrieve (e.g. ['custom_instructions', 'custom_categories']) fields: List of fields to retrieve
Returns: Returns:
Dictionary containing the requested instructions or categories. Dictionary containing the requested fields.
Raises: Raises:
APIError: If the API request fails. APIError: If the API request fails.
@@ -418,20 +469,22 @@ class MemoryClient:
params = self._prepare_params({"fields": fields}) params = self._prepare_params({"fields": fields})
response = self.client.get( response = self.client.get(
f"/api/v1/orgs/organizations/{self.org_id}/projects/{self.project_id}/custom-instructions-and-categories/", f"/api/v1/orgs/organizations/{self.org_id}/projects/{self.project_id}/",
params=params, params=params,
) )
response.raise_for_status() response.raise_for_status()
capture_client_event("client.get_custom_instructions_and_categories", self, {"fields": fields}) capture_client_event("client.get_project_details", self, {"fields": fields})
return response.json() return response.json()
@api_error_handler @api_error_handler
def update_custom_instructions_and_categories(self, fields: Dict[str, Any]) -> Dict[str, Any]: def update_project(
"""Update instructions or categories for the current project. self, custom_instructions: Optional[str] = None, custom_categories: Optional[List[str]] = None
) -> Dict[str, Any]:
"""Update the project settings.
Args: Args:
fields: Dictionary of fields to update custom_instructions: New instructions for the project
(e.g. {"custom_categories": "new instructions", "custom_categories": ["cat1"]}) custom_categories: New categories for the project
Returns: Returns:
Dictionary containing the API response. Dictionary containing the API response.
@@ -443,12 +496,24 @@ class MemoryClient:
if not (self.org_id and self.project_id): if not (self.org_id and self.project_id):
raise ValueError("org_id and project_id must be set to update instructions or categories") raise ValueError("org_id and project_id must be set to update instructions or categories")
response = self.client.post( if custom_instructions is None and custom_categories is None:
f"/api/v1/orgs/organizations/{self.org_id}/projects/{self.project_id}/custom-instructions-and-categories/", raise ValueError(
json=fields, "Currently we only support updating custom_instructions or custom_categories, so you must provide at least one of them"
)
payload = self._prepare_params(
{"custom_instructions": custom_instructions, "custom_categories": custom_categories}
)
response = self.client.patch(
f"/api/v1/orgs/organizations/{self.org_id}/projects/{self.project_id}/",
json=payload,
) )
response.raise_for_status() response.raise_for_status()
capture_client_event("client.update_custom_instructions_and_categories", self, {"fields": list(fields.keys())}) capture_client_event(
"client.update_project",
self,
{"custom_instructions": custom_instructions, "custom_categories": custom_categories},
)
return response.json() return response.json()
def chat(self): def chat(self):
@@ -459,6 +524,97 @@ class MemoryClient:
""" """
raise NotImplementedError("Chat is not implemented yet") raise NotImplementedError("Chat is not implemented yet")
@api_error_handler
def get_webhooks(self, project_id: str) -> Dict[str, Any]:
"""Get webhooks configuration for the project.
Args:
project_id: The ID of the project to get webhooks for.
Returns:
Dictionary containing webhook details.
Raises:
APIError: If the API request fails.
ValueError: If project_id is not set.
"""
response = self.client.get(f"api/v1/webhooks/{project_id}/webhook/")
response.raise_for_status()
capture_client_event("client.get_webhook", self)
return response.json()
@api_error_handler
def create_webhook(self, url: str, name: str, project_id: str, event_types: List[str]) -> Dict[str, Any]:
"""Create a webhook for the current project.
Args:
url: The URL to send the webhook to.
name: The name of the webhook.
event_types: List of event types to trigger the webhook for.
Returns:
Dictionary containing the created webhook details.
Raises:
APIError: If the API request fails.
ValueError: If project_id is not set.
"""
payload = {"url": url, "name": name, "event_types": event_types}
response = self.client.post(f"api/v1/webhooks/{project_id}/webhook/", json=payload)
response.raise_for_status()
capture_client_event("client.create_webhook", self)
return response.json()
@api_error_handler
def update_webhook(
self, webhook_id: int, project_id: str, name: Optional[str] = None, url: Optional[str] = None, event_types: Optional[List[str]] = None
) -> Dict[str, Any]:
"""Update a webhook configuration.
Args:
webhook_id: ID of the webhook to update
project_id: The ID of the project to update the webhook for.
name: Optional new name for the webhook
url: Optional new URL for the webhook
event_types: Optional list of event types to trigger the webhook for.
Returns:
Dictionary containing the updated webhook details.
Raises:
APIError: If the API request fails.
ValueError: If project_id is not set.
"""
payload = {k: v for k, v in {"name": name, "url": url, "event_types": event_types}.items() if v is not None}
response = self.client.put(f"api/v1/webhooks/{project_id}/webhook/{webhook_id}/", json=payload)
response.raise_for_status()
capture_client_event("client.update_webhook", self, {"webhook_id": webhook_id})
return response.json()
@api_error_handler
def delete_webhook(self, webhook_id: int, project_id: str) -> Dict[str, str]:
"""Delete a webhook configuration.
Args:
webhook_id: ID of the webhook to delete
project_id: The ID of the project to delete the webhook for.
Returns:
Dictionary containing success message.
Raises:
APIError: If the API request fails.
ValueError: If project_id is not set.
"""
response = self.client.delete(f"api/v1/webhooks/{project_id}/webhook/{webhook_id}/")
response.raise_for_status()
capture_client_event("client.delete_webhook", self, {"webhook_id": webhook_id})
return response.json()
def _prepare_payload( def _prepare_payload(
self, messages: Union[str, List[Dict[str, str]], None], kwargs: Dict[str, Any] self, messages: Union[str, List[Dict[str, str]], None], kwargs: Dict[str, Any]
) -> Dict[str, Any]: ) -> Dict[str, Any]:
@@ -490,32 +646,18 @@ class MemoryClient:
A dictionary containing the prepared parameters. A dictionary containing the prepared parameters.
Raises: Raises:
ValueError: If both org_id/project_id and org_name/project_name are provided. ValueError: If either org_id or project_id is provided but not both.
""" """
if kwargs is None: if kwargs is None:
kwargs = {} kwargs = {}
has_new = bool(self.org_id or self.project_id) # Add org_id and project_id if both are available
has_old = bool(self.organization or self.project) if self.org_id and self.project_id:
if has_new and has_old:
raise ValueError(
"Please use either org_id/project_id or org_name/project_name, not both. "
"Note that org_name/project_name are deprecated."
)
# Add org_id and project_id if available
if self.org_id:
kwargs["org_id"] = self.org_id kwargs["org_id"] = self.org_id
if self.project_id:
kwargs["project_id"] = self.project_id kwargs["project_id"] = self.project_id
elif self.org_id or self.project_id:
# Add deprecated org_name and project_name for backward compatibility raise ValueError("Please provide both org_id and project_id")
if self.organization:
kwargs["org_name"] = self.organization
if self.project:
kwargs["project_name"] = self.project
return {k: v for k, v in kwargs.items() if v is not None} return {k: v for k, v in kwargs.items() if v is not None}
@@ -535,16 +677,14 @@ class AsyncMemoryClient:
self, self,
api_key: Optional[str] = None, api_key: Optional[str] = None,
host: Optional[str] = None, host: Optional[str] = None,
organization: Optional[str] = None,
project: Optional[str] = None,
org_id: Optional[str] = None, org_id: Optional[str] = None,
project_id: Optional[str] = None, project_id: Optional[str] = None,
): ):
self.sync_client = MemoryClient(api_key, host, organization, project, org_id, project_id) self.sync_client = MemoryClient(api_key, host, org_id, project_id)
self.async_client = httpx.AsyncClient( self.async_client = httpx.AsyncClient(
base_url=self.sync_client.host, base_url=self.sync_client.host,
headers=self.sync_client.client.headers, headers=self.sync_client.client.headers,
timeout=60, timeout=300,
) )
async def __aenter__(self): async def __aenter__(self):
@@ -641,14 +781,59 @@ class AsyncMemoryClient:
return response.json() return response.json()
@api_error_handler @api_error_handler
async def delete_users(self) -> Dict[str, str]: async def delete_users(
self,
user_id: Optional[str] = None,
agent_id: Optional[str] = None,
app_id: Optional[str] = None,
run_id: Optional[str] = None,
) -> Dict[str, str]:
"""Delete specific entities or all entities if no filters provided.
Args:
user_id: Optional user ID to delete specific user
agent_id: Optional agent ID to delete specific agent
app_id: Optional app ID to delete specific app
run_id: Optional run ID to delete specific run
Returns:
Dict with success message
Raises:
ValueError: If specified entity not found
APIError: If deletion fails
"""
params = self.sync_client._prepare_params() params = self.sync_client._prepare_params()
entities = await self.users() entities = await self.users()
for entity in entities["results"]:
# Filter entities based on provided IDs using list comprehension
to_delete = [
entity
for entity in entities["results"]
if (user_id and entity["type"] == "user" and entity["name"] == user_id)
or (agent_id and entity["type"] == "agent" and entity["name"] == agent_id)
or (app_id and entity["type"] == "app" and entity["name"] == app_id)
or (run_id and entity["type"] == "run" and entity["name"] == run_id)
]
# If filters provided but no matches found, raise error
if not to_delete and (user_id or agent_id or app_id or run_id):
raise ValueError("No entity found with the provided ID.")
# If no filters provided, delete all entities
elif not to_delete:
to_delete = entities["results"]
# Delete entities and check response immediately
for entity in to_delete:
response = await self.async_client.delete(f"/v1/entities/{entity['type']}/{entity['id']}/", params=params) response = await self.async_client.delete(f"/v1/entities/{entity['type']}/{entity['id']}/", params=params)
response.raise_for_status() response.raise_for_status()
capture_client_event("async_client.delete_users", self.sync_client) capture_client_event("async_client.delete_users", self.sync_client)
return {"message": "All users, agents, and sessions deleted."} return {
"message": "Entity deleted successfully."
if (user_id or agent_id or app_id or run_id)
else "All users, agents, apps and runs deleted."
}
@api_error_handler @api_error_handler
async def reset(self) -> Dict[str, str]: async def reset(self) -> Dict[str, str]:
@@ -731,35 +916,85 @@ class AsyncMemoryClient:
return response.json() return response.json()
@api_error_handler @api_error_handler
async def get_custom_instructions_and_categories(self, fields: List[str]) -> Dict[str, Any]: async def get_project(self, fields: Optional[List[str]] = None) -> Dict[str, Any]:
if not (self.sync_client.org_id and self.sync_client.project_id): if not (self.sync_client.org_id and self.sync_client.project_id):
raise ValueError("org_id and project_id must be set to access instructions or categories") raise ValueError("org_id and project_id must be set to access instructions or categories")
params = self.sync_client._prepare_params({"fields": fields}) params = self.sync_client._prepare_params({"fields": fields})
response = await self.async_client.get( response = await self.async_client.get(
f"/api/v1/orgs/organizations/{self.sync_client.org_id}/projects/{self.sync_client.project_id}/custom-instructions-and-categories/", f"/api/v1/orgs/organizations/{self.sync_client.org_id}/projects/{self.sync_client.project_id}/",
params=params, params=params,
) )
response.raise_for_status() response.raise_for_status()
capture_client_event( capture_client_event("async_client.get_project", self.sync_client, {"fields": fields})
"async_client.get_custom_instructions_and_categories", self.sync_client, {"fields": fields}
)
return response.json() return response.json()
@api_error_handler @api_error_handler
async def update_custom_instructions_and_categories(self, fields: Dict[str, Any]) -> Dict[str, Any]: async def update_project(
self, custom_instructions: Optional[str] = None, custom_categories: Optional[List[str]] = None
) -> Dict[str, Any]:
if not (self.sync_client.org_id and self.sync_client.project_id): if not (self.sync_client.org_id and self.sync_client.project_id):
raise ValueError("org_id and project_id must be set to update instructions or categories") raise ValueError("org_id and project_id must be set to update instructions or categories")
response = await self.async_client.post( if custom_instructions is None and custom_categories is None:
f"/api/v1/orgs/organizations/{self.sync_client.org_id}/projects/{self.sync_client.project_id}/custom-instructions-and-categories/", raise ValueError(
json=fields, "Currently we only support updating custom_instructions or custom_categories, so you must provide at least one of them"
)
payload = self.sync_client._prepare_params(
{"custom_instructions": custom_instructions, "custom_categories": custom_categories}
)
response = await self.async_client.patch(
f"/api/v1/orgs/organizations/{self.sync_client.org_id}/projects/{self.sync_client.project_id}/",
json=payload,
) )
response.raise_for_status() response.raise_for_status()
capture_client_event( capture_client_event(
"async_client.update_custom_instructions_and_categories", self.sync_client, {"fields": list(fields.keys())} "async_client.update_project",
self.sync_client,
{"custom_instructions": custom_instructions, "custom_categories": custom_categories},
) )
return response.json() return response.json()
async def chat(self): async def chat(self):
raise NotImplementedError("Chat is not implemented yet") raise NotImplementedError("Chat is not implemented yet")
@api_error_handler
async def get_webhooks(self, project_id: str) -> Dict[str, Any]:
response = await self.async_client.get(
f"api/v1/webhooks/{project_id}/webhook/",
)
response.raise_for_status()
capture_client_event("async_client.get_webhook", self.sync_client)
return response.json()
@api_error_handler
async def create_webhook(self, url: str, name: str, project_id: str, event_types: List[str]) -> Dict[str, Any]:
payload = {"url": url, "name": name, "event_types": event_types}
response = await self.async_client.post(
f"api/v1/webhooks/{project_id}/webhook/", json=payload
)
response.raise_for_status()
capture_client_event("async_client.create_webhook", self.sync_client)
return response.json()
@api_error_handler
async def update_webhook(
self, webhook_id: int,project_id: str, name: Optional[str] = None, url: Optional[str] = None, event_types: Optional[List[str]] = None
) -> Dict[str, Any]:
payload = {k: v for k, v in {"name": name, "url": url, "event_types": event_types}.items() if v is not None}
response = await self.async_client.put(f"api/v1/webhooks/{project_id}/webhook/{webhook_id}/", json=payload)
response.raise_for_status()
capture_client_event("async_client.update_webhook", self.sync_client, {"webhook_id": webhook_id})
return response.json()
@api_error_handler
async def delete_webhook(self, webhook_id: int, project_id: str) -> Dict[str, str]:
response = await self.async_client.delete(f"api/v1/webhooks/{project_id}/webhook/{webhook_id}/")
response.raise_for_status()
capture_client_event("async_client.delete_webhook", self.sync_client, {"webhook_id": webhook_id})
return response.json()
+7
View File
@@ -33,6 +33,8 @@ class BaseLlmConfig(ABC):
azure_kwargs: Optional[AzureConfig] = {}, azure_kwargs: Optional[AzureConfig] = {},
# AzureOpenAI specific # AzureOpenAI specific
http_client_proxies: Optional[Union[Dict, str]] = None, http_client_proxies: Optional[Union[Dict, str]] = None,
# DeepSeek specific
deepseek_base_url: Optional[str] = None,
): ):
""" """
Initializes a configuration class instance for the LLM. Initializes a configuration class instance for the LLM.
@@ -69,6 +71,8 @@ class BaseLlmConfig(ABC):
:type azure_kwargs: Optional[Dict[str, Any]], defaults a dict inside init :type azure_kwargs: Optional[Dict[str, Any]], defaults a dict inside init
:param http_client_proxies: The proxy server(s) settings used to create self.http_client, defaults to None :param http_client_proxies: The proxy server(s) settings used to create self.http_client, defaults to None
:type http_client_proxies: Optional[Dict | str], optional :type http_client_proxies: Optional[Dict | str], optional
:param deepseek_base_url: DeepSeek base URL to be use, defaults to None
:type deepseek_base_url: Optional[str], optional
""" """
self.model = model self.model = model
@@ -92,5 +96,8 @@ class BaseLlmConfig(ABC):
# Ollama specific # Ollama specific
self.ollama_base_url = ollama_base_url self.ollama_base_url = ollama_base_url
# DeepSeek specific
self.deepseek_base_url = deepseek_base_url
# AzureOpenAI specific # AzureOpenAI specific
self.azure_kwargs = AzureConfig(**azure_kwargs) or {} self.azure_kwargs = AzureConfig(**azure_kwargs) or {}
+42
View File
@@ -0,0 +1,42 @@
from typing import Any, Dict, Optional
from pydantic import BaseModel, Field, model_validator
class OpenSearchConfig(BaseModel):
collection_name: str = Field("mem0", description="Name of the index")
host: str = Field("localhost", description="OpenSearch host")
port: int = Field(9200, description="OpenSearch port")
user: Optional[str] = Field(None, description="Username for authentication")
password: Optional[str] = Field(None, description="Password for authentication")
api_key: Optional[str] = Field(None, description="API key for authentication (if applicable)")
embedding_model_dims: int = Field(1536, description="Dimension of the embedding vector")
verify_certs: bool = Field(False, description="Verify SSL certificates (default False for OpenSearch)")
use_ssl: bool = Field(False, description="Use SSL for connection (default False for OpenSearch)")
auto_create_index: bool = Field(True, description="Automatically create index during initialization")
@model_validator(mode="before")
@classmethod
def validate_auth(cls, values: Dict[str, Any]) -> Dict[str, Any]:
# Check if host is provided
if not values.get("host"):
raise ValueError("Host must be provided for OpenSearch")
# Authentication: Either API key or user/password must be provided
if not any([values.get("api_key"), (values.get("user") and values.get("password"))]):
raise ValueError("Either api_key or user/password must be provided for OpenSearch authentication")
return values
@model_validator(mode="before")
@classmethod
def validate_extra_fields(cls, values: Dict[str, Any]) -> Dict[str, Any]:
allowed_fields = set(cls.model_fields.keys())
input_fields = set(values.keys())
extra_fields = input_fields - allowed_fields
if extra_fields:
raise ValueError(
f"Extra fields not allowed: {', '.join(extra_fields)}. "
f"Allowed fields: {', '.join(allowed_fields)}"
)
return values
+1
View File
@@ -22,6 +22,7 @@ class LlmConfig(BaseModel):
"openai_structured", "openai_structured",
"azure_openai_structured", "azure_openai_structured",
"gemini", "gemini",
"deepseek",
): ):
return v return v
else: else:
+84
View File
@@ -0,0 +1,84 @@
import json
import os
from typing import Dict, List, Optional
from openai import OpenAI
from mem0.configs.llms.base import BaseLlmConfig
from mem0.llms.base import LLMBase
class DeepSeekLLM(LLMBase):
def __init__(self, config: Optional[BaseLlmConfig] = None):
super().__init__(config)
if not self.config.model:
self.config.model = "deepseek-chat"
api_key = self.config.api_key or os.getenv("DEEPSEEK_API_KEY")
base_url = self.config.deepseek_base_url or os.getenv("DEEPSEEK_API_BASE") or "https://api.deepseek.com"
self.client = OpenAI(api_key=api_key, base_url=base_url)
def _parse_response(self, response, tools):
"""
Process the response based on whether tools are used or not.
Args:
response: The raw response from API.
tools: The list of tools provided in the request.
Returns:
str or dict: The processed response.
"""
if tools:
processed_response = {
"content": response.choices[0].message.content,
"tool_calls": [],
}
if response.choices[0].message.tool_calls:
for tool_call in response.choices[0].message.tool_calls:
processed_response["tool_calls"].append(
{
"name": tool_call.function.name,
"arguments": json.loads(tool_call.function.arguments),
}
)
return processed_response
else:
return response.choices[0].message.content
def generate_response(
self,
messages: List[Dict[str, str]],
response_format=None,
tools: Optional[List[Dict]] = None,
tool_choice: str = "auto",
):
"""
Generate a response based on the given messages using DeepSeek.
Args:
messages (list): List of message dicts containing 'role' and 'content'.
response_format (str or object, optional): Format of the response. Defaults to "text".
tools (list, optional): List of tools that the model can call. Defaults to None.
tool_choice (str, optional): Tool choice method. Defaults to "auto".
Returns:
str: The generated response.
"""
params = {
"model": self.config.model,
"messages": messages,
"temperature": self.config.temperature,
"max_tokens": self.config.max_tokens,
"top_p": self.config.top_p,
}
if tools:
params["tools"] = tools
params["tool_choice"] = tool_choice
response = self.client.chat.completions.create(**params)
return self._parse_response(response, tools)
+2 -1
View File
@@ -63,6 +63,7 @@ class OpenAILLM(LLMBase):
response_format=None, response_format=None,
tools: Optional[List[Dict]] = None, tools: Optional[List[Dict]] = None,
tool_choice: str = "auto", tool_choice: str = "auto",
max_tokens: int = 100,
): ):
""" """
Generate a response based on the given messages using OpenAI. Generate a response based on the given messages using OpenAI.
@@ -80,7 +81,7 @@ class OpenAILLM(LLMBase):
"model": self.config.model, "model": self.config.model,
"messages": messages, "messages": messages,
"temperature": self.config.temperature, "temperature": self.config.temperature,
"max_tokens": self.config.max_tokens, "max_tokens": max_tokens,
"top_p": self.config.top_p, "top_p": self.config.top_p,
} }
+9 -4
View File
@@ -9,7 +9,7 @@ from typing import Any, Dict
import pytz import pytz
from pydantic import ValidationError from pydantic import ValidationError
from mem0.memory.utils import parse_vision_messages
from mem0.configs.base import MemoryConfig, MemoryItem from mem0.configs.base import MemoryConfig, MemoryItem
from mem0.configs.prompts import get_update_memory_messages from mem0.configs.prompts import get_update_memory_messages
from mem0.memory.base import MemoryBase from mem0.memory.base import MemoryBase
@@ -114,6 +114,8 @@ class Memory(MemoryBase):
if isinstance(messages, str): if isinstance(messages, str):
messages = [{"role": "user", "content": messages}] messages = [{"role": "user", "content": messages}]
messages = parse_vision_messages(messages)
with concurrent.futures.ThreadPoolExecutor() as executor: with concurrent.futures.ThreadPoolExecutor() as executor:
future1 = executor.submit(self._add_to_vector_store, messages, metadata, filters) future1 = executor.submit(self._add_to_vector_store, messages, metadata, filters)
future2 = executor.submit(self._add_to_graph, messages, filters) future2 = executor.submit(self._add_to_graph, messages, filters)
@@ -143,7 +145,7 @@ class Memory(MemoryBase):
if self.custom_prompt: if self.custom_prompt:
system_prompt = self.custom_prompt system_prompt = self.custom_prompt
user_prompt = f"Input: {parsed_messages}" user_prompt = f"Input:\n{parsed_messages}"
else: else:
system_prompt, user_prompt = get_fact_retrieval_messages(parsed_messages) system_prompt, user_prompt = get_fact_retrieval_messages(parsed_messages)
@@ -174,7 +176,10 @@ class Memory(MemoryBase):
) )
for mem in existing_memories: for mem in existing_memories:
retrieved_old_memory.append({"id": mem.id, "text": mem.payload["data"]}) retrieved_old_memory.append({"id": mem.id, "text": mem.payload["data"]})
unique_data = {}
for item in retrieved_old_memory:
unique_data[item['id']] = item
retrieved_old_memory = list(unique_data.values())
logging.info(f"Total existing memories: {len(retrieved_old_memory)}") logging.info(f"Total existing memories: {len(retrieved_old_memory)}")
# mapping UUIDs with integers for handling UUID hallucinations # mapping UUIDs with integers for handling UUID hallucinations
@@ -432,7 +437,7 @@ class Memory(MemoryBase):
return {"results": original_memories} return {"results": original_memories}
else: else:
warnings.warn( warnings.warn(
"The current get_all API output format is deprecated. " "The current search API output format is deprecated. "
"To use the latest format, set `api_version='v1.1'`. " "To use the latest format, set `api_version='v1.1'`. "
"The current format will be removed in mem0ai 1.1.0 and later versions.", "The current format will be removed in mem0ai 1.1.0 and later versions.",
category=DeprecationWarning, category=DeprecationWarning,
+110 -103
View File
@@ -1,89 +1,93 @@
import sqlite3 import sqlite3
import uuid import uuid
import threading
class SQLiteManager: class SQLiteManager:
def __init__(self, db_path=":memory:"): def __init__(self, db_path=":memory:"):
self.connection = sqlite3.connect(db_path, check_same_thread=False) self.connection = sqlite3.connect(db_path, check_same_thread=False)
self._lock = threading.Lock()
self._migrate_history_table() self._migrate_history_table()
self._create_history_table() self._create_history_table()
def _migrate_history_table(self): def _migrate_history_table(self):
with self.connection: with self._lock:
cursor = self.connection.cursor() with self.connection:
cursor = self.connection.cursor()
cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='history'") cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='history'")
table_exists = cursor.fetchone() is not None table_exists = cursor.fetchone() is not None
if table_exists: if table_exists:
# Get the current schema of the history table # Get the current schema of the history table
cursor.execute("PRAGMA table_info(history)") cursor.execute("PRAGMA table_info(history)")
current_schema = {row[1]: row[2] for row in cursor.fetchall()} current_schema = {row[1]: row[2] for row in cursor.fetchall()}
# Define the expected schema # Define the expected schema
expected_schema = { expected_schema = {
"id": "TEXT", "id": "TEXT",
"memory_id": "TEXT", "memory_id": "TEXT",
"old_memory": "TEXT", "old_memory": "TEXT",
"new_memory": "TEXT", "new_memory": "TEXT",
"new_value": "TEXT", "new_value": "TEXT",
"event": "TEXT", "event": "TEXT",
"created_at": "DATETIME", "created_at": "DATETIME",
"updated_at": "DATETIME", "updated_at": "DATETIME",
"is_deleted": "INTEGER", "is_deleted": "INTEGER",
} }
# Check if the schemas are the same # Check if the schemas are the same
if current_schema != expected_schema: if current_schema != expected_schema:
# Rename the old table # Rename the old table
cursor.execute("ALTER TABLE history RENAME TO old_history") cursor.execute("ALTER TABLE history RENAME TO old_history")
cursor.execute( cursor.execute(
"""
CREATE TABLE IF NOT EXISTS history (
id TEXT PRIMARY KEY,
memory_id TEXT,
old_memory TEXT,
new_memory TEXT,
new_value TEXT,
event TEXT,
created_at DATETIME,
updated_at DATETIME,
is_deleted INTEGER
)
""" """
CREATE TABLE IF NOT EXISTS history (
id TEXT PRIMARY KEY,
memory_id TEXT,
old_memory TEXT,
new_memory TEXT,
new_value TEXT,
event TEXT,
created_at DATETIME,
updated_at DATETIME,
is_deleted INTEGER
) )
"""
)
# Copy data from the old table to the new table # Copy data from the old table to the new table
cursor.execute( cursor.execute(
""" """
INSERT INTO history (id, memory_id, old_memory, new_memory, new_value, event, created_at, updated_at, is_deleted) INSERT INTO history (id, memory_id, old_memory, new_memory, new_value, event, created_at, updated_at, is_deleted)
SELECT id, memory_id, prev_value, new_value, new_value, event, timestamp, timestamp, is_deleted SELECT id, memory_id, prev_value, new_value, new_value, event, timestamp, timestamp, is_deleted
FROM old_history FROM old_history
""" # noqa: E501 """ # noqa: E501
) )
cursor.execute("DROP TABLE old_history") cursor.execute("DROP TABLE old_history")
self.connection.commit() self.connection.commit()
def _create_history_table(self): def _create_history_table(self):
with self.connection: with self._lock:
self.connection.execute( with self.connection:
self.connection.execute(
"""
CREATE TABLE IF NOT EXISTS history (
id TEXT PRIMARY KEY,
memory_id TEXT,
old_memory TEXT,
new_memory TEXT,
new_value TEXT,
event TEXT,
created_at DATETIME,
updated_at DATETIME,
is_deleted INTEGER
)
""" """
CREATE TABLE IF NOT EXISTS history (
id TEXT PRIMARY KEY,
memory_id TEXT,
old_memory TEXT,
new_memory TEXT,
new_value TEXT,
event TEXT,
created_at DATETIME,
updated_at DATETIME,
is_deleted INTEGER
) )
"""
)
def add_history( def add_history(
self, self,
@@ -95,49 +99,52 @@ class SQLiteManager:
updated_at=None, updated_at=None,
is_deleted=0, is_deleted=0,
): ):
with self.connection: with self._lock:
self.connection.execute( with self.connection:
""" self.connection.execute(
INSERT INTO history (id, memory_id, old_memory, new_memory, event, created_at, updated_at, is_deleted) """
VALUES (?, ?, ?, ?, ?, ?, ?, ?) INSERT INTO history (id, memory_id, old_memory, new_memory, event, created_at, updated_at, is_deleted)
""", VALUES (?, ?, ?, ?, ?, ?, ?, ?)
( """,
str(uuid.uuid4()), (
memory_id, str(uuid.uuid4()),
old_memory, memory_id,
new_memory, old_memory,
event, new_memory,
created_at, event,
updated_at, created_at,
is_deleted, updated_at,
), is_deleted,
) ),
)
def get_history(self, memory_id): def get_history(self, memory_id):
cursor = self.connection.execute( with self._lock:
""" cursor = self.connection.execute(
SELECT id, memory_id, old_memory, new_memory, event, created_at, updated_at """
FROM history SELECT id, memory_id, old_memory, new_memory, event, created_at, updated_at
WHERE memory_id = ? FROM history
ORDER BY updated_at ASC WHERE memory_id = ?
""", ORDER BY updated_at ASC
(memory_id,), """,
) (memory_id,),
rows = cursor.fetchall() )
return [ rows = cursor.fetchall()
{ return [
"id": row[0], {
"memory_id": row[1], "id": row[0],
"old_memory": row[2], "memory_id": row[1],
"new_memory": row[3], "old_memory": row[2],
"event": row[4], "new_memory": row[3],
"created_at": row[5], "event": row[4],
"updated_at": row[6], "created_at": row[5],
} "updated_at": row[6],
for row in rows }
] for row in rows
]
def reset(self): def reset(self):
with self.connection: with self._lock:
self.connection.execute("DROP TABLE IF EXISTS history") with self.connection:
self._create_history_table() self.connection.execute("DROP TABLE IF EXISTS history")
self._create_history_table()
+44 -2
View File
@@ -1,10 +1,10 @@
import re import re
from mem0.configs.prompts import FACT_RETRIEVAL_PROMPT from mem0.configs.prompts import FACT_RETRIEVAL_PROMPT
from mem0.llms.openai import OpenAILLM
def get_fact_retrieval_messages(message): def get_fact_retrieval_messages(message):
return FACT_RETRIEVAL_PROMPT, f"Input: {message}" return FACT_RETRIEVAL_PROMPT, f"Input:\n{message}"
def parse_messages(messages): def parse_messages(messages):
@@ -43,3 +43,45 @@ def remove_code_blocks(content: str) -> str:
pattern = r"^```[a-zA-Z0-9]*\n([\s\S]*?)\n```$" pattern = r"^```[a-zA-Z0-9]*\n([\s\S]*?)\n```$"
match = re.match(pattern, content.strip()) match = re.match(pattern, content.strip())
return match.group(1).strip() if match else content.strip() return match.group(1).strip() if match else content.strip()
def get_image_description(image_url):
"""
Get the description of the image
"""
llm = OpenAILLM()
response = llm.generate_response(
messages=[
{
"role": "user",
"content": [
{"type": "text", "text": "Provide a description of the image and do not include any additional text."},
{"type": "image_url", "image_url": {"url": image_url}}
],
},
],
max_tokens=100,
)
return response
def parse_vision_messages(messages):
"""
Parse the vision messages from the messages
"""
returned_messages = []
for msg in messages:
if msg["role"] != "system":
if not isinstance(msg["content"], str) and msg["content"]["type"] == "image_url":
image_url = msg["content"]["image_url"]["url"]
try:
description = get_image_description(image_url)
msg["content"]["text"] = description
returned_messages.append({"role": msg["role"], "content": description})
except Exception:
raise Exception(f"Error while downloading {image_url}.")
else:
returned_messages.append(msg)
else:
returned_messages.append(msg)
return returned_messages
+2
View File
@@ -23,6 +23,7 @@ class LlmFactory:
"anthropic": "mem0.llms.anthropic.AnthropicLLM", "anthropic": "mem0.llms.anthropic.AnthropicLLM",
"azure_openai_structured": "mem0.llms.azure_openai_structured.AzureOpenAIStructuredLLM", "azure_openai_structured": "mem0.llms.azure_openai_structured.AzureOpenAIStructuredLLM",
"gemini": "mem0.llms.gemini.GeminiLLM", "gemini": "mem0.llms.gemini.GeminiLLM",
"deepseek": "mem0.llms.deepseek.DeepSeekLLM",
} }
@classmethod @classmethod
@@ -67,6 +68,7 @@ class VectorStoreFactory:
"azure_ai_search": "mem0.vector_stores.azure_ai_search.AzureAISearch", "azure_ai_search": "mem0.vector_stores.azure_ai_search.AzureAISearch",
"redis": "mem0.vector_stores.redis.RedisDB", "redis": "mem0.vector_stores.redis.RedisDB",
"elasticsearch": "mem0.vector_stores.elasticsearch.ElasticsearchDB", "elasticsearch": "mem0.vector_stores.elasticsearch.ElasticsearchDB",
"opensearch": "mem0.vector_stores.opensearch.OpenSearchDB"
} }
@classmethod @classmethod
+53 -17
View File
@@ -76,6 +76,9 @@ class AzureAISearch(VectorStoreBase):
fields = [ fields = [
SimpleField(name="id", type=SearchFieldDataType.String, key=True), SimpleField(name="id", type=SearchFieldDataType.String, key=True),
SimpleField(name="user_id", type=SearchFieldDataType.String, filterable=True),
SimpleField(name="run_id", type=SearchFieldDataType.String, filterable=True),
SimpleField(name="agent_id", type=SearchFieldDataType.String, filterable=True),
SearchField( SearchField(
name="vector", name="vector",
type=vector_type, type=vector_type,
@@ -96,6 +99,14 @@ class AzureAISearch(VectorStoreBase):
index = SearchIndex(name=self.index_name, fields=fields, vector_search=vector_search) index = SearchIndex(name=self.index_name, fields=fields, vector_search=vector_search)
self.index_client.create_or_update_index(index) self.index_client.create_or_update_index(index)
def _generate_document(self, vector, payload, id):
document = {"id": id, "vector": vector, "payload": json.dumps(payload)}
# Extract additional fields if they exist
for field in ["user_id", "run_id", "agent_id"]:
if field in payload:
document[field] = payload[field]
return document
def insert(self, vectors, payloads=None, ids=None): def insert(self, vectors, payloads=None, ids=None):
"""Insert vectors into the index. """Insert vectors into the index.
@@ -105,12 +116,26 @@ class AzureAISearch(VectorStoreBase):
ids (List[str], optional): List of IDs corresponding to vectors. ids (List[str], optional): List of IDs corresponding to vectors.
""" """
logger.info(f"Inserting {len(vectors)} vectors into index {self.index_name}") logger.info(f"Inserting {len(vectors)} vectors into index {self.index_name}")
documents = [ documents = [
{"id": id, "vector": vector, "payload": json.dumps(payload)} self._generate_document(vector, payload, id)
for id, vector, payload in zip(ids, vectors, payloads) for id, vector, payload in zip(ids, vectors, payloads)
] ]
self.search_client.upload_documents(documents) self.search_client.upload_documents(documents)
def _build_filter_expression(self, filters):
filter_conditions = []
for key, value in filters.items():
# If the value is a string, add quotes
if isinstance(value, str):
condition = f"{key} eq '{value}'"
else:
condition = f"{key} eq {value}"
filter_conditions.append(condition)
# Use 'and' to join multiple conditions
filter_expression = ' and '.join(filter_conditions)
return filter_expression
def search(self, query, limit=5, filters=None): def search(self, query, limit=5, filters=None):
"""Search for similar vectors. """Search for similar vectors.
@@ -122,17 +147,23 @@ class AzureAISearch(VectorStoreBase):
Returns: Returns:
list: Search results. list: Search results.
""" """
# Build filter expression
filter_expression = None
if filters:
filter_expression = self._build_filter_expression(filters)
vector_query = VectorizedQuery(vector=query, k_nearest_neighbors=limit, fields="vector") vector_query = VectorizedQuery(
search_results = self.search_client.search(vector_queries=[vector_query], top=limit) vector=query, k_nearest_neighbors=limit, fields="vector"
)
search_results = self.search_client.search(
vector_queries=[vector_query],
filter=filter_expression,
top=limit
)
results = [] results = []
for result in search_results: for result in search_results:
payload = json.loads(result["payload"]) payload = json.loads(result["payload"])
if filters:
for key, value in filters.items():
if key not in payload or payload[key] != value:
continue
results.append(OutputData(id=result["id"], score=result["@search.score"], payload=payload)) results.append(OutputData(id=result["id"], score=result["@search.score"], payload=payload))
return results return results
@@ -143,6 +174,7 @@ class AzureAISearch(VectorStoreBase):
vector_id (str): ID of the vector to delete. vector_id (str): ID of the vector to delete.
""" """
self.search_client.delete_documents(documents=[{"id": vector_id}]) self.search_client.delete_documents(documents=[{"id": vector_id}])
logger.info(f"Deleted document with ID '{vector_id}' from index '{self.index_name}'.")
def update(self, vector_id, vector=None, payload=None): def update(self, vector_id, vector=None, payload=None):
"""Update a vector and its payload. """Update a vector and its payload.
@@ -156,7 +188,10 @@ class AzureAISearch(VectorStoreBase):
if vector: if vector:
document["vector"] = vector document["vector"] = vector
if payload: if payload:
document["payload"] = json.dumps(payload) json_payload = json.dumps(payload)
document["payload"] = json_payload
for field in ["user_id", "run_id", "agent_id"]:
document[field] = payload.get(field)
self.search_client.merge_or_upload_documents(documents=[document]) self.search_client.merge_or_upload_documents(documents=[document])
def get(self, vector_id) -> OutputData: def get(self, vector_id) -> OutputData:
@@ -206,18 +241,19 @@ class AzureAISearch(VectorStoreBase):
Returns: Returns:
List[OutputData]: List of vectors. List[OutputData]: List of vectors.
""" """
search_results = self.search_client.search(search_text="*", top=limit) filter_expression = None
if filters:
filter_expression = self._build_filter_expression(filters)
search_results = self.search_client.search(
search_text="*",
filter=filter_expression,
top=limit
)
results = [] results = []
for result in search_results: for result in search_results:
payload = json.loads(result["payload"]) payload = json.loads(result["payload"])
include_result = True results.append(OutputData(id=result["id"], score=result["@search.score"], payload=payload))
if filters:
for key, value in filters.items():
if (key not in payload) or (payload[key] != filters[key]):
include_result = False
break
if include_result:
results.append(OutputData(id=result["id"], score=result["@search.score"], payload=payload))
return [results] return [results]
+1
View File
@@ -18,6 +18,7 @@ class VectorStoreConfig(BaseModel):
"azure_ai_search": "AzureAISearchConfig", "azure_ai_search": "AzureAISearchConfig",
"redis": "RedisDBConfig", "redis": "RedisDBConfig",
"elasticsearch": "ElasticsearchConfig", "elasticsearch": "ElasticsearchConfig",
"opensearch": "OpenSearchConfig",
} }
@model_validator(mode="after") @model_validator(mode="after")
+71 -32
View File
@@ -5,9 +5,7 @@ try:
from elasticsearch import Elasticsearch from elasticsearch import Elasticsearch
from elasticsearch.helpers import bulk from elasticsearch.helpers import bulk
except ImportError: except ImportError:
raise ImportError( raise ImportError("Elasticsearch requires extra dependencies. Install with `pip install elasticsearch`") from None
"Elasticsearch requires extra dependencies. Install with `pip install elasticsearch`"
) from None
from pydantic import BaseModel from pydantic import BaseModel
@@ -51,18 +49,28 @@ class ElasticsearchDB(VectorStoreBase):
def create_index(self) -> None: def create_index(self) -> None:
"""Create Elasticsearch index with proper mappings if it doesn't exist""" """Create Elasticsearch index with proper mappings if it doesn't exist"""
index_settings = { index_settings = {
"settings": {
"index": {
"number_of_replicas": 1,
"number_of_shards": 5,
"refresh_interval": "1s"
}
},
"mappings": { "mappings": {
"properties": { "properties": {
"text": {"type": "text"}, "text": {"type": "text"},
"embedding": { "vector": {
"type": "dense_vector", "type": "dense_vector",
"dims": self.vector_dim, "dims": self.vector_dim,
"index": True, "index": True,
"similarity": "cosine", "similarity": "cosine"
}, },
"metadata": {"type": "object"}, "metadata": {
"user_id": {"type": "keyword"}, "type": "object",
"hash": {"type": "keyword"}, "properties": {
"user_id": {"type": "keyword"}
}
}
} }
} }
} }
@@ -101,44 +109,64 @@ class ElasticsearchDB(VectorStoreBase):
actions = [] actions = []
for i, (vec, id_) in enumerate(zip(vectors, ids)): for i, (vec, id_) in enumerate(zip(vectors, ids)):
action = {"_index": self.collection_name, "_id": id_, "vector": vec, "payload": payloads[i]} action = {
"_index": self.collection_name,
"_id": id_,
"_source": {
"vector": vec,
"metadata": payloads[i] # Store all metadata in the metadata field
}
}
actions.append(action) actions.append(action)
bulk(self.client, actions) bulk(self.client, actions)
# Return OutputData objects for inserted documents
results = [] results = []
for i, id_ in enumerate(ids): for i, id_ in enumerate(ids):
results.append( results.append(
OutputData( OutputData(
id=id_, id=id_,
score=1.0, # Default score for inserts score=1.0, # Default score for inserts
payload=payloads[i], payload=payloads[i]
) )
) )
return results return results
def search(self, query: List[float], limit: int = 5, filters: Optional[Dict] = None) -> List[OutputData]: def search(self, query: List[float], limit: int = 5, filters: Optional[Dict] = None) -> List[OutputData]:
"""Search for similar vectors using KNN search with pre-filtering.""" """Search for similar vectors using KNN search with pre-filtering."""
search_query = { if not filters:
"query": { # If no filters, just do KNN search
"bool": { search_query = {
"must": [ "knn": {
# Exact match filters for memory isolation "field": "vector",
*({"term": {f"payload.{k}": v}} for k, v in (filters or {}).items()), "query_vector": query,
# KNN vector search "k": limit,
{ "num_candidates": limit * 2
"knn": { }
"vector": { }
"vector": query, else:
"k": limit # If filters exist, apply them with KNN search
} filter_conditions = []
} for key, value in filters.items():
filter_conditions.append({
"term": {
f"metadata.{key}": value
}
})
search_query = {
"knn": {
"field": "vector",
"query_vector": query,
"k": limit,
"num_candidates": limit * 2,
"filter": {
"bool": {
"must": filter_conditions
} }
] }
} }
} }
}
response = self.client.search(index=self.collection_name, body=search_query) response = self.client.search(index=self.collection_name, body=search_query)
@@ -148,7 +176,7 @@ class ElasticsearchDB(VectorStoreBase):
OutputData( OutputData(
id=hit["_id"], id=hit["_id"],
score=hit["_score"], score=hit["_score"],
payload=hit["_source"].get("payload", {}) payload=hit.get("_source", {}).get("metadata", {})
) )
) )
@@ -164,7 +192,7 @@ class ElasticsearchDB(VectorStoreBase):
if vector is not None: if vector is not None:
doc["vector"] = vector doc["vector"] = vector
if payload is not None: if payload is not None:
doc["payload"] = payload doc["metadata"] = payload
self.client.update(index=self.collection_name, id=vector_id, body={"doc": doc}) self.client.update(index=self.collection_name, id=vector_id, body={"doc": doc})
@@ -175,7 +203,7 @@ class ElasticsearchDB(VectorStoreBase):
return OutputData( return OutputData(
id=response["_id"], id=response["_id"],
score=1.0, # Default score for direct get score=1.0, # Default score for direct get
payload=response["_source"].get("payload", {}), payload=response["_source"].get("metadata", {})
) )
except KeyError as e: except KeyError as e:
logger.warning(f"Missing key in Elasticsearch response: {e}") logger.warning(f"Missing key in Elasticsearch response: {e}")
@@ -204,7 +232,18 @@ class ElasticsearchDB(VectorStoreBase):
query: Dict[str, Any] = {"query": {"match_all": {}}} query: Dict[str, Any] = {"query": {"match_all": {}}}
if filters: if filters:
query["query"] = {"bool": {"must": [{"match": {f"payload.{k}": v}} for k, v in filters.items()]}} filter_conditions = []
for key, value in filters.items():
filter_conditions.append({
"term": {
f"metadata.{key}": value
}
})
query["query"] = {
"bool": {
"must": filter_conditions
}
}
if limit: if limit:
query["size"] = limit query["size"] = limit
@@ -217,7 +256,7 @@ class ElasticsearchDB(VectorStoreBase):
OutputData( OutputData(
id=hit["_id"], id=hit["_id"],
score=1.0, # Default score for list operation score=1.0, # Default score for list operation
payload=hit["_source"].get("payload", {}), payload=hit.get("_source", {}).get("metadata", {})
) )
) )
+189
View File
@@ -0,0 +1,189 @@
import logging
from typing import Any, Dict, List, Optional
try:
from opensearchpy import OpenSearch
from opensearchpy.helpers import bulk
except ImportError:
raise ImportError("OpenSearch requires extra dependencies. Install with `pip install opensearch-py`") from None
from pydantic import BaseModel
from mem0.configs.vector_stores.opensearch import OpenSearchConfig
from mem0.vector_stores.base import VectorStoreBase
logger = logging.getLogger(__name__)
class OutputData(BaseModel):
id: str
score: float
payload: Dict
class OpenSearchDB(VectorStoreBase):
def __init__(self, **kwargs):
config = OpenSearchConfig(**kwargs)
# Initialize OpenSearch client
self.client = OpenSearch(
hosts=[{"host": config.host, "port": config.port or 9200}],
http_auth=(config.user, config.password) if (config.user and config.password) else None,
use_ssl=config.use_ssl,
verify_certs=config.verify_certs,
)
self.collection_name = config.collection_name
self.vector_dim = config.embedding_model_dims
# Create index only if auto_create_index is True
if config.auto_create_index:
self.create_index()
def create_index(self) -> None:
"""Create OpenSearch index with proper mappings if it doesn't exist."""
index_settings = {
# ToDo change replicas to 1
"settings": {
"index": {"number_of_replicas": 1, "number_of_shards": 5, "refresh_interval": "1s", "knn": True}
},
"mappings": {
"properties": {
"text": {"type": "text"},
"vector": {
"type": "knn_vector",
"dimension": self.vector_dim
},
"metadata": {"type": "object", "properties": {"user_id": {"type": "keyword"}}},
}
},
}
if not self.client.indices.exists(index=self.collection_name):
self.client.indices.create(index=self.collection_name, body=index_settings)
logger.info(f"Created index {self.collection_name}")
else:
logger.info(f"Index {self.collection_name} already exists")
def create_col(self, name: str, vector_size: int) -> None:
"""Create a new collection (index in OpenSearch)."""
index_settings = {
"mappings": {
"properties": {
"vector": {
"type": "knn_vector",
"dimension": vector_size,
"method": { "engine": "lucene", "name": "hnsw", "space_type": "cosinesimil"},
},
"payload": {"type": "object"},
"id": {"type": "keyword"},
}
}
}
if not self.client.indices.exists(index=name):
self.client.indices.create(index=name, body=index_settings)
logger.info(f"Created index {name}")
def insert(
self, vectors: List[List[float]], payloads: Optional[List[Dict]] = None, ids: Optional[List[str]] = None
) -> List[OutputData]:
"""Insert vectors into the index."""
if not ids:
ids = [str(i) for i in range(len(vectors))]
if payloads is None:
payloads = [{} for _ in range(len(vectors))]
actions = []
for i, (vec, id_) in enumerate(zip(vectors, ids)):
action = {
"_index": self.collection_name,
"_id": id_,
"_source": {
"vector": vec,
"metadata": payloads[i], # Store metadata in the metadata field
},
}
actions.append(action)
bulk(self.client, actions)
results = []
for i, id_ in enumerate(ids):
results.append(OutputData(id=id_, score=1.0, payload=payloads[i]))
return results
def search(self, query: List[float], limit: int = 5, filters: Optional[Dict] = None) -> List[OutputData]:
"""Search for similar vectors using OpenSearch k-NN search with pre-filtering."""
search_query = {
"size": limit,
"query": {
"knn": {
"vector": {
"vector": query,
"k": limit,
}
}
}
}
if filters:
filter_conditions = [{"term": {f"metadata.{key}": value}} for key, value in filters.items()]
search_query["query"]["knn"]["vector"]["filter"] = { "bool": {"filter": filter_conditions} }
response = self.client.search(index=self.collection_name, body=search_query)
results = [
OutputData(id=hit["_id"], score=hit["_score"], payload=hit["_source"].get("metadata", {}))
for hit in response["hits"]["hits"]
]
return results
def delete(self, vector_id: str) -> None:
"""Delete a vector by ID."""
self.client.delete(index=self.collection_name, id=vector_id)
def update(self, vector_id: str, vector: Optional[List[float]] = None, payload: Optional[Dict] = None) -> None:
"""Update a vector and its payload."""
doc = {}
if vector is not None:
doc["vector"] = vector
if payload is not None:
doc["metadata"] = payload
self.client.update(index=self.collection_name, id=vector_id, body={"doc": doc})
def get(self, vector_id: str) -> Optional[OutputData]:
"""Retrieve a vector by ID."""
try:
response = self.client.get(index=self.collection_name, id=vector_id)
return OutputData(id=response["_id"], score=1.0, payload=response["_source"].get("metadata", {}))
except Exception as e:
logger.error(f"Error retrieving vector {vector_id}: {e}")
return None
def list_cols(self) -> List[str]:
"""List all collections (indices)."""
return list(self.client.indices.get_alias().keys())
def delete_col(self) -> None:
"""Delete a collection (index)."""
self.client.indices.delete(index=self.collection_name)
def col_info(self, name: str) -> Any:
"""Get information about a collection (index)."""
return self.client.indices.get(index=name)
def list(self, filters: Optional[Dict] = None, limit: Optional[int] = None) -> List[List[OutputData]]:
"""List all memories."""
query = {"query": {"match_all": {}}}
if filters:
query["query"] = {"bool": {"must": [{"term": {f"metadata.{key}": value}} for key, value in filters.items()]}}
if limit:
query["size"] = limit
response = self.client.search(index=self.collection_name, body=query)
return [[OutputData(id=hit["_id"], score=1.0, payload=hit["_source"].get("metadata", {})) for hit in response["hits"]["hits"]]]
Generated
+649 -419
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -1,6 +1,6 @@
[tool.poetry] [tool.poetry]
name = "mem0ai" name = "mem0ai"
version = "0.1.43" version = "0.1.53"
description = "Long-term memory for AI Agents" description = "Long-term memory for AI Agents"
authors = ["Mem0 <founders@mem0.ai>"] authors = ["Mem0 <founders@mem0.ai>"]
exclude = [ exclude = [
+3 -3
View File
@@ -97,8 +97,8 @@ def test_generate_response_with_tools(mock_openai_client):
[None, {"Firstkey": "FirstVal", "SecondKey": "SecondVal"}], [None, {"Firstkey": "FirstVal", "SecondKey": "SecondVal"}],
) )
def test_generate_with_http_proxies(default_headers): def test_generate_with_http_proxies(default_headers):
mock_http_client = Mock(spec=httpx.Client) mock_http_client = Mock()
mock_http_client_instance = Mock(spec=httpx.Client) mock_http_client_instance = Mock()
mock_http_client.return_value = mock_http_client_instance mock_http_client.return_value = mock_http_client_instance
azure_kwargs = {"api_key": "test"} azure_kwargs = {"api_key": "test"}
if default_headers: if default_headers:
@@ -106,7 +106,7 @@ def test_generate_with_http_proxies(default_headers):
with ( with (
patch("mem0.llms.azure_openai.AzureOpenAI") as mock_azure_openai, patch("mem0.llms.azure_openai.AzureOpenAI") as mock_azure_openai,
patch("httpx.Client", new=mock_http_client) as mock_http_client, patch("httpx.Client", new=mock_http_client),
): ):
config = BaseLlmConfig( config = BaseLlmConfig(
model=MODEL, model=MODEL,
+113
View File
@@ -0,0 +1,113 @@
from unittest.mock import Mock, patch
import os
import pytest
from mem0.configs.llms.base import BaseLlmConfig
from mem0.llms.deepseek import DeepSeekLLM
@pytest.fixture
def mock_deepseek_client():
with patch("mem0.llms.deepseek.OpenAI") as mock_openai:
mock_client = Mock()
mock_openai.return_value = mock_client
yield mock_client
def test_deepseek_llm_base_url():
# case1: default config with deepseek official base url
config = BaseLlmConfig(model="deepseek-chat", temperature=0.7, max_tokens=100, top_p=1.0, api_key="api_key")
llm = DeepSeekLLM(config)
assert str(llm.client.base_url) == "https://api.deepseek.com"
# case2: with env variable DEEPSEEK_API_BASE
provider_base_url = "https://api.provider.com/v1/"
os.environ["DEEPSEEK_API_BASE"] = provider_base_url
config = BaseLlmConfig(model="deepseek-chat", temperature=0.7, max_tokens=100, top_p=1.0, api_key="api_key")
llm = DeepSeekLLM(config)
assert str(llm.client.base_url) == provider_base_url
# case3: with config.deepseek_base_url
config_base_url = "https://api.config.com/v1/"
config = BaseLlmConfig(
model="deepseek-chat",
temperature=0.7,
max_tokens=100,
top_p=1.0,
api_key="api_key",
deepseek_base_url=config_base_url
)
llm = DeepSeekLLM(config)
assert str(llm.client.base_url) == config_base_url
def test_generate_response_without_tools(mock_deepseek_client):
config = BaseLlmConfig(model="deepseek-chat", temperature=0.7, max_tokens=100, top_p=1.0)
llm = DeepSeekLLM(config)
messages = [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Hello, how are you?"},
]
mock_response = Mock()
mock_response.choices = [Mock(message=Mock(content="I'm doing well, thank you for asking!"))]
mock_deepseek_client.chat.completions.create.return_value = mock_response
response = llm.generate_response(messages)
mock_deepseek_client.chat.completions.create.assert_called_once_with(
model="deepseek-chat", messages=messages, temperature=0.7, max_tokens=100, top_p=1.0
)
assert response == "I'm doing well, thank you for asking!"
def test_generate_response_with_tools(mock_deepseek_client):
config = BaseLlmConfig(model="deepseek-chat", temperature=0.7, max_tokens=100, top_p=1.0)
llm = DeepSeekLLM(config)
messages = [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Add a new memory: Today is a sunny day."},
]
tools = [
{
"type": "function",
"function": {
"name": "add_memory",
"description": "Add a memory",
"parameters": {
"type": "object",
"properties": {"data": {"type": "string", "description": "Data to add to memory"}},
"required": ["data"],
},
},
}
]
mock_response = Mock()
mock_message = Mock()
mock_message.content = "I've added the memory for you."
mock_tool_call = Mock()
mock_tool_call.function.name = "add_memory"
mock_tool_call.function.arguments = '{"data": "Today is a sunny day."}'
mock_message.tool_calls = [mock_tool_call]
mock_response.choices = [Mock(message=mock_message)]
mock_deepseek_client.chat.completions.create.return_value = mock_response
response = llm.generate_response(messages, tools=tools)
mock_deepseek_client.chat.completions.create.assert_called_once_with(
model="deepseek-chat",
messages=messages,
temperature=0.7,
max_tokens=100,
top_p=1.0,
tools=tools,
tool_choice="auto"
)
assert response["content"] == "I've added the memory for you."
assert len(response["tool_calls"]) == 1
assert response["tool_calls"][0]["name"] == "add_memory"
assert response["tool_calls"][0]["arguments"] == {"data": "Today is a sunny day."}
+25 -34
View File
@@ -92,13 +92,11 @@ class TestElasticsearchDB(unittest.TestCase):
# Verify field mappings # Verify field mappings
mappings = create_args["body"]["mappings"]["properties"] mappings = create_args["body"]["mappings"]["properties"]
self.assertEqual(mappings["text"]["type"], "text") self.assertEqual(mappings["text"]["type"], "text")
self.assertEqual(mappings["embedding"]["type"], "dense_vector") self.assertEqual(mappings["vector"]["type"], "dense_vector")
self.assertEqual(mappings["embedding"]["dims"], 1536) self.assertEqual(mappings["vector"]["dims"], 1536)
self.assertEqual(mappings["embedding"]["index"], True) self.assertEqual(mappings["vector"]["index"], True)
self.assertEqual(mappings["embedding"]["similarity"], "cosine") self.assertEqual(mappings["vector"]["similarity"], "cosine")
self.assertEqual(mappings["metadata"]["type"], "object") self.assertEqual(mappings["metadata"]["type"], "object")
self.assertEqual(mappings["user_id"]["type"], "keyword")
self.assertEqual(mappings["hash"]["type"], "keyword")
# Reset mocks for next test # Reset mocks for next test
self.client_mock.reset_mock() self.client_mock.reset_mock()
@@ -170,8 +168,8 @@ class TestElasticsearchDB(unittest.TestCase):
self.assertEqual(len(actions), 2) self.assertEqual(len(actions), 2)
self.assertEqual(actions[0]["_index"], "test_collection") self.assertEqual(actions[0]["_index"], "test_collection")
self.assertEqual(actions[0]["_id"], "id1") self.assertEqual(actions[0]["_id"], "id1")
self.assertEqual(actions[0]["vector"], vectors[0]) self.assertEqual(actions[0]["_source"]["vector"], vectors[0])
self.assertEqual(actions[0]["payload"], payloads[0]) self.assertEqual(actions[0]["_source"]["metadata"], payloads[0])
# Verify returned objects # Verify returned objects
self.assertEqual(len(results), 2) self.assertEqual(len(results), 2)
@@ -189,34 +187,35 @@ class TestElasticsearchDB(unittest.TestCase):
"_score": 0.8, "_score": 0.8,
"_source": { "_source": {
"vector": [0.1] * 1536, "vector": [0.1] * 1536,
"payload": {"key1": "value1"} "metadata": {"key1": "value1"}
} }
} }
] ]
} }
} }
self.client_mock.search.return_value = mock_response self.client_mock.search.return_value = mock_response
# Perform search # Perform search
query_vector = [0.1] * 1536 query_vector = [0.1] * 1536
results = self.es_db.search(query=query_vector, limit=5) results = self.es_db.search(query=query_vector, limit=5)
# Verify search call # Verify search call
self.client_mock.search.assert_called_once() self.client_mock.search.assert_called_once()
search_args = self.client_mock.search.call_args[1] search_args = self.client_mock.search.call_args[1]
# Verify search parameters # Verify search parameters
self.assertEqual(search_args["index"], "test_collection") self.assertEqual(search_args["index"], "test_collection")
body = search_args["body"] body = search_args["body"]
self.assertIn("script_score", body["query"])
self.assertEqual(
body["query"]["script_score"]["script"]["params"]["query_vector"],
query_vector
)
# Verify KNN query structure
self.assertIn("knn", body)
self.assertEqual(body["knn"]["field"], "vector")
self.assertEqual(body["knn"]["query_vector"], query_vector)
self.assertEqual(body["knn"]["k"], 5)
self.assertEqual(body["knn"]["num_candidates"], 10)
# Verify results # Verify results
self.assertEqual(len(results), 1) self.assertEqual(len(results), 1)
self.assertIsInstance(results[0], OutputData)
self.assertEqual(results[0].id, "id1") self.assertEqual(results[0].id, "id1")
self.assertEqual(results[0].score, 0.8) self.assertEqual(results[0].score, 0.8)
self.assertEqual(results[0].payload, {"key1": "value1"}) self.assertEqual(results[0].payload, {"key1": "value1"})
@@ -227,10 +226,8 @@ class TestElasticsearchDB(unittest.TestCase):
"_id": "id1", "_id": "id1",
"_source": { "_source": {
"vector": [0.1] * 1536, "vector": [0.1] * 1536,
"payload": {"key": "value"}, "metadata": {"key": "value"},
"text": "sample text", "text": "sample text"
"user_id": "test_user",
"hash": "sample_hash"
} }
} }
self.client_mock.get.return_value = mock_response self.client_mock.get.return_value = mock_response
@@ -244,17 +241,11 @@ class TestElasticsearchDB(unittest.TestCase):
id="id1" id="id1"
) )
# Basic assertions that should pass if OutputData is created correctly # Verify result
self.assertIsNotNone(result) self.assertIsNotNone(result)
self.assertTrue(hasattr(result, 'id')) self.assertEqual(result.id, "id1")
self.assertTrue(hasattr(result, 'score')) self.assertEqual(result.score, 1.0)
self.assertTrue(hasattr(result, 'payload')) self.assertEqual(result.payload, {"key": "value"})
# If the above assertions pass, we can safely check the values
if result is not None: # This satisfies the linter
self.assertEqual(result.id, "id1")
self.assertEqual(result.score, 1.0)
self.assertEqual(result.payload, {"key": "value"})
def test_get_not_found(self): def test_get_not_found(self):
# Mock get raising exception # Mock get raising exception
@@ -273,7 +264,7 @@ class TestElasticsearchDB(unittest.TestCase):
"_id": "id1", "_id": "id1",
"_source": { "_source": {
"vector": [0.1] * 1536, "vector": [0.1] * 1536,
"payload": {"key1": "value1"} "metadata": {"key1": "value1"}
}, },
"_score": 1.0 "_score": 1.0
}, },
@@ -281,7 +272,7 @@ class TestElasticsearchDB(unittest.TestCase):
"_id": "id2", "_id": "id2",
"_source": { "_source": {
"vector": [0.2] * 1536, "vector": [0.2] * 1536,
"payload": {"key2": "value2"} "metadata": {"key2": "value2"}
}, },
"_score": 0.8 "_score": 0.8
} }
+150
View File
@@ -0,0 +1,150 @@
import os
import unittest
from unittest.mock import MagicMock, patch
import dotenv
try:
from opensearchpy import OpenSearch
except ImportError:
raise ImportError(
"OpenSearch requires extra dependencies. Install with `pip install opensearch-py`"
) from None
from mem0.vector_stores.opensearch import OpenSearchDB
class TestOpenSearchDB(unittest.TestCase):
@classmethod
def setUpClass(cls):
dotenv.load_dotenv()
cls.original_env = {
'OS_URL': os.getenv('OS_URL', 'http://localhost:9200'),
'OS_USERNAME': os.getenv('OS_USERNAME', 'test_user'),
'OS_PASSWORD': os.getenv('OS_PASSWORD', 'test_password')
}
os.environ['OS_URL'] = 'http://localhost'
os.environ['OS_USERNAME'] = 'test_user'
os.environ['OS_PASSWORD'] = 'test_password'
def setUp(self):
self.client_mock = MagicMock(spec=OpenSearch)
self.client_mock.indices = MagicMock()
self.client_mock.indices.exists = MagicMock(return_value=False)
self.client_mock.indices.create = MagicMock()
self.client_mock.indices.delete = MagicMock()
self.client_mock.indices.get_alias = MagicMock()
self.client_mock.get = MagicMock()
self.client_mock.update = MagicMock()
self.client_mock.delete = MagicMock()
self.client_mock.search = MagicMock()
patcher = patch('mem0.vector_stores.opensearch.OpenSearch', return_value=self.client_mock)
self.mock_os = patcher.start()
self.addCleanup(patcher.stop)
self.os_db = OpenSearchDB(
host=os.getenv('OS_URL'),
port=9200,
collection_name="test_collection",
embedding_model_dims=1536,
user=os.getenv('OS_USERNAME'),
password=os.getenv('OS_PASSWORD'),
verify_certs=False,
use_ssl=False,
auto_create_index=False
)
self.client_mock.reset_mock()
@classmethod
def tearDownClass(cls):
for key, value in cls.original_env.items():
if value is not None:
os.environ[key] = value
else:
os.environ.pop(key, None)
def tearDown(self):
self.client_mock.reset_mock()
def test_create_index(self):
self.client_mock.indices.exists.return_value = False
self.os_db.create_index()
self.client_mock.indices.create.assert_called_once()
create_args = self.client_mock.indices.create.call_args[1]
self.assertEqual(create_args["index"], "test_collection")
mappings = create_args["body"]["mappings"]["properties"]
self.assertEqual(mappings["vector"]["type"], "knn_vector")
self.assertEqual(mappings["vector"]["dimension"], 1536)
self.client_mock.reset_mock()
self.client_mock.indices.exists.return_value = True
self.os_db.create_index()
self.client_mock.indices.create.assert_not_called()
def test_insert(self):
vectors = [[0.1] * 1536, [0.2] * 1536]
payloads = [{"key1": "value1"}, {"key2": "value2"}]
ids = ["id1", "id2"]
with patch('mem0.vector_stores.opensearch.bulk') as mock_bulk:
mock_bulk.return_value = (2, [])
results = self.os_db.insert(vectors=vectors, payloads=payloads, ids=ids)
mock_bulk.assert_called_once()
actions = mock_bulk.call_args[0][1]
self.assertEqual(actions[0]["_index"], "test_collection")
self.assertEqual(actions[0]["_id"], "id1")
self.assertEqual(actions[0]["_source"]["vector"], vectors[0])
self.assertEqual(actions[0]["_source"]["metadata"], payloads[0])
self.assertEqual(len(results), 2)
self.assertEqual(results[0].id, "id1")
self.assertEqual(results[0].payload, payloads[0])
def test_get(self):
mock_response = {"_id": "id1", "_source": {"metadata": {"key1": "value1"}}}
self.client_mock.get.return_value = mock_response
result = self.os_db.get("id1")
self.client_mock.get.assert_called_once_with(index="test_collection", id="id1")
self.assertIsNotNone(result)
self.assertEqual(result.id, "id1")
self.assertEqual(result.payload, {"key1": "value1"})
def test_update(self):
vector = [0.3] * 1536
payload = {"key3": "value3"}
self.os_db.update("id1", vector=vector, payload=payload)
self.client_mock.update.assert_called_once()
update_args = self.client_mock.update.call_args[1]
self.assertEqual(update_args["index"], "test_collection")
self.assertEqual(update_args["id"], "id1")
self.assertEqual(update_args["body"], {"doc": {"vector": vector, "metadata": payload}})
def test_list_cols(self):
self.client_mock.indices.get_alias.return_value = {"test_collection": {}}
result = self.os_db.list_cols()
self.client_mock.indices.get_alias.assert_called_once()
self.assertEqual(result, ["test_collection"])
def test_search(self):
mock_response = {"hits": {"hits": [{"_id": "id1", "_score": 0.8, "_source": {"vector": [0.1] * 1536, "metadata": {"key1": "value1"}}}]}}
self.client_mock.search.return_value = mock_response
query_vector = [0.1] * 1536
results = self.os_db.search(query=query_vector, limit=5)
self.client_mock.search.assert_called_once()
search_args = self.client_mock.search.call_args[1]
self.assertEqual(search_args["index"], "test_collection")
body = search_args["body"]
self.assertIn("knn", body["query"])
self.assertIn("vector", body["query"]["knn"])
self.assertEqual(body["query"]["knn"]["vector"]["vector"], query_vector)
self.assertEqual(body["query"]["knn"]["vector"]["k"], 5)
self.assertEqual(len(results), 1)
self.assertEqual(results[0].id, "id1")
self.assertEqual(results[0].score, 0.8)
self.assertEqual(results[0].payload, {"key1": "value1"})
def test_delete(self):
self.os_db.delete(vector_id="id1")
self.client_mock.delete.assert_called_once_with(index="test_collection", id="id1")
def test_delete_col(self):
self.os_db.delete_col()
self.client_mock.indices.delete.assert_called_once_with(index="test_collection")