Compare commits

..
10 Commits
75 changed files with 1421 additions and 1062 deletions
+2 -2
View File
@@ -52,7 +52,7 @@ jobs:
virtualenvs-in-project: true
- name: Load cached venv
id: cached-poetry-dependencies
uses: actions/cache@v2
uses: actions/cache@v3
with:
path: .venv
key: venv-mem0-${{ runner.os }}-${{ hashFiles('**/poetry.lock') }}
@@ -83,7 +83,7 @@ jobs:
virtualenvs-in-project: true
- name: Load cached venv
id: cached-poetry-dependencies
uses: actions/cache@v2
uses: actions/cache@v3
with:
path: .venv
key: venv-embedchain-${{ runner.os }}-${{ hashFiles('**/poetry.lock') }}
+1 -1
View File
@@ -13,7 +13,7 @@ install:
install_all:
poetry install
poetry run pip install groq together boto3 litellm ollama chromadb sentence_transformers vertexai \
google-generativeai elasticsearch opensearch-py
google-generativeai elasticsearch opensearch-py vecs
# Format code with ruff
format:
+44 -13
View File
@@ -8,16 +8,18 @@ Config in mem0 is a dictionary that specifies the settings for your embedding mo
## How to define configurations?
The config is defined as a Python dictionary with two main keys:
The config is defined as an object (or dictionary) with two main keys:
- `embedder`: Specifies the embedder provider and its configuration
- `provider`: The name of the embedder (e.g., "openai", "ollama")
- `config`: A nested dictionary containing provider-specific settings
- `config`: A nested object or dictionary containing provider-specific settings
## How to use configurations?
Here's a general example of how to use the config with mem0:
```python
<CodeGroup>
```python Python
import os
from mem0 import Memory
@@ -36,6 +38,25 @@ m = Memory.from_config(config)
m.add("Your text here", user_id="user", metadata={"category": "example"})
```
```typescript TypeScript
import { Memory } from 'mem0ai/oss';
const config = {
embedder: {
provider: 'openai',
config: {
apiKey: process.env.OPENAI_API_KEY || '',
model: 'text-embedding-3-small',
// Provider-specific settings go here
},
},
};
const memory = new Memory(config);
await memory.add("Your text here", { userId: "user", metadata: { category: "example" } });
```
</CodeGroup>
## Why is Config Needed?
Config is essential for:
@@ -47,21 +68,31 @@ Config is essential for:
Here's a comprehensive list of all parameters that can be used across different embedders:
| Parameter | Description |
|-----------|-------------|
| `model` | Embedding model to use |
| `api_key` | API key of the provider |
| `embedding_dims` | Dimensions of the embedding model |
| `http_client_proxies` | Allow proxy server settings |
| `ollama_base_url` | Base URL for the Ollama embedding model |
| `model_kwargs` | Key-Value arguments for the Huggingface embedding model |
| `azure_kwargs` | Key-Value arguments for the AzureOpenAI embedding model |
<Tabs>
<Tab title="Python">
| Parameter | Description | Provider |
|-----------|-------------|----------|
| `model` | Embedding model to use | All |
| `api_key` | API key of the provider | All |
| `embedding_dims` | Dimensions of the embedding model | All |
| `http_client_proxies` | Allow proxy server settings | All |
| `ollama_base_url` | Base URL for the Ollama embedding model | Ollama |
| `model_kwargs` | Key-Value arguments for the Huggingface embedding model | Huggingface |
| `azure_kwargs` | Key-Value arguments for the AzureOpenAI embedding model | Azure OpenAI |
| `openai_base_url` | Base URL for OpenAI API | OpenAI |
| `vertex_credentials_json` | Path to the Google Cloud credentials JSON file for VertexAI | VertexAI |
| `memory_add_embedding_type` | The type of embedding to use for the add memory action | VertexAI |
| `memory_update_embedding_type` | The type of embedding to use for the update memory action | VertexAI |
| `memory_search_embedding_type` | The type of embedding to use for the search memory action | VertexAI |
</Tab>
<Tab title="TypeScript">
| Parameter | Description | Provider |
|-----------|-------------|----------|
| `model` | Embedding model to use | All |
| `apiKey` | API key of the provider | All |
| `embeddingDims` | Dimensions of the embedding model | All |
</Tab>
</Tabs>
## Supported Embedding Models
@@ -37,7 +37,13 @@ config = {
}
m = Memory.from_config(config)
m.add("I'm visiting Paris", user_id="john")
messages = [
{"role": "user", "content": "I'm planning to watch a movie tonight. Any recommendations?"},
{"role": "assistant", "content": "How about a thriller movies? They can be quite engaging."},
{"role": "user", "content": "I’m not a big fan of thriller movies but I love sci-fi movies."},
{"role": "assistant", "content": "Got it! I'll avoid thriller recommendations and suggest sci-fi movies in the future."}
]
m.add(messages, user_id="john")
```
### Config
+7 -1
View File
@@ -23,7 +23,13 @@ config = {
}
m = Memory.from_config(config)
m.add("I'm visiting Paris", user_id="john")
messages = [
{"role": "user", "content": "I'm planning to watch a movie tonight. Any recommendations?"},
{"role": "assistant", "content": "How about a thriller movies? They can be quite engaging."},
{"role": "user", "content": "I’m not a big fan of thriller movies but I love sci-fi movies."},
{"role": "assistant", "content": "Got it! I'll avoid thriller recommendations and suggest sci-fi movies in the future."}
]
m.add(messages, user_id="john")
```
### Config
@@ -22,7 +22,13 @@ config = {
}
m = Memory.from_config(config)
m.add("I'm visiting Paris", user_id="john")
messages = [
{"role": "user", "content": "I'm planning to watch a movie tonight. Any recommendations?"},
{"role": "assistant", "content": "How about a thriller movies? They can be quite engaging."},
{"role": "user", "content": "I’m not a big fan of thriller movies but I love sci-fi movies."},
{"role": "assistant", "content": "Got it! I'll avoid thriller recommendations and suggest sci-fi movies in the future."}
]
m.add(messages, user_id="john")
```
### Config
+7 -1
View File
@@ -18,7 +18,13 @@ config = {
}
m = Memory.from_config(config)
m.add("I'm visiting Paris", user_id="john")
messages = [
{"role": "user", "content": "I'm planning to watch a movie tonight. Any recommendations?"},
{"role": "assistant", "content": "How about a thriller movies? They can be quite engaging."},
{"role": "user", "content": "I’m not a big fan of thriller movies but I love sci-fi movies."},
{"role": "assistant", "content": "Got it! I'll avoid thriller recommendations and suggest sci-fi movies in the future."}
]
m.add(messages, user_id="john")
```
### Config
+38 -2
View File
@@ -6,7 +6,8 @@ To use OpenAI embedding models, set the `OPENAI_API_KEY` environment variable. Y
### Usage
```python
<CodeGroup>
```python Python
import os
from mem0 import Memory
@@ -22,15 +23,50 @@ config = {
}
m = Memory.from_config(config)
m.add("I'm visiting Paris", user_id="john")
messages = [
{"role": "user", "content": "I'm planning to watch a movie tonight. Any recommendations?"},
{"role": "assistant", "content": "How about a thriller movies? They can be quite engaging."},
{"role": "user", "content": "I’m not a big fan of thriller movies but I love sci-fi movies."},
{"role": "assistant", "content": "Got it! I'll avoid thriller recommendations and suggest sci-fi movies in the future."}
]
m.add(messages, user_id="john")
```
```typescript TypeScript
import { Memory } from 'mem0ai/oss';
const config = {
embedder: {
provider: 'openai',
config: {
apiKey: 'your-openai-api-key',
model: 'text-embedding-3-large',
},
},
};
const memory = new Memory(config);
await memory.add("I'm visiting Paris", { userId: "john" });
```
</CodeGroup>
### Config
Here are the parameters available for configuring OpenAI embedder:
<Tabs>
<Tab title="Python">
| Parameter | Description | Default Value |
| --- | --- | --- |
| `model` | The name of the embedding model to use | `text-embedding-3-small` |
| `embedding_dims` | Dimensions of the embedding model | `1536` |
| `api_key` | The OpenAI API key | `None` |
</Tab>
<Tab title="TypeScript">
| Parameter | Description | Default Value |
| --- | --- | --- |
| `model` | The name of the embedding model to use | `text-embedding-3-small` |
| `embeddingDims` | Dimensions of the embedding model | `1536` |
| `apiKey` | The OpenAI API key | `None` |
</Tab>
</Tabs>
@@ -25,7 +25,13 @@ config = {
}
m = Memory.from_config(config)
m.add("I'm visiting Paris", user_id="john")
messages = [
{"role": "user", "content": "I'm planning to watch a movie tonight. Any recommendations?"},
{"role": "assistant", "content": "How about a thriller movies? They can be quite engaging."},
{"role": "user", "content": "I’m not a big fan of thriller movies but I love sci-fi movies."},
{"role": "assistant", "content": "Got it! I'll avoid thriller recommendations and suggest sci-fi movies in the future."}
]
m.add(messages, user_id="john")
```
### Config
@@ -25,7 +25,13 @@ config = {
}
m = Memory.from_config(config)
m.add("I'm visiting Paris", user_id="john")
messages = [
{"role": "user", "content": "I'm planning to watch a movie tonight. Any recommendations?"},
{"role": "assistant", "content": "How about a thriller movies? They can be quite engaging."},
{"role": "user", "content": "I’m not a big fan of thriller movies but I love sci-fi movies."},
{"role": "assistant", "content": "Got it! I'll avoid thriller recommendations and suggest sci-fi movies in the future."}
]
m.add(messages, user_id="john")
```
The embedding types can be one of the following:
- SEMANTIC_SIMILARITY
+4
View File
@@ -10,6 +10,10 @@ Mem0 offers support for various embedding models, allowing users to choose the o
See the list of supported embedders below.
<Note>
The following embedders are supported in the Python implementation. The TypeScript implementation currently only supports OpenAI.
</Note>
<CardGroup cols={4}>
<Card title="OpenAI" href="/components/embedders/models/openai"></Card>
<Card title="Azure OpenAI" href="/components/embedders/models/azure_openai"></Card>
+78 -33
View File
@@ -6,26 +6,40 @@ iconType: "solid"
## How to define configurations?
The `config` is defined as a Python dictionary with two main keys:
- `llm`: Specifies the llm provider and its configuration
- `provider`: The name of the llm (e.g., "openai", "groq")
- `config`: A nested dictionary containing provider-specific settings
<Tabs>
<Tab title="Python">
The `config` is defined as a Python dictionary with two main keys:
- `llm`: Specifies the llm provider and its configuration
- `provider`: The name of the llm (e.g., "openai", "groq")
- `config`: A nested dictionary containing provider-specific settings
</Tab>
<Tab title="TypeScript">
The `config` is defined as a TypeScript object with these keys:
- `llm`: Specifies the LLM provider and its configuration (required)
- `provider`: The name of the LLM (e.g., "openai", "groq")
- `config`: A nested object containing provider-specific settings
- `embedder`: Specifies the embedder provider and its configuration (optional)
- `vectorStore`: Specifies the vector store provider and its configuration (optional)
- `historyDbPath`: Path to the history database file (optional)
</Tab>
</Tabs>
### Config Values Precedence
Config values are applied in the following order of precedence (from highest to lowest):
1. Values explicitly set in the `config` dictionary
1. Values explicitly set in the `config` object/dictionary
2. Environment variables (e.g., `OPENAI_API_KEY`, `OPENAI_API_BASE`)
3. Default values defined in the LLM implementation
This means that values specified in the `config` dictionary will override corresponding environment variables, which in turn override default values.
This means that values specified in the `config` will override corresponding environment variables, which in turn override default values.
## How to Use Config
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:
```python
<CodeGroup>
```python Python
import os
from mem0 import Memory
@@ -44,39 +58,70 @@ m = Memory.from_config(config)
m.add("Your text here", user_id="user", metadata={"category": "example"})
```
```typescript TypeScript
import { Memory } from 'mem0ai/oss';
// Minimal configuration with just the LLM settings
const config = {
llm: {
provider: 'your_chosen_provider',
config: {
// Provider-specific settings go here
}
}
};
const memory = new Memory(config);
await memory.add("Your text here", { userId: "user123", metadata: { category: "example" } });
```
</CodeGroup>
## Why is Config Needed?
Config is essential for:
1. Specifying which llm to use.
1. Specifying which LLM to use.
2. Providing necessary connection details (e.g., model, api_key, temperature).
3. Ensuring proper initialization and connection to your chosen llm.
3. Ensuring proper initialization and connection to your chosen LLM.
## Master List of All Params in Config
Here's a comprehensive list of all parameters that can be used across different llms:
Here's a comprehensive list of all parameters that can be used across different LLMs:
Here's the table based on the provided parameters:
| Parameter | Description | Provider |
|----------------------|-----------------------------------------------|-------------------|
| `model` | Embedding 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 |
| `xai_base_url` | Base URL for XAI API | XAI |
<Tabs>
<Tab title="Python">
| Parameter | Description | Provider |
|----------------------|-----------------------------------------------|-------------------|
| `model` | Embedding 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 |
| `xai_base_url` | Base URL for XAI API | XAI |
</Tab>
<Tab title="TypeScript">
| Parameter | Description | Provider |
|----------------------|-----------------------------------------------|-------------------|
| `model` | Embedding model to use | All |
| `temperature` | Temperature of the model | All |
| `apiKey` | API key to use | All |
| `maxTokens` | Tokens to generate | All |
| `topP` | Probability threshold for nucleus sampling | All |
| `topK` | Number of highest probability tokens to keep | All |
| `openaiBaseUrl` | Base URL for OpenAI API | OpenAI |
</Tab>
</Tabs>
## Supported LLMs
For detailed information on configuring specific llms, please visit the [LLMs](./models) section. There you'll find information for each supported llm with provider-specific usage examples and configuration details.
For detailed information on configuring specific LLMs, please visit the [LLMs](./models) section. There you'll find information for each supported LLM with provider-specific usage examples and configuration details.
+39 -2
View File
@@ -1,8 +1,13 @@
---
title: Anthropic
---
To use anthropic's models, please set the `ANTHROPIC_API_KEY` which you find on their [Account Settings Page](https://console.anthropic.com/account/keys).
## Usage
```python
<CodeGroup>
```python Python
import os
from mem0 import Memory
@@ -21,9 +26,41 @@ config = {
}
m = Memory.from_config(config)
m.add("Likes to play cricket on weekends", user_id="alice", metadata={"category": "hobbies"})
messages = [
{"role": "user", "content": "I'm planning to watch a movie tonight. Any recommendations?"},
{"role": "assistant", "content": "How about a thriller movies? They can be quite engaging."},
{"role": "user", "content": "I’m not a big fan of thriller movies but I love sci-fi movies."},
{"role": "assistant", "content": "Got it! I'll avoid thriller recommendations and suggest sci-fi movies in the future."}
]
m.add(messages, user_id="alice", metadata={"category": "movies"})
```
```typescript TypeScript
import { Memory } from 'mem0ai/oss';
const config = {
llm: {
provider: 'anthropic',
config: {
apiKey: process.env.ANTHROPIC_API_KEY || '',
model: 'claude-3-7-sonnet-latest',
temperature: 0.1,
maxTokens: 2000,
},
},
};
const memory = new Memory(config);
const messages = [
{"role": "user", "content": "I'm planning to watch a movie tonight. Any recommendations?"},
{"role": "assistant", "content": "How about a thriller movies? They can be quite engaging."},
{"role": "user", "content": "I’m not a big fan of thriller movies but I love sci-fi movies."},
{"role": "assistant", "content": "Got it! I'll avoid thriller recommendations and suggest sci-fi movies in the future."}
]
await memory.add(messages, { userId: "alice", metadata: { category: "movies" } });
```
</CodeGroup>
## Config
All available parameters for the `anthropic` config are present in [Master List of All Params in Config](../config).
+7 -1
View File
@@ -30,7 +30,13 @@ config = {
}
m = Memory.from_config(config)
m.add("Likes to play cricket on weekends", user_id="alice", metadata={"category": "hobbies"})
messages = [
{"role": "user", "content": "I'm planning to watch a movie tonight. Any recommendations?"},
{"role": "assistant", "content": "How about a thriller movies? They can be quite engaging."},
{"role": "user", "content": "I’m not a big fan of thriller movies but I love sci-fi movies."},
{"role": "assistant", "content": "Got it! I'll avoid thriller recommendations and suggest sci-fi movies in the future."}
]
m.add(messages, user_id="alice", metadata={"category": "movies"})
```
### Config
+7 -1
View File
@@ -36,7 +36,13 @@ config = {
}
m = Memory.from_config(config)
m.add("Likes to play cricket on weekends", user_id="alice", metadata={"category": "hobbies"})
messages = [
{"role": "user", "content": "I'm planning to watch a movie tonight. Any recommendations?"},
{"role": "assistant", "content": "How about a thriller movies? They can be quite engaging."},
{"role": "user", "content": "I’m not a big fan of thriller movies but I love sci-fi movies."},
{"role": "assistant", "content": "Got it! I'll avoid thriller recommendations and suggest sci-fi movies in the future."}
]
m.add(messages, user_id="alice", metadata={"category": "movies"})
```
We also support the new [OpenAI structured-outputs](https://platform.openai.com/docs/guides/structured-outputs/introduction) model.
+7 -1
View File
@@ -26,7 +26,13 @@ config = {
}
m = Memory.from_config(config)
m.add("Likes to play cricket on weekends", user_id="alice", metadata={"category": "hobbies"})
messages = [
{"role": "user", "content": "I'm planning to watch a movie tonight. Any recommendations?"},
{"role": "assistant", "content": "How about a thriller movies? They can be quite engaging."},
{"role": "user", "content": "I’m not a big fan of thriller movies but I love sci-fi movies."},
{"role": "assistant", "content": "Got it! I'll avoid thriller recommendations and suggest sci-fi movies in the future."}
]
m.add(messages, user_id="alice", metadata={"category": "movies"})
```
You can also configure the API base URL in the config:
+7 -1
View File
@@ -25,7 +25,13 @@ config = {
}
m = Memory.from_config(config)
m.add("Likes to play cricket on weekends", user_id="alice", metadata={"category": "hobbies"})
messages = [
{"role": "user", "content": "I'm planning to watch a movie tonight. Any recommendations?"},
{"role": "assistant", "content": "How about a thriller movies? They can be quite engaging."},
{"role": "user", "content": "I’m not a big fan of thriller movies but I love sci-fi movies."},
{"role": "assistant", "content": "Got it! I'll avoid thriller recommendations and suggest sci-fi movies in the future."}
]
m.add(messages, user_id="alice", metadata={"category": "movies"})
```
## Config
+7 -1
View File
@@ -25,7 +25,13 @@ config = {
}
m = Memory.from_config(config)
m.add("Likes to play cricket on weekends", user_id="alice", metadata={"category": "hobbies"})
messages = [
{"role": "user", "content": "I'm planning to watch a movie tonight. Any recommendations?"},
{"role": "assistant", "content": "How about a thriller movies? They can be quite engaging."},
{"role": "user", "content": "I’m not a big fan of thriller movies but I love sci-fi movies."},
{"role": "assistant", "content": "Got it! I'll avoid thriller recommendations and suggest sci-fi movies in the future."}
]
m.add(messages, user_id="alice", metadata={"category": "movies"})
```
## Config
+39 -2
View File
@@ -1,10 +1,15 @@
---
title: Groq
---
[Groq](https://groq.com/) is the creator of the world's first Language Processing Unit (LPU), providing exceptional speed performance for AI workloads running on their LPU Inference Engine.
In order to use LLMs from Groq, go to their [platform](https://console.groq.com/keys) and get the API key. Set the API key as `GROQ_API_KEY` environment variable to use the model as given below in the example.
## Usage
```python
<CodeGroup>
```python Python
import os
from mem0 import Memory
@@ -23,9 +28,41 @@ config = {
}
m = Memory.from_config(config)
m.add("Likes to play cricket on weekends", user_id="alice", metadata={"category": "hobbies"})
messages = [
{"role": "user", "content": "I'm planning to watch a movie tonight. Any recommendations?"},
{"role": "assistant", "content": "How about a thriller movies? They can be quite engaging."},
{"role": "user", "content": "I’m not a big fan of thriller movies but I love sci-fi movies."},
{"role": "assistant", "content": "Got it! I'll avoid thriller recommendations and suggest sci-fi movies in the future."}
]
m.add(messages, user_id="alice", metadata={"category": "movies"})
```
```typescript TypeScript
import { Memory } from 'mem0ai/oss';
const config = {
llm: {
provider: 'groq',
config: {
apiKey: process.env.GROQ_API_KEY || '',
model: 'mixtral-8x7b-32768',
temperature: 0.1,
maxTokens: 1000,
},
},
};
const memory = new Memory(config);
const messages = [
{"role": "user", "content": "I'm planning to watch a movie tonight. Any recommendations?"},
{"role": "assistant", "content": "How about a thriller movies? They can be quite engaging."},
{"role": "user", "content": "I’m not a big fan of thriller movies but I love sci-fi movies."},
{"role": "assistant", "content": "Got it! I'll avoid thriller recommendations and suggest sci-fi movies in the future."}
]
await memory.add(messages, { userId: "alice", metadata: { category: "movies" } });
```
</CodeGroup>
## Config
All available parameters for the `groq` config are present in [Master List of All Params in Config](../config).
+7 -1
View File
@@ -20,7 +20,13 @@ config = {
}
m = Memory.from_config(config)
m.add("Likes to play cricket on weekends", user_id="alice", metadata={"category": "hobbies"})
messages = [
{"role": "user", "content": "I'm planning to watch a movie tonight. Any recommendations?"},
{"role": "assistant", "content": "How about a thriller movies? They can be quite engaging."},
{"role": "user", "content": "I’m not a big fan of thriller movies but I love sci-fi movies."},
{"role": "assistant", "content": "Got it! I'll avoid thriller recommendations and suggest sci-fi movies in the future."}
]
m.add(messages, user_id="alice", metadata={"category": "movies"})
```
## Config
+7 -1
View File
@@ -25,7 +25,13 @@ config = {
}
m = Memory.from_config(config)
m.add("Likes to play cricket on weekends", user_id="alice", metadata={"category": "hobbies"})
messages = [
{"role": "user", "content": "I'm planning to watch a movie tonight. Any recommendations?"},
{"role": "assistant", "content": "How about a thriller movies? They can be quite engaging."},
{"role": "user", "content": "I’m not a big fan of thriller movies but I love sci-fi movies."},
{"role": "assistant", "content": "Got it! I'll avoid thriller recommendations and suggest sci-fi movies in the future."}
]
m.add(messages, user_id="alice", metadata={"category": "movies"})
```
## Config
+7 -1
View File
@@ -20,7 +20,13 @@ config = {
}
m = Memory.from_config(config)
m.add("Likes to play cricket on weekends", user_id="alice", metadata={"category": "hobbies"})
messages = [
{"role": "user", "content": "I'm planning to watch a movie tonight. Any recommendations?"},
{"role": "assistant", "content": "How about a thriller movies? They can be quite engaging."},
{"role": "user", "content": "I’m not a big fan of thriller movies but I love sci-fi movies."},
{"role": "assistant", "content": "Got it! I'll avoid thriller recommendations and suggest sci-fi movies in the future."}
]
m.add(messages, user_id="alice", metadata={"category": "movies"})
```
## Config
+38 -3
View File
@@ -6,7 +6,8 @@ To use OpenAI LLM models, you have to set the `OPENAI_API_KEY` environment varia
## Usage
```python
<CodeGroup>
```python Python
import os
from mem0 import Memory
@@ -35,9 +36,41 @@ config = {
# }
m = Memory.from_config(config)
m.add("Likes to play cricket on weekends", user_id="alice", metadata={"category": "hobbies"})
messages = [
{"role": "user", "content": "I'm planning to watch a movie tonight. Any recommendations?"},
{"role": "assistant", "content": "How about a thriller movies? They can be quite engaging."},
{"role": "user", "content": "I’m not a big fan of thriller movies but I love sci-fi movies."},
{"role": "assistant", "content": "Got it! I'll avoid thriller recommendations and suggest sci-fi movies in the future."}
]
m.add(messages, user_id="alice", metadata={"category": "movies"})
```
```typescript TypeScript
import { Memory } from 'mem0ai/oss';
const config = {
llm: {
provider: 'openai',
config: {
apiKey: process.env.OPENAI_API_KEY || '',
model: 'gpt-4-turbo-preview',
temperature: 0.2,
maxTokens: 1500,
},
},
};
const memory = new Memory(config);
const messages = [
{"role": "user", "content": "I'm planning to watch a movie tonight. Any recommendations?"},
{"role": "assistant", "content": "How about a thriller movies? They can be quite engaging."},
{"role": "user", "content": "I’m not a big fan of thriller movies but I love sci-fi movies."},
{"role": "assistant", "content": "Got it! I'll avoid thriller recommendations and suggest sci-fi movies in the future."}
]
await memory.add(messages, { userId: "alice", metadata: { category: "movies" } });
```
</CodeGroup>
We also support the new [OpenAI structured-outputs](https://platform.openai.com/docs/guides/structured-outputs/introduction) model.
```python
@@ -59,7 +92,9 @@ config = {
m = Memory.from_config(config)
```
<Note>
OpenAI structured-outputs is currently only available in the Python implementation.
</Note>
## Config
+7 -1
View File
@@ -21,7 +21,13 @@ config = {
}
m = Memory.from_config(config)
m.add("Likes to play cricket on weekends", user_id="alice", metadata={"category": "hobbies"})
messages = [
{"role": "user", "content": "I'm planning to watch a movie tonight. Any recommendations?"},
{"role": "assistant", "content": "How about a thriller movies? They can be quite engaging."},
{"role": "user", "content": "I’m not a big fan of thriller movies but I love sci-fi movies."},
{"role": "assistant", "content": "Got it! I'll avoid thriller recommendations and suggest sci-fi movies in the future."}
]
m.add(messages, user_id="alice", metadata={"category": "movies"})
```
## Config
+7 -1
View File
@@ -27,7 +27,13 @@ config = {
}
m = Memory.from_config(config)
m.add("Likes to play cricket on weekends", user_id="alice", metadata={"category": "hobbies"})
messages = [
{"role": "user", "content": "I'm planning to watch a movie tonight. Any recommendations?"},
{"role": "assistant", "content": "How about a thriller movies? They can be quite engaging."},
{"role": "user", "content": "I’m not a big fan of thriller movies but I love sci-fi movies."},
{"role": "assistant", "content": "Got it! I'll avoid thriller recommendations and suggest sci-fi movies in the future."}
]
m.add(messages, user_id="alice", metadata={"category": "movies"})
```
## Config
+17 -13
View File
@@ -14,20 +14,24 @@ For a comprehensive list of available parameters for llm configuration, please r
To view all supported llms, visit the [Supported LLMs](./models).
<Note>
All LLMs are supported in Python. The following LLMs are also supported in TypeScript: **OpenAI**, **Anthropic**, and **Groq**.
</Note>
<CardGroup cols={4}>
<Card title="OpenAI" href="/components/llms/models/openai"></Card>
<Card title="Ollama" href="/components/llms/models/ollama"></Card>
<Card title="Azure OpenAI" href="/components/llms/models/azure_openai"></Card>
<Card title="Anthropic" href="/components/llms/models/anthropic"></Card>
<Card title="Together" href="/components/llms/models/together"></Card>
<Card title="Groq" href="/components/llms/models/groq"></Card>
<Card title="Litellm" href="/components/llms/models/litellm"></Card>
<Card title="Mistral AI" href="/components/llms/models/mistral_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="Gemini" href="/components/llms/models/gemini"></Card>
<Card title="DeepSeek" href="/components/llms/models/deepseek"></Card>
<Card title="xAI" href="/components/llms/models/xAI"></Card>
<Card title="OpenAI" href="/components/llms/models/openai" />
<Card title="Ollama" href="/components/llms/models/ollama" />
<Card title="Azure OpenAI" href="/components/llms/models/azure_openai" />
<Card title="Anthropic" href="/components/llms/models/anthropic" />
<Card title="Together" href="/components/llms/models/together" />
<Card title="Groq" href="/components/llms/models/groq" />
<Card title="Litellm" href="/components/llms/models/litellm" />
<Card title="Mistral AI" href="/components/llms/models/mistral_ai" />
<Card title="Google AI" href="/components/llms/models/google_ai" />
<Card title="AWS bedrock" href="/components/llms/models/aws_bedrock" />
<Card title="Gemini" href="/components/llms/models/gemini" />
<Card title="DeepSeek" href="/components/llms/models/deepseek" />
<Card title="xAI" href="/components/llms/models/xAI" />
</CardGroup>
## Structured vs Unstructured Outputs
+51 -4
View File
@@ -6,16 +6,17 @@ iconType: "solid"
## How to define configurations?
The `config` is defined as a Python dictionary with two main keys:
The `config` is defined as an object with two main keys:
- `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")
- `config`: A nested dictionary containing provider-specific settings
- `provider`: The name of the vector database (e.g., "chroma", "pgvector", "qdrant", "milvus", "azure_ai_search")
- `config`: A nested object containing provider-specific settings
## How to Use Config
Here's a general example of how to use the config with mem0:
```python
<CodeGroup>
```python Python
import os
from mem0 import Memory
@@ -34,6 +35,29 @@ m = Memory.from_config(config)
m.add("Your text here", user_id="user", metadata={"category": "example"})
```
```typescript TypeScript
// Example for in-memory vector database (Only supported in TypeScript)
import { Memory } from 'mem0ai/oss';
const configMemory = {
vector_store: {
provider: 'memory',
config: {
collectionName: 'memories',
dimension: 1536,
},
},
};
const memory = new Memory(configMemory);
await memory.add("Your text here", { userId: "user", metadata: { category: "example" } });
```
</CodeGroup>
<Note>
The in-memory vector database is only supported in the TypeScript implementation.
</Note>
## Why is Config Needed?
Config is essential for:
@@ -46,6 +70,8 @@ Config is essential for:
Here's a comprehensive list of all parameters that can be used across different vector databases:
<Tabs>
<Tab title="Python">
| Parameter | Description |
|-----------|-------------|
| `collection_name` | Name of the collection |
@@ -60,6 +86,27 @@ Here's a comprehensive list of all parameters that can be used across different
| `url` | Full URL for the server |
| `api_key` | API key for the server |
| `on_disk` | Enable persistent storage |
| `connection_string` | PostgreSQL connection string (for Supabase/PGVector) |
| `index_method` | Vector index method (for Supabase) |
| `index_measure` | Distance measure for similarity search (for Supabase) |
</Tab>
<Tab title="TypeScript">
| Parameter | Description |
|-----------|-------------|
| `collectionName` | Name of the collection |
| `embeddingModelDims` | Dimensions of the embedding model |
| `dimension` | Dimensions of the embedding model (for memory provider) |
| `host` | Host where the server is running |
| `port` | Port where the server is running |
| `url` | URL for the server |
| `apiKey` | API key for the server |
| `path` | Path for the database |
| `onDisk` | Enable persistent storage |
| `redisUrl` | URL for the Redis server |
| `username` | Username for database connection |
| `password` | Password for database connection |
</Tab>
</Tabs>
## Customizing Config
@@ -22,7 +22,13 @@ config = {
}
m = Memory.from_config(config)
m.add("Likes to play cricket on weekends", user_id="alice", metadata={"category": "hobbies"})
messages = [
{"role": "user", "content": "I'm planning to watch a movie tonight. Any recommendations?"},
{"role": "assistant", "content": "How about a thriller movies? They can be quite engaging."},
{"role": "user", "content": "I’m not a big fan of thriller movies but I love sci-fi movies."},
{"role": "assistant", "content": "Got it! I'll avoid thriller recommendations and suggest sci-fi movies in the future."}
]
m.add(messages, user_id="alice", metadata={"category": "movies"})
```
### Config
+7 -1
View File
@@ -19,7 +19,13 @@ config = {
}
m = Memory.from_config(config)
m.add("Likes to play cricket on weekends", user_id="alice", metadata={"category": "hobbies"})
messages = [
{"role": "user", "content": "I'm planning to watch a movie tonight. Any recommendations?"},
{"role": "assistant", "content": "How about a thriller movies? They can be quite engaging."},
{"role": "user", "content": "I’m not a big fan of thriller movies but I love sci-fi movies."},
{"role": "assistant", "content": "Got it! I'll avoid thriller recommendations and suggest sci-fi movies in the future."}
]
m.add(messages, user_id="alice", metadata={"category": "movies"})
```
### Config
@@ -29,7 +29,13 @@ config = {
}
m = Memory.from_config(config)
m.add("Likes to play cricket on weekends", user_id="alice", metadata={"category": "hobbies"})
messages = [
{"role": "user", "content": "I'm planning to watch a movie tonight. Any recommendations?"},
{"role": "assistant", "content": "How about a thriller movies? They can be quite engaging."},
{"role": "user", "content": "I’m not a big fan of thriller movies but I love sci-fi movies."},
{"role": "assistant", "content": "Got it! I'll avoid thriller recommendations and suggest sci-fi movies in the future."}
]
m.add(messages, user_id="alice", metadata={"category": "movies"})
```
### Config
+7 -1
View File
@@ -19,7 +19,13 @@ config = {
}
m = Memory.from_config(config)
m.add("Likes to play cricket on weekends", user_id="alice", metadata={"category": "hobbies"})
messages = [
{"role": "user", "content": "I'm planning to watch a movie tonight. Any recommendations?"},
{"role": "assistant", "content": "How about a thriller movies? They can be quite engaging."},
{"role": "user", "content": "I’m not a big fan of thriller movies but I love sci-fi movies."},
{"role": "assistant", "content": "Got it! I'll avoid thriller recommendations and suggest sci-fi movies in the future."}
]
m.add(messages, user_id="alice", metadata={"category": "movies"})
```
### Config
+7 -1
View File
@@ -29,7 +29,13 @@ config = {
}
m = Memory.from_config(config)
m.add("Likes to play cricket on weekends", user_id="alice", metadata={"category": "hobbies"})
messages = [
{"role": "user", "content": "I'm planning to watch a movie tonight. Any recommendations?"},
{"role": "assistant", "content": "How about a thriller movies? They can be quite engaging."},
{"role": "user", "content": "I’m not a big fan of thriller movies but I love sci-fi movies."},
{"role": "assistant", "content": "Got it! I'll avoid thriller recommendations and suggest sci-fi movies in the future."}
]
m.add(messages, user_id="alice", metadata={"category": "movies"})
```
### Config
+7 -1
View File
@@ -21,7 +21,13 @@ config = {
}
m = Memory.from_config(config)
m.add("Likes to play cricket on weekends", user_id="alice", metadata={"category": "hobbies"})
messages = [
{"role": "user", "content": "I'm planning to watch a movie tonight. Any recommendations?"},
{"role": "assistant", "content": "How about a thriller movies? They can be quite engaging."},
{"role": "user", "content": "I’m not a big fan of thriller movies but I love sci-fi movies."},
{"role": "assistant", "content": "Got it! I'll avoid thriller recommendations and suggest sci-fi movies in the future."}
]
m.add(messages, user_id="alice", metadata={"category": "movies"})
```
### Config
+52 -3
View File
@@ -2,7 +2,8 @@
### Usage
```python
<CodeGroup>
```python Python
import os
from mem0 import Memory
@@ -20,13 +21,47 @@ config = {
}
m = Memory.from_config(config)
m.add("Likes to play cricket on weekends", user_id="alice", metadata={"category": "hobbies"})
messages = [
{"role": "user", "content": "I'm planning to watch a movie tonight. Any recommendations?"},
{"role": "assistant", "content": "How about a thriller movies? They can be quite engaging."},
{"role": "user", "content": "I’m not a big fan of thriller movies but I love sci-fi movies."},
{"role": "assistant", "content": "Got it! I'll avoid thriller recommendations and suggest sci-fi movies in the future."}
]
m.add(messages, user_id="alice", metadata={"category": "movies"})
```
```typescript TypeScript
import { Memory } from 'mem0ai/oss';
const config = {
vectorStore: {
provider: 'qdrant',
config: {
collectionName: 'memories',
embeddingModelDims: 1536,
host: 'localhost',
port: 6333,
},
},
};
const memory = new Memory(config);
const messages = [
{"role": "user", "content": "I'm planning to watch a movie tonight. Any recommendations?"},
{"role": "assistant", "content": "How about a thriller movies? They can be quite engaging."},
{"role": "user", "content": "I’m not a big fan of thriller movies but I love sci-fi movies."},
{"role": "assistant", "content": "Got it! I'll avoid thriller recommendations and suggest sci-fi movies in the future."}
]
await memory.add(messages, { userId: "alice", metadata: { category: "movies" } });
```
</CodeGroup>
### Config
Let's see the available parameters for the `qdrant` config:
<Tabs>
<Tab title="Python">
| Parameter | Description | Default Value |
| --- | --- | --- |
| `collection_name` | The name of the collection to store the vectors | `mem0` |
@@ -37,4 +72,18 @@ Let's see the available parameters for the `qdrant` config:
| `path` | Path for the qdrant database | `/tmp/qdrant` |
| `url` | Full URL for the qdrant server | `None` |
| `api_key` | API key for the qdrant server | `None` |
| `on_disk` | For enabling persistent storage | `False` |
| `on_disk` | For enabling persistent storage | `False` |
</Tab>
<Tab title="TypeScript">
| Parameter | Description | Default Value |
| --- | --- | --- |
| `collectionName` | The name of the collection to store the vectors | `mem0` |
| `embeddingModelDims` | Dimensions of the embedding model | `1536` |
| `host` | The host where the Qdrant server is running | `None` |
| `port` | The port where the Qdrant server is running | `None` |
| `path` | Path for the Qdrant database | `/tmp/qdrant` |
| `url` | Full URL for the Qdrant server | `None` |
| `apiKey` | API key for the Qdrant server | `None` |
| `onDisk` | For enabling persistent storage | `False` |
</Tab>
</Tabs>
+50 -3
View File
@@ -12,7 +12,8 @@ docker run -d --name redis-stack -p 6379:6379 -p 8001:8001 redis/redis-stack:lat
### Usage
```python
<CodeGroup>
```python Python
import os
from mem0 import Memory
@@ -31,15 +32,61 @@ config = {
}
m = Memory.from_config(config)
m.add("Likes to play cricket on weekends", user_id="alice", metadata={"category": "hobbies"})
messages = [
{"role": "user", "content": "I'm planning to watch a movie tonight. Any recommendations?"},
{"role": "assistant", "content": "How about a thriller movies? They can be quite engaging."},
{"role": "user", "content": "I’m not a big fan of thriller movies but I love sci-fi movies."},
{"role": "assistant", "content": "Got it! I'll avoid thriller recommendations and suggest sci-fi movies in the future."}
]
m.add(messages, user_id="alice", metadata={"category": "movies"})
```
```typescript TypeScript
import { Memory } from 'mem0ai/oss';
const config = {
vectorStore: {
provider: 'redis',
config: {
collectionName: 'memories',
embeddingModelDims: 1536,
redisUrl: 'redis://localhost:6379',
username: 'your-redis-username',
password: 'your-redis-password',
},
},
};
const memory = new Memory(config);
const messages = [
{"role": "user", "content": "I'm planning to watch a movie tonight. Any recommendations?"},
{"role": "assistant", "content": "How about a thriller movies? They can be quite engaging."},
{"role": "user", "content": "I’m not a big fan of thriller movies but I love sci-fi movies."},
{"role": "assistant", "content": "Got it! I'll avoid thriller recommendations and suggest sci-fi movies in the future."}
]
await memory.add(messages, { userId: "alice", metadata: { category: "movies" } });
```
</CodeGroup>
### Config
Let's see the available parameters for the `redis` config:
<Tabs>
<Tab title="Python">
| Parameter | Description | Default Value |
| --- | --- | --- |
| `collection_name` | The name of the collection to store the vectors | `mem0` |
| `embedding_model_dims` | Dimensions of the embedding model | `1536` |
| `redis_url` | The URL of the Redis server | `None` |
| `redis_url` | The URL of the Redis server | `None` |
</Tab>
<Tab title="TypeScript">
| Parameter | Description | Default Value |
| --- | --- | --- |
| `collectionName` | The name of the collection to store the vectors | `mem0` |
| `embeddingModelDims` | Dimensions of the embedding model | `1536` |
| `redisUrl` | The URL of the Redis server | `None` |
| `username` | Username for Redis connection | `None` |
| `password` | Password for Redis connection | `None` |
</Tab>
</Tabs>
@@ -0,0 +1,78 @@
[Supabase](https://supabase.com/) is an open-source Firebase alternative that provides a PostgreSQL database with pgvector extension for vector similarity search. It offers a powerful and scalable solution for storing and querying vector embeddings.
Create a [Supabase](https://supabase.com/dashboard/projects) account and project, then get your connection string from Project Settings > Database. See the [docs](https://supabase.github.io/vecs/hosting/) for details.
### Usage
```python
import os
from mem0 import Memory
os.environ["OPENAI_API_KEY"] = "sk-xx"
config = {
"vector_store": {
"provider": "supabase",
"config": {
"connection_string": "postgresql://user:password@host:port/database",
"collection_name": "memories",
"index_method": "hnsw", # Optional: defaults to "auto"
"index_measure": "cosine_distance" # Optional: defaults to "cosine_distance"
}
}
}
m = Memory.from_config(config)
messages = [
{"role": "user", "content": "I'm planning to watch a movie tonight. Any recommendations?"},
{"role": "assistant", "content": "How about a thriller movies? They can be quite engaging."},
{"role": "user", "content": "I'm not a big fan of thriller movies but I love sci-fi movies."},
{"role": "assistant", "content": "Got it! I'll avoid thriller recommendations and suggest sci-fi movies in the future."}
]
m.add(messages, user_id="alice", metadata={"category": "movies"})
```
### Config
Here are the parameters available for configuring Supabase:
| Parameter | Description | Default Value |
| --- | --- | --- |
| `connection_string` | PostgreSQL connection string (required) | None |
| `collection_name` | Name for the vector collection | `mem0` |
| `embedding_model_dims` | Dimensions of the embedding model | `1536` |
| `index_method` | Vector index method to use | `auto` |
| `index_measure` | Distance measure for similarity search | `cosine_distance` |
### Index Methods
The following index methods are supported:
- `auto`: Automatically selects the best available index method
- `hnsw`: Hierarchical Navigable Small World graph index (faster search, more memory usage)
- `ivfflat`: Inverted File Flat index (good balance of speed and memory)
### Distance Measures
Available distance measures for similarity search:
- `cosine_distance`: Cosine similarity (recommended for most embedding models)
- `l2_distance`: Euclidean distance
- `l1_distance`: Manhattan distance
- `max_inner_product`: Maximum inner product similarity
### Best Practices
1. **Index Method Selection**:
- Use `hnsw` for fastest search performance when memory is not a constraint
- Use `ivfflat` for a good balance of search speed and memory usage
- Use `auto` if unsure, it will select the best method based on your data
2. **Distance Measure Selection**:
- Use `cosine_distance` for most embedding models (OpenAI, Hugging Face, etc.)
- Use `max_inner_product` if your vectors are normalized
- Use `l2_distance` or `l1_distance` if working with raw feature vectors
3. **Connection String**:
- Always use environment variables for sensitive information in the connection string
- Format: `postgresql://user:password@host:port/database`
+5
View File
@@ -10,6 +10,10 @@ Mem0 includes built-in support for various popular databases. Memory can utilize
See the list of supported vector databases below.
<Note>
The following vector databases are supported in the Python implementation. The TypeScript implementation currently only supports Qdrant, Redis and in-memory vector database.
</Note>
<CardGroup cols={3}>
<Card title="Qdrant" href="/components/vectordbs/dbs/qdrant"></Card>
<Card title="Chroma" href="/components/vectordbs/dbs/chroma"></Card>
@@ -19,6 +23,7 @@ See the list of supported vector databases below.
<Card title="Redis" href="/components/vectordbs/dbs/redis"></Card>
<Card title="Elasticsearch" href="/components/vectordbs/dbs/elasticsearch"></Card>
<Card title="OpenSearch" href="/components/vectordbs/dbs/opensearch"></Card>
<Card title="Supabase" href="/components/vectordbs/dbs/supabase"></Card>
</CardGroup>
## Usage
+3 -62
View File
@@ -65,6 +65,7 @@
"pages": [
"open-source/quickstart",
"open-source/python-quickstart",
"open-source-typescript/quickstart",
{
"group": "Features",
"icon": "wrench",
@@ -127,7 +128,8 @@
"components/vectordbs/dbs/azure_ai_search",
"components/vectordbs/dbs/redis",
"components/vectordbs/dbs/elasticsearch",
"components/vectordbs/dbs/opensearch"
"components/vectordbs/dbs/opensearch",
"components/vectordbs/dbs/supabase"
]
}
]
@@ -151,67 +153,6 @@
]
}
]
},
{
"group": "Node.js",
"icon": "js",
"pages": [
"open-source-typescript/quickstart",
{
"group": "Features",
"icon": "wrench",
"pages": [
"open-source-typescript/features/custom-prompts"
]
},
{
"group": "LLMs",
"icon": "brain",
"pages": [
"open-source-typescript/components/llms/overview",
"open-source-typescript/components/llms/config",
{
"group": "Supported LLMs",
"icon": "list",
"pages": [
"open-source-typescript/components/llms/models/openai",
"open-source-typescript/components/llms/models/anthropic",
"open-source-typescript/components/llms/models/groq"
]
}
]
},{
"group": "Vector Databases",
"icon": "database",
"pages": [
"open-source-typescript/components/vectordbs/overview",
"open-source-typescript/components/vectordbs/config",
{
"group": "Supported Vector Databases",
"icon": "server",
"pages": [
"open-source-typescript/components/vectordbs/dbs/qdrant",
"open-source-typescript/components/vectordbs/dbs/redis"
]
}
]
},
{
"group": "Embedding Models",
"icon": "layer-group",
"pages": [
"open-source-typescript/components/embedders/overview",
"open-source-typescript/components/embedders/config",
{
"group": "Supported Embedding Models",
"icon": "list",
"pages": [
"open-source-typescript/components/embedders/models/openai"
]
}
]
}
]
}
]
}
+2 -2
View File
@@ -29,7 +29,7 @@ const openaiClient = new OpenAI();
const memory = new Memory();
async function chatWithMemories(message, userId = "default_user") {
const relevantMemories = await memory.search(message, userId);
const relevantMemories = await memory.search(message, { userId: userId });
const memoriesStr = relevantMemories.results
.map(entry => `- ${entry.memory}`)
@@ -52,7 +52,7 @@ ${memoriesStr}`;
const assistantResponse = response.choices[0].message.content || "";
messages.push({ role: "assistant", content: assistantResponse });
await memory.add(messages, userId);
await memory.add(messages, { userId: userId });
return assistantResponse;
}
+64 -6
View File
@@ -17,7 +17,8 @@ To create an effective custom prompt:
Example of a custom prompt:
```python
<CodeGroup>
```python Python
custom_prompt = """
Please only extract entities containing customer support information, order details, and user information.
Here are some few shot examples:
@@ -39,12 +40,37 @@ Output: {{"facts" : ["Ordered red shirt, size medium", "Received blue shirt inst
Return the facts and customer information in a json format as shown above.
"""
```
Here we initialize the custom prompt in the config.
```typescript TypeScript
const customPrompt = `
Please only extract entities containing customer support information, order details, and user information.
Here are some few shot examples:
```python
Input: Hi.
Output: {"facts" : []}
Input: The weather is nice today.
Output: {"facts" : []}
Input: My order #12345 hasn't arrived yet.
Output: {"facts" : ["Order #12345 not received"]}
Input: I am John Doe, and I would like to return the shoes I bought last week.
Output: {"facts" : ["Customer name: John Doe", "Wants to return shoes", "Purchase made last week"]}
Input: I ordered a red shirt, size medium, but received a blue one instead.
Output: {"facts" : ["Ordered red shirt, size medium", "Received blue shirt instead"]}
Return the facts and customer information in a json format as shown above.
`;
```
</CodeGroup>
Here we initialize the custom prompt in the config:
<CodeGroup>
```python Python
from mem0 import Memory
config = {
@@ -63,15 +89,40 @@ config = {
m = Memory.from_config(config_dict=config, user_id="alice")
```
```typescript TypeScript
import { Memory } from 'mem0ai/oss';
const config = {
version: 'v1.1',
llm: {
provider: 'openai',
config: {
apiKey: process.env.OPENAI_API_KEY || '',
model: 'gpt-4-turbo-preview',
temperature: 0.2,
maxTokens: 1500,
},
},
customPrompt: customPrompt
};
const memory = new Memory(config);
```
</CodeGroup>
### Example 1
In this example, we are adding a memory of a user ordering a laptop. As seen in the output, the custom prompt is used to extract the relevant information from the user's message.
<CodeGroup>
```python Code
```python Python
m.add("Yesterday, I ordered a laptop, the order id is 12345", user_id="alice")
```
```typescript TypeScript
await memory.add('Yesterday, I ordered a laptop, the order id is 12345', { userId: "user123" });
```
```json Output
{
"results": [
@@ -97,11 +148,16 @@ m.add("Yesterday, I ordered a laptop, the order id is 12345", user_id="alice")
In this example, we are adding a memory of a user liking to go on hikes. This add message is not specific to the use-case mentioned in the custom prompt.
Hence, the memory is not added.
<CodeGroup>
```python Code
```python Python
m.add("I like going to hikes", user_id="alice")
```
```typescript TypeScript
await memory.add('I like going to hikes', { userId: "user123" });
```
```json Output
{
"results": [],
@@ -109,3 +165,5 @@ m.add("I like going to hikes", user_id="alice")
}
```
</CodeGroup>
The custom prompt will process both the user and assistant messages to extract relevant information according to the defined format.
@@ -1,56 +0,0 @@
---
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.
## How to define configurations?
The config is defined as a TypeScript object with two main keys:
- `embedder`: Specifies the embedder provider and its configuration
- `provider`: The name of the embedder (e.g., "openai", "ollama")
- `config`: A nested object containing provider-specific settings
## How to use configurations?
Here's a general example of how to use the config with Mem0:
```typescript
import { Memory } from 'mem0ai/oss';
const config = {
embedder: {
provider: 'openai',
config: {
apiKey: 'your-openai-api-key',
model: 'text-embedding-3-small',
},
},
};
const memory = new Memory(config);
await memory.add("Your text here", { userId: "user", metadata: { category: "example" } });
```
## Why is Config Needed?
Config is essential for:
1. Specifying which embedding model to use.
2. Providing necessary connection details (e.g., model, api_key, embedding_dims).
3. Ensuring proper initialization and connection to your chosen embedder.
## Master List of All Params in Config
Here's a comprehensive list of all parameters that can be used across different embedders:
| Parameter | Description |
|------------------------|--------------------------------------------------|
| `model` | Embedding model to use |
| `apiKey` | API key of the provider |
| `embeddingDims` | Dimensions of the embedding model |
## Supported Embedding Models
For detailed information on configuring specific embedders, please visit the [Embedding Models](./models) section. There you'll find information for each supported embedder with provider-specific usage examples and configuration details.
@@ -1,36 +0,0 @@
---
title: OpenAI
---
To use OpenAI embedding models, you need to provide the API key directly in your configuration. You can obtain the OpenAI API key from the [OpenAI Platform](https://platform.openai.com/account/api-keys).
### Usage
Here's how to configure OpenAI embedding models in your application:
```typescript
import { Memory } from 'mem0ai/oss';
const config = {
embedder: {
provider: 'openai',
config: {
apiKey: 'your-openai-api-key',
model: 'text-embedding-3-large',
},
},
};
const memory = new Memory(config);
await memory.add("I'm visiting Paris", { userId: "john" });
```
### Config
Here are the parameters available for configuring the OpenAI embedder:
| Parameter | Description | Default Value |
|------------------------|--------------------------------------------------|---------------|
| `model` | The name of the embedding model to use | `text-embedding-3-small` |
| `embedding_dims` | Dimensions of the embedding model | `1536` |
| `api_key` | The OpenAI API key | `None` |
@@ -1,21 +0,0 @@
---
title: Overview
icon: "info"
iconType: "solid"
---
Mem0 offers support for various embedding models, allowing users to choose the one that best suits their needs.
## Supported Embedders
See the list of supported embedders below.
<CardGroup cols={1}>
<Card title="OpenAI" href="/components/embedders/models/openai"></Card>
</CardGroup>
## Usage
To utilize a embedder, you must provide a configuration to customize its usage. If no configuration is supplied, a default configuration will be applied, and `OpenAI` will be used as the embedder.
For a comprehensive list of available parameters for embedder configuration, please refer to [Config](./config).
@@ -1,85 +0,0 @@
---
title: Configurations
icon: "gear"
iconType: "solid"
---
## How to define configurations?
The `config` is defined as a TypeScript object with two main keys:
- `llm`: Specifies the LLM provider and its configuration
- `provider`: The name of the LLM (e.g., "openai", "groq")
- `config`: A nested object containing provider-specific settings
### Config Values Precedence
Config values are applied in the following order of precedence (from highest to lowest):
1. Values explicitly set in the `config` object
2. Environment variables (e.g., `OPENAI_API_KEY`, `OPENAI_API_BASE`)
3. Default values defined in the LLM implementation
This means that values specified in the `config` object will override corresponding environment variables, which in turn override default values.
## How to Use Config
Here's a general example of how to use the config with Mem0:
```typescript
import { Memory } from 'mem0ai/oss';
const config = {
llm: {
provider: 'openai',
config: {
apiKey: process.env.OPENAI_API_KEY || '',
model: 'gpt-4-turbo-preview',
temperature: 0.2,
maxTokens: 1500,
},
},
embedder: {
provider: 'openai',
config: {
apiKey: process.env.OPENAI_API_KEY || '',
model: 'text-embedding-3-small',
},
},
vectorStore: {
provider: 'memory',
config: {
collectionName: 'memories',
dimension: 1536,
},
},
historyDbPath: 'memory.db',
};
const memory = new Memory(config);
memory.add("Your text here", { userId: "user123", metadata: { category: "example" } });
```
## Why is Config Needed?
Config is essential for:
1. Specifying which LLM to use.
2. Providing necessary connection details (e.g., model, api_key, temperature).
3. Ensuring proper initialization and connection to your chosen LLM.
## Master List of All Params in Config
Here's a comprehensive list of all parameters that can be used across different LLMs:
| Parameter | Description | Provider |
|----------------------|-----------------------------------------------|-------------------|
| `model` | Embedding model to use | All |
| `temperature` | Temperature of the model | All |
| `apiKey` | API key to use | All |
| `maxTokens` | Tokens to generate | All |
| `topP` | Probability threshold for nucleus sampling | All |
| `topK` | Number of highest probability tokens to keep | All |
| `openaiBaseUrl` | Base URL for OpenAI API | OpenAI |
## Supported LLMs
For detailed information on configuring specific LLMs, please visit the [LLMs](./models) section. There you'll find information for each supported LLM with provider-specific usage examples and configuration details.
@@ -1,30 +0,0 @@
---
title: Anthropic
---
To use Anthropic's models, please set the `ANTHROPIC_API_KEY`, which you can find on their [Account Settings Page](https://console.anthropic.com/account/keys).
## Usage
```typescript
import { Memory } from 'mem0ai/oss';
const config = {
llm: {
provider: 'anthropic',
config: {
apiKey: process.env.ANTHROPIC_API_KEY || '',
model: 'claude-3-7-sonnet-latest',
temperature: 0.1,
maxTokens: 2000,
},
},
};
const memory = new Memory(config);
await memory.add("Likes to play cricket on weekends", { userId: "alice", metadata: { category: "hobbies" } });
```
## Config
All available parameters for the `anthropic` config are present in the [Master List of All Params in Config](../config).
@@ -1,32 +0,0 @@
---
title: Groq
---
[Groq](https://groq.com/) is the creator of the world's first Language Processing Unit (LPU), providing exceptional speed performance for AI workloads running on their LPU Inference Engine.
In order to use LLMs from Groq, go to their [platform](https://console.groq.com/keys) and get the API key. Set the API key as `GROQ_API_KEY` environment variable to use the model as given below in the example.
## Usage
```typescript
import { Memory } from 'mem0ai/oss';
const config = {
llm: {
provider: 'groq',
config: {
apiKey: process.env.GROQ_API_KEY || '',
model: 'mixtral-8x7b-32768',
temperature: 0.1,
maxTokens: 1000,
},
},
};
const memory = new Memory(config);
await memory.add("Likes to play cricket on weekends", { userId: "alice", metadata: { category: "hobbies" } });
```
## Config
All available parameters for the `groq` config are present in the [Master List of All Params in Config](../config).
@@ -1,30 +0,0 @@
---
title: OpenAI
---
To use OpenAI LLM models, you need to set the `OPENAI_API_KEY` environment variable. You can obtain the OpenAI API key from the [OpenAI Platform](https://platform.openai.com/account/api-keys).
## Usage
```typescript
import { Memory } from 'mem0ai/oss';
const config = {
llm: {
provider: 'openai',
config: {
apiKey: process.env.OPENAI_API_KEY || '',
model: 'gpt-4-turbo-preview',
temperature: 0.2,
maxTokens: 1500,
},
},
};
const memory = new Memory(config);
await memory.add("Likes to play cricket on weekends", { userId: "alice", metadata: { category: "hobbies" } });
```
## Config
All available parameters for the `openai` config are present in the [Master List of All Params in Config](../config).
@@ -1,45 +0,0 @@
---
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.
## Usage
To use a llm, you must provide a configuration to customize its usage. If no configuration is supplied, a default configuration will be applied, and `OpenAI` will be used as the llm.
For a comprehensive list of available parameters for llm configuration, please refer to [Config](./config).
To view all supported llms, visit the [Supported LLMs](./models).
<CardGroup cols={3}>
<Card title="OpenAI" href="/open-source-typescript/components/llms/models/openai"></Card>
<Card title="Anthropic" href="/open-source-typescript/components/llms/models/anthropic"></Card>
<Card title="Groq" href="/open-source-typescript/components/llms/models/groq"></Card>
</CardGroup>
## Structured vs Unstructured Outputs
Mem0 supports two types of OpenAI LLM formats, each with its own strengths and use cases:
### Structured Outputs
Structured outputs are LLMs that align with OpenAI's structured outputs model:
- **Optimized for:** Returning structured responses (e.g., JSON objects)
- **Benefits:** Precise, easily parseable data
- **Ideal for:** Data extraction, form filling, API responses
- **Learn more:** [OpenAI Structured Outputs Guide](https://platform.openai.com/docs/guides/structured-outputs/introduction)
### Unstructured Outputs
Unstructured outputs correspond to OpenAI's standard, free-form text model:
- **Flexibility:** Returns open-ended, natural language responses
- **Customization:** Use the `response_format` parameter to guide output
- **Trade-off:** Less efficient than structured outputs for specific data needs
- **Best for:** Creative writing, explanations, general conversation
Choose the format that best suits your application's requirements for optimal performance and usability.
@@ -1,100 +0,0 @@
---
title: Configurations
icon: "gear"
iconType: "solid"
---
## How to define configurations?
The `config` is defined as a TypeScript object with two main keys:
- `vectorStore`: Specifies the vector database provider and its configuration
- `provider`: The name of the vector database (e.g., "chroma", "pgvector", "qdrant", "milvus", "azure_ai_search", "redis", "memory")
- `config`: A nested object containing provider-specific settings
## In-Memory Storage Option
We also support an in-memory storage option for the vector store, which is useful for reduced overhead and faster access times. Here's how to configure it:
### Example for In-Memory Storage
```typescript
const configMemory = {
vector_store: {
provider: 'memory',
config: {
collectionName: 'memories',
dimension: 1536,
},
},
};
const memory = new Memory(configMemory);
await memory.add("Your text here", { userId: "user", metadata: { category: "example" } });
```
## How to Use Config
Here's a general example of how to use the config with Mem0:
### Example for qdrant
```typescript
import { Memory } from 'mem0ai/oss';
const config = {
vector_store: {
provider: 'qdrant',
config: {
collectionName: 'memories',
embeddingModelDims: 1536,
host: 'localhost',
port: 6333,
url: 'https://your-qdrant-url.com',
apiKey: 'your-qdrant-api-key',
onDisk: true,
},
},
};
const memory = new Memory(config);
await memory.add("Your text here", { userId: "user", metadata: { category: "example" } });
```
## Why is Config Needed?
Config is essential for:
1. Specifying which vector database to use.
2. Providing necessary connection details (e.g., host, port, credentials).
3. Customizing database-specific settings (e.g., collection name, path).
4. Ensuring proper initialization and connection to your chosen vector store.
## Master List of All Params in Config
Here's a comprehensive list of all parameters that can be used across different vector databases:
| Parameter | Description |
|------------------------|--------------------------------------|
| `collectionName` | Name of the collection |
| `dimension` | Dimensions of the embedding model |
| `host` | Host where the server is running |
| `port` | Port where the server is running |
| `embeddingModelDims` | Dimensions of the embedding model |
| `url` | URL for the Qdrant server |
| `apiKey` | API key for the Qdrant server |
| `path` | Path for the Qdrant server |
| `onDisk` | Enable persistent storage (for Qdrant) |
| `redisUrl` | URL for the Redis server |
| `username` | Username for Redis connection |
| `password` | Password for Redis connection |
## Customizing Config
Each vector database has its own specific configuration requirements. To customize the config for your chosen vector store:
1. Identify the vector database you want to use from [supported vector databases](./dbs).
2. Refer to the `Config` section in the respective vector database's documentation.
3. Include only the relevant parameters for your chosen database in the `config` object.
## Supported Vector Databases
For detailed information on configuring specific vector databases, please visit the [Supported Vector Databases](./dbs) section. There you'll find individual pages for each supported vector store with provider-specific usage examples and configuration details.
@@ -1,44 +0,0 @@
[pgvector](https://github.com/pgvector/pgvector) is open-source vector similarity search for Postgres. After connecting with Postgres, run `CREATE EXTENSION IF NOT EXISTS vector;` to create the vector extension.
### Usage
Here's how to configure pgvector in your application:
```typescript
import { Memory } from 'mem0ai/oss';
const config = {
vector_store: {
provider: 'pgvector',
config: {
collectionName: 'memories',
dimension: 1536,
dbname: 'vectordb',
user: 'postgres',
password: 'postgres',
host: 'localhost',
port: 5432,
embeddingModelDims: 1536,
hnsw: true,
},
},
};
const memory = new Memory(config);
await memory.add("Likes to play cricket on weekends", { userId: "alice", metadata: { category: "hobbies" } });
```
### Config
Here's the parameters available for configuring pgvector:
| Parameter | Description | Default Value |
|------------------------|--------------------------------------------------|---------------|
| `dbname` | The name of the database | `postgres` |
| `collectionName` | The name of the collection | `mem0` |
| `embeddingModelDims` | Dimensions of the embedding model | `1536` |
| `user` | Username to connect to the database | `None` |
| `password` | Password to connect to the database | `None` |
| `host` | The host where the Postgres server is running | `None` |
| `port` | The port where the Postgres server is running | `None` |
| `hnsw` | Enable HNSW indexing | `False` |
@@ -1,42 +0,0 @@
[Qdrant](https://qdrant.tech/) is an open-source vector search engine. It is designed to work with large-scale datasets and provides a high-performance search engine for vector data.
### Usage
Here's how to configure Qdrant in your application:
```typescript
import { Memory } from 'mem0ai/oss';
const config = {
vector_store: {
provider: 'qdrant',
config: {
collectionName: 'memories',
embeddingModelDims: 1536,
host: 'localhost',
port: 6333,
url: 'https://your-qdrant-url.com',
apiKey: 'your-qdrant-api-key',
onDisk: true,
},
},
};
const memory = new Memory(config);
await memory.add("Likes to play cricket on weekends", { userId: "alice", metadata: { category: "hobbies" } });
```
### Config
Let's see the available parameters for the `qdrant` config:
| Parameter | Description | Default Value |
|------------------------|--------------------------------------------------|---------------|
| `collectionName` | The name of the collection to store the vectors | `mem0` |
| `embeddingModelDims` | Dimensions of the embedding model | `1536` |
| `host` | The host where the Qdrant server is running | `None` |
| `port` | The port where the Qdrant server is running | `None` |
| `path` | Path for the Qdrant database | `/tmp/qdrant` |
| `url` | Full URL for the Qdrant server | `None` |
| `apiKey` | API key for the Qdrant server | `None` |
| `onDisk` | For enabling persistent storage | `False` |
@@ -1,47 +0,0 @@
[Redis](https://redis.io/) is a scalable, real-time database that can store, search, and analyze vector data.
### Installation
```bash
pip install redis redisvl
```
Redis Stack using Docker:
```bash
docker run -d --name redis-stack -p 6379:6379 -p 8001:8001 redis/redis-stack:latest
```
### Usage
Here's how to configure Redis in your application:
```typescript
import { Memory } from 'mem0ai/oss';
const config = {
vector_store: {
provider: 'redis',
config: {
collectionName: 'memories',
embeddingModelDims: 1536,
redisUrl: 'redis://localhost:6379',
username: 'your-redis-username',
password: 'your-redis-password',
},
},
};
const memoryRedis = new Memory(config);
await memoryRedis.add("Likes to play cricket on weekends", { userId: "alice", metadata: { category: "hobbies" } });
```
### Config
Let's see the available parameters for the `redis` config:
| Parameter | Description | Default Value |
|------------------------|--------------------------------------------------|---------------|
| `collectionName` | The name of the collection to store the vectors | `mem0` |
| `embeddingModelDims` | Dimensions of the embedding model | `1536` |
| `redisUrl` | The URL of the Redis server | `None` |
| `username` | Username for Redis connection | `None` |
| `password` | Password for Redis connection | `None` |
@@ -1,36 +0,0 @@
---
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.
## Supported Vector Databases
See the list of supported vector databases below.
<CardGroup cols={2}>
<Card title="Memory" href="/components/vectordbs/dbs/memory"></Card>
<Card title="Qdrant" href="/components/vectordbs/dbs/qdrant"></Card>
<Card title="Redis" href="/components/vectordbs/dbs/redis"></Card>
<Card title="Pgvector" href="/components/vectordbs/dbs/pgvector"></Card>
</CardGroup>
## Usage
To utilize a vector database, you must provide a configuration to customize its usage. If no configuration is supplied, a default configuration will be applied, and `Memory` will be used as the vector database.
For a comprehensive list of available parameters for vector database configuration, please refer to [Config](./config).
## Common issues
### Using model with different dimensions
If you are using customized model, which is having different dimensions other than 1536
for example 768, you may encounter below error:
`ValueError: shapes (0,1536) and (768,) not aligned: 1536 (dim 1) != 768 (dim 0)`
you could add `"embedding_model_dims": 768,` to the config of the vector_store to overcome this issue.
@@ -1,141 +0,0 @@
---
title: Custom Prompts
description: 'Enhance your product experience by adding custom prompts tailored to your needs'
icon: "pencil"
iconType: "solid"
---
## Introduction to Custom Prompts
Custom prompts allow you to tailor the behavior of your Mem0 instance to specific use cases or domains.
By defining a custom prompt, you can control how information is extracted, processed, and stored in your memory system.
To create an effective custom prompt:
1. Be specific about the information to extract.
2. Provide few-shot examples to guide the LLM.
3. Ensure examples follow the format shown below.
Example of a custom prompt:
```typescript
const customPrompt = `
Please only extract entities containing customer support information, order details, and user information.
Here are some few shot examples:
Input: Hi.
Output: {"facts" : []}
Input: The weather is nice today.
Output: {"facts" : []}
Input: My order #12345 hasn't arrived yet.
Output: {"facts" : ["Order #12345 not received"]}
Input: I'm John Doe, and I'd like to return the shoes I bought last week.
Output: {"facts" : ["Customer name: John Doe", "Wants to return shoes", "Purchase made last week"]}
Input: I ordered a red shirt, size medium, but received a blue one instead.
Output: {"facts" : ["Ordered red shirt, size medium", "Received blue shirt instead"]}
Return the facts and customer information in a json format as shown above.
`;
```
Here we initialize the custom prompt in the config:
```typescript
import { Memory } from 'mem0ai/oss';
const config = {
version: 'v1.1',
embedder: {
provider: 'openai',
config: {
apiKey: process.env.OPENAI_API_KEY || '',
model: 'text-embedding-3-small',
},
},
vectorStore: {
provider: 'memory',
config: {
collectionName: 'memories',
dimension: 1536,
},
},
llm: {
provider: 'openai',
config: {
apiKey: process.env.OPENAI_API_KEY || '',
model: 'gpt-4-turbo-preview',
temperature: 0.2,
maxTokens: 1500,
},
},
customPrompt: customPrompt,
historyDbPath: 'memory.db',
};
const memory = new Memory(config);
```
### Example 1
In this example, we are adding a memory of a user ordering a laptop. As seen in the output, the custom prompt is used to extract the relevant information from the user's message.
<CodeGroup>
```typescript Code
await memory.add('Yesterday, I ordered a laptop, the order id is 12345', 'user123');
```
```json Output
{
"results": [
{
"id": "c03c9045-df76-4949-bbc5-d5dc1932aa5c",
"memory": "Ordered a laptop",
"metadata": {}
},
{
"id": "cbb1fe73-0bf1-4067-8c1f-63aa53e7b1a4",
"memory": "Order ID: 12345",
"metadata": {}
},
{
"id": "e5f2a012-3b45-4c67-9d8e-123456789abc",
"memory": "Order placed yesterday",
"metadata": {}
}
]
}
```
</CodeGroup>
### Example 2
In this example, we are adding a memory of a user liking to go on hikes. This add message is not specific to the use-case mentioned in the custom prompt.
Hence, the memory is not added.
<CodeGroup>
```typescript Code
await memory.add('I like going to hikes', 'user123');
```
```json Output
{
"results": []
}
```
</CodeGroup>
You can also use custom prompts with chat messages:
```typescript
const messages = [
{ role: 'user', content: 'Hi, I ordered item #54321 last week but haven\'t received it yet.' },
{ role: 'assistant', content: 'I understand you\'re concerned about your order #54321. Let me help track that for you.' }
];
await memory.add(messages, 'user123');
```
The custom prompt will process both the user and assistant messages to extract relevant information according to the defined format.
+92 -50
View File
@@ -1,5 +1,5 @@
---
title: Node.js Guide
title: Node SDK
description: 'Get started with Mem0 quickly!'
icon: "node"
iconType: "solid"
@@ -67,15 +67,14 @@ const memory = new Memory({
<CodeGroup>
```typescript Code
// For a user
const result = await memory.add('Hi, my name is John and I am a software', 'user123');
console.log(result);
const messages = [
{"role": "user", "content": "I'm planning to watch a movie tonight. Any recommendations?"},
{"role": "assistant", "content": "How about a thriller movies? They can be quite engaging."},
{"role": "user", "content": "I'm not a big fan of thriller movies but I love sci-fi movies."},
{"role": "assistant", "content": "Got it! I'll avoid thriller recommendations and suggest sci-fi movies in the future."}
]
// const messages = [
// {"role": "user", "content": "Hi, I'm Alex. I like to play cricket on weekends."},
// {"role": "assistant", "content": "Hello Alex! It's great to know that you enjoy playing cricket on weekends. I'll remember that for future reference."}
// ]
// await memory.add(messages, 'user123');
await memory.add(messages, { userId: "user123", metadata: { category: "movie_recommendations" } });
```
```json Output
@@ -83,13 +82,24 @@ console.log(result);
"results": [
{
"id": "c03c9045-df76-4949-bbc5-d5dc1932aa5c",
"memory": "Name is John",
"metadata": [Object]
"memory": "User is planning to watch a movie tonight.",
"metadata": {
"category": "movie_recommendations"
}
},
{
"id": "cbb1fe73-0bf1-4067-8c1f-63aa53e7b1a4",
"memory": "Is a software",
"metadata": [Object]
"memory": "User is not a big fan of thriller movies.",
"metadata": {
"category": "movie_recommendations"
}
},
{
"id": "475bde34-21e6-42ab-8bef-0ab84474f156",
"memory": "User loves sci-fi movies.",
"metadata": {
"category": "movie_recommendations"
}
}
]
}
@@ -101,7 +111,7 @@ console.log(result);
<CodeGroup>
```typescript Code
// Get all memories
const allMemories = await memory.getAll('user123');
const allMemories = await memory.getAll({ userId: "user123" });
console.log(allMemories)
```
@@ -110,20 +120,35 @@ console.log(allMemories)
"results": [
{
"id": "892db2ae-06d9-49e5-8b3e-585ef9b85b8e",
"memory": "Name is Alex Jones",
"memory": "User is planning to watch a movie tonight.",
"hash": "1a271c007316c94377175ee80e746a19",
"createdAt": "2025-02-27T16:33:20.557Z",
"updatedAt": "2025-02-27T16:33:27.051Z",
"metadata": {},
"metadata": {
"category": "movie_recommendations"
},
"userId": "user123"
},
{
"id": "475bde34-21e6-42ab-8bef-0ab84474f156",
"memory": "Likes to play cricket on weekends",
"memory": "User loves sci-fi movies.",
"hash": "285d07801ae42054732314853e9eadd7",
"createdAt": "2025-02-27T16:33:20.560Z",
"updatedAt": undefined,
"metadata": {},
"metadata": {
"category": "movie_recommendations"
},
"userId": "user123"
},
{
"id": "cbb1fe73-0bf1-4067-8c1f-63aa53e7b1a4",
"memory": "User is not a big fan of thriller movies.",
"hash": "285d07801ae42054732314853e9eadd7",
"createdAt": "2025-02-27T16:33:20.560Z",
"updatedAt": undefined,
"metadata": {
"category": "movie_recommendations"
},
"userId": "user123"
}
]
@@ -137,18 +162,20 @@ console.log(allMemories)
<CodeGroup>
```typescript Code
// Get a single memory by ID
const singleMemory = await memory.get('6c1c11a2-4fbc-4a2b-8e8a-d60e67e57aaa');
const singleMemory = await memory.get('892db2ae-06d9-49e5-8b3e-585ef9b85b8e');
console.log(singleMemory);
```
```json Output
{
"id": "6c1c11a2-4fbc-4a2b-8e8a-d60e67e57aaa",
"memory": "Name is Alex",
"hash": "d0fccc8fa47f7a149ee95750c37bb0ca",
"createdAt": "2025-02-27T16:37:04.378Z",
"id": "892db2ae-06d9-49e5-8b3e-585ef9b85b8e",
"memory": "User is planning to watch a movie tonight.",
"hash": "1a271c007316c94377175ee80e746a19",
"createdAt": "2025-02-27T16:33:20.557Z",
"updatedAt": undefined,
"metadata": {},
"metadata": {
"category": "movie_recommendations"
},
"userId": "user123"
}
```
@@ -158,7 +185,7 @@ console.log(singleMemory);
<CodeGroup>
```typescript Code
const result = await memory.search('What do you know about me?', 'user123');
const result = await memory.search('What do you know about me?', { userId: "user123" });
console.log(result);
```
@@ -166,23 +193,39 @@ console.log(result);
{
"results": [
{
"id": "28c3eee7-186e-4644-8c5d-13b306233d4e",
"memory": "Name is Alex",
"hash": "d0fccc8fa47f7a149ee95750c37bb0ca",
"createdAt": "2025-02-27T16:43:56.310Z",
"id": "892db2ae-06d9-49e5-8b3e-585ef9b85b8e",
"memory": "User is planning to watch a movie tonight.",
"hash": "1a271c007316c94377175ee80e746a19",
"createdAt": "2025-02-27T16:33:20.557Z",
"updatedAt": undefined,
"score": 0.08920719231944799,
"metadata": {},
"score": 0.38920719231944799,
"metadata": {
"category": "movie_recommendations"
},
"userId": "user123"
},
{
"id": "f3433da0-45f4-444f-a4bc-59a170890a1f",
"memory": "Likes to play cricket on weekends",
"id": "475bde34-21e6-42ab-8bef-0ab84474f156",
"memory": "User loves sci-fi movies.",
"hash": "285d07801ae42054732314853e9eadd7",
"createdAt": "2025-02-27T16:43:56.314Z",
"createdAt": "2025-02-27T16:33:20.560Z",
"updatedAt": undefined,
"score": 0.06869761478135689,
"metadata": {},
"score": 0.36869761478135689,
"metadata": {
"category": "movie_recommendations"
},
"userId": "user123"
},
{
"id": "cbb1fe73-0bf1-4067-8c1f-63aa53e7b1a4",
"memory": "User is not a big fan of thriller movies.",
"hash": "285d07801ae42054732314853e9eadd7",
"createdAt": "2025-02-27T16:33:20.560Z",
"updatedAt": undefined,
"score": 0.33855272141248272,
"metadata": {
"category": "movie_recommendations"
},
"userId": "user123"
}
]
@@ -195,9 +238,8 @@ console.log(result);
<CodeGroup>
```typescript Code
const result = await memory.update(
'6c1c11a2-4fbc-4a2b-8e8a-d60e67e57aaa',
'I love India, it is my favorite country.',
'user123'
'892db2ae-06d9-49e5-8b3e-585ef9b85b8e',
'I love India, it is my favorite country.'
);
console.log(result);
```
@@ -213,7 +255,7 @@ console.log(result);
<CodeGroup>
```typescript Code
const history = await memory.history('d2cc4cef-e0c1-47dd-948a-677030482e9e');
const history = await memory.history('892db2ae-06d9-49e5-8b3e-585ef9b85b8e');
console.log(history);
```
@@ -221,21 +263,21 @@ console.log(history);
[
{
"id": 39,
"memory_id": "d2cc4cef-e0c1-47dd-948a-677030482e9e",
"previous_value": "Name is Alex",
"new_value": "Name is Alex Jones",
"memory_id": "892db2ae-06d9-49e5-8b3e-585ef9b85b8e",
"previous_value": "User is planning to watch a movie tonight.",
"new_value": "I love India, it is my favorite country.",
"action": "UPDATE",
"created_at": "2025-02-27T16:46:15.853Z",
"updated_at": "2025-02-27T16:46:20.909Z",
"created_at": "2025-02-27T16:33:20.557Z",
"updated_at": "2025-02-27T16:33:27.051Z",
"is_deleted": 0
},
{
"id": 37,
"memory_id": "d2cc4cef-e0c1-47dd-948a-677030482e9e",
"memory_id": "892db2ae-06d9-49e5-8b3e-585ef9b85b8e",
"previous_value": null,
"new_value": "Name is Alex",
"new_value": "User is planning to watch a movie tonight.",
"action": "ADD",
"created_at": "2025-02-27T16:46:15.853Z",
"created_at": "2025-02-27T16:33:20.557Z",
"updated_at": null,
"is_deleted": 0
}
@@ -247,10 +289,10 @@ console.log(history);
```typescript
// Delete a memory by id
await memory.delete('bf4d4092-cf91-4181-bfeb-b6fa2ed3061b');
await memory.delete('892db2ae-06d9-49e5-8b3e-585ef9b85b8e');
// Delete all memories for a user
await memory.deleteAll('alice');
await memory.deleteAll({ userId: "user123" });
```
### Reset Memory
+1 -2
View File
@@ -28,8 +28,7 @@ config = {
"password": "xxx"
},
"custom_prompt": "Please only extract entities containing sports related relationships and nothing else.",
},
"version": "v1.1"
}
}
m = Memory.from_config(config_dict=config)
+3 -6
View File
@@ -38,8 +38,7 @@ allowfullscreen
## Initialize Graph Memory
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*).
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/).
<Note>If you are using Neo4j locally, then you need to install [APOC plugins](https://neo4j.com/labs/apoc/4.1/installation/).</Note>
@@ -65,8 +64,7 @@ config = {
"username": "neo4j",
"password": "xxx"
}
},
"version": "v1.1"
}
}
m = Memory.from_config(config_dict=config)
@@ -98,8 +96,7 @@ config = {
"temperature": 0.0,
}
}
},
"version": "v1.1"
}
}
m = Memory.from_config(config_dict=config)
+3 -16
View File
@@ -1,5 +1,5 @@
---
title: Python Guide
title: Python SDK
description: 'Get started with Mem0 quickly!'
icon: "python"
iconType: "solid"
@@ -71,8 +71,7 @@ config = {
"username": "neo4j",
"password": "---"
}
},
"version": "v1.1"
}
}
m = Memory.from_config(config_dict=config)
@@ -100,10 +99,6 @@ result = m.add("Likes to play cricket on weekends", user_id="alice", metadata={"
{
"results": [
{"id": "bf4d4092-cf91-4181-bfeb-b6fa2ed3061b", "memory": "Likes to play cricket on weekends", "event": "ADD"}
],
"relations": [
{"source": "alice", "relationship": "likes_to_play", "target": "cricket"},
{"source": "alice", "relationship": "plays_on", "target": "weekends"}
]
}
```
@@ -129,10 +124,6 @@ all_memories = m.get_all(user_id="alice")
"updated_at": None,
"user_id": "alice"
}
],
"relations": [
{"source": "alice", "relationship": "likes_to_play", "target": "cricket"},
{"source": "alice", "relationship": "plays_on", "target": "weekends"}
]
}
```
@@ -180,10 +171,6 @@ related_memories = m.search(query="What are Alice's hobbies?", user_id="alice")
"updated_at": None,
"user_id": "alice"
}
],
"relations": [
{"source": "alice", "relationship": "plays_on", "target": "weekends"},
{"source": "alice", "relationship": "likes_to_play", "target": "cricket"}
]
}
```
@@ -303,7 +290,7 @@ Mem0 offers extensive configuration options to customize its behavior according
| Parameter | Description | Default |
|------------------|--------------------------------------|----------------------------|
| `history_db_path` | Path to the history database | "{mem0_dir}/history.db" |
| `version` | API version | "v1.0" |
| `version` | API version | "v1.1" |
| `custom_prompt` | Custom prompt for memory processing | None |
</Accordion>
+2 -2
View File
@@ -330,7 +330,7 @@ result = m.add("I like to drink coffee in the morning and go for a walk.", user_
```
```typescript TypeScript
const result = memory.add("I like to drink coffee in the morning and go for a walk.", 'alice');
const result = memory.add("I like to drink coffee in the morning and go for a walk.", { userId: "alice", metadata: { category: "preferences" } });
```
```json Output
@@ -361,7 +361,7 @@ related_memories = m.search("Should I drink coffee or tea?", user_id="alice")
```
```typescript TypeScript
const relatedMemories = memory.search("Should I drink coffee or tea?", "alice");
const relatedMemories = memory.search("Should I drink coffee or tea?", { userId: "alice" });
```
```json Output
+3
View File
@@ -2,6 +2,9 @@
Mem0 is a self-improving memory layer for LLM applications, enabling personalized AI experiences that save costs and delight users. We offer both cloud and open-source solutions to cater to different needs.
See the complete [OSS Docs](https://docs.mem0.ai/open-source-typescript/quickstart).
See the complete [Platform API Reference](https://docs.mem0.ai/api-reference/overview).
## 1. Installation
For the open-source version, you can install the Mem0 package using npm:
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "mem0ai",
"version": "2.0.0",
"version": "2.0.1",
"description": "The Memory Layer For Your AI Apps",
"main": "./dist/index.js",
"module": "./dist/index.mjs",
+3
View File
@@ -1,4 +1,5 @@
export * from "./memory";
export * from "./memory/memory.types";
export * from "./types";
export * from "./embeddings/base";
export * from "./embeddings/openai";
@@ -9,4 +10,6 @@ export * from "./llms/anthropic";
export * from "./llms/groq";
export * from "./vector_stores/base";
export * from "./vector_stores/memory";
export * from "./vector_stores/qdrant";
export * from "./vector_stores/redis";
export * from "./utils/factory";
+26 -21
View File
@@ -24,6 +24,12 @@ import { Embedder } from "../embeddings/base";
import { LLM } from "../llms/base";
import { VectorStore } from "../vector_stores/base";
import { ConfigManager } from "../config/manager";
import {
AddMemoryOptions,
SearchMemoryOptions,
DeleteAllMemoryOptions,
GetAllMemoryOptions,
} from "./memory.types";
export class Memory {
private config: MemoryConfig;
@@ -69,13 +75,17 @@ export class Memory {
async add(
messages: string | Message[],
userId?: string,
agentId?: string,
runId?: string,
metadata: Record<string, any> = {},
filters: SearchFilters = {},
prompt?: string,
config: AddMemoryOptions,
): Promise<SearchResult> {
const {
userId,
agentId,
runId,
metadata = {},
filters = {},
prompt,
} = config;
if (userId) filters.userId = metadata.userId = userId;
if (agentId) filters.agentId = metadata.agentId = agentId;
if (runId) filters.runId = metadata.runId = runId;
@@ -87,7 +97,7 @@ export class Memory {
}
const parsedMessages = Array.isArray(messages)
? messages
? (messages as Message[])
: [{ role: "user", content: messages }];
const vectorStoreResult = await this.addToVectorStore(
@@ -260,12 +270,10 @@ export class Memory {
async search(
query: string,
userId?: string,
agentId?: string,
runId?: string,
limit: number = 100,
filters: SearchFilters = {},
config: SearchMemoryOptions,
): Promise<SearchResult> {
const { userId, agentId, runId, limit = 100, filters = {} } = config;
if (userId) filters.userId = userId;
if (agentId) filters.agentId = agentId;
if (runId) filters.runId = runId;
@@ -322,10 +330,10 @@ export class Memory {
}
async deleteAll(
userId?: string,
agentId?: string,
runId?: string,
config: DeleteAllMemoryOptions,
): Promise<{ message: string }> {
const { userId, agentId, runId } = config;
const filters: SearchFilters = {};
if (userId) filters.userId = userId;
if (agentId) filters.agentId = agentId;
@@ -358,12 +366,9 @@ export class Memory {
);
}
async getAll(
userId?: string,
agentId?: string,
runId?: string,
limit: number = 100,
): Promise<SearchResult> {
async getAll(config: GetAllMemoryOptions): Promise<SearchResult> {
const { userId, agentId, runId, limit = 100 } = config;
const filters: SearchFilters = {};
if (userId) filters.userId = userId;
if (agentId) filters.agentId = agentId;
@@ -0,0 +1,26 @@
import { Message } from "../types";
import { SearchFilters } from "../types";
export interface Entity {
userId?: string;
agentId?: string;
runId?: string;
}
export interface AddMemoryOptions extends Entity {
metadata?: Record<string, any>;
filters?: SearchFilters;
prompt?: string;
}
export interface SearchMemoryOptions extends Entity {
query: string;
limit?: number;
filters?: SearchFilters;
}
export interface GetAllMemoryOptions extends Entity {
limit?: number;
}
export interface DeleteAllMemoryOptions extends Entity {}
+1 -1
View File
@@ -46,7 +46,7 @@ class MemoryConfig(BaseModel):
)
version: str = Field(
description="The version of the API",
default="v1.0",
default="v1.1",
)
custom_prompt: Optional[str] = Field(
description="Custom prompt for the memory",
+44
View File
@@ -0,0 +1,44 @@
from typing import Any, Dict, Optional
from enum import Enum
from pydantic import BaseModel, Field, model_validator
class IndexMethod(str, Enum):
AUTO = "auto"
HNSW = "hnsw"
IVFFLAT = "ivfflat"
class IndexMeasure(str, Enum):
COSINE = "cosine_distance"
L2 = "l2_distance"
L1 = "l1_distance"
MAX_INNER_PRODUCT = "max_inner_product"
class SupabaseConfig(BaseModel):
connection_string: str = Field(..., description="PostgreSQL connection string")
collection_name: str = Field("mem0", description="Name for the vector collection")
embedding_model_dims: Optional[int] = Field(1536, description="Dimensions of the embedding model")
index_method: Optional[IndexMethod] = Field(IndexMethod.AUTO, description="Index method to use")
index_measure: Optional[IndexMeasure] = Field(IndexMeasure.COSINE, description="Distance measure to use")
@model_validator(mode="before")
def check_connection_string(cls, values):
conn_str = values.get("connection_string")
if not conn_str or not conn_str.startswith("postgresql://"):
raise ValueError("A valid PostgreSQL connection string must be provided")
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)}. Please input only the following fields: {', '.join(allowed_fields)}"
)
return values
+27 -30
View File
@@ -46,7 +46,7 @@ class Memory(MemoryBase):
self.enable_graph = False
if self.api_version == "v1.1" and self.config.graph_store.config:
if self.config.graph_store.config:
from mem0.memory.graph_memory import MemoryGraph
self.graph = MemoryGraph(self.config)
@@ -126,12 +126,7 @@ class Memory(MemoryBase):
vector_store_result = future1.result()
graph_result = future2.result()
if self.api_version == "v1.1":
return {
"results": vector_store_result,
"relations": graph_result,
}
else:
if self.api_version == "v1.0":
warnings.warn(
"The current add API output format is deprecated. "
"To use the latest format, set `api_version='v1.1'`. "
@@ -141,6 +136,14 @@ class Memory(MemoryBase):
)
return vector_store_result
if self.enable_graph:
return {
"results": vector_store_result,
"relations": graph_result,
}
return {"results": vector_store_result}
def _add_to_vector_store(self, messages, metadata, filters):
parsed_messages = parse_messages(messages)
@@ -252,7 +255,7 @@ class Memory(MemoryBase):
def _add_to_graph(self, messages, filters):
added_entities = []
if self.api_version == "v1.1" and self.enable_graph:
if self.enable_graph:
if filters.get("user_id") is None:
filters["user_id"] = "user"
@@ -324,11 +327,7 @@ class Memory(MemoryBase):
with concurrent.futures.ThreadPoolExecutor() as executor:
future_memories = executor.submit(self._get_all_from_vector_store, filters, limit)
future_graph_entities = (
executor.submit(self.graph.get_all, filters, limit)
if self.api_version == "v1.1" and self.enable_graph
else None
)
future_graph_entities = executor.submit(self.graph.get_all, filters, limit) if self.enable_graph else None
concurrent.futures.wait(
[future_memories, future_graph_entities] if future_graph_entities else [future_memories]
@@ -337,12 +336,10 @@ class Memory(MemoryBase):
all_memories = future_memories.result()
graph_entities = future_graph_entities.result() if future_graph_entities else None
if self.api_version == "v1.1":
if self.enable_graph:
return {"results": all_memories, "relations": graph_entities}
else:
return {"results": all_memories}
else:
if self.enable_graph:
return {"results": all_memories, "relations": graph_entities}
if self.api_version == "v1.0":
warnings.warn(
"The current get_all API output format is deprecated. "
"To use the latest format, set `api_version='v1.1'`. "
@@ -351,6 +348,8 @@ class Memory(MemoryBase):
stacklevel=2,
)
return all_memories
else:
return {"results": all_memories}
def _get_all_from_vector_store(self, filters, limit):
memories = self.vector_store.list(filters=filters, limit=limit)
@@ -419,9 +418,7 @@ class Memory(MemoryBase):
with concurrent.futures.ThreadPoolExecutor() as executor:
future_memories = executor.submit(self._search_vector_store, query, filters, limit)
future_graph_entities = (
executor.submit(self.graph.search, query, filters, limit)
if self.api_version == "v1.1" and self.enable_graph
else None
executor.submit(self.graph.search, query, filters, limit) if self.enable_graph else None
)
concurrent.futures.wait(
@@ -431,20 +428,20 @@ class Memory(MemoryBase):
original_memories = future_memories.result()
graph_entities = future_graph_entities.result() if future_graph_entities else None
if self.api_version == "v1.1":
if self.enable_graph:
return {"results": original_memories, "relations": graph_entities}
else:
return {"results": original_memories}
else:
if self.enable_graph:
return {"results": original_memories, "relations": graph_entities}
if self.api_version == "v1.0":
warnings.warn(
"The current search API output format is deprecated. "
"The current get_all API output format is deprecated. "
"To use the latest format, set `api_version='v1.1'`. "
"The current format will be removed in mem0ai 1.1.0 and later versions.",
category=DeprecationWarning,
stacklevel=2,
)
return original_memories
else:
return {"results": original_memories}
def _search_vector_store(self, query, filters, limit):
embeddings = self.embedding_model.embed(query, "search")
@@ -540,7 +537,7 @@ class Memory(MemoryBase):
logger.info(f"Deleted {len(memories)} memories")
if self.api_version == "v1.1" and self.enable_graph:
if self.enable_graph:
self.graph.delete_all(filters)
return {"message": "Memories deleted successfully!"}
+1
View File
@@ -70,6 +70,7 @@ class VectorStoreFactory:
"redis": "mem0.vector_stores.redis.RedisDB",
"elasticsearch": "mem0.vector_stores.elasticsearch.ElasticsearchDB",
"opensearch": "mem0.vector_stores.opensearch.OpenSearchDB",
"supabase": "mem0.vector_stores.supabase.Supabase",
}
@classmethod
+4 -4
View File
@@ -105,10 +105,10 @@ class ChromaDB(VectorStoreBase):
chromadb.Collection: The created or retrieved collection.
"""
# Skip creating collection if already exists
collections = self.list_cols()
for collection in collections:
if collection.name == name:
logging.debug(f"Collection {name} already exists. Skipping creation.")
collection_info = self.client.get_collection(name=name)
if collection_info:
logging.debug(f"Collection {name} already exists. Skipping creation.")
return collection_info
collection = self.client.get_or_create_collection(
name=name,
+1
View File
@@ -19,6 +19,7 @@ class VectorStoreConfig(BaseModel):
"redis": "RedisDBConfig",
"elasticsearch": "ElasticsearchConfig",
"opensearch": "OpenSearchConfig",
"supabase": "SupabaseConfig",
}
@model_validator(mode="after")
+231
View File
@@ -0,0 +1,231 @@
import logging
import uuid
from typing import List, Optional, Dict, Any
from pydantic import BaseModel
try:
import vecs
except ImportError:
raise ImportError("The 'vecs' library is required. Please install it using 'pip install vecs'.")
from mem0.vector_stores.base import VectorStoreBase
from mem0.configs.vector_stores.supabase import IndexMethod, IndexMeasure
logger = logging.getLogger(__name__)
class OutputData(BaseModel):
id: Optional[str]
score: Optional[float]
payload: Optional[dict]
class Supabase(VectorStoreBase):
def __init__(
self,
connection_string: str,
collection_name: str,
embedding_model_dims: int,
index_method: IndexMethod = IndexMethod.AUTO,
index_measure: IndexMeasure = IndexMeasure.COSINE,
):
"""
Initialize the Supabase vector store using vecs.
Args:
connection_string (str): PostgreSQL connection string
collection_name (str): Collection name
embedding_model_dims (int): Dimension of the embedding vector
index_method (IndexMethod): Index method to use. Defaults to AUTO.
index_measure (IndexMeasure): Distance measure to use. Defaults to COSINE.
"""
self.db = vecs.create_client(connection_string)
self.collection_name = collection_name
self.embedding_model_dims = embedding_model_dims
self.index_method = index_method
self.index_measure = index_measure
collections = self.list_cols()
if collection_name not in collections:
self.create_col(embedding_model_dims)
def _preprocess_filters(self, filters: Optional[dict] = None) -> Optional[dict]:
"""
Preprocess filters to be compatible with vecs.
Args:
filters (Dict, optional): Filters to preprocess. Multiple filters will be
combined with AND logic.
"""
if filters is None:
return None
if len(filters) == 1:
# For single filter, keep the simple format
key, value = next(iter(filters.items()))
return {key: {"$eq": value}}
# For multiple filters, use $and clause
return {"$and": [{key: {"$eq": value}} for key, value in filters.items()]}
def create_col(self, embedding_model_dims: Optional[int] = None) -> None:
"""
Create a new collection with vector support.
Will also initialize vector search index.
Args:
embedding_model_dims (int, optional): Dimension of the embedding vector.
If not provided, uses the dimension specified in initialization.
"""
dims = embedding_model_dims or self.embedding_model_dims
if not dims:
raise ValueError(
"embedding_model_dims must be provided either during initialization or when creating collection"
)
logger.info(f"Creating new collection: {self.collection_name}")
try:
self.collection = self.db.get_or_create_collection(name=self.collection_name, dimension=dims)
self.collection.create_index(method=self.index_method.value, measure=self.index_measure.value)
logger.info(f"Successfully created collection {self.collection_name} with dimension {dims}")
except Exception as e:
logger.error(f"Failed to create collection: {str(e)}")
raise
def insert(
self, vectors: List[List[float]], payloads: Optional[List[dict]] = None, ids: Optional[List[str]] = None
):
"""
Insert vectors into the collection.
Args:
vectors (List[List[float]]): List of vectors to insert
payloads (List[Dict], optional): List of payloads corresponding to vectors
ids (List[str], optional): List of IDs corresponding to vectors
"""
logger.info(f"Inserting {len(vectors)} vectors into collection {self.collection_name}")
if not ids:
ids = [str(uuid.uuid4()) for _ in vectors]
if not payloads:
payloads = [{} for _ in vectors]
records = [(id, vector, payload) for id, vector, payload in zip(ids, vectors, payloads)]
print(records)
self.collection.upsert(records)
def search(self, query: List[float], limit: int = 5, filters: Optional[dict] = None) -> List[OutputData]:
"""
Search for similar vectors.
Args:
query (List[float]): Query vector
limit (int, optional): Number of results to return. Defaults to 5.
filters (Dict, optional): Filters to apply to the search. Defaults to None.
Returns:
List[OutputData]: Search results
"""
filters = self._preprocess_filters(filters)
print(filters)
results = self.collection.query(
data=query, limit=limit, filters=filters, include_metadata=True, include_value=True
)
print(results)
return [OutputData(id=str(result[0]), score=float(result[1]), payload=result[2]) for result in results]
def delete(self, vector_id: str):
"""
Delete a vector by ID.
Args:
vector_id (str): ID of the vector to delete
"""
self.collection.delete([(vector_id,)])
def update(self, vector_id: str, vector: Optional[List[float]] = None, payload: Optional[dict] = None):
"""
Update a vector and/or its payload.
Args:
vector_id (str): ID of the vector to update
vector (List[float], optional): Updated vector
payload (Dict, optional): Updated payload
"""
if vector is None:
# If only updating metadata, we need to get the existing vector
existing = self.get(vector_id)
if existing and existing.payload:
vector = existing.payload.get("vector", [])
if vector:
self.collection.upsert([(vector_id, vector, payload or {})])
def get(self, vector_id: str) -> Optional[OutputData]:
"""
Retrieve a vector by ID.
Args:
vector_id (str): ID of the vector to retrieve
Returns:
Optional[OutputData]: Retrieved vector data or None if not found
"""
result = self.collection.fetch([(vector_id,)])
if not result:
return []
record = result[0]
return OutputData(id=str(record.id), score=None, payload=record.metadata)
def list_cols(self) -> List[str]:
"""
List all collections.
Returns:
List[str]: List of collection names
"""
return self.db.list_collections()
def delete_col(self):
"""Delete the collection."""
self.db.delete_collection(self.collection_name)
def col_info(self) -> dict:
"""
Get information about the collection.
Returns:
Dict: Collection information including name and configuration
"""
info = self.collection.describe()
return {
"name": info.name,
"count": info.vectors,
"dimension": info.dimension,
"index": {"method": info.index_method, "metric": info.distance_metric},
}
def list(self, filters: Optional[dict] = None, limit: int = 100) -> List[OutputData]:
"""
List vectors in the collection.
Args:
filters (Dict, optional): Filters to apply
limit (int, optional): Maximum number of results to return. Defaults to 100.
Returns:
List[OutputData]: List of vectors
"""
filters = self._preprocess_filters(filters)
query = [0] * self.embedding_model_dims
ids = self.collection.query(
data=query, limit=limit, filters=filters, include_metadata=True, include_value=False
)
ids = [id[0] for id in ids]
records = self.collection.fetch(ids=ids)
return [[OutputData(id=str(record[0]), score=None, payload=record[2]) for record in records]]
+1 -1
View File
@@ -1,6 +1,6 @@
[tool.poetry]
name = "mem0ai"
version = "0.1.58"
version = "0.1.61"
description = "Long-term memory for AI Agents"
authors = ["Mem0 <founders@mem0.ai>"]
exclude = [
+8 -4
View File
@@ -41,10 +41,14 @@ def test_add(memory_instance, version, enable_graph):
result = memory_instance.add(messages=[{"role": "user", "content": "Test message"}], user_id="test_user")
assert "results" in result
assert result["results"] == [{"memory": "Test memory", "event": "ADD"}]
assert "relations" in result
assert result["relations"] == []
if enable_graph:
assert "results" in result
assert result["results"] == [{"memory": "Test memory", "event": "ADD"}]
assert "relations" in result
assert result["relations"] == []
else:
assert "results" in result
assert result["results"] == [{"memory": "Test memory", "event": "ADD"}]
memory_instance._add_to_vector_store.assert_called_once_with(
[{"role": "user", "content": "Test message"}], {"user_id": "test_user"}, {"user_id": "test_user"}
+6 -6
View File
@@ -51,21 +51,21 @@ class TestQdrant(unittest.TestCase):
def test_search(self):
query_vector = [0.1, 0.2]
self.client_mock.search.return_value = [{"id": str(uuid.uuid4()), "score": 0.95, "payload": {"key": "value"}}]
mock_point = MagicMock(id=str(uuid.uuid4()), score=0.95, payload={"key": "value"})
self.client_mock.query_points.return_value = MagicMock(points=[mock_point])
results = self.qdrant.search(query=query_vector, limit=1)
self.client_mock.search.assert_called_once_with(
self.client_mock.query_points.assert_called_once_with(
collection_name="test_collection",
query_vector=query_vector,
query=query_vector,
query_filter=None,
limit=1,
)
self.assertEqual(len(results), 1)
self.assertIn("id", results[0])
self.assertIn("score", results[0])
self.assertIn("payload", results[0])
self.assertEqual(results[0].payload, {"key": "value"})
self.assertEqual(results[0].score, 0.95)
def test_delete(self):
vector_id = str(uuid.uuid4())
+178
View File
@@ -0,0 +1,178 @@
from unittest.mock import Mock, patch
import pytest
from mem0.configs.vector_stores.supabase import IndexMeasure, IndexMethod
from mem0.vector_stores.supabase import Supabase
@pytest.fixture
def mock_vecs_client():
with patch("vecs.create_client") as mock_client:
yield mock_client
@pytest.fixture
def mock_collection():
collection = Mock()
collection.name = "test_collection"
collection.vectors = 100
collection.dimension = 1536
collection.index_method = "hnsw"
collection.distance_metric = "cosine_distance"
collection.describe.return_value = collection
return collection
@pytest.fixture
def supabase_instance(mock_vecs_client, mock_collection):
# Set up the mock client to return our mock collection
mock_vecs_client.return_value.get_or_create_collection.return_value = mock_collection
mock_vecs_client.return_value.list_collections.return_value = ["test_collection"]
instance = Supabase(
connection_string="postgresql://user:password@localhost:5432/test",
collection_name="test_collection",
embedding_model_dims=1536,
index_method=IndexMethod.HNSW,
index_measure=IndexMeasure.COSINE,
)
# Manually set the collection attribute since we're mocking the initialization
instance.collection = mock_collection
return instance
def test_create_col(supabase_instance, mock_vecs_client, mock_collection):
supabase_instance.create_col(1536)
mock_vecs_client.return_value.get_or_create_collection.assert_called_with(
name="test_collection",
dimension=1536
)
mock_collection.create_index.assert_called_with(
method="hnsw",
measure="cosine_distance"
)
def test_insert_vectors(supabase_instance, mock_collection):
vectors = [[0.1, 0.2, 0.3], [0.4, 0.5, 0.6]]
payloads = [{"name": "vector1"}, {"name": "vector2"}]
ids = ["id1", "id2"]
supabase_instance.insert(vectors=vectors, payloads=payloads, ids=ids)
expected_records = [
("id1", [0.1, 0.2, 0.3], {"name": "vector1"}),
("id2", [0.4, 0.5, 0.6], {"name": "vector2"})
]
mock_collection.upsert.assert_called_once_with(expected_records)
def test_search_vectors(supabase_instance, mock_collection):
mock_results = [
("id1", 0.9, {"name": "vector1"}),
("id2", 0.8, {"name": "vector2"})
]
mock_collection.query.return_value = mock_results
query = [0.1, 0.2, 0.3]
filters = {"category": "test"}
results = supabase_instance.search(query=query, limit=2, filters=filters)
mock_collection.query.assert_called_once_with(
data=query,
limit=2,
filters={"category": {"$eq": "test"}},
include_metadata=True,
include_value=True
)
assert len(results) == 2
assert results[0].id == "id1"
assert results[0].score == 0.9
assert results[0].payload == {"name": "vector1"}
def test_delete_vector(supabase_instance, mock_collection):
vector_id = "id1"
supabase_instance.delete(vector_id=vector_id)
mock_collection.delete.assert_called_once_with([("id1",)])
def test_update_vector(supabase_instance, mock_collection):
vector_id = "id1"
new_vector = [0.7, 0.8, 0.9]
new_payload = {"name": "updated_vector"}
supabase_instance.update(vector_id=vector_id, vector=new_vector, payload=new_payload)
mock_collection.upsert.assert_called_once_with([("id1", new_vector, new_payload)])
def test_get_vector(supabase_instance, mock_collection):
# Create a Mock object to represent the record
mock_record = Mock()
mock_record.id = "id1"
mock_record.metadata = {"name": "vector1"}
mock_record.values = [0.1, 0.2, 0.3]
# Set the fetch return value to a list containing our mock record
mock_collection.fetch.return_value = [mock_record]
result = supabase_instance.get(vector_id="id1")
mock_collection.fetch.assert_called_once_with([("id1",)])
assert result.id == "id1"
assert result.payload == {"name": "vector1"}
def test_list_vectors(supabase_instance, mock_collection):
mock_query_results = [("id1", 0.9, {}), ("id2", 0.8, {})]
mock_fetch_results = [
("id1", [0.1, 0.2, 0.3], {"name": "vector1"}),
("id2", [0.4, 0.5, 0.6], {"name": "vector2"})
]
mock_collection.query.return_value = mock_query_results
mock_collection.fetch.return_value = mock_fetch_results
results = supabase_instance.list(limit=2, filters={"category": "test"})
assert len(results[0]) == 2
assert results[0][0].id == "id1"
assert results[0][0].payload == {"name": "vector1"}
assert results[0][1].id == "id2"
assert results[0][1].payload == {"name": "vector2"}
def test_col_info(supabase_instance, mock_collection):
info = supabase_instance.col_info()
assert info == {
"name": "test_collection",
"count": 100,
"dimension": 1536,
"index": {
"method": "hnsw",
"metric": "cosine_distance"
}
}
def test_preprocess_filters(supabase_instance):
# Test single filter
single_filter = {"category": "test"}
assert supabase_instance._preprocess_filters(single_filter) == {"category": {"$eq": "test"}}
# Test multiple filters
multi_filter = {"category": "test", "type": "document"}
assert supabase_instance._preprocess_filters(multi_filter) == {
"$and": [
{"category": {"$eq": "test"}},
{"type": {"$eq": "document"}}
]
}
# Test None filters
assert supabase_instance._preprocess_filters(None) is None