Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6e65730b0e | ||
|
|
8452dd598f | ||
|
|
2556c5fe88 | ||
|
|
a4340b2336 | ||
|
|
f4dc5f6c71 | ||
|
|
32ebdaef2f | ||
|
|
4318663697 | ||
|
|
5606c3ffb8 | ||
|
|
c1aba35884 | ||
|
|
d9b48191de | ||
|
|
e06f95cea4 | ||
|
|
b131c4bfc4 | ||
|
|
6acb00731d | ||
|
|
8143f86be6 | ||
|
|
8d07469ba7 | ||
|
|
434b555a29 | ||
|
|
f8071a753b | ||
|
|
d200691e9b | ||
|
|
ecff6315e7 | ||
|
|
ff4510f83d | ||
|
|
308e79bb68 | ||
|
|
48176bd194 | ||
|
|
5cebe9ab52 | ||
|
|
371848cfbc | ||
|
|
8e3ed634d1 | ||
|
|
e9bc4cdc95 | ||
|
|
a236aa2315 | ||
|
|
5660fffa96 | ||
|
|
eba6f77330 | ||
|
|
b5d00e9b6c | ||
|
|
1be0d70d02 | ||
|
|
edb53209ef | ||
|
|
7443e58a9d | ||
|
|
7f25caba47 | ||
|
|
c42934b7fb | ||
|
|
17887b5959 | ||
|
|
5d47f4f060 | ||
|
|
600c9fae63 | ||
|
|
2d0c8fe94e |
@@ -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') }}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
**/node_modules/
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -71,6 +71,12 @@ Install the Mem0 package via pip:
|
||||
pip install mem0ai
|
||||
```
|
||||
|
||||
Install the Mem0 package via npm:
|
||||
|
||||
```bash
|
||||
npm install mem0ai
|
||||
```
|
||||
|
||||
### Basic Usage
|
||||
|
||||
Mem0 requires an LLM to function, with `gpt-4o` from OpenAI as the default. However, it supports a variety of LLMs; for details, refer to our [Supported LLMs documentation](https://docs.mem0.ai/llms).
|
||||
@@ -114,6 +120,8 @@ if __name__ == "__main__":
|
||||
main()
|
||||
```
|
||||
|
||||
See the example for [Node.js](https://docs.mem0.ai/examples/ai_companion_js).
|
||||
|
||||
For more advanced usage and API documentation, visit our [documentation](https://docs.mem0.ai).
|
||||
|
||||
> [!TIP]
|
||||
|
||||
@@ -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,18 +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 |
|
||||
|
||||
| `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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -16,15 +16,31 @@ config = {
|
||||
"embedder": {
|
||||
"provider": "vertexai",
|
||||
"config": {
|
||||
"model": "text-embedding-004"
|
||||
"model": "text-embedding-004",
|
||||
"memory_add_embedding_type": "RETRIEVAL_DOCUMENT",
|
||||
"memory_update_embedding_type": "RETRIEVAL_DOCUMENT",
|
||||
"memory_search_embedding_type": "RETRIEVAL_QUERY"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
- CLASSIFICATION
|
||||
- CLUSTERING
|
||||
- RETRIEVAL_DOCUMENT, RETRIEVAL_QUERY, QUESTION_ANSWERING, FACT_VERIFICATION
|
||||
- CODE_RETRIEVAL_QUERY
|
||||
Check out the [Vertex AI documentation](https://cloud.google.com/vertex-ai/generative-ai/docs/embeddings/task-types#supported_task_types) for more information.
|
||||
|
||||
### Config
|
||||
|
||||
Here are the parameters available for configuring the Vertex AI embedder:
|
||||
@@ -34,3 +50,6 @@ Here are the parameters available for configuring the Vertex AI embedder:
|
||||
| `model` | The name of the Vertex AI embedding model to use | `text-embedding-004` |
|
||||
| `vertex_credentials_json` | Path to the Google Cloud credentials JSON file | `None` |
|
||||
| `embedding_dims` | Dimensions of the embedding model | `256` |
|
||||
| `memory_add_embedding_type` | The type of embedding to use for the add memory action | `RETRIEVAL_DOCUMENT` |
|
||||
| `memory_update_embedding_type` | The type of embedding to use for the update memory action | `RETRIEVAL_DOCUMENT` |
|
||||
| `memory_search_embedding_type` | The type of embedding to use for the search memory action | `RETRIEVAL_QUERY` |
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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 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 |
|
||||
Here's a comprehensive list of all parameters that can be used across different LLMs:
|
||||
|
||||
<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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -13,7 +18,7 @@ config = {
|
||||
"llm": {
|
||||
"provider": "anthropic",
|
||||
"config": {
|
||||
"model": "claude-3-5-sonnet-latest",
|
||||
"model": "claude-3-7-sonnet-latest",
|
||||
"temperature": 0.1,
|
||||
"max_tokens": 2000,
|
||||
}
|
||||
@@ -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).
|
||||
@@ -24,13 +24,19 @@ config = {
|
||||
"config": {
|
||||
"model": "arn:aws:bedrock:us-east-1:123456789012:model/your-model-name",
|
||||
"temperature": 0.2,
|
||||
"max_tokens": 1500,
|
||||
"max_tokens": 2000,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -19,14 +19,20 @@ config = {
|
||||
"config": {
|
||||
"model": "deepseek-chat", # default model
|
||||
"temperature": 0.2,
|
||||
"max_tokens": 1500,
|
||||
"max_tokens": 2000,
|
||||
"top_p": 1.0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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:
|
||||
|
||||
@@ -19,13 +19,19 @@ config = {
|
||||
"config": {
|
||||
"model": "gemini-1.5-flash-latest",
|
||||
"temperature": 0.2,
|
||||
"max_tokens": 1500,
|
||||
"max_tokens": 2000,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
@@ -19,13 +19,19 @@ config = {
|
||||
"config": {
|
||||
"model": "gemini/gemini-pro",
|
||||
"temperature": 0.2,
|
||||
"max_tokens": 1500,
|
||||
"max_tokens": 2000,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -17,15 +22,47 @@ config = {
|
||||
"config": {
|
||||
"model": "mixtral-8x7b-32768",
|
||||
"temperature": 0.1,
|
||||
"max_tokens": 1000,
|
||||
"max_tokens": 2000,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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).
|
||||
@@ -14,13 +14,19 @@ config = {
|
||||
"config": {
|
||||
"model": "gpt-4o-mini",
|
||||
"temperature": 0.2,
|
||||
"max_tokens": 1500,
|
||||
"max_tokens": 2000,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -18,7 +19,7 @@ config = {
|
||||
"config": {
|
||||
"model": "gpt-4o",
|
||||
"temperature": 0.2,
|
||||
"max_tokens": 1500,
|
||||
"max_tokens": 2000,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -15,13 +15,19 @@ config = {
|
||||
"config": {
|
||||
"model": "mistralai/Mixtral-8x7B-Instruct-v0.1",
|
||||
"temperature": 0.2,
|
||||
"max_tokens": 1500,
|
||||
"max_tokens": 2000,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
---
|
||||
title: xAI
|
||||
---
|
||||
|
||||
[xAI](https://x.ai/) is a new AI company founded by Elon Musk that develops large language models, including Grok. Grok is trained on real-time data from X (formerly Twitter) and aims to provide accurate, up-to-date responses with a touch of wit and humor.
|
||||
|
||||
In order to use LLMs from xAI, go to their [platform](https://console.x.ai) and get the API key. Set the API key as `XAI_API_KEY` environment variable to use the model as given below in the example.
|
||||
|
||||
## Usage
|
||||
|
||||
```python
|
||||
import os
|
||||
from mem0 import Memory
|
||||
|
||||
os.environ["OPENAI_API_KEY"] = "your-api-key" # used for embedding model
|
||||
os.environ["XAI_API_KEY"] = "your-api-key"
|
||||
|
||||
config = {
|
||||
"llm": {
|
||||
"provider": "xai",
|
||||
"config": {
|
||||
"model": "grok-2-latest",
|
||||
"temperature": 0.1,
|
||||
"max_tokens": 2000,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
All available parameters for the `xai` config are present in [Master List of All Params in Config](../config).
|
||||
@@ -14,19 +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="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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
@@ -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`
|
||||
@@ -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
|
||||
|
||||
+9
-3
@@ -54,7 +54,7 @@
|
||||
"features/direct-import",
|
||||
"features/async-client",
|
||||
"features/memory-export",
|
||||
"features/webhook"
|
||||
"features/webhooks"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -64,6 +64,8 @@
|
||||
"icon": "code-branch",
|
||||
"pages": [
|
||||
"open-source/quickstart",
|
||||
"open-source/python-quickstart",
|
||||
"open-source-typescript/quickstart",
|
||||
{
|
||||
"group": "Features",
|
||||
"icon": "wrench",
|
||||
@@ -102,7 +104,9 @@
|
||||
"components/llms/models/mistral_AI",
|
||||
"components/llms/models/google_AI",
|
||||
"components/llms/models/aws_bedrock",
|
||||
"components/llms/models/gemini"
|
||||
"components/llms/models/gemini",
|
||||
"components/llms/models/deepseek",
|
||||
"components/llms/models/xAI"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -124,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"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -161,6 +166,7 @@
|
||||
"icon": "lightbulb",
|
||||
"pages": [
|
||||
"examples/overview",
|
||||
"examples/ai_companion_js",
|
||||
"examples/mem0-with-ollama",
|
||||
"examples/personal-ai-tutor",
|
||||
"examples/customer-support-agent",
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
---
|
||||
title: AI Companion in Node.js
|
||||
---
|
||||
|
||||
You can create a personalised AI Companion using Mem0. This guide will walk you through the necessary steps and provide the complete code to get you started.
|
||||
|
||||
## Overview
|
||||
|
||||
The Personalized AI Companion leverages Mem0 to retain information across interactions, enabling a tailored learning experience. It creates memories for each user interaction and integrates with OpenAI's GPT models to provide detailed and context-aware responses to user queries.
|
||||
|
||||
## Setup
|
||||
|
||||
Before you begin, ensure you have Node.js installed and create a new project. Install the required dependencies using npm:
|
||||
|
||||
```bash
|
||||
npm install openai mem0ai
|
||||
```
|
||||
|
||||
## Full Code Example
|
||||
|
||||
Below is the complete code to create and interact with an AI Companion using Mem0:
|
||||
|
||||
```javascript
|
||||
import { OpenAI } from 'openai';
|
||||
import { Memory } from 'mem0ai/oss';
|
||||
import * as readline from 'readline';
|
||||
|
||||
const openaiClient = new OpenAI();
|
||||
const memory = new Memory();
|
||||
|
||||
async function chatWithMemories(message, userId = "default_user") {
|
||||
const relevantMemories = await memory.search(message, { userId: userId });
|
||||
|
||||
const memoriesStr = relevantMemories.results
|
||||
.map(entry => `- ${entry.memory}`)
|
||||
.join('\n');
|
||||
|
||||
const systemPrompt = `You are a helpful AI. Answer the question based on query and memories.
|
||||
User Memories:
|
||||
${memoriesStr}`;
|
||||
|
||||
const messages = [
|
||||
{ role: "system", content: systemPrompt },
|
||||
{ role: "user", content: message }
|
||||
];
|
||||
|
||||
const response = await openaiClient.chat.completions.create({
|
||||
model: "gpt-4o-mini",
|
||||
messages: messages
|
||||
});
|
||||
|
||||
const assistantResponse = response.choices[0].message.content || "";
|
||||
|
||||
messages.push({ role: "assistant", content: assistantResponse });
|
||||
await memory.add(messages, { userId: userId });
|
||||
|
||||
return assistantResponse;
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const rl = readline.createInterface({
|
||||
input: process.stdin,
|
||||
output: process.stdout
|
||||
});
|
||||
|
||||
console.log("Chat with AI (type 'exit' to quit)");
|
||||
|
||||
const askQuestion = () => {
|
||||
return new Promise((resolve) => {
|
||||
rl.question("You: ", (input) => {
|
||||
resolve(input.trim());
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
try {
|
||||
while (true) {
|
||||
const userInput = await askQuestion();
|
||||
|
||||
if (userInput.toLowerCase() === 'exit') {
|
||||
console.log("Goodbye!");
|
||||
rl.close();
|
||||
break;
|
||||
}
|
||||
|
||||
const response = await chatWithMemories(userInput, "sample_user");
|
||||
console.log(`AI: ${response}`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("An error occurred:", error);
|
||||
rl.close();
|
||||
}
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
```
|
||||
|
||||
### Key Components
|
||||
|
||||
1. **Initialization**
|
||||
- The code initializes both OpenAI and Mem0 Memory clients
|
||||
- Uses Node.js's built-in readline module for command-line interaction
|
||||
|
||||
2. **Memory Management (chatWithMemories function)**
|
||||
- Retrieves relevant memories using Mem0's search functionality
|
||||
- Constructs a system prompt that includes past memories
|
||||
- Makes API calls to OpenAI for generating responses
|
||||
- Stores new interactions in memory
|
||||
|
||||
3. **Interactive Chat Interface (main function)**
|
||||
- Creates a command-line interface for user interaction
|
||||
- Handles user input and displays AI responses
|
||||
- Includes graceful exit functionality
|
||||
|
||||
### Environment Setup
|
||||
|
||||
Make sure to set up your environment variables:
|
||||
```bash
|
||||
export OPENAI_API_KEY=your_api_key
|
||||
```
|
||||
|
||||
### Conclusion
|
||||
|
||||
This implementation demonstrates how to create an AI Companion that maintains context across conversations using Mem0's memory capabilities. The system automatically stores and retrieves relevant information, creating a more personalized and context-aware interaction experience.
|
||||
|
||||
As users interact with the system, Mem0's memory system continuously learns and adapts, making future responses more relevant and personalized. This setup is ideal for creating long-term learning AI assistants that can maintain context and provide increasingly personalized responses over time.
|
||||
@@ -37,7 +37,7 @@ config = {
|
||||
"config": {
|
||||
"model": "llama3.1:latest",
|
||||
"temperature": 0,
|
||||
"max_tokens": 8000,
|
||||
"max_tokens": 2000,
|
||||
"ollama_base_url": "http://localhost:11434", # Ensure this URL is correct
|
||||
},
|
||||
},
|
||||
|
||||
@@ -17,6 +17,9 @@ Here are some examples of how Mem0 can be integrated into various applications:
|
||||
## Examples
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="AI Companion in Node.js" icon="square-6" href="/examples/ai_companion_js">
|
||||
Create a Personalized AI Companion using Mem0 in Node.js.
|
||||
</Card>
|
||||
<Card title="Mem0 with Ollama" icon="square-1" href="/examples/mem0-with-ollama">
|
||||
Run Mem0 locally with Ollama.
|
||||
</Card>
|
||||
|
||||
@@ -14,13 +14,17 @@ To use the async client, you first need to initialize it:
|
||||
<CodeGroup>
|
||||
|
||||
```python Python
|
||||
import os
|
||||
from mem0 import AsyncMemoryClient
|
||||
client = AsyncMemoryClient(api_key="your-api-key")
|
||||
|
||||
os.environ["MEM0_API_KEY"] = "your-api-key"
|
||||
|
||||
client = AsyncMemoryClient()
|
||||
```
|
||||
|
||||
```javascript JavaScript
|
||||
const { MemoryClient } = require('mem0ai');
|
||||
const client = new MemoryClient('your-api-key');
|
||||
const client = new MemoryClient({ apiKey: 'your-api-key'});
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
@@ -60,7 +64,7 @@ Search for memories based on a query asynchronously.
|
||||
<CodeGroup>
|
||||
|
||||
```python Python
|
||||
await client.search(query="What is Alice's favorite sport?", user_id="alice")
|
||||
await client.search("What is Alice's favorite sport?", user_id="alice")
|
||||
```
|
||||
|
||||
```javascript JavaScript
|
||||
|
||||
@@ -19,9 +19,12 @@ Here's how to set custom categories:
|
||||
|
||||
<CodeGroup>
|
||||
```python Code
|
||||
import os
|
||||
from mem0 import MemoryClient
|
||||
|
||||
client = MemoryClient(api_key="<your_mem0_api_key>")
|
||||
os.environ["MEM0_API_KEY"] = "your-api-key"
|
||||
|
||||
client = MemoryClient()
|
||||
|
||||
# Update custom categories
|
||||
new_categories = [
|
||||
@@ -95,8 +98,11 @@ You can also set custom categories during the `add` API call. This will override
|
||||
|
||||
<CodeGroup>
|
||||
```python Code
|
||||
import os
|
||||
from mem0 import MemoryClient
|
||||
|
||||
os.environ["MEM0_API_KEY"] = "your-api-key"
|
||||
|
||||
client = MemoryClient(api_key="<your_mem0_api_key>")
|
||||
|
||||
custom_categories = [
|
||||
@@ -148,9 +154,12 @@ Here is the list of **default categories**. If you don't specify any custom cate
|
||||
|
||||
<CodeGroup>
|
||||
```python Code
|
||||
import os
|
||||
from mem0 import MemoryClient
|
||||
|
||||
client = MemoryClient(api_key="<your_mem0_api_key>")
|
||||
os.environ["MEM0_API_KEY"] = "your-api-key"
|
||||
|
||||
client = MemoryClient()
|
||||
|
||||
messages = [
|
||||
{"role": "user", "content": "Hi, my name is Alice."},
|
||||
|
||||
@@ -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 = {
|
||||
@@ -53,7 +79,7 @@ config = {
|
||||
"config": {
|
||||
"model": "gpt-4o",
|
||||
"temperature": 0.2,
|
||||
"max_tokens": 1500,
|
||||
"max_tokens": 2000,
|
||||
}
|
||||
},
|
||||
"custom_prompt": custom_prompt,
|
||||
@@ -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.
|
||||
|
||||
@@ -41,7 +41,7 @@ You can retrieve memories using the `search` method.
|
||||
<CodeGroup>
|
||||
|
||||
```python Python
|
||||
client.search(query="What is Alice's favorite sport?", user_id="alice", output_format="v1.1")
|
||||
client.search("What is Alice's favorite sport?", user_id="alice", output_format="v1.1")
|
||||
```
|
||||
|
||||
```json Output
|
||||
|
||||
@@ -1,21 +1,24 @@
|
||||
---
|
||||
title: Multimodal Support
|
||||
description: Integrate images into your interactions with Mem0
|
||||
icon: "image"
|
||||
iconType: "solid"
|
||||
---
|
||||
|
||||
Mem0 extends its capabilities beyond text by supporting multimodal data, including images. Users can seamlessly integrate images into their interactions, allowing Mem0 to extract pertinent information from visual content and enrich the memory system.
|
||||
Mem0 extends its capabilities beyond text by supporting multimodal data, including images. With this feature, users can seamlessly integrate images into their interactions—allowing Mem0 to extract relevant information from visual content and enrich the memory system.
|
||||
|
||||
## How It Works
|
||||
|
||||
When a user provides an image, Mem0 processes the image to extract textual information and relevant details, which are then added to the user's memory. This feature enhances the system's ability to understand and remember details based on visual inputs.
|
||||
When a user submits an image, Mem0 processes it to extract textual information and other pertinent details. These details are then added to the user's memory, enhancing the system's ability to understand and recall visual inputs.
|
||||
|
||||
<CodeGroup>
|
||||
```python Code
|
||||
import os
|
||||
from mem0 import MemoryClient
|
||||
|
||||
# Initialize the MemoryClient with your API key
|
||||
client = MemoryClient(api_key="your_api_key_here")
|
||||
os.environ["MEM0_API_KEY"] = "your-api-key"
|
||||
|
||||
client = MemoryClient()
|
||||
|
||||
messages = [
|
||||
{
|
||||
@@ -61,13 +64,13 @@ client.add(messages, user_id="alice")
|
||||
|
||||
## Image Integration Methods
|
||||
|
||||
Mem0 allows you to add images to user interactions through two primary methods: by providing an image URL or by using a Base64-encoded image. Below are examples demonstrating each approach.
|
||||
Mem0 supports incorporating images into user interactions using two primary methods: by providing an image URL or by using a Base64-encoded image. The examples below demonstrate both approaches.
|
||||
|
||||
## 1. Using an Image URL (Recommended)
|
||||
|
||||
You can include an image by passing its direct URL. This method is simple and efficient for online images.
|
||||
You can include an image by providing its direct URL. This method is simple and efficient for online images.
|
||||
|
||||
```python
|
||||
```python {2, 5-13}
|
||||
# Define the image URL
|
||||
image_url = "https://www.superhealthykids.com/wp-content/uploads/2021/10/best-veggie-pizza-featured-image-square-2.jpg"
|
||||
|
||||
@@ -81,12 +84,12 @@ image_message = {
|
||||
}
|
||||
}
|
||||
}
|
||||
client.add([image_message], user_id="alice")
|
||||
```
|
||||
|
||||
## 2. Using Base64 Image Encoding for Local Files
|
||||
|
||||
For local images or scenarios where embedding the image directly is preferable, you can use a Base64-encoded string.
|
||||
|
||||
For local images—or when embedding the image directly is preferable—you can use a Base64-encoded string.
|
||||
```python
|
||||
import base64
|
||||
|
||||
@@ -107,9 +110,10 @@ image_message = {
|
||||
}
|
||||
}
|
||||
}
|
||||
client.add([image_message], user_id="alice")
|
||||
```
|
||||
|
||||
By utilizing these methods, you can effectively incorporate images into user interactions, enhancing the multimodal capabilities of your Mem0 instance.
|
||||
Using these methods, you can seamlessly incorporate images into your interactions, further enhancing Mem0's multimodal capabilities.
|
||||
|
||||
If you have any questions, please feel free to reach out to us using one of the following methods:
|
||||
|
||||
|
||||
@@ -29,9 +29,12 @@ Users can define specific kinds of memories to store. This feature enhances memo
|
||||
Here’s how you can do it:
|
||||
|
||||
```python
|
||||
import os
|
||||
from mem0 import MemoryClient
|
||||
|
||||
m = MemoryClient(api_key="xxx")
|
||||
os.environ["MEM0_API_KEY"] = "your-api-key"
|
||||
|
||||
m = MemoryClient()
|
||||
|
||||
# Define what to include
|
||||
includes = "sports related things"
|
||||
|
||||
@@ -7,41 +7,43 @@ iconType: "solid"
|
||||
|
||||
## Overview
|
||||
|
||||
Webhooks allow you to receive real-time notifications when memory events occur in your Mem0 project. Webhooks are configured at the project level, meaning each webhook is associated with a specific project and will only receive events from that project. You can configure webhooks to send HTTP POST requests to your specified URLs whenever memories are created, updated, or deleted.
|
||||
Webhooks enable real-time notifications for memory events in your Mem0 project. Webhooks are configured at the project level, meaning each webhook is tied to a specific project and receives events solely from that project. You can configure webhooks to send HTTP POST requests to your specified URLs whenever memories are created, updated, or deleted.
|
||||
|
||||
## Managing Webhooks
|
||||
|
||||
### Create Webhook
|
||||
|
||||
Create a new webhook for your project. The webhook will only receive events from the specified project:
|
||||
|
||||
Create a webhook for your project; it will receive events only from that project:
|
||||
<CodeGroup>
|
||||
|
||||
```python Python
|
||||
import os
|
||||
from mem0 import MemoryClient
|
||||
|
||||
client = MemoryClient(api_key="your-api-key")
|
||||
os.environ["MEM0_API_KEY"] = "your-api-key"
|
||||
|
||||
client = MemoryClient()
|
||||
|
||||
# Create webhook in a specific project
|
||||
webhook = client.create_webhook(
|
||||
url="https://your-app.com/webhook",
|
||||
name="Memory Logger",
|
||||
project_id="proj_123",
|
||||
event_types=["memory:add"]
|
||||
event_types=["memory_add"]
|
||||
)
|
||||
print(webhook)
|
||||
```
|
||||
|
||||
```javascript JavaScript
|
||||
const { MemoryClient } = require('mem0ai');
|
||||
const client = new MemoryClient('your-api-key');
|
||||
const client = new MemoryClient({ apiKey: 'your-api-key'});
|
||||
|
||||
// Create webhook in a specific project
|
||||
const webhook = await client.createWebhook({
|
||||
url: "https://your-app.com/webhook",
|
||||
name: "Memory Logger",
|
||||
projectId: "proj_123",
|
||||
eventTypes: ["memory:add"]
|
||||
eventTypes: ["memory_add"]
|
||||
});
|
||||
console.log(webhook);
|
||||
```
|
||||
@@ -63,7 +65,7 @@ console.log(webhook);
|
||||
|
||||
### Get Webhooks
|
||||
|
||||
Retrieve all webhooks configured for your project:
|
||||
Retrieve all webhooks for your project:
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
@@ -100,7 +102,7 @@ console.log(webhooks);
|
||||
|
||||
### Update Webhook
|
||||
|
||||
Modify an existing webhook's configuration. Use `webhook_id` to update the parameters of the webhook:
|
||||
Update an existing webhook’s configuration by specifying its `webhook_id`:
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
@@ -109,7 +111,7 @@ Modify an existing webhook's configuration. Use `webhook_id` to update the param
|
||||
updated_webhook = client.update_webhook(
|
||||
name="Updated Logger",
|
||||
url="https://your-app.com/new-webhook",
|
||||
event_types=["memory:update", "memory:add"],
|
||||
event_types=["memory_update", "memory_add"],
|
||||
webhook_id="wh_123"
|
||||
)
|
||||
print(updated_webhook)
|
||||
@@ -120,8 +122,7 @@ print(updated_webhook)
|
||||
const updatedWebhook = await client.updateWebhook({
|
||||
name: "Updated Logger",
|
||||
url: "https://your-app.com/new-webhook",
|
||||
eventTypes: ["memory:update", "memory:add"],
|
||||
projectId: "proj_123",
|
||||
eventTypes: ["memory_update", "memory_add"],
|
||||
webhookId: "wh_123"
|
||||
});
|
||||
console.log(updatedWebhook);
|
||||
@@ -137,7 +138,7 @@ console.log(updatedWebhook);
|
||||
|
||||
### Delete Webhook
|
||||
|
||||
Webhook can be deleted by using the `webhook_id` of the webhook:
|
||||
Delete a webhook by providing its `webhook_id`:
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
@@ -165,13 +166,13 @@ console.log(response);
|
||||
|
||||
Mem0 supports the following event types for webhooks:
|
||||
|
||||
- `memory:add`: Triggered when a new memory is added.
|
||||
- `memory:update`: Triggered when an existing memory is updated.
|
||||
- `memory:delete`: Triggered when a memory is deleted.
|
||||
- `memory_add`: Triggered when a memory is added.
|
||||
- `memory_update`: Triggered when an existing memory is updated.
|
||||
- `memory_delete`: Triggered when a memory is deleted.
|
||||
|
||||
## Webhook Payload
|
||||
|
||||
When a memory event occurs in your project, Mem0 sends a POST request to your webhook URL with the following example payload structure:
|
||||
When a memory event occurs, Mem0 sends an HTTP POST request to your webhook URL with the following payload:
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -187,13 +188,13 @@ When a memory event occurs in your project, Mem0 sends a POST request to your we
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Implement Retry Logic**: Your webhook endpoint should be able to handle temporary failures and implement appropriate retry mechanisms.
|
||||
1. **Implement Retry Logic**: Ensure your webhook endpoint can handle temporary failures by implementing retry logic.
|
||||
|
||||
2. **Verify Webhook Source**: Implement security measures to verify that webhook requests are coming from Mem0.
|
||||
2. **Verify Webhook Source**: Implement security measures to verify that webhook requests originate from Mem0.
|
||||
|
||||
3. **Process Events Asynchronously**: Handle webhook events asynchronously to prevent timeouts and ensure reliable processing.
|
||||
3. **Process Events Asynchronously**: Process webhook events asynchronously to avoid timeouts and ensure reliable handling.
|
||||
|
||||
4. **Monitor Webhook Health**: Regularly check your webhook logs to ensure proper functionality and handle any delivery failures.
|
||||
4. **Monitor Webhook Health**: Regularly review your webhook logs to ensure functionality and promptly address any delivery failures.
|
||||
|
||||
If you have any questions, please feel free to reach out to us using one of the following methods:
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 180 KiB After Width: | Height: | Size: 601 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 169 KiB After Width: | Height: | Size: 224 KiB |
@@ -30,9 +30,10 @@ USER_ID = "customer_service_bot"
|
||||
|
||||
# Set up OpenAI API key
|
||||
os.environ['OPENAI_API_KEY'] = OPENAI_API_KEY
|
||||
os.environ['MEM0_API_KEY'] = MEM0_API_KEY
|
||||
|
||||
# Initialize Mem0 and AutoGen agents
|
||||
memory_client = MemoryClient(api_key=MEM0_API_KEY)
|
||||
memory_client = MemoryClient()
|
||||
agent = ConversableAgent(
|
||||
"chatbot",
|
||||
llm_config={"config_list": [{"model": "gpt-4", "api_key": OPENAI_API_KEY}]},
|
||||
|
||||
@@ -164,3 +164,5 @@ By combining CrewAI with Mem0, you can create sophisticated AI systems that main
|
||||
|
||||
- For CrewAI documentation, visit [CrewAI Documentation](https://docs.crewai.com/)
|
||||
- For Mem0 documentation, refer to the [Mem0 Platform](https://app.mem0.ai/)
|
||||
|
||||
<Snippet file="get-help.mdx" />
|
||||
|
||||
@@ -25,9 +25,11 @@ from langchain_core.tools import StructuredTool
|
||||
from mem0 import MemoryClient
|
||||
from pydantic import BaseModel, Field
|
||||
from typing import List, Dict, Any, Optional
|
||||
import os
|
||||
|
||||
os.environ["MEM0_API_KEY"] = "your-api-key"
|
||||
|
||||
client = MemoryClient(
|
||||
api_key=your_api_key,
|
||||
org_id=your_org_id,
|
||||
project_id=your_project_id
|
||||
)
|
||||
@@ -325,4 +327,10 @@ All tools are implemented as Langchain `StructuredTool` instances, making them c
|
||||
2. Add the tools to your agent's toolset
|
||||
3. The agent can now use these tools to manage memories through natural language interactions
|
||||
|
||||
Each tool provides structured input validation through Pydantic models and returns consistent responses that can be processed by your agent.
|
||||
Each tool provides structured input validation through Pydantic models and returns consistent responses that can be processed by your agent.
|
||||
|
||||
## Help
|
||||
|
||||
In case of any questions, please feel free to reach out to us using one of the following methods:
|
||||
|
||||
<Snippet file="get-help.mdx" />
|
||||
|
||||
@@ -37,7 +37,7 @@ os.environ["MEM0_API_KEY"] = "your-mem0-api-key"
|
||||
|
||||
# Initialize LangChain and Mem0
|
||||
llm = ChatOpenAI(model="gpt-4o-mini")
|
||||
mem0 = MemoryClient(api_key=os.environ["MEM0_API_KEY"])
|
||||
mem0 = MemoryClient()
|
||||
```
|
||||
|
||||
## Create Prompt Template
|
||||
|
||||
@@ -80,7 +80,7 @@ config = {
|
||||
"config": {
|
||||
"model": "gpt-4o",
|
||||
"temperature": 0.2,
|
||||
"max_tokens": 1500,
|
||||
"max_tokens": 2000,
|
||||
},
|
||||
},
|
||||
"embedder": {
|
||||
|
||||
@@ -34,10 +34,11 @@ USER_ID = "your-user-id"
|
||||
|
||||
# Set up OpenAI API key
|
||||
os.environ['OPENAI_API_KEY'] = OPENAI_API_KEY
|
||||
os.environ['MEM0_API_KEY'] = MEM0_API_KEY
|
||||
|
||||
# Initialize Mem0 and MultiOn
|
||||
memory = Memory() # For local usage
|
||||
memory_client = MemoryClient(api_key=MEM0_API_KEY) # For API usage
|
||||
memory_client = MemoryClient() # For API usage
|
||||
multion = MultiOn(api_key=MULTION_API_KEY)
|
||||
```
|
||||
|
||||
@@ -209,3 +210,5 @@ These examples illustrate how combining memory management with web browsing capa
|
||||
- For more details and advanced usage, refer to the full [cookbooks here](https://github.com/mem0ai/mem0/blob/main/cookbooks).
|
||||
- Feel free to visit our [Github](https://github.com/mem0ai/mem0) or [Mem0 Platform](https://app.mem0.ai/).
|
||||
- For any questions or assistance, please reach out to `taranjeetio` on [Discord](https://mem0.dev/DiD).
|
||||
|
||||
<Snippet file="get-help.mdx" />
|
||||
@@ -72,7 +72,7 @@ Here are the available integrations for Mem0:
|
||||
</defs>
|
||||
</svg>
|
||||
}
|
||||
href="/integrations/llamaindex"
|
||||
href="/integrations/llama-index"
|
||||
>
|
||||
Build RAG applications with LlamaIndex and Mem0.
|
||||
</Card>
|
||||
|
||||
@@ -0,0 +1,380 @@
|
||||
---
|
||||
title: Node SDK
|
||||
description: 'Get started with Mem0 quickly!'
|
||||
icon: "node"
|
||||
iconType: "solid"
|
||||
---
|
||||
|
||||
> Welcome to the Mem0 quickstart guide. This guide will help you get up and running with Mem0 in no time.
|
||||
|
||||
## Installation
|
||||
|
||||
To install Mem0, you can use npm. Run the following command in your terminal:
|
||||
|
||||
```bash
|
||||
npm install mem0ai
|
||||
```
|
||||
|
||||
## Basic Usage
|
||||
|
||||
### Initialize Mem0
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Basic">
|
||||
```typescript
|
||||
import { Memory } from 'mem0ai/oss';
|
||||
|
||||
const memory = new Memory();
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Advanced">
|
||||
If you want to run Mem0 in production, initialize using the following method:
|
||||
|
||||
```typescript
|
||||
import { Memory } from 'mem0ai/oss';
|
||||
|
||||
const memory = new Memory({
|
||||
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',
|
||||
},
|
||||
},
|
||||
historyDbPath: 'memory.db',
|
||||
});
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
|
||||
### Store a Memory
|
||||
|
||||
<CodeGroup>
|
||||
```typescript Code
|
||||
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: "user123", metadata: { category: "movie_recommendations" } });
|
||||
```
|
||||
|
||||
```json Output
|
||||
{
|
||||
"results": [
|
||||
{
|
||||
"id": "c03c9045-df76-4949-bbc5-d5dc1932aa5c",
|
||||
"memory": "User is planning to watch a movie tonight.",
|
||||
"metadata": {
|
||||
"category": "movie_recommendations"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "cbb1fe73-0bf1-4067-8c1f-63aa53e7b1a4",
|
||||
"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"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### Retrieve Memories
|
||||
|
||||
<CodeGroup>
|
||||
```typescript Code
|
||||
// Get all memories
|
||||
const allMemories = await memory.getAll({ userId: "user123" });
|
||||
console.log(allMemories)
|
||||
```
|
||||
|
||||
```json Output
|
||||
{
|
||||
"results": [
|
||||
{
|
||||
"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": "2025-02-27T16:33:27.051Z",
|
||||
"metadata": {
|
||||
"category": "movie_recommendations"
|
||||
},
|
||||
"userId": "user123"
|
||||
},
|
||||
{
|
||||
"id": "475bde34-21e6-42ab-8bef-0ab84474f156",
|
||||
"memory": "User loves sci-fi movies.",
|
||||
"hash": "285d07801ae42054732314853e9eadd7",
|
||||
"createdAt": "2025-02-27T16:33:20.560Z",
|
||||
"updatedAt": undefined,
|
||||
"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"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
|
||||
<br />
|
||||
|
||||
<CodeGroup>
|
||||
```typescript Code
|
||||
// Get a single memory by ID
|
||||
const singleMemory = await memory.get('892db2ae-06d9-49e5-8b3e-585ef9b85b8e');
|
||||
console.log(singleMemory);
|
||||
```
|
||||
|
||||
```json Output
|
||||
{
|
||||
"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": {
|
||||
"category": "movie_recommendations"
|
||||
},
|
||||
"userId": "user123"
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### Search Memories
|
||||
|
||||
<CodeGroup>
|
||||
```typescript Code
|
||||
const result = await memory.search('What do you know about me?', { userId: "user123" });
|
||||
console.log(result);
|
||||
```
|
||||
|
||||
```json Output
|
||||
{
|
||||
"results": [
|
||||
{
|
||||
"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.38920719231944799,
|
||||
"metadata": {
|
||||
"category": "movie_recommendations"
|
||||
},
|
||||
"userId": "user123"
|
||||
},
|
||||
{
|
||||
"id": "475bde34-21e6-42ab-8bef-0ab84474f156",
|
||||
"memory": "User loves sci-fi movies.",
|
||||
"hash": "285d07801ae42054732314853e9eadd7",
|
||||
"createdAt": "2025-02-27T16:33:20.560Z",
|
||||
"updatedAt": undefined,
|
||||
"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"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### Update a Memory
|
||||
|
||||
<CodeGroup>
|
||||
```typescript Code
|
||||
const result = await memory.update(
|
||||
'892db2ae-06d9-49e5-8b3e-585ef9b85b8e',
|
||||
'I love India, it is my favorite country.'
|
||||
);
|
||||
console.log(result);
|
||||
```
|
||||
|
||||
```json Output
|
||||
{
|
||||
"message": "Memory updated successfully!"
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### Memory History
|
||||
|
||||
<CodeGroup>
|
||||
```typescript Code
|
||||
const history = await memory.history('892db2ae-06d9-49e5-8b3e-585ef9b85b8e');
|
||||
console.log(history);
|
||||
```
|
||||
|
||||
```json Output
|
||||
[
|
||||
{
|
||||
"id": 39,
|
||||
"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:33:20.557Z",
|
||||
"updated_at": "2025-02-27T16:33:27.051Z",
|
||||
"is_deleted": 0
|
||||
},
|
||||
{
|
||||
"id": 37,
|
||||
"memory_id": "892db2ae-06d9-49e5-8b3e-585ef9b85b8e",
|
||||
"previous_value": null,
|
||||
"new_value": "User is planning to watch a movie tonight.",
|
||||
"action": "ADD",
|
||||
"created_at": "2025-02-27T16:33:20.557Z",
|
||||
"updated_at": null,
|
||||
"is_deleted": 0
|
||||
}
|
||||
]
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### Delete Memory
|
||||
|
||||
```typescript
|
||||
// Delete a memory by id
|
||||
await memory.delete('892db2ae-06d9-49e5-8b3e-585ef9b85b8e');
|
||||
|
||||
// Delete all memories for a user
|
||||
await memory.deleteAll({ userId: "user123" });
|
||||
```
|
||||
|
||||
### Reset Memory
|
||||
|
||||
```typescript
|
||||
await memory.reset(); // Reset all memories
|
||||
```
|
||||
|
||||
## Configuration Parameters
|
||||
|
||||
Mem0 offers extensive configuration options to customize its behavior according to your needs. These configurations span across different components like vector stores, language models, embedders, and graph stores.
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Vector Store Configuration">
|
||||
| Parameter | Description | Default |
|
||||
|-------------|---------------------------------|-------------|
|
||||
| `provider` | Vector store provider (e.g., "memory") | "memory" |
|
||||
| `host` | Host address | "localhost" |
|
||||
| `port` | Port number | undefined |
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="LLM Configuration">
|
||||
| Parameter | Description | Provider |
|
||||
|-----------------------|-----------------------------------------------|-------------------|
|
||||
| `provider` | LLM provider (e.g., "openai", "anthropic") | All |
|
||||
| `model` | Model to use | All |
|
||||
| `temperature` | Temperature of the model | All |
|
||||
| `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 |
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Embedder Configuration">
|
||||
| Parameter | Description | Default |
|
||||
|-------------|---------------------------------|------------------------------|
|
||||
| `provider` | Embedding provider | "openai" |
|
||||
| `model` | Embedding model to use | "text-embedding-3-small" |
|
||||
| `apiKey` | API key for embedding service | None |
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="General Configuration">
|
||||
| Parameter | Description | Default |
|
||||
|------------------|--------------------------------------|----------------------------|
|
||||
| `historyDbPath` | Path to the history database | "{mem0_dir}/history.db" |
|
||||
| `version` | API version | "v1.0" |
|
||||
| `customPrompt` | Custom prompt for memory processing | None |
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Complete Configuration Example">
|
||||
```typescript
|
||||
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',
|
||||
},
|
||||
},
|
||||
historyDbPath: 'memory.db',
|
||||
customPrompt: "I'm a virtual assistant. I'm here to help you with your queries.",
|
||||
}
|
||||
```
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
If you have any questions, please feel free to reach out to us using one of the following methods:
|
||||
|
||||
<Snippet file="get-help.mdx" />
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
@@ -81,7 +79,7 @@ config = {
|
||||
"config": {
|
||||
"model": "gpt-4o",
|
||||
"temperature": 0.2,
|
||||
"max_tokens": 1500,
|
||||
"max_tokens": 2000,
|
||||
}
|
||||
},
|
||||
"graph_store": {
|
||||
@@ -98,8 +96,7 @@ config = {
|
||||
"temperature": 0.0,
|
||||
}
|
||||
}
|
||||
},
|
||||
"version": "v1.1"
|
||||
}
|
||||
}
|
||||
|
||||
m = Memory.from_config(config_dict=config)
|
||||
|
||||
@@ -0,0 +1,480 @@
|
||||
---
|
||||
title: Python SDK
|
||||
description: 'Get started with Mem0 quickly!'
|
||||
icon: "python"
|
||||
iconType: "solid"
|
||||
---
|
||||
|
||||
> Welcome to the Mem0 quickstart guide. This guide will help you get up and running with Mem0 in no time.
|
||||
|
||||
## Installation
|
||||
|
||||
To install Mem0, you can use pip. Run the following command in your terminal:
|
||||
|
||||
```bash
|
||||
pip install mem0ai
|
||||
```
|
||||
|
||||
## Basic Usage
|
||||
|
||||
### Initialize Mem0
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Basic">
|
||||
```python
|
||||
from mem0 import Memory
|
||||
m = Memory()
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Advanced">
|
||||
If you want to run Mem0 in production, initialize using the following method:
|
||||
|
||||
Run Qdrant first:
|
||||
|
||||
```bash
|
||||
docker pull qdrant/qdrant
|
||||
|
||||
docker run -p 6333:6333 -p 6334:6334 \
|
||||
-v $(pwd)/qdrant_storage:/qdrant/storage:z \
|
||||
qdrant/qdrant
|
||||
```
|
||||
|
||||
Then, instantiate memory with qdrant server:
|
||||
|
||||
```python
|
||||
from mem0 import Memory
|
||||
|
||||
config = {
|
||||
"vector_store": {
|
||||
"provider": "qdrant",
|
||||
"config": {
|
||||
"host": "localhost",
|
||||
"port": 6333,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
m = Memory.from_config(config)
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab title="Advanced (Graph Memory)">
|
||||
|
||||
```python
|
||||
from mem0 import Memory
|
||||
|
||||
config = {
|
||||
"graph_store": {
|
||||
"provider": "neo4j",
|
||||
"config": {
|
||||
"url": "neo4j+s://---",
|
||||
"username": "neo4j",
|
||||
"password": "---"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m = Memory.from_config(config_dict=config)
|
||||
```
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
|
||||
### Store a Memory
|
||||
|
||||
<CodeGroup>
|
||||
```python Code
|
||||
# For a user
|
||||
result = m.add("Likes to play cricket on weekends", user_id="alice", metadata={"category": "hobbies"})
|
||||
|
||||
# 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."}
|
||||
# ]
|
||||
# client.add(messages, user_id="alice")
|
||||
```
|
||||
|
||||
```json Output
|
||||
{
|
||||
"results": [
|
||||
{"id": "bf4d4092-cf91-4181-bfeb-b6fa2ed3061b", "memory": "Likes to play cricket on weekends", "event": "ADD"}
|
||||
]
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### Retrieve Memories
|
||||
|
||||
<CodeGroup>
|
||||
```python Code
|
||||
# Get all memories
|
||||
all_memories = m.get_all(user_id="alice")
|
||||
```
|
||||
|
||||
```json Output
|
||||
{
|
||||
"results": [
|
||||
{
|
||||
"id": "bf4d4092-cf91-4181-bfeb-b6fa2ed3061b",
|
||||
"memory": "Likes to play cricket on weekends",
|
||||
"hash": "285d07801ae42054732314853e9eadd7",
|
||||
"metadata": {"category": "hobbies"},
|
||||
"created_at": "2024-10-28T12:32:07.744891-07:00",
|
||||
"updated_at": None,
|
||||
"user_id": "alice"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
|
||||
<br />
|
||||
|
||||
<CodeGroup>
|
||||
```python Code
|
||||
# Get a single memory by ID
|
||||
specific_memory = m.get("bf4d4092-cf91-4181-bfeb-b6fa2ed3061b")
|
||||
```
|
||||
|
||||
```json Output
|
||||
{
|
||||
"id": "bf4d4092-cf91-4181-bfeb-b6fa2ed3061b",
|
||||
"memory": "Likes to play cricket on weekends",
|
||||
"hash": "285d07801ae42054732314853e9eadd7",
|
||||
"metadata": {"category": "hobbies"},
|
||||
"created_at": "2024-10-28T12:32:07.744891-07:00",
|
||||
"updated_at": None,
|
||||
"user_id": "alice"
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### Search Memories
|
||||
|
||||
<CodeGroup>
|
||||
```python Code
|
||||
related_memories = m.search(query="What are Alice's hobbies?", user_id="alice")
|
||||
```
|
||||
|
||||
```json Output
|
||||
{
|
||||
"results": [
|
||||
{
|
||||
"id": "bf4d4092-cf91-4181-bfeb-b6fa2ed3061b",
|
||||
"memory": "Likes to play cricket on weekends",
|
||||
"hash": "285d07801ae42054732314853e9eadd7",
|
||||
"metadata": {"category": "hobbies"},
|
||||
"score": 0.30808347,
|
||||
"created_at": "2024-10-28T12:32:07.744891-07:00",
|
||||
"updated_at": None,
|
||||
"user_id": "alice"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### Update a Memory
|
||||
|
||||
<CodeGroup>
|
||||
```python Code
|
||||
result = m.update(memory_id="bf4d4092-cf91-4181-bfeb-b6fa2ed3061b", data="Likes to play tennis on weekends")
|
||||
```
|
||||
|
||||
```json Output
|
||||
{'message': 'Memory updated successfully!'}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### Memory History
|
||||
|
||||
<CodeGroup>
|
||||
```python Code
|
||||
history = m.history(memory_id="bf4d4092-cf91-4181-bfeb-b6fa2ed3061b")
|
||||
```
|
||||
|
||||
```json Output
|
||||
[
|
||||
{
|
||||
"id": "96d2821d-e551-4089-aa57-9398c421d450",
|
||||
"memory_id": "bf4d4092-cf91-4181-bfeb-b6fa2ed3061b",
|
||||
"old_memory": None,
|
||||
"new_memory": "Likes to play cricket on weekends",
|
||||
"event": "ADD",
|
||||
"created_at": "2024-10-28T12:32:07.744891-07:00",
|
||||
"updated_at": None
|
||||
},
|
||||
{
|
||||
"id": "3db4cb58-c0f1-4dd0-b62a-8123068ebfe7",
|
||||
"memory_id": "bf4d4092-cf91-4181-bfeb-b6fa2ed3061b",
|
||||
"old_memory": "Likes to play cricket on weekends",
|
||||
"new_memory": "Likes to play tennis on weekends",
|
||||
"event": "UPDATE",
|
||||
"created_at": "2024-10-28T12:32:07.744891-07:00",
|
||||
"updated_at": "2024-10-28T13:05:46.987978-07:00"
|
||||
}
|
||||
]
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### Delete Memory
|
||||
|
||||
```python
|
||||
# Delete a memory by id
|
||||
m.delete(memory_id="bf4d4092-cf91-4181-bfeb-b6fa2ed3061b")
|
||||
# Delete all memories for a user
|
||||
m.delete_all(user_id="alice")
|
||||
```
|
||||
|
||||
### Reset Memory
|
||||
|
||||
```python
|
||||
m.reset() # Reset all memories
|
||||
```
|
||||
|
||||
## Configuration Parameters
|
||||
|
||||
Mem0 offers extensive configuration options to customize its behavior according to your needs. These configurations span across different components like vector stores, language models, embedders, and graph stores.
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Vector Store Configuration">
|
||||
| Parameter | Description | Default |
|
||||
|-------------|---------------------------------|-------------|
|
||||
| `provider` | Vector store provider (e.g., "qdrant") | "qdrant" |
|
||||
| `host` | Host address | "localhost" |
|
||||
| `port` | Port number | 6333 |
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="LLM Configuration">
|
||||
| Parameter | Description | Provider |
|
||||
|-----------------------|-----------------------------------------------|-------------------|
|
||||
| `provider` | LLM provider (e.g., "openai", "anthropic") | All |
|
||||
| `model` | Model to use | All |
|
||||
| `temperature` | Temperature of the model | All |
|
||||
| `api_key` | API key to use | All |
|
||||
| `max_tokens` | Tokens to generate | All |
|
||||
| `top_p` | Probability threshold for nucleus sampling | All |
|
||||
| `top_k` | Number of highest probability tokens to keep | All |
|
||||
| `http_client_proxies` | Allow proxy server settings | AzureOpenAI |
|
||||
| `models` | List of models | Openrouter |
|
||||
| `route` | Routing strategy | Openrouter |
|
||||
| `openrouter_base_url` | Base URL for Openrouter API | Openrouter |
|
||||
| `site_url` | Site URL | Openrouter |
|
||||
| `app_name` | Application name | Openrouter |
|
||||
| `ollama_base_url` | Base URL for Ollama API | Ollama |
|
||||
| `openai_base_url` | Base URL for OpenAI API | OpenAI |
|
||||
| `azure_kwargs` | Azure LLM args for initialization | AzureOpenAI |
|
||||
| `deepseek_base_url` | Base URL for DeepSeek API | DeepSeek |
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Embedder Configuration">
|
||||
| Parameter | Description | Default |
|
||||
|-------------|---------------------------------|------------------------------|
|
||||
| `provider` | Embedding provider | "openai" |
|
||||
| `model` | Embedding model to use | "text-embedding-3-small" |
|
||||
| `api_key` | API key for embedding service | None |
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Graph Store Configuration">
|
||||
| Parameter | Description | Default |
|
||||
|-------------|---------------------------------|-------------|
|
||||
| `provider` | Graph store provider (e.g., "neo4j") | "neo4j" |
|
||||
| `url` | Connection URL | None |
|
||||
| `username` | Authentication username | None |
|
||||
| `password` | Authentication password | None |
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="General Configuration">
|
||||
| Parameter | Description | Default |
|
||||
|------------------|--------------------------------------|----------------------------|
|
||||
| `history_db_path` | Path to the history database | "{mem0_dir}/history.db" |
|
||||
| `version` | API version | "v1.1" |
|
||||
| `custom_prompt` | Custom prompt for memory processing | None |
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Complete Configuration Example">
|
||||
```python
|
||||
config = {
|
||||
"vector_store": {
|
||||
"provider": "qdrant",
|
||||
"config": {
|
||||
"host": "localhost",
|
||||
"port": 6333
|
||||
}
|
||||
},
|
||||
"llm": {
|
||||
"provider": "openai",
|
||||
"config": {
|
||||
"api_key": "your-api-key",
|
||||
"model": "gpt-4"
|
||||
}
|
||||
},
|
||||
"embedder": {
|
||||
"provider": "openai",
|
||||
"config": {
|
||||
"api_key": "your-api-key",
|
||||
"model": "text-embedding-3-small"
|
||||
}
|
||||
},
|
||||
"graph_store": {
|
||||
"provider": "neo4j",
|
||||
"config": {
|
||||
"url": "neo4j+s://your-instance",
|
||||
"username": "neo4j",
|
||||
"password": "password"
|
||||
}
|
||||
},
|
||||
"history_db_path": "/path/to/history.db",
|
||||
"version": "v1.1",
|
||||
"custom_prompt": "Optional custom prompt for memory processing"
|
||||
}
|
||||
```
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Run Mem0 Locally
|
||||
|
||||
Please refer to the example [Mem0 with Ollama](../examples/mem0-with-ollama) to run Mem0 locally.
|
||||
|
||||
|
||||
## Chat Completion
|
||||
|
||||
Mem0 can be easily integrated into chat applications to enhance conversational agents with structured memory. Mem0's APIs are designed to be compatible with OpenAI's, with the goal of making it easy to leverage Mem0 in applications you may have already built.
|
||||
|
||||
If you have a `Mem0 API key`, you can use it to initialize the client. Alternatively, you can initialize Mem0 without an API key if you're using it locally.
|
||||
|
||||
Mem0 supports several language models (LLMs) through integration with various [providers](https://litellm.vercel.app/docs/providers).
|
||||
|
||||
## Use Mem0 Platform
|
||||
|
||||
```python
|
||||
from mem0.proxy.main import Mem0
|
||||
|
||||
client = Mem0(api_key="m0-xxx")
|
||||
|
||||
# First interaction: Storing user preferences
|
||||
messages = [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "I love indian food but I cannot eat pizza since allergic to cheese."
|
||||
},
|
||||
]
|
||||
user_id = "alice"
|
||||
chat_completion = client.chat.completions.create(messages=messages, model="gpt-4o-mini", user_id=user_id)
|
||||
# Memory saved after this will look like: "Loves Indian food. Allergic to cheese and cannot eat pizza."
|
||||
|
||||
# Second interaction: Leveraging stored memory
|
||||
messages = [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Suggest restaurants in San Francisco to eat.",
|
||||
}
|
||||
]
|
||||
|
||||
chat_completion = client.chat.completions.create(messages=messages, model="gpt-4o-mini", user_id=user_id)
|
||||
print(chat_completion.choices[0].message.content)
|
||||
# Answer: You might enjoy Indian restaurants in San Francisco, such as Amber India, Dosa, or Curry Up Now, which offer delicious options without cheese.
|
||||
```
|
||||
|
||||
In this example, you can see how the second response is tailored based on the information provided in the first interaction. Mem0 remembers the user's preference for Indian food and their cheese allergy, using this information to provide more relevant and personalized restaurant suggestions in San Francisco.
|
||||
|
||||
### Use Mem0 OSS
|
||||
|
||||
```python
|
||||
config = {
|
||||
"vector_store": {
|
||||
"provider": "qdrant",
|
||||
"config": {
|
||||
"host": "localhost",
|
||||
"port": 6333,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
client = Mem0(config=config)
|
||||
|
||||
chat_completion = client.chat.completions.create(
|
||||
messages=[
|
||||
{
|
||||
"role": "user",
|
||||
"content": "What's the capital of France?",
|
||||
}
|
||||
],
|
||||
model="gpt-4o",
|
||||
)
|
||||
```
|
||||
|
||||
## APIs
|
||||
|
||||
Get started with using Mem0 APIs in your applications. For more details, refer to the [Platform](/platform/quickstart.mdx).
|
||||
|
||||
Here is an example of how to use Mem0 APIs:
|
||||
|
||||
```python
|
||||
import os
|
||||
from mem0 import MemoryClient
|
||||
|
||||
os.environ["MEM0_API_KEY"] = "your-api-key"
|
||||
|
||||
client = MemoryClient() # get api_key from https://app.mem0.ai/
|
||||
|
||||
# Store messages
|
||||
messages = [
|
||||
{"role": "user", "content": "Hi, I'm Alex. I'm a vegetarian and I'm allergic to nuts."},
|
||||
{"role": "assistant", "content": "Hello Alex! I've noted that you're a vegetarian and have a nut allergy. I'll keep this in mind for any food-related recommendations or discussions."}
|
||||
]
|
||||
result = client.add(messages, user_id="alex")
|
||||
print(result)
|
||||
|
||||
# Retrieve memories
|
||||
all_memories = client.get_all(user_id="alex")
|
||||
print(all_memories)
|
||||
|
||||
# Search memories
|
||||
query = "What do you know about me?"
|
||||
related_memories = client.search(query, user_id="alex")
|
||||
|
||||
# Get memory history
|
||||
history = client.history(memory_id="m1")
|
||||
print(history)
|
||||
```
|
||||
|
||||
|
||||
## Contributing
|
||||
|
||||
We welcome contributions to Mem0! Here's how you can contribute:
|
||||
|
||||
1. Fork the repository and create your branch from `main`.
|
||||
2. Clone the forked repository to your local machine.
|
||||
3. Install the project dependencies:
|
||||
|
||||
```bash
|
||||
poetry install
|
||||
```
|
||||
|
||||
4. Install pre-commit hooks:
|
||||
|
||||
```bash
|
||||
pip install pre-commit # If pre-commit is not already installed
|
||||
pre-commit install
|
||||
```
|
||||
|
||||
5. Make your changes and ensure they adhere to the project's coding standards.
|
||||
|
||||
6. Run the tests locally:
|
||||
|
||||
```bash
|
||||
poetry run pytest
|
||||
```
|
||||
|
||||
7. If all tests pass, commit your changes and push to your fork.
|
||||
8. Open a pull request with a clear title and description.
|
||||
|
||||
Please make sure your code follows our coding conventions and is well-documented. We appreciate your contributions to make Mem0 better!
|
||||
|
||||
|
||||
If you have any questions, please feel free to reach out to us using one of the following methods:
|
||||
|
||||
<Snippet file="get-help.mdx" />
|
||||
+19
-479
@@ -1,489 +1,29 @@
|
||||
---
|
||||
title: Guide
|
||||
description: 'Get started with Mem0 quickly!'
|
||||
icon: "book"
|
||||
title: Overview
|
||||
icon: "info"
|
||||
iconType: "solid"
|
||||
---
|
||||
|
||||
> Welcome to the Mem0 quickstart guide. This guide will help you get up and running with Mem0 in no time.
|
||||
Welcome to Mem0 Open Source - a powerful, self-hosted memory management solution for AI agents and assistants. With Mem0 OSS, you get full control over your infrastructure while maintaining complete customization flexibility.
|
||||
|
||||
## Installation
|
||||
We offer two SDKs for Python and Node.js.
|
||||
|
||||
To install Mem0, you can use pip. Run the following command in your terminal:
|
||||
Check out our [GitHub repository](https://mem0.dev/gd) to explore the source code.
|
||||
|
||||
```bash
|
||||
pip install mem0ai
|
||||
```
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Python SDK Guide" icon="python" href="/open-source/python-quickstart">
|
||||
Learn more about Mem0 OSS Python SDK
|
||||
</Card>
|
||||
<Card title="Node.js SDK Guide" icon="node" href="/open-source-typescript/quickstart">
|
||||
Learn more about Mem0 OSS Node.js SDK
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Basic Usage
|
||||
## Key Features
|
||||
|
||||
### Initialize Mem0
|
||||
- **Full Infrastructure Control**: Host Mem0 on your own servers
|
||||
- **Customizable Implementation**: Modify and extend functionality as needed
|
||||
- **Local Development**: Perfect for development and testing
|
||||
- **No Vendor Lock-in**: Own your data and infrastructure
|
||||
- **Community Driven**: Benefit from and contribute to community improvements
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Basic">
|
||||
```python
|
||||
from mem0 import Memory
|
||||
m = Memory()
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Advanced">
|
||||
If you want to run Mem0 in production, initialize using the following method:
|
||||
|
||||
Run Qdrant first:
|
||||
|
||||
```bash
|
||||
docker pull qdrant/qdrant
|
||||
|
||||
docker run -p 6333:6333 -p 6334:6334 \
|
||||
-v $(pwd)/qdrant_storage:/qdrant/storage:z \
|
||||
qdrant/qdrant
|
||||
```
|
||||
|
||||
Then, instantiate memory with qdrant server:
|
||||
|
||||
```python
|
||||
from mem0 import Memory
|
||||
|
||||
config = {
|
||||
"vector_store": {
|
||||
"provider": "qdrant",
|
||||
"config": {
|
||||
"host": "localhost",
|
||||
"port": 6333,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
m = Memory.from_config(config)
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab title="Advanced (Graph Memory)">
|
||||
|
||||
```python
|
||||
from mem0 import Memory
|
||||
|
||||
config = {
|
||||
"graph_store": {
|
||||
"provider": "neo4j",
|
||||
"config": {
|
||||
"url": "neo4j+s://---",
|
||||
"username": "neo4j",
|
||||
"password": "---"
|
||||
}
|
||||
},
|
||||
"version": "v1.1"
|
||||
}
|
||||
|
||||
m = Memory.from_config(config_dict=config)
|
||||
```
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
|
||||
### Store a Memory
|
||||
|
||||
<CodeGroup>
|
||||
```python Code
|
||||
# For a user
|
||||
result = m.add("Likes to play cricket on weekends", user_id="alice", metadata={"category": "hobbies"})
|
||||
|
||||
# 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."}
|
||||
# ]
|
||||
# client.add(messages, user_id="alice")
|
||||
```
|
||||
|
||||
```json Output
|
||||
{
|
||||
"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"}
|
||||
]
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### Retrieve Memories
|
||||
|
||||
<CodeGroup>
|
||||
```python Code
|
||||
# Get all memories
|
||||
all_memories = m.get_all(user_id="alice")
|
||||
```
|
||||
|
||||
```json Output
|
||||
{
|
||||
"results": [
|
||||
{
|
||||
"id": "bf4d4092-cf91-4181-bfeb-b6fa2ed3061b",
|
||||
"memory": "Likes to play cricket on weekends",
|
||||
"hash": "285d07801ae42054732314853e9eadd7",
|
||||
"metadata": {"category": "hobbies"},
|
||||
"created_at": "2024-10-28T12:32:07.744891-07:00",
|
||||
"updated_at": None,
|
||||
"user_id": "alice"
|
||||
}
|
||||
],
|
||||
"relations": [
|
||||
{"source": "alice", "relationship": "likes_to_play", "target": "cricket"},
|
||||
{"source": "alice", "relationship": "plays_on", "target": "weekends"}
|
||||
]
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
|
||||
<br />
|
||||
|
||||
<CodeGroup>
|
||||
```python Code
|
||||
# Get a single memory by ID
|
||||
specific_memory = m.get("bf4d4092-cf91-4181-bfeb-b6fa2ed3061b")
|
||||
```
|
||||
|
||||
```json Output
|
||||
{
|
||||
"id": "bf4d4092-cf91-4181-bfeb-b6fa2ed3061b",
|
||||
"memory": "Likes to play cricket on weekends",
|
||||
"hash": "285d07801ae42054732314853e9eadd7",
|
||||
"metadata": {"category": "hobbies"},
|
||||
"created_at": "2024-10-28T12:32:07.744891-07:00",
|
||||
"updated_at": None,
|
||||
"user_id": "alice"
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### Search Memories
|
||||
|
||||
<CodeGroup>
|
||||
```python Code
|
||||
related_memories = m.search(query="What are Alice's hobbies?", user_id="alice")
|
||||
```
|
||||
|
||||
```json Output
|
||||
{
|
||||
"results": [
|
||||
{
|
||||
"id": "bf4d4092-cf91-4181-bfeb-b6fa2ed3061b",
|
||||
"memory": "Likes to play cricket on weekends",
|
||||
"hash": "285d07801ae42054732314853e9eadd7",
|
||||
"metadata": {"category": "hobbies"},
|
||||
"score": 0.30808347,
|
||||
"created_at": "2024-10-28T12:32:07.744891-07:00",
|
||||
"updated_at": None,
|
||||
"user_id": "alice"
|
||||
}
|
||||
],
|
||||
"relations": [
|
||||
{"source": "alice", "relationship": "plays_on", "target": "weekends"},
|
||||
{"source": "alice", "relationship": "likes_to_play", "target": "cricket"}
|
||||
]
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### Update a Memory
|
||||
|
||||
<CodeGroup>
|
||||
```python Code
|
||||
result = m.update(memory_id="bf4d4092-cf91-4181-bfeb-b6fa2ed3061b", data="Likes to play tennis on weekends")
|
||||
```
|
||||
|
||||
```json Output
|
||||
{'message': 'Memory updated successfully!'}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### Memory History
|
||||
|
||||
<CodeGroup>
|
||||
```python Code
|
||||
history = m.history(memory_id="bf4d4092-cf91-4181-bfeb-b6fa2ed3061b")
|
||||
```
|
||||
|
||||
```json Output
|
||||
[
|
||||
{
|
||||
"id": "96d2821d-e551-4089-aa57-9398c421d450",
|
||||
"memory_id": "bf4d4092-cf91-4181-bfeb-b6fa2ed3061b",
|
||||
"old_memory": None,
|
||||
"new_memory": "Likes to play cricket on weekends",
|
||||
"event": "ADD",
|
||||
"created_at": "2024-10-28T12:32:07.744891-07:00",
|
||||
"updated_at": None
|
||||
},
|
||||
{
|
||||
"id": "3db4cb58-c0f1-4dd0-b62a-8123068ebfe7",
|
||||
"memory_id": "bf4d4092-cf91-4181-bfeb-b6fa2ed3061b",
|
||||
"old_memory": "Likes to play cricket on weekends",
|
||||
"new_memory": "Likes to play tennis on weekends",
|
||||
"event": "UPDATE",
|
||||
"created_at": "2024-10-28T12:32:07.744891-07:00",
|
||||
"updated_at": "2024-10-28T13:05:46.987978-07:00"
|
||||
}
|
||||
]
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### Delete Memory
|
||||
|
||||
```python
|
||||
# Delete a memory by id
|
||||
m.delete(memory_id="bf4d4092-cf91-4181-bfeb-b6fa2ed3061b")
|
||||
# Delete all memories for a user
|
||||
m.delete_all(user_id="alice")
|
||||
```
|
||||
|
||||
### Reset Memory
|
||||
|
||||
```python
|
||||
m.reset() # Reset all memories
|
||||
```
|
||||
|
||||
## Configuration Parameters
|
||||
|
||||
Mem0 offers extensive configuration options to customize its behavior according to your needs. These configurations span across different components like vector stores, language models, embedders, and graph stores.
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Vector Store Configuration">
|
||||
| Parameter | Description | Default |
|
||||
|-------------|---------------------------------|-------------|
|
||||
| `provider` | Vector store provider (e.g., "qdrant") | "qdrant" |
|
||||
| `host` | Host address | "localhost" |
|
||||
| `port` | Port number | 6333 |
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="LLM Configuration">
|
||||
| Parameter | Description | Provider |
|
||||
|-----------------------|-----------------------------------------------|-------------------|
|
||||
| `provider` | LLM provider (e.g., "openai", "anthropic") | All |
|
||||
| `model` | Model to use | All |
|
||||
| `temperature` | Temperature of the model | All |
|
||||
| `api_key` | API key to use | All |
|
||||
| `max_tokens` | Tokens to generate | All |
|
||||
| `top_p` | Probability threshold for nucleus sampling | All |
|
||||
| `top_k` | Number of highest probability tokens to keep | All |
|
||||
| `http_client_proxies` | Allow proxy server settings | AzureOpenAI |
|
||||
| `models` | List of models | Openrouter |
|
||||
| `route` | Routing strategy | Openrouter |
|
||||
| `openrouter_base_url` | Base URL for Openrouter API | Openrouter |
|
||||
| `site_url` | Site URL | Openrouter |
|
||||
| `app_name` | Application name | Openrouter |
|
||||
| `ollama_base_url` | Base URL for Ollama API | Ollama |
|
||||
| `openai_base_url` | Base URL for OpenAI API | OpenAI |
|
||||
| `azure_kwargs` | Azure LLM args for initialization | AzureOpenAI |
|
||||
| `deepseek_base_url` | Base URL for DeepSeek API | DeepSeek |
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Embedder Configuration">
|
||||
| Parameter | Description | Default |
|
||||
|-------------|---------------------------------|------------------------------|
|
||||
| `provider` | Embedding provider | "openai" |
|
||||
| `model` | Embedding model to use | "text-embedding-3-small" |
|
||||
| `api_key` | API key for embedding service | None |
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Graph Store Configuration">
|
||||
| Parameter | Description | Default |
|
||||
|-------------|---------------------------------|-------------|
|
||||
| `provider` | Graph store provider (e.g., "neo4j") | "neo4j" |
|
||||
| `url` | Connection URL | None |
|
||||
| `username` | Authentication username | None |
|
||||
| `password` | Authentication password | None |
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="General Configuration">
|
||||
| Parameter | Description | Default |
|
||||
|------------------|--------------------------------------|----------------------------|
|
||||
| `history_db_path` | Path to the history database | "{mem0_dir}/history.db" |
|
||||
| `version` | API version | "v1.0" |
|
||||
| `custom_prompt` | Custom prompt for memory processing | None |
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Complete Configuration Example">
|
||||
```python
|
||||
config = {
|
||||
"vector_store": {
|
||||
"provider": "qdrant",
|
||||
"config": {
|
||||
"host": "localhost",
|
||||
"port": 6333
|
||||
}
|
||||
},
|
||||
"llm": {
|
||||
"provider": "openai",
|
||||
"config": {
|
||||
"api_key": "your-api-key",
|
||||
"model": "gpt-4"
|
||||
}
|
||||
},
|
||||
"embedder": {
|
||||
"provider": "openai",
|
||||
"config": {
|
||||
"api_key": "your-api-key",
|
||||
"model": "text-embedding-3-small"
|
||||
}
|
||||
},
|
||||
"graph_store": {
|
||||
"provider": "neo4j",
|
||||
"config": {
|
||||
"url": "neo4j+s://your-instance",
|
||||
"username": "neo4j",
|
||||
"password": "password"
|
||||
}
|
||||
},
|
||||
"history_db_path": "/path/to/history.db",
|
||||
"version": "v1.1",
|
||||
"custom_prompt": "Optional custom prompt for memory processing"
|
||||
}
|
||||
```
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Run Mem0 Locally
|
||||
|
||||
Please refer to the example [Mem0 with Ollama](../examples/mem0-with-ollama) to run Mem0 locally.
|
||||
|
||||
|
||||
## Chat Completion
|
||||
|
||||
Mem0 can be easily integrated into chat applications to enhance conversational agents with structured memory. Mem0's APIs are designed to be compatible with OpenAI's, with the goal of making it easy to leverage Mem0 in applications you may have already built.
|
||||
|
||||
If you have a `Mem0 API key`, you can use it to initialize the client. Alternatively, you can initialize Mem0 without an API key if you're using it locally.
|
||||
|
||||
Mem0 supports several language models (LLMs) through integration with various [providers](https://litellm.vercel.app/docs/providers).
|
||||
|
||||
## Use Mem0 Platform
|
||||
|
||||
```python
|
||||
from mem0.proxy.main import Mem0
|
||||
|
||||
client = Mem0(api_key="m0-xxx")
|
||||
|
||||
# First interaction: Storing user preferences
|
||||
messages = [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "I love indian food but I cannot eat pizza since allergic to cheese."
|
||||
},
|
||||
]
|
||||
user_id = "alice"
|
||||
chat_completion = client.chat.completions.create(messages=messages, model="gpt-4o-mini", user_id=user_id)
|
||||
# Memory saved after this will look like: "Loves Indian food. Allergic to cheese and cannot eat pizza."
|
||||
|
||||
# Second interaction: Leveraging stored memory
|
||||
messages = [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Suggest restaurants in San Francisco to eat.",
|
||||
}
|
||||
]
|
||||
|
||||
chat_completion = client.chat.completions.create(messages=messages, model="gpt-4o-mini", user_id=user_id)
|
||||
print(chat_completion.choices[0].message.content)
|
||||
# Answer: You might enjoy Indian restaurants in San Francisco, such as Amber India, Dosa, or Curry Up Now, which offer delicious options without cheese.
|
||||
```
|
||||
|
||||
In this example, you can see how the second response is tailored based on the information provided in the first interaction. Mem0 remembers the user's preference for Indian food and their cheese allergy, using this information to provide more relevant and personalized restaurant suggestions in San Francisco.
|
||||
|
||||
### Use Mem0 OSS
|
||||
|
||||
```python
|
||||
config = {
|
||||
"vector_store": {
|
||||
"provider": "qdrant",
|
||||
"config": {
|
||||
"host": "localhost",
|
||||
"port": 6333,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
client = Mem0(config=config)
|
||||
|
||||
chat_completion = client.chat.completions.create(
|
||||
messages=[
|
||||
{
|
||||
"role": "user",
|
||||
"content": "What's the capital of France?",
|
||||
}
|
||||
],
|
||||
model="gpt-4o",
|
||||
)
|
||||
```
|
||||
|
||||
## APIs
|
||||
|
||||
Get started with using Mem0 APIs in your applications. For more details, refer to the [Platform](/platform/quickstart.mdx).
|
||||
|
||||
Here is an example of how to use Mem0 APIs:
|
||||
|
||||
```python
|
||||
from mem0 import MemoryClient
|
||||
client = MemoryClient(api_key="your-api-key") # get api_key from https://app.mem0.ai/
|
||||
|
||||
# Store messages
|
||||
messages = [
|
||||
{"role": "user", "content": "Hi, I'm Alex. I'm a vegetarian and I'm allergic to nuts."},
|
||||
{"role": "assistant", "content": "Hello Alex! I've noted that you're a vegetarian and have a nut allergy. I'll keep this in mind for any food-related recommendations or discussions."}
|
||||
]
|
||||
result = client.add(messages, user_id="alex")
|
||||
print(result)
|
||||
|
||||
# Retrieve memories
|
||||
all_memories = client.get_all(user_id="alex")
|
||||
print(all_memories)
|
||||
|
||||
# Search memories
|
||||
query = "What do you know about me?"
|
||||
related_memories = client.search(query, user_id="alex")
|
||||
|
||||
# Get memory history
|
||||
history = client.history(memory_id="m1")
|
||||
print(history)
|
||||
```
|
||||
|
||||
|
||||
## Contributing
|
||||
|
||||
We welcome contributions to Mem0! Here's how you can contribute:
|
||||
|
||||
1. Fork the repository and create your branch from `main`.
|
||||
2. Clone the forked repository to your local machine.
|
||||
3. Install the project dependencies:
|
||||
|
||||
```bash
|
||||
poetry install
|
||||
```
|
||||
|
||||
4. Install pre-commit hooks:
|
||||
|
||||
```bash
|
||||
pip install pre-commit # If pre-commit is not already installed
|
||||
pre-commit install
|
||||
```
|
||||
|
||||
5. Make your changes and ensure they adhere to the project's coding standards.
|
||||
|
||||
6. Run the tests locally:
|
||||
|
||||
```bash
|
||||
poetry run pytest
|
||||
```
|
||||
|
||||
7. If all tests pass, commit your changes and push to your fork.
|
||||
8. Open a pull request with a clear title and description.
|
||||
|
||||
Please make sure your code follows our coding conventions and is well-documented. We appreciate your contributions to make Mem0 better!
|
||||
|
||||
|
||||
If you have any questions, please feel free to reach out to us using one of the following methods:
|
||||
|
||||
<Snippet file="get-help.mdx" />
|
||||
+40
-24
@@ -774,26 +774,20 @@
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"total_memories": {
|
||||
"type": "integer"
|
||||
},
|
||||
"owner": {
|
||||
"type": "string"
|
||||
},
|
||||
"immutable": {
|
||||
"type": "boolean",
|
||||
"description": "Whether the memory is immutable.",
|
||||
"title": "Immutable",
|
||||
"default": false
|
||||
},
|
||||
"organization": {
|
||||
"type": "string"
|
||||
},
|
||||
"metadata": {
|
||||
"type": "object"
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"user",
|
||||
"agent",
|
||||
"app",
|
||||
"run"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -1097,6 +1091,7 @@
|
||||
"created_at": {"type": "string", "format": "date-time"},
|
||||
"updated_at": {"type": "string", "format": "date-time"},
|
||||
"categories": {"type": "array", "items": {"type": "string"}},
|
||||
"metadata": {"type": "object"},
|
||||
"keywords": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": {
|
||||
@@ -1117,6 +1112,15 @@
|
||||
"style": "deepObject",
|
||||
"explode": true
|
||||
},
|
||||
{
|
||||
"name": "fields",
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"}
|
||||
},
|
||||
"description": "A list of field names to include in the response. If not provided, all fields will be returned."
|
||||
},
|
||||
{
|
||||
"name": "org_id",
|
||||
"in": "query",
|
||||
@@ -1170,26 +1174,20 @@
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"total_memories": {
|
||||
"type": "integer"
|
||||
},
|
||||
"owner": {
|
||||
"type": "string"
|
||||
},
|
||||
"immutable": {
|
||||
"type": "boolean",
|
||||
"description": "Whether the memory is immutable.",
|
||||
"title": "Immutable",
|
||||
"default": false
|
||||
},
|
||||
"organization": {
|
||||
"type": "string"
|
||||
},
|
||||
"metadata": {
|
||||
"type": "object"
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"user",
|
||||
"agent",
|
||||
"app",
|
||||
"run"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -1320,6 +1318,12 @@
|
||||
},
|
||||
"description": "Categories associated with the memory"
|
||||
},
|
||||
"immutable": {
|
||||
"type": "boolean",
|
||||
"description": "Whether the memory is immutable.",
|
||||
"title": "Immutable",
|
||||
"default": false
|
||||
},
|
||||
"created_at": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
@@ -1441,6 +1445,12 @@
|
||||
},
|
||||
"description": "Categories associated with the memory"
|
||||
},
|
||||
"immutable": {
|
||||
"type": "boolean",
|
||||
"description": "Whether the memory is immutable.",
|
||||
"title": "Immutable",
|
||||
"default": false
|
||||
},
|
||||
"created_at": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
@@ -4782,6 +4792,12 @@
|
||||
"type": "string",
|
||||
"nullable": true
|
||||
},
|
||||
"immutable": {
|
||||
"description": "Whether the memory is immutable.",
|
||||
"title": "Immutable",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"org_id": {
|
||||
"description": "The unique identifier of the organization associated with this memory.",
|
||||
"title": "Organization id",
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ iconType: "solid"
|
||||
---
|
||||
|
||||
<Note type="info">
|
||||
🔔 New Feature: [Webhooks](/features/webhook) are now available! Configure real-time notifications for memory events in your Mem0 project.
|
||||
🎉 We now support [Claude 3.7 Sonnet](components/llms/models/anthropic)! Enhance your AI assistants with the latest and most capable language model from Anthropic.
|
||||
</Note>
|
||||
|
||||
# Introduction
|
||||
|
||||
@@ -405,6 +405,7 @@ curl -X POST "https://api.mem0.ai/v1/memories/search/" \
|
||||
"user_id": "alex",
|
||||
"metadata": {"food": "vegan"},
|
||||
"categories": ["food_preferences"],
|
||||
"immutable": false,
|
||||
"created_at": "2024-07-20T01:30:36.275141-07:00",
|
||||
"updated_at": "2024-07-20T01:30:36.275172-07:00"
|
||||
}
|
||||
@@ -420,6 +421,7 @@ curl -X POST "https://api.mem0.ai/v1/memories/search/" \
|
||||
"user_id": "alex",
|
||||
"metadata": {"food": "vegan"},
|
||||
"categories": ["food_preferences"],
|
||||
"immutable": false,
|
||||
"created_at": "2024-07-20T01:30:36.275141-07:00",
|
||||
"updated_at": "2024-07-20T01:30:36.275172-07:00"
|
||||
}
|
||||
@@ -463,6 +465,7 @@ curl -X POST "https://api.mem0.ai/v1/memories/search/?version=v2" \
|
||||
"user_id": "alex",
|
||||
"metadata": {"food": "vegan"},
|
||||
"categories": ["food_preferences"],
|
||||
"immutable": false,
|
||||
"created_at": "2024-07-20T01:30:36.275141-07:00",
|
||||
"updated_at": "2024-07-20T01:30:36.275172-07:00"
|
||||
}
|
||||
@@ -552,6 +555,7 @@ curl -X POST "https://api.mem0.ai/v1/memories/search/?version=v2" \
|
||||
"user_id": "alex",
|
||||
"metadata": null,
|
||||
"categories": ["food_preferences"],
|
||||
"immutable": false,
|
||||
"created_at": "2024-07-20T01:30:36.275141-07:00",
|
||||
"updated_at": "2024-07-20T01:30:36.275172-07:00"
|
||||
}
|
||||
@@ -616,6 +620,7 @@ curl -X POST "https://api.mem0.ai/v1/memories/search/?version=v2" \
|
||||
"user_id": "alex",
|
||||
"metadata": null,
|
||||
"categories": ["food_preferences"],
|
||||
"immutable": false,
|
||||
"created_at": "2024-07-20T01:30:36.275141-07:00",
|
||||
"updated_at": "2024-07-20T01:30:36.275172-07:00"
|
||||
}
|
||||
@@ -689,6 +694,7 @@ curl -X POST "https://api.mem0.ai/v1/memories/search/?version=v2" \
|
||||
"user_id": "alex",
|
||||
"metadata": {"food": "vegan"},
|
||||
"categories": ["food_preferences"],
|
||||
"immutable": false,
|
||||
"created_at": "2024-07-20T01:30:36.275141-07:00",
|
||||
"updated_at": "2024-07-20T01:30:36.275172-07:00"
|
||||
}
|
||||
@@ -788,6 +794,7 @@ curl -X GET "https://api.mem0.ai/v1/memories/?user_id=alex&page=1&page_size=50"
|
||||
"agent_id":"travel-assistant",
|
||||
"hash":"62bc074f56d1f909f1b4c2b639f56f6a",
|
||||
"metadata":None,
|
||||
"immutable": false,
|
||||
"created_at":"2024-07-25T23:57:00.108347-07:00",
|
||||
"updated_at":"2024-07-25T23:57:00.108367-07:00",
|
||||
"categories":None
|
||||
@@ -798,6 +805,7 @@ curl -X GET "https://api.mem0.ai/v1/memories/?user_id=alex&page=1&page_size=50"
|
||||
"agent_id":"travel-assistant",
|
||||
"hash":"35a305373d639b0bffc6c2a3e2eb4244",
|
||||
"metadata":"None",
|
||||
"immutable": false,
|
||||
"created_at":"2024-07-26T00:31:03.543759-07:00",
|
||||
"updated_at":"2024-07-26T00:31:03.543778-07:00",
|
||||
"categories":None
|
||||
@@ -820,6 +828,7 @@ curl -X GET "https://api.mem0.ai/v1/memories/?user_id=alex&page=1&page_size=50"
|
||||
"agent_id":"travel-assistant",
|
||||
"hash":"62bc074f56d1f909f1b4c2b639f56f6a",
|
||||
"metadata":None,
|
||||
"immutable": false,
|
||||
"created_at":"2024-07-25T23:57:00.108347-07:00",
|
||||
"updated_at":"2024-07-25T23:57:00.108367-07:00",
|
||||
"categories":None
|
||||
@@ -830,6 +839,7 @@ curl -X GET "https://api.mem0.ai/v1/memories/?user_id=alex&page=1&page_size=50"
|
||||
"agent_id":"travel-assistant",
|
||||
"hash":"35a305373d639b0bffc6c2a3e2eb4244",
|
||||
"metadata":"None",
|
||||
"immutable": false,
|
||||
"created_at":"2024-07-26T00:31:03.543759-07:00",
|
||||
"updated_at":"2024-07-26T00:31:03.543778-07:00",
|
||||
"categories":None
|
||||
@@ -873,6 +883,7 @@ curl -X GET "https://api.mem0.ai/v1/memories/?agent_id=ai-tutor&page=1&page_size
|
||||
"agent_id":"ai-tutor",
|
||||
"hash":"62bc074f56d1f909f1b4c2b639f56f6a",
|
||||
"metadata":None,
|
||||
"immutable": false,
|
||||
"created_at":"2024-07-25T23:57:00.108347-07:00",
|
||||
"updated_at":"2024-07-25T23:57:00.108367-07:00",
|
||||
"categories":None
|
||||
@@ -883,6 +894,7 @@ curl -X GET "https://api.mem0.ai/v1/memories/?agent_id=ai-tutor&page=1&page_size
|
||||
"agent_id":"ai-tutor",
|
||||
"hash":"35a305373d639b0bffc6c2a3e2eb4244",
|
||||
"metadata":None,
|
||||
"immutable": false,
|
||||
"created_at":"2024-07-26T00:31:03.543759-07:00",
|
||||
"updated_at":"2024-07-26T00:31:03.543778-07:00",
|
||||
"categories":None
|
||||
@@ -905,6 +917,7 @@ curl -X GET "https://api.mem0.ai/v1/memories/?agent_id=ai-tutor&page=1&page_size
|
||||
"agent_id": "ai-tutor",
|
||||
"hash": "62bc074f56d1f909f1b4c2b639f56f6a",
|
||||
"metadata":None,
|
||||
"immutable": false,
|
||||
"created_at": "2024-07-25T23:57:00.108347-07:00",
|
||||
"updated_at": "2024-07-25T23:57:00.108367-07:00"
|
||||
},
|
||||
@@ -914,6 +927,7 @@ curl -X GET "https://api.mem0.ai/v1/memories/?agent_id=ai-tutor&page=1&page_size
|
||||
"agent_id": "ai-tutor",
|
||||
"hash": "35a305373d639b0bffc6c2a3e2eb4244",
|
||||
"metadata":None,
|
||||
"immutable": false,
|
||||
"created_at": "2024-07-26T00:31:03.543759-07:00",
|
||||
"updated_at": "2024-07-26T00:31:03.543778-07:00"
|
||||
}
|
||||
@@ -955,6 +969,7 @@ curl -X GET "https://api.mem0.ai/v1/memories/?user_id=alex123&run_id=trip-planni
|
||||
"user_id":"alex123",
|
||||
"hash":"d2088c936e259f2f5d2d75543d31401c",
|
||||
"metadata":None,
|
||||
"immutable": false,
|
||||
"created_at":"2024-07-26T00:25:16.566471-07:00",
|
||||
"updated_at":"2024-07-26T00:25:16.566492-07:00",
|
||||
"categories":None
|
||||
@@ -965,6 +980,7 @@ curl -X GET "https://api.mem0.ai/v1/memories/?user_id=alex123&run_id=trip-planni
|
||||
"user_id":"alex123",
|
||||
"hash":"d2088c936e259f2f5d2d75543d31401c",
|
||||
"metadata":None,
|
||||
"immutable": false,
|
||||
"created_at":"2024-07-26T00:33:20.350542-07:00",
|
||||
"updated_at":"2024-07-26T00:33:20.350560-07:00",
|
||||
"categories":None
|
||||
@@ -975,6 +991,7 @@ curl -X GET "https://api.mem0.ai/v1/memories/?user_id=alex123&run_id=trip-planni
|
||||
"user_id":"alex123",
|
||||
"hash":"d2088c936e259f2f5d2d75543d31401c",
|
||||
"metadata":None,
|
||||
"immutable": false,
|
||||
"created_at":"2024-07-26T00:51:09.642275-07:00",
|
||||
"updated_at":"2024-07-26T00:51:09.642295-07:00",
|
||||
"categories":None
|
||||
@@ -997,6 +1014,7 @@ curl -X GET "https://api.mem0.ai/v1/memories/?user_id=alex123&run_id=trip-planni
|
||||
"user_id": "alex123",
|
||||
"hash": "d2088c936e259f2f5d2d75543d31401c",
|
||||
"metadata":None,
|
||||
"immutable": false,
|
||||
"created_at": "2024-07-26T00:25:16.566471-07:00",
|
||||
"updated_at": "2024-07-26T00:25:16.566492-07:00",
|
||||
"categories": ["food_preferences"]
|
||||
@@ -1007,6 +1025,7 @@ curl -X GET "https://api.mem0.ai/v1/memories/?user_id=alex123&run_id=trip-planni
|
||||
"user_id": "alex123",
|
||||
"hash": "d2088c936e259f2f5d2d75543d31401c",
|
||||
"metadata":None,
|
||||
"immutable": false,
|
||||
"created_at": "2024-07-26T00:33:20.350542-07:00",
|
||||
"updated_at": "2024-07-26T00:33:20.350560-07:00",
|
||||
"categories": ["food_preferences"]
|
||||
@@ -1017,6 +1036,7 @@ curl -X GET "https://api.mem0.ai/v1/memories/?user_id=alex123&run_id=trip-planni
|
||||
"user_id": "alex123",
|
||||
"hash": "d2088c936e259f2f5d2d75543d31401c",
|
||||
"metadata":None,
|
||||
"immutable": false,
|
||||
"created_at": "2024-07-26T00:51:09.642275-07:00",
|
||||
"updated_at": "2024-07-26T00:51:09.642295-07:00",
|
||||
"categories": None
|
||||
@@ -1055,6 +1075,7 @@ curl -X GET "https://api.mem0.ai/v1/memories/582bbe6d-506b-48c6-a4c6-5df3b1e6342
|
||||
"user_id":"alex123",
|
||||
"hash":"d2088c936e259f2f5d2d75543d31401c",
|
||||
"metadata":"None",
|
||||
"immutable": false,
|
||||
"created_at":"2024-07-26T00:25:16.566471-07:00",
|
||||
"updated_at":"2024-07-26T00:25:16.566492-07:00",
|
||||
"categories": ["travel"]
|
||||
@@ -1134,6 +1155,7 @@ curl -X GET "https://api.mem0.ai/v1/memories/?user_id=alex123&keywords=to play&p
|
||||
"user_id": "alex123",
|
||||
"hash": "d2088c936e259f2f5d2d75543d31401c",
|
||||
"metadata": null,
|
||||
"immutable": false,
|
||||
"created_at": "2024-07-26T00:25:16.566471-07:00",
|
||||
"updated_at": "2024-07-26T00:25:16.566492-07:00",
|
||||
"categories": ["likes", "food_preferences"]
|
||||
@@ -1144,6 +1166,7 @@ curl -X GET "https://api.mem0.ai/v1/memories/?user_id=alex123&keywords=to play&p
|
||||
"user_id": "alex123",
|
||||
"hash": "d2088c936e259f2f5d2d75543d31401c",
|
||||
"metadata": null,
|
||||
"immutable": false,
|
||||
"created_at": "2024-07-26T00:33:20.350542-07:00",
|
||||
"updated_at": "2024-07-26T00:33:20.350560-07:00",
|
||||
"categories": ["likes"]
|
||||
@@ -1160,7 +1183,7 @@ Our advanced retrieval allows you to set custom filters when fetching memories.
|
||||
|
||||
Here you need to define `version` as `v2` in the get_all method.
|
||||
|
||||
Example: Get all memories using user_id and date filters
|
||||
Example 1. Get all memories using user_id and date filters
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
@@ -1282,6 +1305,7 @@ curl -X GET "https://api.mem0.ai/v1/memories/?version=v2&page=1&page_size=50" \
|
||||
"user_id":"alex",
|
||||
"hash":"62bc074f56d1f909f1b4c2b639f56f6a",
|
||||
"metadata":null,
|
||||
"immutable": false,
|
||||
"created_at":"2024-07-25T23:57:00.108347-07:00",
|
||||
"updated_at":"2024-07-25T23:57:00.108367-07:00",
|
||||
"categories": ["food_preferences"]
|
||||
@@ -1301,6 +1325,125 @@ curl -X GET "https://api.mem0.ai/v1/memories/?version=v2&page=1&page_size=50" \
|
||||
"user_id":"alex",
|
||||
"hash":"62bc074f56d1f909f1b4c2b639f56f6a",
|
||||
"metadata":null,
|
||||
"immutable": false,
|
||||
"created_at":"2024-07-25T23:57:00.108347-07:00",
|
||||
"updated_at":"2024-07-25T23:57:00.108367-07:00",
|
||||
"categories": ["food_preferences"]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
Example 2: Search using metadata and categories Filters
|
||||
<CodeGroup>
|
||||
```python Python
|
||||
filters = {
|
||||
"AND": [
|
||||
{"metadata": {"food": "vegan"}},
|
||||
{
|
||||
"categories":{
|
||||
"contains": "food_preferences"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
# Default (No Pagination)
|
||||
client.get_all(version="v2", filters=filters)
|
||||
|
||||
# Pagination (You can also use the page and page_size parameters)
|
||||
client.get_all(version="v2", filters=filters, page=1, page_size=50)
|
||||
```
|
||||
|
||||
```javascript JavaScript
|
||||
const filters = {
|
||||
"AND": [
|
||||
{"metadata": {"food": "vegan"}},
|
||||
{
|
||||
"categories": {
|
||||
"contains": "food_preferences"
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
// Default (No Pagination)
|
||||
client.getAll({ version: "v2", filters })
|
||||
.then(memories => console.log(memories))
|
||||
.catch(error => console.error(error));
|
||||
|
||||
// Pagination (You can also use the page and page_size parameters)
|
||||
client.getAll({ version: "v2", filters, page: 1, page_size: 50 })
|
||||
.then(memories => console.log(memories))
|
||||
.catch(error => console.error(error));
|
||||
```
|
||||
|
||||
```bash cURL
|
||||
# Default (No Pagination)
|
||||
curl -X GET "https://api.mem0.ai/v1/memories/?version=v2" \
|
||||
-H "Authorization: Token your-api-key" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"filters": {
|
||||
"AND": [
|
||||
{"metadata": {"food": "vegan"}},
|
||||
{
|
||||
"categories": {
|
||||
"contains": "food_preferences"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}'
|
||||
|
||||
# Pagination (You can also use the page and page_size parameters)
|
||||
curl -X GET "https://api.mem0.ai/v1/memories/?version=v2&page=1&page_size=50" \
|
||||
-H "Authorization: Token your-api-key" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"filters": {
|
||||
"AND": [
|
||||
{"metadata": {"food": "vegan"}},
|
||||
{
|
||||
"categories": {
|
||||
"contains": "food_preferences"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}'
|
||||
```
|
||||
|
||||
```json Output (Default)
|
||||
[
|
||||
{
|
||||
"id":"f38b689d-6b24-45b7-bced-17fbb4d8bac7",
|
||||
"memory":"Name: Alex. Vegetarian. Allergic to nuts.",
|
||||
"user_id":"alex",
|
||||
"hash":"62bc074f56d1f909f1b4c2b639f56f6a",
|
||||
"metadata":{"food":"vegan"},
|
||||
"immutable": false,
|
||||
"created_at":"2024-07-25T23:57:00.108347-07:00",
|
||||
"updated_at":"2024-07-25T23:57:00.108367-07:00",
|
||||
"categories": ["food_preferences"]
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
```json Output (Paginated)
|
||||
{
|
||||
"count": 1,
|
||||
"next": null,
|
||||
"previous": null,
|
||||
"results": [
|
||||
{
|
||||
"id":"f38b689d-6b24-45b7-bced-17fbb4d8bac7",
|
||||
"memory":"Name: Alex. Vegetarian. Allergic to nuts.",
|
||||
"user_id":"alex",
|
||||
"hash":"62bc074f56d1f909f1b4c2b639f56f6a",
|
||||
"metadata":{"food":"vegan"},
|
||||
"immutable": false,
|
||||
"created_at":"2024-07-25T23:57:00.108347-07:00",
|
||||
"updated_at":"2024-07-25T23:57:00.108367-07:00",
|
||||
"categories": ["food_preferences"]
|
||||
|
||||
+126
-82
@@ -78,16 +78,20 @@ const client = new MemoryClient({ apiKey: 'your-api-key' });
|
||||
|
||||
```python Python
|
||||
messages = [
|
||||
{"role": "user", "content": "Hi, I'm Alex. I'm a vegetarian and I'm allergic to nuts."},
|
||||
{"role": "assistant", "content": "Hello Alex! I've noted that you're a vegetarian and have a nut allergy. I'll keep this in mind for any food-related recommendations or discussions."}
|
||||
{"role": "user", "content": "Thinking of making a sandwich. What do you recommend?"},
|
||||
{"role": "assistant", "content": "How about adding some cheese for extra flavor?"},
|
||||
{"role": "user", "content": "Actually, I don't like cheese."},
|
||||
{"role": "assistant", "content": "I'll remember that you don't like cheese for future recommendations."}
|
||||
]
|
||||
client.add(messages, user_id="alex")
|
||||
```
|
||||
|
||||
```javascript JavaScript
|
||||
const messages = [
|
||||
{"role": "user", "content": "Hi, I'm Alex. I'm a vegetarian and I'm allergic to nuts."},
|
||||
{"role": "assistant", "content": "Hello Alex! I've noted that you're a vegetarian and have a nut allergy. I'll keep this in mind for any food-related recommendations or discussions."}
|
||||
{"role": "user", "content": "Thinking of making a sandwich. What do you recommend?"},
|
||||
{"role": "assistant", "content": "How about adding some cheese for extra flavor?"},
|
||||
{"role": "user", "content": "Actually, I don't like cheese."},
|
||||
{"role": "assistant", "content": "I'll remember that you don't like cheese for future recommendations."}
|
||||
];
|
||||
client.add(messages, { user_id: "alex" })
|
||||
.then(response => console.log(response))
|
||||
@@ -100,23 +104,28 @@ curl -X POST "https://api.mem0.ai/v1/memories/" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"messages": [
|
||||
{"role": "user", "content": "Hi, I'm Alex. I'm a vegetarian and I'm allergic to nuts."},
|
||||
{"role": "assistant", "content": "Hello Alex! I've noted that you're a vegetarian and have a nut allergy. I'll keep this in mind for any food-related recommendations or discussions."}
|
||||
{"role": "user", "content": "I live in San Francisco. Thinking of making a sandwich. What do you recommend?"},
|
||||
{"role": "assistant", "content": "How about adding some cheese for extra flavor?"},
|
||||
{"role": "user", "content": "Actually, I don't like cheese."},
|
||||
{"role": "assistant", "content": "I'll remember that you don't like cheese for future recommendations."}
|
||||
],
|
||||
"user_id": "alex"
|
||||
}'
|
||||
```
|
||||
|
||||
```json Output
|
||||
[{'id': '24e466b5-e1c6-4bde-8a92-f09a327ffa60',
|
||||
'memory': 'Name is Alex',
|
||||
'event': 'ADD'},
|
||||
{'id': 'f2d874ac-09c7-49db-b34a-22cf666bd4ad',
|
||||
'memory': 'Is a vegetarian',
|
||||
'event': 'ADD'},
|
||||
{'id': 'bce04006-01e8-4dbc-8a22-67fa46f1822c',
|
||||
'memory': 'Is allergic to nuts',
|
||||
'event': 'ADD'}]
|
||||
[
|
||||
{
|
||||
"id": "24e466b5-e1c6-4bde-8a92-f09a327ffa60",
|
||||
"memory": "Does not like cheese",
|
||||
"event": "ADD"
|
||||
},
|
||||
{
|
||||
"id": "e8d78459-fadd-4c5a-bece-abb8c3dc7ed7",
|
||||
"memory": "Lives in San Francisco",
|
||||
"event": "ADD"
|
||||
}
|
||||
]
|
||||
```
|
||||
</CodeGroup>
|
||||
</Accordion>
|
||||
@@ -129,7 +138,8 @@ curl -X POST "https://api.mem0.ai/v1/memories/" \
|
||||
<CodeGroup>
|
||||
|
||||
```python Python
|
||||
query = "What can I cook for dinner tonight?"
|
||||
# Example showing location and preference-aware recommendations
|
||||
query = "I'm craving some pizza. Any recommendations?"
|
||||
filters = {
|
||||
"AND": [
|
||||
{
|
||||
@@ -141,7 +151,7 @@ client.search(query, version="v2", filters=filters)
|
||||
```
|
||||
|
||||
```javascript JavaScript
|
||||
const query = "What can I cook for dinner tonight?";
|
||||
const query = "I'm craving some pizza. Any recommendations?";
|
||||
const filters = {
|
||||
"AND": [
|
||||
{
|
||||
@@ -159,7 +169,7 @@ curl -X POST "https://api.mem0.ai/v1/memories/search/?version=v2" \
|
||||
-H "Authorization: Token your-api-key" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"query": "What can I cook for dinner tonight?",
|
||||
"query": "I'm craving some pizza. Any recommendations?",
|
||||
"filters": {
|
||||
"AND": [
|
||||
{
|
||||
@@ -174,11 +184,21 @@ curl -X POST "https://api.mem0.ai/v1/memories/search/?version=v2" \
|
||||
[
|
||||
{
|
||||
"id": "7f165f7e-b411-4afe-b7e5-35789b72c4a5",
|
||||
"memory": "Name: Alex. Vegetarian. Allergic to nuts.",
|
||||
"memory": "Does not like cheese",
|
||||
"user_id": "alex",
|
||||
"metadata": null,
|
||||
"created_at": "2024-07-20T01:30:36.275141-07:00",
|
||||
"updated_at": "2024-07-20T01:30:36.275172-07:00"
|
||||
"updated_at": "2024-07-20T01:30:36.275172-07:00",
|
||||
"score": 0.92
|
||||
},
|
||||
{
|
||||
"id": "8f165f7e-b411-4afe-b7e5-35789b72c4b6",
|
||||
"memory": "Lives in San Francisco",
|
||||
"user_id": "alex",
|
||||
"metadata": null,
|
||||
"created_at": "2024-07-20T01:30:36.275141-07:00",
|
||||
"updated_at": "2024-07-20T01:30:36.275172-07:00",
|
||||
"score": 0.85
|
||||
}
|
||||
]
|
||||
```
|
||||
@@ -193,7 +213,7 @@ curl -X POST "https://api.mem0.ai/v1/memories/search/?version=v2" \
|
||||
filters = {
|
||||
"AND": [
|
||||
{
|
||||
"user_id": "alice"
|
||||
"user_id": "alex"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -205,7 +225,7 @@ all_memories = client.get_all(version="v2", filters=filters, page=1, page_size=5
|
||||
const filters = {
|
||||
"AND": [
|
||||
{
|
||||
"user_id": "alice"
|
||||
"user_id": "alex"
|
||||
}
|
||||
]
|
||||
};
|
||||
@@ -232,24 +252,24 @@ curl -X GET "https://api.mem0.ai/v1/memories/?version=v2&page=1&page_size=50" \
|
||||
|
||||
```json Output
|
||||
[
|
||||
{
|
||||
"id":"f38b689d-6b24-45b7-bced-17fbb4d8bac7",
|
||||
"memory":"是素食主义者,对坚果过敏。",
|
||||
"agent_id":"travel-assistant",
|
||||
"hash":"62bc074f56d1f909f1b4c2b639f56f6a",
|
||||
"metadata":"None",
|
||||
"created_at":"2024-07-25T23:57:00.108347-07:00",
|
||||
"updated_at":"2024-07-25T23:57:00.108367-07:00"
|
||||
},
|
||||
{
|
||||
"id":"0a14d8f0-e364-4f5c-b305-10da1f0d0878",
|
||||
"memory":"Will maintain personalized travel preferences for each user. Provide customized recommendations based on dietary restrictions, interests, and past interactions.",
|
||||
"agent_id":"travel-assistant",
|
||||
"hash":"35a305373d639b0bffc6c2a3e2eb4244",
|
||||
"metadata":"None",
|
||||
"created_at":"2024-07-26T00:31:03.543759-07:00",
|
||||
"updated_at":"2024-07-26T00:31:03.543778-07:00"
|
||||
}
|
||||
{
|
||||
"id": "7f165f7e-b411-4afe-b7e5-35789b72c4a5",
|
||||
"memory": "Does not like cheese",
|
||||
"user_id": "alex",
|
||||
"metadata": null,
|
||||
"created_at": "2024-07-20T01:30:36.275141-07:00",
|
||||
"updated_at": "2024-07-20T01:30:36.275172-07:00",
|
||||
"score": 0.92
|
||||
},
|
||||
{
|
||||
"id": "8f165f7e-b411-4afe-b7e5-35789b72c4b6",
|
||||
"memory": "Lives in San Francisco",
|
||||
"user_id": "alex",
|
||||
"metadata": null,
|
||||
"created_at": "2024-07-20T01:30:36.275141-07:00",
|
||||
"updated_at": "2024-07-20T01:30:36.275172-07:00",
|
||||
"score": 0.85
|
||||
}
|
||||
]
|
||||
```
|
||||
</CodeGroup>
|
||||
@@ -274,9 +294,15 @@ Follow the steps below to get started with Mem0 Open Source:
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Install package">
|
||||
```bash
|
||||
<CodeGroup>
|
||||
```bash pip
|
||||
pip install mem0ai
|
||||
```
|
||||
|
||||
```bash npm
|
||||
npm install mem0ai
|
||||
```
|
||||
</CodeGroup>
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
@@ -284,22 +310,42 @@ pip install mem0ai
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Instantiate client">
|
||||
<CodeGroup>
|
||||
```python Python
|
||||
from mem0 import Memory
|
||||
m = Memory()
|
||||
```
|
||||
|
||||
```typescript TypeScript
|
||||
import { Memory } from 'mem0ai/oss';
|
||||
const memory = new Memory();
|
||||
```
|
||||
</CodeGroup>
|
||||
</Accordion>
|
||||
<Accordion title="Add memories">
|
||||
<CodeGroup>
|
||||
```python Code
|
||||
# For a user
|
||||
result = m.add("I like to take long walks on weekends.", user_id="alice", metadata={"category": "hobbies"})
|
||||
result = m.add("I like to drink coffee in the morning and go for a walk.", user_id="alice", metadata={"category": "preferences"})
|
||||
```
|
||||
|
||||
```typescript TypeScript
|
||||
const result = memory.add("I like to drink coffee in the morning and go for a walk.", { userId: "alice", metadata: { category: "preferences" } });
|
||||
```
|
||||
|
||||
```json Output
|
||||
[{'id': 'ea9b08ee-09d7-4e8b-9912-687ad65548b4',
|
||||
'memory': 'Likes to take long walks on weekends',
|
||||
'event': 'ADD'}]
|
||||
[
|
||||
{
|
||||
"id": "3dc6f65f-fb3f-4e91-89a8-ed1a22f8898a",
|
||||
"data": {"memory": "Likes to drink coffee in the morning"},
|
||||
"event": "ADD"
|
||||
},
|
||||
{
|
||||
"id": "f1673706-e3d6-4f12-a767-0384c7697d53",
|
||||
"data": {"memory": "Likes to go for a walk"},
|
||||
"event": "ADD"
|
||||
}
|
||||
]
|
||||
```
|
||||
</CodeGroup>
|
||||
</Accordion>
|
||||
@@ -310,52 +356,50 @@ result = m.add("I like to take long walks on weekends.", user_id="alice", metada
|
||||
<AccordionGroup>
|
||||
<Accordion title="Search for relevant memories">
|
||||
<CodeGroup>
|
||||
```python Code
|
||||
related_memories = m.search(query="Help me plan my weekend.", user_id="alice")
|
||||
```python Python
|
||||
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?", { userId: "alice" });
|
||||
```
|
||||
|
||||
```json Output
|
||||
[
|
||||
{
|
||||
"id":"ea925981-272f-40dd-b576-be64e4871429",
|
||||
"memory":"Likes to take long walks on weekends.",
|
||||
"hash":"c8809002-25c1-4c97-a3a2-227ce9c20c53",
|
||||
"metadata":{
|
||||
"category":"hobbies"
|
||||
},
|
||||
"score":0.32116443111457704,
|
||||
"created_at":"2024-07-26T10:29:36.630547-07:00",
|
||||
"updated_at":"None",
|
||||
"user_id":"alice"
|
||||
}
|
||||
{
|
||||
"id": "3dc6f65f-fb3f-4e91-89a8-ed1a22f8898a",
|
||||
"memory": "Likes to drink coffee in the morning",
|
||||
"user_id": "alice",
|
||||
"metadata": {"category": "preferences"},
|
||||
"categories": ["user_preferences", "food"],
|
||||
"immutable": false,
|
||||
"created_at": "2025-02-24T20:11:39.010261-08:00",
|
||||
"updated_at": "2025-02-24T20:11:39.010274-08:00",
|
||||
"score": 0.5915589089130715
|
||||
},
|
||||
{
|
||||
"id": "e8d78459-fadd-4c5a-bece-abb8c3dc7ed7",
|
||||
"memory": "Likes to go for a walk",
|
||||
"user_id": "alice",
|
||||
"metadata": {"category": "preferences"},
|
||||
"categories": ["hobby", "food"],
|
||||
"immutable": false,
|
||||
"created_at": "2025-02-24T11:47:52.893038-08:00",
|
||||
"updated_at": "2025-02-24T11:47:52.893048-08:00",
|
||||
"score": 0.43263634637810866
|
||||
}
|
||||
]
|
||||
```
|
||||
</CodeGroup>
|
||||
</Accordion>
|
||||
<Accordion title="Get all memories of a user">
|
||||
<CodeGroup>
|
||||
```python Code
|
||||
# Get all memories
|
||||
all_memories = m.get_all(user_id="alice")
|
||||
```
|
||||
|
||||
```json Output
|
||||
[
|
||||
{
|
||||
"id":"13efe83b-a8df-4ec0-814e-428d6e8451eb",
|
||||
"memory":"Likes to take long walks on weekends",
|
||||
"hash":"87bcddeb-fe45-4353-bc22-15a841c50308",
|
||||
"metadata":"None",
|
||||
"created_at":"2024-07-26T08:44:41.039788-07:00",
|
||||
"updated_at":"None",
|
||||
"user_id":"alice"
|
||||
}
|
||||
]
|
||||
```
|
||||
</CodeGroup>
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
<Card title="Mem0 Open source" icon="code-branch" href="/open-source/overview">
|
||||
Learn more about Mem0 open source
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Mem0 OSS Python SDK" icon="python" href="/open-source/python-quickstart">
|
||||
Learn more about Mem0 OSS Python SDK
|
||||
</Card>
|
||||
<Card title="Mem0 OSS Node.js SDK" icon="node" href="/open-source-typescript/quickstart">
|
||||
Learn more about Mem0 OSS Node.js SDK
|
||||
</Card>
|
||||
</CardGroup>
|
||||
Generated
+8
-5
@@ -1,4 +1,4 @@
|
||||
# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand.
|
||||
# This file is automatically @generated by Poetry 1.8.4 and should not be changed by hand.
|
||||
|
||||
[[package]]
|
||||
name = "aiohttp"
|
||||
@@ -2805,13 +2805,13 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "mem0ai"
|
||||
version = "0.1.29"
|
||||
version = "0.1.54"
|
||||
description = "Long-term memory for AI Agents"
|
||||
optional = false
|
||||
python-versions = "<4.0,>=3.9"
|
||||
files = [
|
||||
{file = "mem0ai-0.1.29-py3-none-any.whl", hash = "sha256:07bbfd4238d0d7da65d5e4cf75a217eeb5b2829834e399074b05bb046730a57f"},
|
||||
{file = "mem0ai-0.1.29.tar.gz", hash = "sha256:42adefb7a9b241be03fbcabadf5328abf91b4ac390bc97e5966e55e3cac192c5"},
|
||||
{file = "mem0ai-0.1.54-py3-none-any.whl", hash = "sha256:026c3262d714ebe536fb796c53e553051dbe6da66a8a313587efebfd420a0f7a"},
|
||||
{file = "mem0ai-0.1.54.tar.gz", hash = "sha256:f7a0dd2303e59a0131c1dea72058ba165d91e2b3e36d159cc7bbbb062610cc87"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -2822,6 +2822,9 @@ pytz = ">=2024.1,<2025.0"
|
||||
qdrant-client = ">=1.9.1,<2.0.0"
|
||||
sqlalchemy = ">=2.0.31,<3.0.0"
|
||||
|
||||
[package.extras]
|
||||
graph = ["langchain-community (>=0.3.1,<0.4.0)", "neo4j (>=5.23.1,<6.0.0)", "rank-bm25 (>=0.2.2,<0.3.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "milvus-lite"
|
||||
version = "2.4.8"
|
||||
@@ -6667,4 +6670,4 @@ weaviate = ["weaviate-client"]
|
||||
[metadata]
|
||||
lock-version = "2.0"
|
||||
python-versions = ">=3.9,<=3.13"
|
||||
content-hash = "98ab80c76f001e35dd37dd705b4d8e88ecd4377383457aab38c0c94d3b872f33"
|
||||
content-hash = "d7b43f88a863fa5f6835deebeaa1f454a423439e8c9b4b3e923c4d0a2a96e4c6"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[tool.poetry]
|
||||
name = "embedchain"
|
||||
version = "0.1.126"
|
||||
version = "0.1.127"
|
||||
description = "Simplest open source retrieval (RAG) framework"
|
||||
authors = [
|
||||
"Taranjeet Singh <taranjeet@embedchain.ai>",
|
||||
@@ -103,7 +103,7 @@ beautifulsoup4 = "^4.12.2"
|
||||
pypdf = "^5.0.0"
|
||||
gptcache = "^0.1.43"
|
||||
pysbd = "^0.3.4"
|
||||
mem0ai = "^0.1.37"
|
||||
mem0ai = "^0.1.54"
|
||||
tiktoken = { version = "^0.7.0", optional = true }
|
||||
sentence-transformers = { version = "^2.2.2", optional = true }
|
||||
torch = { version = "2.3.0", optional = true }
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@mem0/vercel-ai-provider": "^0.0.7",
|
||||
"@mem0/vercel-ai-provider": "0.0.12",
|
||||
"@radix-ui/react-avatar": "^1.1.1",
|
||||
"@radix-ui/react-dialog": "^1.1.2",
|
||||
"@radix-ui/react-icons": "^1.3.1",
|
||||
@@ -18,7 +18,7 @@
|
||||
"@radix-ui/react-scroll-area": "^1.2.0",
|
||||
"@radix-ui/react-select": "^2.1.2",
|
||||
"@radix-ui/react-slot": "^1.1.0",
|
||||
"ai": "^3.4.31",
|
||||
"ai": "4.1.42",
|
||||
"buffer": "^6.0.3",
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"clsx": "^2.1.1",
|
||||
|
||||
@@ -5,7 +5,7 @@ import { Label } from "@/components/ui/label"
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
|
||||
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from "@/components/ui/dialog"
|
||||
import GlobalContext from '@/contexts/GlobalContext'
|
||||
|
||||
import { Provider } from '@/constants/messages'
|
||||
export default function ApiSettingsPopup(props: { isOpen: boolean, setIsOpen: Dispatch<SetStateAction<boolean>> }) {
|
||||
const {isOpen, setIsOpen} = props
|
||||
const [mem0ApiKey, setMem0ApiKey] = useState('')
|
||||
@@ -15,7 +15,7 @@ export default function ApiSettingsPopup(props: { isOpen: boolean, setIsOpen: Di
|
||||
|
||||
const handleSave = () => {
|
||||
// Here you would typically save the settings to your backend or local storage
|
||||
selectorHandler(mem0ApiKey, providerApiKey, provider);
|
||||
selectorHandler(mem0ApiKey, providerApiKey, provider as Provider);
|
||||
setIsOpen(false)
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
import { Message } from "@/types";
|
||||
|
||||
export const WELCOME_MESSAGE: Message = {
|
||||
id: "1",
|
||||
content: "👋 Hi there! I'm your personal assistant. How can I help you today? 😊",
|
||||
sender: "assistant",
|
||||
timestamp: new Date().toLocaleTimeString(),
|
||||
};
|
||||
|
||||
export const INVALID_CONFIG_MESSAGE: Message = {
|
||||
id: "2",
|
||||
content: "Invalid configuration. Please check your API keys, and add a user and try again.",
|
||||
sender: "assistant",
|
||||
timestamp: new Date().toLocaleTimeString(),
|
||||
};
|
||||
|
||||
export const ERROR_MESSAGE: Message = {
|
||||
id: "3",
|
||||
content: "Something went wrong. Please try again.",
|
||||
sender: "assistant",
|
||||
timestamp: new Date().toLocaleTimeString(),
|
||||
};
|
||||
|
||||
export const AI_MODELS = {
|
||||
openai: "gpt-4o",
|
||||
anthropic: "claude-3-haiku-20240307",
|
||||
cohere: "command-r-plus",
|
||||
groq: "gemma2-9b-it",
|
||||
} as const;
|
||||
|
||||
export type Provider = keyof typeof AI_MODELS;
|
||||
@@ -1,281 +1,84 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import { createContext, useEffect, useState } from "react";
|
||||
import { createMem0, searchMemories } from "@mem0/vercel-ai-provider";
|
||||
import { LanguageModelV1Prompt, streamText } from "ai";
|
||||
import { Message, Memory, FileInfo } from "@/types";
|
||||
import { Buffer } from 'buffer';
|
||||
import { createContext } from 'react';
|
||||
import { Message, Memory, FileInfo } from '@/types';
|
||||
import { useAuth } from '@/hooks/useAuth';
|
||||
import { useChat } from '@/hooks/useChat';
|
||||
import { useFileHandler } from '@/hooks/useFileHandler';
|
||||
import { Provider } from '@/constants/messages';
|
||||
|
||||
const GlobalContext = createContext<any>({});
|
||||
|
||||
const WelcomeMessage: Message = {
|
||||
id: "1",
|
||||
content:
|
||||
"👋 Hi there! I'm your personal assistant. How can I help you today? 😊",
|
||||
sender: "assistant",
|
||||
timestamp: new Date().toLocaleTimeString(),
|
||||
};
|
||||
|
||||
const InvalidConfigMessage: Message = {
|
||||
id: "2",
|
||||
content:
|
||||
"Invalid configuration. Please check your API keys, and add a user and try again.",
|
||||
sender: "assistant",
|
||||
timestamp: new Date().toLocaleTimeString(),
|
||||
};
|
||||
|
||||
const SomethingWentWrongMessage: Message = {
|
||||
id: "3",
|
||||
content: "Something went wrong. Please try again.",
|
||||
sender: "assistant",
|
||||
timestamp: new Date().toLocaleTimeString(),
|
||||
};
|
||||
|
||||
const models = {
|
||||
"openai": "gpt-4o",
|
||||
"anthropic": "claude-3-haiku-20240307",
|
||||
"cohere": "command-r-plus",
|
||||
"groq": "gemma2-9b-it"
|
||||
interface GlobalContextType {
|
||||
selectedUser: string;
|
||||
selectUserHandler: (user: string) => void;
|
||||
clearUserHandler: () => void;
|
||||
messages: Message[];
|
||||
memories: Memory[];
|
||||
handleSend: (content: string) => Promise<void>;
|
||||
thinking: boolean;
|
||||
selectedMem0Key: string;
|
||||
selectedOpenAIKey: string;
|
||||
selectedProvider: Provider;
|
||||
selectorHandler: (mem0: string, openai: string, provider: Provider) => void;
|
||||
clearConfiguration: () => void;
|
||||
selectedFile: FileInfo | null;
|
||||
setSelectedFile: (file: FileInfo | null) => void;
|
||||
file: File | null;
|
||||
setFile: (file: File | null) => void;
|
||||
}
|
||||
|
||||
const getModel = (provider: string) => {
|
||||
switch (provider) {
|
||||
case "openai":
|
||||
return models.openai;
|
||||
case "anthropic":
|
||||
return models.anthropic;
|
||||
case "cohere":
|
||||
return models.cohere;
|
||||
case "groq":
|
||||
return models.groq;
|
||||
default:
|
||||
return models.openai;
|
||||
}
|
||||
}
|
||||
const GlobalContext = createContext<GlobalContextType>({} as GlobalContextType);
|
||||
|
||||
const GlobalState = (props: any) => {
|
||||
const [memories, setMemories] = useState<Memory[]>([]);
|
||||
const [messages, setMessages] = useState<Message[]>([]);
|
||||
const [selectedUser, setSelectedUser] = useState<string>("");
|
||||
const [thinking, setThinking] = useState<boolean>(false);
|
||||
const [selectedOpenAIKey, setSelectedOpenAIKey] = useState<string>("");
|
||||
const [selectedMem0Key, setSelectedMem0Key] = useState<string>("");
|
||||
const [selectedProvider, setSelectedProvider] = useState<string>("openai");
|
||||
const [selectedFile, setSelectedFile] = useState<FileInfo | null>(null)
|
||||
const [file, setFile] = useState<any>(null)
|
||||
|
||||
const mem0 = createMem0({
|
||||
provider: selectedProvider,
|
||||
const GlobalState = (props: { children: React.ReactNode }) => {
|
||||
const {
|
||||
mem0ApiKey: selectedMem0Key,
|
||||
apiKey: selectedOpenAIKey,
|
||||
openaiApiKey: selectedOpenAIKey,
|
||||
provider: selectedProvider,
|
||||
user: selectedUser,
|
||||
setAuth: selectorHandler,
|
||||
setUser: selectUserHandler,
|
||||
clearAuth: clearConfiguration,
|
||||
clearUser: clearUserHandler,
|
||||
} = useAuth();
|
||||
|
||||
const {
|
||||
selectedFile,
|
||||
file,
|
||||
fileData,
|
||||
setSelectedFile,
|
||||
handleFile,
|
||||
clearFile,
|
||||
} = useFileHandler();
|
||||
|
||||
const {
|
||||
messages,
|
||||
memories,
|
||||
thinking,
|
||||
sendMessage,
|
||||
} = useChat({
|
||||
user: selectedUser,
|
||||
mem0ApiKey: selectedMem0Key,
|
||||
openaiApiKey: selectedOpenAIKey,
|
||||
provider: selectedProvider,
|
||||
});
|
||||
|
||||
const clearConfiguration = () => {
|
||||
localStorage.removeItem("mem0ApiKey");
|
||||
localStorage.removeItem("openaiApiKey");
|
||||
localStorage.removeItem("provider");
|
||||
setSelectedMem0Key("");
|
||||
setSelectedOpenAIKey("");
|
||||
setSelectedProvider("openai");
|
||||
setSelectedUser("");
|
||||
setMessages([WelcomeMessage]);
|
||||
setMemories([]);
|
||||
setFile(null);
|
||||
};
|
||||
|
||||
const selectorHandler = (mem0: string, openai: string, provider: string) => {
|
||||
setSelectedMem0Key(mem0);
|
||||
setSelectedOpenAIKey(openai);
|
||||
setSelectedProvider(provider);
|
||||
localStorage.setItem("mem0ApiKey", mem0);
|
||||
localStorage.setItem("openaiApiKey", openai);
|
||||
localStorage.setItem("provider", provider);
|
||||
};
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
const mem0 = localStorage.getItem("mem0ApiKey");
|
||||
const openai = localStorage.getItem("openaiApiKey");
|
||||
const provider = localStorage.getItem("provider");
|
||||
const user = localStorage.getItem("user");
|
||||
if (mem0 && openai && provider) {
|
||||
selectorHandler(mem0, openai, provider);
|
||||
}
|
||||
if (user) {
|
||||
setSelectedUser(user);
|
||||
}
|
||||
}, []);
|
||||
|
||||
const selectUserHandler = (user: string) => {
|
||||
setSelectedUser(user);
|
||||
localStorage.setItem("user", user);
|
||||
};
|
||||
|
||||
const clearUserHandler = () => {
|
||||
setSelectedUser("");
|
||||
setMemories([]);
|
||||
};
|
||||
|
||||
const getMemories = async (messages: LanguageModelV1Prompt) => {
|
||||
try {
|
||||
const smemories = await searchMemories(messages, {
|
||||
user_id: selectedUser || "",
|
||||
mem0ApiKey: selectedMem0Key,
|
||||
});
|
||||
|
||||
const newMemories = smemories.map((memory: any) => ({
|
||||
id: memory.id,
|
||||
content: memory.memory,
|
||||
timestamp: memory.updated_at,
|
||||
tags: memory.categories,
|
||||
}));
|
||||
setMemories(newMemories);
|
||||
} catch (error) {
|
||||
console.error("Error in getMemories:", error);
|
||||
}
|
||||
};
|
||||
|
||||
const handleSend = async (inputValue: string) => {
|
||||
if (!inputValue.trim() && !file) return;
|
||||
if (!selectedUser) {
|
||||
const newMessage: Message = {
|
||||
id: Date.now().toString(),
|
||||
content: inputValue,
|
||||
sender: "user",
|
||||
timestamp: new Date().toLocaleTimeString(),
|
||||
};
|
||||
setMessages((prev) => [...prev, newMessage, InvalidConfigMessage]);
|
||||
return;
|
||||
}
|
||||
|
||||
const userMessage: Message = {
|
||||
id: Date.now().toString(),
|
||||
content: inputValue,
|
||||
sender: "user",
|
||||
timestamp: new Date().toLocaleTimeString(),
|
||||
};
|
||||
|
||||
let fileData;
|
||||
const handleSend = async (content: string) => {
|
||||
if (file) {
|
||||
if (file.type.startsWith("image/")) {
|
||||
// Convert image to Base64
|
||||
fileData = await convertToBase64(file);
|
||||
userMessage.image = fileData;
|
||||
} else if (file.type.startsWith("audio/")) {
|
||||
// Convert audio to ArrayBuffer
|
||||
fileData = await getFileBuffer(file);
|
||||
userMessage.audio = fileData;
|
||||
}
|
||||
}
|
||||
|
||||
// Update the state with the new user message
|
||||
setMessages((prev) => [...prev, userMessage]);
|
||||
setThinking(true);
|
||||
|
||||
// Transform messages into the required format
|
||||
const messagesForPrompt: LanguageModelV1Prompt = [];
|
||||
messages.map((message) => {
|
||||
const messageContent: any = {
|
||||
role: message.sender,
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: message.content,
|
||||
},
|
||||
],
|
||||
};
|
||||
if (message.image) {
|
||||
messageContent.content.push({
|
||||
type: "image",
|
||||
image: message.image,
|
||||
});
|
||||
}
|
||||
if (message.audio) {
|
||||
messageContent.content.push({
|
||||
type: 'file',
|
||||
mimeType: 'audio/mpeg',
|
||||
data: message.audio,
|
||||
});
|
||||
}
|
||||
if(!message.audio) messagesForPrompt.push(messageContent);
|
||||
});
|
||||
|
||||
const newMessage: any = {
|
||||
role: "user",
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: inputValue,
|
||||
},
|
||||
],
|
||||
};
|
||||
if (file) {
|
||||
if (file.type.startsWith("image/")) {
|
||||
newMessage.content.push({
|
||||
type: "image",
|
||||
image: userMessage.image,
|
||||
});
|
||||
} else if (file.type.startsWith("audio/")) {
|
||||
newMessage.content.push({
|
||||
type: 'file',
|
||||
mimeType: 'audio/mpeg',
|
||||
data: userMessage.audio,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
messagesForPrompt.push(newMessage);
|
||||
getMemories(messagesForPrompt);
|
||||
|
||||
setFile(null);
|
||||
setSelectedFile(null);
|
||||
|
||||
try {
|
||||
const { textStream } = await streamText({
|
||||
model: mem0(getModel(selectedProvider), {
|
||||
user_id: selectedUser || "",
|
||||
}),
|
||||
messages: messagesForPrompt,
|
||||
await sendMessage(content, {
|
||||
type: file.type,
|
||||
data: fileData!,
|
||||
});
|
||||
|
||||
const assistantMessageId = Date.now() + 1;
|
||||
const assistantMessage: Message = {
|
||||
id: assistantMessageId.toString(),
|
||||
content: "",
|
||||
sender: "assistant",
|
||||
timestamp: new Date().toLocaleTimeString(),
|
||||
};
|
||||
|
||||
setMessages((prev) => [...prev, assistantMessage]);
|
||||
|
||||
// Stream the text part by part
|
||||
for await (const textPart of textStream) {
|
||||
assistantMessage.content += textPart;
|
||||
setThinking(false);
|
||||
setFile(null);
|
||||
setSelectedFile(null);
|
||||
|
||||
setMessages((prev) =>
|
||||
prev.map((msg) =>
|
||||
msg.id === assistantMessageId.toString()
|
||||
? { ...msg, content: assistantMessage.content }
|
||||
: msg
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
setThinking(false);
|
||||
} catch (error) {
|
||||
console.error("Error in handleSend:", error);
|
||||
setMessages((prev) => [...prev, SomethingWentWrongMessage]);
|
||||
setThinking(false);
|
||||
setFile(null);
|
||||
setSelectedFile(null);
|
||||
clearFile();
|
||||
} else {
|
||||
await sendMessage(content);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setMessages([WelcomeMessage]);
|
||||
}, []);
|
||||
const setFile = async (newFile: File | null) => {
|
||||
if (newFile) {
|
||||
await handleFile(newFile);
|
||||
} else {
|
||||
clearFile();
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<GlobalContext.Provider
|
||||
@@ -295,7 +98,7 @@ const GlobalState = (props: any) => {
|
||||
selectedFile,
|
||||
setSelectedFile,
|
||||
file,
|
||||
setFile
|
||||
setFile,
|
||||
}}
|
||||
>
|
||||
{props.children}
|
||||
@@ -304,21 +107,4 @@ const GlobalState = (props: any) => {
|
||||
};
|
||||
|
||||
export default GlobalContext;
|
||||
export { GlobalState };
|
||||
|
||||
|
||||
const convertToBase64 = (file: File): Promise<string> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
reader.readAsDataURL(file);
|
||||
reader.onload = () => resolve(reader.result as string); // Resolve with Base64 string
|
||||
reader.onerror = error => reject(error); // Reject on error
|
||||
});
|
||||
};
|
||||
|
||||
async function getFileBuffer(file: any) {
|
||||
const response = await fetch(file);
|
||||
const arrayBuffer = await response.arrayBuffer();
|
||||
const buffer = Buffer.from(arrayBuffer);
|
||||
return buffer;
|
||||
}
|
||||
export { GlobalState };
|
||||
@@ -0,0 +1,73 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { Provider } from '@/constants/messages';
|
||||
|
||||
interface UseAuthReturn {
|
||||
mem0ApiKey: string;
|
||||
openaiApiKey: string;
|
||||
provider: Provider;
|
||||
user: string;
|
||||
setAuth: (mem0: string, openai: string, provider: Provider) => void;
|
||||
setUser: (user: string) => void;
|
||||
clearAuth: () => void;
|
||||
clearUser: () => void;
|
||||
}
|
||||
|
||||
export const useAuth = (): UseAuthReturn => {
|
||||
const [mem0ApiKey, setMem0ApiKey] = useState<string>('');
|
||||
const [openaiApiKey, setOpenaiApiKey] = useState<string>('');
|
||||
const [provider, setProvider] = useState<Provider>('openai');
|
||||
const [user, setUser] = useState<string>('');
|
||||
|
||||
useEffect(() => {
|
||||
const mem0 = localStorage.getItem('mem0ApiKey');
|
||||
const openai = localStorage.getItem('openaiApiKey');
|
||||
const savedProvider = localStorage.getItem('provider') as Provider;
|
||||
const savedUser = localStorage.getItem('user');
|
||||
|
||||
if (mem0 && openai && savedProvider) {
|
||||
setAuth(mem0, openai, savedProvider);
|
||||
}
|
||||
if (savedUser) {
|
||||
setUser(savedUser);
|
||||
}
|
||||
}, []);
|
||||
|
||||
const setAuth = (mem0: string, openai: string, provider: Provider) => {
|
||||
setMem0ApiKey(mem0);
|
||||
setOpenaiApiKey(openai);
|
||||
setProvider(provider);
|
||||
localStorage.setItem('mem0ApiKey', mem0);
|
||||
localStorage.setItem('openaiApiKey', openai);
|
||||
localStorage.setItem('provider', provider);
|
||||
};
|
||||
|
||||
const clearAuth = () => {
|
||||
localStorage.removeItem('mem0ApiKey');
|
||||
localStorage.removeItem('openaiApiKey');
|
||||
localStorage.removeItem('provider');
|
||||
setMem0ApiKey('');
|
||||
setOpenaiApiKey('');
|
||||
setProvider('openai');
|
||||
};
|
||||
|
||||
const updateUser = (user: string) => {
|
||||
setUser(user);
|
||||
localStorage.setItem('user', user);
|
||||
};
|
||||
|
||||
const clearUser = () => {
|
||||
localStorage.removeItem('user');
|
||||
setUser('');
|
||||
};
|
||||
|
||||
return {
|
||||
mem0ApiKey,
|
||||
openaiApiKey,
|
||||
provider,
|
||||
user,
|
||||
setAuth,
|
||||
setUser: updateUser,
|
||||
clearAuth,
|
||||
clearUser,
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,169 @@
|
||||
import { useState } from 'react';
|
||||
import { createMem0, getMemories } from '@mem0/vercel-ai-provider';
|
||||
import { LanguageModelV1Prompt, streamText } from 'ai';
|
||||
import { Message, Memory } from '@/types';
|
||||
import { WELCOME_MESSAGE, INVALID_CONFIG_MESSAGE, ERROR_MESSAGE, AI_MODELS, Provider } from '@/constants/messages';
|
||||
|
||||
interface UseChatProps {
|
||||
user: string;
|
||||
mem0ApiKey: string;
|
||||
openaiApiKey: string;
|
||||
provider: Provider;
|
||||
}
|
||||
|
||||
interface UseChatReturn {
|
||||
messages: Message[];
|
||||
memories: Memory[];
|
||||
thinking: boolean;
|
||||
sendMessage: (content: string, fileData?: { type: string; data: string | Buffer }) => Promise<void>;
|
||||
}
|
||||
|
||||
interface MemoryResponse {
|
||||
id: string;
|
||||
memory: string;
|
||||
updated_at: string;
|
||||
categories: string[];
|
||||
}
|
||||
|
||||
type MessageContent =
|
||||
| { type: 'text'; text: string }
|
||||
| { type: 'image'; image: string }
|
||||
| { type: 'file'; mimeType: string; data: Buffer };
|
||||
|
||||
interface PromptMessage {
|
||||
role: string;
|
||||
content: MessageContent[];
|
||||
}
|
||||
|
||||
export const useChat = ({ user, mem0ApiKey, openaiApiKey, provider }: UseChatProps): UseChatReturn => {
|
||||
const [messages, setMessages] = useState<Message[]>([WELCOME_MESSAGE]);
|
||||
const [memories, setMemories] = useState<Memory[]>([]);
|
||||
const [thinking, setThinking] = useState(false);
|
||||
|
||||
const mem0 = createMem0({
|
||||
provider,
|
||||
mem0ApiKey,
|
||||
apiKey: openaiApiKey,
|
||||
});
|
||||
|
||||
const updateMemories = async (messages: LanguageModelV1Prompt) => {
|
||||
try {
|
||||
const fetchedMemories = await getMemories(messages, {
|
||||
user_id: user,
|
||||
mem0ApiKey,
|
||||
});
|
||||
|
||||
const newMemories = fetchedMemories.map((memory: MemoryResponse) => ({
|
||||
id: memory.id,
|
||||
content: memory.memory,
|
||||
timestamp: memory.updated_at,
|
||||
tags: memory.categories,
|
||||
}));
|
||||
setMemories(newMemories);
|
||||
} catch (error) {
|
||||
console.error('Error in getMemories:', error);
|
||||
}
|
||||
};
|
||||
|
||||
const formatMessagesForPrompt = (messages: Message[]): PromptMessage[] => {
|
||||
return messages.map((message) => {
|
||||
const messageContent: MessageContent[] = [
|
||||
{ type: 'text', text: message.content }
|
||||
];
|
||||
|
||||
if (message.image) {
|
||||
messageContent.push({
|
||||
type: 'image',
|
||||
image: message.image,
|
||||
});
|
||||
}
|
||||
|
||||
if (message.audio) {
|
||||
messageContent.push({
|
||||
type: 'file',
|
||||
mimeType: 'audio/mpeg',
|
||||
data: message.audio as Buffer,
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
role: message.sender,
|
||||
content: messageContent,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
const sendMessage = async (content: string, fileData?: { type: string; data: string | Buffer }) => {
|
||||
if (!content.trim() && !fileData) return;
|
||||
|
||||
if (!user) {
|
||||
const newMessage: Message = {
|
||||
id: Date.now().toString(),
|
||||
content,
|
||||
sender: 'user',
|
||||
timestamp: new Date().toLocaleTimeString(),
|
||||
};
|
||||
setMessages((prev) => [...prev, newMessage, INVALID_CONFIG_MESSAGE]);
|
||||
return;
|
||||
}
|
||||
|
||||
const userMessage: Message = {
|
||||
id: Date.now().toString(),
|
||||
content,
|
||||
sender: 'user',
|
||||
timestamp: new Date().toLocaleTimeString(),
|
||||
...(fileData?.type.startsWith('image/') && { image: fileData.data.toString() }),
|
||||
...(fileData?.type.startsWith('audio/') && { audio: fileData.data as Buffer }),
|
||||
};
|
||||
|
||||
setMessages((prev) => [...prev, userMessage]);
|
||||
setThinking(true);
|
||||
|
||||
const messagesForPrompt = formatMessagesForPrompt([...messages, userMessage]);
|
||||
await updateMemories(messagesForPrompt as LanguageModelV1Prompt);
|
||||
|
||||
try {
|
||||
const { textStream } = await streamText({
|
||||
model: mem0(AI_MODELS[provider], {
|
||||
user_id: user,
|
||||
}),
|
||||
messages: messagesForPrompt as LanguageModelV1Prompt,
|
||||
});
|
||||
|
||||
const assistantMessageId = Date.now() + 1;
|
||||
const assistantMessage: Message = {
|
||||
id: assistantMessageId.toString(),
|
||||
content: '',
|
||||
sender: 'assistant',
|
||||
timestamp: new Date().toLocaleTimeString(),
|
||||
};
|
||||
|
||||
setMessages((prev) => [...prev, assistantMessage]);
|
||||
|
||||
for await (const textPart of textStream) {
|
||||
assistantMessage.content += textPart;
|
||||
setThinking(false);
|
||||
|
||||
setMessages((prev) =>
|
||||
prev.map((msg) =>
|
||||
msg.id === assistantMessageId.toString()
|
||||
? { ...msg, content: assistantMessage.content }
|
||||
: msg
|
||||
)
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error in sendMessage:', error);
|
||||
setMessages((prev) => [...prev, ERROR_MESSAGE]);
|
||||
} finally {
|
||||
setThinking(false);
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
messages,
|
||||
memories,
|
||||
thinking,
|
||||
sendMessage,
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,45 @@
|
||||
import { useState } from 'react';
|
||||
import { FileInfo } from '@/types';
|
||||
import { convertToBase64, getFileBuffer } from '@/utils/fileUtils';
|
||||
|
||||
interface UseFileHandlerReturn {
|
||||
selectedFile: FileInfo | null;
|
||||
file: File | null;
|
||||
fileData: string | Buffer | null;
|
||||
setSelectedFile: (file: FileInfo | null) => void;
|
||||
handleFile: (file: File) => Promise<void>;
|
||||
clearFile: () => void;
|
||||
}
|
||||
|
||||
export const useFileHandler = (): UseFileHandlerReturn => {
|
||||
const [selectedFile, setSelectedFile] = useState<FileInfo | null>(null);
|
||||
const [file, setFile] = useState<File | null>(null);
|
||||
const [fileData, setFileData] = useState<string | Buffer | null>(null);
|
||||
|
||||
const handleFile = async (file: File) => {
|
||||
setFile(file);
|
||||
|
||||
if (file.type.startsWith('image/')) {
|
||||
const base64Data = await convertToBase64(file);
|
||||
setFileData(base64Data);
|
||||
} else if (file.type.startsWith('audio/')) {
|
||||
const bufferData = await getFileBuffer(file);
|
||||
setFileData(bufferData);
|
||||
}
|
||||
};
|
||||
|
||||
const clearFile = () => {
|
||||
setSelectedFile(null);
|
||||
setFile(null);
|
||||
setFileData(null);
|
||||
};
|
||||
|
||||
return {
|
||||
selectedFile,
|
||||
file,
|
||||
fileData,
|
||||
setSelectedFile,
|
||||
handleFile,
|
||||
clearFile,
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,16 @@
|
||||
import { Buffer } from 'buffer';
|
||||
|
||||
export const convertToBase64 = (file: File): Promise<string> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
reader.readAsDataURL(file);
|
||||
reader.onload = () => resolve(reader.result as string);
|
||||
reader.onerror = error => reject(error);
|
||||
});
|
||||
};
|
||||
|
||||
export const getFileBuffer = async (file: File): Promise<Buffer> => {
|
||||
const response = await fetch(URL.createObjectURL(file));
|
||||
const arrayBuffer = await response.arrayBuffer();
|
||||
return Buffer.from(arrayBuffer);
|
||||
};
|
||||
@@ -0,0 +1,65 @@
|
||||
# Mem0 - The Memory Layer for Your AI Apps
|
||||
|
||||
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:
|
||||
|
||||
```bash
|
||||
npm i mem0ai
|
||||
```
|
||||
|
||||
## 2. API Key Setup
|
||||
|
||||
For the cloud offering, sign in to [Mem0 Platform](https://app.mem0.ai/dashboard/api-keys) to obtain your API Key.
|
||||
|
||||
## 3. Client Features
|
||||
|
||||
### Cloud Offering
|
||||
|
||||
The cloud version provides a comprehensive set of features, including:
|
||||
|
||||
- **Memory Operations**: Perform CRUD operations on memories.
|
||||
- **Search Capabilities**: Search for relevant memories using advanced filters.
|
||||
- **Memory History**: Track changes to memories over time.
|
||||
- **Error Handling**: Robust error handling for API-related issues.
|
||||
- **Async/Await Support**: All methods return promises for easy integration.
|
||||
|
||||
### Open-Source Offering
|
||||
|
||||
The open-source version includes the following top features:
|
||||
|
||||
- **Memory Management**: Add, update, delete, and retrieve memories.
|
||||
- **Vector Store Integration**: Supports various vector store providers for efficient memory retrieval.
|
||||
- **LLM Support**: Integrates with multiple LLM providers for generating responses.
|
||||
- **Customizable Configuration**: Easily configure memory settings and providers.
|
||||
- **SQLite Storage**: Use SQLite for memory history management.
|
||||
|
||||
## 4. Memory Operations
|
||||
|
||||
Mem0 provides a simple and customizable interface for performing memory operations. You can create long-term and short-term memories, search for relevant memories, and manage memory history.
|
||||
|
||||
## 5. Error Handling
|
||||
|
||||
The MemoryClient throws errors for any API-related issues. You can catch and handle these errors effectively.
|
||||
|
||||
## 6. Using with async/await
|
||||
|
||||
All methods of the MemoryClient return promises, allowing for seamless integration with async/await syntax.
|
||||
|
||||
## 7. Testing the Client
|
||||
|
||||
To test the MemoryClient in a Node.js environment, you can create a simple script to verify the functionality of memory operations.
|
||||
|
||||
## Getting Help
|
||||
|
||||
If you have any questions or need assistance, please reach out to us:
|
||||
|
||||
- Email: founders@mem0.ai
|
||||
- [Join our discord community](https://mem0.ai/discord)
|
||||
- [Join our slack community](https://mem0.ai/slack)
|
||||
- GitHub Issues: [Report bugs or request features](https://github.com/mem0ai/mem0ai-node/issues)
|
||||
@@ -0,0 +1,29 @@
|
||||
/** @type {import('ts-jest').JestConfigWithTsJest} */
|
||||
module.exports = {
|
||||
preset: "ts-jest",
|
||||
testEnvironment: "node",
|
||||
roots: ["<rootDir>/src", "<rootDir>/tests"],
|
||||
testMatch: [
|
||||
"**/__tests__/**/*.+(ts|tsx|js)",
|
||||
"**/?(*.)+(spec|test).+(ts|tsx|js)",
|
||||
],
|
||||
transform: {
|
||||
"^.+\\.(ts|tsx)$": [
|
||||
"ts-jest",
|
||||
{
|
||||
tsconfig: "tsconfig.test.json",
|
||||
},
|
||||
],
|
||||
},
|
||||
moduleNameMapper: {
|
||||
"^@/(.*)$": "<rootDir>/src/$1",
|
||||
},
|
||||
setupFiles: ["dotenv/config"],
|
||||
testPathIgnorePatterns: ["/node_modules/", "/dist/"],
|
||||
moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node"],
|
||||
globals: {
|
||||
"ts-jest": {
|
||||
tsconfig: "tsconfig.test.json",
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,117 @@
|
||||
{
|
||||
"name": "mem0ai",
|
||||
"version": "2.0.1",
|
||||
"description": "The Memory Layer For Your AI Apps",
|
||||
"main": "./dist/index.js",
|
||||
"module": "./dist/index.mjs",
|
||||
"types": "./dist/index.d.ts",
|
||||
"typesVersions": {
|
||||
"*": {
|
||||
"*": [
|
||||
"./dist/index.d.ts"
|
||||
],
|
||||
"oss": [
|
||||
"./dist/oss/index.d.ts"
|
||||
]
|
||||
}
|
||||
},
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"require": "./dist/index.js",
|
||||
"import": "./dist/index.mjs"
|
||||
},
|
||||
"./oss": {
|
||||
"types": "./dist/oss/index.d.ts",
|
||||
"require": "./dist/oss/index.js",
|
||||
"import": "./dist/oss/index.mjs"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"scripts": {
|
||||
"clean": "rm -rf dist",
|
||||
"build": "npm run clean && prettier --check . && tsup",
|
||||
"dev": "nodemon",
|
||||
"test": "jest",
|
||||
"test:ts": "jest --config jest.config.js",
|
||||
"test:watch": "jest --config jest.config.js --watch",
|
||||
"format": "npm run clean && prettier --write .",
|
||||
"format:check": "npm run clean && prettier --check ."
|
||||
},
|
||||
"tsup": {
|
||||
"entry": [
|
||||
"src/index.ts"
|
||||
],
|
||||
"format": [
|
||||
"cjs",
|
||||
"esm"
|
||||
],
|
||||
"dts": {
|
||||
"resolve": true
|
||||
},
|
||||
"splitting": false,
|
||||
"sourcemap": true,
|
||||
"clean": true,
|
||||
"treeshake": true,
|
||||
"minify": false
|
||||
},
|
||||
"keywords": [
|
||||
"mem0",
|
||||
"api",
|
||||
"client",
|
||||
"memory",
|
||||
"llm",
|
||||
"long-term-memory",
|
||||
"ai"
|
||||
],
|
||||
"author": "Deshraj Yadav",
|
||||
"license": "Apache-2.0",
|
||||
"devDependencies": {
|
||||
"@types/node": "^22.7.6",
|
||||
"@types/uuid": "^9.0.8",
|
||||
"dotenv": "^16.4.5",
|
||||
"fix-tsup-cjs": "^1.2.0",
|
||||
"jest": "^29.7.0",
|
||||
"prettier": "^3.5.2",
|
||||
"ts-jest": "^29.2.6",
|
||||
"ts-node": "^10.9.2",
|
||||
"tsup": "^8.3.0",
|
||||
"typescript": "5.5.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "1.7.7",
|
||||
"openai": "4.28.0",
|
||||
"uuid": "9.0.1",
|
||||
"zod": "3.22.4"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@anthropic-ai/sdk": "0.18.0",
|
||||
"groq-sdk": "0.3.0",
|
||||
"@qdrant/js-client-rest": "1.13.0",
|
||||
"@types/jest": "29.5.14",
|
||||
"@types/pg": "8.11.0",
|
||||
"@types/sqlite3": "3.1.11",
|
||||
"pg": "8.11.3",
|
||||
"redis": "4.7.0",
|
||||
"sqlite3": "5.1.7"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"posthog-node": {
|
||||
"optional": true
|
||||
},
|
||||
"posthog-js": {
|
||||
"optional": true
|
||||
}
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"posthog-js": "^1.116.6"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
import { MemoryClient } from "./mem0";
|
||||
import type { TelemetryClient, TelemetryInstance } from "./telemetry.types";
|
||||
import {
|
||||
telemetry,
|
||||
captureClientEvent,
|
||||
generateHash,
|
||||
} from "./telemetry.browser";
|
||||
import type * as MemoryTypes from "./mem0.types";
|
||||
|
||||
// Re-export all types from mem0.types
|
||||
export type {
|
||||
MemoryOptions,
|
||||
ProjectOptions,
|
||||
Memory,
|
||||
MemoryHistory,
|
||||
MemoryUpdateBody,
|
||||
ProjectResponse,
|
||||
PromptUpdatePayload,
|
||||
SearchOptions,
|
||||
Webhook,
|
||||
WebhookPayload,
|
||||
Messages,
|
||||
Message,
|
||||
AllUsers,
|
||||
User,
|
||||
} from "./mem0.types";
|
||||
|
||||
// Export telemetry types
|
||||
export type { TelemetryClient, TelemetryInstance };
|
||||
|
||||
// Export telemetry implementation
|
||||
export { telemetry, captureClientEvent, generateHash };
|
||||
|
||||
// Export the main client
|
||||
export { MemoryClient };
|
||||
export default MemoryClient;
|
||||
@@ -0,0 +1,560 @@
|
||||
import axios from "axios";
|
||||
import {
|
||||
AllUsers,
|
||||
ProjectOptions,
|
||||
Memory,
|
||||
MemoryHistory,
|
||||
MemoryOptions,
|
||||
MemoryUpdateBody,
|
||||
ProjectResponse,
|
||||
PromptUpdatePayload,
|
||||
SearchOptions,
|
||||
Webhook,
|
||||
WebhookPayload,
|
||||
} from "./mem0.types";
|
||||
import { captureClientEvent, generateHash } from "./telemetry";
|
||||
|
||||
class APIError extends Error {
|
||||
constructor(message: string) {
|
||||
super(message);
|
||||
this.name = "APIError";
|
||||
}
|
||||
}
|
||||
|
||||
interface ClientOptions {
|
||||
apiKey: string;
|
||||
host?: string;
|
||||
organizationName?: string;
|
||||
projectName?: string;
|
||||
organizationId?: string;
|
||||
projectId?: string;
|
||||
}
|
||||
|
||||
export default class MemoryClient {
|
||||
apiKey: string;
|
||||
host: string;
|
||||
organizationName: string | null;
|
||||
projectName: string | null;
|
||||
organizationId: string | number | null;
|
||||
projectId: string | number | null;
|
||||
headers: Record<string, string>;
|
||||
client: any;
|
||||
telemetryId: string;
|
||||
|
||||
_validateApiKey(): any {
|
||||
if (!this.apiKey) {
|
||||
throw new Error("Mem0 API key is required");
|
||||
}
|
||||
if (typeof this.apiKey !== "string") {
|
||||
throw new Error("Mem0 API key must be a string");
|
||||
}
|
||||
if (this.apiKey.trim() === "") {
|
||||
throw new Error("Mem0 API key cannot be empty");
|
||||
}
|
||||
}
|
||||
|
||||
_validateOrgProject(): void {
|
||||
// Check for organizationName/projectName pair
|
||||
if (
|
||||
(this.organizationName === null && this.projectName !== null) ||
|
||||
(this.organizationName !== null && this.projectName === null)
|
||||
) {
|
||||
console.warn(
|
||||
"Warning: Both organizationName and projectName must be provided together when using either. This will be removedfrom the version 1.0.40. Note that organizationName/projectName are being deprecated in favor of organizationId/projectId.",
|
||||
);
|
||||
}
|
||||
|
||||
// Check for organizationId/projectId pair
|
||||
if (
|
||||
(this.organizationId === null && this.projectId !== null) ||
|
||||
(this.organizationId !== null && this.projectId === null)
|
||||
) {
|
||||
console.warn(
|
||||
"Warning: Both organizationId and projectId must be provided together when using either. This will be removedfrom the version 1.0.40.",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
constructor(options: ClientOptions) {
|
||||
this.apiKey = options.apiKey;
|
||||
this.host = options.host || "https://api.mem0.ai";
|
||||
this.organizationName = options.organizationName || null;
|
||||
this.projectName = options.projectName || null;
|
||||
this.organizationId = options.organizationId || null;
|
||||
this.projectId = options.projectId || null;
|
||||
|
||||
this.headers = {
|
||||
Authorization: `Token ${this.apiKey}`,
|
||||
"Content-Type": "application/json",
|
||||
};
|
||||
|
||||
this.client = axios.create({
|
||||
baseURL: this.host,
|
||||
headers: { Authorization: `Token ${this.apiKey}` },
|
||||
timeout: 60000,
|
||||
});
|
||||
|
||||
this._validateApiKey();
|
||||
this._validateOrgProject();
|
||||
|
||||
// Initialize with a temporary ID that will be updated
|
||||
this.telemetryId = "";
|
||||
|
||||
// Initialize the client
|
||||
this._initializeClient();
|
||||
}
|
||||
|
||||
private async _initializeClient() {
|
||||
try {
|
||||
// do this only in browser
|
||||
if (typeof window !== "undefined") {
|
||||
this.telemetryId = await generateHash(this.apiKey);
|
||||
await captureClientEvent("init", this);
|
||||
}
|
||||
|
||||
// Wrap methods after initialization
|
||||
this.add = this.wrapMethod("add", this.add);
|
||||
this.get = this.wrapMethod("get", this.get);
|
||||
this.getAll = this.wrapMethod("get_all", this.getAll);
|
||||
this.search = this.wrapMethod("search", this.search);
|
||||
this.delete = this.wrapMethod("delete", this.delete);
|
||||
this.deleteAll = this.wrapMethod("delete_all", this.deleteAll);
|
||||
this.history = this.wrapMethod("history", this.history);
|
||||
this.users = this.wrapMethod("users", this.users);
|
||||
this.deleteUser = this.wrapMethod("delete_user", this.deleteUser);
|
||||
this.deleteUsers = this.wrapMethod("delete_users", this.deleteUsers);
|
||||
this.batchUpdate = this.wrapMethod("batch_update", this.batchUpdate);
|
||||
this.batchDelete = this.wrapMethod("batch_delete", this.batchDelete);
|
||||
this.getProject = this.wrapMethod("get_project", this.getProject);
|
||||
this.updateProject = this.wrapMethod(
|
||||
"update_project",
|
||||
this.updateProject,
|
||||
);
|
||||
this.getWebhooks = this.wrapMethod("get_webhook", this.getWebhooks);
|
||||
this.createWebhook = this.wrapMethod(
|
||||
"create_webhook",
|
||||
this.createWebhook,
|
||||
);
|
||||
this.updateWebhook = this.wrapMethod(
|
||||
"update_webhook",
|
||||
this.updateWebhook,
|
||||
);
|
||||
this.deleteWebhook = this.wrapMethod(
|
||||
"delete_webhook",
|
||||
this.deleteWebhook,
|
||||
);
|
||||
} catch (error) {
|
||||
console.error("Failed to initialize client:", error);
|
||||
}
|
||||
}
|
||||
|
||||
wrapMethod(methodName: any, method: any) {
|
||||
return async function (...args: any) {
|
||||
// @ts-ignore
|
||||
await captureClientEvent(methodName, this);
|
||||
// @ts-ignore
|
||||
return method.apply(this, args);
|
||||
}.bind(this);
|
||||
}
|
||||
|
||||
async _fetchWithErrorHandling(url: string, options: any): Promise<any> {
|
||||
const response = await fetch(url, options);
|
||||
if (!response.ok) {
|
||||
const errorData = await response.text();
|
||||
throw new APIError(`API request failed: ${errorData}`);
|
||||
}
|
||||
const jsonResponse = await response.json();
|
||||
return jsonResponse;
|
||||
}
|
||||
|
||||
_preparePayload(
|
||||
messages: string | Array<{ role: string; content: string }>,
|
||||
options: MemoryOptions,
|
||||
): object {
|
||||
const payload: any = {};
|
||||
if (typeof messages === "string") {
|
||||
payload.messages = [{ role: "user", content: messages }];
|
||||
} else if (Array.isArray(messages)) {
|
||||
payload.messages = messages;
|
||||
}
|
||||
return { ...payload, ...options };
|
||||
}
|
||||
|
||||
_prepareParams(options: MemoryOptions): object {
|
||||
return Object.fromEntries(
|
||||
Object.entries(options).filter(([_, v]) => v != null),
|
||||
);
|
||||
}
|
||||
|
||||
async add(
|
||||
messages: string | Array<{ role: string; content: string }>,
|
||||
options: MemoryOptions = {},
|
||||
): Promise<Array<Memory>> {
|
||||
this._validateOrgProject();
|
||||
if (this.organizationName != null && this.projectName != null) {
|
||||
options.org_name = this.organizationName;
|
||||
options.project_name = this.projectName;
|
||||
}
|
||||
|
||||
if (this.organizationId != null && this.projectId != null) {
|
||||
options.org_id = this.organizationId;
|
||||
options.project_id = this.projectId;
|
||||
|
||||
if (options.org_name) delete options.org_name;
|
||||
if (options.project_name) delete options.project_name;
|
||||
}
|
||||
|
||||
const payload = this._preparePayload(messages, options);
|
||||
const response = await this._fetchWithErrorHandling(
|
||||
`${this.host}/v1/memories/`,
|
||||
{
|
||||
method: "POST",
|
||||
headers: this.headers,
|
||||
body: JSON.stringify(payload),
|
||||
},
|
||||
);
|
||||
return response;
|
||||
}
|
||||
|
||||
async update(memoryId: string, message: string): Promise<Array<Memory>> {
|
||||
this._validateOrgProject();
|
||||
const payload = {
|
||||
text: message,
|
||||
};
|
||||
const response = await this._fetchWithErrorHandling(
|
||||
`${this.host}/v1/memories/${memoryId}/`,
|
||||
{
|
||||
method: "PUT",
|
||||
headers: this.headers,
|
||||
body: JSON.stringify(payload),
|
||||
},
|
||||
);
|
||||
return response;
|
||||
}
|
||||
|
||||
async get(memoryId: string): Promise<Memory> {
|
||||
return this._fetchWithErrorHandling(
|
||||
`${this.host}/v1/memories/${memoryId}/`,
|
||||
{
|
||||
headers: this.headers,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
async getAll(options?: SearchOptions): Promise<Array<Memory>> {
|
||||
this._validateOrgProject();
|
||||
const { api_version, page, page_size, ...otherOptions } = options!;
|
||||
if (this.organizationName != null && this.projectName != null) {
|
||||
otherOptions.org_name = this.organizationName;
|
||||
otherOptions.project_name = this.projectName;
|
||||
}
|
||||
|
||||
let appendedParams = "";
|
||||
let paginated_response = false;
|
||||
|
||||
if (page && page_size) {
|
||||
appendedParams += `page=${page}&page_size=${page_size}`;
|
||||
paginated_response = true;
|
||||
}
|
||||
|
||||
if (this.organizationId != null && this.projectId != null) {
|
||||
otherOptions.org_id = this.organizationId;
|
||||
otherOptions.project_id = this.projectId;
|
||||
|
||||
if (otherOptions.org_name) delete otherOptions.org_name;
|
||||
if (otherOptions.project_name) delete otherOptions.project_name;
|
||||
}
|
||||
|
||||
if (api_version === "v2") {
|
||||
let url = paginated_response
|
||||
? `${this.host}/v2/memories/?${appendedParams}`
|
||||
: `${this.host}/v2/memories/`;
|
||||
return this._fetchWithErrorHandling(url, {
|
||||
method: "POST",
|
||||
headers: this.headers,
|
||||
body: JSON.stringify(otherOptions),
|
||||
});
|
||||
} else {
|
||||
// @ts-ignore
|
||||
const params = new URLSearchParams(this._prepareParams(otherOptions));
|
||||
const url = paginated_response
|
||||
? `${this.host}/v1/memories/?${params}&${appendedParams}`
|
||||
: `${this.host}/v1/memories/?${params}`;
|
||||
return this._fetchWithErrorHandling(url, {
|
||||
headers: this.headers,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async search(query: string, options?: SearchOptions): Promise<Array<Memory>> {
|
||||
this._validateOrgProject();
|
||||
const { api_version, ...otherOptions } = options!;
|
||||
const payload = { query, ...otherOptions };
|
||||
if (this.organizationName != null && this.projectName != null) {
|
||||
payload.org_name = this.organizationName;
|
||||
payload.project_name = this.projectName;
|
||||
}
|
||||
|
||||
if (this.organizationId != null && this.projectId != null) {
|
||||
payload.org_id = this.organizationId;
|
||||
payload.project_id = this.projectId;
|
||||
|
||||
if (payload.org_name) delete payload.org_name;
|
||||
if (payload.project_name) delete payload.project_name;
|
||||
}
|
||||
const endpoint =
|
||||
api_version === "v2" ? "/v2/memories/search/" : "/v1/memories/search/";
|
||||
const response = await this._fetchWithErrorHandling(
|
||||
`${this.host}${endpoint}`,
|
||||
{
|
||||
method: "POST",
|
||||
headers: this.headers,
|
||||
body: JSON.stringify(payload),
|
||||
},
|
||||
);
|
||||
return response;
|
||||
}
|
||||
|
||||
async delete(memoryId: string): Promise<{ message: string }> {
|
||||
return this._fetchWithErrorHandling(
|
||||
`${this.host}/v1/memories/${memoryId}/`,
|
||||
{
|
||||
method: "DELETE",
|
||||
headers: this.headers,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
async deleteAll(options: MemoryOptions = {}): Promise<{ message: string }> {
|
||||
this._validateOrgProject();
|
||||
if (this.organizationName != null && this.projectName != null) {
|
||||
options.org_name = this.organizationName;
|
||||
options.project_name = this.projectName;
|
||||
}
|
||||
|
||||
if (this.organizationId != null && this.projectId != null) {
|
||||
options.org_id = this.organizationId;
|
||||
options.project_id = this.projectId;
|
||||
|
||||
if (options.org_name) delete options.org_name;
|
||||
if (options.project_name) delete options.project_name;
|
||||
}
|
||||
// @ts-ignore
|
||||
const params = new URLSearchParams(this._prepareParams(options));
|
||||
const response = await this._fetchWithErrorHandling(
|
||||
`${this.host}/v1/memories/?${params}`,
|
||||
{
|
||||
method: "DELETE",
|
||||
headers: this.headers,
|
||||
},
|
||||
);
|
||||
return response;
|
||||
}
|
||||
|
||||
async history(memoryId: string): Promise<Array<MemoryHistory>> {
|
||||
const response = await this._fetchWithErrorHandling(
|
||||
`${this.host}/v1/memories/${memoryId}/history/`,
|
||||
{
|
||||
headers: this.headers,
|
||||
},
|
||||
);
|
||||
return response;
|
||||
}
|
||||
|
||||
async users(): Promise<AllUsers> {
|
||||
this._validateOrgProject();
|
||||
const options: MemoryOptions = {};
|
||||
if (this.organizationName != null && this.projectName != null) {
|
||||
options.org_name = this.organizationName;
|
||||
options.project_name = this.projectName;
|
||||
}
|
||||
|
||||
if (this.organizationId != null && this.projectId != null) {
|
||||
options.org_id = this.organizationId;
|
||||
options.project_id = this.projectId;
|
||||
|
||||
if (options.org_name) delete options.org_name;
|
||||
if (options.project_name) delete options.project_name;
|
||||
}
|
||||
// @ts-ignore
|
||||
const params = new URLSearchParams(options);
|
||||
const response = await this._fetchWithErrorHandling(
|
||||
`${this.host}/v1/entities/?${params}`,
|
||||
{
|
||||
headers: this.headers,
|
||||
},
|
||||
);
|
||||
return response;
|
||||
}
|
||||
|
||||
async deleteUser(
|
||||
entityId: string,
|
||||
entity: { type: string } = { type: "user" },
|
||||
): Promise<{ message: string }> {
|
||||
const response = await this._fetchWithErrorHandling(
|
||||
`${this.host}/v1/entities/${entity.type}/${entityId}/`,
|
||||
{
|
||||
method: "DELETE",
|
||||
headers: this.headers,
|
||||
},
|
||||
);
|
||||
return response;
|
||||
}
|
||||
|
||||
async deleteUsers(): Promise<{ message: string }> {
|
||||
this._validateOrgProject();
|
||||
const entities = await this.users();
|
||||
|
||||
for (const entity of entities.results) {
|
||||
let options: MemoryOptions = {};
|
||||
if (this.organizationName != null && this.projectName != null) {
|
||||
options.org_name = this.organizationName;
|
||||
options.project_name = this.projectName;
|
||||
}
|
||||
|
||||
if (this.organizationId != null && this.projectId != null) {
|
||||
options.org_id = this.organizationId;
|
||||
options.project_id = this.projectId;
|
||||
|
||||
if (options.org_name) delete options.org_name;
|
||||
if (options.project_name) delete options.project_name;
|
||||
}
|
||||
await this.client.delete(`/v1/entities/${entity.type}/${entity.id}/`, {
|
||||
params: options,
|
||||
});
|
||||
}
|
||||
return { message: "All users, agents, and sessions deleted." };
|
||||
}
|
||||
|
||||
async batchUpdate(memories: Array<MemoryUpdateBody>): Promise<string> {
|
||||
const memoriesBody = memories.map((memory) => ({
|
||||
memory_id: memory.memoryId,
|
||||
text: memory.text,
|
||||
}));
|
||||
const response = await this._fetchWithErrorHandling(
|
||||
`${this.host}/v1/batch/`,
|
||||
{
|
||||
method: "PUT",
|
||||
headers: this.headers,
|
||||
body: JSON.stringify({ memories: memoriesBody }),
|
||||
},
|
||||
);
|
||||
return response;
|
||||
}
|
||||
|
||||
async batchDelete(memories: Array<string>): Promise<string> {
|
||||
const memoriesBody = memories.map((memory) => ({
|
||||
memory_id: memory,
|
||||
}));
|
||||
const response = await this._fetchWithErrorHandling(
|
||||
`${this.host}/v1/batch/`,
|
||||
{
|
||||
method: "DELETE",
|
||||
headers: this.headers,
|
||||
body: JSON.stringify({ memories: memoriesBody }),
|
||||
},
|
||||
);
|
||||
return response;
|
||||
}
|
||||
|
||||
async getProject(options: ProjectOptions): Promise<ProjectResponse> {
|
||||
this._validateOrgProject();
|
||||
|
||||
const { fields } = options;
|
||||
|
||||
if (!(this.organizationId && this.projectId)) {
|
||||
throw new Error(
|
||||
"organizationId and projectId must be set to access instructions or categories",
|
||||
);
|
||||
}
|
||||
|
||||
const params = new URLSearchParams();
|
||||
fields?.forEach((field) => params.append("fields", field));
|
||||
|
||||
const response = await this._fetchWithErrorHandling(
|
||||
`${this.host}/api/v1/orgs/organizations/${this.organizationId}/projects/${this.projectId}/?${params.toString()}`,
|
||||
{
|
||||
headers: this.headers,
|
||||
},
|
||||
);
|
||||
return response;
|
||||
}
|
||||
|
||||
async updateProject(
|
||||
prompts: PromptUpdatePayload,
|
||||
): Promise<Record<string, any>> {
|
||||
this._validateOrgProject();
|
||||
|
||||
if (!(this.organizationId && this.projectId)) {
|
||||
throw new Error(
|
||||
"organizationId and projectId must be set to update instructions or categories",
|
||||
);
|
||||
}
|
||||
|
||||
const response = await this._fetchWithErrorHandling(
|
||||
`${this.host}/api/v1/orgs/organizations/${this.organizationId}/projects/${this.projectId}/`,
|
||||
{
|
||||
method: "PATCH",
|
||||
headers: this.headers,
|
||||
body: JSON.stringify(prompts),
|
||||
},
|
||||
);
|
||||
return response;
|
||||
}
|
||||
|
||||
// WebHooks
|
||||
async getWebhooks(data?: { projectId?: string }): Promise<Array<Webhook>> {
|
||||
const project_id = data?.projectId || this.projectId;
|
||||
const response = await this._fetchWithErrorHandling(
|
||||
`${this.host}/api/v1/webhooks/projects/${project_id}/`,
|
||||
{
|
||||
headers: this.headers,
|
||||
},
|
||||
);
|
||||
return response;
|
||||
}
|
||||
|
||||
async createWebhook(webhook: WebhookPayload): Promise<Webhook> {
|
||||
const response = await this._fetchWithErrorHandling(
|
||||
`${this.host}/api/v1/webhooks/projects/${this.projectId}/`,
|
||||
{
|
||||
method: "POST",
|
||||
headers: this.headers,
|
||||
body: JSON.stringify(webhook),
|
||||
},
|
||||
);
|
||||
return response;
|
||||
}
|
||||
|
||||
async updateWebhook(webhook: WebhookPayload): Promise<{ message: string }> {
|
||||
const project_id = webhook.projectId || this.projectId;
|
||||
const response = await this._fetchWithErrorHandling(
|
||||
`${this.host}/api/v1/webhooks/${webhook.webhookId}/`,
|
||||
{
|
||||
method: "PUT",
|
||||
headers: this.headers,
|
||||
body: JSON.stringify({
|
||||
...webhook,
|
||||
projectId: project_id,
|
||||
}),
|
||||
},
|
||||
);
|
||||
return response;
|
||||
}
|
||||
|
||||
async deleteWebhook(data: {
|
||||
webhookId: string;
|
||||
}): Promise<{ message: string }> {
|
||||
const webhook_id = data.webhookId || data;
|
||||
const response = await this._fetchWithErrorHandling(
|
||||
`${this.host}/api/v1/webhooks/${webhook_id}/`,
|
||||
{
|
||||
method: "DELETE",
|
||||
headers: this.headers,
|
||||
},
|
||||
);
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
export { MemoryClient };
|
||||
@@ -0,0 +1,156 @@
|
||||
export interface MemoryOptions {
|
||||
user_id?: string;
|
||||
agent_id?: string;
|
||||
app_id?: string;
|
||||
run_id?: string;
|
||||
metadata?: Record<string, any>;
|
||||
filters?: Record<string, any>;
|
||||
org_name?: string | null; // Deprecated
|
||||
project_name?: string | null; // Deprecated
|
||||
org_id?: string | number | null;
|
||||
project_id?: string | number | null;
|
||||
infer?: boolean;
|
||||
page?: number;
|
||||
page_size?: number;
|
||||
includes?: string;
|
||||
excludes?: string;
|
||||
enable_graph?: boolean;
|
||||
start_date?: string;
|
||||
end_date?: string;
|
||||
}
|
||||
|
||||
export interface ProjectOptions {
|
||||
fields?: string[];
|
||||
}
|
||||
|
||||
export enum API_VERSION {
|
||||
V1 = "v1",
|
||||
V2 = "v2",
|
||||
}
|
||||
|
||||
export interface Messages {
|
||||
role: string;
|
||||
content: string;
|
||||
}
|
||||
|
||||
export interface Message extends Messages {}
|
||||
|
||||
export interface MemoryHistory {
|
||||
id: string;
|
||||
memory_id: string;
|
||||
input: Array<Messages>;
|
||||
old_memory: string | null;
|
||||
new_memory: string | null;
|
||||
user_id: string;
|
||||
categories: Array<string>;
|
||||
event: Event | string;
|
||||
created_at: Date;
|
||||
updated_at: Date;
|
||||
}
|
||||
|
||||
export interface SearchOptions extends MemoryOptions {
|
||||
api_version?: API_VERSION | string;
|
||||
limit?: number;
|
||||
enable_graph?: boolean;
|
||||
threshold?: number;
|
||||
top_k?: number;
|
||||
only_metadata_based_search?: boolean;
|
||||
keyword_search?: boolean;
|
||||
fields?: string[];
|
||||
categories?: string[];
|
||||
rerank?: boolean;
|
||||
}
|
||||
|
||||
enum Event {
|
||||
ADD = "ADD",
|
||||
UPDATE = "UPDATE",
|
||||
DELETE = "DELETE",
|
||||
NOOP = "NOOP",
|
||||
}
|
||||
|
||||
export interface MemoryData {
|
||||
memory: string;
|
||||
}
|
||||
|
||||
export interface Memory {
|
||||
id: string;
|
||||
messages?: Array<Messages>;
|
||||
event?: Event | string;
|
||||
data?: MemoryData | null;
|
||||
memory?: string;
|
||||
user_id?: string;
|
||||
hash?: string;
|
||||
categories?: Array<string>;
|
||||
created_at?: Date;
|
||||
updated_at?: Date;
|
||||
memory_type?: string;
|
||||
score?: number;
|
||||
metadata?: any | null;
|
||||
owner?: string | null;
|
||||
agent_id?: string | null;
|
||||
app_id?: string | null;
|
||||
run_id?: string | null;
|
||||
}
|
||||
|
||||
export interface MemoryUpdateBody {
|
||||
memoryId: string;
|
||||
text: string;
|
||||
}
|
||||
|
||||
export interface User {
|
||||
id: string;
|
||||
name: string;
|
||||
created_at: Date;
|
||||
updated_at: Date;
|
||||
total_memories: number;
|
||||
owner: string;
|
||||
type: string;
|
||||
}
|
||||
|
||||
export interface AllUsers {
|
||||
count: number;
|
||||
results: Array<User>;
|
||||
next: any;
|
||||
previous: any;
|
||||
}
|
||||
|
||||
export interface ProjectResponse {
|
||||
custom_instructions?: string;
|
||||
custom_categories?: string[];
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
interface custom_categories {
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
export interface PromptUpdatePayload {
|
||||
custom_instructions?: string;
|
||||
custom_categories?: custom_categories[];
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
enum WebhookEvent {
|
||||
MEMORY_ADDED = "memory_add",
|
||||
MEMORY_UPDATED = "memory_update",
|
||||
MEMORY_DELETED = "memory_delete",
|
||||
}
|
||||
|
||||
export interface Webhook {
|
||||
webhook_id?: string;
|
||||
name: string;
|
||||
url: string;
|
||||
project?: string;
|
||||
created_at?: Date;
|
||||
updated_at?: Date;
|
||||
is_active?: boolean;
|
||||
event_types?: WebhookEvent[];
|
||||
}
|
||||
|
||||
export interface WebhookPayload {
|
||||
eventTypes: WebhookEvent[];
|
||||
projectId: string;
|
||||
webhookId: string;
|
||||
name: string;
|
||||
url: string;
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
// @ts-nocheck
|
||||
import type { PostHog } from "posthog-js";
|
||||
import type { TelemetryClient } from "./telemetry.types";
|
||||
|
||||
let version = "1.0.20";
|
||||
|
||||
const MEM0_TELEMETRY = process.env.MEM0_TELEMETRY !== "false";
|
||||
const POSTHOG_API_KEY = "phc_hgJkUVJFYtmaJqrvf6CYN67TIQ8yhXAkWzUn9AMU4yX";
|
||||
const POSTHOG_HOST = "https://us.i.posthog.com";
|
||||
|
||||
// Browser-specific hash function using Web Crypto API
|
||||
async function generateHash(input: string): Promise<string> {
|
||||
const msgBuffer = new TextEncoder().encode(input);
|
||||
const hashBuffer = await window.crypto.subtle.digest("SHA-256", msgBuffer);
|
||||
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
||||
return hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
|
||||
}
|
||||
|
||||
class BrowserTelemetry implements TelemetryClient {
|
||||
client: PostHog | null = null;
|
||||
|
||||
constructor(projectApiKey: string, host: string) {
|
||||
if (MEM0_TELEMETRY) {
|
||||
this.initializeClient(projectApiKey, host);
|
||||
}
|
||||
}
|
||||
|
||||
private async initializeClient(projectApiKey: string, host: string) {
|
||||
try {
|
||||
const posthog = await import("posthog-js").catch(() => null);
|
||||
if (posthog) {
|
||||
posthog.init(projectApiKey, { api_host: host });
|
||||
this.client = posthog;
|
||||
}
|
||||
} catch (error) {
|
||||
// Silently fail if posthog-js is not available
|
||||
this.client = null;
|
||||
}
|
||||
}
|
||||
|
||||
async captureEvent(distinctId: string, eventName: string, properties = {}) {
|
||||
if (!this.client || !MEM0_TELEMETRY) return;
|
||||
|
||||
const eventProperties = {
|
||||
client_source: "browser",
|
||||
client_version: getVersion(),
|
||||
browser: window.navigator.userAgent,
|
||||
...properties,
|
||||
};
|
||||
|
||||
try {
|
||||
this.client.capture(eventName, eventProperties);
|
||||
} catch (error) {
|
||||
// Silently fail if telemetry fails
|
||||
}
|
||||
}
|
||||
|
||||
async shutdown() {
|
||||
// No shutdown needed for browser client
|
||||
}
|
||||
}
|
||||
|
||||
function getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
const telemetry = new BrowserTelemetry(POSTHOG_API_KEY, POSTHOG_HOST);
|
||||
|
||||
async function captureClientEvent(
|
||||
eventName: string,
|
||||
instance: any,
|
||||
additionalData = {},
|
||||
) {
|
||||
const eventData = {
|
||||
function: `${instance.constructor.name}`,
|
||||
...additionalData,
|
||||
};
|
||||
await telemetry.captureEvent(
|
||||
instance.telemetryId,
|
||||
`client.${eventName}`,
|
||||
eventData,
|
||||
);
|
||||
}
|
||||
|
||||
export { telemetry, captureClientEvent, generateHash };
|
||||
@@ -0,0 +1,107 @@
|
||||
// @ts-nocheck
|
||||
import type { TelemetryClient } from "./telemetry.types";
|
||||
|
||||
let version = "1.0.20";
|
||||
|
||||
const MEM0_TELEMETRY = process.env.MEM0_TELEMETRY !== "false";
|
||||
const POSTHOG_API_KEY = "phc_hgJkUVJFYtmaJqrvf6CYN67TIQ8yhXAkWzUn9AMU4yX";
|
||||
const POSTHOG_HOST = "https://us.i.posthog.com";
|
||||
|
||||
// Node-specific hash function using crypto module
|
||||
function generateHash(input: string): string {
|
||||
const crypto = require("crypto");
|
||||
return crypto.createHash("sha256").update(input).digest("hex");
|
||||
}
|
||||
|
||||
class NodeTelemetry implements TelemetryClient {
|
||||
client: any = null;
|
||||
|
||||
constructor(projectApiKey: string, host: string) {
|
||||
if (MEM0_TELEMETRY) {
|
||||
this.initializeClient(projectApiKey, host);
|
||||
}
|
||||
}
|
||||
|
||||
private async initializeClient(projectApiKey: string, host: string) {
|
||||
try {
|
||||
const { PostHog } = await import("posthog-node").catch(() => ({
|
||||
PostHog: null,
|
||||
}));
|
||||
if (PostHog) {
|
||||
this.client = new PostHog(projectApiKey, { host, flushAt: 1 });
|
||||
}
|
||||
} catch (error) {
|
||||
// Silently fail if posthog-node is not available
|
||||
this.client = null;
|
||||
}
|
||||
}
|
||||
|
||||
async captureEvent(distinctId: string, eventName: string, properties = {}) {
|
||||
if (!this.client || !MEM0_TELEMETRY) return;
|
||||
|
||||
const eventProperties = {
|
||||
client_source: "nodejs",
|
||||
client_version: getVersion(),
|
||||
...this.getEnvironmentInfo(),
|
||||
...properties,
|
||||
};
|
||||
|
||||
try {
|
||||
this.client.capture({
|
||||
distinctId,
|
||||
event: eventName,
|
||||
properties: eventProperties,
|
||||
});
|
||||
} catch (error) {
|
||||
// Silently fail if telemetry fails
|
||||
}
|
||||
}
|
||||
|
||||
private getEnvironmentInfo() {
|
||||
try {
|
||||
const os = require("os");
|
||||
return {
|
||||
node_version: process.version,
|
||||
os: process.platform,
|
||||
os_version: os.release(),
|
||||
os_arch: os.arch(),
|
||||
};
|
||||
} catch (error) {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
async shutdown() {
|
||||
if (this.client) {
|
||||
try {
|
||||
return this.client.shutdown();
|
||||
} catch (error) {
|
||||
// Silently fail shutdown
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
const telemetry = new NodeTelemetry(POSTHOG_API_KEY, POSTHOG_HOST);
|
||||
|
||||
async function captureClientEvent(
|
||||
eventName: string,
|
||||
instance: any,
|
||||
additionalData = {},
|
||||
) {
|
||||
const eventData = {
|
||||
function: `${instance.constructor.name}`,
|
||||
...additionalData,
|
||||
};
|
||||
await telemetry.captureEvent(
|
||||
instance.telemetryId,
|
||||
`client.${eventName}`,
|
||||
eventData,
|
||||
);
|
||||
}
|
||||
|
||||
export { telemetry, captureClientEvent, generateHash };
|
||||
@@ -0,0 +1,3 @@
|
||||
// @ts-nocheck
|
||||
// Re-export browser telemetry by default
|
||||
export * from "./telemetry.browser";
|
||||
@@ -0,0 +1,15 @@
|
||||
export interface TelemetryClient {
|
||||
captureEvent(
|
||||
distinctId: string,
|
||||
eventName: string,
|
||||
properties?: Record<string, any>,
|
||||
): Promise<void>;
|
||||
shutdown(): Promise<void>;
|
||||
}
|
||||
|
||||
export interface TelemetryInstance {
|
||||
telemetryId: string;
|
||||
constructor: {
|
||||
name: string;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,391 @@
|
||||
import { MemoryClient } from "../mem0";
|
||||
import dotenv from "dotenv";
|
||||
|
||||
dotenv.config();
|
||||
|
||||
const apiKey = process.env.MEM0_API_KEY || "";
|
||||
// const client = new MemoryClient({ apiKey, host: 'https://api.mem0.ai', organizationId: "org_gRNd1RrQa4y52iK4tG8o59hXyVbaULikgq4kethC", projectId: "proj_7RfMkWs0PMgXYweGUNKqV9M9mgIRNt5XcupE7mSP" });
|
||||
// const client = new MemoryClient({ apiKey, host: 'https://api.mem0.ai', organizationName: "saket-default-org", projectName: "default-project" });
|
||||
const client = new MemoryClient({ apiKey, host: "https://api.mem0.ai" });
|
||||
|
||||
// Generate a random string
|
||||
const randomString = () => {
|
||||
return (
|
||||
Math.random().toString(36).substring(2, 15) +
|
||||
Math.random().toString(36).substring(2, 15)
|
||||
);
|
||||
};
|
||||
|
||||
describe("MemoryClient API", () => {
|
||||
let userId: string, memoryId: string;
|
||||
|
||||
beforeAll(() => {
|
||||
userId = randomString();
|
||||
});
|
||||
|
||||
const messages1 = [
|
||||
{ role: "user", content: "Hey, I am Alex. I'm now a vegetarian." },
|
||||
{ role: "assistant", content: "Hello Alex! Glad to hear!" },
|
||||
];
|
||||
|
||||
it("should add messages successfully", async () => {
|
||||
const res = await client.add(messages1, { user_id: userId || "" });
|
||||
|
||||
// Validate the response contains an iterable list
|
||||
expect(Array.isArray(res)).toBe(true);
|
||||
|
||||
// Validate the fields of the first message in the response
|
||||
const message = res[0];
|
||||
expect(typeof message.id).toBe("string");
|
||||
expect(typeof message.data?.memory).toBe("string");
|
||||
expect(typeof message.event).toBe("string");
|
||||
|
||||
// Store the memory ID for later use
|
||||
memoryId = message.id;
|
||||
});
|
||||
|
||||
it("should retrieve the specific memory by ID", async () => {
|
||||
const memory = await client.get(memoryId);
|
||||
|
||||
// Validate that the memory fields have the correct types and values
|
||||
|
||||
// Should be a string (memory id)
|
||||
expect(typeof memory.id).toBe("string");
|
||||
|
||||
// Should be a string (the actual memory content)
|
||||
expect(typeof memory.memory).toBe("string");
|
||||
|
||||
// Should be a string and equal to the userId
|
||||
expect(typeof memory.user_id).toBe("string");
|
||||
expect(memory.user_id).toBe(userId);
|
||||
|
||||
// Should be null or any object (metadata)
|
||||
expect(
|
||||
memory.metadata === null || typeof memory.metadata === "object",
|
||||
).toBe(true);
|
||||
|
||||
// Should be an array of strings or null (categories)
|
||||
expect(Array.isArray(memory.categories) || memory.categories === null).toBe(
|
||||
true,
|
||||
);
|
||||
if (Array.isArray(memory.categories)) {
|
||||
memory.categories.forEach((category) => {
|
||||
expect(typeof category).toBe("string");
|
||||
});
|
||||
}
|
||||
|
||||
// Should be a valid date (created_at)
|
||||
expect(new Date(memory.created_at || "").toString()).not.toBe(
|
||||
"Invalid Date",
|
||||
);
|
||||
|
||||
// Should be a valid date (updated_at)
|
||||
expect(new Date(memory.updated_at || "").toString()).not.toBe(
|
||||
"Invalid Date",
|
||||
);
|
||||
});
|
||||
|
||||
it("should retrieve all users successfully", async () => {
|
||||
const allUsers = await client.users();
|
||||
|
||||
// Validate the number of users is a number
|
||||
expect(typeof allUsers.count).toBe("number");
|
||||
|
||||
// Validate the structure of the first user
|
||||
const firstUser = allUsers.results[0];
|
||||
expect(typeof firstUser.id).toBe("string");
|
||||
expect(typeof firstUser.name).toBe("string");
|
||||
expect(typeof firstUser.created_at).toBe("string");
|
||||
expect(typeof firstUser.updated_at).toBe("string");
|
||||
expect(typeof firstUser.total_memories).toBe("number");
|
||||
expect(typeof firstUser.type).toBe("string");
|
||||
|
||||
// Find the user with the name matching userId
|
||||
const entity = allUsers.results.find((user) => user.name === userId);
|
||||
expect(entity).not.toBeUndefined();
|
||||
|
||||
// Store the entity ID for later use
|
||||
const entity_id = entity?.id;
|
||||
expect(typeof entity_id).toBe("string");
|
||||
});
|
||||
|
||||
it("should retrieve all memories for the user", async () => {
|
||||
const res3 = await client.getAll({ user_id: userId });
|
||||
|
||||
// Validate that res3 is an iterable list (array)
|
||||
expect(Array.isArray(res3)).toBe(true);
|
||||
|
||||
if (res3.length > 0) {
|
||||
// Iterate through the first memory for validation (you can loop through all if needed)
|
||||
const memory = res3[0];
|
||||
|
||||
// Should be a string (memory id)
|
||||
expect(typeof memory.id).toBe("string");
|
||||
|
||||
// Should be a string (the actual memory content)
|
||||
expect(typeof memory.memory).toBe("string");
|
||||
|
||||
// Should be a string and equal to the userId
|
||||
expect(typeof memory.user_id).toBe("string");
|
||||
expect(memory.user_id).toBe(userId);
|
||||
|
||||
// Should be null or an object (metadata)
|
||||
expect(
|
||||
memory.metadata === null || typeof memory.metadata === "object",
|
||||
).toBe(true);
|
||||
|
||||
// Should be an array of strings or null (categories)
|
||||
expect(
|
||||
Array.isArray(memory.categories) || memory.categories === null,
|
||||
).toBe(true);
|
||||
if (Array.isArray(memory.categories)) {
|
||||
memory.categories.forEach((category) => {
|
||||
expect(typeof category).toBe("string");
|
||||
});
|
||||
}
|
||||
|
||||
// Should be a valid date (created_at)
|
||||
expect(new Date(memory.created_at || "").toString()).not.toBe(
|
||||
"Invalid Date",
|
||||
);
|
||||
|
||||
// Should be a valid date (updated_at)
|
||||
expect(new Date(memory.updated_at || "").toString()).not.toBe(
|
||||
"Invalid Date",
|
||||
);
|
||||
} else {
|
||||
// If there are no memories, assert that the list is empty
|
||||
expect(res3.length).toBe(0);
|
||||
}
|
||||
});
|
||||
|
||||
it("should search and return results based on provided query and filters (API version 2)", async () => {
|
||||
const searchOptionsV2 = {
|
||||
query: "What do you know about me?",
|
||||
filters: {
|
||||
OR: [{ user_id: userId }, { agent_id: "shopping-assistant" }],
|
||||
},
|
||||
threshold: 0.1,
|
||||
api_version: "v2",
|
||||
};
|
||||
|
||||
const searchResultV2 = await client.search(
|
||||
"What do you know about me?",
|
||||
searchOptionsV2,
|
||||
);
|
||||
|
||||
// Validate that searchResultV2 is an iterable list (array)
|
||||
expect(Array.isArray(searchResultV2)).toBe(true);
|
||||
|
||||
if (searchResultV2.length > 0) {
|
||||
// Iterate through the first search result for validation (you can loop through all if needed)
|
||||
const memory = searchResultV2[0];
|
||||
|
||||
// Should be a string (memory id)
|
||||
expect(typeof memory.id).toBe("string");
|
||||
|
||||
// Should be a string (the actual memory content)
|
||||
expect(typeof memory.memory).toBe("string");
|
||||
|
||||
if (memory.user_id) {
|
||||
// Should be a string and equal to userId
|
||||
expect(typeof memory.user_id).toBe("string");
|
||||
expect(memory.user_id).toBe(userId);
|
||||
}
|
||||
|
||||
if (memory.agent_id) {
|
||||
// Should be a string (agent_id)
|
||||
expect(typeof memory.agent_id).toBe("string");
|
||||
expect(memory.agent_id).toBe("shopping-assistant");
|
||||
}
|
||||
|
||||
// Should be null or an object (metadata)
|
||||
expect(
|
||||
memory.metadata === null || typeof memory.metadata === "object",
|
||||
).toBe(true);
|
||||
|
||||
// Should be an array of strings or null (categories)
|
||||
expect(
|
||||
Array.isArray(memory.categories) || memory.categories === null,
|
||||
).toBe(true);
|
||||
if (Array.isArray(memory.categories)) {
|
||||
memory.categories.forEach((category) => {
|
||||
expect(typeof category).toBe("string");
|
||||
});
|
||||
}
|
||||
|
||||
// Should be a valid date (created_at)
|
||||
expect(new Date(memory.created_at || "").toString()).not.toBe(
|
||||
"Invalid Date",
|
||||
);
|
||||
|
||||
// Should be a valid date (updated_at)
|
||||
expect(new Date(memory.updated_at || "").toString()).not.toBe(
|
||||
"Invalid Date",
|
||||
);
|
||||
|
||||
// Should be a number (score)
|
||||
expect(typeof memory.score).toBe("number");
|
||||
} else {
|
||||
// If no search results, assert that the list is empty
|
||||
expect(searchResultV2.length).toBe(0);
|
||||
}
|
||||
});
|
||||
|
||||
it("should search and return results based on provided query (API version 1)", async () => {
|
||||
const searchResultV1 = await client.search("What is my name?", {
|
||||
user_id: userId,
|
||||
});
|
||||
|
||||
// Validate that searchResultV1 is an iterable list (array)
|
||||
expect(Array.isArray(searchResultV1)).toBe(true);
|
||||
|
||||
if (searchResultV1.length > 0) {
|
||||
// Iterate through the first search result for validation (you can loop through all if needed)
|
||||
const memory = searchResultV1[0];
|
||||
|
||||
// Should be a string (memory id)
|
||||
expect(typeof memory.id).toBe("string");
|
||||
|
||||
// Should be a string (the actual memory content)
|
||||
expect(typeof memory.memory).toBe("string");
|
||||
|
||||
// Should be a string and equal to userId
|
||||
expect(typeof memory.user_id).toBe("string");
|
||||
expect(memory.user_id).toBe(userId);
|
||||
|
||||
// Should be null or an object (metadata)
|
||||
expect(
|
||||
memory.metadata === null || typeof memory.metadata === "object",
|
||||
).toBe(true);
|
||||
|
||||
// Should be an array of strings or null (categories)
|
||||
expect(
|
||||
Array.isArray(memory.categories) || memory.categories === null,
|
||||
).toBe(true);
|
||||
if (Array.isArray(memory.categories)) {
|
||||
memory.categories.forEach((category) => {
|
||||
expect(typeof category).toBe("string");
|
||||
});
|
||||
}
|
||||
|
||||
// Should be a valid date (created_at)
|
||||
expect(new Date(memory.created_at || "").toString()).not.toBe(
|
||||
"Invalid Date",
|
||||
);
|
||||
|
||||
// Should be a valid date (updated_at)
|
||||
expect(new Date(memory.updated_at || "").toString()).not.toBe(
|
||||
"Invalid Date",
|
||||
);
|
||||
|
||||
// Should be a number (score)
|
||||
expect(typeof memory.score).toBe("number");
|
||||
} else {
|
||||
// If no search results, assert that the list is empty
|
||||
expect(searchResultV1.length).toBe(0);
|
||||
}
|
||||
});
|
||||
|
||||
it("should retrieve history of a specific memory and validate the fields", async () => {
|
||||
const res22 = await client.history(memoryId);
|
||||
|
||||
// Validate that res22 is an iterable list (array)
|
||||
expect(Array.isArray(res22)).toBe(true);
|
||||
|
||||
if (res22.length > 0) {
|
||||
// Iterate through the first history entry for validation (you can loop through all if needed)
|
||||
const historyEntry = res22[0];
|
||||
|
||||
// Should be a string (history entry id)
|
||||
expect(typeof historyEntry.id).toBe("string");
|
||||
|
||||
// Should be a string (memory id related to the history entry)
|
||||
expect(typeof historyEntry.memory_id).toBe("string");
|
||||
|
||||
// Should be a string and equal to userId
|
||||
expect(typeof historyEntry.user_id).toBe("string");
|
||||
expect(historyEntry.user_id).toBe(userId);
|
||||
|
||||
// Should be a string or null (old memory)
|
||||
expect(
|
||||
historyEntry.old_memory === null ||
|
||||
typeof historyEntry.old_memory === "string",
|
||||
).toBe(true);
|
||||
|
||||
// Should be a string or null (new memory)
|
||||
expect(
|
||||
historyEntry.new_memory === null ||
|
||||
typeof historyEntry.new_memory === "string",
|
||||
).toBe(true);
|
||||
|
||||
// Should be an array of strings or null (categories)
|
||||
expect(
|
||||
Array.isArray(historyEntry.categories) ||
|
||||
historyEntry.categories === null,
|
||||
).toBe(true);
|
||||
if (Array.isArray(historyEntry.categories)) {
|
||||
historyEntry.categories.forEach((category) => {
|
||||
expect(typeof category).toBe("string");
|
||||
});
|
||||
}
|
||||
|
||||
// Should be a valid date (created_at)
|
||||
expect(new Date(historyEntry.created_at).toString()).not.toBe(
|
||||
"Invalid Date",
|
||||
);
|
||||
|
||||
// Should be a valid date (updated_at)
|
||||
expect(new Date(historyEntry.updated_at).toString()).not.toBe(
|
||||
"Invalid Date",
|
||||
);
|
||||
|
||||
// Should be a string, one of: ADD, UPDATE, DELETE, NOOP
|
||||
expect(["ADD", "UPDATE", "DELETE", "NOOP"]).toContain(historyEntry.event);
|
||||
|
||||
// Validate conditions based on event type
|
||||
if (historyEntry.event === "ADD") {
|
||||
expect(historyEntry.old_memory).toBeNull();
|
||||
expect(historyEntry.new_memory).not.toBeNull();
|
||||
} else if (historyEntry.event === "UPDATE") {
|
||||
expect(historyEntry.old_memory).not.toBeNull();
|
||||
expect(historyEntry.new_memory).not.toBeNull();
|
||||
} else if (historyEntry.event === "DELETE") {
|
||||
expect(historyEntry.old_memory).not.toBeNull();
|
||||
expect(historyEntry.new_memory).toBeNull();
|
||||
}
|
||||
|
||||
// Should be a list of objects or null (input)
|
||||
expect(
|
||||
Array.isArray(historyEntry.input) || historyEntry.input === null,
|
||||
).toBe(true);
|
||||
if (Array.isArray(historyEntry.input)) {
|
||||
historyEntry.input.forEach((input) => {
|
||||
// Each input should be an object
|
||||
expect(typeof input).toBe("object");
|
||||
|
||||
// Should have string content
|
||||
expect(typeof input.content).toBe("string");
|
||||
|
||||
// Should have a role that is either 'user' or 'assistant'
|
||||
expect(["user", "assistant"]).toContain(input.role);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// If no history entries, assert that the list is empty
|
||||
expect(res22.length).toBe(0);
|
||||
}
|
||||
});
|
||||
|
||||
it("should delete the user successfully", async () => {
|
||||
const allUsers = await client.users();
|
||||
const entity = allUsers.results.find((user) => user.name === userId);
|
||||
|
||||
if (entity) {
|
||||
const deletedUser = await client.deleteUser(entity.id);
|
||||
|
||||
// Validate the deletion message
|
||||
expect(deletedUser.message).toBe("Entity deleted successfully!");
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,28 @@
|
||||
# OpenAI API Key
|
||||
OPENAI_API_KEY=your-api-key-here
|
||||
|
||||
# Optional: Custom model names
|
||||
OPENAI_EMBEDDING_MODEL=text-embedding-3-small
|
||||
OPENAI_COMPLETION_MODEL=gpt-4-turbo-preview
|
||||
|
||||
# PGVector Configuration (optional)
|
||||
# Uncomment and set these values to use PGVector
|
||||
#PGVECTOR_DB=vectordb
|
||||
#PGVECTOR_USER=postgres
|
||||
#PGVECTOR_PASSWORD=postgres
|
||||
#PGVECTOR_HOST=localhost
|
||||
#PGVECTOR_PORT=5432
|
||||
|
||||
# Qdrant Configuration (optional)
|
||||
# Uncomment and set these values to use Qdrant
|
||||
# QDRANT_URL=http://localhost:6333
|
||||
#QDRANT_API_KEY=your-api-key-here
|
||||
#QDRANT_PATH=/path/to/local/storage # For local file-based storage
|
||||
#QDRANT_HOST=localhost # Alternative to URL
|
||||
#QDRANT_PORT=6333 # Alternative to URL
|
||||
|
||||
# Redis Configuration (optional)
|
||||
# Uncomment and set these values to use Redis
|
||||
# REDIS_URL=redis://localhost:6379
|
||||
# REDIS_USERNAME=default
|
||||
# REDIS_PASSWORD=your-password-here
|
||||
@@ -0,0 +1,23 @@
|
||||
# Dependencies
|
||||
node_modules/
|
||||
|
||||
# Build output
|
||||
dist/
|
||||
|
||||
# Environment variables
|
||||
.env
|
||||
|
||||
# IDE files
|
||||
.vscode/
|
||||
.idea/
|
||||
|
||||
# Logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
|
||||
# SQLite database
|
||||
*.db
|
||||
|
||||
# OS files
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
@@ -0,0 +1,177 @@
|
||||
# mem0-ts
|
||||
|
||||
A TypeScript implementation of the mem0 memory system, using OpenAI for embeddings and completions.
|
||||
|
||||
## Features
|
||||
|
||||
- Memory storage and retrieval using vector embeddings
|
||||
- Fact extraction from text using GPT-4
|
||||
- SQLite-based history tracking
|
||||
- Optional graph-based memory relationships
|
||||
- TypeScript type safety
|
||||
- Built-in OpenAI integration with default configuration
|
||||
- In-memory vector store implementation
|
||||
- Extensible architecture with interfaces for custom implementations
|
||||
|
||||
## Installation
|
||||
|
||||
1. Clone the repository:
|
||||
|
||||
```bash
|
||||
git clone <repository-url>
|
||||
cd mem0-ts
|
||||
```
|
||||
|
||||
2. Install dependencies:
|
||||
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
3. Set up environment variables:
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
# Edit .env with your OpenAI API key
|
||||
```
|
||||
|
||||
4. Build the project:
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Example
|
||||
|
||||
```typescript
|
||||
import { Memory } from "mem0-ts";
|
||||
|
||||
// Create a memory instance with default OpenAI configuration
|
||||
const memory = new Memory();
|
||||
|
||||
// Or with minimal configuration (only API key)
|
||||
const memory = new Memory({
|
||||
embedder: {
|
||||
config: {
|
||||
apiKey: process.env.OPENAI_API_KEY,
|
||||
},
|
||||
},
|
||||
llm: {
|
||||
config: {
|
||||
apiKey: process.env.OPENAI_API_KEY,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Or with custom configuration
|
||||
const memory = new Memory({
|
||||
embedder: {
|
||||
provider: "openai",
|
||||
config: {
|
||||
apiKey: process.env.OPENAI_API_KEY,
|
||||
model: "text-embedding-3-small",
|
||||
},
|
||||
},
|
||||
vectorStore: {
|
||||
provider: "memory",
|
||||
config: {
|
||||
collectionName: "custom-memories",
|
||||
},
|
||||
},
|
||||
llm: {
|
||||
provider: "openai",
|
||||
config: {
|
||||
apiKey: process.env.OPENAI_API_KEY,
|
||||
model: "gpt-4-turbo-preview",
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Add a memory
|
||||
await memory.add("The sky is blue", "user123");
|
||||
|
||||
// Search memories
|
||||
const results = await memory.search("What color is the sky?", "user123");
|
||||
```
|
||||
|
||||
### Default Configuration
|
||||
|
||||
The memory system comes with sensible defaults:
|
||||
|
||||
- OpenAI embeddings with `text-embedding-3-small` model
|
||||
- In-memory vector store
|
||||
- OpenAI GPT-4 Turbo for LLM operations
|
||||
- SQLite for history tracking
|
||||
|
||||
You only need to provide API keys - all other settings are optional.
|
||||
|
||||
### Methods
|
||||
|
||||
- `add(messages: string | Message[], userId?: string, ...): Promise<SearchResult>`
|
||||
- `search(query: string, userId?: string, ...): Promise<SearchResult>`
|
||||
- `get(memoryId: string): Promise<MemoryItem | null>`
|
||||
- `update(memoryId: string, data: string): Promise<{ message: string }>`
|
||||
- `delete(memoryId: string): Promise<{ message: string }>`
|
||||
- `deleteAll(userId?: string, ...): Promise<{ message: string }>`
|
||||
- `history(memoryId: string): Promise<any[]>`
|
||||
- `reset(): Promise<void>`
|
||||
|
||||
### Try the Example
|
||||
|
||||
We provide a comprehensive example in `examples/basic.ts` that demonstrates all the features including:
|
||||
|
||||
- Default configuration usage
|
||||
- In-memory vector store
|
||||
- PGVector store (with PostgreSQL)
|
||||
- Qdrant vector store
|
||||
- Redis vector store
|
||||
- Memory operations (add, search, update, delete)
|
||||
|
||||
To run the example:
|
||||
|
||||
```bash
|
||||
npm run example
|
||||
```
|
||||
|
||||
You can use this example as a template and modify it according to your needs. The example includes:
|
||||
|
||||
- Different vector store configurations
|
||||
- Various memory operations
|
||||
- Error handling
|
||||
- Environment variable usage
|
||||
|
||||
## Development
|
||||
|
||||
1. Build the project:
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
2. Clean build files:
|
||||
|
||||
```bash
|
||||
npm run clean
|
||||
```
|
||||
|
||||
## Extending
|
||||
|
||||
The system is designed to be extensible. You can implement your own:
|
||||
|
||||
- Embedders by implementing the `Embedder` interface
|
||||
- Vector stores by implementing the `VectorStore` interface
|
||||
- Language models by implementing the `LLM` interface
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
|
||||
## Contributing
|
||||
|
||||
1. Fork the repository
|
||||
2. Create your feature branch
|
||||
3. Commit your changes
|
||||
4. Push to the branch
|
||||
5. Create a new Pull Request
|
||||
@@ -0,0 +1,287 @@
|
||||
import { Memory } from "../src";
|
||||
import dotenv from "dotenv";
|
||||
|
||||
// Load environment variables
|
||||
dotenv.config();
|
||||
|
||||
async function demoDefaultConfig() {
|
||||
console.log("\n=== Testing Default Config ===\n");
|
||||
|
||||
const memory = new Memory();
|
||||
await runTests(memory);
|
||||
}
|
||||
|
||||
async function run_examples() {
|
||||
// Test default config
|
||||
await demoDefaultConfig();
|
||||
}
|
||||
|
||||
run_examples();
|
||||
|
||||
async function runTests(memory: Memory) {
|
||||
try {
|
||||
// Reset all memories
|
||||
console.log("\nResetting all memories...");
|
||||
await memory.reset();
|
||||
console.log("All memories reset");
|
||||
|
||||
// Add a single memory
|
||||
console.log("\nAdding a single memory...");
|
||||
const result1 = await memory.add(
|
||||
"Hi, my name is John and I am a software engineer.",
|
||||
"user123",
|
||||
);
|
||||
console.log("Added memory:", result1);
|
||||
|
||||
// Add multiple messages
|
||||
console.log("\nAdding multiple messages...");
|
||||
const result2 = await memory.add(
|
||||
[
|
||||
{ role: "user", content: "What is your favorite city?" },
|
||||
{ role: "assistant", content: "I love Paris, it is my favorite city." },
|
||||
],
|
||||
"user123",
|
||||
);
|
||||
console.log("Added messages:", result2);
|
||||
|
||||
// Trying to update the memory
|
||||
const result3 = await memory.add(
|
||||
[
|
||||
{ role: "user", content: "What is your favorite city?" },
|
||||
{
|
||||
role: "assistant",
|
||||
content: "I love New York, it is my favorite city.",
|
||||
},
|
||||
],
|
||||
"user123",
|
||||
);
|
||||
console.log("Updated messages:", result3);
|
||||
|
||||
// Get a single memory
|
||||
console.log("\nGetting a single memory...");
|
||||
if (result1.results && result1.results.length > 0) {
|
||||
const singleMemory = await memory.get(result1.results[0].id);
|
||||
console.log("Single memory:", singleMemory);
|
||||
} else {
|
||||
console.log("No memory was added in the first step");
|
||||
}
|
||||
|
||||
// Updating this memory
|
||||
const result4 = await memory.update(
|
||||
result1.results[0].id,
|
||||
"I love India, it is my favorite country.",
|
||||
);
|
||||
console.log("Updated memory:", result4);
|
||||
|
||||
// Get all memories
|
||||
console.log("\nGetting all memories...");
|
||||
const allMemories = await memory.getAll("user123");
|
||||
console.log("All memories:", allMemories);
|
||||
|
||||
// Search for memories
|
||||
console.log("\nSearching memories...");
|
||||
const searchResult = await memory.search(
|
||||
"What do you know about Paris?",
|
||||
"user123",
|
||||
);
|
||||
console.log("Search results:", searchResult);
|
||||
|
||||
// Get memory history
|
||||
if (result1.results && result1.results.length > 0) {
|
||||
console.log("\nGetting memory history...");
|
||||
const history = await memory.history(result1.results[0].id);
|
||||
console.log("Memory history:", history);
|
||||
}
|
||||
|
||||
// Delete a memory
|
||||
if (result1.results && result1.results.length > 0) {
|
||||
console.log("\nDeleting a memory...");
|
||||
await memory.delete(result1.results[0].id);
|
||||
console.log("Memory deleted successfully");
|
||||
}
|
||||
|
||||
// Reset all memories
|
||||
console.log("\nResetting all memories...");
|
||||
await memory.reset();
|
||||
console.log("All memories reset");
|
||||
} catch (error) {
|
||||
console.error("Error:", error);
|
||||
}
|
||||
}
|
||||
|
||||
async function demoMemoryStore() {
|
||||
console.log("\n=== Testing In-Memory Vector Store ===\n");
|
||||
|
||||
const memory = new Memory({
|
||||
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",
|
||||
},
|
||||
},
|
||||
historyDbPath: "memory.db",
|
||||
});
|
||||
|
||||
await runTests(memory);
|
||||
}
|
||||
|
||||
async function demoPGVector() {
|
||||
console.log("\n=== Testing PGVector Store ===\n");
|
||||
|
||||
const memory = new Memory({
|
||||
version: "v1.1",
|
||||
embedder: {
|
||||
provider: "openai",
|
||||
config: {
|
||||
apiKey: process.env.OPENAI_API_KEY || "",
|
||||
model: "text-embedding-3-small",
|
||||
},
|
||||
},
|
||||
vectorStore: {
|
||||
provider: "pgvector",
|
||||
config: {
|
||||
collectionName: "memories",
|
||||
dimension: 1536,
|
||||
dbname: process.env.PGVECTOR_DB || "vectordb",
|
||||
user: process.env.PGVECTOR_USER || "postgres",
|
||||
password: process.env.PGVECTOR_PASSWORD || "postgres",
|
||||
host: process.env.PGVECTOR_HOST || "localhost",
|
||||
port: parseInt(process.env.PGVECTOR_PORT || "5432"),
|
||||
embeddingModelDims: 1536,
|
||||
hnsw: true,
|
||||
},
|
||||
},
|
||||
llm: {
|
||||
provider: "openai",
|
||||
config: {
|
||||
apiKey: process.env.OPENAI_API_KEY || "",
|
||||
model: "gpt-4-turbo-preview",
|
||||
},
|
||||
},
|
||||
historyDbPath: "memory.db",
|
||||
});
|
||||
|
||||
await runTests(memory);
|
||||
}
|
||||
|
||||
async function demoQdrant() {
|
||||
console.log("\n=== Testing Qdrant Store ===\n");
|
||||
|
||||
const memory = new Memory({
|
||||
version: "v1.1",
|
||||
embedder: {
|
||||
provider: "openai",
|
||||
config: {
|
||||
apiKey: process.env.OPENAI_API_KEY || "",
|
||||
model: "text-embedding-3-small",
|
||||
},
|
||||
},
|
||||
vectorStore: {
|
||||
provider: "qdrant",
|
||||
config: {
|
||||
collectionName: "memories",
|
||||
embeddingModelDims: 1536,
|
||||
url: process.env.QDRANT_URL,
|
||||
apiKey: process.env.QDRANT_API_KEY,
|
||||
path: process.env.QDRANT_PATH,
|
||||
host: process.env.QDRANT_HOST,
|
||||
port: process.env.QDRANT_PORT
|
||||
? parseInt(process.env.QDRANT_PORT)
|
||||
: undefined,
|
||||
onDisk: true,
|
||||
},
|
||||
},
|
||||
llm: {
|
||||
provider: "openai",
|
||||
config: {
|
||||
apiKey: process.env.OPENAI_API_KEY || "",
|
||||
model: "gpt-4-turbo-preview",
|
||||
},
|
||||
},
|
||||
historyDbPath: "memory.db",
|
||||
});
|
||||
|
||||
await runTests(memory);
|
||||
}
|
||||
|
||||
async function demoRedis() {
|
||||
console.log("\n=== Testing Redis Store ===\n");
|
||||
|
||||
const memory = new Memory({
|
||||
version: "v1.1",
|
||||
embedder: {
|
||||
provider: "openai",
|
||||
config: {
|
||||
apiKey: process.env.OPENAI_API_KEY || "",
|
||||
model: "text-embedding-3-small",
|
||||
},
|
||||
},
|
||||
vectorStore: {
|
||||
provider: "redis",
|
||||
config: {
|
||||
collectionName: "memories",
|
||||
embeddingModelDims: 1536,
|
||||
redisUrl: process.env.REDIS_URL || "redis://localhost:6379",
|
||||
username: process.env.REDIS_USERNAME,
|
||||
password: process.env.REDIS_PASSWORD,
|
||||
},
|
||||
},
|
||||
llm: {
|
||||
provider: "openai",
|
||||
config: {
|
||||
apiKey: process.env.OPENAI_API_KEY || "",
|
||||
model: "gpt-4-turbo-preview",
|
||||
},
|
||||
},
|
||||
historyDbPath: "memory.db",
|
||||
});
|
||||
|
||||
await runTests(memory);
|
||||
}
|
||||
|
||||
async function main() {
|
||||
// Test in-memory store
|
||||
await demoMemoryStore();
|
||||
|
||||
// Test PGVector store if environment variables are set
|
||||
if (process.env.PGVECTOR_DB) {
|
||||
await demoPGVector();
|
||||
} else {
|
||||
console.log("\nSkipping PGVector test - environment variables not set");
|
||||
}
|
||||
|
||||
// Test Qdrant store if environment variables are set
|
||||
if (
|
||||
process.env.QDRANT_URL ||
|
||||
(process.env.QDRANT_HOST && process.env.QDRANT_PORT)
|
||||
) {
|
||||
await demoQdrant();
|
||||
} else {
|
||||
console.log("\nSkipping Qdrant test - environment variables not set");
|
||||
}
|
||||
|
||||
// Test Redis store if environment variables are set
|
||||
if (process.env.REDIS_URL) {
|
||||
await demoRedis();
|
||||
} else {
|
||||
console.log("\nSkipping Redis test - environment variables not set");
|
||||
}
|
||||
}
|
||||
|
||||
// main();
|
||||
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"name": "mem0ai-oss",
|
||||
"version": "1.0.0",
|
||||
"description": "TypeScript implementation of mem0 memory system",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"test": "jest",
|
||||
"start": "ts-node examples/basic.ts",
|
||||
"example": "ts-node examples/basic.ts",
|
||||
"clean": "rimraf dist",
|
||||
"prepare": "npm run build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@anthropic-ai/sdk": "^0.18.0",
|
||||
"@qdrant/js-client-rest": "^1.13.0",
|
||||
"@types/node": "^20.11.19",
|
||||
"@types/pg": "^8.11.0",
|
||||
"@types/redis": "^4.0.10",
|
||||
"@types/sqlite3": "^3.1.11",
|
||||
"@types/uuid": "^9.0.8",
|
||||
"dotenv": "^16.4.4",
|
||||
"groq-sdk": "^0.3.0",
|
||||
"openai": "^4.28.0",
|
||||
"pg": "^8.11.3",
|
||||
"redis": "^4.7.0",
|
||||
"sqlite3": "^5.1.7",
|
||||
"uuid": "^9.0.1",
|
||||
"zod": "^3.22.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "^29.5.12",
|
||||
"jest": "^29.7.0",
|
||||
"rimraf": "^5.0.5",
|
||||
"ts-jest": "^29.1.2",
|
||||
"ts-node": "^10.9.2",
|
||||
"typescript": "^5.3.3"
|
||||
},
|
||||
"keywords": [
|
||||
"memory",
|
||||
"openai",
|
||||
"embeddings",
|
||||
"vector-store",
|
||||
"typescript"
|
||||
],
|
||||
"author": "",
|
||||
"license": "MIT"
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import { MemoryConfig } from "../types";
|
||||
|
||||
export const DEFAULT_MEMORY_CONFIG: MemoryConfig = {
|
||||
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",
|
||||
},
|
||||
},
|
||||
historyDbPath: "memory.db",
|
||||
};
|
||||
@@ -0,0 +1,56 @@
|
||||
import { MemoryConfig, MemoryConfigSchema } from "../types";
|
||||
import { DEFAULT_MEMORY_CONFIG } from "./defaults";
|
||||
|
||||
export class ConfigManager {
|
||||
static mergeConfig(userConfig: Partial<MemoryConfig> = {}): MemoryConfig {
|
||||
const mergedConfig = {
|
||||
version: userConfig.version || DEFAULT_MEMORY_CONFIG.version,
|
||||
embedder: {
|
||||
provider:
|
||||
userConfig.embedder?.provider ||
|
||||
DEFAULT_MEMORY_CONFIG.embedder.provider,
|
||||
config: {
|
||||
apiKey:
|
||||
userConfig.embedder?.config?.apiKey ||
|
||||
DEFAULT_MEMORY_CONFIG.embedder.config.apiKey,
|
||||
model:
|
||||
userConfig.embedder?.config?.model ||
|
||||
DEFAULT_MEMORY_CONFIG.embedder.config.model,
|
||||
},
|
||||
},
|
||||
vectorStore: {
|
||||
provider:
|
||||
userConfig.vectorStore?.provider ||
|
||||
DEFAULT_MEMORY_CONFIG.vectorStore.provider,
|
||||
config: {
|
||||
collectionName:
|
||||
userConfig.vectorStore?.config?.collectionName ||
|
||||
DEFAULT_MEMORY_CONFIG.vectorStore.config.collectionName,
|
||||
dimension:
|
||||
userConfig.vectorStore?.config?.dimension ||
|
||||
DEFAULT_MEMORY_CONFIG.vectorStore.config.dimension,
|
||||
...userConfig.vectorStore?.config,
|
||||
},
|
||||
},
|
||||
llm: {
|
||||
provider:
|
||||
userConfig.llm?.provider || DEFAULT_MEMORY_CONFIG.llm.provider,
|
||||
config: {
|
||||
apiKey:
|
||||
userConfig.llm?.config?.apiKey ||
|
||||
DEFAULT_MEMORY_CONFIG.llm.config.apiKey,
|
||||
model:
|
||||
userConfig.llm?.config?.model ||
|
||||
DEFAULT_MEMORY_CONFIG.llm.config.model,
|
||||
},
|
||||
},
|
||||
historyDbPath:
|
||||
userConfig.historyDbPath || DEFAULT_MEMORY_CONFIG.historyDbPath,
|
||||
customPrompt: userConfig.customPrompt,
|
||||
graphStore: userConfig.graphStore,
|
||||
};
|
||||
|
||||
// Validate the merged config
|
||||
return MemoryConfigSchema.parse(mergedConfig);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
export interface Embedder {
|
||||
embed(text: string): Promise<number[]>;
|
||||
embedBatch(texts: string[]): Promise<number[][]>;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import OpenAI from "openai";
|
||||
import { Embedder } from "./base";
|
||||
import { EmbeddingConfig } from "../types";
|
||||
|
||||
export class OpenAIEmbedder implements Embedder {
|
||||
private openai: OpenAI;
|
||||
private model: string;
|
||||
|
||||
constructor(config: EmbeddingConfig) {
|
||||
this.openai = new OpenAI({ apiKey: config.apiKey });
|
||||
this.model = config.model || "text-embedding-3-small";
|
||||
}
|
||||
|
||||
async embed(text: string): Promise<number[]> {
|
||||
const response = await this.openai.embeddings.create({
|
||||
model: this.model,
|
||||
input: text,
|
||||
});
|
||||
return response.data[0].embedding;
|
||||
}
|
||||
|
||||
async embedBatch(texts: string[]): Promise<number[][]> {
|
||||
const response = await this.openai.embeddings.create({
|
||||
model: this.model,
|
||||
input: texts,
|
||||
});
|
||||
return response.data.map((item) => item.embedding);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
export * from "./memory";
|
||||
export * from "./memory/memory.types";
|
||||
export * from "./types";
|
||||
export * from "./embeddings/base";
|
||||
export * from "./embeddings/openai";
|
||||
export * from "./llms/base";
|
||||
export * from "./llms/openai";
|
||||
export * from "./llms/openai_structured";
|
||||
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";
|
||||
@@ -0,0 +1,46 @@
|
||||
import Anthropic from "@anthropic-ai/sdk";
|
||||
import { LLM, LLMResponse } from "./base";
|
||||
import { LLMConfig, Message } from "../types";
|
||||
|
||||
export class AnthropicLLM implements LLM {
|
||||
private client: Anthropic;
|
||||
private model: string;
|
||||
|
||||
constructor(config: LLMConfig) {
|
||||
const apiKey = config.apiKey || process.env.ANTHROPIC_API_KEY;
|
||||
if (!apiKey) {
|
||||
throw new Error("Anthropic API key is required");
|
||||
}
|
||||
this.client = new Anthropic({ apiKey });
|
||||
this.model = config.model || "claude-3-sonnet-20240229";
|
||||
}
|
||||
|
||||
async generateResponse(
|
||||
messages: Message[],
|
||||
responseFormat?: { type: string },
|
||||
): Promise<string> {
|
||||
// Extract system message if present
|
||||
const systemMessage = messages.find((msg) => msg.role === "system");
|
||||
const otherMessages = messages.filter((msg) => msg.role !== "system");
|
||||
|
||||
const response = await this.client.messages.create({
|
||||
model: this.model,
|
||||
messages: otherMessages.map((msg) => ({
|
||||
role: msg.role as "user" | "assistant",
|
||||
content: msg.content,
|
||||
})),
|
||||
system: systemMessage?.content,
|
||||
max_tokens: 4096,
|
||||
});
|
||||
|
||||
return response.content[0].text;
|
||||
}
|
||||
|
||||
async generateChat(messages: Message[]): Promise<LLMResponse> {
|
||||
const response = await this.generateResponse(messages);
|
||||
return {
|
||||
content: response,
|
||||
role: "assistant",
|
||||
};
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user