Compare commits
122 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ac085db500 | |||
| 2cc253341c | |||
| e3e2da6d45 | |||
| acf7a30d32 | |||
| a4f6751741 | |||
| 6f3fbd087d | |||
| a98842422b | |||
| aaf879322c | |||
| 8139b5887f | |||
| b4b27f099e | |||
| dc877fd3ba | |||
| 2bb0653e67 | |||
| eb24b92227 | |||
| a5ec286fd4 | |||
| 89499aedbe | |||
| 386d8b87ae | |||
| c173ec32d0 | |||
| dd6f6f7a2e | |||
| b6684b96f7 | |||
| 1fa0f0a157 | |||
| 2754f45387 | |||
| ecd4d91046 | |||
| a5a247b161 | |||
| d47cb8d284 | |||
| fa15db089d | |||
| d35065c887 | |||
| cdee6a4ff0 | |||
| 9eb4e77c75 | |||
| c700d790db | |||
| a90b572389 | |||
| 62c330e5b3 | |||
| c70dc7614b | |||
| e0003247c3 | |||
| 888ee766c5 | |||
| c7e91171a0 | |||
| 18c870ec79 | |||
| 3e5f68ee90 | |||
| a0cd4065d9 | |||
| 7c0c4a03c4 | |||
| a8ace18607 | |||
| df43f904d1 | |||
| a5a07d711b | |||
| a40268dd51 | |||
| c59752c6d6 | |||
| aa334fb569 | |||
| 40a5e87022 | |||
| 4dec9ace88 | |||
| e1dc27276b | |||
| 9a12ea7b3c | |||
| e10a509645 | |||
| fe3f10adb8 | |||
| 53c91fb107 | |||
| ecc596b11f | |||
| be37fca1bb | |||
| 849452cc93 | |||
| 1f2df450bb | |||
| 06d86996f2 | |||
| bb14cc42a0 | |||
| fbee8d5c20 | |||
| 855c322da6 | |||
| 240acca3de | |||
| 7ef1378304 | |||
| 9622ac7dff | |||
| 8a280b4a54 | |||
| 1ba9c71f54 | |||
| 5c6fbcaab0 | |||
| b339cab3c1 | |||
| a952df0953 | |||
| 6cebddebbe | |||
| b3d340f59c | |||
| 78e2efc0f2 | |||
| d21970efcc | |||
| 816039036d | |||
| faf1a34f70 | |||
| 6986153c90 | |||
| 8048e0b32f | |||
| af1cfd8139 | |||
| f5c3804f79 | |||
| 443816365a | |||
| 097959d5cc | |||
| bad6e12972 | |||
| d85fcda037 | |||
| dff91154a7 | |||
| c3f3f82a3e | |||
| 70af43c08c | |||
| 1786d907f7 | |||
| 12a268da30 | |||
| 0aefdf5251 | |||
| df72245b6b | |||
| fe872d0776 | |||
| 052d31939d | |||
| 1c44b675d9 | |||
| a1c9a63074 | |||
| 931df14e25 | |||
| 1b0d8bdd2e | |||
| 5c67a5e6bc | |||
| 267e5b13ea | |||
| a22287a3ba | |||
| da59412150 | |||
| c41719ff9a | |||
| f51b39db91 | |||
| 8d61d73d2f | |||
| 10acf78618 | |||
| caeae60dda | |||
| d7b8497b24 | |||
| a96e1d58f7 | |||
| 0d895b28ae | |||
| 84910b40da | |||
| 0e7c34f541 | |||
| 2b58775c17 | |||
| 326f33757b | |||
| c01221d4aa | |||
| 73d9ccac69 | |||
| 5bbd0d9ca9 | |||
| 641be2878d | |||
| eb7f5a774c | |||
| 6e9f8cf218 | |||
| 02a2b59555 | |||
| ec1d7a45d3 | |||
| 725a1aa114 | |||
| d41f19b9ce | |||
| a0fe9ca5b2 |
@@ -18,20 +18,17 @@ jobs:
|
||||
with:
|
||||
python-version: '3.11'
|
||||
|
||||
- name: Install Poetry
|
||||
- name: Install Hatch
|
||||
run: |
|
||||
curl -sSL https://install.python-poetry.org | python3 -
|
||||
echo "$HOME/.local/bin" >> $GITHUB_PATH
|
||||
pip install hatch
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
cd mem0
|
||||
poetry install
|
||||
hatch env create
|
||||
|
||||
- name: Build a binary wheel and a source tarball
|
||||
run: |
|
||||
cd mem0
|
||||
poetry build
|
||||
hatch build --clean
|
||||
|
||||
# TODO: Needs to setup mem0 repo on Test PyPI
|
||||
# - name: Publish distribution 📦 to Test PyPI
|
||||
|
||||
+27
-20
@@ -44,21 +44,28 @@ jobs:
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Install poetry
|
||||
uses: snok/install-poetry@v1
|
||||
with:
|
||||
version: 1.4.2
|
||||
virtualenvs-create: true
|
||||
virtualenvs-in-project: true
|
||||
- name: Install Hatch
|
||||
run: pip install hatch
|
||||
- name: Load cached venv
|
||||
id: cached-poetry-dependencies
|
||||
id: cached-hatch-dependencies
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: .venv
|
||||
key: venv-mem0-${{ runner.os }}-${{ hashFiles('**/poetry.lock') }}
|
||||
key: venv-mem0-${{ runner.os }}-${{ hashFiles('**/pyproject.toml') }}
|
||||
- name: Install GEOS Libraries
|
||||
run: sudo apt-get update && sudo apt-get install -y libgeos-dev
|
||||
- name: Install dependencies
|
||||
run: make install_all
|
||||
if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
pip install --upgrade pip wheel setuptools
|
||||
pip install --only-binary=shapely shapely
|
||||
make install_all
|
||||
pip install -e ".[test]"
|
||||
pip install pinecone pinecone-text
|
||||
if: steps.cached-hatch-dependencies.outputs.cache-hit != 'true'
|
||||
- name: Run Formatting
|
||||
run: |
|
||||
mkdir -p .ruff_cache && chmod -R 777 .ruff_cache
|
||||
hatch run format
|
||||
- name: Run tests and generate coverage report
|
||||
run: make test
|
||||
|
||||
@@ -75,21 +82,21 @@ jobs:
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Install poetry
|
||||
uses: snok/install-poetry@v1
|
||||
with:
|
||||
version: 1.4.2
|
||||
virtualenvs-create: true
|
||||
virtualenvs-in-project: true
|
||||
- name: Install Hatch
|
||||
run: pip install hatch
|
||||
- name: Load cached venv
|
||||
id: cached-poetry-dependencies
|
||||
id: cached-hatch-dependencies
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: .venv
|
||||
key: venv-embedchain-${{ runner.os }}-${{ hashFiles('**/poetry.lock') }}
|
||||
key: venv-embedchain-${{ runner.os }}-${{ hashFiles('**/pyproject.toml') }}
|
||||
- name: Install dependencies
|
||||
run: cd embedchain && make install_all
|
||||
if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true'
|
||||
if: steps.cached-hatch-dependencies.outputs.cache-hit != 'true'
|
||||
- name: Run Formatting
|
||||
run: |
|
||||
mkdir -p embedchain/.ruff_cache && chmod -R 777 embedchain/.ruff_cache
|
||||
cd embedchain && hatch run format
|
||||
- name: Lint with ruff
|
||||
run: cd embedchain && make lint
|
||||
- name: Run tests and generate coverage report
|
||||
@@ -99,4 +106,4 @@ jobs:
|
||||
with:
|
||||
file: coverage.xml
|
||||
env:
|
||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||
|
||||
+21
-15
@@ -16,18 +16,19 @@ To make a contribution, follow these steps:
|
||||
For more details about pull requests, please read [GitHub's guides](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request).
|
||||
|
||||
|
||||
### 📦 Package manager
|
||||
### 📦 Development Environment
|
||||
|
||||
We use `poetry` as our package manager. You can install poetry by following the instructions [here](https://python-poetry.org/docs/#installation).
|
||||
|
||||
Please DO NOT use pip or conda to install the dependencies. Instead, use poetry:
|
||||
We use `hatch` for managing development environments. To set up:
|
||||
|
||||
```bash
|
||||
make install_all
|
||||
# Activate environment for specific Python version:
|
||||
hatch shell dev_py_3_9 # Python 3.9
|
||||
hatch shell dev_py_3_10 # Python 3.10
|
||||
hatch shell dev_py_3_11 # Python 3.11
|
||||
|
||||
#activate
|
||||
|
||||
poetry shell
|
||||
# The environment will automatically install all dev dependencies
|
||||
# Run tests within the activated shell:
|
||||
make test
|
||||
```
|
||||
|
||||
### 📌 Pre-commit
|
||||
@@ -40,16 +41,21 @@ pre-commit install
|
||||
|
||||
### 🧪 Testing
|
||||
|
||||
We use `pytest` to test our code. You can run the tests by running the following command:
|
||||
We use `pytest` to test our code across multiple Python versions. You can run tests using:
|
||||
|
||||
```bash
|
||||
poetry run pytest tests
|
||||
|
||||
# or
|
||||
|
||||
# Run tests with default Python version
|
||||
make test
|
||||
|
||||
# Test specific Python versions:
|
||||
make test-py-3.9 # Python 3.9 environment
|
||||
make test-py-3.10 # Python 3.10 environment
|
||||
make test-py-3.11 # Python 3.11 environment
|
||||
|
||||
# When using hatch shells, run tests with:
|
||||
make test # After activating a shell with hatch shell test_XX
|
||||
```
|
||||
|
||||
Several packages have been removed from Poetry to make the package lighter. Therefore, it is recommended to run `make install_all` to install the remaining packages and ensure all tests pass. Make sure that all tests pass before submitting a pull request.
|
||||
Make sure that all tests pass across all supported Python versions before submitting a pull request.
|
||||
|
||||
We look forward to your pull requests and can't wait to see your contributions!
|
||||
We look forward to your pull requests and can't wait to see your contributions!
|
||||
|
||||
@@ -8,37 +8,45 @@ PROJECT_NAME := mem0ai
|
||||
all: format sort lint
|
||||
|
||||
install:
|
||||
poetry install
|
||||
hatch env create
|
||||
|
||||
install_all:
|
||||
poetry install
|
||||
poetry run pip install groq together boto3 litellm ollama chromadb weaviate weaviate-client sentence_transformers vertexai \
|
||||
google-generativeai elasticsearch opensearch-py vecs pinecone pinecone-text faiss-cpu langchain-community \
|
||||
upstash-vector azure-search-documents langchain-memgraph
|
||||
pip install ruff==0.6.9 groq together boto3 litellm ollama chromadb weaviate weaviate-client sentence_transformers vertexai \
|
||||
google-generativeai elasticsearch opensearch-py vecs "pinecone<7.0.0" pinecone-text faiss-cpu langchain-community \
|
||||
upstash-vector azure-search-documents langchain-memgraph langchain-neo4j rank-bm25 pymochow
|
||||
|
||||
# Format code with ruff
|
||||
format:
|
||||
poetry run ruff format mem0/
|
||||
hatch run format
|
||||
|
||||
# Sort imports with isort
|
||||
sort:
|
||||
poetry run isort mem0/
|
||||
hatch run isort mem0/
|
||||
|
||||
# Lint code with ruff
|
||||
lint:
|
||||
poetry run ruff check mem0/
|
||||
hatch run lint
|
||||
|
||||
docs:
|
||||
cd docs && mintlify dev
|
||||
|
||||
build:
|
||||
poetry build
|
||||
hatch build
|
||||
|
||||
publish:
|
||||
poetry publish
|
||||
hatch publish
|
||||
|
||||
clean:
|
||||
poetry run rm -rf dist
|
||||
rm -rf dist
|
||||
|
||||
test:
|
||||
poetry run pytest tests
|
||||
hatch run test
|
||||
|
||||
test-py-3.9:
|
||||
hatch run dev_py_3_9:test
|
||||
|
||||
test-py-3.10:
|
||||
hatch run dev_py_3_10:test
|
||||
|
||||
test-py-3.11:
|
||||
hatch run dev_py_3_11:test
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
<a href="https://mem0.dev/DiG">Join Discord</a>
|
||||
·
|
||||
<a href="https://mem0.dev/demo">Demo</a>
|
||||
·
|
||||
<a href="https://mem0.dev/openmemory">OpenMemory</a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
"import anthropic\n",
|
||||
"\n",
|
||||
"# Set up environment variables\n",
|
||||
"os.environ[\"OPENAI_API_KEY\"] = \"your_openai_api_key\" # needed for embedding model\n",
|
||||
"os.environ[\"OPENAI_API_KEY\"] = \"your_openai_api_key\" # needed for embedding model\n",
|
||||
"os.environ[\"ANTHROPIC_API_KEY\"] = \"your_anthropic_api_key\""
|
||||
]
|
||||
},
|
||||
@@ -33,7 +33,7 @@
|
||||
" \"model\": \"claude-3-5-sonnet-latest\",\n",
|
||||
" \"temperature\": 0.1,\n",
|
||||
" \"max_tokens\": 2000,\n",
|
||||
" }\n",
|
||||
" },\n",
|
||||
" }\n",
|
||||
" }\n",
|
||||
" self.client = anthropic.Client(api_key=os.environ[\"ANTHROPIC_API_KEY\"])\n",
|
||||
@@ -50,11 +50,7 @@
|
||||
" - Keep track of open issues and follow-ups\n",
|
||||
" \"\"\"\n",
|
||||
"\n",
|
||||
" def store_customer_interaction(self,\n",
|
||||
" user_id: str,\n",
|
||||
" message: str,\n",
|
||||
" response: str,\n",
|
||||
" metadata: Dict = None):\n",
|
||||
" def store_customer_interaction(self, user_id: str, message: str, response: str, metadata: Dict = None):\n",
|
||||
" \"\"\"Store customer interaction in memory.\"\"\"\n",
|
||||
" if metadata is None:\n",
|
||||
" metadata = {}\n",
|
||||
@@ -63,24 +59,17 @@
|
||||
" metadata[\"timestamp\"] = datetime.now().isoformat()\n",
|
||||
"\n",
|
||||
" # Format conversation for storage\n",
|
||||
" conversation = [\n",
|
||||
" {\"role\": \"user\", \"content\": message},\n",
|
||||
" {\"role\": \"assistant\", \"content\": response}\n",
|
||||
" ]\n",
|
||||
" conversation = [{\"role\": \"user\", \"content\": message}, {\"role\": \"assistant\", \"content\": response}]\n",
|
||||
"\n",
|
||||
" # Store in Mem0\n",
|
||||
" self.memory.add(\n",
|
||||
" conversation,\n",
|
||||
" user_id=user_id,\n",
|
||||
" metadata=metadata\n",
|
||||
" )\n",
|
||||
" self.memory.add(conversation, user_id=user_id, metadata=metadata)\n",
|
||||
"\n",
|
||||
" def get_relevant_history(self, user_id: str, query: str) -> List[Dict]:\n",
|
||||
" \"\"\"Retrieve relevant past interactions.\"\"\"\n",
|
||||
" return self.memory.search(\n",
|
||||
" query=query,\n",
|
||||
" user_id=user_id,\n",
|
||||
" limit=5 # Adjust based on needs\n",
|
||||
" limit=5, # Adjust based on needs\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
" def handle_customer_query(self, user_id: str, query: str) -> str:\n",
|
||||
@@ -112,15 +101,12 @@
|
||||
" model=\"claude-3-5-sonnet-latest\",\n",
|
||||
" messages=[{\"role\": \"user\", \"content\": prompt}],\n",
|
||||
" max_tokens=2000,\n",
|
||||
" temperature=0.1\n",
|
||||
" temperature=0.1,\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
" # Store interaction\n",
|
||||
" self.store_customer_interaction(\n",
|
||||
" user_id=user_id,\n",
|
||||
" message=query,\n",
|
||||
" response=response,\n",
|
||||
" metadata={\"type\": \"support_query\"}\n",
|
||||
" user_id=user_id, message=query, response=response, metadata={\"type\": \"support_query\"}\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
" return response.content[0].text"
|
||||
@@ -203,12 +189,12 @@
|
||||
" # Get user input\n",
|
||||
" query = input()\n",
|
||||
" print(\"Customer:\", query)\n",
|
||||
" \n",
|
||||
"\n",
|
||||
" # Check if user wants to exit\n",
|
||||
" if query.lower() == 'exit':\n",
|
||||
" if query.lower() == \"exit\":\n",
|
||||
" print(\"Thank you for using our support service. Goodbye!\")\n",
|
||||
" break\n",
|
||||
" \n",
|
||||
"\n",
|
||||
" # Handle the query and print the response\n",
|
||||
" response = chatbot.handle_customer_query(user_id, query)\n",
|
||||
" print(\"Support:\", response, \"\\n\\n\")"
|
||||
|
||||
@@ -7,10 +7,12 @@
|
||||
# forked from autogen.agentchat.contrib.capabilities.teachability.Teachability
|
||||
|
||||
from typing import Dict, Optional, Union
|
||||
|
||||
from autogen.agentchat.assistant_agent import ConversableAgent
|
||||
from autogen.agentchat.contrib.capabilities.agent_capability import AgentCapability
|
||||
from autogen.agentchat.contrib.text_analyzer_agent import TextAnalyzerAgent
|
||||
from termcolor import colored
|
||||
|
||||
from mem0 import Memory
|
||||
|
||||
|
||||
|
||||
+272
-274
File diff suppressed because it is too large
Load Diff
@@ -3,12 +3,15 @@ title: 'Get Memories (v2)'
|
||||
openapi: post /v2/memories/
|
||||
---
|
||||
|
||||
The v2 get memories API is powerful and flexible, allowing for more precise memory listing without the need for a search query. It supports complex logical operations (AND, OR) and comparison operators for advanced filtering capabilities. The comparison operators include:
|
||||
The v2 get memories API is powerful and flexible, allowing for more precise memory listing without the need for a search query. It supports complex logical operations (AND, OR, NOT) and comparison operators for advanced filtering capabilities. The comparison operators include:
|
||||
- `in`: Matches any of the values specified
|
||||
- `gte`: Greater than or equal to
|
||||
- `lte`: Less than or equal to
|
||||
- `gt`: Greater than
|
||||
- `lt`: Less than
|
||||
- `ne`: Not equal to
|
||||
- `icontains`: Case-insensitive containment check
|
||||
- `*`: Wildcard character that matches everything
|
||||
|
||||
<CodeGroup>
|
||||
```python Code
|
||||
@@ -41,3 +44,22 @@ memories = m.get_all(
|
||||
]
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
<CodeGroup>
|
||||
```python Wildcard Example
|
||||
# Using wildcard to get all memories for a specific user across all run_ids
|
||||
memories = m.get_all(
|
||||
filters={
|
||||
"AND": [
|
||||
{
|
||||
"user_id": "alex"
|
||||
},
|
||||
{
|
||||
"run_id": "*"
|
||||
}
|
||||
]
|
||||
},
|
||||
version="v2"
|
||||
)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
@@ -3,7 +3,7 @@ title: 'Search Memories (v2)'
|
||||
openapi: post /v2/memories/search/
|
||||
---
|
||||
|
||||
The v2 search API is powerful and flexible, allowing for more precise memory retrieval. It supports complex logical operations (AND, OR) and comparison operators for advanced filtering capabilities. The comparison operators include:
|
||||
The v2 search API is powerful and flexible, allowing for more precise memory retrieval. It supports complex logical operations (AND, OR, NOT) and comparison operators for advanced filtering capabilities. The comparison operators include:
|
||||
- `in`: Matches any of the values specified
|
||||
- `gte`: Greater than or equal to
|
||||
- `lte`: Less than or equal to
|
||||
@@ -11,6 +11,7 @@ The v2 search API is powerful and flexible, allowing for more precise memory ret
|
||||
- `lt`: Less than
|
||||
- `ne`: Not equal to
|
||||
- `icontains`: Case-insensitive containment check
|
||||
- `*`: Wildcard character that matches everything
|
||||
|
||||
<CodeGroup>
|
||||
```python Code
|
||||
@@ -18,7 +19,7 @@ The v2 search API is powerful and flexible, allowing for more precise memory ret
|
||||
query="What are Alice's hobbies?",
|
||||
version="v2",
|
||||
filters={
|
||||
"AND": [
|
||||
"OR": [
|
||||
{
|
||||
"user_id": "alice"
|
||||
},
|
||||
@@ -49,3 +50,23 @@ The v2 search API is powerful and flexible, allowing for more precise memory ret
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
<CodeGroup>
|
||||
```python Wildcard Example
|
||||
# Using wildcard to match all run_ids for a specific user
|
||||
all_memories = m.search(
|
||||
query="What are Alice's hobbies?",
|
||||
version="v2",
|
||||
filters={
|
||||
"AND": [
|
||||
{
|
||||
"user_id": "alice"
|
||||
},
|
||||
{
|
||||
"run_id": "*"
|
||||
}
|
||||
]
|
||||
},
|
||||
)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
+365
-133
@@ -8,6 +8,206 @@ mode: "wide"
|
||||
<Tabs>
|
||||
<Tab title="Python">
|
||||
|
||||
<Update label="2025-06-19" description="v0.1.109">
|
||||
|
||||
**New Features:**
|
||||
- **AgentOps:** Added AgentOps integration
|
||||
- **LM Studio:** Added response_format parameter for LM Studio configuration
|
||||
- **Examples:** Added Memory agent powered by voice (Cartesia + Agno)
|
||||
|
||||
**Improvements:**
|
||||
- **AI SDK:** Added output_format parameter
|
||||
- **Client:** Enhanced update method to support metadata
|
||||
- **Google:** Added Google Genai library support
|
||||
|
||||
**Bug Fixes:**
|
||||
- **Build:** Fixed Build CI failure
|
||||
- **Pinecone:** Fixed pinecone for async memory
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2025-06-14" description="v0.1.108">
|
||||
|
||||
**New Features:**
|
||||
- **MongoDB:** Added MongoDB Vector Store support
|
||||
- **Client:** Added client support for summary functionality
|
||||
|
||||
**Improvements:**
|
||||
- **Pinecone:** Fixed pinecone version issues
|
||||
- **OpenSearch:** Added logger support
|
||||
- **Testing:** Added python version test environments
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2025-06-11" description="v0.1.107">
|
||||
|
||||
**Improvements:**
|
||||
- **Documentation:**
|
||||
- Updated Livekit documentation migration
|
||||
- Updated OpenMemory hosted version documentation
|
||||
- **Core:** Updated categorization flow
|
||||
- **Storage:** Fixed migration issues
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2025-06-09" description="v0.1.106">
|
||||
|
||||
**New Features:**
|
||||
- **Cloudflare:** Added Cloudflare vector store support
|
||||
- **Search:** Added threshold parameter to search functionality
|
||||
- **API:** Added wildcard character support for v2 Memory APIs
|
||||
|
||||
**Improvements:**
|
||||
- **Documentation:** Updated README docs for OpenMemory environment setup
|
||||
- **Core:** Added support for unique user IDs
|
||||
|
||||
**Bug Fixes:**
|
||||
- **Core:** Fixed error handling exceptions
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2025-06-03" description="v0.1.104">
|
||||
|
||||
**Bug Fixes:**
|
||||
- **Vector Stores:** Fixed GET_ALL functionality for FAISS and OpenSearch
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2025-06-02" description="v0.1.103">
|
||||
|
||||
**New Features:**
|
||||
- **LLM:** Added support for OpenAI compatible LLM providers with baseUrl configuration
|
||||
|
||||
**Improvements:**
|
||||
- **Documentation:**
|
||||
- Fixed broken links
|
||||
- Improved Graph Memory features documentation clarity
|
||||
- Updated enable_graph documentation
|
||||
- **TypeScript SDK:** Updated Google SDK peer dependency version
|
||||
- **Client:** Added async mode parameter
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2025-05-26" description="v0.1.102">
|
||||
|
||||
**New Features:**
|
||||
- **Examples:** Added Neo4j example
|
||||
- **AI SDK:** Added Google provider support
|
||||
- **OpenMemory:** Added LLM and Embedding Providers support
|
||||
|
||||
**Improvements:**
|
||||
- **Documentation:**
|
||||
- Updated memory export documentation
|
||||
- Enhanced role-based memory attribution rules documentation
|
||||
- Updated API reference and messages documentation
|
||||
- Added Mastra and Raycast documentation
|
||||
- Added NOT filter documentation for Search and GetAll V2
|
||||
- Announced Claude 4 support
|
||||
- **Core:**
|
||||
- Removed support for passing string as input in client.add()
|
||||
- Added support for sarvam-m model
|
||||
- **TypeScript SDK:** Fixed types from message interface
|
||||
|
||||
**Bug Fixes:**
|
||||
- **Memory:** Prevented saving prompt artifacts as memory when no new facts are present
|
||||
- **OpenMemory:** Fixed typos in MCP tool description
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2025-05-15" description="v0.1.101">
|
||||
|
||||
**New Features:**
|
||||
- **Neo4j:** Added base label configuration support
|
||||
|
||||
**Improvements:**
|
||||
- **Documentation:**
|
||||
- Updated Healthcare example index
|
||||
- Enhanced collaborative task agent documentation clarity
|
||||
- Added criteria-based filtering documentation
|
||||
- **OpenMemory:** Added cURL command for easy installation
|
||||
- **Build:** Migrated to Hatch build system
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2025-05-10" description="v0.1.100">
|
||||
|
||||
**New Features:**
|
||||
- **Memory:** Added Group Chat Memory Feature support
|
||||
- **Examples:** Added Healthcare assistant using Mem0 and Google ADK
|
||||
|
||||
**Bug Fixes:**
|
||||
- **SSE:** Fixed SSE connection issues
|
||||
- **MCP:** Fixed memories not appearing in MCP clients added from Dashboard
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2025-05-07" description="v0.1.99">
|
||||
|
||||
**New Features:**
|
||||
- **OpenMemory:** Added OpenMemory support
|
||||
- **Neo4j:** Added weights to Neo4j model
|
||||
- **AWS:** Added support for Opsearch Serverless
|
||||
- **Examples:** Added ElizaOS Example
|
||||
|
||||
**Improvements:**
|
||||
- **Documentation:** Updated Azure AI documentation
|
||||
- **AI SDK:** Added missing parameters and updated demo application
|
||||
- **OSS:** Fixed AOSS and AWS BedRock LLM
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2025-04-30" description="v0.1.98">
|
||||
|
||||
**New Features:**
|
||||
- **Neo4j:** Added support for Neo4j database
|
||||
- **AWS:** Added support for AWS Bedrock Embeddings
|
||||
|
||||
**Improvements:**
|
||||
- **Client:** Updated delete_users() to use V2 API endpoints
|
||||
- **Documentation:** Updated timestamp and dual-identity memory management docs
|
||||
- **Neo4j:** Improved Neo4j queries and removed warnings
|
||||
- **AI SDK:** Added support for graceful failure when services are down
|
||||
|
||||
**Bug Fixes:**
|
||||
- Fixed AI SDK filters
|
||||
- Fixed new memories wrong type
|
||||
- Fixed duplicated metadata issue while adding/updating memories
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2025-04-23" description="v0.1.97">
|
||||
|
||||
**New Features:**
|
||||
- **HuggingFace:** Added support for HF Inference
|
||||
|
||||
**Bug Fixes:**
|
||||
- Fixed proxy for Mem0
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2025-04-16" description="v0.1.96">
|
||||
|
||||
**New Features:**
|
||||
- **Vercel AI SDK:** Added Graph Memory support
|
||||
|
||||
**Improvements:**
|
||||
- **Documentation:** Fixed timestamp and README links
|
||||
- **Client:** Updated TS client to use proper types for deleteUsers
|
||||
- **Dependencies:** Removed unnecessary dependencies from base package
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2025-04-09" description="v0.1.95">
|
||||
|
||||
**Improvements:**
|
||||
- **Client:** Fixed Ping Method for using default org_id and project_id
|
||||
- **Documentation:** Updated documentation
|
||||
|
||||
**Bug Fixes:**
|
||||
- Fixed mem0-migrations issue
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2025-04-26" description="v0.1.94">
|
||||
|
||||
**New Features:**
|
||||
@@ -209,6 +409,66 @@ mode: "wide"
|
||||
|
||||
<Tab title="TypeScript">
|
||||
|
||||
<Update label="2025-06-24" description="v2.1.33">
|
||||
**Improvement :**
|
||||
- **Client:** Added `immutable` param to `add` method.
|
||||
</Update>
|
||||
|
||||
<Update label="2025-06-20" description="v2.1.32">
|
||||
**Improvement :**
|
||||
- **Client:** Made `api_version` V2 as default.
|
||||
</Update>
|
||||
|
||||
<Update label="2025-06-17" description="v2.1.31">
|
||||
**Improvement :**
|
||||
- **Client:** Added param `filter_memories`.
|
||||
</Update>
|
||||
|
||||
<Update label="2025-06-06" description="v2.1.30">
|
||||
**New Features:**
|
||||
- **OSS:** Added Cloudflare support
|
||||
|
||||
**Improvements:**
|
||||
- **OSS:** Fixed baseURL param in LLM Config.
|
||||
</Update>
|
||||
|
||||
<Update label="2025-05-30" description="v2.1.29">
|
||||
**Improvements:**
|
||||
- **Client:** Added Async Mode Param for `add` method.
|
||||
</Update>
|
||||
|
||||
<Update label="2025-05-30" description="v2.1.28">
|
||||
**Improvements:**
|
||||
- **SDK:** Update Google SDK Peer Dependency Version.
|
||||
</Update>
|
||||
|
||||
<Update label="2025-05-27" description="v2.1.27">
|
||||
**Improvements:**
|
||||
- **OSS:** Added baseURL param in LLM Config.
|
||||
</Update>
|
||||
|
||||
<Update label="2025-05-23" description="v2.1.26">
|
||||
**Improvements:**
|
||||
- **Client:** Removed type `string` from `messages` interface
|
||||
</Update>
|
||||
|
||||
<Update label="2025-05-08" description="v2.1.25">
|
||||
**Improvements:**
|
||||
- **Client:** Improved error handling in client.
|
||||
</Update>
|
||||
|
||||
<Update label="2025-05-06" description="v2.1.24">
|
||||
**New Features:**
|
||||
- **Client:** Added new param `output_format` to match Python SDK.
|
||||
- **Client:** Added new enum `OutputFormat` for `v1.0` and `v1.1`
|
||||
</Update>
|
||||
|
||||
<Update label="2025-05-05" description="v2.1.23">
|
||||
**New Features:**
|
||||
- **Client:** Updated `deleteUsers` to use `v2` API.
|
||||
- **Client:** Deprecated `deleteUser` and added deprecation warning.
|
||||
</Update>
|
||||
|
||||
<Update label="2025-05-02" description="v2.1.22">
|
||||
**New Features:**
|
||||
- **Client:** Updated `deleteUser` to use `entity_id` and `entity_type`
|
||||
@@ -313,163 +573,135 @@ mode: "wide"
|
||||
|
||||
<Tab title="Platform">
|
||||
|
||||
<Update label="2025-04-26" description="">
|
||||
|
||||
**Improvements:**
|
||||
- **Performance:** Parallelized embedding calls
|
||||
- **Monitoring:** Added timing for LLM calls
|
||||
- **Search:** Added category checking in Search V2
|
||||
- **Bug Fixes:** Fixed issues with ADD filters
|
||||
- **Graph:** Implemented new graph updates
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2025-04-25" description="">
|
||||
|
||||
**Improvements:**
|
||||
- **Memory:** Fixed memory export functionality
|
||||
- **Analytics:** Added logging for project
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2025-04-24" description="">
|
||||
|
||||
**Improvements:**
|
||||
- **Output:** Added memory_type display for ADD output
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2025-04-23" description="">
|
||||
<Update label="2025-06-19" description="">
|
||||
|
||||
**New Features:**
|
||||
- **UI:** Added new Pricing Component
|
||||
- **Memory:** Implemented Long/Short term memory categorization
|
||||
- **Output:** Modified serializer to hide memory_type
|
||||
- **Rate Limiting:** Implemented comprehensive rate limiting system
|
||||
|
||||
**Documentation:**
|
||||
- Updated README for deployment
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2025-04-22" description="">
|
||||
|
||||
**New Features:**
|
||||
- **Memory:** Added timestamp to ADD call
|
||||
**Improvements:**
|
||||
- **Performance:** Added performance indexes for memory stats query
|
||||
|
||||
**Bug Fixes:**
|
||||
- Fixed issues with coreV2
|
||||
- **Search:** Fixed search events not respecting top-k parameter
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2025-04-21" description="">
|
||||
<Update label="2025-06-18" description="">
|
||||
|
||||
**New Features:**
|
||||
- **Memory:** Implemented backdating with migrations and backfilling script
|
||||
- **Memory Management:** Implemented OpenAI Batch API for Memory Cleaning with fallback
|
||||
- **Playground:** Added Claude 4 support on Playground
|
||||
|
||||
**Improvements:**
|
||||
- **Memory:** Added ability to update memory metadata
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2025-04-17" description="">
|
||||
<Update label="2025-06-17" description="">
|
||||
|
||||
**New Features:**
|
||||
- **Billing:** Integrated Stripe Billing Dashboard
|
||||
- **Admin:** Added webhook creation functionality
|
||||
- **UI:** New Memories Page UI design
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2025-06-16" description="">
|
||||
|
||||
**Improvements:**
|
||||
- **Infrastructure:** Migrated to Application Load Balancer (ALB)
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2025-06-13" description="">
|
||||
|
||||
**Improvements:**
|
||||
- **Memory Management:** Enhanced Memory Management with Cosine Similarity Fallback
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2025-06-11" description="">
|
||||
|
||||
**New Features:**
|
||||
- **OMM:** Added OMM Script and UI functionality
|
||||
|
||||
**Improvements:**
|
||||
- **API:** Added filters validation to semantic_search_v2 endpoint
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2025-06-09" description="">
|
||||
|
||||
**New Features:**
|
||||
- **Intercom:** Set Intercom events for ADD and SEARCH operations
|
||||
- **OpenMemory:** Added Posthog integration and feedback functionality
|
||||
- **MCP:** New JavaScript MCP Server with feedback support
|
||||
|
||||
**Improvements:**
|
||||
- **Structured Data:** Enhanced structured data handling in memory management
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2025-06-06" description="">
|
||||
|
||||
**New Features:**
|
||||
- **OAuth:** Added Mem0 OAuth integration
|
||||
- **OMM:** Added OMM-Mem0 sync for deleted memories
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2025-06-05" description="">
|
||||
|
||||
**New Features:**
|
||||
- **Filters:** Implemented Wildcard Filters and refactored filter logic in V2 Views
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2025-06-02" description="">
|
||||
|
||||
**New Features:**
|
||||
- **OpenMemory Cloud:** Added OpenMemory Cloud support
|
||||
- **Structured Data:** Added 'structured_attributes' field to Memory model
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2025-05-30" description="">
|
||||
|
||||
**New Features:**
|
||||
- **Projects:** Added version and enable_graph to project views
|
||||
- **OpenMemory:** Added Postgres support for OpenMemory
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2025-05-19" description="">
|
||||
|
||||
**Bug Fixes:**
|
||||
- Fixed Users Page issues
|
||||
- Fixed Custom Categories
|
||||
- Fixed Table components
|
||||
- Updated Stripe configuration
|
||||
- **Core:** Fixed unicode error in user_id, agent_id, run_id and app_id
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2025-04-16" description="">
|
||||
|
||||
**Improvements:**
|
||||
- **Performance:** Made Admin panel and Memory Page faster
|
||||
- **Security:** Implemented active session cancellation
|
||||
- **Analytics:** Added Stripe customer ID capture
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2025-04-12" description="">
|
||||
|
||||
**New Features:**
|
||||
- **Memory Management:**
|
||||
- Added ability to delete memories from Project level with filters
|
||||
- Added delete memories capability on Memories Page
|
||||
- **Memory Visualization:** Released V1 Graph Memory Visualization
|
||||
- **Graph Playground:** Enabled for @mem0.ai users
|
||||
- **Notifications:** Added email alerts to organization owners when new members join
|
||||
- **Memory Export:** Added date support for filtering memory exports
|
||||
|
||||
**Improvements:**
|
||||
- **Performance:**
|
||||
- Optimized graph for better performance
|
||||
- Optimized database calls in ADD method
|
||||
- **Analytics:** Added flagging of paid users in Posthog
|
||||
- **CI/CD:** Improved CI pipeline and fixed lint issues
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2025-04-10" description="">
|
||||
|
||||
**New Features:**
|
||||
- **Notifications:** Implemented email notifications for organization owners when new members join
|
||||
|
||||
**Improvements:**
|
||||
- **CI/CD:** Fixed Dockerfile for CI tests
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2025-04-09" description="">
|
||||
|
||||
**Improvements:**
|
||||
- **Integrations:** Updated chat model for Together Qwen
|
||||
- **Platform:** Removed older platforms
|
||||
- **Bug Fixes:** Fixed FILTER_MAPPING
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2025-04-03" description="">
|
||||
|
||||
**New Features:**
|
||||
- **Memory:** Added implicit memory capabilities
|
||||
- **API:** Improved implicit lambda and get_all v2 functionality
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2025-04-02" description="">
|
||||
|
||||
**New Features:**
|
||||
- **Integrations:** Added Clay integration
|
||||
|
||||
**Improvements:**
|
||||
- **Integrations:** Removed deepseek coder from Together
|
||||
- **API:** Added custom instructions for add v2
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2025-03-31" description="">
|
||||
|
||||
**Security:**
|
||||
- **Validation:** Added key validation in messages
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2025-03-28" description="">
|
||||
- **Updated Playground Prompt**
|
||||
- **Send Email on User Addition to Org/Proj**
|
||||
- **Fix Search Entity**
|
||||
</Update>
|
||||
|
||||
<Update label="2025-03-19" description="">
|
||||
- **General Stability & Performance Improvements**
|
||||
</Update>
|
||||
|
||||
</Tab>
|
||||
|
||||
<Tab title="Vercel AI SDK">
|
||||
|
||||
<Update label="2025-06-15" description="v1.0.6">
|
||||
**New Features:**
|
||||
- **Vercel AI SDK:** Added param `filter_memories`.
|
||||
</Update>
|
||||
|
||||
<Update label="2025-05-23" description="v1.0.5">
|
||||
**New Features:**
|
||||
- **Vercel AI SDK:** Added support for Google provider.
|
||||
</Update>
|
||||
|
||||
<Update label="2025-05-10" description="v1.0.4">
|
||||
**New Features:**
|
||||
- **Vercel AI SDK:** Added support for new param `output_format`.
|
||||
</Update>
|
||||
|
||||
<Update label="2025-05-08" description="v1.0.3">
|
||||
**Improvements:**
|
||||
- **Vercel AI SDK:** Added support for graceful failure in cases services are down.
|
||||
</Update>
|
||||
|
||||
<Update label="2025-05-01" description="v1.0.1">
|
||||
**New Features:**
|
||||
- **Vercel AI SDK:** Added support for graph memories
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
---
|
||||
title: AWS Bedrock
|
||||
---
|
||||
|
||||
To use AWS Bedrock embedding models, you need to have the appropriate AWS credentials and permissions. The embeddings implementation relies on the `boto3` library.
|
||||
|
||||
### Setup
|
||||
- Ensure you have model access from the [AWS Bedrock Console](https://us-east-1.console.aws.amazon.com/bedrock/home?region=us-east-1#/modelaccess)
|
||||
- Authenticate the boto3 client using a method described in the [AWS documentation](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/credentials.html)
|
||||
- Set up environment variables for authentication:
|
||||
```bash
|
||||
export AWS_REGION=us-east-1
|
||||
export AWS_ACCESS_KEY_ID=your-access-key
|
||||
export AWS_SECRET_ACCESS_KEY=your-secret-key
|
||||
```
|
||||
|
||||
### Usage
|
||||
|
||||
<CodeGroup>
|
||||
```python Python
|
||||
import os
|
||||
from mem0 import Memory
|
||||
|
||||
# For LLM if needed
|
||||
os.environ["OPENAI_API_KEY"] = "your-openai-api-key"
|
||||
|
||||
# AWS credentials
|
||||
os.environ["AWS_REGION"] = "us-west-2"
|
||||
os.environ["AWS_ACCESS_KEY_ID"] = "your-access-key"
|
||||
os.environ["AWS_SECRET_ACCESS_KEY"] = "your-secret-key"
|
||||
|
||||
config = {
|
||||
"embedder": {
|
||||
"provider": "aws_bedrock",
|
||||
"config": {
|
||||
"model": "amazon.titan-embed-text-v2:0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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")
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### Config
|
||||
|
||||
Here are the parameters available for configuring AWS Bedrock embedder:
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Python">
|
||||
| Parameter | Description | Default Value |
|
||||
| --- | --- | --- |
|
||||
| `model` | The name of the embedding model to use | `amazon.titan-embed-text-v1` |
|
||||
</Tab>
|
||||
</Tabs>
|
||||
@@ -39,5 +39,5 @@ Here are the parameters available for configuring Gemini embedder:
|
||||
| Parameter | Description | Default Value |
|
||||
| --- | --- | --- |
|
||||
| `model` | The name of the embedding model to use | `models/text-embedding-004` |
|
||||
| `embedding_dims` | Dimensions of the embedding model | `768` |
|
||||
| `embedding_dims` | Dimensions of the embedding model (output_dimensionality will be considered as embedding_dims, so please set embedding_dims accordingly) | `768` |
|
||||
| `api_key` | The Gemini API key | `None` |
|
||||
|
||||
@@ -26,6 +26,7 @@ See the list of supported embedders below.
|
||||
<Card title="Together" href="/components/embedders/models/together"></Card>
|
||||
<Card title="LM Studio" href="/components/embedders/models/lmstudio"></Card>
|
||||
<Card title="Langchain" href="/components/embedders/models/langchain"></Card>
|
||||
<Card title="AWS Bedrock" href="/components/embedders/models/aws_bedrock"></Card>
|
||||
</CardGroup>
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -58,6 +58,7 @@ config = {
|
||||
|
||||
m = Memory.from_config(config)
|
||||
m.add("Your text here", user_id="user", metadata={"category": "example"})
|
||||
|
||||
```
|
||||
|
||||
```typescript TypeScript
|
||||
@@ -76,6 +77,7 @@ const config = {
|
||||
const memory = new Memory(config);
|
||||
await memory.add("Your text here", { userId: "user123", metadata: { category: "example" } });
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
## Why is Config Needed?
|
||||
@@ -110,6 +112,12 @@ Here's a comprehensive list of all parameters that can be used across different
|
||||
| `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 |
|
||||
| `sarvam_base_url` | Base URL for Sarvam API | Sarvam |
|
||||
| `reasoning_effort` | Reasoning level (low, medium, high) | Sarvam |
|
||||
| `frequency_penalty` | Penalize frequent tokens (-2.0 to 2.0) | Sarvam |
|
||||
| `presence_penalty` | Penalize existing tokens (-2.0 to 2.0) | Sarvam |
|
||||
| `seed` | Seed for deterministic sampling | Sarvam |
|
||||
| `stop` | Stop sequences (max 4) | Sarvam |
|
||||
| `lmstudio_base_url` | Base URL for LM Studio API | LM Studio |
|
||||
</Tab>
|
||||
<Tab title="TypeScript">
|
||||
|
||||
@@ -20,7 +20,7 @@ config = {
|
||||
"llm": {
|
||||
"provider": "anthropic",
|
||||
"config": {
|
||||
"model": "claude-3-7-sonnet-latest",
|
||||
"model": "claude-sonnet-4-20250514",
|
||||
"temperature": 0.1,
|
||||
"max_tokens": 2000,
|
||||
}
|
||||
@@ -45,7 +45,7 @@ const config = {
|
||||
provider: 'anthropic',
|
||||
config: {
|
||||
apiKey: process.env.ANTHROPIC_API_KEY || '',
|
||||
model: 'claude-3-7-sonnet-latest',
|
||||
model: 'claude-sonnet-4-20250514',
|
||||
temperature: 0.1,
|
||||
maxTokens: 2000,
|
||||
},
|
||||
|
||||
@@ -15,16 +15,15 @@ title: AWS Bedrock
|
||||
import os
|
||||
from mem0 import Memory
|
||||
|
||||
os.environ["OPENAI_API_KEY"] = "your-api-key" # used for embedding model
|
||||
os.environ['AWS_REGION'] = 'us-east-1'
|
||||
os.environ["AWS_ACCESS_KEY"] = "xx"
|
||||
os.environ['AWS_REGION'] = 'us-west-2'
|
||||
os.environ["AWS_ACCESS_KEY_ID"] = "xx"
|
||||
os.environ["AWS_SECRET_ACCESS_KEY"] = "xx"
|
||||
|
||||
config = {
|
||||
"llm": {
|
||||
"provider": "aws_bedrock",
|
||||
"config": {
|
||||
"model": "arn:aws:bedrock:us-east-1:123456789012:model/your-model-name",
|
||||
"model": "anthropic.claude-3-5-haiku-20241022-v1:0",
|
||||
"temperature": 0.2,
|
||||
"max_tokens": 2000,
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@ To use Azure OpenAI models, you have to set the `LLM_AZURE_OPENAI_API_KEY`, `LLM
|
||||
import os
|
||||
from mem0 import Memory
|
||||
|
||||
os.environ["OPENAI_API_KEY"] = "your-api-key" # used for embedding model
|
||||
|
||||
os.environ["LLM_AZURE_OPENAI_API_KEY"] = "your-api-key"
|
||||
os.environ["LLM_AZURE_DEPLOYMENT"] = "your-deployment-name"
|
||||
os.environ["LLM_AZURE_ENDPOINT"] = "your-api-base-url"
|
||||
|
||||
@@ -4,7 +4,11 @@ title: Gemini
|
||||
|
||||
<Snippet file="paper-release.mdx" />
|
||||
|
||||
To use Gemini model, you have to set the `GEMINI_API_KEY` environment variable. You can obtain the Gemini API key from the [Google AI Studio](https://aistudio.google.com/app/apikey)
|
||||
To use the Gemini model, set the `GEMINI_API_KEY` environment variable. You can obtain the Gemini API key from [Google AI Studio](https://aistudio.google.com/app/apikey).
|
||||
|
||||
> **Note:** As of the latest release, Mem0 uses the new `google.genai` SDK instead of the deprecated `google.generativeai`. All message formatting and model interaction now use the updated `types` module from `google.genai`.
|
||||
|
||||
> **Note:** Some Gemini models are being deprecated and will retire soon. It is recommended to migrate to the latest stable models like `"gemini-2.0-flash-001"` or `"gemini-2.0-flash-lite-001"` to ensure ongoing support and improvements.
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -12,28 +16,32 @@ To use Gemini model, you have to set the `GEMINI_API_KEY` environment variable.
|
||||
import os
|
||||
from mem0 import Memory
|
||||
|
||||
os.environ["OPENAI_API_KEY"] = "your-api-key" # used for embedding model
|
||||
os.environ["GEMINI_API_KEY"] = "your-api-key"
|
||||
os.environ["OPENAI_API_KEY"] = "your-openai-api-key" # Used for embedding model
|
||||
os.environ["GEMINI_API_KEY"] = "your-gemini-api-key"
|
||||
|
||||
config = {
|
||||
"llm": {
|
||||
"provider": "gemini",
|
||||
"config": {
|
||||
"model": "gemini-1.5-flash-latest",
|
||||
"model": "gemini-2.0-flash-001",
|
||||
"temperature": 0.2,
|
||||
"max_tokens": 2000,
|
||||
"top_p": 1.0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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."}
|
||||
{"role": "assistant", "content": "How about thriller movies? They can be quite engaging."},
|
||||
{"role": "user", "content": "I’m not a big fan of thrillers, but I love sci-fi movies."},
|
||||
{"role": "assistant", "content": "Got it! I'll avoid thrillers and suggest sci-fi movies instead."}
|
||||
]
|
||||
|
||||
m.add(messages, user_id="alice", metadata={"category": "movies"})
|
||||
|
||||
```
|
||||
|
||||
## Config
|
||||
|
||||
@@ -23,6 +23,7 @@ config = {
|
||||
"temperature": 0.2,
|
||||
"max_tokens": 2000,
|
||||
"lmstudio_base_url": "http://localhost:1234/v1", # default LM Studio API URL
|
||||
"lmstudio_response_format": {"type": "json_schema", "json_schema": {"type": "object", "schema": {}}},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
---
|
||||
title: Sarvam AI
|
||||
---
|
||||
|
||||
<Snippet file="paper-release.mdx" />
|
||||
|
||||
**Sarvam AI** is an Indian AI company developing language models with a focus on Indian languages and cultural context. Their latest model **Sarvam-M** is designed to understand and generate content in multiple Indian languages while maintaining high performance in English.
|
||||
|
||||
To use Sarvam AI's models, please set the `SARVAM_API_KEY` which you can get from their [platform](https://dashboard.sarvam.ai/).
|
||||
|
||||
## Usage
|
||||
|
||||
```python
|
||||
import os
|
||||
from mem0 import Memory
|
||||
|
||||
os.environ["OPENAI_API_KEY"] = "your-api-key" # used for embedding model
|
||||
os.environ["SARVAM_API_KEY"] = "your-api-key"
|
||||
|
||||
config = {
|
||||
"llm": {
|
||||
"provider": "sarvam",
|
||||
"config": {
|
||||
"model": "sarvam-m",
|
||||
"temperature": 0.7,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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="alex")
|
||||
```
|
||||
|
||||
## Advanced Usage with Sarvam-Specific Features
|
||||
|
||||
```python
|
||||
import os
|
||||
from mem0 import Memory
|
||||
|
||||
config = {
|
||||
"llm": {
|
||||
"provider": "sarvam",
|
||||
"config": {
|
||||
"model": {
|
||||
"name": "sarvam-m",
|
||||
"reasoning_effort": "high", # Enable advanced reasoning
|
||||
"frequency_penalty": 0.1, # Reduce repetition
|
||||
"seed": 42 # For deterministic outputs
|
||||
},
|
||||
"temperature": 0.3,
|
||||
"max_tokens": 2000,
|
||||
"api_key": "your-sarvam-api-key"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m = Memory.from_config(config)
|
||||
|
||||
# Example with Hindi conversation
|
||||
messages = [
|
||||
{"role": "user", "content": "मैं SBI में joint account खोलना चाहता हूँ।"},
|
||||
{"role": "assistant", "content": "SBI में joint account खोलने के लिए आपको कुछ documents की जरूरत होगी। क्या आप जानना चाहते हैं कि कौन से documents चाहिए?"}
|
||||
]
|
||||
m.add(messages, user_id="rajesh", metadata={"language": "hindi", "topic": "banking"})
|
||||
```
|
||||
|
||||
## Config
|
||||
|
||||
All available parameters for the `sarvam` config are present in [Master List of All Params in Config](../config).
|
||||
@@ -0,0 +1,109 @@
|
||||
---
|
||||
title: vLLM
|
||||
---
|
||||
|
||||
<Snippet file="paper-release.mdx" />
|
||||
|
||||
[vLLM](https://docs.vllm.ai/) is a high-performance inference engine for large language models that provides significant performance improvements for local inference. It's designed to maximize throughput and memory efficiency for serving LLMs.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
1. **Install vLLM**:
|
||||
|
||||
```bash
|
||||
pip install vllm
|
||||
```
|
||||
|
||||
2. **Start vLLM server**:
|
||||
|
||||
```bash
|
||||
# For testing with a small model
|
||||
vllm serve microsoft/DialoGPT-medium --port 8000
|
||||
|
||||
# For production with a larger model (requires GPU)
|
||||
vllm serve Qwen/Qwen2.5-32B-Instruct --port 8000
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```python
|
||||
import os
|
||||
from mem0 import Memory
|
||||
|
||||
os.environ["OPENAI_API_KEY"] = "your-api-key" # used for embedding model
|
||||
|
||||
config = {
|
||||
"llm": {
|
||||
"provider": "vllm",
|
||||
"config": {
|
||||
"model": "Qwen/Qwen2.5-32B-Instruct",
|
||||
"vllm_base_url": "http://localhost:8000/v1",
|
||||
"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 thriller movies? They can be quite engaging."},
|
||||
{"role": "user", "content": "I'm not a big fan of thrillers, but I love sci-fi movies."},
|
||||
{"role": "assistant", "content": "Got it! I'll avoid thrillers and suggest sci-fi movies instead."}
|
||||
]
|
||||
m.add(messages, user_id="alice", metadata={"category": "movies"})
|
||||
```
|
||||
|
||||
## Configuration Parameters
|
||||
|
||||
| Parameter | Description | Default | Environment Variable |
|
||||
| --------------- | --------------------------------- | ----------------------------- | -------------------- |
|
||||
| `model` | Model name running on vLLM server | `"Qwen/Qwen2.5-32B-Instruct"` | - |
|
||||
| `vllm_base_url` | vLLM server URL | `"http://localhost:8000/v1"` | `VLLM_BASE_URL` |
|
||||
| `api_key` | API key (dummy for local) | `"vllm-api-key"` | `VLLM_API_KEY` |
|
||||
| `temperature` | Sampling temperature | `0.1` | - |
|
||||
| `max_tokens` | Maximum tokens to generate | `2000` | - |
|
||||
|
||||
## Environment Variables
|
||||
|
||||
You can set these environment variables instead of specifying them in config:
|
||||
|
||||
```bash
|
||||
export VLLM_BASE_URL="http://localhost:8000/v1"
|
||||
export VLLM_API_KEY="your-vllm-api-key"
|
||||
export OPENAI_API_KEY="your-openai-api-key" # for embeddings
|
||||
```
|
||||
|
||||
## Benefits
|
||||
|
||||
- **High Performance**: 2-24x faster inference than standard implementations
|
||||
- **Memory Efficient**: Optimized memory usage with PagedAttention
|
||||
- **Local Deployment**: Keep your data private and reduce API costs
|
||||
- **Easy Integration**: Drop-in replacement for other LLM providers
|
||||
- **Flexible**: Works with any model supported by vLLM
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
1. **Server not responding**: Make sure vLLM server is running
|
||||
|
||||
```bash
|
||||
curl http://localhost:8000/health
|
||||
```
|
||||
|
||||
2. **404 errors**: Ensure correct base URL format
|
||||
|
||||
```python
|
||||
"vllm_base_url": "http://localhost:8000/v1" # Note the /v1
|
||||
```
|
||||
|
||||
3. **Model not found**: Check model name matches server
|
||||
|
||||
4. **Out of memory**: Try smaller models or reduce `max_model_len`
|
||||
|
||||
```bash
|
||||
vllm serve Qwen/Qwen2.5-32B-Instruct --max-model-len 4096
|
||||
```
|
||||
|
||||
## Config
|
||||
|
||||
All available parameters for the `vllm` config are present in [Master List of All Params in Config](../config).
|
||||
@@ -14,7 +14,9 @@ To use a llm, you must provide a configuration to customize its usage. If no con
|
||||
|
||||
For a comprehensive list of available parameters for llm configuration, please refer to [Config](./config).
|
||||
|
||||
To view all supported llms, visit the [Supported LLMs](./models).
|
||||
## Supported LLMs
|
||||
|
||||
See the list of supported LLMs below.
|
||||
|
||||
<Note>
|
||||
All LLMs are supported in Python. The following LLMs are also supported in TypeScript: **OpenAI**, **Anthropic**, and **Groq**.
|
||||
@@ -34,6 +36,7 @@ To view all supported llms, visit the [Supported LLMs](./models).
|
||||
<Card title="Gemini" href="/components/llms/models/gemini" />
|
||||
<Card title="DeepSeek" href="/components/llms/models/deepseek" />
|
||||
<Card title="xAI" href="/components/llms/models/xAI" />
|
||||
<Card title="Sarvam AI" href="/components/llms/models/sarvam" />
|
||||
<Card title="LM Studio" href="/components/llms/models/lmstudio" />
|
||||
<Card title="Langchain" href="/components/llms/models/langchain" />
|
||||
</CardGroup>
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
---
|
||||
title: Baidu VectorDB (Mochow)
|
||||
---
|
||||
|
||||
[Baidu VectorDB](https://cloud.baidu.com/doc/VDB/index.html) is an enterprise-level distributed vector database service developed by Baidu Intelligent Cloud. It is powered by Baidu's proprietary "Mochow" vector database kernel, providing high performance, availability, and security for vector search.
|
||||
|
||||
### Usage
|
||||
|
||||
```python
|
||||
import os
|
||||
from mem0 import Memory
|
||||
|
||||
config = {
|
||||
"vector_store": {
|
||||
"provider": "baidu",
|
||||
"config": {
|
||||
"endpoint": "http://your-mochow-endpoint:8287",
|
||||
"account": "root",
|
||||
"api_key": "your-api-key",
|
||||
"database_name": "mem0",
|
||||
"table_name": "mem0_table",
|
||||
"embedding_model_dims": 1536,
|
||||
"metric_type": "COSINE"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 movie? 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 available parameters for the `mochow` config:
|
||||
|
||||
| Parameter | Description | Default Value |
|
||||
| --- | --- | --- |
|
||||
| `endpoint` | Endpoint URL for your Baidu VectorDB instance | Required |
|
||||
| `account` | Baidu VectorDB account name | `root` |
|
||||
| `api_key` | API key for accessing Baidu VectorDB | Required |
|
||||
| `database_name` | Name of the database | `mem0` |
|
||||
| `table_name` | Name of the table | `mem0_table` |
|
||||
| `embedding_model_dims` | Dimensions of the embedding model | `1536` |
|
||||
| `metric_type` | Distance metric for similarity search | `L2` |
|
||||
|
||||
### Distance Metrics
|
||||
|
||||
The following distance metrics are supported:
|
||||
|
||||
- `L2`: Euclidean distance (default)
|
||||
- `IP`: Inner product
|
||||
- `COSINE`: Cosine similarity
|
||||
|
||||
### Index Configuration
|
||||
|
||||
The vector index is automatically configured with the following HNSW parameters:
|
||||
|
||||
- `m`: 16 (number of connections per element)
|
||||
- `efconstruction`: 200 (size of the dynamic candidate list)
|
||||
- `auto_build`: true (automatically build index)
|
||||
- `auto_build_index_policy`: Incremental build with 10000 rows increment
|
||||
@@ -0,0 +1,49 @@
|
||||
# MongoDB
|
||||
|
||||
[MongoDB](https://www.mongodb.com/) is a versatile document database that supports vector search capabilities, allowing for efficient high-dimensional similarity searches over large datasets with robust scalability and performance.
|
||||
|
||||
## Usage
|
||||
|
||||
```python
|
||||
import os
|
||||
from mem0 import Memory
|
||||
|
||||
os.environ["OPENAI_API_KEY"] = "sk-xx"
|
||||
|
||||
config = {
|
||||
"vector_store": {
|
||||
"provider": "mongodb",
|
||||
"config": {
|
||||
"db_name": "mem0-db",
|
||||
"collection_name": "mem0-collection",
|
||||
"user": "my-user",
|
||||
"password": "my-password",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 MongoDB:
|
||||
|
||||
| Parameter | Description | Default Value |
|
||||
| --- | --- | --- |
|
||||
| db_name | Name of the MongoDB database | `"mem0_db"` |
|
||||
| collection_name | Name of the MongoDB collection | `"mem0_collection"` |
|
||||
| embedding_model_dims | Dimensions of the embedding vectors | `1536` |
|
||||
| user | MongoDB user for authentication | `None` |
|
||||
| password | Password for the MongoDB user | `None` |
|
||||
| host | MongoDB host | `"localhost"` |
|
||||
| port | MongoDB port | `27017` |
|
||||
|
||||
> **Note**: `user` and `password` must either be provided together or omitted together.
|
||||
@@ -1,59 +1,75 @@
|
||||
[OpenSearch](https://opensearch.org/) is an open-source, enterprise-grade search and observability suite that brings order to unstructured data at scale. OpenSearch supports k-NN (k-Nearest Neighbors) and allows you to store and retrieve high-dimensional vector embeddings efficiently.
|
||||
[OpenSearch](https://opensearch.org/) is an enterprise-grade search and observability suite that brings order to unstructured data at scale. OpenSearch supports k-NN (k-Nearest Neighbors) and allows you to store and retrieve high-dimensional vector embeddings efficiently.
|
||||
|
||||
### Installation
|
||||
|
||||
OpenSearch support requires additional dependencies. Install them with:
|
||||
|
||||
```bash
|
||||
pip install opensearch>=2.8.0
|
||||
pip install opensearch-py
|
||||
```
|
||||
|
||||
### Prerequisites
|
||||
|
||||
Before using OpenSearch with Mem0, you need to set up a collection in AWS OpenSearch Service.
|
||||
|
||||
#### AWS OpenSearch Service
|
||||
You can create a collection through the AWS Console:
|
||||
- Navigate to [OpenSearch Service Console](https://console.aws.amazon.com/aos/home)
|
||||
- Click "Create collection"
|
||||
- Select "Serverless collection" and then enable "Vector search" capabilities
|
||||
- Once created, note the endpoint URL (host) for your configuration
|
||||
|
||||
|
||||
### Usage
|
||||
|
||||
```python
|
||||
import os
|
||||
from mem0 import Memory
|
||||
import boto3
|
||||
from opensearchpy import OpenSearch, RequestsHttpConnection, AWSV4SignerAuth
|
||||
|
||||
os.environ["OPENAI_API_KEY"] = "sk-xx"
|
||||
# For AWS OpenSearch Service with IAM authentication
|
||||
region = 'us-west-2'
|
||||
service = 'aoss'
|
||||
credentials = boto3.Session().get_credentials()
|
||||
auth = AWSV4SignerAuth(credentials, region, service)
|
||||
|
||||
config = {
|
||||
"vector_store": {
|
||||
"provider": "opensearch",
|
||||
"config": {
|
||||
"collection_name": "mem0",
|
||||
"host": "localhost",
|
||||
"port": 9200,
|
||||
"embedding_model_dims": 1536
|
||||
"host": "your-domain.us-west-2.aoss.amazonaws.com",
|
||||
"port": 443,
|
||||
"http_auth": auth,
|
||||
"embedding_model_dims": 1024,
|
||||
"connection_class": RequestsHttpConnection,
|
||||
"pool_maxsize": 20,
|
||||
"use_ssl": True,
|
||||
"verify_certs": True
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Add Memories
|
||||
|
||||
```python
|
||||
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": "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
|
||||
### Search Memories
|
||||
|
||||
Let's see the available parameters for the `opensearch` config:
|
||||
|
||||
| Parameter | Description | Default Value |
|
||||
| ---------------------- | -------------------------------------------------- | ------------- |
|
||||
| `collection_name` | The name of the index to store the vectors | `mem0` |
|
||||
| `embedding_model_dims` | Dimensions of the embedding model | `1536` |
|
||||
| `host` | The host where the OpenSearch server is running | `localhost` |
|
||||
| `port` | The port where the OpenSearch server is running | `9200` |
|
||||
| `api_key` | API key for authentication | `None` |
|
||||
| `user` | Username for basic authentication | `None` |
|
||||
| `password` | Password for basic authentication | `None` |
|
||||
| `verify_certs` | Whether to verify SSL certificates | `False` |
|
||||
| `auto_create_index` | Whether to automatically create the index | `True` |
|
||||
| `use_ssl` | Whether to use SSL for connection | `False` |
|
||||
```python
|
||||
results = m.search("What kind of movies does Alice like?", user_id="alice")
|
||||
```
|
||||
|
||||
### Features
|
||||
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
[Cloudflare Vectorize](https://developers.cloudflare.com/vectorize/) is a vector database offering from Cloudflare, allowing you to build AI-powered applications with vector embeddings.
|
||||
|
||||
### Usage
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript
|
||||
import { Memory } from 'mem0ai/oss';
|
||||
|
||||
const config = {
|
||||
vectorStore: {
|
||||
provider: 'vectorize',
|
||||
config: {
|
||||
indexName: 'my-memory-index',
|
||||
accountId: 'your-cloudflare-account-id',
|
||||
apiKey: 'your-cloudflare-api-key',
|
||||
dimension: 1536, // Optional: defaults to 1536
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const memory = new Memory(config);
|
||||
const messages = [
|
||||
{"role": "user", "content": "I'm looking for a good book to read."},
|
||||
{"role": "assistant", "content": "Sure, what genre are you interested in?"},
|
||||
{"role": "user", "content": "I enjoy fantasy novels with strong world-building."},
|
||||
{"role": "assistant", "content": "Great! I'll keep that in mind for future recommendations."}
|
||||
]
|
||||
await memory.add(messages, { userId: "bob", metadata: { interest: "books" } });
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### Config
|
||||
|
||||
Let's see the available parameters for the `vectorize` config:
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
| Parameter | Description | Default Value |
|
||||
| --- | --- | --- |
|
||||
| `indexName` | The name of the Vectorize index | `None` (Required) |
|
||||
| `accountId` | Your Cloudflare account ID | `None` (Required) |
|
||||
| `apiKey` | Your Cloudflare API token | `None` (Required) |
|
||||
| `dimension` | Dimensions of the embedding model | `1536` |
|
||||
</Tab>
|
||||
</Tabs>
|
||||
@@ -13,7 +13,7 @@ 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.
|
||||
The following vector databases are supported in the Python implementation. The TypeScript implementation currently only supports Qdrant, Redis,Vectorize and in-memory vector database.
|
||||
</Note>
|
||||
|
||||
<CardGroup cols={3}>
|
||||
@@ -23,6 +23,7 @@ See the list of supported vector databases below.
|
||||
<Card title="Upstash Vector" href="/components/vectordbs/dbs/upstash-vector"></Card>
|
||||
<Card title="Milvus" href="/components/vectordbs/dbs/milvus"></Card>
|
||||
<Card title="Pinecone" href="/components/vectordbs/dbs/pinecone"></Card>
|
||||
<Card title="MongoDB" href="/components/vectordbs/dbs/mongodb"></Card>
|
||||
<Card title="Azure" href="/components/vectordbs/dbs/azure"></Card>
|
||||
<Card title="Redis" href="/components/vectordbs/dbs/redis"></Card>
|
||||
<Card title="Elasticsearch" href="/components/vectordbs/dbs/elasticsearch"></Card>
|
||||
|
||||
@@ -29,7 +29,7 @@ For detailed guidance on pull requests, refer to [GitHub's documentation](https:
|
||||
|
||||
## 📦 Dependency Management
|
||||
|
||||
We use `poetry` as our package manager. Install it by following the [official instructions](https://python-poetry.org/docs/#installation).
|
||||
We use `hatch` as our package manager. Install it by following the [official instructions](https://hatch.pypa.io/latest/install/).
|
||||
|
||||
⚠️ **Do NOT use `pip` or `conda` for dependency management.** Instead, run:
|
||||
|
||||
@@ -37,7 +37,7 @@ We use `poetry` as our package manager. Install it by following the [official in
|
||||
make install_all
|
||||
|
||||
# Activate virtual environment
|
||||
poetry shell
|
||||
hatch shell
|
||||
```
|
||||
|
||||
---
|
||||
@@ -60,9 +60,9 @@ Run the linter and fix any reported issues before submitting your PR:
|
||||
make lint
|
||||
```
|
||||
|
||||
### 🎨 Code Formatting with `black`
|
||||
### 🎨 Code Formatting
|
||||
|
||||
To maintain a consistent code style, format your code using `black`:
|
||||
To maintain a consistent code style, format your code:
|
||||
|
||||
```bash
|
||||
make format
|
||||
@@ -76,7 +76,7 @@ Run tests to verify functionality before submitting your PR:
|
||||
make test
|
||||
```
|
||||
|
||||
💡 **Note:** Some dependencies have been removed from Poetry to reduce package size. Run `make install_all` to install necessary dependencies before running tests.
|
||||
💡 **Note:** Some dependencies have been removed from the main dependencies to reduce package size. Run `make install_all` to install necessary dependencies before running tests.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
---
|
||||
title: Add Memory
|
||||
description: Add memory into the Mem0 platform by storing user-assistant interactions and facts for later retrieval.
|
||||
icon: "plus"
|
||||
iconType: "solid"
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
The `add` operation is how you store memory into Mem0. Whether you're working with a chatbot, a voice assistant, or a multi-agent system, this is the entry point to create long-term memory.
|
||||
|
||||
Memories typically come from a **user-assistant interaction** and Mem0 handles the extraction, transformation, and storage for you.
|
||||
|
||||
Mem0 offers two implementation flows:
|
||||
|
||||
- **Mem0 Platform** (Managed, scalable, with dashboard + API)
|
||||
- **Mem0 Open Source** (Lightweight, fully local, flexible SDKs)
|
||||
|
||||
Each supports the same core memory operations, but with slightly different setup. Below, we walk through examples for both.
|
||||
|
||||
|
||||
## Architecture
|
||||
|
||||
<Frame caption="Architecture diagram illustrating the process of adding memories.">
|
||||
<img src="../../images/add_architecture.png" />
|
||||
</Frame>
|
||||
|
||||
When you call `add`, Mem0 performs the following steps under the hood:
|
||||
|
||||
1. **Information Extraction**
|
||||
The input messages are passed through an LLM that extracts key facts, decisions, preferences, or events worth remembering.
|
||||
|
||||
2. **Conflict Resolution**
|
||||
Mem0 compares the new memory against existing ones to detect duplication or contradiction and handles updates accordingly.
|
||||
|
||||
3. **Memory Storage**
|
||||
The result is stored in a vector database (for semantic search) and optionally in a graph structure (for relationship mapping).
|
||||
|
||||
You don’t need to handle any of this manually, Mem0 takes care of it with a single API call or SDK method.
|
||||
|
||||
---
|
||||
|
||||
## Example: Mem0 Platform
|
||||
|
||||
<CodeGroup>
|
||||
```python Python
|
||||
from mem0 import MemoryClient
|
||||
|
||||
client = MemoryClient(api_key="your-api-key")
|
||||
|
||||
messages = [
|
||||
{"role": "user", "content": "I'm planning a trip to Tokyo next month."},
|
||||
{"role": "assistant", "content": "Great! I’ll remember that for future suggestions."}
|
||||
]
|
||||
|
||||
client.add(
|
||||
messages=messages,
|
||||
user_id="alice",
|
||||
version="v2"
|
||||
)
|
||||
```
|
||||
|
||||
```javascript JavaScript
|
||||
import { MemoryClient } from "mem0ai";
|
||||
|
||||
const client = new MemoryClient({apiKey: "your-api-key"});
|
||||
|
||||
const messages = [
|
||||
{ role: "user", content: "I'm planning a trip to Tokyo next month." },
|
||||
{ role: "assistant", content: "Great! I’ll remember that for future suggestions." }
|
||||
];
|
||||
|
||||
await client.add({
|
||||
messages,
|
||||
user_id: "alice",
|
||||
version: "v2"
|
||||
});
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
---
|
||||
|
||||
## Example: Mem0 Open Source
|
||||
|
||||
<CodeGroup>
|
||||
```python Python
|
||||
import os
|
||||
from mem0 import Memory
|
||||
|
||||
os.environ["OPENAI_API_KEY"] = "your-api-key"
|
||||
|
||||
m = Memory()
|
||||
|
||||
messages = [
|
||||
{"role": "user", "content": "I'm planning to watch a movie tonight. Any recommendations?"},
|
||||
{"role": "assistant", "content": "How about a thriller movies? They can be quite engaging."},
|
||||
{"role": "user", "content": "I'm not a big fan of thriller movies but I love sci-fi movies."},
|
||||
{"role": "assistant", "content": "Got it! I'll avoid thriller recommendations and suggest sci-fi movies in the future."}
|
||||
]
|
||||
|
||||
# Store inferred memories (default behavior)
|
||||
result = m.add(messages, user_id="alice", metadata={"category": "movie_recommendations"})
|
||||
|
||||
# Optionally store raw messages without inference
|
||||
result = m.add(messages, user_id="alice", metadata={"category": "movie_recommendations"}, infer=False)
|
||||
```
|
||||
|
||||
```javascript JavaScript
|
||||
import { Memory } from 'mem0ai/oss';
|
||||
|
||||
const memory = new Memory();
|
||||
|
||||
const messages = [
|
||||
{
|
||||
role: "user",
|
||||
content: "I like to drink coffee in the morning and go for a walk"
|
||||
}
|
||||
];
|
||||
|
||||
const result = memory.add(messages, {
|
||||
userId: "alice",
|
||||
metadata: { category: "preferences" }
|
||||
});
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
---
|
||||
|
||||
## When Should You Add Memory?
|
||||
|
||||
Add memory whenever your agent learns something useful:
|
||||
|
||||
- A new user preference is shared
|
||||
- A decision or suggestion is made
|
||||
- A goal or task is completed
|
||||
- A new entity is introduced
|
||||
- A user gives feedback or clarification
|
||||
|
||||
Storing this context allows the agent to reason better in future interactions.
|
||||
|
||||
|
||||
### More Details
|
||||
|
||||
For full list of supported fields, required formats, and advanced options, see the
|
||||
[Add Memory API Reference](/api-reference/memory/add-memories).
|
||||
|
||||
---
|
||||
|
||||
## Need help?
|
||||
If you have any questions, please feel free to reach out to us using one of the following methods:
|
||||
|
||||
<Snippet file="get-help.mdx"/>
|
||||
@@ -0,0 +1,141 @@
|
||||
---
|
||||
title: Delete Memory
|
||||
description: Remove memories from Mem0 either individually, in bulk, or via filters.
|
||||
icon: "trash"
|
||||
iconType: "solid"
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Memories can become outdated, irrelevant, or need to be removed for privacy or compliance reasons. Mem0 offers flexible ways to delete memory:
|
||||
|
||||
1. **Delete a Single Memory**: Using a specific memory ID
|
||||
2. **Batch Delete**: Delete multiple known memory IDs (up to 1000)
|
||||
3. **Filtered Delete**: Delete memories matching a filter (e.g., `user_id`, `metadata`, `run_id`)
|
||||
|
||||
This page walks through code example for each method.
|
||||
|
||||
|
||||
## Use Cases
|
||||
|
||||
- Forget a user’s past preferences by request
|
||||
- Remove outdated or incorrect memory entries
|
||||
- Clean up memory after session expiration
|
||||
- Comply with data deletion requests (e.g., GDPR)
|
||||
|
||||
---
|
||||
|
||||
## 1. Delete a Single Memory by ID
|
||||
|
||||
<CodeGroup>
|
||||
```python Python
|
||||
from mem0 import MemoryClient
|
||||
|
||||
client = MemoryClient(api_key="your-api-key")
|
||||
|
||||
memory_id = "your_memory_id"
|
||||
client.delete(memory_id=memory_id)
|
||||
```
|
||||
|
||||
```javascript JavaScript
|
||||
import MemoryClient from 'mem0ai';
|
||||
|
||||
const client = new MemoryClient({ apiKey: "your-api-key" });
|
||||
|
||||
client.delete("your_memory_id")
|
||||
.then(result => console.log(result))
|
||||
.catch(error => console.error(error));
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
---
|
||||
|
||||
## 2. Batch Delete Multiple Memories
|
||||
|
||||
<CodeGroup>
|
||||
```python Python
|
||||
from mem0 import MemoryClient
|
||||
|
||||
client = MemoryClient(api_key="your-api-key")
|
||||
|
||||
delete_memories = [
|
||||
{"memory_id": "id1"},
|
||||
{"memory_id": "id2"}
|
||||
]
|
||||
|
||||
response = client.batch_delete(delete_memories)
|
||||
print(response)
|
||||
```
|
||||
|
||||
```javascript JavaScript
|
||||
import MemoryClient from 'mem0ai';
|
||||
|
||||
const client = new MemoryClient({ apiKey: "your-api-key" });
|
||||
|
||||
const deleteMemories = [
|
||||
{ memory_id: "id1" },
|
||||
{ memory_id: "id2" }
|
||||
];
|
||||
|
||||
client.batchDelete(deleteMemories)
|
||||
.then(response => console.log('Batch delete response:', response))
|
||||
.catch(error => console.error(error));
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
---
|
||||
|
||||
## 3. Delete Memories by Filter (e.g., user_id)
|
||||
|
||||
<CodeGroup>
|
||||
```python Python
|
||||
from mem0 import MemoryClient
|
||||
|
||||
client = MemoryClient(api_key="your-api-key")
|
||||
|
||||
# Delete all memories for a specific user
|
||||
client.delete_all(user_id="alice")
|
||||
```
|
||||
|
||||
```javascript JavaScript
|
||||
import MemoryClient from 'mem0ai';
|
||||
|
||||
const client = new MemoryClient({ apiKey: "your-api-key" });
|
||||
|
||||
client.deleteAll({ user_id: "alice" })
|
||||
.then(result => console.log(result))
|
||||
.catch(error => console.error(error));
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
You can also filter by other parameters such as:
|
||||
- `agent_id`
|
||||
- `run_id`
|
||||
- `metadata` (as JSON string)
|
||||
|
||||
---
|
||||
|
||||
## Key Differences
|
||||
|
||||
| Method | Use When | IDs Needed | Filters |
|
||||
|----------------------|-------------------------------------------|------------|----------|
|
||||
| `delete(memory_id)` | You know exactly which memory to remove | ✔ | ✘ |
|
||||
| `batch_delete([...])`| You have a known list of memory IDs | ✔ | ✘ |
|
||||
| `delete_all(...)` | You want to delete by user/agent/run/etc | ✘ | ✔ |
|
||||
|
||||
|
||||
### More Details
|
||||
|
||||
For request/response schema and additional filtering options, see:
|
||||
- [Delete Memory API Reference](/api-reference/memory/delete-memory)
|
||||
- [Batch Delete API Reference](/api-reference/memory/batch-delete)
|
||||
- [Delete Memories by Filter Reference](/api-reference/memory/delete-memories)
|
||||
|
||||
You’ve now seen how to add, search, update, and delete memories in Mem0.
|
||||
|
||||
---
|
||||
|
||||
## Need help?
|
||||
If you have any questions, please feel free to reach out to us using one of the following methods:
|
||||
|
||||
<Snippet file="get-help.mdx"/>
|
||||
@@ -0,0 +1,124 @@
|
||||
---
|
||||
title: Search Memory
|
||||
description: Retrieve relevant memories from Mem0 using powerful semantic and filtered search capabilities.
|
||||
icon: "magnifying-glass"
|
||||
iconType: "solid"
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
The `search` operation allows you to retrieve relevant memories based on a natural language query and optional filters like user ID, agent ID, categories, and more. This is the foundation of giving your agents memory-aware behavior.
|
||||
|
||||
Mem0 supports:
|
||||
- Semantic similarity search
|
||||
- Metadata filtering (with advanced logic)
|
||||
- Reranking and thresholds
|
||||
- Cross-agent, multi-session context resolution
|
||||
|
||||
This applies to both:
|
||||
- **Mem0 Platform** (hosted API with full-scale features)
|
||||
- **Mem0 Open Source** (local-first with LLM inference and local vector DB)
|
||||
|
||||
|
||||
## Architecture
|
||||
|
||||
<Frame caption="Architecture diagram illustrating the memory search process.">
|
||||
<img src="../../images/search_architecture.png" />
|
||||
</Frame>
|
||||
|
||||
The search flow follows these steps:
|
||||
|
||||
1. **Query Processing**
|
||||
An LLM refines and optimizes your natural language query.
|
||||
|
||||
2. **Vector Search**
|
||||
Semantic embeddings are used to find the most relevant memories using cosine similarity.
|
||||
|
||||
3. **Filtering & Ranking**
|
||||
Logical and comparison-based filters are applied. Memories are scored, filtered, and optionally reranked.
|
||||
|
||||
4. **Results Delivery**
|
||||
Relevant memories are returned with associated metadata and timestamps.
|
||||
|
||||
---
|
||||
|
||||
## Example: Mem0 Platform
|
||||
|
||||
<CodeGroup>
|
||||
```python Python
|
||||
from mem0 import MemoryClient
|
||||
|
||||
client = MemoryClient(api_key="your-api-key")
|
||||
|
||||
query = "What do you know about me?"
|
||||
filters = {
|
||||
"OR": [
|
||||
{"user_id": "alice"},
|
||||
{"agent_id": {"in": ["travel-assistant", "customer-support"]}}
|
||||
]
|
||||
}
|
||||
|
||||
results = client.search(query, version="v2", filters=filters)
|
||||
```
|
||||
|
||||
```javascript JavaScript
|
||||
import { MemoryClient } from "mem0ai";
|
||||
|
||||
const client = new MemoryClient({apiKey: "your-api-key"});
|
||||
|
||||
const query = "I'm craving some pizza. Any recommendations?";
|
||||
const filters = {
|
||||
AND: [
|
||||
{ user_id: "alice" }
|
||||
]
|
||||
};
|
||||
|
||||
const results = await client.search(query, {
|
||||
version: "v2",
|
||||
filters
|
||||
});
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
---
|
||||
|
||||
## Example: Mem0 Open Source
|
||||
|
||||
<CodeGroup>
|
||||
```python Python
|
||||
from mem0 import Memory
|
||||
|
||||
m = Memory()
|
||||
related_memories = m.search("Should I drink coffee or tea?", user_id="alice")
|
||||
```
|
||||
|
||||
```javascript JavaScript
|
||||
import { Memory } from 'mem0ai/oss';
|
||||
|
||||
const memory = new Memory();
|
||||
const relatedMemories = memory.search("Should I drink coffee or tea?", { userId: "alice" });
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
---
|
||||
|
||||
## Tips for Better Search
|
||||
|
||||
- Use descriptive natural queries (Mem0 can interpret intent)
|
||||
- Apply filters for scoped, faster lookup
|
||||
- Use `version: "v2"` for enhanced results
|
||||
- Consider wildcard filters (e.g., `run_id: "*"`) for broader matches
|
||||
- Tune with `top_k`, `threshold`, or `rerank` if needed
|
||||
|
||||
|
||||
### More Details
|
||||
|
||||
For the full list of filter logic, comparison operators, and optional search parameters, see the
|
||||
[Search Memory API Reference](/api-reference/memory/v2-search-memories).
|
||||
|
||||
---
|
||||
|
||||
## Need help?
|
||||
If you have any questions, please feel free to reach out to us using one of the following methods:
|
||||
|
||||
<Snippet file="get-help.mdx"/>
|
||||
@@ -0,0 +1,117 @@
|
||||
---
|
||||
title: Update Memory
|
||||
description: Modify an existing memory by updating its content or metadata.
|
||||
icon: "pencil"
|
||||
iconType: "solid"
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
User preferences, interests, and behaviors often evolve over time. The `update` operation lets you revise a stored memory, whether it's updating facts and memories, rephrasing a message, or enriching metadata.
|
||||
|
||||
Mem0 supports both:
|
||||
- **Single Memory Update** for one specific memory using its ID
|
||||
- **Batch Update** for updating many memories at once (up to 1000)
|
||||
|
||||
This guide includes usage for both single update and batch update of memories through **Mem0 Platform**
|
||||
|
||||
|
||||
## Use Cases
|
||||
|
||||
- Refine a vague or incorrect memory after a correction
|
||||
- Add or edit memory with new metadata (e.g., categories, tags)
|
||||
- Evolve factual knowledge as the user’s profile changes
|
||||
- A user profile evolves: “I love spicy food” → later says “Actually, I can’t handle spicy food.”
|
||||
|
||||
Updating memory ensures your agents remain accurate, adaptive, and personalized.
|
||||
|
||||
---
|
||||
|
||||
## Update Memory
|
||||
|
||||
<CodeGroup>
|
||||
```python Python
|
||||
from mem0 import MemoryClient
|
||||
|
||||
client = MemoryClient(api_key="your-api-key")
|
||||
|
||||
memory_id = "your_memory_id"
|
||||
client.update(
|
||||
memory_id=memory_id,
|
||||
text="Updated memory content about the user",
|
||||
metadata={"category": "profile-update"}
|
||||
)
|
||||
```
|
||||
|
||||
```javascript JavaScript
|
||||
import MemoryClient from 'mem0ai';
|
||||
|
||||
const client = new MemoryClient({ apiKey: "your-api-key" });
|
||||
const memory_id = "your_memory_id";
|
||||
|
||||
client.update(memory_id, {
|
||||
text: "Updated memory content about the user",
|
||||
metadata: { category: "profile-update" }
|
||||
})
|
||||
.then(result => console.log(result))
|
||||
.catch(error => console.error(error));
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
---
|
||||
|
||||
## Batch Update
|
||||
|
||||
Update up to 1000 memories in one call.
|
||||
|
||||
<CodeGroup>
|
||||
```python Python
|
||||
from mem0 import MemoryClient
|
||||
|
||||
client = MemoryClient(api_key="your-api-key")
|
||||
|
||||
update_memories = [
|
||||
{"memory_id": "id1", "text": "Watches football"},
|
||||
{"memory_id": "id2", "text": "Likes to travel"}
|
||||
]
|
||||
|
||||
response = client.batch_update(update_memories)
|
||||
print(response)
|
||||
```
|
||||
|
||||
```javascript JavaScript
|
||||
import MemoryClient from 'mem0ai';
|
||||
|
||||
const client = new MemoryClient({ apiKey: "your-api-key" });
|
||||
|
||||
const updateMemories = [
|
||||
{ memoryId: "id1", text: "Watches football" },
|
||||
{ memoryId: "id2", text: "Likes to travel" }
|
||||
];
|
||||
|
||||
client.batchUpdate(updateMemories)
|
||||
.then(response => console.log('Batch update response:', response))
|
||||
.catch(error => console.error(error));
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
---
|
||||
|
||||
## Tips
|
||||
|
||||
- You can update both `text` and `metadata` in the same call.
|
||||
- Use `batchUpdate` when you're applying similar corrections at scale.
|
||||
- If memory is marked `immutable`, it must first be deleted and re-added.
|
||||
- Combine this with feedback mechanisms (e.g., user thumbs-up/down) to self-improve memory.
|
||||
|
||||
|
||||
### More Details
|
||||
|
||||
Refer to the full [Update Memory API Reference](/api-reference/memory/update-memory) and [Batch Update Reference](/api-reference/memory/batch-update) for schema and advanced fields.
|
||||
|
||||
---
|
||||
|
||||
## Need help?
|
||||
If you have any questions, please feel free to reach out to us using one of the following methods:
|
||||
|
||||
<Snippet file="get-help.mdx"/>
|
||||
+57
-53
@@ -19,10 +19,10 @@
|
||||
"tab": "Documentation",
|
||||
"groups": [
|
||||
{
|
||||
"group": "Get Started",
|
||||
"group": "Getting Started",
|
||||
"icon": "rocket",
|
||||
"pages": [
|
||||
"overview",
|
||||
"what-is-mem0",
|
||||
"quickstart",
|
||||
"faqs"
|
||||
]
|
||||
@@ -32,7 +32,16 @@
|
||||
"icon": "brain",
|
||||
"pages": [
|
||||
"core-concepts/memory-types",
|
||||
"core-concepts/memory-operations"
|
||||
{
|
||||
"group": "Memory Operations",
|
||||
"icon": "gear",
|
||||
"pages": [
|
||||
"core-concepts/memory-operations/add",
|
||||
"core-concepts/memory-operations/search",
|
||||
"core-concepts/memory-operations/update",
|
||||
"core-concepts/memory-operations/delete"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -45,21 +54,20 @@
|
||||
"group": "Features",
|
||||
"icon": "star",
|
||||
"pages": [
|
||||
"features/platform-overview",
|
||||
"features/advanced-retrieval",
|
||||
"features/contextual-add",
|
||||
"features/multimodal-support",
|
||||
"features/timestamp",
|
||||
"features/selective-memory",
|
||||
"features/custom-categories",
|
||||
"features/custom-instructions",
|
||||
"features/direct-import",
|
||||
"features/async-client",
|
||||
"features/memory-export",
|
||||
"features/webhooks",
|
||||
"features/graph-memory",
|
||||
"features/feedback-mechanism",
|
||||
"features/expiration-date"
|
||||
"platform/features/platform-overview",
|
||||
"platform/features/contextual-add",
|
||||
"platform/features/async-client",
|
||||
"platform/features/advanced-retrieval",
|
||||
"platform/features/criteria-retrieval",
|
||||
"platform/features/selective-memory",
|
||||
"platform/features/custom-categories",
|
||||
"platform/features/custom-instructions",
|
||||
"platform/features/direct-import",
|
||||
"platform/features/memory-export",
|
||||
"platform/features/timestamp",
|
||||
"platform/features/expiration-date",
|
||||
"platform/features/webhooks",
|
||||
"platform/features/feedback-mechanism"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -68,18 +76,18 @@
|
||||
"group": "Open Source",
|
||||
"icon": "code-branch",
|
||||
"pages": [
|
||||
"open-source/quickstart",
|
||||
"open-source/overview",
|
||||
"open-source/python-quickstart",
|
||||
"open-source/node-quickstart",
|
||||
{
|
||||
"group": "Features",
|
||||
"icon": "wrench",
|
||||
"icon": "star",
|
||||
"pages": [
|
||||
"open-source/features/async-memory",
|
||||
"features/openai_compatibility",
|
||||
"features/custom-fact-extraction-prompt",
|
||||
"features/custom-update-memory-prompt",
|
||||
"open-source/multimodal-support",
|
||||
"open-source/features/openai_compatibility",
|
||||
"open-source/features/custom-fact-extraction-prompt",
|
||||
"open-source/features/custom-update-memory-prompt",
|
||||
"open-source/features/multimodal-support",
|
||||
"open-source/features/rest-api"
|
||||
]
|
||||
},
|
||||
@@ -114,8 +122,10 @@
|
||||
"components/llms/models/gemini",
|
||||
"components/llms/models/deepseek",
|
||||
"components/llms/models/xAI",
|
||||
"components/llms/models/sarvam",
|
||||
"components/llms/models/lmstudio",
|
||||
"components/llms/models/langchain"
|
||||
"components/llms/models/langchain",
|
||||
"components/llms/models/vllm"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -135,6 +145,7 @@
|
||||
"components/vectordbs/dbs/pgvector",
|
||||
"components/vectordbs/dbs/milvus",
|
||||
"components/vectordbs/dbs/pinecone",
|
||||
"components/vectordbs/dbs/mongodb",
|
||||
"components/vectordbs/dbs/azure",
|
||||
"components/vectordbs/dbs/redis",
|
||||
"components/vectordbs/dbs/elasticsearch",
|
||||
@@ -143,7 +154,8 @@
|
||||
"components/vectordbs/dbs/vertex_ai",
|
||||
"components/vectordbs/dbs/weaviate",
|
||||
"components/vectordbs/dbs/faiss",
|
||||
"components/vectordbs/dbs/langchain"
|
||||
"components/vectordbs/dbs/langchain",
|
||||
"components/vectordbs/dbs/baidu"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -166,7 +178,8 @@
|
||||
"components/embedders/models/gemini",
|
||||
"components/embedders/models/lmstudio",
|
||||
"components/embedders/models/together",
|
||||
"components/embedders/models/langchain"
|
||||
"components/embedders/models/langchain",
|
||||
"components/embedders/models/aws_bedrock"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -183,6 +196,15 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tab": "OpenMemory",
|
||||
"icon": "square-terminal",
|
||||
"pages": [
|
||||
"openmemory/overview",
|
||||
"openmemory/quickstart",
|
||||
"openmemory/integrations"
|
||||
]
|
||||
},
|
||||
{
|
||||
"tab": "Examples",
|
||||
"groups": [
|
||||
@@ -191,8 +213,11 @@
|
||||
"icon": "lightbulb",
|
||||
"pages": [
|
||||
"examples",
|
||||
"examples/aws_example",
|
||||
"examples/mem0-demo",
|
||||
"examples/ai_companion_js",
|
||||
"examples/collaborative-task-agent",
|
||||
"examples/eliza_os",
|
||||
"examples/mem0-mastra",
|
||||
"examples/mem0-with-ollama",
|
||||
"examples/personal-ai-tutor",
|
||||
@@ -206,6 +231,7 @@
|
||||
"examples/mem0-agentic-tool",
|
||||
"examples/openai-inbuilt-tools",
|
||||
"examples/mem0-openai-voice-demo",
|
||||
"examples/mem0-google-adk-healthcare-assistant",
|
||||
"examples/email_processing",
|
||||
"examples/youtube-assistant"
|
||||
]
|
||||
@@ -220,6 +246,7 @@
|
||||
"icon": "plug",
|
||||
"pages": [
|
||||
"integrations",
|
||||
"integrations/agentops",
|
||||
"integrations/vercel-ai-sdk",
|
||||
"integrations/flowise",
|
||||
"integrations/crewai",
|
||||
@@ -234,7 +261,9 @@
|
||||
"integrations/elevenlabs",
|
||||
"integrations/pipecat",
|
||||
"integrations/agno",
|
||||
"integrations/keywords"
|
||||
"integrations/keywords",
|
||||
"integrations/raycast",
|
||||
"integrations/mastra"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -329,31 +358,6 @@
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"anchor": "Your Dashboard",
|
||||
"href": "https://app.mem0.ai",
|
||||
"icon": "chart-simple"
|
||||
},
|
||||
{
|
||||
"anchor": "Demo",
|
||||
"href": "https://mem0.dev/demo",
|
||||
"icon": "play"
|
||||
},
|
||||
{
|
||||
"anchor": "Discord",
|
||||
"href": "https://mem0.dev/DiD",
|
||||
"icon": "discord"
|
||||
},
|
||||
{
|
||||
"anchor": "GitHub",
|
||||
"href": "https://github.com/mem0ai/mem0",
|
||||
"icon": "github"
|
||||
},
|
||||
{
|
||||
"anchor": "Support",
|
||||
"href": "mailto:founders@mem0.ai",
|
||||
"icon": "envelope"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
+5
-1
@@ -75,7 +75,11 @@ Explore how **Mem0** can power real-world applications and bring personalized, i
|
||||
|
||||
<Card title="Mem0 OpenAI Voice Demo" icon="microphone" href="/examples/mem0-openai-voice-demo">
|
||||
Use Mem0's memory capabilities with OpenAI's Inbuilt Tools to create AI agents with persistent memory.
|
||||
</Card>
|
||||
</Card>
|
||||
|
||||
<Card title="Healthcare Assistant Google ADK" icon="microphone" href="/examples/mem0-google-adk-healthcare-assistant">
|
||||
Build a personalized healthcare assistant with persistent memory using Google's ADK and Mem0.
|
||||
</Card>
|
||||
|
||||
<Card title="Email Processing" icon="envelope" href="/examples/email_processing">
|
||||
Use Mem0's memory capabilities to process emails and create AI agents with persistent memory.
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
---
|
||||
title: AWS Bedrock and AOSS
|
||||
---
|
||||
|
||||
<Snippet file="paper-release.mdx" />
|
||||
|
||||
This example demonstrates how to configure and use the `mem0ai` SDK with **AWS Bedrock** and **OpenSearch Service (AOSS)** for persistent memory capabilities in Python.
|
||||
|
||||
## Installation
|
||||
|
||||
Install the required dependencies:
|
||||
|
||||
```bash
|
||||
pip install mem0ai boto3 opensearch-py
|
||||
```
|
||||
|
||||
## Environment Setup
|
||||
|
||||
Set your AWS environment variables:
|
||||
|
||||
```python
|
||||
import os
|
||||
|
||||
# Set these in your environment or notebook
|
||||
os.environ['AWS_REGION'] = 'us-west-2'
|
||||
os.environ['AWS_ACCESS_KEY_ID'] = 'AK00000000000000000'
|
||||
os.environ['AWS_SECRET_ACCESS_KEY'] = 'AS00000000000000000'
|
||||
|
||||
# Confirm they are set
|
||||
print(os.environ['AWS_REGION'])
|
||||
print(os.environ['AWS_ACCESS_KEY_ID'])
|
||||
print(os.environ['AWS_SECRET_ACCESS_KEY'])
|
||||
```
|
||||
|
||||
## Configuration and Usage
|
||||
|
||||
This sets up Mem0 with AWS Bedrock for embeddings and LLM, and OpenSearch as the vector store.
|
||||
|
||||
```python
|
||||
import boto3
|
||||
from opensearchpy import OpenSearch, RequestsHttpConnection, AWSV4SignerAuth
|
||||
from mem0.memory.main import Memory
|
||||
|
||||
region = 'us-west-2'
|
||||
service = 'aoss'
|
||||
credentials = boto3.Session().get_credentials()
|
||||
auth = AWSV4SignerAuth(credentials, region, service)
|
||||
|
||||
config = {
|
||||
"embedder": {
|
||||
"provider": "aws_bedrock",
|
||||
"config": {
|
||||
"model": "amazon.titan-embed-text-v2:0"
|
||||
}
|
||||
},
|
||||
"llm": {
|
||||
"provider": "aws_bedrock",
|
||||
"config": {
|
||||
"model": "anthropic.claude-3-5-haiku-20241022-v1:0",
|
||||
"temperature": 0.1,
|
||||
"max_tokens": 2000
|
||||
}
|
||||
},
|
||||
"vector_store": {
|
||||
"provider": "opensearch",
|
||||
"config": {
|
||||
"collection_name": "mem0",
|
||||
"host": "your-opensearch-domain.us-west-2.es.amazonaws.com",
|
||||
"port": 443,
|
||||
"http_auth": auth,
|
||||
"embedding_model_dims": 1024,
|
||||
"connection_class": RequestsHttpConnection,
|
||||
"pool_maxsize": 20,
|
||||
"use_ssl": True,
|
||||
"verify_certs": True
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Initialize memory system
|
||||
m = Memory.from_config(config)
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
#### Add a memory:
|
||||
|
||||
```python
|
||||
messages = [
|
||||
{"role": "user", "content": "I'm planning to watch a movie tonight. Any recommendations?"},
|
||||
{"role": "assistant", "content": "How about a thriller movies? They can be quite engaging."},
|
||||
{"role": "user", "content": "I'm not a big fan of thriller movies but I love sci-fi movies."},
|
||||
{"role": "assistant", "content": "Got it! I'll avoid thriller recommendations and suggest sci-fi movies in the future."}
|
||||
]
|
||||
|
||||
# Store inferred memories (default behavior)
|
||||
result = m.add(messages, user_id="alice", metadata={"category": "movie_recommendations"})
|
||||
```
|
||||
|
||||
#### Search a memory:
|
||||
```python
|
||||
relevant_memories = m.search(query, user_id="alice")
|
||||
```
|
||||
|
||||
#### Get all memories:
|
||||
```python
|
||||
all_memories = m.get_all(user_id="alice")
|
||||
```
|
||||
|
||||
#### Get a specific memory:
|
||||
```python
|
||||
memory = m.get(memory_id)
|
||||
```
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Conclusion
|
||||
|
||||
With Mem0 and AWS services like Bedrock and OpenSearch, you can build intelligent AI companions that remember, adapt, and personalize their responses over time. This makes them ideal for long-term assistants, tutors, or support bots with persistent memory and natural conversation abilities.
|
||||
@@ -0,0 +1,125 @@
|
||||
---
|
||||
title: Multi-User Collaboration with Mem0
|
||||
---
|
||||
|
||||
<Snippet file="paper-release.mdx" />
|
||||
|
||||
## Overview
|
||||
|
||||
Build a multi-user collaborative chat or task management system with Mem0. Each message is attributed to its author, and all messages are stored in a shared project space. Mem0 makes it easy to track contributions, sort and group messages, and collaborate in real time.
|
||||
|
||||
## Setup
|
||||
|
||||
Install the required packages:
|
||||
|
||||
```bash
|
||||
pip install openai mem0ai
|
||||
```
|
||||
|
||||
## Full Code Example
|
||||
|
||||
```python
|
||||
from openai import OpenAI
|
||||
from mem0 import Memory
|
||||
import os
|
||||
from datetime import datetime
|
||||
from collections import defaultdict
|
||||
|
||||
# Set your OpenAI API key
|
||||
os.environ["OPENAI_API_KEY"] = "sk-your-key"
|
||||
|
||||
# Shared project context
|
||||
RUN_ID = "project-demo"
|
||||
|
||||
# Initialize Mem0
|
||||
mem = Memory()
|
||||
|
||||
class CollaborativeAgent:
|
||||
def __init__(self, run_id):
|
||||
self.run_id = run_id
|
||||
self.mem = mem
|
||||
|
||||
def add_message(self, role, name, content):
|
||||
msg = {"role": role, "name": name, "content": content}
|
||||
self.mem.add([msg], run_id=self.run_id, infer=False)
|
||||
|
||||
def brainstorm(self, prompt):
|
||||
# Get recent messages for context
|
||||
memories = self.mem.search(prompt, run_id=self.run_id, limit=5)["results"]
|
||||
context = "\n".join(f"- {m['memory']} (by {m.get('actor_id', 'Unknown')})" for m in memories)
|
||||
client = OpenAI()
|
||||
messages = [
|
||||
{"role": "system", "content": "You are a helpful project assistant."},
|
||||
{"role": "user", "content": f"Prompt: {prompt}\nContext:\n{context}"}
|
||||
]
|
||||
reply = client.chat.completions.create(
|
||||
model="gpt-4o-mini",
|
||||
messages=messages
|
||||
).choices[0].message.content.strip()
|
||||
self.add_message("assistant", "assistant", reply)
|
||||
return reply
|
||||
|
||||
def get_all_messages(self):
|
||||
return self.mem.get_all(run_id=self.run_id)["results"]
|
||||
|
||||
def print_sorted_by_time(self):
|
||||
messages = self.get_all_messages()
|
||||
messages.sort(key=lambda m: m.get('created_at', ''))
|
||||
print("\n--- Messages (sorted by time) ---")
|
||||
for m in messages:
|
||||
who = m.get("actor_id") or "Unknown"
|
||||
ts = m.get('created_at', 'Timestamp N/A')
|
||||
try:
|
||||
dt = datetime.fromisoformat(ts.replace('Z', '+00:00'))
|
||||
ts_fmt = dt.strftime('%Y-%m-%d %H:%M:%S')
|
||||
except Exception:
|
||||
ts_fmt = ts
|
||||
print(f"[{ts_fmt}] [{who}] {m['memory']}")
|
||||
|
||||
def print_grouped_by_actor(self):
|
||||
messages = self.get_all_messages()
|
||||
grouped = defaultdict(list)
|
||||
for m in messages:
|
||||
grouped[m.get("actor_id") or "Unknown"].append(m)
|
||||
print("\n--- Messages (grouped by actor) ---")
|
||||
for actor, mems in grouped.items():
|
||||
print(f"\n=== {actor} ===")
|
||||
for m in mems:
|
||||
ts = m.get('created_at', 'Timestamp N/A')
|
||||
try:
|
||||
dt = datetime.fromisoformat(ts.replace('Z', '+00:00'))
|
||||
ts_fmt = dt.strftime('%Y-%m-%d %H:%M:%S')
|
||||
except Exception:
|
||||
ts_fmt = ts
|
||||
print(f"[{ts_fmt}] {m['memory']}")
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```python
|
||||
# Example usage
|
||||
agent = CollaborativeAgent(RUN_ID)
|
||||
agent.add_message("user", "alice", "Let's list tasks for the new landing page.")
|
||||
agent.add_message("user", "bob", "I'll own the hero section copy.")
|
||||
agent.add_message("user", "carol", "I'll choose product screenshots.")
|
||||
|
||||
# Brainstorm with context
|
||||
print("\nAssistant reply:\n", agent.brainstorm("What are the current open tasks?"))
|
||||
|
||||
# Print all messages sorted by time
|
||||
agent.print_sorted_by_time()
|
||||
|
||||
# Print all messages grouped by actor
|
||||
agent.print_grouped_by_actor()
|
||||
```
|
||||
|
||||
## Key Points
|
||||
|
||||
- Each message is attributed to a user or agent (actor)
|
||||
- All messages are stored in a shared project space (`run_id`)
|
||||
- You can sort messages by time, group by actor, and format timestamps for clarity
|
||||
- Mem0 makes it easy to build collaborative, attributed chat/task systems
|
||||
|
||||
## Conclusion
|
||||
|
||||
Mem0 enables fast, transparent collaboration for teams and agents, with full attribution, flexible memory search, and easy message organization.
|
||||
@@ -0,0 +1,75 @@
|
||||
---
|
||||
title: Eliza OS Character
|
||||
---
|
||||
|
||||
<Snippet file="paper-release.mdx" />
|
||||
|
||||
You can create a personalised Eliza OS Character using Mem0. This guide will walk you through the necessary steps and provide the complete code to get you started.
|
||||
|
||||
## Overview
|
||||
|
||||
ElizaOS is a powerful AI agent framework for autonomy & personality. It is a collection of tools that help you create a personalised AI agent.
|
||||
|
||||
## Setup
|
||||
You can start by cloning the eliza-os repository:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/elizaOS/eliza.git
|
||||
```
|
||||
|
||||
Change the directory to the eliza-os repository:
|
||||
|
||||
```bash
|
||||
cd eliza
|
||||
```
|
||||
|
||||
Install the dependencies:
|
||||
|
||||
```bash
|
||||
pnpm install
|
||||
```
|
||||
|
||||
Build the project:
|
||||
|
||||
```bash
|
||||
pnpm build
|
||||
```
|
||||
|
||||
## Setup ENVs
|
||||
|
||||
Create a `.env` file in the root of the project and add the following ( You can use the `.env.example` file as a reference):
|
||||
|
||||
```bash
|
||||
# Mem0 Configuration
|
||||
MEM0_API_KEY= # Mem0 API Key ( Get from https://app.mem0.ai/dashboard/api-keys )
|
||||
MEM0_USER_ID= # Default: eliza-os-user
|
||||
MEM0_PROVIDER= # Default: openai
|
||||
MEM0_PROVIDER_API_KEY= # API Key for the provider (openai, anthropic, etc.)
|
||||
SMALL_MEM0_MODEL= # Default: gpt-4o-mini
|
||||
MEDIUM_MEM0_MODEL= # Default: gpt-4o
|
||||
LARGE_MEM0_MODEL= # Default: gpt-4o
|
||||
```
|
||||
|
||||
## Make the default character use Mem0
|
||||
|
||||
By default, there is a character called `eliza` that uses the `ollama` model. You can make this character use Mem0 by changing the config in the `agent/src/defaultCharacter.ts` file.
|
||||
|
||||
```ts
|
||||
modelProvider: ModelProviderName.MEM0,
|
||||
```
|
||||
|
||||
This will make the character use Mem0 to generate responses.
|
||||
|
||||
## Run the project
|
||||
|
||||
```bash
|
||||
pnpm start
|
||||
```
|
||||
|
||||
## Conclusion
|
||||
|
||||
You have now created a personalised Eliza OS Character using Mem0. You can now start interacting with the character by running the project and talking to the character.
|
||||
|
||||
This is a simple example of how to use Mem0 to create a personalised AI agent. You can use this as a starting point to create your own AI agent.
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ os.environ["OPENAI_API_KEY"] = "<your-openai-api-key>"
|
||||
llm = OpenAI(model="gpt-4o")
|
||||
```
|
||||
|
||||
Initialize the Mem0 client. You can find your API key [here](https://app.mem0.ai/dashboard/). Read about Mem0 [Open Source](https://docs.mem0.ai/open-source/quickstart).
|
||||
Initialize the Mem0 client. You can find your API key [here](https://app.mem0.ai/dashboard/api-keys). Read about Mem0 [Open Source](https://docs.mem0.ai/open-source/overview).
|
||||
```python
|
||||
os.environ["MEM0_API_KEY"] = "<your-mem0-api-key>"
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ You can create a personalized AI Companion using Mem0. This guide will walk you
|
||||
src="https://github.com/user-attachments/assets/cebc4f8e-bdb9-4837-868d-13c5ab7bb433"
|
||||
></video>
|
||||
|
||||
You can try the [Mem0 Demo](https://mem0.dev/demo) live here.
|
||||
You can try the [Mem0 Demo](https://mem0-4vmi.vercel.app) live here.
|
||||
|
||||
## Overview
|
||||
|
||||
|
||||
@@ -0,0 +1,291 @@
|
||||
---
|
||||
title: 'Healthcare Assistant with Mem0 and Google ADK'
|
||||
description: 'Build a personalized healthcare agent that remembers patient information across conversations using Mem0 and Google ADK'
|
||||
---
|
||||
|
||||
<Snippet file="paper-release.mdx" />
|
||||
|
||||
# Healthcare Assistant with Memory
|
||||
|
||||
This example demonstrates how to build a healthcare assistant that remembers patient information across conversations using Google ADK and Mem0.
|
||||
|
||||
## Overview
|
||||
|
||||
The Healthcare Assistant helps patients by:
|
||||
- Remembering their medical history and symptoms
|
||||
- Providing general health information
|
||||
- Scheduling appointment reminders
|
||||
- Maintaining a personalized experience across conversations
|
||||
|
||||
By integrating Mem0's memory layer with Google ADK, the assistant maintains context about the patient without requiring them to repeat information.
|
||||
|
||||
## Setup
|
||||
|
||||
Before you begin, make sure you have:
|
||||
|
||||
Installed Google ADK and Mem0 SDK:
|
||||
```bash
|
||||
pip install google-adk
|
||||
pip install mem0ai
|
||||
```
|
||||
|
||||
## Code Breakdown
|
||||
|
||||
Let's get started and understand the different components required in building a healthcare assistant powered by memory
|
||||
|
||||
```python
|
||||
# Import dependencies
|
||||
import os
|
||||
from google.adk.agents import Agent
|
||||
from google.adk.sessions import InMemorySessionService
|
||||
from google.adk.runners import Runner
|
||||
from google.genai import types
|
||||
from mem0 import MemoryClient
|
||||
|
||||
# Set up API keys (replace with your actual keys)
|
||||
os.environ["GOOGLE_API_KEY"] = "your-google-api-key"
|
||||
os.environ["MEM0_API_KEY"] = "your-mem0-api-key"
|
||||
|
||||
# Define a global user ID for simplicity
|
||||
USER_ID = "Alex"
|
||||
|
||||
# Initialize Mem0 client
|
||||
mem0_client = MemoryClient()
|
||||
```
|
||||
|
||||
## Define Memory Tools
|
||||
|
||||
First, we'll create tools that allow our agent to store and retrieve information using Mem0:
|
||||
|
||||
```python
|
||||
def save_patient_info(information: str) -> dict:
|
||||
"""Saves important patient information to memory."""
|
||||
|
||||
# Store in Mem0
|
||||
response = mem0_client.add(
|
||||
[{"role": "user", "content": information}],
|
||||
user_id=USER_ID,
|
||||
run_id="healthcare_session",
|
||||
metadata={"type": "patient_information"}
|
||||
)
|
||||
|
||||
|
||||
def retrieve_patient_info(query: str) -> dict:
|
||||
"""Retrieves relevant patient information from memory."""
|
||||
|
||||
# Search Mem0
|
||||
results = mem0_client.search(
|
||||
query,
|
||||
user_id=USER_ID,
|
||||
limit=5,
|
||||
threshold=0.7, # Higher threshold for more relevant results
|
||||
output_format="v1.1"
|
||||
)
|
||||
|
||||
# Format and return the results
|
||||
if results and len(results) > 0:
|
||||
memories = [memory["memory"] for memory in results.get('results', [])]
|
||||
return {
|
||||
"status": "success",
|
||||
"memories": memories,
|
||||
"count": len(memories)
|
||||
}
|
||||
else:
|
||||
return {
|
||||
"status": "no_results",
|
||||
"memories": [],
|
||||
"count": 0
|
||||
}
|
||||
```
|
||||
|
||||
## Define Healthcare Tools
|
||||
|
||||
Next, we'll add tools specific to healthcare assistance:
|
||||
|
||||
```python
|
||||
def schedule_appointment(date: str, time: str, reason: str) -> dict:
|
||||
"""Schedules a doctor's appointment."""
|
||||
# In a real app, this would connect to a scheduling system
|
||||
appointment_id = f"APT-{hash(date + time) % 10000}"
|
||||
|
||||
return {
|
||||
"status": "success",
|
||||
"appointment_id": appointment_id,
|
||||
"confirmation": f"Appointment scheduled for {date} at {time} for {reason}",
|
||||
"message": "Please arrive 15 minutes early to complete paperwork."
|
||||
}
|
||||
```
|
||||
|
||||
## Create the Healthcare Assistant Agent
|
||||
|
||||
Now we'll create our main agent with all the tools:
|
||||
|
||||
```python
|
||||
# Create the agent
|
||||
healthcare_agent = Agent(
|
||||
name="healthcare_assistant",
|
||||
model="gemini-1.5-flash", # Using Gemini for healthcare assistant
|
||||
description="Healthcare assistant that helps patients with health information and appointment scheduling.",
|
||||
instruction="""You are a helpful Healthcare Assistant with memory capabilities.
|
||||
|
||||
Your primary responsibilities are to:
|
||||
1. Remember patient information using the 'save_patient_info' tool when they share symptoms, conditions, or preferences.
|
||||
2. Retrieve past patient information using the 'retrieve_patient_info' tool when relevant to the current conversation.
|
||||
3. Help schedule appointments using the 'schedule_appointment' tool.
|
||||
|
||||
IMPORTANT GUIDELINES:
|
||||
- Always be empathetic, professional, and helpful.
|
||||
- Save important patient information like symptoms, conditions, allergies, and preferences.
|
||||
- Check if you have relevant patient information before asking for details they may have shared previously.
|
||||
- Make it clear you are not a doctor and cannot provide medical diagnosis or treatment.
|
||||
- For serious symptoms, always recommend consulting a healthcare professional.
|
||||
- Keep all patient information confidential.
|
||||
""",
|
||||
tools=[save_patient_info, retrieve_patient_info, schedule_appointment]
|
||||
)
|
||||
```
|
||||
|
||||
## Set Up Session and Runner
|
||||
|
||||
```python
|
||||
# Set up Session Service and Runner
|
||||
session_service = InMemorySessionService()
|
||||
|
||||
# Define constants for the conversation
|
||||
APP_NAME = "healthcare_assistant_app"
|
||||
USER_ID = "Alex"
|
||||
SESSION_ID = "session_001"
|
||||
|
||||
# Create a session
|
||||
session = session_service.create_session(
|
||||
app_name=APP_NAME,
|
||||
user_id=USER_ID,
|
||||
session_id=SESSION_ID
|
||||
)
|
||||
|
||||
# Create the runner
|
||||
runner = Runner(
|
||||
agent=healthcare_agent,
|
||||
app_name=APP_NAME,
|
||||
session_service=session_service
|
||||
)
|
||||
```
|
||||
|
||||
## Interact with the Healthcare Assistant
|
||||
|
||||
```python
|
||||
# Function to interact with the agent
|
||||
async def call_agent_async(query, runner, user_id, session_id):
|
||||
"""Sends a query to the agent and returns the final response."""
|
||||
print(f"\n>>> Patient: {query}")
|
||||
|
||||
# Format the user's message
|
||||
content = types.Content(
|
||||
role='user',
|
||||
parts=[types.Part(text=query)]
|
||||
)
|
||||
|
||||
# Set user_id for tools to access
|
||||
save_patient_info.user_id = user_id
|
||||
retrieve_patient_info.user_id = user_id
|
||||
|
||||
# Run the agent
|
||||
async for event in runner.run_async(
|
||||
user_id=user_id,
|
||||
session_id=session_id,
|
||||
new_message=content
|
||||
):
|
||||
if event.is_final_response():
|
||||
if event.content and event.content.parts:
|
||||
response = event.content.parts[0].text
|
||||
print(f"<<< Assistant: {response}")
|
||||
return response
|
||||
|
||||
return "No response received."
|
||||
|
||||
# Example conversation flow
|
||||
async def run_conversation():
|
||||
# First interaction - patient introduces themselves with key information
|
||||
await call_agent_async(
|
||||
"Hi, I'm Alex. I've been having headaches for the past week, and I have a penicillin allergy.",
|
||||
runner=runner,
|
||||
user_id=USER_ID,
|
||||
session_id=SESSION_ID
|
||||
)
|
||||
|
||||
# Request for health information
|
||||
await call_agent_async(
|
||||
"Can you tell me more about what might be causing my headaches?",
|
||||
runner=runner,
|
||||
user_id=USER_ID,
|
||||
session_id=SESSION_ID
|
||||
)
|
||||
|
||||
# Schedule an appointment
|
||||
await call_agent_async(
|
||||
"I think I should see a doctor. Can you help me schedule an appointment for next Monday at 2pm?",
|
||||
runner=runner,
|
||||
user_id=USER_ID,
|
||||
session_id=SESSION_ID
|
||||
)
|
||||
|
||||
# Test memory - should remember patient name, symptoms, and allergy
|
||||
await call_agent_async(
|
||||
"What medications should I avoid for my headaches?",
|
||||
runner=runner,
|
||||
user_id=USER_ID,
|
||||
session_id=SESSION_ID
|
||||
)
|
||||
|
||||
# Run the conversation example
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(run_conversation())
|
||||
```
|
||||
|
||||
## How It Works
|
||||
|
||||
This healthcare assistant demonstrates several key capabilities:
|
||||
|
||||
1. **Memory Storage**: When Alex mentions her headaches and penicillin allergy, the agent stores this information in Mem0 using the `save_patient_info` tool.
|
||||
|
||||
2. **Contextual Retrieval**: When Alex asks about headache causes, the agent uses the `retrieve_patient_info` tool to recall her specific situation.
|
||||
|
||||
3. **Memory Application**: When discussing medications, the agent remembers Alex's penicillin allergy without her needing to repeat it, providing safer and more personalized advice.
|
||||
|
||||
4. **Conversation Continuity**: The agent maintains context across the entire conversation session, creating a more natural and efficient interaction.
|
||||
|
||||
## Key Implementation Details
|
||||
|
||||
### User ID Management
|
||||
|
||||
Instead of passing the user ID as a parameter to the memory tools (which would require modifying the ADK's tool calling system), we attach it directly to the function object:
|
||||
|
||||
```python
|
||||
# Set user_id for tools to access
|
||||
save_patient_info.user_id = user_id
|
||||
retrieve_patient_info.user_id = user_id
|
||||
```
|
||||
|
||||
Inside the tool functions, we retrieve this attribute:
|
||||
|
||||
```python
|
||||
# Get user_id from session state or use default
|
||||
user_id = getattr(save_patient_info, 'user_id', 'default_user')
|
||||
```
|
||||
|
||||
This approach allows our tools to maintain user context without complicating their parameter signatures.
|
||||
|
||||
### Mem0 Integration
|
||||
|
||||
The integration with Mem0 happens through two primary functions:
|
||||
|
||||
1. `mem0_client.add()` - Stores new information with appropriate metadata
|
||||
2. `mem0_client.search()` - Retrieves relevant memories using semantic search
|
||||
|
||||
The `threshold` parameter in the search function ensures that only highly relevant memories are returned.
|
||||
|
||||
## Conclusion
|
||||
|
||||
This example demonstrates how to build a healthcare assistant with persistent memory using Google ADK and Mem0. The integration allows for a more personalized patient experience by maintaining context across conversation turns, which is particularly valuable in healthcare scenarios where continuity of information is crucial.
|
||||
|
||||
By storing and retrieving patient information intelligently, the assistant provides more relevant responses without requiring the patient to repeat their medical history, symptoms, or preferences.
|
||||
@@ -1,105 +0,0 @@
|
||||
---
|
||||
title: Advanced Retrieval
|
||||
icon: "magnifying-glass"
|
||||
iconType: "solid"
|
||||
---
|
||||
|
||||
<Snippet file="paper-release.mdx" />
|
||||
|
||||
Mem0's **Advanced Retrieval** feature delivers superior search results by leveraging state-of-the-art search algorithms. Beyond the default search functionality, Mem0 offers the following advanced retrieval modes:
|
||||
|
||||
1. **Keyword Search**
|
||||
|
||||
This mode emphasizes keywords within the query, returning memories that contain the most relevant keywords alongside those from the default search. By default, this parameter is set to `false`. Enabling it enhances search recall, though it may slightly impact precision.
|
||||
|
||||
```python
|
||||
client.search(query, keyword_search=True, user_id='alex')
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```python
|
||||
# Search for memories about food preferences with keyword search enabled
|
||||
query = "What are my food preferences?"
|
||||
results = client.search(query, keyword_search=True, user_id='alex')
|
||||
|
||||
# Output might include:
|
||||
# - "Vegetarian. Allergic to nuts." (highly relevant)
|
||||
# - "Prefers spicy food and enjoys Thai cuisine" (relevant)
|
||||
# - "Mentioned disliking sea food during restaurant discussion" (keyword match)
|
||||
|
||||
# Without keyword_search=True, only the most relevant memories would be returned:
|
||||
# - "Vegetarian. Allergic to nuts." (highly relevant)
|
||||
# - "Prefers spicy food and enjoys Thai cuisine" (relevant)
|
||||
# The keyword-based match about "sea food" would be excluded
|
||||
```
|
||||
|
||||
2. **Reranking**
|
||||
|
||||
Normal retrieval gives you memories sorted in order of their relevancy, but the order may not be perfect. Reranking uses a deep neural network to correct this order, ensuring the most relevant memories appear first. If you are concerned about the order of memories, or want that the best results always comes at top then use reranking. This parameter is set to `false` by default. When enabled, it reorders the memories based on a more accurate relevance score.
|
||||
|
||||
```python
|
||||
client.search(query, rerank=True, user_id='alex')
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```python
|
||||
# Search for travel plans with reranking enabled
|
||||
query = "What are my travel plans?"
|
||||
results = client.search(query, rerank=True, user_id='alex')
|
||||
|
||||
# Without reranking, results might be ordered like:
|
||||
# 1. "Traveled to France last year" (less relevant to current plans)
|
||||
# 2. "Planning a trip to Japan next month" (more relevant to current plans)
|
||||
# 3. "Interested in visiting Tokyo restaurants" (relevant to current plans)
|
||||
|
||||
# With reranking enabled, results would be reordered:
|
||||
# 1. "Planning a trip to Japan next month" (most relevant to current plans)
|
||||
# 2. "Interested in visiting Tokyo restaurants" (highly relevant to current plans)
|
||||
# 3. "Traveled to France last year" (less relevant to current plans)
|
||||
```
|
||||
|
||||
3. **Filtering**
|
||||
|
||||
Filtering allows you to narrow down search results by applying specific criterias. This parameter is set to `false` by default. When activated, it significantly enhances search precision by removing irrelevant memories, though it may slightly reduce recall. Filtering is particularly useful when you need highly specific information.
|
||||
|
||||
```python
|
||||
client.search(query, filter_memories=True, user_id='alex')
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```python
|
||||
# Search for dietary restrictions with filtering enabled
|
||||
query = "What are my dietary restrictions?"
|
||||
results = client.search(query, filter_memories=True, user_id='alex')
|
||||
|
||||
# Without filtering, results might include:
|
||||
# - "Vegetarian. Allergic to nuts." (directly relevant)
|
||||
# - "I enjoy cooking Italian food on weekends" (somewhat related to food)
|
||||
# - "Mentioned disliking seafood during restaurant discussion" (food-related)
|
||||
# - "Prefers to eat dinner at 7pm" (tangentially food-related)
|
||||
|
||||
# With filtering enabled, results would be focused:
|
||||
# - "Vegetarian. Allergic to nuts." (directly relevant)
|
||||
# - "Mentioned disliking seafood during restaurant discussion" (relevant restriction)
|
||||
#
|
||||
# The filtering process removes memories that are about food preferences
|
||||
# but not specifically about dietary restrictions
|
||||
```
|
||||
|
||||
<Note> You can enable or disable these search modes by passing the respective parameters to the `search` method. There is no required sequence for these modes, and any combination can be used based on your needs. </Note>
|
||||
|
||||
|
||||
### Latency Numbers
|
||||
|
||||
Here are the typical latency ranges for each search mode:
|
||||
|
||||
| **Mode** | **Latency** |
|
||||
|---------------------|------------------|
|
||||
| **Keyword Search** | **<10ms** |
|
||||
| **Reranking** | **150-200ms** |
|
||||
| **Filtering** | **200-300ms** |
|
||||
|
||||
|
||||
If you have any questions, please feel free to reach out to us using one of the following methods:
|
||||
|
||||
<Snippet file="get-help.mdx" />
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 50 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 285 KiB |
@@ -18,6 +18,23 @@ Here are the available integrations for Mem0:
|
||||
## Integrations
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card
|
||||
title="AgentOps"
|
||||
icon={
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="25"
|
||||
height="26"
|
||||
viewBox="0 0 30 36"
|
||||
fill="none"
|
||||
>
|
||||
<path d="M10.4659 6.47277C10.45 6.37428 10.4381 6.27986 10.4303 6.18101L10.4285 6.16388C10.4212 6.09482 10.414 6.02566 10.4106 5.95626L1.18538 21.8752C0.505422 23.0493 0.323356 24.4208 0.675227 25.7289C0.849119 26.3869 1.14971 26.9859 1.55323 27.5098C1.95675 28.0338 2.46282 28.4751 3.05175 28.8143C3.83464 29.2675 4.70856 29.5 5.59028 29.5C6.03318 29.5 6.4798 29.4408 6.91899 29.3226C8.23581 28.972 9.3349 28.1326 10.0152 26.9545L15.9268 16.749V16.7449L16.5001 15.7637L17.6431 13.7936L16.5001 11.8234L15.9309 10.8381L15.9268 10.8341L13.7836 7.13406C13.6651 6.933 13.5741 6.72418 13.5109 6.51165C13.2817 5.80223 13.3292 5.04172 13.6097 4.37599L13.8115 4.02535C14.3532 3.09155 15.31 2.53987 16.3184 2.47692C16.3738 2.46915 16.4251 2.46915 16.4804 2.46915C16.5421 2.46915 16.6038 2.47257 16.6654 2.47599L16.6822 2.47692C17.6906 2.53987 18.6474 3.09155 19.1892 4.02535L21.2216 7.52838L21.8146 8.55289L21.8421 8.60399L30.1024 22.8601C30.5174 23.5814 30.6281 24.4167 30.4148 25.2205C30.1975 26.0244 29.6832 26.6942 28.9598 27.1081C28.2364 27.5258 27.3977 27.6361 26.5911 27.4195C25.7844 27.2066 25.1123 26.6905 24.6968 25.9696L18.2119 14.7788L17.069 16.7449L22.9847 26.9545C23.6646 28.1326 24.7641 28.972 26.0809 29.3226C26.5197 29.4408 26.9626 29.5 27.4096 29.5C28.2914 29.5 29.1612 29.2675 29.9482 28.8143C31.1264 28.1367 31.9728 27.0411 32.3247 25.7289C32.6766 24.4208 32.4949 23.0493 31.8145 21.8752L21.1261 3.43034C20.7029 2.51617 20.0033 1.72011 19.0621 1.18027C18.5281 0.877027 17.9708 0.675975 17.3975 0.581189C17.3027 0.565268 17.2076 0.549717 17.1129 0.537868C17.0099 0.52602 16.9074 0.518244 16.8045 0.510469C16.6027 0.498621 16.3972 0.494548 16.1914 0.510469C16.0885 0.518244 15.9859 0.52639 15.883 0.537868C15.795 0.54887 15.7067 0.563384 15.6187 0.577852L15.5984 0.581189C15.0291 0.675605 14.4673 0.876657 13.9375 1.18027C12.9885 1.72789 12.2766 2.53579 11.8537 3.46181C11.7742 3.63473 11.707 3.81282 11.6471 3.99314C11.6361 4.02668 11.6269 4.06051 11.6177 4.09435C11.612 4.11503 11.6064 4.13579 11.6003 4.15642C11.5624 4.28601 11.5275 4.41634 11.4996 4.54853C11.4885 4.60231 11.4794 4.65668 11.4703 4.71111L11.4666 4.73329C11.4443 4.86399 11.4264 4.99543 11.4145 5.12762C11.4093 5.18686 11.4045 5.24573 11.4012 5.30534C11.3934 5.44567 11.3923 5.58637 11.3963 5.72744C11.3969 5.74403 11.3962 5.76062 11.3956 5.7772C11.3949 5.79616 11.3942 5.81512 11.3952 5.83407C11.3952 5.86184 11.3952 5.88924 11.3993 5.92071C11.3998 5.9291 11.4006 5.93736 11.4014 5.94564C11.402 5.95125 11.4026 5.95687 11.403 5.96255C11.4045 5.98181 11.4064 6.00106 11.4082 6.02031C11.4097 6.03577 11.4109 6.05122 11.4122 6.06674C11.4142 6.09134 11.4163 6.11621 11.419 6.14139L11.4428 6.32282C11.4506 6.38983 11.4625 6.46092 11.4744 6.52757C11.5063 6.68863 11.5468 6.84896 11.5936 7.0078C11.5944 7.0102 11.5949 7.0127 11.5955 7.0152C11.5958 7.01662 11.5961 7.01804 11.5965 7.01944C11.5967 7.02051 11.597 7.02157 11.5974 7.02261C11.6483 7.19293 11.7081 7.36177 11.7787 7.52838C11.8619 7.72943 11.9607 7.92641 12.0715 8.11932L12.3245 8.5566V8.56067L12.4984 8.85614L12.7199 9.24232H12.7239L12.728 9.25417L14.7802 12.7927V12.7968L14.7883 12.805V12.809L15.3576 13.7943L14.7883 14.7796L8.30344 25.9703C7.88431 26.6912 7.21216 27.2077 6.40921 27.4202C6.14019 27.4913 5.86338 27.5306 5.59474 27.5306C5.053 27.5306 4.51906 27.3888 4.04085 27.1089C3.31705 26.6953 2.79909 26.0251 2.58581 25.2213C2.36845 24.4174 2.47917 23.5821 2.89829 22.8609L11.1585 8.60473L11.186 8.56141V8.55734C11.1266 8.45478 11.0753 8.35629 11.024 8.25409C11.0105 8.22496 10.9969 8.19611 10.9834 8.16739C10.9458 8.08735 10.9086 8.00836 10.8739 7.92715C10.8718 7.92504 10.8708 7.92194 10.8698 7.91887C10.8688 7.91602 10.8679 7.91319 10.8661 7.91123V7.90346C10.8423 7.8483 10.8186 7.79311 10.7989 7.73795C10.7476 7.60799 10.7041 7.47803 10.6644 7.3477C10.6012 7.15479 10.5536 6.96152 10.518 6.76861C10.4942 6.67012 10.4786 6.5757 10.4667 6.47684C10.4667 6.47684 10.47 6.47684 10.4659 6.47277Z" fill="currentColor"></path>
|
||||
</svg>
|
||||
}
|
||||
href="/integrations/agentops"
|
||||
>
|
||||
Monitor and analyze Mem0 operations with comprehensive AI agent analytics and LLM observability.
|
||||
</Card>
|
||||
<Card
|
||||
title="LangChain"
|
||||
icon={
|
||||
@@ -305,6 +322,7 @@ Here are the available integrations for Mem0:
|
||||
>
|
||||
Build autonomous agents with memory using Agno framework.
|
||||
</Card>
|
||||
|
||||
<Card
|
||||
title="Keywords AI"
|
||||
icon={
|
||||
@@ -322,4 +340,60 @@ Here are the available integrations for Mem0:
|
||||
>
|
||||
Build AI applications with persistent memory and comprehensive LLM observability.
|
||||
</Card>
|
||||
<Card
|
||||
title="Raycast"
|
||||
icon={
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
>
|
||||
<path
|
||||
d="M3 12L21 12M12 3L12 21M7.5 7.5L16.5 16.5M16.5 7.5L7.5 16.5"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
/>
|
||||
</svg>
|
||||
}
|
||||
href="/integrations/raycast"
|
||||
>
|
||||
Mem0 Raycast extension for intelligent memory management and retrieval.
|
||||
</Card>
|
||||
<Card
|
||||
title="Mastra"
|
||||
icon={
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
>
|
||||
<path
|
||||
d="M12 2L22 7L12 12L2 7L12 2Z"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M2 17L12 22L22 17"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M2 12L12 17L22 12"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
}
|
||||
href="/integrations/mastra"
|
||||
>
|
||||
Build AI agents with persistent memory using Mastra's framework and tools.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
@@ -0,0 +1,172 @@
|
||||
---
|
||||
title: AgentOps
|
||||
---
|
||||
<Snippet file="paper-release.mdx" />
|
||||
|
||||
Integrate [**Mem0**](https://github.com/mem0ai/mem0) with [AgentOps](https://agentops.ai), a comprehensive monitoring and analytics platform for AI agents. This integration enables automatic tracking and analysis of memory operations, providing insights into agent performance and memory usage patterns.
|
||||
|
||||
## Overview
|
||||
|
||||
1. Automatic monitoring of Mem0 operations and performance metrics
|
||||
2. Real-time tracking of memory add, search, and retrieval operations
|
||||
3. Analytics dashboard with memory usage patterns and insights
|
||||
4. Error tracking and debugging capabilities for memory operations
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before setting up Mem0 with AgentOps, ensure you have:
|
||||
|
||||
1. Installed the required packages:
|
||||
```bash
|
||||
pip install mem0ai agentops
|
||||
```
|
||||
|
||||
2. Valid API keys:
|
||||
- [AgentOps API Key](https://app.agentops.ai/dashboard/api-keys)
|
||||
- OpenAI API Key (for LLM operations)
|
||||
- [Mem0 API Key](https://app.mem0.ai/dashboard/api-keys) (optional, for cloud operations)
|
||||
|
||||
## Basic Integration Example
|
||||
|
||||
The following example demonstrates how to integrate Mem0 with AgentOps monitoring for comprehensive memory operation tracking:
|
||||
|
||||
```python
|
||||
#Import the required libraries for local memory management with Mem0
|
||||
from mem0 import Memory, AsyncMemory
|
||||
import os
|
||||
import asyncio
|
||||
import logging
|
||||
from dotenv import load_dotenv
|
||||
import agentops
|
||||
|
||||
#Set up environment variables for API keys
|
||||
os.environ["AGENTOPS_API_KEY"] = os.getenv("AGENTOPS_API_KEY")
|
||||
os.environ["OPENAI_API_KEY"] = os.getenv("OPENAI_API_KEY")
|
||||
|
||||
#Set up the configuration for local memory storage and define sample user data.
|
||||
local_config = {
|
||||
"llm": {
|
||||
"provider": "openai",
|
||||
"config": {
|
||||
"model": "gpt-4o-mini",
|
||||
"temperature": 0.1,
|
||||
"max_tokens": 2000,
|
||||
},
|
||||
}
|
||||
}
|
||||
user_id = "alice_demo"
|
||||
agent_id = "assistant_demo"
|
||||
run_id = "session_001"
|
||||
|
||||
sample_messages = [
|
||||
{"role": "user", "content": "I'm planning to watch a movie tonight. Any recommendations?"},
|
||||
{"role": "assistant", "content": "How about a thriller? 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.",
|
||||
},
|
||||
]
|
||||
|
||||
sample_preferences = [
|
||||
"I prefer dark roast coffee over light roast",
|
||||
"I exercise every morning at 6 AM",
|
||||
"I'm vegetarian and avoid all meat products",
|
||||
"I love reading science fiction novels",
|
||||
"I work in software engineering",
|
||||
]
|
||||
|
||||
#This function demonstrates sequential memory operations using the synchronous Memory class
|
||||
def demonstrate_sync_memory(local_config, sample_messages, sample_preferences, user_id):
|
||||
"""
|
||||
Demonstrate synchronous Memory class operations.
|
||||
"""
|
||||
|
||||
agentops.start_trace("mem0_memory_example", tags=["mem0_memory_example"])
|
||||
try:
|
||||
|
||||
memory = Memory.from_config(local_config)
|
||||
|
||||
result = memory.add(
|
||||
sample_messages, user_id=user_id, metadata={"category": "movie_preferences", "session": "demo"}
|
||||
)
|
||||
|
||||
for i, preference in enumerate(sample_preferences):
|
||||
result = memory.add(preference, user_id=user_id, metadata={"type": "preference", "index": i})
|
||||
|
||||
search_queries = [
|
||||
"What movies does the user like?",
|
||||
"What are the user's food preferences?",
|
||||
"When does the user exercise?",
|
||||
]
|
||||
|
||||
for query in search_queries:
|
||||
results = memory.search(query, user_id=user_id)
|
||||
|
||||
if results and "results" in results:
|
||||
for j, result in enumerate(results):
|
||||
print(f"Result {j+1}: {result.get('memory', 'N/A')}")
|
||||
else:
|
||||
print("No results found")
|
||||
|
||||
all_memories = memory.get_all(user_id=user_id)
|
||||
if all_memories and "results" in all_memories:
|
||||
print(f"Total memories: {len(all_memories['results'])}")
|
||||
|
||||
delete_all_result = memory.delete_all(user_id=user_id)
|
||||
print(f"Delete all result: {delete_all_result}")
|
||||
|
||||
agentops.end_trace(end_state="success")
|
||||
except Exception as e:
|
||||
agentops.end_trace(end_state="error")
|
||||
|
||||
# Execute sync demonstrations
|
||||
demonstrate_sync_memory(local_config, sample_messages, sample_preferences, user_id)
|
||||
|
||||
```
|
||||
|
||||
For detailed information on this integration, refer to the official [Agentops Mem0 integration documentation](https://docs.agentops.ai/v2/integrations/mem0).
|
||||
|
||||
|
||||
## Key Features
|
||||
|
||||
### 1. Automatic Operation Tracking
|
||||
|
||||
AgentOps automatically monitors all Mem0 operations:
|
||||
|
||||
- **Memory Operations**: Track add, search, get_all, delete operations and much more
|
||||
- **Performance Metrics**: Monitor response times and success rates
|
||||
- **Error Tracking**: Capture and analyze operation failures
|
||||
|
||||
### 2. Real-time Analytics Dashboard
|
||||
|
||||
Access comprehensive analytics through the AgentOps dashboard:
|
||||
|
||||
- **Usage Patterns**: Visualize memory usage trends over time
|
||||
- **User Behavior**: Analyze how different users interact with memory
|
||||
- **Performance Insights**: Identify bottlenecks and optimization opportunities
|
||||
|
||||
### 3. Session Management
|
||||
|
||||
Organize your monitoring with structured sessions:
|
||||
|
||||
- **Session Tracking**: Group related operations into logical sessions
|
||||
- **Success/Failure Rates**: Track session outcomes for reliability monitoring
|
||||
- **Custom Metadata**: Add context to sessions for better analysis
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Initialize Early**: Always initialize AgentOps before importing Mem0 classes
|
||||
2. **Session Management**: Use meaningful session names and end sessions appropriately
|
||||
3. **Error Handling**: Wrap operations in try-catch blocks and report failures
|
||||
4. **Tagging**: Use tags to organize different types of memory operations
|
||||
5. **Environment Separation**: Use different projects or tags for dev/staging/prod
|
||||
|
||||
## Help & Resources
|
||||
|
||||
- [AgentOps Documentation](https://docs.agentops.ai/)
|
||||
- [AgentOps Dashboard](https://app.agentops.ai/)
|
||||
- [Mem0 Platform](https://app.mem0.ai/)
|
||||
|
||||
<Snippet file="get-help.mdx" />
|
||||
|
||||
+147
-117
@@ -12,8 +12,7 @@ Before you begin, make sure you have:
|
||||
|
||||
1. Installed Livekit Agents SDK with voice dependencies of silero and deepgram:
|
||||
```bash
|
||||
pip install livekit \
|
||||
livekit-agents \
|
||||
pip install livekit-agents[voice] \
|
||||
livekit-plugins-silero \
|
||||
livekit-plugins-deepgram \
|
||||
livekit-plugins-openai
|
||||
@@ -38,7 +37,7 @@ OPENAI_API_KEY=your_openai_api_key
|
||||
|
||||
## Code Breakdown
|
||||
|
||||
Let's break down the key components of this implementation:
|
||||
Let's break down the key components of this implementation using LiveKit Agents:
|
||||
|
||||
### 1. Setting Up Dependencies and Environment
|
||||
|
||||
@@ -51,17 +50,19 @@ from typing import List, Dict, Any, Annotated
|
||||
import aiohttp
|
||||
from dotenv import load_dotenv
|
||||
from livekit.agents import (
|
||||
Agent,
|
||||
AgentSession,
|
||||
AutoSubscribe,
|
||||
JobContext,
|
||||
JobProcess,
|
||||
WorkerOptions,
|
||||
cli,
|
||||
llm,
|
||||
metrics,
|
||||
function_tool,
|
||||
RunContext,
|
||||
cli,
|
||||
WorkerOptions,
|
||||
ModelSettings,
|
||||
)
|
||||
from livekit import rtc, api
|
||||
from livekit.agents.pipeline import VoicePipelineAgent
|
||||
from livekit.plugins import deepgram, openai, silero
|
||||
from livekit.plugins.turn_detector.multilingual import MultilingualModel
|
||||
from mem0 import AsyncMemoryClient
|
||||
|
||||
# Load environment variables
|
||||
@@ -88,36 +89,45 @@ This section handles:
|
||||
### 2. Memory Enrichment Function
|
||||
|
||||
```python
|
||||
async def _enrich_with_memory(agent: VoicePipelineAgent, chat_ctx: llm.ChatContext):
|
||||
"""Add memories and Augment chat context with relevant memories"""
|
||||
async def _enrich_with_memory(chat_ctx: llm.ChatContext):
|
||||
"""Add memories and augment chat context with relevant memories"""
|
||||
if not chat_ctx.messages:
|
||||
return
|
||||
|
||||
# Store user message in Mem0
|
||||
|
||||
# Get the latest user message
|
||||
user_msg = chat_ctx.messages[-1]
|
||||
if user_msg.role != "user":
|
||||
return
|
||||
|
||||
user_content = user_msg.text_content()
|
||||
if not user_content:
|
||||
return
|
||||
|
||||
# Store user message in Mem0
|
||||
await mem0.add(
|
||||
[{"role": "user", "content": user_msg.content}],
|
||||
[{"role": "user", "content": user_content}],
|
||||
user_id=USER_ID
|
||||
)
|
||||
|
||||
|
||||
# Search for relevant memories
|
||||
results = await mem0.search(
|
||||
user_msg.content,
|
||||
user_content,
|
||||
user_id=USER_ID,
|
||||
)
|
||||
|
||||
|
||||
# Augment context with retrieved memories
|
||||
if results:
|
||||
memories = ' '.join([result["memory"] for result in results])
|
||||
logger.info(f"Enriching with memory: {memories}")
|
||||
|
||||
rag_msg = llm.ChatMessage.create(
|
||||
|
||||
# Add memory context as a assistant message
|
||||
memory_msg = llm.ChatMessage.create(
|
||||
text=f"Relevant Memory: {memories}\n",
|
||||
role="assistant",
|
||||
)
|
||||
|
||||
|
||||
# Modify chat context with retrieved memories
|
||||
chat_ctx.messages[-1] = rag_msg
|
||||
chat_ctx.messages[-1] = memory_msg
|
||||
chat_ctx.messages.append(user_msg)
|
||||
```
|
||||
|
||||
@@ -130,62 +140,45 @@ This function:
|
||||
### 3. Prewarm and Entrypoint Functions
|
||||
|
||||
```python
|
||||
def prewarm_process(proc: JobProcess):
|
||||
# Preload silero VAD in memory to speed up session start
|
||||
def prewarm_process(proc):
|
||||
"""Preload components to speed up session start"""
|
||||
proc.userdata["vad"] = silero.VAD.load()
|
||||
|
||||
async def entrypoint(ctx: JobContext):
|
||||
"""Main entrypoint for the memory-enabled voice agent"""
|
||||
|
||||
# Connect to LiveKit room
|
||||
await ctx.connect(auto_subscribe=AutoSubscribe.AUDIO_ONLY)
|
||||
|
||||
# Wait for participant
|
||||
participant = await ctx.wait_for_participant()
|
||||
|
||||
# Initialize Mem0 client
|
||||
mem0 = AsyncMemoryClient()
|
||||
|
||||
# Define initial system context
|
||||
initial_ctx = llm.ChatContext().append(
|
||||
role="system",
|
||||
text=(
|
||||
"""
|
||||
You are a helpful voice assistant.
|
||||
You are a travel guide named George and will help the user to plan a travel trip of their dreams.
|
||||
You should help the user plan for various adventures like work retreats, family vacations or solo backpacking trips.
|
||||
You should be careful to not suggest anything that would be dangerous, illegal or inappropriate.
|
||||
You can remember past interactions and use them to inform your answers.
|
||||
Use semantic memory retrieval to provide contextually relevant responses.
|
||||
"""
|
||||
),
|
||||
)
|
||||
|
||||
# Create VoicePipelineAgent with memory capabilities
|
||||
agent = VoicePipelineAgent(
|
||||
chat_ctx=initial_ctx,
|
||||
vad=silero.VAD.load(),
|
||||
# Create agent session with modern 1.0 architecture
|
||||
session = AgentSession(
|
||||
stt=deepgram.STT(),
|
||||
llm=openai.LLM(model="gpt-4o-mini"),
|
||||
tts=openai.TTS(),
|
||||
before_llm_cb=_enrich_with_memory,
|
||||
vad=silero.VAD.load(),
|
||||
turn_detection=MultilingualModel(),
|
||||
)
|
||||
|
||||
# Start agent and initial greeting
|
||||
agent.start(ctx.room, participant)
|
||||
await agent.say(
|
||||
"Hello! I'm George. Can I help you plan an upcoming trip? ",
|
||||
allow_interruptions=True
|
||||
# Create memory-enabled agent
|
||||
agent = MemoryEnabledAgent()
|
||||
|
||||
# Start the session
|
||||
await session.start(
|
||||
room=ctx.room,
|
||||
agent=agent,
|
||||
)
|
||||
|
||||
# Run the application
|
||||
if __name__ == "__main__":
|
||||
cli.run_app(WorkerOptions(entrypoint_fnc=entrypoint, prewarm_fnc=prewarm_process))
|
||||
# Initial greeting
|
||||
await session.generate_reply(
|
||||
instructions="Greet the user warmly as George the travel guide and ask how you can help them plan their next adventure."
|
||||
)
|
||||
```
|
||||
|
||||
The entrypoint function:
|
||||
- Connects to LiveKit room
|
||||
- Initializes Mem0 memory client
|
||||
- Sets up initial system context
|
||||
- Creates a VoicePipelineAgent with memory enrichment
|
||||
- Create agent session using `AgentSession` orchestrator with memory enrichment
|
||||
- Uses modern turn detection with `MultilingualModel()`
|
||||
- Starts the agent with an initial greeting
|
||||
|
||||
## Create a Memory-Enabled Voice Agent
|
||||
@@ -196,22 +189,22 @@ Now that we've explained each component, here's the complete implementation that
|
||||
import asyncio
|
||||
import logging
|
||||
import os
|
||||
from typing import List, Dict, Any, Annotated
|
||||
from typing import AsyncIterable, Any
|
||||
|
||||
import aiohttp
|
||||
from dotenv import load_dotenv
|
||||
from livekit.agents import (
|
||||
AutoSubscribe,
|
||||
Agent,
|
||||
AgentSession,
|
||||
JobContext,
|
||||
JobProcess,
|
||||
WorkerOptions,
|
||||
cli,
|
||||
llm,
|
||||
metrics,
|
||||
function_tool,
|
||||
RunContext,
|
||||
cli,
|
||||
WorkerOptions,
|
||||
ModelSettings,
|
||||
)
|
||||
from livekit import rtc, api
|
||||
from livekit.agents.pipeline import VoicePipelineAgent
|
||||
from livekit.plugins import deepgram, openai, silero
|
||||
from livekit.plugins.turn_detector.multilingual import MultilingualModel
|
||||
from mem0 import AsyncMemoryClient
|
||||
|
||||
# Load environment variables
|
||||
@@ -227,92 +220,129 @@ USER_ID = "voice_user"
|
||||
# Initialize Mem0 memory client
|
||||
mem0 = AsyncMemoryClient()
|
||||
|
||||
def prewarm_process(proc: JobProcess):
|
||||
# Preload silero VAD in memory to speed up session start
|
||||
proc.userdata["vad"] = silero.VAD.load()
|
||||
class MemoryEnabledAgent(Agent):
|
||||
"""Travel guide agent with Mem0 memory integration"""
|
||||
|
||||
async def entrypoint(ctx: JobContext):
|
||||
# Connect to LiveKit room
|
||||
await ctx.connect(auto_subscribe=AutoSubscribe.AUDIO_ONLY)
|
||||
|
||||
# Wait for participant
|
||||
participant = await ctx.wait_for_participant()
|
||||
|
||||
async def _enrich_with_memory(agent: VoicePipelineAgent, chat_ctx: llm.ChatContext):
|
||||
"""Add memories and Augment chat context with relevant memories"""
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
instructions="""
|
||||
You are a helpful voice assistant.
|
||||
You are a travel guide named George and will help the user to plan a travel trip of their dreams.
|
||||
You should help the user plan for various adventures like work retreats, family vacations or solo backpacking trips.
|
||||
You should be careful to not suggest anything that would be dangerous, illegal or inappropriate.
|
||||
You can remember past interactions and use them to inform your answers.
|
||||
Use semantic memory retrieval to provide contextually relevant responses.
|
||||
"""
|
||||
)
|
||||
|
||||
async def llm_node(
|
||||
self,
|
||||
chat_ctx: llm.ChatContext,
|
||||
tools: list[llm.FunctionTool],
|
||||
model_settings: ModelSettings,
|
||||
) -> AsyncIterable[llm.ChatChunk]:
|
||||
"""Override LLM node to add memory enrichment before inference"""
|
||||
|
||||
# Enrich context with memory before LLM inference
|
||||
await self._enrich_with_memory(chat_ctx)
|
||||
|
||||
# Call default LLM node with enriched context
|
||||
async for chunk in Agent.default.llm_node(self, chat_ctx, tools, model_settings):
|
||||
yield chunk
|
||||
|
||||
async def _enrich_with_memory(self, chat_ctx: llm.ChatContext):
|
||||
"""Add memories and augment chat context with relevant memories"""
|
||||
if not chat_ctx.messages:
|
||||
return
|
||||
|
||||
# Store user message in Mem0
|
||||
|
||||
# Get the latest user message
|
||||
user_msg = chat_ctx.messages[-1]
|
||||
if user_msg.role != "user":
|
||||
return
|
||||
|
||||
user_content = user_msg.text_content()
|
||||
if not user_content:
|
||||
return
|
||||
|
||||
# Store user message in Mem0
|
||||
await mem0.add(
|
||||
[{"role": "user", "content": user_msg.content}],
|
||||
[{"role": "user", "content": user_content}],
|
||||
user_id=USER_ID
|
||||
)
|
||||
|
||||
|
||||
# Search for relevant memories
|
||||
results = await mem0.search(
|
||||
user_msg.content,
|
||||
user_content,
|
||||
user_id=USER_ID,
|
||||
)
|
||||
|
||||
|
||||
# Augment context with retrieved memories
|
||||
if results:
|
||||
memories = ' '.join([result["memory"] for result in results])
|
||||
logger.info(f"Enriching with memory: {memories}")
|
||||
|
||||
rag_msg = llm.ChatMessage.create(
|
||||
|
||||
# Add memory context as a assistant message
|
||||
memory_msg = llm.ChatMessage.create(
|
||||
text=f"Relevant Memory: {memories}\n",
|
||||
role="assistant",
|
||||
)
|
||||
|
||||
|
||||
# Modify chat context with retrieved memories
|
||||
chat_ctx.messages[-1] = rag_msg
|
||||
chat_ctx.messages[-1] = memory_msg
|
||||
chat_ctx.messages.append(user_msg)
|
||||
|
||||
# Define initial system context
|
||||
initial_ctx = llm.ChatContext().append(
|
||||
role="system",
|
||||
text=(
|
||||
"""
|
||||
You are a helpful voice assistant.
|
||||
You are a travel guide named George and will help the user to plan a travel trip of their dreams.
|
||||
You should help the user plan for various adventures like work retreats, family vacations or solo backpacking trips.
|
||||
You should be careful to not suggest anything that would be dangerous, illegal or inappropriate.
|
||||
You can remember past interactions and use them to inform your answers.
|
||||
Use semantic memory retrieval to provide contextually relevant responses.
|
||||
"""
|
||||
),
|
||||
)
|
||||
def prewarm_process(proc):
|
||||
"""Preload components to speed up session start"""
|
||||
proc.userdata["vad"] = silero.VAD.load()
|
||||
|
||||
# Create VoicePipelineAgent with memory capabilities
|
||||
agent = VoicePipelineAgent(
|
||||
chat_ctx=initial_ctx,
|
||||
vad=silero.VAD.load(),
|
||||
async def entrypoint(ctx: JobContext):
|
||||
"""Main entrypoint for the memory-enabled voice agent"""
|
||||
|
||||
# Connect to LiveKit room
|
||||
await ctx.connect(auto_subscribe=AutoSubscribe.AUDIO_ONLY)
|
||||
|
||||
# Initialize Mem0 client
|
||||
mem0 = AsyncMemoryClient()
|
||||
|
||||
# Create agent session with modern 1.0 architecture
|
||||
session = AgentSession(
|
||||
stt=deepgram.STT(),
|
||||
llm=openai.LLM(model="gpt-4o-mini"),
|
||||
tts=openai.TTS(),
|
||||
before_llm_cb=_enrich_with_memory,
|
||||
vad=silero.VAD.load(),
|
||||
turn_detection=MultilingualModel(),
|
||||
)
|
||||
|
||||
# Start agent and initial greeting
|
||||
agent.start(ctx.room, participant)
|
||||
await agent.say(
|
||||
"Hello! I'm George. Can I help you plan an upcoming trip? ",
|
||||
# Create memory-enabled agent
|
||||
agent = MemoryEnabledAgent()
|
||||
|
||||
# Start the session
|
||||
await session.start(
|
||||
room=ctx.room,
|
||||
agent=agent,
|
||||
)
|
||||
|
||||
# Initial greeting
|
||||
await session.generate_reply(
|
||||
instructions="Greet the user warmly as George the travel guide and ask how you can help them plan their next adventure.",
|
||||
allow_interruptions=True
|
||||
)
|
||||
|
||||
# Run the application
|
||||
if __name__ == "__main__":
|
||||
cli.run_app(WorkerOptions(entrypoint_fnc=entrypoint, prewarm_fnc=prewarm_process))
|
||||
cli.run_app(WorkerOptions(
|
||||
entrypoint_fnc=entrypoint,
|
||||
prewarm_fnc=prewarm_process
|
||||
))
|
||||
```
|
||||
|
||||
## Key Features of This Implementation
|
||||
|
||||
1. **Semantic Memory Retrieval**: Uses Mem0 to store and retrieve contextually relevant memories
|
||||
2. **Voice Interaction**: Leverages LiveKit for voice communication
|
||||
2. **Voice Interaction**: Leverages LiveKit for voice communication with proper turn detection
|
||||
3. **Intelligent Context Management**: Augments conversations with past interactions
|
||||
4. **Travel Planning Specialization**: Focused on creating a helpful travel guide assistant
|
||||
5. **Function Tools**: Modern tool definition for enhanced capabilities
|
||||
|
||||
## Running the Example
|
||||
|
||||
@@ -325,13 +355,13 @@ To run this example:
|
||||
```sh
|
||||
python mem0-livekit-voice-agent.py start
|
||||
```
|
||||
5. After the script starts, you can interact with the voice agent using [Livekit's Agent Platform](https://agents-playground.livekit.io/) and Connect to the agent inorder to start conversations.
|
||||
5. After the script starts, you can interact with the voice agent using [Livekit's Agent Platform](https://agents-playground.livekit.io/) and connect to the agent inorder to start conversations.
|
||||
|
||||
## Best Practices for Voice Agents with Memory
|
||||
|
||||
1. **Context Preservation**: Store enough context with each memory for effective retrieval
|
||||
2. **Privacy Considerations**: Implement secure memory management
|
||||
3. **Relevant Memory Filtering**: Use semantic search to retrieve only the most pertinent memories
|
||||
3. **Relevant Memory Filtering**: Use semantic search to retrieve only the most relevant memories
|
||||
4. **Error Handling**: Implement robust error handling for memory operations
|
||||
|
||||
## Debugging Function Tools
|
||||
|
||||
@@ -63,7 +63,7 @@ context = {
|
||||
Set your Mem0 OSS by providing configuration details:
|
||||
|
||||
<Note type="info">
|
||||
To know more about Mem0 OSS, read [Mem0 OSS Quickstart](https://docs.mem0.ai/open-source/quickstart).
|
||||
To know more about Mem0 OSS, read [Mem0 OSS Quickstart](https://docs.mem0.ai/open-source/overview).
|
||||
</Note>
|
||||
|
||||
```python
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
---
|
||||
title: Mastra
|
||||
---
|
||||
|
||||
<Snippet file="paper-release.mdx" />
|
||||
|
||||
The [**Mastra**](https://mastra.ai/) integration demonstrates how to use Mastra's agent system with Mem0 as the memory backend through custom tools. This enables agents to remember and recall information across conversations.
|
||||
|
||||
## Overview
|
||||
|
||||
In this guide, we'll create a Mastra agent that:
|
||||
1. Uses Mem0 to store information using a memory tool
|
||||
2. Retrieves relevant memories using a search tool
|
||||
3. Provides personalized responses based on past interactions
|
||||
4. Maintains context across conversations and sessions
|
||||
|
||||
## Setup and Configuration
|
||||
|
||||
Install the required libraries:
|
||||
|
||||
```bash
|
||||
npm install @mastra/core @mastra/mem0 @ai-sdk/openai zod
|
||||
```
|
||||
|
||||
Set up your environment variables:
|
||||
|
||||
<Note>Remember to get the Mem0 API key from [Mem0 Platform](https://app.mem0.ai).</Note>
|
||||
|
||||
```bash
|
||||
MEM0_API_KEY=your-mem0-api-key
|
||||
OPENAI_API_KEY=your-openai-api-key
|
||||
```
|
||||
|
||||
## Initialize Mem0 Integration
|
||||
|
||||
Import required modules and set up the Mem0 integration:
|
||||
|
||||
```typescript
|
||||
import { Mem0Integration } from '@mastra/mem0';
|
||||
import { createTool } from '@mastra/core/tools';
|
||||
import { Agent } from '@mastra/core/agent';
|
||||
import { openai } from '@ai-sdk/openai';
|
||||
import { z } from 'zod';
|
||||
|
||||
// Initialize Mem0 integration
|
||||
const mem0 = new Mem0Integration({
|
||||
config: {
|
||||
apiKey: process.env.MEM0_API_KEY || '',
|
||||
user_id: 'alice', // Unique user identifier
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
## Create Memory Tools
|
||||
|
||||
Set up tools for memorizing and remembering information:
|
||||
|
||||
```typescript
|
||||
// Tool for remembering saved memories
|
||||
const mem0RememberTool = createTool({
|
||||
id: 'Mem0-remember',
|
||||
description: "Remember your agent memories that you've previously saved using the Mem0-memorize tool.",
|
||||
inputSchema: z.object({
|
||||
question: z.string().describe('Question used to look up the answer in saved memories.'),
|
||||
}),
|
||||
outputSchema: z.object({
|
||||
answer: z.string().describe('Remembered answer'),
|
||||
}),
|
||||
execute: async ({ context }) => {
|
||||
console.log(`Searching memory "${context.question}"`);
|
||||
const memory = await mem0.searchMemory(context.question);
|
||||
console.log(`\nFound memory "${memory}"\n`);
|
||||
|
||||
return {
|
||||
answer: memory,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
// Tool for saving new memories
|
||||
const mem0MemorizeTool = createTool({
|
||||
id: 'Mem0-memorize',
|
||||
description: 'Save information to mem0 so you can remember it later using the Mem0-remember tool.',
|
||||
inputSchema: z.object({
|
||||
statement: z.string().describe('A statement to save into memory'),
|
||||
}),
|
||||
execute: async ({ context }) => {
|
||||
console.log(`\nCreating memory "${context.statement}"\n`);
|
||||
// To reduce latency, memories can be saved async without blocking tool execution
|
||||
void mem0.createMemory(context.statement).then(() => {
|
||||
console.log(`\nMemory "${context.statement}" saved.\n`);
|
||||
});
|
||||
return { success: true };
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
## Create Mastra Agent
|
||||
|
||||
Initialize an agent with memory tools and clear instructions:
|
||||
|
||||
```typescript
|
||||
// Create an agent with memory tools
|
||||
const mem0Agent = new Agent({
|
||||
name: 'Mem0 Agent',
|
||||
instructions: `
|
||||
You are a helpful assistant that has the ability to memorize and remember facts using Mem0.
|
||||
Use the Mem0-memorize tool to save important information that might be useful later.
|
||||
Use the Mem0-remember tool to recall previously saved information when answering questions.
|
||||
`,
|
||||
model: openai('gpt-4o'),
|
||||
tools: { mem0RememberTool, mem0MemorizeTool },
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
## Key Features
|
||||
|
||||
1. **Tool-based Memory Control**: The agent decides when to save and retrieve information using specific tools
|
||||
2. **Semantic Search**: Mem0 finds relevant memories based on semantic similarity, not just exact matches
|
||||
3. **User-specific Memory Spaces**: Each user_id maintains separate memory contexts
|
||||
4. **Asynchronous Saving**: Memories are saved in the background to reduce response latency
|
||||
5. **Cross-conversation Persistence**: Memories persist across different conversation threads
|
||||
6. **Transparent Operations**: Memory operations are visible through tool usage
|
||||
|
||||
## Conclusion
|
||||
|
||||
By integrating Mastra with Mem0, you can build intelligent agents that learn and remember information across conversations. The tool-based approach provides transparency and control over memory operations, making it easy to create personalized and context-aware AI experiences.
|
||||
|
||||
## Help
|
||||
|
||||
- For more details on Mastra, visit the [Mastra documentation](https://docs.mastra.ai/).
|
||||
- For Mem0 documentation, refer to the [Mem0 Platform](https://app.mem0.ai/).
|
||||
- If you need further assistance, please feel free to reach out to us through the following methods:
|
||||
|
||||
<Snippet file="get-help.mdx" />
|
||||
@@ -0,0 +1,47 @@
|
||||
---
|
||||
title: "Raycast Extension"
|
||||
description: "Mem0 Raycast extension for intelligent memory management"
|
||||
---
|
||||
|
||||
# Mem0
|
||||
|
||||
Mem0 is a self-improving memory layer for LLM applications, enabling personalized AI experiences that save costs and delight users. This extension lets you store and retrieve text snippets using Mem0's intelligent memory system. Find Mem0 in [Raycast Store](https://www.raycast.com/dev_khant/mem0) for using it.
|
||||
|
||||
## 🚀 Getting Started
|
||||
|
||||
**Get your API Key**: You'll need a Mem0 API key to use this extension:
|
||||
|
||||
a. Sign up at [app.mem0.ai](https://app.mem0.ai)
|
||||
|
||||
b. Navigate to your API Keys page
|
||||
|
||||
c. Copy your API key
|
||||
|
||||
d. Enter this key in the extension preferences
|
||||
|
||||
**Basic Usage**:
|
||||
|
||||
- Store memories and text snippets
|
||||
- Retrieve context-aware information
|
||||
- Manage persistent user preferences
|
||||
- Search through stored memories
|
||||
|
||||
## ✨ Features
|
||||
|
||||
**Remember Everything**: Never lose important information - store notes, preferences, and conversations that your AI can recall later
|
||||
|
||||
**Smart Connections**: Automatically links related topics, just like your brain does - helping you discover useful connections
|
||||
|
||||
**Cost Saver**: Spend less on AI usage by efficiently retrieving relevant information instead of regenerating responses
|
||||
|
||||
## 🔑 How This Helps You
|
||||
|
||||
**More Personal Experience**: Your AI remembers your preferences and past conversations, making interactions feel more natural
|
||||
|
||||
**Learn Your Style**: Adapts to how you work and what you like, becoming more helpful over time
|
||||
|
||||
**No More Repetition**: Stop explaining the same things over and over - your AI remembers your context and preferences
|
||||
|
||||
---
|
||||
|
||||
<Snippet file="get-help.mdx" />
|
||||
+10
-10
@@ -37,13 +37,13 @@
|
||||
|
||||
## Features
|
||||
|
||||
[Graph Memory](https://docs.mem0.ai/features/graph-memory): Mem0's graph memory system builds relationships between entities in your data, enabling contextually relevant retrieval by analyzing connections between information points - activate it with `enable_graph=True` to enhance search results beyond direct semantic matches, ideal for applications tracking evolving relationships.
|
||||
[Advanced Retrieval](https://docs.mem0.ai/features/advanced-retrieval): Mem0 offers enhanced search capabilities through three advanced retrieval modes: keyword search (improves recall by matching specific terms), reranking (ensures most relevant results appear first using neural networks), and filtering (narrows results by specific criteria) - each can be enabled independently or in combination to optimize search precision and relevance.
|
||||
[Multimodal Support](https://docs.mem0.ai/features/multimodal-support): Mem0 extends beyond text by supporting images and documents (JPG, PNG, MDX, TXT, PDF), allowing users to integrate visual and document content through direct URLs or Base64 encoding, enhancing the memory system's ability to understand and recall information from various media types.
|
||||
[Memory Customization](https://docs.mem0.ai/features/selective-memory): Mem0 enables selective memory storage through inclusion and exclusion rules, allowing users to focus on relevant information (like specific topics) while omitting irrelevant data (such as food preferences), resulting in more efficient, accurate, and privacy-conscious AI interactions.
|
||||
[Custom Categories](https://docs.mem0.ai/features/custom-categories): Mem0 allows setting custom categories at both project level and during individual API calls, overriding default categories (like personal_details, family, sports) with more specific ones to improve memory categorization accuracy - simply provide a list of category dictionaries with descriptive definitions when adding memories.
|
||||
[Async Client](https://docs.mem0.ai/features/async-client): Mem0 provides an AsyncMemoryClient for non-blocking operations, offering the same functionality as the synchronous client (add, search, get_all, delete, etc.) but with async/await support, making it ideal for high-concurrency applications that need to perform memory operations without blocking execution.
|
||||
[Memory Export](https://docs.mem0.ai/features/memory-export): Mem0 enables exporting memories in structured formats using customizable Pydantic schemas, allowing you to transform stored memories into specific data structures by defining schemas, submitting export jobs with optional processing instructions, and retrieving the formatted data with various filtering options.
|
||||
[Graph Memory](https://docs.mem0.ai/platform/features/graph-memory): Mem0's graph memory system builds relationships between entities in your data, enabling contextually relevant retrieval by analyzing connections between information points - activate it with `enable_graph=True` to enhance search results beyond direct semantic matches, ideal for applications tracking evolving relationships.
|
||||
[Advanced Retrieval](https://docs.mem0.ai/platform/features/advanced-retrieval): Mem0 offers enhanced search capabilities through three advanced retrieval modes: keyword search (improves recall by matching specific terms), reranking (ensures most relevant results appear first using neural networks), and filtering (narrows results by specific criteria) - each can be enabled independently or in combination to optimize search precision and relevance.
|
||||
[Multimodal Support](https://docs.mem0.ai/platform/features/multimodal-support): Mem0 extends beyond text by supporting images and documents (JPG, PNG, MDX, TXT, PDF), allowing users to integrate visual and document content through direct URLs or Base64 encoding, enhancing the memory system's ability to understand and recall information from various media types.
|
||||
[Memory Customization](https://docs.mem0.ai/platform/features/selective-memory): Mem0 enables selective memory storage through inclusion and exclusion rules, allowing users to focus on relevant information (like specific topics) while omitting irrelevant data (such as food preferences), resulting in more efficient, accurate, and privacy-conscious AI interactions.
|
||||
[Custom Categories](https://docs.mem0.ai/platform/features/custom-categories): Mem0 allows setting custom categories at both project level and during individual API calls, overriding default categories (like personal_details, family, sports) with more specific ones to improve memory categorization accuracy - simply provide a list of category dictionaries with descriptive definitions when adding memories.
|
||||
[Async Client](https://docs.mem0.ai/platform/features/async-client): Mem0 provides an AsyncMemoryClient for non-blocking operations, offering the same functionality as the synchronous client (add, search, get_all, delete, etc.) but with async/await support, making it ideal for high-concurrency applications that need to perform memory operations without blocking execution.
|
||||
[Memory Export](https://docs.mem0.ai/platform/features/memory-export): Mem0 enables exporting memories in structured formats using customizable Pydantic schemas, allowing you to transform stored memories into specific data structures by defining schemas, submitting export jobs with optional processing instructions, and retrieving the formatted data with various filtering options.
|
||||
|
||||
## OSS
|
||||
|
||||
@@ -72,9 +72,9 @@
|
||||
|
||||
### Features
|
||||
|
||||
[OpenAI Compatibility](https://docs.mem0.ai/features/openai_compatibility): Mem0 offers seamless integration with OpenAI-compatible APIs, allowing developers to enhance conversational agents with structured memory by initializing with a Mem0 API key (or locally without one), supporting various LLM providers, and enabling personalized responses through user context persistence across interactions with parameters like user_id, agent_id, and custom filters.
|
||||
[Custom Fact Extraction Prompt](https://docs.mem0.ai/features/custom-fact-extraction-prompt): Mem0 enables custom fact extraction prompts to tailor information extraction for specific use cases by defining domain-specific examples and formats, allowing precise control over what information is extracted from messages - simply provide a custom prompt with few-shot examples in the config when initializing the Memory client.
|
||||
[Custom Update Memory Prompt](https://docs.mem0.ai/features/custom-update-memory-prompt): Mem0 enables customizing the update memory prompt to control how memories are modified by comparing newly retrieved facts with existing memories and determining appropriate actions (add, update, delete, or no change) based on custom logic and examples provided in the prompt configuration.
|
||||
[OpenAI Compatibility](https://docs.mem0.ai/open-source/features/openai_compatibility): Mem0 offers seamless integration with OpenAI-compatible APIs, allowing developers to enhance conversational agents with structured memory by initializing with a Mem0 API key (or locally without one), supporting various LLM providers, and enabling personalized responses through user context persistence across interactions with parameters like user_id, agent_id, and custom filters.
|
||||
[Custom Fact Extraction Prompt](https://docs.mem0.ai/open-source/features/custom-fact-extraction-prompt): Mem0 enables custom fact extraction prompts to tailor information extraction for specific use cases by defining domain-specific examples and formats, allowing precise control over what information is extracted from messages - simply provide a custom prompt with few-shot examples in the config when initializing the Memory client.
|
||||
[Custom Update Memory Prompt](https://docs.mem0.ai/open-source/features/custom-update-memory-prompt): Mem0 enables customizing the update memory prompt to control how memories are modified by comparing newly retrieved facts with existing memories and determining appropriate actions (add, update, delete, or no change) based on custom logic and examples provided in the prompt configuration.
|
||||
[REST API Server](https://docs.mem0.ai/open-source/features/rest-api): Mem0 provides a FastAPI-based REST API server that supports core operations (create/retrieve/search/update/delete memories) with OpenAPI documentation at /docs, easily deployable via Docker Compose with pre-configured databases (postgres pgvector, neo4j) - just set OPENAI_API_KEY to get started.
|
||||
[Graph Memory](https://docs.mem0.ai/open-source/graph_memory/overview): Mem0's open-source graph memory system enables building and querying relationships between entities by installing with `pip install "mem0ai[graph]"` and configuring a graph store provider (like Neo4j) - this allows for more contextual memory retrieval by combining vector and graph-based approaches to track evolving relationships between information points.
|
||||
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
---
|
||||
title: Multimodal Support
|
||||
description: Integrate images into your interactions with Mem0
|
||||
icon: "image"
|
||||
iconType: "solid"
|
||||
---
|
||||
|
||||
<Snippet file="paper-release.mdx" />
|
||||
|
||||
Mem0 extends its capabilities beyond text by supporting multimodal data. With this feature, users can seamlessly integrate images into their interactions—allowing Mem0 to extract relevant information.
|
||||
|
||||
## How It Works
|
||||
|
||||
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 multimodal inputs.
|
||||
|
||||
<CodeGroup>
|
||||
```python Python
|
||||
import os
|
||||
from mem0 import Memory
|
||||
|
||||
client = Memory()
|
||||
|
||||
messages = [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Hi, my name is Alice."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "Nice to meet you, Alice! What do you like to eat?"
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"content": {
|
||||
"type": "image_url",
|
||||
"image_url": {
|
||||
"url": "https://www.superhealthykids.com/wp-content/uploads/2021/10/best-veggie-pizza-featured-image-square-2.jpg"
|
||||
}
|
||||
}
|
||||
},
|
||||
]
|
||||
|
||||
# Calling the add method to ingest messages into the memory system
|
||||
client.add(messages, user_id="alice")
|
||||
```
|
||||
|
||||
```json Output
|
||||
{
|
||||
"results": [
|
||||
{
|
||||
"memory": "Name is Alice",
|
||||
"event": "ADD",
|
||||
"id": "7ae113a3-3cb5-46e9-b6f7-486c36391847"
|
||||
},
|
||||
{
|
||||
"memory": "Likes large pizza with toppings including cherry tomatoes, black olives, green spinach, yellow bell peppers, diced ham, and sliced mushrooms",
|
||||
"event": "ADD",
|
||||
"id": "56545065-7dee-4acf-8bf2-a5b2535aabb3"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
Using these methods, you can seamlessly incorporate various media types 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:
|
||||
|
||||
<Snippet file="get-help.mdx" />
|
||||
@@ -10,13 +10,12 @@ iconType: "solid"
|
||||
Graph Memory is a powerful feature that allows users to create and utilize complex relationships between pieces of information.
|
||||
|
||||
## Graph Memory supports the following features:
|
||||
A list of features provided by Graph Memory.
|
||||
|
||||
### Add Customize Prompt
|
||||
### Using Custom Prompts
|
||||
|
||||
Users can add a customized prompt that will be used to extract specific entities from the given input text.
|
||||
This allows for more targeted and relevant information extraction based on the user's needs.
|
||||
Here's an example of how to add a customized prompt:
|
||||
Users can specify a custom prompt that will be used to extract specific entities from the given input text.
|
||||
This allows for more targeted and relevant information extraction based on the user's needs.
|
||||
Here's an example of how to specify a custom prompt:
|
||||
|
||||
<CodeGroup>
|
||||
```python Python
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
title: Overview
|
||||
description: 'Enhance your memory system with graph-based knowledge representation and retrieval'
|
||||
icon: "database"
|
||||
icon: "info"
|
||||
iconType: "solid"
|
||||
---
|
||||
|
||||
@@ -238,16 +238,24 @@ The Mem0's graph supports the following operations:
|
||||
### Add Memories
|
||||
|
||||
<Note>
|
||||
If you are using Mem0 with Graph Memory, it is recommended to pass `user_id`. Use `userId` in NodeSDK.
|
||||
Mem0 with Graph Memory supports both "user_id" and "agent_id" parameters. You can use either or both to organize your memories. Use "userId" and "agentId" in NodeSDK.
|
||||
</Note>
|
||||
|
||||
<CodeGroup>
|
||||
```python Python
|
||||
# Using only user_id
|
||||
m.add("I like pizza", user_id="alice")
|
||||
|
||||
# Using both user_id and agent_id
|
||||
m.add("I like pizza", user_id="alice", agent_id="food-assistant")
|
||||
```
|
||||
|
||||
```typescript TypeScript
|
||||
// Using only userId
|
||||
memory.add("I like pizza", { userId: "alice" });
|
||||
|
||||
// Using both userId and agentId
|
||||
memory.add("I like pizza", { userId: "alice", agentId: "food-assistant" });
|
||||
```
|
||||
|
||||
```json Output
|
||||
@@ -260,11 +268,19 @@ memory.add("I like pizza", { userId: "alice" });
|
||||
|
||||
<CodeGroup>
|
||||
```python Python
|
||||
# Get all memories for a user
|
||||
m.get_all(user_id="alice")
|
||||
|
||||
# Get all memories for a specific agent belonging to a user
|
||||
m.get_all(user_id="alice", agent_id="food-assistant")
|
||||
```
|
||||
|
||||
```typescript TypeScript
|
||||
// Get all memories for a user
|
||||
memory.getAll({ userId: "alice" });
|
||||
|
||||
// Get all memories for a specific agent belonging to a user
|
||||
memory.getAll({ userId: "alice", agentId: "food-assistant" });
|
||||
```
|
||||
|
||||
```json Output
|
||||
@@ -277,7 +293,8 @@ memory.getAll({ userId: "alice" });
|
||||
'metadata': None,
|
||||
'created_at': '2024-08-20T14:09:27.588719-07:00',
|
||||
'updated_at': None,
|
||||
'user_id': 'alice'
|
||||
'user_id': 'alice',
|
||||
'agent_id': 'food-assistant'
|
||||
}
|
||||
],
|
||||
'entities': [
|
||||
@@ -295,11 +312,19 @@ memory.getAll({ userId: "alice" });
|
||||
|
||||
<CodeGroup>
|
||||
```python Python
|
||||
# Search memories for a user
|
||||
m.search("tell me my name.", user_id="alice")
|
||||
|
||||
# Search memories for a specific agent belonging to a user
|
||||
m.search("tell me my name.", user_id="alice", agent_id="food-assistant")
|
||||
```
|
||||
|
||||
```typescript TypeScript
|
||||
// Search memories for a user
|
||||
memory.search("tell me my name.", { userId: "alice" });
|
||||
|
||||
// Search memories for a specific agent belonging to a user
|
||||
memory.search("tell me my name.", { userId: "alice", agentId: "food-assistant" });
|
||||
```
|
||||
|
||||
```json Output
|
||||
@@ -312,7 +337,8 @@ memory.search("tell me my name.", { userId: "alice" });
|
||||
'metadata': None,
|
||||
'created_at': '2024-08-20T14:09:27.588719-07:00',
|
||||
'updated_at': None,
|
||||
'user_id': 'alice'
|
||||
'user_id': 'alice',
|
||||
'agent_id': 'food-assistant'
|
||||
}
|
||||
],
|
||||
'entities': [
|
||||
@@ -331,11 +357,19 @@ memory.search("tell me my name.", { userId: "alice" });
|
||||
|
||||
<CodeGroup>
|
||||
```python Python
|
||||
# Delete all memories for a user
|
||||
m.delete_all(user_id="alice")
|
||||
|
||||
# Delete all memories for a specific agent belonging to a user
|
||||
m.delete_all(user_id="alice", agent_id="food-assistant")
|
||||
```
|
||||
|
||||
```typescript TypeScript
|
||||
// Delete all memories for a user
|
||||
memory.deleteAll({ userId: "alice" });
|
||||
|
||||
// Delete all memories for a specific agent belonging to a user
|
||||
memory.deleteAll({ userId: "alice", agentId: "food-assistant" });
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
@@ -516,6 +550,44 @@ memory.search("Who is spiderman?", { userId: "alice123" });
|
||||
|
||||
> **Note:** The Graph Memory implementation is not standalone. You will be adding/retrieving memories to the vector store and the graph store simultaneously.
|
||||
|
||||
## Using Multiple Agents with Graph Memory
|
||||
|
||||
|
||||
When working with multiple agents, you can use the "agent_id" parameter to organize memories by both user and agent. This allows you to:
|
||||
|
||||
|
||||
1. Create agent-specific knowledge graphs
|
||||
2. Share common knowledge between agents
|
||||
3. Isolate sensitive or specialized information to specific agents
|
||||
|
||||
### Example: Multi-Agent Setup
|
||||
|
||||
<CodeGroup>
|
||||
```python Python
|
||||
# Add memories for different agents
|
||||
m.add("I prefer Italian cuisine", user_id="bob", agent_id="food-assistant")
|
||||
m.add("I'm allergic to peanuts", user_id="bob", agent_id="health-assistant")
|
||||
m.add("I live in Seattle", user_id="bob") # Shared across all agents
|
||||
|
||||
# Search within specific agent context
|
||||
food_preferences = m.search("What food do I like?", user_id="bob", agent_id="food-assistant")
|
||||
health_info = m.search("What are my allergies?", user_id="bob", agent_id="health-assistant")
|
||||
location = m.search("Where do I live?", user_id="bob") # Searches across all agents
|
||||
```
|
||||
|
||||
```typescript TypeScript
|
||||
// Add memories for different agents
|
||||
memory.add("I prefer Italian cuisine", { userId: "bob", agentId: "food-assistant" });
|
||||
memory.add("I'm allergic to peanuts", { userId: "bob", agentId: "health-assistant" });
|
||||
memory.add("I live in Seattle", { userId: "bob" }); // Shared across all agents
|
||||
|
||||
// Search within specific agent context
|
||||
const foodPreferences = memory.search("What food do I like?", { userId: "bob", agentId: "food-assistant" });
|
||||
const healthInfo = memory.search("What are my allergies?", { userId: "bob", agentId: "health-assistant" });
|
||||
const location = memory.search("Where do I live?", { userId: "bob" }); // Searches across all agents
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
If you want to use a managed version of Mem0, please check out [Mem0](https://mem0.dev/pd). If you have any questions, please feel free to reach out to us using one of the following methods:
|
||||
|
||||
<Snippet file="get-help.mdx" />
|
||||
<Snippet file="get-help.mdx" />
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
title: Node SDK
|
||||
title: Node SDK Quickstart
|
||||
description: 'Get started with Mem0 quickly!'
|
||||
icon: "node"
|
||||
iconType: "solid"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: Overview
|
||||
icon: "info"
|
||||
icon: "eye"
|
||||
iconType: "solid"
|
||||
---
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
title: Python SDK
|
||||
title: Python SDK Quickstart
|
||||
description: 'Get started with Mem0 quickly!'
|
||||
icon: "python"
|
||||
iconType: "solid"
|
||||
@@ -513,7 +513,7 @@ chat_completion = client.chat.completions.create(
|
||||
|
||||
## APIs
|
||||
|
||||
Get started with using Mem0 APIs in your applications. For more details, refer to the [Platform](/platform/quickstart.mdx).
|
||||
Get started with using Mem0 APIs in your applications. For more details, refer to the [Platform](../platform/quickstart).
|
||||
|
||||
Here is an example of how to use Mem0 APIs:
|
||||
|
||||
|
||||
+71
-55
@@ -1490,11 +1490,11 @@
|
||||
"x-code-samples": [
|
||||
{
|
||||
"lang": "Python",
|
||||
"source": "# To use the Python SDK, install the package:\n# pip install mem0ai\n\nfrom mem0 import MemoryClient\nclient = MemoryClient(api_key=\"your_api_key\", org_id=\"your_org_id\", project_id=\"your_project_id\")\n\nquery = \"What do you know about me?\"\nfilters = {\n \"AND\":[\n {\n \"user_id\":\"alex\"\n },\n {\n \"agent_id\":{\n \"in\":[\n \"travel-assistant\",\n \"customer-support\"\n ]\n }\n }\n ]\n}\nclient.search(query, version=\"v2\", filters=filters)"
|
||||
"source": "# To use the Python SDK, install the package:\n# pip install mem0ai\n\nfrom mem0 import MemoryClient\nclient = MemoryClient(api_key=\"your_api_key\", org_id=\"your_org_id\", project_id=\"your_project_id\")\n\nquery = \"What do you know about me?\"\nfilters = {\n \"OR\":[\n {\n \"user_id\":\"alex\"\n },\n {\n \"agent_id\":{\n \"in\":[\n \"travel-assistant\",\n \"customer-support\"\n ]\n }\n }\n ]\n}\nclient.search(query, version=\"v2\", filters=filters)"
|
||||
},
|
||||
{
|
||||
"lang": "JavaScript",
|
||||
"source": "// To use the JavaScript SDK, install the package:\n// npm i mem0ai\n\nimport MemoryClient from 'mem0ai';\nconst client = new MemoryClient({ apiKey: \"your-api-key\" });\n\nconst query = \"What do you know about me?\";\nconst filters = {\n AND: [\n { user_id: \"alex\" },\n { agent_id: { in: [\"travel-assistant\", \"customer-support\"] } }\n ]\n};\n\nclient.search(query, { api_version: \"v2\", filters })\n .then(result => console.log(result))\n .catch(error => console.error(error));"
|
||||
"source": "// To use the JavaScript SDK, install the package:\n// npm i mem0ai\n\nimport MemoryClient from 'mem0ai';\nconst client = new MemoryClient({ apiKey: \"your-api-key\" });\n\nconst query = \"What do you know about me?\";\nconst filters = {\n OR: [\n { user_id: \"alex\" },\n { agent_id: { in: [\"travel-assistant\", \"customer-support\"] } }\n ]\n};\n\nclient.search(query, { api_version: \"v2\", filters })\n .then(result => console.log(result))\n .catch(error => console.error(error));"
|
||||
},
|
||||
{
|
||||
"lang": "cURL",
|
||||
@@ -1769,27 +1769,27 @@
|
||||
"x-code-samples": [
|
||||
{
|
||||
"lang": "Python",
|
||||
"source": "# To use the Python SDK, install the package:\n# pip install mem0ai\n\nfrom mem0 import MemoryClient\nclient = MemoryClient(api_key=\"your_api_key\", org_id=\"your_org_id\", project_id=\"your_project_id\")\n\n# Update a memory\nmemory_id = \"<memory_id>\"\nmessage = \"Your updated memory message here\"\nclient.update(memory_id, message)"
|
||||
"source": "# To use the Python SDK, install the package:\n# pip install mem0ai\n\nfrom mem0 import MemoryClient\nclient = MemoryClient(api_key=\"your_api_key\", org_id=\"your_org_id\", project_id=\"your_project_id\")\n\n# Update a memory\nmemory_id = \"<memory_id>\"\nclient.update(\n memory_id=memory_id,\n text=\"Your updated memory message here\",\n metadata={\"category\": \"example\"}\n)"
|
||||
},
|
||||
{
|
||||
"lang": "JavaScript",
|
||||
"source": "// To use the JavaScript SDK, install the package:\n// npm i mem0ai\n\nimport MemoryClient from 'mem0ai';\nconst client = new MemoryClient({ apiKey: \"your-api-key\" });\n\n// Update a specific memory\nconst memory_id=<memory_id>\nconst message=\"Your updated memory message here\"\nclient.update(memory_id, message)\n .then(result => console.log(result))\n .catch(error => console.error(error));"
|
||||
"source": "// To use the JavaScript SDK, install the package:\n// npm i mem0ai\n\nimport MemoryClient from 'mem0ai';\nconst client = new MemoryClient({ apiKey: \"your-api-key\" });\n\n// Update a specific memory\nconst memory_id = \"<memory_id>\";\nclient.update(memory_id, { \n text: \"Your updated memory message here\",\n metadata: { category: \"example\" }\n})\n .then(result => console.log(result))\n .catch(error => console.error(error));"
|
||||
},
|
||||
{
|
||||
"lang": "cURL",
|
||||
"source": "curl --request PUT \\\n --url https://api.mem0.ai/v1/memories/{memory_id}/ \\\n --header 'Authorization: Token <api-key>' \\\n --header 'Content-Type: application/json' \\\n --data '{\"text\": \"Your updated memory text here\"}'"
|
||||
"source": "curl --request PUT \\\n --url https://api.mem0.ai/v1/memories/{memory_id}/ \\\n --header 'Authorization: Token <api-key>' \\\n --header 'Content-Type: application/json' \\\n --data '{\"text\": \"Your updated memory text here\", \"metadata\": {\"category\": \"example\"}}'"
|
||||
},
|
||||
{
|
||||
"lang": "Go",
|
||||
"source": "package main\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"net/http\"\n\t\"io/ioutil\"\n)\n\nfunc main() {\n\n\turl := \"https://api.mem0.ai/v1/memories/{memory_id}/\"\n\n\tpayload := strings.NewReader(`{\n\t\"text\": \"Your updated memory text here\"\n}`)\n\n\treq, _ := http.NewRequest(\"PUT\", url, payload)\n\n\treq.Header.Add(\"Authorization\", \"Token <api-key>\")\n\treq.Header.Add(\"Content-Type\", \"application/json\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := ioutil.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}"
|
||||
"source": "package main\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"net/http\"\n\t\"io/ioutil\"\n)\n\nfunc main() {\n\n\turl := \"https://api.mem0.ai/v1/memories/{memory_id}/\"\n\n\tpayload := strings.NewReader(`{\n\t\"text\": \"Your updated memory text here\",\n\t\"metadata\": {\n\t\t\"category\": \"example\"\n\t}\n}`)\n\n\treq, _ := http.NewRequest(\"PUT\", url, payload)\n\n\treq.Header.Add(\"Authorization\", \"Token <api-key>\")\n\treq.Header.Add(\"Content-Type\", \"application/json\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := ioutil.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}"
|
||||
},
|
||||
{
|
||||
"lang": "PHP",
|
||||
"source": "<?php\n\n$curl = curl_init();\n\ncurl_setopt_array($curl, [\n CURLOPT_URL => \"https://api.mem0.ai/v1/memories/{memory_id}/\",\n CURLOPT_RETURNTRANSFER => true,\n CURLOPT_ENCODING => \"\",\n CURLOPT_MAXREDIRS => 10,\n CURLOPT_TIMEOUT => 30,\n CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,\n CURLOPT_CUSTOMREQUEST => \"PUT\",\n CURLOPT_HTTPHEADER => [\n \"Authorization: Token <api-key>\",\n \"Content-Type: application/json\"\n ],\n CURLOPT_POSTFIELDS => json_encode({\n \"text\": \"Your updated memory text here\"\n })\n]);\n\n$response = curl_exec($curl);\n$err = curl_error($curl);\n\ncurl_close($curl);\n\nif ($err) {\n echo \"cURL Error #:\" . $err;\n} else {\n echo $response;\n}"
|
||||
"source": "<?php\n\n$curl = curl_init();\n\ncurl_setopt_array($curl, [\n CURLOPT_URL => \"https://api.mem0.ai/v1/memories/{memory_id}/\",\n CURLOPT_RETURNTRANSFER => true,\n CURLOPT_ENCODING => \"\",\n CURLOPT_MAXREDIRS => 10,\n CURLOPT_TIMEOUT => 30,\n CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,\n CURLOPT_CUSTOMREQUEST => \"PUT\",\n CURLOPT_HTTPHEADER => [\n \"Authorization: Token <api-key>\",\n \"Content-Type: application/json\"\n ],\n CURLOPT_POSTFIELDS => json_encode([\n \"text\" => \"Your updated memory text here\",\n \"metadata\" => [\"category\" => \"example\"]\n ])\n]);\n\n$response = curl_exec($curl);\n$err = curl_error($curl);\n\ncurl_close($curl);\n\nif ($err) {\n echo \"cURL Error #:\" . $err;\n} else {\n echo $response;\n}"
|
||||
},
|
||||
{
|
||||
"lang": "Java",
|
||||
"source": "HttpResponse<String> response = Unirest.put(\"https://api.mem0.ai/v1/memories/{memory_id}/\")\n .header(\"Authorization\", \"Token <api-key>\")\n .header(\"Content-Type\", \"application/json\")\n .body({\"text\": \"Your updated memory text here\"})\n .asString();"
|
||||
"source": "HttpResponse<String> response = Unirest.put(\"https://api.mem0.ai/v1/memories/{memory_id}/\")\n .header(\"Authorization\", \"Token <api-key>\")\n .header(\"Content-Type\", \"application/json\")\n .body(\"{\\\"text\\\": \\\"Your updated memory text here\\\", \\\"metadata\\\": {\\\"category\\\": \\\"example\\\"}}\")\n .asString();"
|
||||
}
|
||||
],
|
||||
"x-codegen-request-body-name": "data"
|
||||
@@ -2316,6 +2316,11 @@
|
||||
"message": {
|
||||
"type": "string",
|
||||
"example": "Organization created successfully."
|
||||
},
|
||||
"org_id": {
|
||||
"type": "string",
|
||||
"format": "uuid",
|
||||
"description": "Unique identifier for the organization"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2722,13 +2727,13 @@
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"username",
|
||||
"email",
|
||||
"role"
|
||||
],
|
||||
"properties": {
|
||||
"username": {
|
||||
"email": {
|
||||
"type": "string",
|
||||
"description": "Username of the member whose role is to be updated"
|
||||
"description": "Email of the member whose role is to be updated"
|
||||
},
|
||||
"role": {
|
||||
"type": "string",
|
||||
@@ -2798,27 +2803,27 @@
|
||||
"x-code-samples": [
|
||||
{
|
||||
"lang": "Python",
|
||||
"source": "import requests\n\nurl = \"https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/members/\"\n\npayload = {\n \"username\": \"<string>\",\n \"role\": \"<string>\"\n}\nheaders = {\n \"Authorization\": \"<api-key>\",\n \"Content-Type\": \"application/json\"\n}\n\nresponse = requests.request(\"PUT\", url, json=payload, headers=headers)\n\nprint(response.text)"
|
||||
"source": "import requests\n\nurl = \"https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/members/\"\n\npayload = {\n \"email\": \"<string>\",\n \"role\": \"<string>\"\n}\nheaders = {\n \"Authorization\": \"<api-key>\",\n \"Content-Type\": \"application/json\"\n}\n\nresponse = requests.request(\"PUT\", url, json=payload, headers=headers)\n\nprint(response.text)"
|
||||
},
|
||||
{
|
||||
"lang": "JavaScript",
|
||||
"source": "const options = {\n method: 'PUT',\n headers: {Authorization: 'Token <api-key>', 'Content-Type': 'application/json'},\n body: '{\"username\":\"<string>\",\"role\":\"<string>\"}'\n};\n\nfetch('https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/members/', options)\n .then(response => response.json())\n .then(response => console.log(response))\n .catch(err => console.error(err));"
|
||||
"source": "const options = {\n method: 'PUT',\n headers: {Authorization: 'Token <api-key>', 'Content-Type': 'application/json'},\n body: '{\"email\":\"<string>\",\"role\":\"<string>\"}'\n};\n\nfetch('https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/members/', options)\n .then(response => response.json())\n .then(response => console.log(response))\n .catch(err => console.error(err));"
|
||||
},
|
||||
{
|
||||
"lang": "cURL",
|
||||
"source": "curl --request PUT \\\n --url https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/members/ \\\n --header 'Authorization: Token <api-key>' \\\n --header 'Content-Type: application/json' \\\n --data '{\n \"username\": \"<string>\",\n \"role\": \"<string>\"\n}'"
|
||||
"source": "curl --request PUT \\\n --url https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/members/ \\\n --header 'Authorization: Token <api-key>' \\\n --header 'Content-Type: application/json' \\\n --data '{\n \"email\": \"<string>\",\n \"role\": \"<string>\"\n}'"
|
||||
},
|
||||
{
|
||||
"lang": "Go",
|
||||
"source": "package main\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"net/http\"\n\t\"io/ioutil\"\n)\n\nfunc main() {\n\n\turl := \"https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/members/\"\n\n\tpayload := strings.NewReader(\"{\n \\\"username\\\": \\\"<string>\\\",\n \\\"role\\\": \\\"<string>\\\"\n}\")\n\n\treq, _ := http.NewRequest(\"PUT\", url, payload)\n\n\treq.Header.Add(\"Authorization\", \"Token <api-key>\")\n\treq.Header.Add(\"Content-Type\", \"application/json\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := ioutil.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}"
|
||||
"source": "package main\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"net/http\"\n\t\"io/ioutil\"\n)\n\nfunc main() {\n\n\turl := \"https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/members/\"\n\n\tpayload := strings.NewReader(\"{\n \\\"email\\\": \\\"<string>\\\",\n \\\"role\\\": \\\"<string>\\\"\n}\")\n\n\treq, _ := http.NewRequest(\"PUT\", url, payload)\n\n\treq.Header.Add(\"Authorization\", \"Token <api-key>\")\n\treq.Header.Add(\"Content-Type\", \"application/json\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := ioutil.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}"
|
||||
},
|
||||
{
|
||||
"lang": "PHP",
|
||||
"source": "<?php\n\n$curl = curl_init();\n\ncurl_setopt_array($curl, [\n CURLOPT_URL => \"https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/members/\",\n CURLOPT_RETURNTRANSFER => true,\n CURLOPT_ENCODING => \"\",\n CURLOPT_MAXREDIRS => 10,\n CURLOPT_TIMEOUT => 30,\n CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,\n CURLOPT_CUSTOMREQUEST => \"PUT\",\n CURLOPT_POSTFIELDS => \"{\n \\\"username\\\": \\\"<string>\\\",\n \\\"role\\\": \\\"<string>\\\"\n}\",\n CURLOPT_HTTPHEADER => [\n \"Authorization: Token <api-key>\",\n \"Content-Type: application/json\"\n ],\n]);\n\n$response = curl_exec($curl);\n$err = curl_error($curl);\n\ncurl_close($curl);\n\nif ($err) {\n echo \"cURL Error #:\" . $err;\n} else {\n echo $response;\n}"
|
||||
"source": "<?php\n\n$curl = curl_init();\n\ncurl_setopt_array($curl, [\n CURLOPT_URL => \"https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/members/\",\n CURLOPT_RETURNTRANSFER => true,\n CURLOPT_ENCODING => \"\",\n CURLOPT_MAXREDIRS => 10,\n CURLOPT_TIMEOUT => 30,\n CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,\n CURLOPT_CUSTOMREQUEST => \"PUT\",\n CURLOPT_POSTFIELDS => \"{\n \\\"email\\\": \\\"<string>\\\",\n \\\"role\\\": \\\"<string>\\\"\n}\",\n CURLOPT_HTTPHEADER => [\n \"Authorization: Token <api-key>\",\n \"Content-Type: application/json\"\n ],\n]);\n\n$response = curl_exec($curl);\n$err = curl_error($curl);\n\ncurl_close($curl);\n\nif ($err) {\n echo \"cURL Error #:\" . $err;\n} else {\n echo $response;\n}"
|
||||
},
|
||||
{
|
||||
"lang": "Java",
|
||||
"source": "HttpResponse<String> response = Unirest.put(\"https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/members/\")\n .header(\"Authorization\", \"Token <api-key>\")\n .header(\"Content-Type\", \"application/json\")\n .body(\"{\n \\\"username\\\": \\\"<string>\\\",\n \\\"role\\\": \\\"<string>\\\"\n}\")\n .asString();"
|
||||
"source": "HttpResponse<String> response = Unirest.put(\"https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/members/\")\n .header(\"Authorization\", \"Token <api-key>\")\n .header(\"Content-Type\", \"application/json\")\n .body(\"{\n \\\"email\\\": \\\"<string>\\\",\n \\\"role\\\": \\\"<string>\\\"\n}\")\n .asString();"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -2847,13 +2852,13 @@
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"username",
|
||||
"email",
|
||||
"role"
|
||||
],
|
||||
"properties": {
|
||||
"username": {
|
||||
"email": {
|
||||
"type": "string",
|
||||
"description": "Username of the member to be added"
|
||||
"description": "Email of the member to be added"
|
||||
},
|
||||
"role": {
|
||||
"type": "string",
|
||||
@@ -2923,23 +2928,23 @@
|
||||
"x-code-samples": [
|
||||
{
|
||||
"lang": "Python",
|
||||
"source": "import requests\n\nurl = \"https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/members/\"\n\npayload = {\n \"username\": \"<string>\",\n \"role\": \"<string>\"\n}\nheaders = {\n \"Authorization\": \"<api-key>\",\n \"Content-Type\": \"application/json\"\n}\n\nresponse = requests.request(\"POST\", url, json=payload, headers=headers)\n\nprint(response.text)"
|
||||
"source": "import requests\n\nurl = \"https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/members/\"\n\npayload = {\n \"email\": \"<string>\",\n \"role\": \"<string>\"\n}\nheaders = {\n \"Authorization\": \"<api-key>\",\n \"Content-Type\": \"application/json\"\n}\n\nresponse = requests.request(\"POST\", url, json=payload, headers=headers)\n\nprint(response.text)"
|
||||
},
|
||||
{
|
||||
"lang": "JavaScript",
|
||||
"source": "const options = {\n method: 'POST',\n headers: {Authorization: 'Token <api-key>', 'Content-Type': 'application/json'},\n body: '{\"username\":\"<string>\",\"role\":\"<string>\"}'\n};\n\nfetch('https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/members/', options)\n .then(response => response.json())\n .then(response => console.log(response))\n .catch(err => console.error(err));"
|
||||
"source": "const options = {\n method: 'POST',\n headers: {Authorization: 'Token <api-key>', 'Content-Type': 'application/json'},\n body: '{\"email\":\"<string>\",\"role\":\"<string>\"}'\n};\n\nfetch('https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/members/', options)\n .then(response => response.json())\n .then(response => console.log(response))\n .catch(err => console.error(err));"
|
||||
},
|
||||
{
|
||||
"lang": "cURL",
|
||||
"source": "curl --request POST \\\n --url https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/members/ \\\n --header 'Authorization: Token <api-key>' \\\n --header 'Content-Type: application/json' \\\n --data '{\n \"username\": \"<string>\",\n \"role\": \"<string>\"\n}'"
|
||||
"source": "curl --request POST \\\n --url https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/members/ \\\n --header 'Authorization: Token <api-key>' \\\n --header 'Content-Type: application/json' \\\n --data '{\n \"email\": \"<string>\",\n \"role\": \"<string>\"\n}'"
|
||||
},
|
||||
{
|
||||
"lang": "Go",
|
||||
"source": "package main\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"net/http\"\n\t\"io/ioutil\"\n)\n\nfunc main() {\n\n\turl := \"https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/members/\"\n\n\tpayload := strings.NewReader(\"{\n \\\"username\\\": \\\"<string>\\\",\n \\\"role\\\": \\\"<string>\\\"\n}\")\n\n\treq, _ := http.NewRequest(\"POST\", url, payload)\n\n\treq.Header.Add(\"Authorization\", \"Token <api-key>\")\n\treq.Header.Add(\"Content-Type\", \"application/json\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := ioutil.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}"
|
||||
"source": "package main\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"net/http\"\n\t\"io/ioutil\"\n)\n\nfunc main() {\n\n\turl := \"https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/members/\"\n\n\tpayload := strings.NewReader(\"{\n \\\"email\\\": \\\"<string>\\\",\n \\\"role\\\": \\\"<string>\\\"\n}\")\n\n\treq, _ := http.NewRequest(\"POST\", url, payload)\n\n\treq.Header.Add(\"Authorization\", \"Token <api-key>\")\n\treq.Header.Add(\"Content-Type\", \"application/json\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := ioutil.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}"
|
||||
},
|
||||
{
|
||||
"lang": "PHP",
|
||||
"source": "<?php\n\n$curl = curl_init();\n\ncurl_setopt_array($curl, [\n CURLOPT_URL => \"https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/members/\",\n CURLOPT_RETURNTRANSFER => true,\n CURLOPT_ENCODING => \"\",\n CURLOPT_MAXREDIRS => 10,\n CURLOPT_TIMEOUT => 30,\n CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,\n CURLOPT_CUSTOMREQUEST => \"POST\",\n CURLOPT_POSTFIELDS => \"{\n \\\"username\\\": \\\"<string>\\\",\n \\\"role\\\": \\\"<string>\\\"\n}\",\n CURLOPT_HTTPHEADER => [\n \"Authorization: Token <api-key>\",\n \"Content-Type: application/json\"\n ],\n]);\n\n$response = curl_exec($curl);\n$err = curl_error($curl);\n\ncurl_close($curl);\n\nif ($err) {\n echo \"cURL Error #:\" . $err;\n} else {\n echo $response;\n}"
|
||||
"source": "<?php\n\n$curl = curl_init();\n\ncurl_setopt_array($curl, [\n CURLOPT_URL => \"https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/members/\",\n CURLOPT_RETURNTRANSFER => true,\n CURLOPT_ENCODING => \"\",\n CURLOPT_MAXREDIRS => 10,\n CURLOPT_TIMEOUT => 30,\n CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,\n CURLOPT_CUSTOMREQUEST => \"POST\",\n CURLOPT_POSTFIELDS => \"{\n \\\"email\\\": \\\"<string>\\\",\n \\\"role\\\": \\\"<string>\\\"\n}\",\n CURLOPT_HTTPHEADER => [\n \"Authorization: Token <api-key>\",\n \"Content-Type: application/json\"\n ],\n]);\n\n$response = curl_exec($curl);\n$err = curl_error($curl);\n\ncurl_close($curl);\n\nif ($err) {\n echo \"cURL Error #:\" . $err;\n} else {\n echo $response;\n}"
|
||||
},
|
||||
{
|
||||
"lang": "Java",
|
||||
@@ -2971,12 +2976,12 @@
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"username"
|
||||
"email"
|
||||
],
|
||||
"properties": {
|
||||
"username": {
|
||||
"email": {
|
||||
"type": "string",
|
||||
"description": "Username of the member to be removed"
|
||||
"description": "Email of the member to be removed"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3020,27 +3025,27 @@
|
||||
"x-code-samples": [
|
||||
{
|
||||
"lang": "Python",
|
||||
"source": "import requests\n\nurl = \"https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/members/\"\n\npayload = {\"username\": \"<string>\"}\nheaders = {\n \"Authorization\": \"<api-key>\",\n \"Content-Type\": \"application/json\"\n}\n\nresponse = requests.request(\"DELETE\", url, json=payload, headers=headers)\n\nprint(response.text)"
|
||||
"source": "import requests\n\nurl = \"https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/members/\"\n\npayload = {\"email\": \"<string>\"}\nheaders = {\n \"Authorization\": \"<api-key>\",\n \"Content-Type\": \"application/json\"\n}\n\nresponse = requests.request(\"DELETE\", url, json=payload, headers=headers)\n\nprint(response.text)"
|
||||
},
|
||||
{
|
||||
"lang": "JavaScript",
|
||||
"source": "const options = {\n method: 'DELETE',\n headers: {Authorization: 'Token <api-key>', 'Content-Type': 'application/json'},\n body: '{\"username\":\"<string>\"}'\n};\n\nfetch('https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/members/', options)\n .then(response => response.json())\n .then(response => console.log(response))\n .catch(err => console.error(err));"
|
||||
"source": "const options = {\n method: 'DELETE',\n headers: {Authorization: 'Token <api-key>', 'Content-Type': 'application/json'},\n body: '{\"email\":\"<string>\"}'\n};\n\nfetch('https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/members/', options)\n .then(response => response.json())\n .then(response => console.log(response))\n .catch(err => console.error(err));"
|
||||
},
|
||||
{
|
||||
"lang": "cURL",
|
||||
"source": "curl --request DELETE \\\n --url https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/members/ \\\n --header 'Authorization: Token <api-key>' \\\n --header 'Content-Type: application/json' \\\n --data '{\n \"username\": \"<string>\"\n}'"
|
||||
"source": "curl --request DELETE \\\n --url https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/members/ \\\n --header 'Authorization: Token <api-key>' \\\n --header 'Content-Type: application/json' \\\n --data '{\n \"email\": \"<string>\"\n}'"
|
||||
},
|
||||
{
|
||||
"lang": "Go",
|
||||
"source": "package main\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"net/http\"\n\t\"io/ioutil\"\n)\n\nfunc main() {\n\n\turl := \"https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/members/\"\n\n\tpayload := strings.NewReader(\"{\n \\\"username\\\": \\\"<string>\\\"\n}\")\n\n\treq, _ := http.NewRequest(\"DELETE\", url, payload)\n\n\treq.Header.Add(\"Authorization\", \"Token <api-key>\")\n\treq.Header.Add(\"Content-Type\", \"application/json\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := ioutil.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}"
|
||||
"source": "package main\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"net/http\"\n\t\"io/ioutil\"\n)\n\nfunc main() {\n\n\turl := \"https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/members/\"\n\n\tpayload := strings.NewReader(\"{\n \\\"email\\\": \\\"<string>\\\"\n}\")\n\n\treq, _ := http.NewRequest(\"DELETE\", url, payload)\n\n\treq.Header.Add(\"Authorization\", \"Token <api-key>\")\n\treq.Header.Add(\"Content-Type\", \"application/json\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := ioutil.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}"
|
||||
},
|
||||
{
|
||||
"lang": "PHP",
|
||||
"source": "<?php\n\n$curl = curl_init();\n\ncurl_setopt_array($curl, [\n CURLOPT_URL => \"https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/members/\",\n CURLOPT_RETURNTRANSFER => true,\n CURLOPT_ENCODING => \"\",\n CURLOPT_MAXREDIRS => 10,\n CURLOPT_TIMEOUT => 30,\n CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,\n CURLOPT_CUSTOMREQUEST => \"DELETE\",\n CURLOPT_POSTFIELDS => \"{\n \\\"username\\\": \\\"<string>\\\"\n}\",\n CURLOPT_HTTPHEADER => [\n \"Authorization: Token <api-key>\",\n \"Content-Type: application/json\"\n ],\n]);\n\n$response = curl_exec($curl);\n$err = curl_error($curl);\n\ncurl_close($curl);\n\nif ($err) {\n echo \"cURL Error #:\" . $err;\n} else {\n echo $response;\n}"
|
||||
"source": "<?php\n\n$curl = curl_init();\n\ncurl_setopt_array($curl, [\n CURLOPT_URL => \"https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/members/\",\n CURLOPT_RETURNTRANSFER => true,\n CURLOPT_ENCODING => \"\",\n CURLOPT_MAXREDIRS => 10,\n CURLOPT_TIMEOUT => 30,\n CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,\n CURLOPT_CUSTOMREQUEST => \"DELETE\",\n CURLOPT_POSTFIELDS => \"{\n \\\"email\\\": \\\"<string>\\\"\n}\",\n CURLOPT_HTTPHEADER => [\n \"Authorization: Token <api-key>\",\n \"Content-Type: application/json\"\n ],\n]);\n\n$response = curl_exec($curl);\n$err = curl_error($curl);\n\ncurl_close($curl);\n\nif ($err) {\n echo \"cURL Error #:\" . $err;\n} else {\n echo $response;\n}"
|
||||
},
|
||||
{
|
||||
"lang": "Java",
|
||||
"source": "HttpResponse<String> response = Unirest.delete(\"https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/members/\")\n .header(\"Authorization\", \"Token <api-key>\")\n .header(\"Content-Type\", \"application/json\")\n .body(\"{\n \\\"username\\\": \\\"<string>\\\"\n}\")\n .asString();"
|
||||
"source": "HttpResponse<String> response = Unirest.delete(\"https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/members/\")\n .header(\"Authorization\", \"Token <api-key>\")\n .header(\"Content-Type\", \"application/json\")\n .body(\"{\n \\\"email\\\": \\\"<string>\\\"\n}\")\n .asString();"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -3199,6 +3204,11 @@
|
||||
"message": {
|
||||
"type": "string",
|
||||
"example": "Project created successfully."
|
||||
},
|
||||
"project_id": {
|
||||
"type": "string",
|
||||
"format": "uuid",
|
||||
"description": "Unique identifier for the project"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3753,13 +3763,13 @@
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"username",
|
||||
"email",
|
||||
"role"
|
||||
],
|
||||
"properties": {
|
||||
"username": {
|
||||
"email": {
|
||||
"type": "string",
|
||||
"description": "Username of the member to be added"
|
||||
"description": "Email of the member to be added"
|
||||
},
|
||||
"role": {
|
||||
"type": "string",
|
||||
@@ -3823,27 +3833,27 @@
|
||||
"x-code-samples": [
|
||||
{
|
||||
"lang": "Python",
|
||||
"source": "import requests\n\nurl = \"https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/projects/{project_id}/members/\"\n\npayload = {\n \"username\": \"<string>\",\n \"role\": \"<string>\"\n}\nheaders = {\n \"Authorization\": \"<api-key>\",\n \"Content-Type\": \"application/json\"\n}\n\nresponse = requests.request(\"POST\", url, json=payload, headers=headers)\n\nprint(response.text)"
|
||||
"source": "import requests\n\nurl = \"https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/projects/{project_id}/members/\"\n\npayload = {\n \"email\": \"<string>\",\n \"role\": \"<string>\"\n}\nheaders = {\n \"Authorization\": \"<api-key>\",\n \"Content-Type\": \"application/json\"\n}\n\nresponse = requests.request(\"POST\", url, json=payload, headers=headers)\n\nprint(response.text)"
|
||||
},
|
||||
{
|
||||
"lang": "JavaScript",
|
||||
"source": "const options = {\n method: 'POST',\n headers: {Authorization: 'Token <api-key>', 'Content-Type': 'application/json'},\n body: '{\"username\":\"<string>\",\"role\":\"<string>\"}'\n};\n\nfetch('https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/projects/{project_id}/members/', options)\n .then(response => response.json())\n .then(response => console.log(response))\n .catch(err => console.error(err));"
|
||||
"source": "const options = {\n method: 'POST',\n headers: {Authorization: 'Token <api-key>', 'Content-Type': 'application/json'},\n body: '{\"email\":\"<string>\",\"role\":\"<string>\"}'\n};\n\nfetch('https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/projects/{project_id}/members/', options)\n .then(response => response.json())\n .then(response => console.log(response))\n .catch(err => console.error(err));"
|
||||
},
|
||||
{
|
||||
"lang": "cURL",
|
||||
"source": "curl --request POST \\\n --url https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/projects/{project_id}/members/ \\\n --header 'Authorization: Token <api-key>' \\\n --header 'Content-Type: application/json' \\\n --data '{\n \"username\": \"<string>\",\n \"role\": \"<string>\"\n}'"
|
||||
"source": "curl --request POST \\\n --url https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/projects/{project_id}/members/ \\\n --header 'Authorization: Token <api-key>' \\\n --header 'Content-Type: application/json' \\\n --data '{\n \"email\": \"<string>\",\n \"role\": \"<string>\"\n}'"
|
||||
},
|
||||
{
|
||||
"lang": "Go",
|
||||
"source": "package main\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"net/http\"\n\t\"io/ioutil\"\n)\n\nfunc main() {\n\n\turl := \"https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/projects/{project_id}/members/\"\n\n\tpayload := strings.NewReader(\"{\n \\\"username\\\": \\\"<string>\\\",\n \\\"role\\\": \\\"<string>\\\"\n}\")\n\n\treq, _ := http.NewRequest(\"POST\", url, payload)\n\n\treq.Header.Add(\"Authorization\", \"Token <api-key>\")\n\treq.Header.Add(\"Content-Type\", \"application/json\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := ioutil.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}"
|
||||
"source": "package main\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"net/http\"\n\t\"io/ioutil\"\n)\n\nfunc main() {\n\n\turl := \"https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/projects/{project_id}/members/\"\n\n\tpayload := strings.NewReader(\"{\n \\\"email\\\": \\\"<string>\\\",\n \\\"role\\\": \\\"<string>\\\"\n}\")\n\n\treq, _ := http.NewRequest(\"POST\", url, payload)\n\n\treq.Header.Add(\"Authorization\", \"Token <api-key>\")\n\treq.Header.Add(\"Content-Type\", \"application/json\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := ioutil.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}"
|
||||
},
|
||||
{
|
||||
"lang": "PHP",
|
||||
"source": "<?php\n\n$curl = curl_init();\n\ncurl_setopt_array($curl, [\n CURLOPT_URL => \"https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/projects/{project_id}/members/\",\n CURLOPT_RETURNTRANSFER => true,\n CURLOPT_ENCODING => \"\",\n CURLOPT_MAXREDIRS => 10,\n CURLOPT_TIMEOUT => 30,\n CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,\n CURLOPT_CUSTOMREQUEST => \"POST\",\n CURLOPT_POSTFIELDS => \"{\n \\\"username\\\": \\\"<string>\\\",\n \\\"role\\\": \\\"<string>\\\"\n}\",\n CURLOPT_HTTPHEADER => [\n \"Authorization: Token <api-key>\",\n \"Content-Type: application/json\"\n ],\n]);\n\n$response = curl_exec($curl);\n$err = curl_error($curl);\n\ncurl_close($curl);\n\nif ($err) {\n echo \"cURL Error #:\" . $err;\n} else {\n echo $response;\n}"
|
||||
"source": "<?php\n\n$curl = curl_init();\n\ncurl_setopt_array($curl, [\n CURLOPT_URL => \"https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/projects/{project_id}/members/\",\n CURLOPT_RETURNTRANSFER => true,\n CURLOPT_ENCODING => \"\",\n CURLOPT_MAXREDIRS => 10,\n CURLOPT_TIMEOUT => 30,\n CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,\n CURLOPT_CUSTOMREQUEST => \"POST\",\n CURLOPT_POSTFIELDS => \"{\n \\\"email\\\": \\\"<string>\\\",\n \\\"role\\\": \\\"<string>\\\"\n}\",\n CURLOPT_HTTPHEADER => [\n \"Authorization: Token <api-key>\",\n \"Content-Type: application/json\"\n ],\n]);\n\n$response = curl_exec($curl);\n$err = curl_error($curl);\n\ncurl_close($curl);\n\nif ($err) {\n echo \"cURL Error #:\" . $err;\n} else {\n echo $response;\n}"
|
||||
},
|
||||
{
|
||||
"lang": "Java",
|
||||
"source": "HttpResponse<String> response = Unirest.post(\"https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/projects/{project_id}/members/\")\n .header(\"Authorization\", \"Token <api-key>\")\n .header(\"Content-Type\", \"application/json\")\n .body(\"{\n \\\"username\\\": \\\"<string>\\\",\n \\\"role\\\": \\\"<string>\\\"\n}\")\n .asString();"
|
||||
"source": "HttpResponse<String> response = Unirest.post(\"https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/projects/{project_id}/members/\")\n .header(\"Authorization\", \"Token <api-key>\")\n .header(\"Content-Type\", \"application/json\")\n .body(\"{\n \\\"email\\\": \\\"<string>\\\",\n \\\"role\\\": \\\"<string>\\\"\n}\")\n .asString();"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -3881,13 +3891,13 @@
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"username",
|
||||
"email",
|
||||
"role"
|
||||
],
|
||||
"properties": {
|
||||
"username": {
|
||||
"email": {
|
||||
"type": "string",
|
||||
"description": "Username of the member to be updated"
|
||||
"description": "Email of the member to be updated"
|
||||
},
|
||||
"role": {
|
||||
"type": "string",
|
||||
@@ -3951,27 +3961,27 @@
|
||||
"x-code-samples": [
|
||||
{
|
||||
"lang": "Python",
|
||||
"source": "import requests\n\nurl = \"https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/projects/{project_id}/members/\"\n\npayload = {\n \"username\": \"<string>\",\n \"role\": \"<string>\"\n}\nheaders = {\n \"Authorization\": \"<api-key>\",\n \"Content-Type\": \"application/json\"\n}\n\nresponse = requests.request(\"PUT\", url, json=payload, headers=headers)\n\nprint(response.text)"
|
||||
"source": "import requests\n\nurl = \"https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/projects/{project_id}/members/\"\n\npayload = {\n \"email\": \"<string>\",\n \"role\": \"<string>\"\n}\nheaders = {\n \"Authorization\": \"<api-key>\",\n \"Content-Type\": \"application/json\"\n}\n\nresponse = requests.request(\"PUT\", url, json=payload, headers=headers)\n\nprint(response.text)"
|
||||
},
|
||||
{
|
||||
"lang": "JavaScript",
|
||||
"source": "const options = {\n method: 'PUT',\n headers: {Authorization: 'Token <api-key>', 'Content-Type': 'application/json'},\n body: '{\"username\":\"<string>\",\"role\":\"<string>\"}'\n};\n\nfetch('https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/projects/{project_id}/members/', options)\n .then(response => response.json())\n .then(response => console.log(response))\n .catch(err => console.error(err));"
|
||||
"source": "const options = {\n method: 'PUT',\n headers: {Authorization: 'Token <api-key>', 'Content-Type': 'application/json'},\n body: '{\"email\":\"<string>\",\"role\":\"<string>\"}'\n};\n\nfetch('https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/projects/{project_id}/members/', options)\n .then(response => response.json())\n .then(response => console.log(response))\n .catch(err => console.error(err));"
|
||||
},
|
||||
{
|
||||
"lang": "cURL",
|
||||
"source": "curl --request PUT \\\n --url https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/projects/{project_id}/members/ \\\n --header 'Authorization: Token <api-key>' \\\n --header 'Content-Type: application/json' \\\n --data '{\n \"username\": \"<string>\",\n \"role\": \"<string>\"\n}'"
|
||||
"source": "curl --request PUT \\\n --url https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/projects/{project_id}/members/ \\\n --header 'Authorization: Token <api-key>' \\\n --header 'Content-Type: application/json' \\\n --data '{\n \"email\": \"<string>\",\n \"role\": \"<string>\"\n}'"
|
||||
},
|
||||
{
|
||||
"lang": "Go",
|
||||
"source": "package main\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"net/http\"\n\t\"io/ioutil\"\n)\n\nfunc main() {\n\n\turl := \"https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/projects/{project_id}/members/\"\n\n\tpayload := strings.NewReader(\"{\n \\\"username\\\": \\\"<string>\\\",\n \\\"role\\\": \\\"<string>\\\"\n}\")\n\n\treq, _ := http.NewRequest(\"PUT\", url, payload)\n\n\treq.Header.Add(\"Authorization\", \"Token <api-key>\")\n\treq.Header.Add(\"Content-Type\", \"application/json\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := ioutil.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}"
|
||||
"source": "package main\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"net/http\"\n\t\"io/ioutil\"\n)\n\nfunc main() {\n\n\turl := \"https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/projects/{project_id}/members/\"\n\n\tpayload := strings.NewReader(\"{\n \\\"email\\\": \\\"<string>\\\",\n \\\"role\\\": \\\"<string>\\\"\n}\")\n\n\treq, _ := http.NewRequest(\"PUT\", url, payload)\n\n\treq.Header.Add(\"Authorization\", \"Token <api-key>\")\n\treq.Header.Add(\"Content-Type\", \"application/json\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := ioutil.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}"
|
||||
},
|
||||
{
|
||||
"lang": "PHP",
|
||||
"source": "<?php\n\n$curl = curl_init();\n\ncurl_setopt_array($curl, [\n CURLOPT_URL => \"https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/projects/{project_id}/members/\",\n CURLOPT_RETURNTRANSFER => true,\n CURLOPT_ENCODING => \"\",\n CURLOPT_MAXREDIRS => 10,\n CURLOPT_TIMEOUT => 30,\n CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,\n CURLOPT_CUSTOMREQUEST => \"PUT\",\n CURLOPT_POSTFIELDS => \"{\n \\\"username\\\": \\\"<string>\\\",\n \\\"role\\\": \\\"<string>\\\"\n}\",\n CURLOPT_HTTPHEADER => [\n \"Authorization: Token <api-key>\",\n \"Content-Type: application/json\"\n ],\n]);\n\n$response = curl_exec($curl);\n$err = curl_error($curl);\n\ncurl_close($curl);\n\nif ($err) {\n echo \"cURL Error #:\" . $err;\n} else {\n echo $response;\n}"
|
||||
"source": "<?php\n\n$curl = curl_init();\n\ncurl_setopt_array($curl, [\n CURLOPT_URL => \"https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/projects/{project_id}/members/\",\n CURLOPT_RETURNTRANSFER => true,\n CURLOPT_ENCODING => \"\",\n CURLOPT_MAXREDIRS => 10,\n CURLOPT_TIMEOUT => 30,\n CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,\n CURLOPT_CUSTOMREQUEST => \"PUT\",\n CURLOPT_POSTFIELDS => \"{\n \\\"email\\\": \\\"<string>\\\",\n \\\"role\\\": \\\"<string>\\\"\n}\",\n CURLOPT_HTTPHEADER => [\n \"Authorization: Token <api-key>\",\n \"Content-Type: application/json\"\n ],\n]);\n\n$response = curl_exec($curl);\n$err = curl_error($curl);\n\ncurl_close($curl);\n\nif ($err) {\n echo \"cURL Error #:\" . $err;\n} else {\n echo $response;\n}"
|
||||
},
|
||||
{
|
||||
"lang": "Java",
|
||||
"source": "HttpResponse<String> response = Unirest.put(\"https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/projects/{project_id}/members/\")\n .header(\"Authorization\", \"Token <api-key>\")\n .header(\"Content-Type\", \"application/json\")\n .body(\"{\n \\\"username\\\": \\\"<string>\\\",\n \\\"role\\\": \\\"<string>\\\"\n}\")\n .asString();"
|
||||
"source": "HttpResponse<String> response = Unirest.put(\"https://api.mem0.ai/api/v1/orgs/organizations/{org_id}/projects/{project_id}/members/\")\n .header(\"Authorization\", \"Token <api-key>\")\n .header(\"Content-Type\", \"application/json\")\n .body(\"{\n \\\"email\\\": \\\"<string>\\\",\n \\\"role\\\": \\\"<string>\\\"\n}\")\n .asString();"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -3999,10 +4009,10 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "username",
|
||||
"name": "email",
|
||||
"in": "query",
|
||||
"required": true,
|
||||
"description": "Username of the member to be removed",
|
||||
"description": "Email of the member to be removed",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
@@ -4809,7 +4819,7 @@
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"messages": {
|
||||
"description": "An array of message objects representing the content of the memory. Each message object typically contains 'role' and 'content' fields, where 'role' indicates the sender (e.g., 'user', 'assistant', 'system') and 'content' contains the actual message text. This structure allows for the representation of conversations or multi-part memories.",
|
||||
"description": "An array of message objects representing the content of the memory. Each message object typically contains 'role' and 'content' fields, where 'role' indicates the sender either 'user' or 'assistant' and 'content' contains the actual message text. This structure allows for the representation of conversations or multi-part memories.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
@@ -4900,6 +4910,12 @@
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"async_mode": {
|
||||
"description": "Whether to add the memory completely asynchronously.",
|
||||
"title": "Async mode",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"timestamp": {
|
||||
"description": "The timestamp of the memory. Format: Unix timestamp",
|
||||
"title": "Timestamp",
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
---
|
||||
title: MCP Client Integration Guide
|
||||
icon: "plug"
|
||||
iconType: "solid"
|
||||
---
|
||||
|
||||
## Connecting an MCP Client
|
||||
|
||||
Once your OpenMemory server is running locally, you can connect any compatible MCP client to your personal memory stream. This enables a seamless memory layer integration for AI tools and agents.
|
||||
|
||||
Ensure the following environment variables are correctly set in your configuration files:
|
||||
|
||||
**In `/ui/.env`:**
|
||||
```env
|
||||
NEXT_PUBLIC_API_URL=http://localhost:8765
|
||||
NEXT_PUBLIC_USER_ID=<user-id>
|
||||
```
|
||||
|
||||
**In `/api/.env`:**
|
||||
```env
|
||||
OPENAI_API_KEY=sk-xxx
|
||||
USER=<user-id>
|
||||
```
|
||||
|
||||
These values define where your MCP server is running and which user's memory is accessed.
|
||||
|
||||
### MCP Client Setup
|
||||
|
||||
Use the following one step command to configure OpenMemory Local MCP to a client. The general command format is as follows:
|
||||
|
||||
```bash
|
||||
npx @openmemory/install local http://localhost:8765/mcp/<client-name>/sse/<user-id> --client <client-name>
|
||||
```
|
||||
|
||||
Replace `<client-name>` with the desired client name and `<user-id>` with the value specified in your environment variables.
|
||||
|
||||
### Example Commands for Supported Clients
|
||||
|
||||
| Client | Command |
|
||||
|-------------|---------|
|
||||
| Claude | `npx install-mcp http://localhost:8765/mcp/claude/sse/<user-id> --client claude` |
|
||||
| Cursor | `npx install-mcp http://localhost:8765/mcp/cursor/sse/<user-id> --client cursor` |
|
||||
| Cline | `npx install-mcp http://localhost:8765/mcp/cline/sse/<user-id> --client cline` |
|
||||
| RooCline | `npx install-mcp http://localhost:8765/mcp/roocline/sse/<user-id> --client roocline` |
|
||||
| Windsurf | `npx install-mcp http://localhost:8765/mcp/windsurf/sse/<user-id> --client windsurf` |
|
||||
| Witsy | `npx install-mcp http://localhost:8765/mcp/witsy/sse/<user-id> --client witsy` |
|
||||
| Enconvo | `npx install-mcp http://localhost:8765/mcp/enconvo/sse/<user-id> --client enconvo` |
|
||||
| Augment | `npx install-mcp http://localhost:8765/mcp/augment/sse/<user-id> --client augment` |
|
||||
|
||||
### What This Does
|
||||
|
||||
Running one of the above commands registers the specified MCP client and connects it to your OpenMemory server. This enables the client to stream and store contextual memory for the provided user ID.
|
||||
|
||||
The connection status and memory activity can be monitored via the OpenMemory UI at [http://localhost:3000](http://localhost:3000).
|
||||
@@ -0,0 +1,125 @@
|
||||
---
|
||||
title: Overview
|
||||
icon: "info"
|
||||
iconType: "solid"
|
||||
---
|
||||
|
||||
<Snippet file="paper-release.mdx" />
|
||||
|
||||
## 🚀 Hosted OpenMemory MCP Now Available!
|
||||
|
||||
#### Sign Up Now - [app.openmemory.dev](https://app.openmemory.dev)
|
||||
|
||||
Everything you love about OpenMemory MCP but with zero setup.
|
||||
|
||||
✅ Works with all MCP-compatible tools (Claude Desktop, Cursor...)
|
||||
✅ Same standard memory ops: `add_memories`, `search_memory`, etc
|
||||
✅ One-click provisioning, no Docker required
|
||||
✅ Powered by Mem0
|
||||
|
||||
Add shared, persistent, low-friction memory to your MCP-compatible clients in seconds.
|
||||
|
||||
### 🌟 Get Started Now
|
||||
**Sign up and get your access key at [app.openmemory.dev](https://app.openmemory.dev)**
|
||||
|
||||
Example installation: `npx @openmemory/install --client claude --env OPENMEMORY_API_KEY=your-key`
|
||||
|
||||
OpenMemory is a local memory infrastructure powered by Mem0 that lets you carry your memory across any AI app. It provides a unified memory layer that stays with you, enabling agents and assistants to remember what matters across applications.
|
||||
|
||||
<img src="https://github.com/user-attachments/assets/3c701757-ad82-4afa-bfbe-e049c2b4320b" alt="OpenMemory UI" />
|
||||
|
||||
## What is the OpenMemory MCP Server
|
||||
|
||||
The OpenMemory MCP Server is a private, local-first memory server that creates a shared, persistent memory layer for your MCP-compatible tools. This runs entirely on your machine, enabling seamless context handoff across tools. Whether you're switching between development, planning, or debugging environments, your AI assistants can access relevant memory without needing repeated instructions.
|
||||
|
||||
The OpenMemory MCP Server ensures all memory stays local, structured, and under your control with no cloud sync or external storage.
|
||||
|
||||
## OpenMemory Easy Setup
|
||||
|
||||
### Prerequisites
|
||||
- Docker
|
||||
- OpenAI API Key
|
||||
|
||||
You can quickly run OpenMemory by running the following command:
|
||||
|
||||
```bash
|
||||
curl -sL https://raw.githubusercontent.com/mem0ai/mem0/main/openmemory/run.sh | bash
|
||||
```
|
||||
|
||||
You should set the `OPENAI_API_KEY` as a global environment variable:
|
||||
|
||||
```bash
|
||||
export OPENAI_API_KEY=your_api_key
|
||||
```
|
||||
|
||||
You can also set the `OPENAI_API_KEY` as a parameter to the script:
|
||||
|
||||
```bash
|
||||
curl -sL https://raw.githubusercontent.com/mem0ai/mem0/main/openmemory/run.sh | OPENAI_API_KEY=your_api_key bash
|
||||
```
|
||||
|
||||
This will start the OpenMemory server and the OpenMemory UI. Deleting the container will lead to the deletion of the memory store.
|
||||
We suggest you follow the instructions [here](/openmemory/quickstart#setting-up-openmemory) to set up OpenMemory on your local machine, with more persistent memory store.
|
||||
|
||||
## How the OpenMemory MCP Server Works
|
||||
|
||||
Built around the Model Context Protocol (MCP), the OpenMemory MCP Server exposes a standardized set of memory tools:
|
||||
- `add_memories`: Store new memory objects
|
||||
- `search_memory`: Retrieve relevant memories
|
||||
- `list_memories`: View all stored memory
|
||||
- `delete_all_memories`: Clear memory entirely
|
||||
|
||||
Any MCP-compatible tool can connect to the server and use these APIs to persist and access memory.
|
||||
|
||||
## What It Enables
|
||||
|
||||
### Cross-Client Memory Access
|
||||
Store context in Cursor and retrieve it later in Claude or Windsurf without repeating yourself.
|
||||
|
||||
### Fully Local Memory Store
|
||||
All memory is stored on your machine. Nothing goes to the cloud. You maintain full ownership and control.
|
||||
|
||||
### Unified Memory UI
|
||||
The built-in OpenMemory dashboard provides a central view of everything stored. Add, browse, delete and control memory access to clients directly from the dashboard.
|
||||
|
||||
## Supported Clients
|
||||
|
||||
The OpenMemory MCP Server is compatible with any client that supports the Model Context Protocol. This includes:
|
||||
- Cursor
|
||||
- Claude Desktop
|
||||
- Windsurf
|
||||
- Cline, and more.
|
||||
|
||||
As more AI systems adopt MCP, your private memory becomes more valuable.
|
||||
|
||||
## Real-World Examples
|
||||
|
||||
### Scenario 1: Cross-Tool Project Flow
|
||||
Define technical requirements of a project in Claude Desktop. Build in Cursor. Debug issues in Windsurf - all with shared context passed through OpenMemory.
|
||||
|
||||
### Scenario 2: Preferences That Persist
|
||||
Set your preferred code style or tone in one tool. When you switch to another MCP client, it can access those same preferences without redefining them.
|
||||
|
||||
### Scenario 3: Project Knowledge
|
||||
Save important project details once, then access them from any compatible AI tool, no more repetitive explanations.
|
||||
|
||||
## Conclusion
|
||||
|
||||
The OpenMemory MCP Server brings memory to MCP-compatible tools without giving up control or privacy. It solves a foundational limitation in modern LLM workflows: the loss of context across tools, sessions, and environments.
|
||||
|
||||
By standardizing memory operations and keeping all data local, it reduces token overhead, improves performance, and unlocks more intelligent interactions across the growing ecosystem of AI assistants.
|
||||
|
||||
This is just the beginning. The MCP server is the first core layer in the OpenMemory platform - a broader effort to make memory portable, private, and interoperable across AI systems.
|
||||
|
||||
## Getting Started Today
|
||||
|
||||
- Repository: [GitHub](https://github.com/mem0ai/mem0/tree/main/openmemory)
|
||||
- Join our community: [Discord](https://discord.gg/6PzXDgEjG5)
|
||||
|
||||
With OpenMemory, your AI memories stay private, portable, and under your control, exactly where they belong.
|
||||
|
||||
OpenMemory: Your memories, your control.
|
||||
|
||||
## Contributing
|
||||
|
||||
OpenMemory is open source and we welcome contributions. Please see the [CONTRIBUTING.md](https://github.com/mem0ai/mem0/blob/main/openmemory/CONTRIBUTING.md) file for more information.
|
||||
@@ -0,0 +1,162 @@
|
||||
---
|
||||
title: Quickstart
|
||||
icon: "terminal"
|
||||
iconType: "solid"
|
||||
---
|
||||
|
||||
<Snippet file="paper-release.mdx" />
|
||||
|
||||
## 🚀 Hosted OpenMemory MCP Now Available!
|
||||
|
||||
#### Sign Up Now - [app.openmemory.dev](https://app.openmemory.dev)
|
||||
|
||||
Everything you love about OpenMemory MCP but with zero setup.
|
||||
|
||||
✅ Works with all MCP-compatible tools (Claude Desktop, Cursor...)
|
||||
✅ Same standard memory ops: `add_memories`, `search_memory`, etc
|
||||
✅ One-click provisioning, no Docker required
|
||||
✅ Powered by Mem0
|
||||
|
||||
Add shared, persistent, low-friction memory to your MCP-compatible clients in seconds.
|
||||
|
||||
### 🌟 Get Started Now
|
||||
**Sign up and get your access key at [app.openmemory.dev](https://app.openmemory.dev)**
|
||||
|
||||
Example installation: `npx @openmemory/install --client claude --env OPENMEMORY_API_KEY=your-key`
|
||||
|
||||
## Getting Started with Hosted OpenMemory
|
||||
|
||||
The fastest way to get started is with our hosted version - no setup required:
|
||||
|
||||
### 1. Get your API key
|
||||
Visit [app.openmemory.dev](https://app.openmemory.dev) to sign up and get your `OPENMEMORY_API_KEY`.
|
||||
|
||||
### 2. Install and connect to your preferred client
|
||||
Example commands (replace `your-key` with your actual API key):
|
||||
|
||||
For Claude Desktop: `npx @openmemory/install --client claude --env OPENMEMORY_API_KEY=your-key`
|
||||
|
||||
For Cursor: `npx @openmemory/install --client cursor --env OPENMEMORY_API_KEY=your-key`
|
||||
|
||||
For Windsurf: `npx @openmemory/install --client windsurf --env OPENMEMORY_API_KEY=your-key`
|
||||
|
||||
That's it! Your AI client now has persistent memory across sessions.
|
||||
|
||||
## Local Setup (Self-Hosted)
|
||||
|
||||
Prefer to run OpenMemory locally? Follow the instructions below for a self-hosted setup.
|
||||
|
||||
## OpenMemory Easy Setup
|
||||
|
||||
### Prerequisites
|
||||
- Docker
|
||||
- OpenAI API Key
|
||||
|
||||
You can quickly run OpenMemory by running the following command:
|
||||
|
||||
```bash
|
||||
curl -sL https://raw.githubusercontent.com/mem0ai/mem0/main/openmemory/run.sh | bash
|
||||
```
|
||||
|
||||
You should set the `OPENAI_API_KEY` as a global environment variable:
|
||||
|
||||
```bash
|
||||
export OPENAI_API_KEY=your_api_key
|
||||
```
|
||||
|
||||
You can also set the `OPENAI_API_KEY` as a parameter to the script:
|
||||
|
||||
```bash
|
||||
curl -sL https://raw.githubusercontent.com/mem0ai/mem0/main/openmemory/run.sh | OPENAI_API_KEY=your_api_key bash
|
||||
```
|
||||
|
||||
This will start the OpenMemory server and the OpenMemory UI. Deleting the container will lead to the deletion of the memory store.
|
||||
We suggest you follow the instructions below to set up OpenMemory on your local machine, with more persistant memory store.
|
||||
|
||||
## Setting Up OpenMemory
|
||||
|
||||
Getting started with OpenMemory is straight forward and takes just a few minutes to set up on your local machine. Follow these steps:
|
||||
|
||||
### Getting started
|
||||
|
||||
|
||||
### 1. First clone the repository and then follow the instructions:
|
||||
```bash
|
||||
# Clone the repository
|
||||
git clone https://github.com/mem0ai/mem0.git
|
||||
cd mem0/openmemory
|
||||
```
|
||||
|
||||
### 2. Set Up Environment Variables
|
||||
|
||||
Before running the project, you need to configure environment variables for both the API and the UI.
|
||||
|
||||
You can do this in one of the following ways:
|
||||
|
||||
- **Manually**:
|
||||
Create a `.env` file in each of the following directories:
|
||||
- `/api/.env`
|
||||
- `/ui/.env`
|
||||
|
||||
- **Using `.env.example` files**:
|
||||
Copy and rename the example files:
|
||||
|
||||
```bash
|
||||
cp api/.env.example api/.env
|
||||
cp ui/.env.example ui/.env
|
||||
```
|
||||
|
||||
- **Using Makefile** (if supported):
|
||||
Run:
|
||||
|
||||
```bash
|
||||
make env
|
||||
```
|
||||
- #### Example `/api/.env`
|
||||
|
||||
``` bash
|
||||
OPENAI_API_KEY=sk-xxx
|
||||
USER=<user-id> # The User Id you want to associate the memories with
|
||||
```
|
||||
- #### Example `/ui/.env`
|
||||
|
||||
```bash
|
||||
NEXT_PUBLIC_API_URL=http://localhost:8765
|
||||
NEXT_PUBLIC_USER_ID=<user-id> # Same as the user id for environment variable in api
|
||||
```
|
||||
|
||||
### 3. Build and Run the Project
|
||||
You can run the project using the following two commands:
|
||||
```bash
|
||||
make build # builds the mcp server and ui
|
||||
make up # runs openmemory mcp server and ui
|
||||
```
|
||||
|
||||
After running these commands, you will have:
|
||||
- OpenMemory MCP server running at: http://localhost:8765 (API documentation available at http://localhost:8765/docs)
|
||||
- OpenMemory UI running at: http://localhost:3000
|
||||
|
||||
#### UI not working on http://localhost:3000?
|
||||
|
||||
If the UI does not start properly on http://localhost:3000, try running it manually:
|
||||
|
||||
```bash
|
||||
cd ui
|
||||
pnpm install
|
||||
pnpm dev
|
||||
```
|
||||
|
||||
|
||||
You can configure the MCP client using the following command (replace username with your username):
|
||||
|
||||
```bash
|
||||
npx @openmemory/install local "http://localhost:8765/mcp/cursor/sse/username" --client cursor
|
||||
```
|
||||
|
||||
The OpenMemory dashboard will be available at http://localhost:3000. From here, you can view and manage your memories, as well as check connection status with your MCP clients.
|
||||
|
||||
Once set up, OpenMemory runs locally on your machine, ensuring all your AI memories remain private and secure while being accessible across any compatible MCP client.
|
||||
|
||||
### Getting Started Today
|
||||
|
||||
- Github Repository: https://github.com/mem0ai/mem0/tree/main/openmemory
|
||||
@@ -5,6 +5,10 @@ iconType: "solid"
|
||||
---
|
||||
|
||||
<Snippet file="paper-release.mdx" />
|
||||
<Note type="info">
|
||||
🎉 We're excited to announce that Claude 4 is now available with Mem0! Check it out [here](components/llms/models/anthropic).
|
||||
</Note>
|
||||
|
||||
|
||||
# Introduction
|
||||
|
||||
|
||||
@@ -0,0 +1,175 @@
|
||||
---
|
||||
title: Advanced Retrieval
|
||||
icon: "magnifying-glass"
|
||||
iconType: "solid"
|
||||
---
|
||||
|
||||
<Snippet file="paper-release.mdx" />
|
||||
|
||||
Mem0’s **Advanced Retrieval** provides additional control over how memories are selected and ranked during search. While the default search uses embedding-based semantic similarity, Advanced Retrieval introduces specialized options to improve recall, ranking accuracy, or filtering based on specific use case.
|
||||
|
||||
You can enable any of the following modes independently or together:
|
||||
|
||||
- Keyword Search
|
||||
- Reranking
|
||||
- Filtering
|
||||
|
||||
Each enhancement can be toggled independently via the `search()` API call. These flags are off by default. These are useful when building agents that require fine-grained retrieval control
|
||||
|
||||
## Keyword Search
|
||||
|
||||
Keyword search expands the result set by including memories that contain lexically similar terms and important keywords from the query, even if they're not semantically similar.
|
||||
|
||||
### When to use
|
||||
- You are searching for specific entities, names, or technical terms
|
||||
- When you need comprehensive coverage of a topic
|
||||
- You want broader recall at the cost of slight noise
|
||||
|
||||
|
||||
### API Usage
|
||||
```python
|
||||
results = client.search(
|
||||
query="What are my food preferences?",
|
||||
keyword_search=True,
|
||||
user_id="alex"
|
||||
)
|
||||
```
|
||||
|
||||
### Example
|
||||
|
||||
**Without keyword_search:**
|
||||
- "Vegetarian. Allergic to nuts."
|
||||
- "Prefers spicy food and enjoys Thai cuisine"
|
||||
|
||||
**With keyword_search=True:**
|
||||
- "Vegetarian. Allergic to nuts."
|
||||
- "Prefers spicy food and enjoys Thai cuisine"
|
||||
- "Mentioned disliking seafood during restaurant discussion"
|
||||
|
||||
### Trade-offs
|
||||
- Increases recall
|
||||
- May slightly reduce precision
|
||||
- Adds ~10ms latency
|
||||
|
||||
|
||||
|
||||
## Reranking
|
||||
|
||||
Reranking reorders the retrieved results using a deep semantic relevance model that improves the position of the most relevant matches.
|
||||
|
||||
### When to use
|
||||
- You rely on top-1 or top-N precision
|
||||
- When result order is critical for your application
|
||||
- You want consistent result quality across sessions
|
||||
|
||||
### API Usage
|
||||
```python
|
||||
results = client.search(
|
||||
query="What are my travel plans?",
|
||||
rerank=True,
|
||||
user_id="alex"
|
||||
)
|
||||
```
|
||||
|
||||
### Example
|
||||
|
||||
**Without rerank:**
|
||||
1. "Traveled to France last year"
|
||||
2. "Planning a trip to Japan next month"
|
||||
3. "Interested in visiting Tokyo restaurants"
|
||||
|
||||
**With rerank=True:**
|
||||
1. "Planning a trip to Japan next month"
|
||||
2. "Interested in visiting Tokyo restaurants"
|
||||
3. "Traveled to France last year"
|
||||
|
||||
### Trade-offs
|
||||
- Significantly improves result ordering accuracy
|
||||
- Ensures most relevant memories appear first
|
||||
- Adds ~150–200ms latency
|
||||
- Higher computational cost
|
||||
|
||||
|
||||
|
||||
## Filtering
|
||||
|
||||
Filtering allows you to narrow down search results by applying specific criteria from the set of retrieved memories.
|
||||
|
||||
### When to use
|
||||
- You require highly specific results
|
||||
- You are working with huge amount of data where noise is problematic
|
||||
- You require quality over quantity results
|
||||
|
||||
### API Usage
|
||||
```python
|
||||
results = client.search(
|
||||
query="What are my dietary restrictions?",
|
||||
filter_memories=True,
|
||||
user_id="alex"
|
||||
)
|
||||
```
|
||||
|
||||
### Example
|
||||
|
||||
**Without filtering:**
|
||||
- "Vegetarian. Allergic to nuts."
|
||||
- "I enjoy cooking Italian food on weekends"
|
||||
- "Mentioned disliking seafood during restaurant discussion"
|
||||
- "Prefers to eat dinner at 7pm"
|
||||
|
||||
**With filter_memories=True:**
|
||||
- "Vegetarian. Allergic to nuts."
|
||||
- "Mentioned disliking seafood during restaurant discussion"
|
||||
|
||||
### Trade-offs
|
||||
- Maximizes precision (highly relevant results only)
|
||||
- May reduce recall (filters out some relevant memories)
|
||||
- Adds ~200-300ms latency
|
||||
- Best for focused, specific queries
|
||||
|
||||
|
||||
|
||||
## Combining Modes
|
||||
|
||||
You can combine all three retrieval modes as needed:
|
||||
|
||||
```python
|
||||
results = client.search(
|
||||
query="What are my travel plans?",
|
||||
keyword_search=True,
|
||||
rerank=True,
|
||||
filter_memories=True,
|
||||
user_id="alex"
|
||||
)
|
||||
```
|
||||
|
||||
This configuration broadens the candidate pool with keywords, improves ordering via rerank, and finally cuts noise with filtering.
|
||||
<Note> Combining all modes may add up to ~450ms latency per query. </Note>
|
||||
|
||||
|
||||
|
||||
## Performance Benchmarks
|
||||
|
||||
| **Mode** | **Approximate Latency** |
|
||||
|------------------|-------------------------|
|
||||
| `keyword_search` | <10ms |
|
||||
| `rerank` | 150–200ms |
|
||||
| `filter_memories`| 200–300ms |
|
||||
|
||||
|
||||
|
||||
## Best Practices & Limitations
|
||||
|
||||
- Use `keyword_search` for broader recall when query context is limited
|
||||
- Use `rerank` to prioritize the top-most relevant result
|
||||
- Use `filter_memories` in production-facing or safety-critical agents
|
||||
- Combine filtering and reranking for maximum accuracy
|
||||
- Filters may eliminate all results—always handle the empty set gracefully
|
||||
- Filtering uses LLM evaluation and may be rate-limited depending on your plan
|
||||
|
||||
<Note> You can enable or disable these search modes by passing the respective parameters to the `search` method. There is no required sequence for these modes, and any combination can be used based on your needs. </Note>
|
||||
|
||||
---
|
||||
If you have any questions, please feel free to reach out to us using one of the following methods:
|
||||
|
||||
<Snippet file="get-help.mdx" />
|
||||
@@ -0,0 +1,213 @@
|
||||
---
|
||||
title: Criteria Retrieval
|
||||
icon: "magnifying-glass-plus"
|
||||
iconType: "solid"
|
||||
---
|
||||
|
||||
<Snippet file="paper-release.mdx" />
|
||||
|
||||
|
||||
Mem0’s **Criteria Retrieval** feature allows you to retrieve memories based on your defined criteria. It goes beyond generic semantic relevance and rank memories based on what matters to your application - emotional tone, intent, behavioral signals, or other custom traits.
|
||||
|
||||
Instead of just searching for "how similar a memory is to this query?", you can define what *relevance* really means for your project. For example:
|
||||
|
||||
- Prioritize joyful memories when building a wellness assistant
|
||||
- Downrank negative memories in a productivity-focused agent
|
||||
- Highlight curiosity in a tutoring agent
|
||||
|
||||
You define **criteria** - custom attributes like "joy", "negativity", "confidence", or "urgency", and assign weights to control how they influence scoring. When you `search`, Mem0 uses these to re-rank memories that are semantically relevant, favoring those that better match your intent.
|
||||
|
||||
This gives you nuanced, intent-aware memory search that adapts to your use case.
|
||||
|
||||
|
||||
|
||||
## When to Use Criteria Retrieval
|
||||
|
||||
Use Criteria Retrieval if:
|
||||
|
||||
- You’re building an agent that should react to **emotions** or **behavioral signals**
|
||||
- You want to guide memory selection based on **context**, not just content
|
||||
- You have domain-specific signals like "risk", "positivity", "confidence", etc. that shape recall
|
||||
|
||||
|
||||
|
||||
## Setting Up Criteria Retrieval
|
||||
|
||||
Let’s walk through how to configure and use Criteria Retrieval step by step.
|
||||
|
||||
### Initialize the Client
|
||||
|
||||
Before defining any criteria, make sure to initialize the `MemoryClient` with your credentials and project ID:
|
||||
|
||||
```python
|
||||
from mem0 import MemoryClient
|
||||
|
||||
client = MemoryClient(
|
||||
api_key="your_mem0_api_key",
|
||||
org_id="your_organization_id",
|
||||
project_id="your_project_id"
|
||||
)
|
||||
```
|
||||
|
||||
### Define Your Criteria
|
||||
|
||||
Each criterion includes:
|
||||
- A `name` (used in scoring)
|
||||
- A `description` (interpreted by the LLM)
|
||||
- A `weight` (how much it influences the final score)
|
||||
|
||||
```python
|
||||
retrieval_criteria = [
|
||||
{
|
||||
"name": "joy",
|
||||
"description": "Measure the intensity of positive emotions such as happiness, excitement, or amusement expressed in the sentence. A higher score reflects greater joy.",
|
||||
"weight": 3
|
||||
},
|
||||
{
|
||||
"name": "curiosity",
|
||||
"description": "Assess the extent to which the sentence reflects inquisitiveness, interest in exploring new information, or asking questions. A higher score reflects stronger curiosity.",
|
||||
"weight": 2
|
||||
},
|
||||
{
|
||||
"name": "emotion",
|
||||
"description": "Evaluate the presence and depth of sadness or negative emotional tone, including expressions of disappointment, frustration, or sorrow. A higher score reflects greater sadness.",
|
||||
"weight": 1
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
### Apply Criteria to Your Project
|
||||
|
||||
Once defined, register the criteria to your project:
|
||||
|
||||
```python
|
||||
client.update_project(retrieval_criteria=retrieval_criteria)
|
||||
```
|
||||
|
||||
Criteria apply project-wide. Once set, they affect all searches using `version="v2"`.
|
||||
|
||||
|
||||
## Example Walkthrough
|
||||
|
||||
After setting up your criteria, you can use them to filter and retrieve memories. Here's an example:
|
||||
|
||||
### Add Memories
|
||||
|
||||
```python
|
||||
messages = [
|
||||
{"role": "user", "content": "What a beautiful sunny day! I feel so refreshed and ready to take on anything!"},
|
||||
{"role": "user", "content": "I've always wondered how storms form—what triggers them in the atmosphere?"},
|
||||
{"role": "user", "content": "It's been raining for days, and it just makes everything feel heavier."},
|
||||
{"role": "user", "content": "Finally I get time to draw something today, after a long time!! I am super happy today."}
|
||||
]
|
||||
|
||||
client.add(messages, user_id="alice")
|
||||
```
|
||||
|
||||
### Run Standard vs. Criteria-Based Search
|
||||
|
||||
```python
|
||||
# With criteria
|
||||
filters = {
|
||||
"AND": [
|
||||
{"user_id": "alice"}
|
||||
]
|
||||
}
|
||||
results_with_criteria = client.search(
|
||||
query="Why I am feeling happy today?",
|
||||
filters=filters,
|
||||
version="v2"
|
||||
)
|
||||
|
||||
# Without criteria
|
||||
results_without_criteria = client.search(
|
||||
query="Why I am feeling happy today?",
|
||||
user_id="alice"
|
||||
)
|
||||
```
|
||||
|
||||
### Compare Results
|
||||
|
||||
### Search Results (with Criteria)
|
||||
```python
|
||||
[
|
||||
{"memory": "User feels refreshed and ready to take on anything on a beautiful sunny day", "score": 0.666, ...},
|
||||
{"memory": "User finally has time to draw something after a long time", "score": 0.616, ...},
|
||||
{"memory": "User is happy today", "score": 0.500, ...},
|
||||
{"memory": "User is curious about how storms form and what triggers them in the atmosphere.", "score": 0.400, ...},
|
||||
{"memory": "It has been raining for days, making everything feel heavier.", "score": 0.116, ...}
|
||||
]
|
||||
```
|
||||
|
||||
### Search Results (without Criteria)
|
||||
```python
|
||||
[
|
||||
{"memory": "User is happy today", "score": 0.607, ...},
|
||||
{"memory": "User feels refreshed and ready to take on anything on a beautiful sunny day", "score": 0.512, ...},
|
||||
{"memory": "It has been raining for days, making everything feel heavier.", "score": 0.4617, ...},
|
||||
{"memory": "User is curious about how storms form and what triggers them in the atmosphere.", "score": 0.340, ...},
|
||||
{"memory": "User finally has time to draw something after a long time", "score": 0.336, ...},
|
||||
]
|
||||
```
|
||||
|
||||
## Search Results Comparison
|
||||
|
||||
1. **Memory Ordering**: With criteria, memories with high joy scores (like feeling refreshed and drawing) are ranked higher, while without criteria, the most relevant memory ("User is happy today") comes first.
|
||||
2. **Score Distribution**: With criteria, scores are more spread out (0.116 to 0.666) and reflect the criteria weights, while without criteria, scores are more clustered (0.336 to 0.607) and based purely on relevance.
|
||||
3. **Trait Sensitivity**: “Rainy day” content is penalized due to negative tone. “Storm curiosity” is recognized and scored accordingly.
|
||||
|
||||
|
||||
|
||||
## Key Differences vs. Standard Search
|
||||
|
||||
| Aspect | Standard Search | Criteria Retrieval |
|
||||
|-------------------------|--------------------------------------|-------------------------------------------------|
|
||||
| Ranking Logic | Semantic similarity only | Semantic + LLM-based criteria scoring |
|
||||
| Control Over Relevance | None | Fully customizable with weighted criteria |
|
||||
| Memory Reordering | Static based on similarity | Dynamically re-ranked by intent alignment |
|
||||
| Emotional Sensitivity | No tone or trait awareness | Incorporates emotion, tone, or custom behaviors |
|
||||
| Version Required | Defaults | `search(version="v2")` |
|
||||
|
||||
<Note>
|
||||
If no criteria are defined for a project, `version="v2"` behaves like normal search.
|
||||
</Note>
|
||||
|
||||
|
||||
|
||||
## Best Practices
|
||||
|
||||
- Choose **3–5 criteria** that reflect your application’s intent
|
||||
- Make descriptions **clear and distinct**, those are interpreted by an LLM
|
||||
- Use **stronger weights** to amplify impact of important traits
|
||||
- Avoid redundant or ambiguous criteria (e.g. “positivity” + “joy”)
|
||||
- Always handle empty result sets in your application logic
|
||||
|
||||
|
||||
|
||||
## How It Works
|
||||
|
||||
1. **Criteria Definition**: Define custom criteria with a name, description, and weight. These describe what matters in a memory (e.g., joy, urgency, empathy).
|
||||
2. **Project Configuration**: Register these criteria using `update_project()`. They apply at the project level and influence all searches using `version="v2"`.
|
||||
3. **Memory Retrieval**: When you perform a search with `version="v2"`, Mem0 first retrieves relevant memories based on the query and your defined criteria.
|
||||
4. **Weighted Scoring**: Each retrieved memory is evaluated and scored against the defined criteria and weights.
|
||||
|
||||
This lets you prioritize memories that align with your agent’s goals and not just those that look similar to the query.
|
||||
|
||||
<Note>
|
||||
Criteria retrieval is currently supported only in search v2. Make sure to use `version="v2"` when performing searches with custom criteria.
|
||||
</Note>
|
||||
|
||||
|
||||
|
||||
## Summary
|
||||
|
||||
- Define what “relevant” means using criteria
|
||||
- Apply them per project via `update_project()`
|
||||
- Use `version="v2"` to activate criteria-aware search
|
||||
- Build agents that reason not just with relevance, but **contextual importance**
|
||||
|
||||
---
|
||||
|
||||
Need help designing or tuning your criteria?
|
||||
|
||||
<Snippet file="get-help.mdx" />
|
||||
@@ -61,8 +61,8 @@ import { MemoryClient } from "mem0";
|
||||
|
||||
const client = new MemoryClient({
|
||||
apiKey: "your-api-key",
|
||||
orgId: "your-org-id",
|
||||
projectId: "your-project-id"
|
||||
org_id: "your-org-id",
|
||||
project_id: "your-project-id"
|
||||
});
|
||||
|
||||
const messages = [
|
||||
@@ -74,10 +74,10 @@ const messages = [
|
||||
// Enable graph memory when adding
|
||||
await client.add({
|
||||
messages,
|
||||
userId: "joseph",
|
||||
user_id: "joseph",
|
||||
version: "v1",
|
||||
enableGraph: true,
|
||||
outputFormat: "v1.1"
|
||||
enable_graph: true,
|
||||
output_format: "v1.1"
|
||||
});
|
||||
```
|
||||
|
||||
@@ -142,9 +142,9 @@ print(results)
|
||||
// Search with graph memory enabled
|
||||
const results = await client.search({
|
||||
query: "what is my name?",
|
||||
userId: "joseph",
|
||||
enableGraph: true,
|
||||
outputFormat: "v1.1"
|
||||
user_id: "joseph",
|
||||
enable_graph: true,
|
||||
output_format: "v1.1"
|
||||
});
|
||||
|
||||
console.log(results);
|
||||
@@ -211,9 +211,9 @@ print(memories)
|
||||
```javascript JavaScript
|
||||
// Get all memories with graph context
|
||||
const memories = await client.getAll({
|
||||
userId: "joseph",
|
||||
enableGraph: true,
|
||||
outputFormat: "v1.1"
|
||||
user_id: "joseph",
|
||||
enable_graph: true,
|
||||
output_format: "v1.1"
|
||||
});
|
||||
|
||||
console.log(memories);
|
||||
@@ -281,6 +281,67 @@ console.log(memories);
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
### Setting Graph Memory at Project Level
|
||||
|
||||
Instead of passing `enable_graph=True` to every add call, you can enable it once at the project level:
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```python Python
|
||||
from mem0 import MemoryClient
|
||||
|
||||
client = MemoryClient(
|
||||
api_key="your-api-key",
|
||||
org_id="your-org-id",
|
||||
project_id="your-project-id"
|
||||
)
|
||||
|
||||
# Enable graph memory for all operations in this project
|
||||
client.update_project(enable_graph=True, version="v1")
|
||||
|
||||
# Now all add operations will use graph memory by default
|
||||
messages = [
|
||||
{"role": "user", "content": "My name is Joseph"},
|
||||
{"role": "assistant", "content": "Hello Joseph, it's nice to meet you!"},
|
||||
{"role": "user", "content": "I'm from Seattle and I work as a software engineer"}
|
||||
]
|
||||
|
||||
client.add(
|
||||
messages,
|
||||
user_id="joseph",
|
||||
output_format="v1.1"
|
||||
)
|
||||
```
|
||||
|
||||
```javascript JavaScript
|
||||
import { MemoryClient } from "mem0";
|
||||
|
||||
const client = new MemoryClient({
|
||||
apiKey: "your-api-key",
|
||||
org_id: "your-org-id",
|
||||
project_id: "your-project-id"
|
||||
});
|
||||
|
||||
# Enable graph memory for all operations in this project
|
||||
await client.updateProject({ enable_graph: true, version: "v1" });
|
||||
|
||||
# Now all add operations will use graph memory by default
|
||||
const messages = [
|
||||
{ role: "user", content: "My name is Joseph" },
|
||||
{ role: "assistant", content: "Hello Joseph, it's nice to meet you!" },
|
||||
{ role: "user", content: "I'm from Seattle and I work as a software engineer" }
|
||||
];
|
||||
|
||||
await client.add({
|
||||
messages,
|
||||
user_id: "joseph",
|
||||
output_format: "v1.1"
|
||||
});
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
|
||||
## Best Practices
|
||||
|
||||
- Enable Graph Memory for applications where understanding context and relationships between memories is important
|
||||
@@ -131,12 +131,14 @@ curl -X POST "https://api.mem0.ai/v1/memories/export/" \
|
||||
|
||||
### Retrieve Export
|
||||
|
||||
Once the export job is complete, you can retrieve the structured data:
|
||||
Once the export job is complete, you can retrieve the structured data in two ways:
|
||||
|
||||
#### Using Filters
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```python Python
|
||||
# Corrected date range (assuming you meant July 10 to July 20)
|
||||
# Retrieve using filters
|
||||
filters = {
|
||||
"AND": [
|
||||
{"created_at": {"gte": "2024-07-10", "lte": "2024-07-20"}},
|
||||
@@ -148,9 +150,27 @@ response = client.get_memory_export(filters=filters)
|
||||
print(response)
|
||||
```
|
||||
|
||||
```bash cURL
|
||||
curl -X GET "https://api.mem0.ai/v1/memories/export/?user_id=alice" \
|
||||
-H "Authorization: Token your-api-key"
|
||||
```json Output
|
||||
{
|
||||
"full_name": "John Doe",
|
||||
"current_role": "Senior Software Engineer",
|
||||
"years_experience": 8,
|
||||
"employment_status": "full_time",
|
||||
"education_level": "masters",
|
||||
"skills": ["Python", "AWS", "Machine Learning"]
|
||||
}
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
#### Using Export ID
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```python Python
|
||||
# Retrieve using export ID
|
||||
response = client.get_memory_export(memory_export_id="550e8400-e29b-41d4-a716-446655440000")
|
||||
print(response)
|
||||
```
|
||||
|
||||
```json Output
|
||||
+10
-10
@@ -11,34 +11,34 @@ Learn about the key features and capabilities that make Mem0 a powerful platform
|
||||
## Core Features
|
||||
|
||||
<CardGroup>
|
||||
<Card title="Advanced Retrieval" icon="magnifying-glass" href="/features/advanced-retrieval">
|
||||
<Card title="Advanced Retrieval" icon="magnifying-glass" href="advanced-retrieval">
|
||||
Superior search results using state-of-the-art algorithms, including keyword search, reranking, and filtering capabilities.
|
||||
</Card>
|
||||
<Card title="Contextual Add" icon="square-plus" href="/features/contextual-add">
|
||||
<Card title="Contextual Add" icon="square-plus" href="contextual-add">
|
||||
Only send your latest conversation history - we automatically retrieve the rest and generate properly contextualized memories.
|
||||
</Card>
|
||||
<Card title="Multimodal Support" icon="photo-film" href="/features/multimodal-support">
|
||||
<Card title="Multimodal Support" icon="photo-film" href="multimodal-support">
|
||||
Process and analyze various types of content including images.
|
||||
</Card>
|
||||
<Card title="Memory Customization" icon="filter" href="/features/selective-memory">
|
||||
<Card title="Memory Customization" icon="filter" href="selective-memory">
|
||||
Customize and curate stored memories to focus on relevant information while excluding unnecessary data, enabling improved accuracy, privacy control, and resource efficiency.
|
||||
</Card>
|
||||
<Card title="Custom Categories" icon="tags" href="/features/custom-categories">
|
||||
<Card title="Custom Categories" icon="tags" href="custom-categories">
|
||||
Create and manage custom categories to organize memories based on your specific needs and requirements.
|
||||
</Card>
|
||||
<Card title="Custom Instructions" icon="list-check" href="/features/custom-instructions">
|
||||
<Card title="Custom Instructions" icon="list-check" href="custom-instructions">
|
||||
Define specific guidelines for your project to ensure consistent handling of information and requirements.
|
||||
</Card>
|
||||
<Card title="Direct Import" icon="message-bot" href="/features/direct-import">
|
||||
<Card title="Direct Import" icon="message-bot" href="direct-import">
|
||||
Tailor the behavior of your Mem0 instance with custom prompts for specific use cases or domains.
|
||||
</Card>
|
||||
<Card title="Async Client" icon="bolt" href="/features/async-client">
|
||||
<Card title="Async Client" icon="bolt" href="async-client">
|
||||
Asynchronous client for non-blocking operations and high concurrency applications.
|
||||
</Card>
|
||||
<Card title="Memory Export" icon="file-export" href="/features/memory-export">
|
||||
<Card title="Memory Export" icon="file-export" href="memory-export">
|
||||
Export memories in structured formats using customizable Pydantic schemas.
|
||||
</Card>
|
||||
<Card title="Graph Memory" icon="graph" href="/features/graph-memory">
|
||||
<Card title="Graph Memory" icon="graph" href="graph-memory">
|
||||
Add memories in the form of nodes and edges in a graph database and search for related memories.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -39,9 +39,16 @@ When adding new memories, you can specify a custom timestamp to indicate when th
|
||||
<CodeGroup>
|
||||
|
||||
```python Python
|
||||
import os
|
||||
import time
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from mem0 import MemoryClient
|
||||
|
||||
os.environ["MEM0_API_KEY"] = "your-api-key"
|
||||
|
||||
client = MemoryClient()
|
||||
|
||||
# Get the current time
|
||||
current_time = datetime.now()
|
||||
|
||||
@@ -52,10 +59,16 @@ five_days_ago = current_time - timedelta(days=5)
|
||||
unix_timestamp = int(five_days_ago.timestamp())
|
||||
|
||||
# Add memory with custom timestamp
|
||||
client.add("I'm travelling to SF", user_id="user1", timestamp=unix_timestamp)
|
||||
messages = [
|
||||
{"role": "user", "content": "I'm travelling to SF"}
|
||||
]
|
||||
client.add(messages, user_id="user1", timestamp=unix_timestamp)
|
||||
```
|
||||
|
||||
```javascript JavaScript
|
||||
import MemoryClient from 'mem0ai';
|
||||
const client = new MemoryClient({ apiKey: 'your-api-key' });
|
||||
|
||||
// Get the current time
|
||||
const currentTime = new Date();
|
||||
|
||||
@@ -67,7 +80,10 @@ fiveDaysAgo.setDate(currentTime.getDate() - 5);
|
||||
const unixTimestamp = Math.floor(fiveDaysAgo.getTime() / 1000);
|
||||
|
||||
// Add memory with custom timestamp
|
||||
client.add("I'm travelling to SF", { user_id: "user1", timestamp: unixTimestamp })
|
||||
const messages = [
|
||||
{"role": "user", "content": "I'm travelling to SF"}
|
||||
]
|
||||
client.add(messages, { user_id: "user1", timestamp: unixTimestamp })
|
||||
.then(response => console.log(response))
|
||||
.catch(error => console.error(error));
|
||||
```
|
||||
@@ -109,14 +125,20 @@ For example, to create a memory with a timestamp of January 1, 2023:
|
||||
# January 1, 2023 timestamp
|
||||
january_2023_timestamp = 1672531200 # Unix timestamp for 2023-01-01 00:00:00 UTC
|
||||
|
||||
client.add("Important historical information", user_id="user1", timestamp=january_2023_timestamp)
|
||||
messages = [
|
||||
{"role": "user", "content": "I'm travelling to SF"}
|
||||
]
|
||||
client.add(messages, user_id="user1", timestamp=january_2023_timestamp)
|
||||
```
|
||||
|
||||
```javascript JavaScript
|
||||
// January 1, 2023 timestamp
|
||||
const january2023Timestamp = 1672531200; // Unix timestamp for 2023-01-01 00:00:00 UTC
|
||||
|
||||
client.add("Important historical information", { user_id: "user1", timestamp: january2023Timestamp })
|
||||
const messages = [
|
||||
{"role": "user", "content": "I'm travelling to SF"}
|
||||
]
|
||||
client.add(messages, { user_id: "user1", timestamp: january2023Timestamp })
|
||||
.then(response => console.log(response))
|
||||
.catch(error => console.error(error));
|
||||
```
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
title: Introduction
|
||||
title: Overview
|
||||
description: 'Empower your AI applications with long-term memory and personalization'
|
||||
icon: "eye"
|
||||
iconType: "solid"
|
||||
@@ -26,11 +26,11 @@ Mem0 Platform offers a powerful, user-centric solution for AI memory management
|
||||
|
||||
## Getting Started
|
||||
|
||||
Check out our [Platform Guide](/platform/guide) to start using Mem0 platform quickly.
|
||||
Check out our [Platform Guide](/platform/quickstart) to start using Mem0 platform quickly.
|
||||
|
||||
## Next Steps
|
||||
|
||||
- Sign up to the [Mem0 Platform](https://mem0.dev/pd)
|
||||
- Join our [Discord](https://mem0.dev/Did) or [Slack](https://mem0.dev/slack) with other developers and get support.
|
||||
- Join our [Discord](https://mem0.dev/Did) with other developers and get support.
|
||||
|
||||
We're excited to see what you'll build with Mem0 Platform. Let's create smarter, more personalized AI experiences together!
|
||||
|
||||
+478
-29
@@ -1,7 +1,7 @@
|
||||
---
|
||||
title: Guide
|
||||
title: Quickstart
|
||||
description: 'Get started with Mem0 Platform in minutes'
|
||||
icon: "book"
|
||||
icon: "bolt"
|
||||
iconType: "solid"
|
||||
---
|
||||
|
||||
@@ -64,7 +64,10 @@ client = AsyncMemoryClient()
|
||||
|
||||
|
||||
async def main():
|
||||
response = await client.add("I'm travelling to SF", user_id="john")
|
||||
messages = [
|
||||
{"role": "user", "content": "I'm travelling to SF"}
|
||||
]
|
||||
response = await client.add(messages, user_id="john")
|
||||
print(response)
|
||||
|
||||
await main()
|
||||
@@ -139,7 +142,20 @@ curl -X POST "https://api.mem0.ai/v1/memories/" \
|
||||
</CodeGroup>
|
||||
|
||||
<Note>
|
||||
Messages passed along with `user_id`, `run_id`, or `app_id` are stored as user memories, while messages from the assistant are excluded from memory. To store messages for the assistant, use `agent_id` exclusively and avoid including other IDs, such as user_id, alongside it. This ensures the memory is properly attributed to the assistant.
|
||||
When passing `user_id`, memories are primarily created based on user messages, but may be influenced by assistant messages for contextual understanding. For example, in a conversation about food preferences, both the user's stated preferences and their responses to the assistant's questions would form user memories. Similarly, when using `agent_id`, assistant messages are prioritized, but user messages might influence the agent's memories based on context. This approach ensures comprehensive memory creation while maintaining appropriate attribution to either users or agents.
|
||||
|
||||
**Example:**
|
||||
```
|
||||
User: My favorite cuisine is Italian
|
||||
Assistant: Nice! What about Indian cuisine?
|
||||
User: Don't like it much since I cannot eat spicy food
|
||||
|
||||
Resulting user memories:
|
||||
memory1 - Likes Italian food
|
||||
memory2 - Doesn't like Indian food since cannot eat spicy
|
||||
|
||||
(memory2 comes from user's response about Indian cuisine)
|
||||
```
|
||||
</Note>
|
||||
|
||||
<Note>Metadata allows you to store structured information (location, timestamp, user state) with memories. Add it during creation to enable precise filtering and retrieval during searches.</Note>
|
||||
@@ -269,10 +285,12 @@ curl -X POST "https://api.mem0.ai/v1/memories/" \
|
||||
</Note>
|
||||
|
||||
#### Long-term memory for both users and agents
|
||||
When you provide both `user_id` and `agent_id`, Mem0 will store memories with both identifiers attached:
|
||||
- Each memory will be tagged with both the specified `user_id` and `agent_id`
|
||||
- During retrieval, you'll need to provide both IDs to access the memories
|
||||
- This enables tracking the full context of conversations between specific users and agents
|
||||
When you provide both `user_id` and `agent_id`, Mem0 will store memories for both identifiers separately:
|
||||
- Memories from messages with `"role": "user"` are automatically tagged with the provided `user_id`
|
||||
- Memories from messages with `"role": "assistant"` are automatically tagged with the provided `agent_id`
|
||||
- During retrieval, you can provide either `user_id` or `agent_id` to access the respective memories
|
||||
- You can continuously enrich existing memory collections by adding new memories to the same `user_id` or `agent_id` in subsequent API calls, either together or separately, allowing for progressive memory building over time
|
||||
- This dual-tagging approach enables personalized experiences for both users and AI agents in your application
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
@@ -314,11 +332,13 @@ curl -X POST "https://api.mem0.ai/v1/memories/" \
|
||||
{
|
||||
"results": [
|
||||
{
|
||||
// memory from user1
|
||||
"id": "c57abfa2-f0ac-48af-896a-21728dbcecee0",
|
||||
"data": {"memory": "Travelling to San Francisco"},
|
||||
"event": "ADD"
|
||||
},
|
||||
{
|
||||
// memory from agent1
|
||||
"id": "0e8c003f-7db7-426a-9fdc-a46f9331a0c2",
|
||||
"data": {"memory": "Going to Dubai next month"},
|
||||
"event": "ADD"
|
||||
@@ -329,6 +349,59 @@ curl -X POST "https://api.mem0.ai/v1/memories/" \
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
|
||||
#### Async Memory Addition
|
||||
|
||||
When you set `async_mode=True`, memory processing happens completely asynchronously in the background. This allows for faster API responses while your memories are processed. The memories will be available on the dashboard and for retrieval within a few seconds.
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```python Python
|
||||
messages = [
|
||||
{"role": "user", "content": "I love hiking and outdoor activities"},
|
||||
{"role": "assistant", "content": "That's great! I'll remember your interest in hiking and outdoor activities for future recommendations."}
|
||||
]
|
||||
|
||||
client.add(messages, user_id="alex", async_mode=True)
|
||||
```
|
||||
|
||||
```javascript JavaScript
|
||||
const messages = [
|
||||
{"role": "user", "content": "I love hiking and outdoor activities"},
|
||||
{"role": "assistant", "content": "That's great! I'll remember your interest in hiking and outdoor activities for future recommendations."}
|
||||
];
|
||||
|
||||
client.add(messages, { user_id: "alex", async_mode: true })
|
||||
.then(response => console.log(response))
|
||||
.catch(error => console.error(error));
|
||||
```
|
||||
|
||||
```bash cURL
|
||||
curl -X POST "https://api.mem0.ai/v1/memories/" \
|
||||
-H "Authorization: Token your-api-key" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"messages": [
|
||||
{"role": "user", "content": "I love hiking and outdoor activities"},
|
||||
{"role": "assistant", "content": "That's great! I'll remember your interest in hiking and outdoor activities for future recommendations."}
|
||||
],
|
||||
"user_id": "alex",
|
||||
"async_mode": true
|
||||
}'
|
||||
```
|
||||
|
||||
```json Output
|
||||
{
|
||||
"results": [
|
||||
{
|
||||
"message": "Memory processing has been queued for background execution"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
#### Monitor Memories
|
||||
|
||||
You can monitor memory operations on the platform dashboard:
|
||||
@@ -438,7 +511,7 @@ curl -X POST "https://api.mem0.ai/v1/memories/search/?version=v2" \
|
||||
|
||||
#### Search using custom filters
|
||||
|
||||
Our advanced search allows you to set custom search filters. You can filter by user_id, agent_id, app_id, run_id, created_at, updated_at, categories, and text. The filters support logical operators (AND, OR) and comparison operators (in, gte, lte, gt, lt, ne, contains, icontains). For more details, see [V2 Search Memories](/api-reference/memory/v2-search-memories).
|
||||
Our advanced search allows you to set custom search filters. You can filter by user_id, agent_id, app_id, run_id, created_at, updated_at, categories, and text. The filters support logical operators (AND, OR) and comparison operators (in, gte, lte, gt, lt, ne, contains, icontains, *). The wildcard character (*) matches everything for a specific field. For more details, see [V2 Search Memories](/api-reference/memory/v2-search-memories).
|
||||
|
||||
Here you need to define `version` as `v2` in the search method.
|
||||
|
||||
@@ -449,7 +522,7 @@ Example 1: Search using user_id and agent_id filters
|
||||
```python Python
|
||||
query = "What do you know about me?"
|
||||
filters = {
|
||||
"AND":[
|
||||
"OR":[
|
||||
{
|
||||
"user_id":"alex"
|
||||
},
|
||||
@@ -469,7 +542,7 @@ client.search(query, version="v2", filters=filters)
|
||||
```javascript JavaScript
|
||||
const query = "What do you know about me?";
|
||||
const filters = {
|
||||
"AND":[
|
||||
"OR":[
|
||||
{
|
||||
"user_id":"alex"
|
||||
},
|
||||
@@ -495,7 +568,7 @@ curl -X POST "https://api.mem0.ai/v1/memories/search/?version=v2" \
|
||||
-d '{
|
||||
"query": "What do you know about me?",
|
||||
"filters": {
|
||||
"AND": [
|
||||
"OR": [
|
||||
{
|
||||
"user_id": "alex"
|
||||
},
|
||||
@@ -674,6 +747,152 @@ curl -X POST "https://api.mem0.ai/v1/memories/search/?version=v2" \
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
Example 4: Search using NOT filters
|
||||
<CodeGroup>
|
||||
```python Python
|
||||
query = "What do you know about me?"
|
||||
filters = {
|
||||
"NOT": [
|
||||
{
|
||||
"categories": {
|
||||
"contains": "food_preferences"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
client.search(query, version="v2", filters=filters)
|
||||
```
|
||||
|
||||
```javascript JavaScript
|
||||
const query = "What do you know about me?";
|
||||
const filters = {
|
||||
"NOT": [
|
||||
{
|
||||
"categories": {
|
||||
"contains": "food_preferences"
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
client.search(query, { version: "v2", filters })
|
||||
.then(results => console.log(results))
|
||||
.catch(error => console.error(error));
|
||||
```
|
||||
|
||||
```bash cURL
|
||||
curl -X POST "https://api.mem0.ai/v1/memories/search/?version=v2" \
|
||||
-H "Authorization: Token your-api-key" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"query": "What do you know about me?",
|
||||
"filters": {
|
||||
"NOT": [
|
||||
{
|
||||
"categories": {
|
||||
"contains": "food_preferences"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}'
|
||||
```
|
||||
|
||||
```json Output
|
||||
{
|
||||
"results": [
|
||||
{
|
||||
"id": "123abc-d456-7890-efgh-ijklmnopqrst",
|
||||
"memory": "Lives in San Francisco",
|
||||
"user_id": "alex",
|
||||
"metadata": null,
|
||||
"categories": ["location"],
|
||||
"immutable": false,
|
||||
"expiration_date": null,
|
||||
"created_at": "2024-07-20T01:30:36.275141-07:00",
|
||||
"updated_at": "2024-07-20T01:30:36.275172-07:00"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
Example 5: Search using wildcard filters
|
||||
<CodeGroup>
|
||||
```python Python
|
||||
query = "What do you know about me?"
|
||||
filters = {
|
||||
"AND": [
|
||||
{
|
||||
"user_id": "alex"
|
||||
},
|
||||
{
|
||||
"run_id": "*" # Matches all run_ids
|
||||
}
|
||||
]
|
||||
}
|
||||
client.search(query, version="v2", filters=filters)
|
||||
```
|
||||
|
||||
```javascript JavaScript
|
||||
const query = "What do you know about me?";
|
||||
const filters = {
|
||||
"AND": [
|
||||
{
|
||||
"user_id": "alex"
|
||||
},
|
||||
{
|
||||
"run_id": "*" // Matches all run_ids
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
client.search(query, { version: "v2", filters })
|
||||
.then(results => console.log(results))
|
||||
.catch(error => console.error(error));
|
||||
```
|
||||
|
||||
```bash cURL
|
||||
curl -X POST "https://api.mem0.ai/v1/memories/search/?version=v2" \
|
||||
-H "Authorization: Token your-api-key" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"query": "What do you know about me?",
|
||||
"filters": {
|
||||
"AND": [
|
||||
{
|
||||
"user_id": "alex"
|
||||
},
|
||||
{
|
||||
"run_id": "*"
|
||||
}
|
||||
]
|
||||
}
|
||||
}'
|
||||
```
|
||||
|
||||
```json Output
|
||||
{
|
||||
"results": [
|
||||
{
|
||||
"id": "7f165f7e-b411-4afe-b7e5-35789b72c4a5",
|
||||
"memory": "Name: Alex. Vegetarian. Allergic to nuts.",
|
||||
"user_id": "alex",
|
||||
"run_id": "session-1",
|
||||
"metadata": null,
|
||||
"categories": ["food_preferences"],
|
||||
"immutable": false,
|
||||
"expiration_date": null,
|
||||
"created_at": "2024-07-20T01:30:36.275141-07:00",
|
||||
"updated_at": "2024-07-20T01:30:36.275172-07:00"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
|
||||
### 4.3 Get All Users
|
||||
|
||||
@@ -1047,7 +1266,7 @@ curl -X GET "https://api.mem0.ai/v1/memories/?user_id=alex&keywords=to play&page
|
||||
|
||||
#### Get all memories using custom filters
|
||||
|
||||
Our advanced retrieval allows you to set custom filters when fetching memories. You can filter by user_id, agent_id, app_id, run_id, created_at, updated_at, categories, and keywords. The filters support logical operators (AND, OR) and comparison operators (in, gte, lte, gt, lt, ne, contains, icontains). For more details, see [v2 Get Memories](/api-reference/memory/v2-get-memories).
|
||||
Our advanced retrieval allows you to set custom filters when fetching memories. You can filter by user_id, agent_id, app_id, run_id, created_at, updated_at, categories, and keywords. The filters support logical operators (AND, OR) and comparison operators (in, gte, lte, gt, lt, ne, contains, icontains, *). The wildcard character (*) matches everything for a specific field. For more details, see [v2 Get Memories](/api-reference/memory/v2-get-memories).
|
||||
|
||||
Here you need to define `version` as `v2` in the get_all method.
|
||||
|
||||
@@ -1181,7 +1400,7 @@ curl -X GET "https://api.mem0.ai/v1/memories/?version=v2&page=1&page_size=50" \
|
||||
"memory":"Name: Alex. Vegetarian. Allergic to nuts.",
|
||||
"user_id":"alex",
|
||||
"hash":"62bc074f56d1f909f1b4c2b639f56f6a",
|
||||
"metadata":null,
|
||||
"metadata":None,
|
||||
"immutable": false,
|
||||
"expiration_date": null,
|
||||
"created_at":"2024-07-25T23:57:00.108347-07:00",
|
||||
@@ -1291,6 +1510,234 @@ curl -X GET "https://api.mem0.ai/v1/memories/?version=v2&page=1&page_size=50" \
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
Example 3: Get all memories using NOT filters
|
||||
<CodeGroup>
|
||||
```python Python
|
||||
filters = {
|
||||
"NOT": [
|
||||
{
|
||||
"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 = {
|
||||
"NOT": [
|
||||
{
|
||||
"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": {
|
||||
"NOT": [
|
||||
{
|
||||
"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": {
|
||||
"NOT": [
|
||||
{
|
||||
"categories": {
|
||||
"contains": "food_preferences"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}'
|
||||
```
|
||||
|
||||
```json Output
|
||||
[
|
||||
{
|
||||
"id": "789xyz-e012-3456-fghi-jklmnopqrstu",
|
||||
"memory": "Works as a software engineer",
|
||||
"user_id": "alex",
|
||||
"metadata": {"job": "tech"},
|
||||
"categories": ["work"],
|
||||
"immutable": false,
|
||||
"expiration_date": null,
|
||||
"created_at": "2024-07-20T01:30:36.275141-07:00",
|
||||
"updated_at": "2024-07-20T01:30:36.275172-07:00"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
```json Output (Paginated)
|
||||
{
|
||||
"count": 1,
|
||||
"next": null,
|
||||
"previous": null,
|
||||
"results": [
|
||||
{
|
||||
"id": "789xyz-e012-3456-fghi-jklmnopqrstu",
|
||||
"memory": "Works as a software engineer",
|
||||
"user_id": "alex",
|
||||
"metadata": {"job": "tech"},
|
||||
"categories": ["work"],
|
||||
"immutable": false,
|
||||
"expiration_date": null,
|
||||
"created_at": "2024-07-20T01:30:36.275141-07:00",
|
||||
"updated_at": "2024-07-20T01:30:36.275172-07:00"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
Example 4: Get all memories using wildcard filters
|
||||
<CodeGroup>
|
||||
```python Python
|
||||
filters = {
|
||||
"AND": [
|
||||
{
|
||||
"user_id": "alex"
|
||||
},
|
||||
{
|
||||
"run_id": "*" # Matches all run_ids
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
# 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": [
|
||||
{
|
||||
"user_id": "alex"
|
||||
},
|
||||
{
|
||||
"run_id": "*" // Matches all run_ids
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
// 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": [
|
||||
{"user_id":"alex"},
|
||||
{"run_id": "*"}
|
||||
]
|
||||
}
|
||||
}'
|
||||
|
||||
# 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": [
|
||||
{"user_id":"alex"},
|
||||
{"run_id": "*"}
|
||||
]
|
||||
}
|
||||
}'
|
||||
```
|
||||
|
||||
```json Output (Default)
|
||||
[
|
||||
{
|
||||
"id": "f38b689d-6b24-45b7-bced-17fbb4d8bac7",
|
||||
"memory": "Name: Alex. Vegetarian. Allergic to nuts.",
|
||||
"user_id": "alex",
|
||||
"run_id": "session-1",
|
||||
"metadata": null,
|
||||
"categories": ["food_preferences"],
|
||||
"immutable": false,
|
||||
"expiration_date": null,
|
||||
"created_at": "2024-07-20T01:30:36.275141-07:00",
|
||||
"updated_at": "2024-07-20T01:30:36.275172-07:00"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
```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",
|
||||
"run_id": "session-1",
|
||||
"metadata": null,
|
||||
"categories": ["food_preferences"],
|
||||
"immutable": false,
|
||||
"expiration_date": null,
|
||||
"created_at": "2024-07-20T01:30:36.275141-07:00",
|
||||
"updated_at": "2024-07-20T01:30:36.275172-07:00"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
|
||||
### 4.5 Memory History
|
||||
|
||||
@@ -1386,24 +1833,26 @@ curl -X GET "https://api.mem0.ai/v1/memories/<memory-id-here>/history/" \
|
||||
|
||||
### 4.6 Update Memory
|
||||
|
||||
Update a memory with new data.
|
||||
Update a memory with new data. You can update the memory's text, metadata, or both.
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```python Python
|
||||
message = "I recently tried chicken and I loved it. I'm thinking of trying more non-vegetarian dishes.."
|
||||
client.update(memory_id, message)
|
||||
client.update(
|
||||
memory_id="<memory-id-here>",
|
||||
text="I am now a vegetarian.",
|
||||
metadata={"diet": "vegetarian"}
|
||||
)
|
||||
```
|
||||
|
||||
```javascript JavaScript
|
||||
const message = "I recently tried chicken and I loved it. I'm thinking of trying more non-vegetarian dishes..";
|
||||
client.update("memory-id-here", message)
|
||||
client.update("memory-id-here", { text: "I am now a vegetarian.", metadata: { diet: "vegetarian" } })
|
||||
.then(result => console.log(result))
|
||||
.catch(error => console.error(error));
|
||||
```
|
||||
|
||||
```bash cURL
|
||||
curl -X PUT "https://api.mem0.ai/v1/memories/memory-id-here" \
|
||||
curl -X PUT "https://api.mem0.ai/v1/memories/<memory-id-here>" \
|
||||
-H "Authorization: Token your-api-key" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
@@ -1513,7 +1962,7 @@ client.delete_users({ user_id: "alex" })
|
||||
```
|
||||
|
||||
```bash cURL
|
||||
curl -X DELETE "https://api.mem0.ai/v1/entities/?user_id=alex" \
|
||||
curl -X DELETE "https://api.mem0.ai/v2/entities/user/alex" \
|
||||
-H "Authorization: Token your-api-key"
|
||||
```
|
||||
|
||||
@@ -1531,12 +1980,6 @@ curl -X DELETE "https://api.mem0.ai/v1/entities/?user_id=alex" \
|
||||
client.reset()
|
||||
```
|
||||
|
||||
```javascript JavaScript
|
||||
client.reset()
|
||||
.then(result => console.log(result))
|
||||
.catch(error => console.error(error));
|
||||
```
|
||||
|
||||
```json Output
|
||||
{'message': 'Client reset successful. All users and memories deleted.'}
|
||||
```
|
||||
@@ -1549,11 +1992,17 @@ Fun fact: You can also delete the memory using the `add()` method by passing a n
|
||||
<CodeGroup>
|
||||
|
||||
```python Python
|
||||
client.add("Delete all of my food preferences", user_id="alex")
|
||||
messages = [
|
||||
{"role": "user", "content": "Delete all of my food preferences"}
|
||||
]
|
||||
client.add(messages, user_id="alex")
|
||||
```
|
||||
|
||||
```javascript JavaScript
|
||||
client.add("Delete all of my food preferences", { user_id: "alex" })
|
||||
const messages = [
|
||||
{"role": "user", "content": "Delete all of my food preferences"}
|
||||
]
|
||||
client.add(messages, { user_id: "alex" })
|
||||
.then(result => console.log(result))
|
||||
.catch(error => console.error(error));
|
||||
```
|
||||
|
||||
+15
-3
@@ -330,11 +330,23 @@ const memory = new Memory();
|
||||
<CodeGroup>
|
||||
```python Code
|
||||
# For a user
|
||||
result = m.add("I like to drink coffee in the morning and go for a walk.", user_id="alice", metadata={"category": "preferences"})
|
||||
messages = [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "I like to drink coffee in the morning and go for a walk"
|
||||
}
|
||||
]
|
||||
result = m.add(messages, 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" } });
|
||||
const messages = [
|
||||
{
|
||||
role: "user",
|
||||
content: "I like to drink coffee in the morning and go for a walk"
|
||||
}
|
||||
];
|
||||
const result = memory.add(messages, { userId: "alice", metadata: { category: "preferences" } });
|
||||
```
|
||||
|
||||
```json Output
|
||||
@@ -403,7 +415,7 @@ const relatedMemories = memory.search("Should I drink coffee or tea?", { userId:
|
||||
<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">
|
||||
<Card title="Mem0 OSS Node.js SDK" icon="node" href="/open-source/node-quickstart">
|
||||
Learn more about Mem0 OSS Node.js SDK
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -0,0 +1,113 @@
|
||||
---
|
||||
title: What is Mem0?
|
||||
icon: "brain"
|
||||
iconType: "solid"
|
||||
---
|
||||
|
||||
|
||||
Mem0 is a memory layer designed for modern AI agents. It acts as a persistent memory layer that agents can use to:
|
||||
|
||||
- Recall relevant past interactions
|
||||
- Store important user preferences and factual context
|
||||
- Learn from successes and failures
|
||||
|
||||
It gives AI agents memory so they can remember, learn, and evolve across interactions. Mem0 integrates easily into your agent stack and scales from prototypes to production systems.
|
||||
|
||||
|
||||
## Stateless vs. Stateful Agents
|
||||
|
||||
Most current agents are stateless: they process a query, generate a response, and forget everything. Even with huge context windows, everything resets the next session.
|
||||
|
||||
Stateful agents, powered by Mem0, are different. They retain context, recall what matters, and behave more intelligently over time.
|
||||
|
||||
<Frame caption="Stateless vs Stateful Agent">
|
||||
<img src="../images/stateless-vs-stateful-agent.png" />
|
||||
</Frame>
|
||||
|
||||
|
||||
## Where Memory Fits in the Agent Stack
|
||||
|
||||
Mem0 sits alongside your retriever, planner, and LLM. Unlike retrieval-based systems (like RAG), Mem0 tracks past interactions, stores long-term knowledge, and evolves the agent’s behavior.
|
||||
|
||||
<Frame caption="Memory in Agent Architecture">
|
||||
<img src="../images/memory-agent-stack.png" />
|
||||
</Frame>
|
||||
|
||||
Memory is not about pushing more tokens into a prompt but about intelligently remembering context that matters. This distinction matters:
|
||||
|
||||
| Capability | Context Window | Mem0 Memory |
|
||||
|------------------|------------------------|-----------------------------|
|
||||
| Retention | Temporary | Persistent |
|
||||
| Cost | Grows with input size | Optimized (only what matters) |
|
||||
| Recall | Token proximity | Relevance + intent-based |
|
||||
| Personalization | None | Deep, evolving profile |
|
||||
| Behavior | Reactive | Adaptive |
|
||||
|
||||
|
||||
## Memory vs. RAG: Complementary Tools
|
||||
|
||||
RAG (Retrieval-Augmented Generation) is great for fetching facts from documents. But it’s stateless. It doesn’t know who the user is, what they’ve asked before, or what failed last time.
|
||||
|
||||
Mem0 provides continuity. It stores decisions, preferences, and context—not just knowledge.
|
||||
|
||||
| Aspect | RAG | Mem0 Memory |
|
||||
|--------------------|-------------------------------|-------------------------------|
|
||||
| Statefulness | Stateless | Stateful |
|
||||
| Recall Type | Document lookup | Evolving user context |
|
||||
| Use Case | Ground answers in data | Guide behavior across time |
|
||||
|
||||
Together, they’re stronger: RAG informs the LLM; Mem0 shapes its memory.
|
||||
|
||||
|
||||
## Types of Memory in Mem0
|
||||
|
||||
Mem0 supports different kinds of memory to mimic how humans store information:
|
||||
|
||||
- **Working Memory**: short-term session awareness
|
||||
- **Factual Memory**: long-term structured knowledge (e.g., preferences, settings)
|
||||
- **Episodic Memory**: records specific past conversations
|
||||
- **Semantic Memory**: builds general knowledge over time
|
||||
|
||||
|
||||
## Why Developers Choose Mem0
|
||||
|
||||
Mem0 isn’t a wrapper around a vector store. It’s a full memory engine with:
|
||||
|
||||
- **LLM-based extraction**: Intelligently decides what to remember
|
||||
- **Filtering & decay**: Avoids memory bloat, forgets irrelevant info
|
||||
- **Costs Reduction**: Save compute costs with smart prompt injection of only relevant memories
|
||||
- **Dashboards & APIs**: Observability, fine-grained control
|
||||
- **Cloud and OSS**: Use our platform version or our open-source SDK version
|
||||
|
||||
You plug Mem0 into your agent framework, it doesn’t replace your LLM or workflows. Instead, it adds a smart memory layer on top.
|
||||
|
||||
|
||||
## Core Capabilities
|
||||
|
||||
- **Reduced token usage and faster responses**: sub-50 ms lookups
|
||||
- **Semantic memory**: procedural, episodic, and factual support
|
||||
- **Multimodal support**: handle both text and images
|
||||
- **Graph memory**: connect insights and entities across sessions
|
||||
- **Host your way**: either a managed service or a self-hosted version
|
||||
|
||||
|
||||
## Getting Started
|
||||
Mem0 offers two powerful ways to leverage our technology: our [managed platform](/platform/overview) and our [open source solution](/open-source/overview).
|
||||
|
||||
|
||||
<CardGroup cols={3}>
|
||||
<Card title="Quickstart" icon="rocket" href="/quickstart">
|
||||
Integrate Mem0 in a few lines of code
|
||||
</Card>
|
||||
<Card title="Playground" icon="play" href="https://app.mem0.ai/playground">
|
||||
Mem0 in action
|
||||
</Card>
|
||||
<Card title="Examples" icon="lightbulb" href="/examples">
|
||||
See what you can build with Mem0
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Need help?
|
||||
If you have any questions, please feel free to reach out to us using one of the following methods:
|
||||
|
||||
<Snippet file="get-help.mdx"/>
|
||||
+1
-1
@@ -12,7 +12,7 @@ install:
|
||||
# TODO: use a more efficient way to install these packages
|
||||
install_all:
|
||||
poetry install --all-extras
|
||||
poetry run pip install pinecone-text pinecone-client langchain-anthropic "unstructured[local-inference, all-docs]" ollama langchain_together==0.1.3 \
|
||||
poetry run pip install ruff==0.6.9 pinecone-text pinecone-client langchain-anthropic "unstructured[local-inference, all-docs]" ollama langchain_together==0.1.3 \
|
||||
langchain_cohere==0.1.5 deepgram-sdk==3.2.7 langchain-huggingface psutil clarifai==10.0.1 flask==2.3.3 twilio==8.5.0 fastapi-poe==0.0.16 discord==2.3.2 \
|
||||
slack-sdk==3.21.3 huggingface_hub==0.23.0 gitpython==3.1.38 yt_dlp==2023.11.14 PyGithub==1.59.1 feedparser==6.0.10 newspaper3k==0.2.8 listparser==0.19 \
|
||||
modal==0.56.4329 dropbox==11.36.2 boto3==1.34.20 youtube-transcript-api==0.6.1 pytube==15.0.0 beautifulsoup4==4.12.3
|
||||
|
||||
@@ -24,7 +24,7 @@ def merge_metadata_dict(left: Optional[dict[str, Any]], right: Optional[dict[str
|
||||
for k, v in right.items():
|
||||
if k not in merged:
|
||||
merged[k] = v
|
||||
elif type(merged[k]) != type(v):
|
||||
elif type(merged[k]) is not type(v):
|
||||
raise ValueError(f'additional_kwargs["{k}"] already exists in this message,' " but with a different type.")
|
||||
elif isinstance(merged[k], str):
|
||||
merged[k] += v
|
||||
|
||||
Generated
+2
-2
@@ -2552,7 +2552,7 @@ azure = ["adlfs (>=2024.2.0)"]
|
||||
clip = ["open-clip", "pillow", "torch"]
|
||||
dev = ["pre-commit", "ruff"]
|
||||
docs = ["mkdocs", "mkdocs-jupyter", "mkdocs-material", "mkdocstrings[python]"]
|
||||
embeddings = ["awscli (>=1.29.57)", "boto3 (>=1.28.57)", "botocore (>=1.31.57)", "cohere", "google-generativeai", "huggingface-hub", "instructorembedding", "open-clip-torch", "openai (>=1.6.1)", "pillow", "sentence-transformers", "torch"]
|
||||
embeddings = ["awscli (>=1.29.57)", "boto3 (>=1.28.57)", "botocore (>=1.31.57)", "cohere", "google-generativeai", "huggingface-hub", "instructorembedding", "open-clip-torch", "openai (>=1.6.1)", "pillow", "sentence-transformers", "torch", "google-genai"]
|
||||
tests = ["aiohttp", "boto3", "duckdb", "pandas (>=1.4)", "polars (>=0.19)", "pytest", "pytest-asyncio", "pytest-mock", "pytz", "tantivy"]
|
||||
|
||||
[[package]]
|
||||
@@ -7129,7 +7129,7 @@ cffi = ["cffi (>=1.11)"]
|
||||
aws = ["langchain-aws"]
|
||||
elasticsearch = ["elasticsearch"]
|
||||
gmail = ["google-api-core", "google-api-python-client", "google-auth", "google-auth-httplib2", "google-auth-oauthlib", "requests"]
|
||||
google = ["google-generativeai"]
|
||||
google = ["google-generativeai", "google-genai"]
|
||||
googledrive = ["google-api-python-client", "google-auth-httplib2", "google-auth-oauthlib"]
|
||||
lancedb = ["lancedb"]
|
||||
llama2 = ["replicate"]
|
||||
|
||||
@@ -22,10 +22,7 @@ build-backend = "poetry.core.masonry.api"
|
||||
requires = ["poetry-core"]
|
||||
|
||||
[tool.ruff]
|
||||
select = ["ASYNC", "E", "F"]
|
||||
ignore = []
|
||||
fixable = ["ALL"]
|
||||
unfixable = []
|
||||
line-length = 120
|
||||
exclude = [
|
||||
".bzr",
|
||||
".direnv",
|
||||
@@ -49,17 +46,22 @@ exclude = [
|
||||
"node_modules",
|
||||
"venv"
|
||||
]
|
||||
line-length = 120
|
||||
dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
|
||||
target-version = "py38"
|
||||
|
||||
[tool.ruff.mccabe]
|
||||
max-complexity = 10
|
||||
[tool.ruff.lint]
|
||||
select = ["ASYNC", "E", "F"]
|
||||
ignore = []
|
||||
fixable = ["ALL"]
|
||||
unfixable = []
|
||||
dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
|
||||
|
||||
# Ignore `E402` (import violations) in all `__init__.py` files, and in `path/to/file.py`.
|
||||
[tool.ruff.per-file-ignores]
|
||||
[tool.ruff.lint.per-file-ignores]
|
||||
"embedchain/__init__.py" = ["E401"]
|
||||
|
||||
[tool.ruff.lint.mccabe]
|
||||
max-complexity = 10
|
||||
|
||||
[tool.black]
|
||||
line-length = 120
|
||||
target-version = ["py38", "py39", "py310", "py311"]
|
||||
|
||||
+34
-34
@@ -1,11 +1,12 @@
|
||||
import json
|
||||
import argparse
|
||||
from metrics.utils import calculate_metrics, calculate_bleu_scores
|
||||
from metrics.llm_judge import evaluate_llm_judge
|
||||
from collections import defaultdict
|
||||
from tqdm import tqdm
|
||||
import concurrent.futures
|
||||
import json
|
||||
import threading
|
||||
from collections import defaultdict
|
||||
|
||||
from metrics.llm_judge import evaluate_llm_judge
|
||||
from metrics.utils import calculate_bleu_scores, calculate_metrics
|
||||
from tqdm import tqdm
|
||||
|
||||
|
||||
def process_item(item_data):
|
||||
@@ -13,46 +14,47 @@ def process_item(item_data):
|
||||
local_results = defaultdict(list)
|
||||
|
||||
for item in v:
|
||||
gt_answer = str(item['answer'])
|
||||
pred_answer = str(item['response'])
|
||||
category = str(item['category'])
|
||||
question = str(item['question'])
|
||||
gt_answer = str(item["answer"])
|
||||
pred_answer = str(item["response"])
|
||||
category = str(item["category"])
|
||||
question = str(item["question"])
|
||||
|
||||
# Skip category 5
|
||||
if category == '5':
|
||||
if category == "5":
|
||||
continue
|
||||
|
||||
metrics = calculate_metrics(pred_answer, gt_answer)
|
||||
bleu_scores = calculate_bleu_scores(pred_answer, gt_answer)
|
||||
llm_score = evaluate_llm_judge(question, gt_answer, pred_answer)
|
||||
|
||||
local_results[k].append({
|
||||
"question": question,
|
||||
"answer": gt_answer,
|
||||
"response": pred_answer,
|
||||
"category": category,
|
||||
"bleu_score": bleu_scores["bleu1"],
|
||||
"f1_score": metrics["f1"],
|
||||
"llm_score": llm_score
|
||||
})
|
||||
local_results[k].append(
|
||||
{
|
||||
"question": question,
|
||||
"answer": gt_answer,
|
||||
"response": pred_answer,
|
||||
"category": category,
|
||||
"bleu_score": bleu_scores["bleu1"],
|
||||
"f1_score": metrics["f1"],
|
||||
"llm_score": llm_score,
|
||||
}
|
||||
)
|
||||
|
||||
return local_results
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description='Evaluate RAG results')
|
||||
parser.add_argument('--input_file', type=str,
|
||||
default="results/rag_results_500_k1.json",
|
||||
help='Path to the input dataset file')
|
||||
parser.add_argument('--output_file', type=str,
|
||||
default="evaluation_metrics.json",
|
||||
help='Path to save the evaluation results')
|
||||
parser.add_argument('--max_workers', type=int, default=10,
|
||||
help='Maximum number of worker threads')
|
||||
parser = argparse.ArgumentParser(description="Evaluate RAG results")
|
||||
parser.add_argument(
|
||||
"--input_file", type=str, default="results/rag_results_500_k1.json", help="Path to the input dataset file"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--output_file", type=str, default="evaluation_metrics.json", help="Path to save the evaluation results"
|
||||
)
|
||||
parser.add_argument("--max_workers", type=int, default=10, help="Maximum number of worker threads")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
with open(args.input_file, 'r') as f:
|
||||
with open(args.input_file, "r") as f:
|
||||
data = json.load(f)
|
||||
|
||||
results = defaultdict(list)
|
||||
@@ -60,18 +62,16 @@ def main():
|
||||
|
||||
# Use ThreadPoolExecutor with specified workers
|
||||
with concurrent.futures.ThreadPoolExecutor(max_workers=args.max_workers) as executor:
|
||||
futures = [executor.submit(process_item, item_data)
|
||||
for item_data in data.items()]
|
||||
futures = [executor.submit(process_item, item_data) for item_data in data.items()]
|
||||
|
||||
for future in tqdm(concurrent.futures.as_completed(futures),
|
||||
total=len(futures)):
|
||||
for future in tqdm(concurrent.futures.as_completed(futures), total=len(futures)):
|
||||
local_results = future.result()
|
||||
with results_lock:
|
||||
for k, items in local_results.items():
|
||||
results[k].extend(items)
|
||||
|
||||
# Save results to JSON file
|
||||
with open(args.output_file, 'w') as f:
|
||||
with open(args.output_file, "w") as f:
|
||||
json.dump(results, f, indent=4)
|
||||
|
||||
print(f"Results saved to {args.output_file}")
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import pandas as pd
|
||||
import json
|
||||
|
||||
import pandas as pd
|
||||
|
||||
# Load the evaluation metrics data
|
||||
with open('evaluation_metrics.json', 'r') as f:
|
||||
with open("evaluation_metrics.json", "r") as f:
|
||||
data = json.load(f)
|
||||
|
||||
# Flatten the data into a list of question items
|
||||
@@ -14,28 +15,20 @@ for key in data:
|
||||
df = pd.DataFrame(all_items)
|
||||
|
||||
# Convert category to numeric type
|
||||
df['category'] = pd.to_numeric(df['category'])
|
||||
df["category"] = pd.to_numeric(df["category"])
|
||||
|
||||
# Calculate mean scores by category
|
||||
result = df.groupby('category').agg({
|
||||
'bleu_score': 'mean',
|
||||
'f1_score': 'mean',
|
||||
'llm_score': 'mean'
|
||||
}).round(4)
|
||||
result = df.groupby("category").agg({"bleu_score": "mean", "f1_score": "mean", "llm_score": "mean"}).round(4)
|
||||
|
||||
# Add count of questions per category
|
||||
result['count'] = df.groupby('category').size()
|
||||
result["count"] = df.groupby("category").size()
|
||||
|
||||
# Print the results
|
||||
print("Mean Scores Per Category:")
|
||||
print(result)
|
||||
|
||||
# Calculate overall means
|
||||
overall_means = df.agg({
|
||||
'bleu_score': 'mean',
|
||||
'f1_score': 'mean',
|
||||
'llm_score': 'mean'
|
||||
}).round(4)
|
||||
overall_means = df.agg({"bleu_score": "mean", "f1_score": "mean", "llm_score": "mean"}).round(4)
|
||||
|
||||
print("\nOverall Mean Scores:")
|
||||
print(overall_means)
|
||||
print(overall_means)
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
from openai import OpenAI
|
||||
import argparse
|
||||
import json
|
||||
from collections import defaultdict
|
||||
|
||||
import numpy as np
|
||||
import argparse
|
||||
from openai import OpenAI
|
||||
from mem0.memory.utils import extract_json
|
||||
|
||||
client = OpenAI()
|
||||
|
||||
@@ -21,7 +23,7 @@ The generated answer might be much longer, but you should be generous with your
|
||||
|
||||
For time related questions, the gold answer will be a specific date, month, year, etc. The generated answer might be much longer or use relative time references (like "last Tuesday" or "next month"), but you should be generous with your grading - as long as it refers to the same date or time period as the gold answer, it should be counted as CORRECT. Even if the format differs (e.g., "May 7th" vs "7 May"), consider it CORRECT if it's the same date.
|
||||
|
||||
Now it’s time for the real question:
|
||||
Now it's time for the real question:
|
||||
Question: {question}
|
||||
Gold answer: {gold_answer}
|
||||
Generated answer: {generated_answer}
|
||||
@@ -32,35 +34,34 @@ Do NOT include both CORRECT and WRONG in your response, or it will break the eva
|
||||
Just return the label CORRECT or WRONG in a json format with the key as "label".
|
||||
"""
|
||||
|
||||
|
||||
def evaluate_llm_judge(question, gold_answer, generated_answer):
|
||||
"""Evaluate the generated answer against the gold answer using an LLM judge."""
|
||||
response = client.chat.completions.create(
|
||||
model="gpt-4o-mini",
|
||||
messages=[{
|
||||
"role": "user",
|
||||
"content": ACCURACY_PROMPT.format(
|
||||
question=question,
|
||||
gold_answer=gold_answer,
|
||||
generated_answer=generated_answer
|
||||
)
|
||||
}],
|
||||
messages=[
|
||||
{
|
||||
"role": "user",
|
||||
"content": ACCURACY_PROMPT.format(
|
||||
question=question, gold_answer=gold_answer, generated_answer=generated_answer
|
||||
),
|
||||
}
|
||||
],
|
||||
response_format={"type": "json_object"},
|
||||
temperature=0.0
|
||||
temperature=0.0,
|
||||
)
|
||||
label = json.loads(response.choices[0].message.content)['label']
|
||||
label = json.loads(extract_json(response.choices[0].message.content))["label"]
|
||||
return 1 if label == "CORRECT" else 0
|
||||
|
||||
|
||||
def main():
|
||||
"""Main function to evaluate RAG results using LLM judge."""
|
||||
parser = argparse.ArgumentParser(
|
||||
description='Evaluate RAG results using LLM judge'
|
||||
)
|
||||
parser = argparse.ArgumentParser(description="Evaluate RAG results using LLM judge")
|
||||
parser.add_argument(
|
||||
'--input_file',
|
||||
"--input_file",
|
||||
type=str,
|
||||
default="results/default_run_v4_k30_new_graph.json",
|
||||
help='Path to the input dataset file'
|
||||
help="Path to the input dataset file",
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
@@ -77,10 +78,10 @@ def main():
|
||||
index = 0
|
||||
for k, v in data.items():
|
||||
for x in v:
|
||||
question = x['question']
|
||||
gold_answer = x['answer']
|
||||
generated_answer = x['response']
|
||||
category = x['category']
|
||||
question = x["question"]
|
||||
gold_answer = x["answer"]
|
||||
generated_answer = x["response"]
|
||||
category = x["category"]
|
||||
|
||||
# Skip category 5
|
||||
if int(category) == 5:
|
||||
@@ -91,13 +92,15 @@ def main():
|
||||
LLM_JUDGE[category].append(label)
|
||||
|
||||
# Store the results
|
||||
RESULTS[index].append({
|
||||
"question": question,
|
||||
"gt_answer": gold_answer,
|
||||
"response": generated_answer,
|
||||
"category": category,
|
||||
"llm_label": label
|
||||
})
|
||||
RESULTS[index].append(
|
||||
{
|
||||
"question": question,
|
||||
"gt_answer": gold_answer,
|
||||
"response": generated_answer,
|
||||
"category": category,
|
||||
"llm_label": label,
|
||||
}
|
||||
)
|
||||
|
||||
# Save intermediate results
|
||||
with open(output_path, "w") as f:
|
||||
@@ -107,8 +110,7 @@ def main():
|
||||
print("All categories accuracy:")
|
||||
for cat, results in LLM_JUDGE.items():
|
||||
if results: # Only print if there are results for this category
|
||||
print(f" Category {cat}: {np.mean(results):.4f} "
|
||||
f"({sum(results)}/{len(results)})")
|
||||
print(f" Category {cat}: {np.mean(results):.4f} " f"({sum(results)}/{len(results)})")
|
||||
print("------------------------------------------")
|
||||
index += 1
|
||||
|
||||
|
||||
+61
-74
@@ -3,97 +3,89 @@ Borrowed from https://github.com/WujiangXu/AgenticMemory/blob/main/utils.py
|
||||
|
||||
@article{xu2025mem,
|
||||
title={A-mem: Agentic memory for llm agents},
|
||||
author={Xu, Wujiang and Liang, Zujie and Mei, Kai and Gao, Hang and Tan, Juntao
|
||||
author={Xu, Wujiang and Liang, Zujie and Mei, Kai and Gao, Hang and Tan, Juntao
|
||||
and Zhang, Yongfeng},
|
||||
journal={arXiv preprint arXiv:2502.12110},
|
||||
year={2025}
|
||||
}
|
||||
"""
|
||||
|
||||
import re
|
||||
import string
|
||||
import numpy as np
|
||||
from typing import List, Dict, Union
|
||||
import statistics
|
||||
from collections import defaultdict
|
||||
from rouge_score import rouge_scorer
|
||||
from nltk.translate.bleu_score import sentence_bleu, SmoothingFunction
|
||||
from bert_score import score as bert_score
|
||||
from typing import Dict, List, Union
|
||||
|
||||
import nltk
|
||||
from bert_score import score as bert_score
|
||||
from nltk.translate.bleu_score import SmoothingFunction, sentence_bleu
|
||||
from nltk.translate.meteor_score import meteor_score
|
||||
from rouge_score import rouge_scorer
|
||||
from sentence_transformers import SentenceTransformer
|
||||
import logging
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
from openai import OpenAI
|
||||
|
||||
# from load_dataset import load_locomo_dataset, QA, Turn, Session, Conversation
|
||||
from sentence_transformers.util import pytorch_cos_sim
|
||||
|
||||
# Download required NLTK data
|
||||
try:
|
||||
nltk.download('punkt', quiet=True)
|
||||
nltk.download('wordnet', quiet=True)
|
||||
nltk.download("punkt", quiet=True)
|
||||
nltk.download("wordnet", quiet=True)
|
||||
except Exception as e:
|
||||
print(f"Error downloading NLTK data: {e}")
|
||||
|
||||
# Initialize SentenceTransformer model (this will be reused)
|
||||
try:
|
||||
sentence_model = SentenceTransformer('all-MiniLM-L6-v2')
|
||||
sentence_model = SentenceTransformer("all-MiniLM-L6-v2")
|
||||
except Exception as e:
|
||||
print(f"Warning: Could not load SentenceTransformer model: {e}")
|
||||
sentence_model = None
|
||||
|
||||
|
||||
def simple_tokenize(text):
|
||||
"""Simple tokenization function."""
|
||||
# Convert to string if not already
|
||||
text = str(text)
|
||||
return text.lower().replace('.', ' ').replace(',', ' ').replace('!', ' ').replace('?', ' ').split()
|
||||
return text.lower().replace(".", " ").replace(",", " ").replace("!", " ").replace("?", " ").split()
|
||||
|
||||
|
||||
def calculate_rouge_scores(prediction: str, reference: str) -> Dict[str, float]:
|
||||
"""Calculate ROUGE scores for prediction against reference."""
|
||||
scorer = rouge_scorer.RougeScorer(['rouge1', 'rouge2', 'rougeL'], use_stemmer=True)
|
||||
scorer = rouge_scorer.RougeScorer(["rouge1", "rouge2", "rougeL"], use_stemmer=True)
|
||||
scores = scorer.score(reference, prediction)
|
||||
return {
|
||||
'rouge1_f': scores['rouge1'].fmeasure,
|
||||
'rouge2_f': scores['rouge2'].fmeasure,
|
||||
'rougeL_f': scores['rougeL'].fmeasure
|
||||
"rouge1_f": scores["rouge1"].fmeasure,
|
||||
"rouge2_f": scores["rouge2"].fmeasure,
|
||||
"rougeL_f": scores["rougeL"].fmeasure,
|
||||
}
|
||||
|
||||
|
||||
def calculate_bleu_scores(prediction: str, reference: str) -> Dict[str, float]:
|
||||
"""Calculate BLEU scores with different n-gram settings."""
|
||||
pred_tokens = nltk.word_tokenize(prediction.lower())
|
||||
ref_tokens = [nltk.word_tokenize(reference.lower())]
|
||||
|
||||
|
||||
weights_list = [(1, 0, 0, 0), (0.5, 0.5, 0, 0), (0.33, 0.33, 0.33, 0), (0.25, 0.25, 0.25, 0.25)]
|
||||
smooth = SmoothingFunction().method1
|
||||
|
||||
|
||||
scores = {}
|
||||
for n, weights in enumerate(weights_list, start=1):
|
||||
try:
|
||||
score = sentence_bleu(ref_tokens, pred_tokens, weights=weights, smoothing_function=smooth)
|
||||
except Exception:
|
||||
except Exception as e:
|
||||
print(f"Error calculating BLEU score: {e}")
|
||||
score = 0.0
|
||||
scores[f'bleu{n}'] = score
|
||||
|
||||
scores[f"bleu{n}"] = score
|
||||
|
||||
return scores
|
||||
|
||||
|
||||
def calculate_bert_scores(prediction: str, reference: str) -> Dict[str, float]:
|
||||
"""Calculate BERTScore for semantic similarity."""
|
||||
try:
|
||||
P, R, F1 = bert_score([prediction], [reference], lang='en', verbose=False)
|
||||
return {
|
||||
'bert_precision': P.item(),
|
||||
'bert_recall': R.item(),
|
||||
'bert_f1': F1.item()
|
||||
}
|
||||
P, R, F1 = bert_score([prediction], [reference], lang="en", verbose=False)
|
||||
return {"bert_precision": P.item(), "bert_recall": R.item(), "bert_f1": F1.item()}
|
||||
except Exception as e:
|
||||
print(f"Error calculating BERTScore: {e}")
|
||||
return {
|
||||
'bert_precision': 0.0,
|
||||
'bert_recall': 0.0,
|
||||
'bert_f1': 0.0
|
||||
}
|
||||
return {"bert_precision": 0.0, "bert_recall": 0.0, "bert_f1": 0.0}
|
||||
|
||||
|
||||
def calculate_meteor_score(prediction: str, reference: str) -> float:
|
||||
"""Calculate METEOR score for the prediction."""
|
||||
@@ -103,6 +95,7 @@ def calculate_meteor_score(prediction: str, reference: str) -> float:
|
||||
print(f"Error calculating METEOR score: {e}")
|
||||
return 0.0
|
||||
|
||||
|
||||
def calculate_sentence_similarity(prediction: str, reference: str) -> float:
|
||||
"""Calculate sentence embedding similarity using SentenceBERT."""
|
||||
if sentence_model is None:
|
||||
@@ -111,7 +104,7 @@ def calculate_sentence_similarity(prediction: str, reference: str) -> float:
|
||||
# Encode sentences
|
||||
embedding1 = sentence_model.encode([prediction], convert_to_tensor=True)
|
||||
embedding2 = sentence_model.encode([reference], convert_to_tensor=True)
|
||||
|
||||
|
||||
# Calculate cosine similarity
|
||||
similarity = pytorch_cos_sim(embedding1, embedding2).item()
|
||||
return float(similarity)
|
||||
@@ -119,6 +112,7 @@ def calculate_sentence_similarity(prediction: str, reference: str) -> float:
|
||||
print(f"Error calculating sentence similarity: {e}")
|
||||
return 0.0
|
||||
|
||||
|
||||
def calculate_metrics(prediction: str, reference: str) -> Dict[str, float]:
|
||||
"""Calculate comprehensive evaluation metrics for a prediction."""
|
||||
# Handle empty or None values
|
||||
@@ -135,90 +129,83 @@ def calculate_metrics(prediction: str, reference: str) -> Dict[str, float]:
|
||||
"bleu4": 0.0,
|
||||
"bert_f1": 0.0,
|
||||
"meteor": 0.0,
|
||||
"sbert_similarity": 0.0
|
||||
"sbert_similarity": 0.0,
|
||||
}
|
||||
|
||||
|
||||
# Convert to strings if they're not already
|
||||
prediction = str(prediction).strip()
|
||||
reference = str(reference).strip()
|
||||
|
||||
|
||||
# Calculate exact match
|
||||
exact_match = int(prediction.lower() == reference.lower())
|
||||
|
||||
|
||||
# Calculate token-based F1 score
|
||||
pred_tokens = set(simple_tokenize(prediction))
|
||||
ref_tokens = set(simple_tokenize(reference))
|
||||
common_tokens = pred_tokens & ref_tokens
|
||||
|
||||
|
||||
if not pred_tokens or not ref_tokens:
|
||||
f1 = 0.0
|
||||
else:
|
||||
precision = len(common_tokens) / len(pred_tokens)
|
||||
recall = len(common_tokens) / len(ref_tokens)
|
||||
f1 = 2 * precision * recall / (precision + recall) if (precision + recall) > 0 else 0.0
|
||||
|
||||
|
||||
# Calculate all scores
|
||||
rouge_scores = 0 #calculate_rouge_scores(prediction, reference)
|
||||
bleu_scores = calculate_bleu_scores(prediction, reference)
|
||||
bert_scores = 0 # calculate_bert_scores(prediction, reference)
|
||||
meteor = 0 # calculate_meteor_score(prediction, reference)
|
||||
sbert_similarity = 0 # calculate_sentence_similarity(prediction, reference)
|
||||
|
||||
|
||||
# Combine all metrics
|
||||
metrics = {
|
||||
"exact_match": exact_match,
|
||||
"f1": f1,
|
||||
# **rouge_scores,
|
||||
**bleu_scores,
|
||||
# **bert_scores,
|
||||
# "meteor": meteor,
|
||||
# "sbert_similarity": sbert_similarity
|
||||
}
|
||||
|
||||
return metrics
|
||||
|
||||
def aggregate_metrics(all_metrics: List[Dict[str, float]], all_categories: List[int]) -> Dict[str, Dict[str, Union[float, Dict[str, float]]]]:
|
||||
|
||||
def aggregate_metrics(
|
||||
all_metrics: List[Dict[str, float]], all_categories: List[int]
|
||||
) -> Dict[str, Dict[str, Union[float, Dict[str, float]]]]:
|
||||
"""Calculate aggregate statistics for all metrics, split by category."""
|
||||
if not all_metrics:
|
||||
return {}
|
||||
|
||||
|
||||
# Initialize aggregates for overall and per-category metrics
|
||||
aggregates = defaultdict(list)
|
||||
category_aggregates = defaultdict(lambda: defaultdict(list))
|
||||
|
||||
|
||||
# Collect all values for each metric, both overall and per category
|
||||
for metrics, category in zip(all_metrics, all_categories):
|
||||
for metric_name, value in metrics.items():
|
||||
aggregates[metric_name].append(value)
|
||||
category_aggregates[category][metric_name].append(value)
|
||||
|
||||
|
||||
# Calculate statistics for overall metrics
|
||||
results = {
|
||||
"overall": {}
|
||||
}
|
||||
|
||||
results = {"overall": {}}
|
||||
|
||||
for metric_name, values in aggregates.items():
|
||||
results["overall"][metric_name] = {
|
||||
'mean': statistics.mean(values),
|
||||
'std': statistics.stdev(values) if len(values) > 1 else 0.0,
|
||||
'median': statistics.median(values),
|
||||
'min': min(values),
|
||||
'max': max(values),
|
||||
'count': len(values)
|
||||
"mean": statistics.mean(values),
|
||||
"std": statistics.stdev(values) if len(values) > 1 else 0.0,
|
||||
"median": statistics.median(values),
|
||||
"min": min(values),
|
||||
"max": max(values),
|
||||
"count": len(values),
|
||||
}
|
||||
|
||||
|
||||
# Calculate statistics for each category
|
||||
for category in sorted(category_aggregates.keys()):
|
||||
results[f"category_{category}"] = {}
|
||||
for metric_name, values in category_aggregates[category].items():
|
||||
if values: # Only calculate if we have values for this category
|
||||
results[f"category_{category}"][metric_name] = {
|
||||
'mean': statistics.mean(values),
|
||||
'std': statistics.stdev(values) if len(values) > 1 else 0.0,
|
||||
'median': statistics.median(values),
|
||||
'min': min(values),
|
||||
'max': max(values),
|
||||
'count': len(values)
|
||||
"mean": statistics.mean(values),
|
||||
"std": statistics.stdev(values) if len(values) > 1 else 0.0,
|
||||
"median": statistics.median(values),
|
||||
"min": min(values),
|
||||
"max": max(values),
|
||||
"count": len(values),
|
||||
}
|
||||
|
||||
|
||||
return results
|
||||
|
||||
@@ -144,4 +144,4 @@ ANSWER_PROMPT_ZEP = """
|
||||
|
||||
Question: {{question}}
|
||||
Answer:
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import argparse
|
||||
import os
|
||||
import json
|
||||
|
||||
from src.langmem import LangMemManager
|
||||
from src.memzero.add import MemoryADD
|
||||
from src.memzero.search import MemorySearch
|
||||
from src.utils import TECHNIQUES, METHODS
|
||||
import argparse
|
||||
from src.rag import RAGManager
|
||||
from src.langmem import LangMemManager
|
||||
from src.zep.search import ZepSearch
|
||||
from src.zep.add import ZepAdd
|
||||
from src.openai.predict import OpenAIPredict
|
||||
from src.rag import RAGManager
|
||||
from src.utils import METHODS, TECHNIQUES
|
||||
from src.zep.add import ZepAdd
|
||||
from src.zep.search import ZepSearch
|
||||
|
||||
|
||||
class Experiment:
|
||||
@@ -21,23 +21,15 @@ class Experiment:
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description='Run memory experiments')
|
||||
parser.add_argument('--technique_type', choices=TECHNIQUES, default='mem0',
|
||||
help='Memory technique to use')
|
||||
parser.add_argument('--method', choices=METHODS, default='add',
|
||||
help='Method to use')
|
||||
parser.add_argument('--chunk_size', type=int, default=1000,
|
||||
help='Chunk size for processing')
|
||||
parser.add_argument('--output_folder', type=str, default='results/',
|
||||
help='Output path for results')
|
||||
parser.add_argument('--top_k', type=int, default=30,
|
||||
help='Number of top memories to retrieve')
|
||||
parser.add_argument('--filter_memories', action='store_true', default=False,
|
||||
help='Whether to filter memories')
|
||||
parser.add_argument('--is_graph', action='store_true', default=False,
|
||||
help='Whether to use graph-based search')
|
||||
parser.add_argument('--num_chunks', type=int, default=1,
|
||||
help='Number of chunks to process')
|
||||
parser = argparse.ArgumentParser(description="Run memory experiments")
|
||||
parser.add_argument("--technique_type", choices=TECHNIQUES, default="mem0", help="Memory technique to use")
|
||||
parser.add_argument("--method", choices=METHODS, default="add", help="Method to use")
|
||||
parser.add_argument("--chunk_size", type=int, default=1000, help="Chunk size for processing")
|
||||
parser.add_argument("--output_folder", type=str, default="results/", help="Output path for results")
|
||||
parser.add_argument("--top_k", type=int, default=30, help="Number of top memories to retrieve")
|
||||
parser.add_argument("--filter_memories", action="store_true", default=False, help="Whether to filter memories")
|
||||
parser.add_argument("--is_graph", action="store_true", default=False, help="Whether to use graph-based search")
|
||||
parser.add_argument("--num_chunks", type=int, default=1, help="Number of chunks to process")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
@@ -46,33 +38,18 @@ def main():
|
||||
|
||||
if args.technique_type == "mem0":
|
||||
if args.method == "add":
|
||||
memory_manager = MemoryADD(
|
||||
data_path='dataset/locomo10.json',
|
||||
is_graph=args.is_graph
|
||||
)
|
||||
memory_manager = MemoryADD(data_path="dataset/locomo10.json", is_graph=args.is_graph)
|
||||
memory_manager.process_all_conversations()
|
||||
elif args.method == "search":
|
||||
output_file_path = os.path.join(
|
||||
args.output_folder,
|
||||
f"mem0_results_top_{args.top_k}_filter_{args.filter_memories}_graph_{args.is_graph}.json"
|
||||
f"mem0_results_top_{args.top_k}_filter_{args.filter_memories}_graph_{args.is_graph}.json",
|
||||
)
|
||||
memory_searcher = MemorySearch(
|
||||
output_file_path,
|
||||
args.top_k,
|
||||
args.filter_memories,
|
||||
args.is_graph
|
||||
)
|
||||
memory_searcher.process_data_file('dataset/locomo10.json')
|
||||
memory_searcher = MemorySearch(output_file_path, args.top_k, args.filter_memories, args.is_graph)
|
||||
memory_searcher.process_data_file("dataset/locomo10.json")
|
||||
elif args.technique_type == "rag":
|
||||
output_file_path = os.path.join(
|
||||
args.output_folder,
|
||||
f"rag_results_{args.chunk_size}_k{args.num_chunks}.json"
|
||||
)
|
||||
rag_manager = RAGManager(
|
||||
data_path="dataset/locomo10_rag.json",
|
||||
chunk_size=args.chunk_size,
|
||||
k=args.num_chunks
|
||||
)
|
||||
output_file_path = os.path.join(args.output_folder, f"rag_results_{args.chunk_size}_k{args.num_chunks}.json")
|
||||
rag_manager = RAGManager(data_path="dataset/locomo10_rag.json", chunk_size=args.chunk_size, k=args.num_chunks)
|
||||
rag_manager.process_all_conversations(output_file_path)
|
||||
elif args.technique_type == "langmem":
|
||||
output_file_path = os.path.join(args.output_folder, "langmem_results.json")
|
||||
@@ -85,11 +62,7 @@ def main():
|
||||
elif args.method == "search":
|
||||
output_file_path = os.path.join(args.output_folder, "zep_search_results.json")
|
||||
zep_manager = ZepSearch()
|
||||
zep_manager.process_data_file(
|
||||
"dataset/locomo10.json",
|
||||
"1",
|
||||
output_file_path
|
||||
)
|
||||
zep_manager.process_data_file("dataset/locomo10.json", "1", output_file_path)
|
||||
elif args.technique_type == "openai":
|
||||
output_file_path = os.path.join(args.output_folder, "openai_results.json")
|
||||
openai_manager = OpenAIPredict()
|
||||
|
||||
+46
-54
@@ -1,28 +1,24 @@
|
||||
import json
|
||||
import multiprocessing as mp
|
||||
import os
|
||||
import time
|
||||
from collections import defaultdict
|
||||
|
||||
from dotenv import load_dotenv
|
||||
from jinja2 import Template
|
||||
from langgraph.checkpoint.memory import MemorySaver
|
||||
from langgraph.prebuilt import create_react_agent
|
||||
from langgraph.store.memory import InMemoryStore
|
||||
from langgraph.utils.config import get_store
|
||||
from langmem import (
|
||||
create_manage_memory_tool,
|
||||
create_search_memory_tool
|
||||
)
|
||||
import time
|
||||
import multiprocessing as mp
|
||||
import json
|
||||
from functools import partial
|
||||
import os
|
||||
from tqdm import tqdm
|
||||
from langmem import create_manage_memory_tool, create_search_memory_tool
|
||||
from openai import OpenAI
|
||||
from collections import defaultdict
|
||||
from dotenv import load_dotenv
|
||||
from prompts import ANSWER_PROMPT
|
||||
from tqdm import tqdm
|
||||
|
||||
load_dotenv()
|
||||
|
||||
client = OpenAI()
|
||||
|
||||
from jinja2 import Template
|
||||
|
||||
ANSWER_PROMPT_TEMPLATE = Template(ANSWER_PROMPT)
|
||||
|
||||
|
||||
@@ -32,14 +28,12 @@ def get_answer(question, speaker_1_user_id, speaker_1_memories, speaker_2_user_i
|
||||
speaker_1_user_id=speaker_1_user_id,
|
||||
speaker_1_memories=speaker_1_memories,
|
||||
speaker_2_user_id=speaker_2_user_id,
|
||||
speaker_2_memories=speaker_2_memories
|
||||
speaker_2_memories=speaker_2_memories,
|
||||
)
|
||||
|
||||
t1 = time.time()
|
||||
response = client.chat.completions.create(
|
||||
model=os.getenv("MODEL"),
|
||||
messages=[{"role": "system", "content": prompt}],
|
||||
temperature=0.0
|
||||
model=os.getenv("MODEL"), messages=[{"role": "system", "content": prompt}], temperature=0.0
|
||||
)
|
||||
t2 = time.time()
|
||||
return response.choices[0].message.content, t2 - t1
|
||||
@@ -63,7 +57,9 @@ def prompt(state):
|
||||
|
||||
|
||||
class LangMem:
|
||||
def __init__(self,):
|
||||
def __init__(
|
||||
self,
|
||||
):
|
||||
self.store = InMemoryStore(
|
||||
index={
|
||||
"dims": 1536,
|
||||
@@ -84,18 +80,12 @@ class LangMem:
|
||||
)
|
||||
|
||||
def add_memory(self, message, config):
|
||||
return self.agent.invoke(
|
||||
{"messages": [{"role": "user", "content": message}]},
|
||||
config=config
|
||||
)
|
||||
return self.agent.invoke({"messages": [{"role": "user", "content": message}]}, config=config)
|
||||
|
||||
def search_memory(self, query, config):
|
||||
try:
|
||||
t1 = time.time()
|
||||
response = self.agent.invoke(
|
||||
{"messages": [{"role": "user", "content": query}]},
|
||||
config=config
|
||||
)
|
||||
response = self.agent.invoke({"messages": [{"role": "user", "content": query}]}, config=config)
|
||||
t2 = time.time()
|
||||
return response["messages"][-1].content, t2 - t1
|
||||
except Exception as e:
|
||||
@@ -106,7 +96,7 @@ class LangMem:
|
||||
class LangMemManager:
|
||||
def __init__(self, dataset_path):
|
||||
self.dataset_path = dataset_path
|
||||
with open(self.dataset_path, 'r') as f:
|
||||
with open(self.dataset_path, "r") as f:
|
||||
self.data = json.load(f)
|
||||
|
||||
def process_all_conversations(self, output_file_path):
|
||||
@@ -127,7 +117,7 @@ class LangMemManager:
|
||||
|
||||
# Identify speakers
|
||||
for conv in chat_history:
|
||||
speakers.add(conv['speaker'])
|
||||
speakers.add(conv["speaker"])
|
||||
|
||||
if len(speakers) != 2:
|
||||
raise ValueError(f"Expected 2 speakers, got {len(speakers)}")
|
||||
@@ -138,50 +128,52 @@ class LangMemManager:
|
||||
# Add memories for each message
|
||||
for conv in tqdm(chat_history, desc=f"Processing messages {key}", leave=False):
|
||||
message = f"{conv['timestamp']} | {conv['speaker']}: {conv['text']}"
|
||||
if conv['speaker'] == speaker1:
|
||||
if conv["speaker"] == speaker1:
|
||||
agent1.add_memory(message, config)
|
||||
elif conv['speaker'] == speaker2:
|
||||
elif conv["speaker"] == speaker2:
|
||||
agent2.add_memory(message, config)
|
||||
else:
|
||||
raise ValueError(f"Expected speaker1 or speaker2, got {conv['speaker']}")
|
||||
|
||||
# Process questions
|
||||
for q in tqdm(questions, desc=f"Processing questions {key}", leave=False):
|
||||
category = q['category']
|
||||
category = q["category"]
|
||||
|
||||
if int(category) == 5:
|
||||
continue
|
||||
|
||||
answer = q['answer']
|
||||
question = q['question']
|
||||
answer = q["answer"]
|
||||
question = q["question"]
|
||||
response1, speaker1_memory_time = agent1.search_memory(question, config)
|
||||
response2, speaker2_memory_time = agent2.search_memory(question, config)
|
||||
|
||||
generated_answer, response_time = get_answer(
|
||||
question, speaker1, response1, speaker2, response2
|
||||
)
|
||||
generated_answer, response_time = get_answer(question, speaker1, response1, speaker2, response2)
|
||||
|
||||
result[key].append({
|
||||
"question": question,
|
||||
"answer": answer,
|
||||
"response1": response1,
|
||||
"response2": response2,
|
||||
"category": category,
|
||||
"speaker1_memory_time": speaker1_memory_time,
|
||||
"speaker2_memory_time": speaker2_memory_time,
|
||||
"response_time": response_time,
|
||||
'response': generated_answer
|
||||
})
|
||||
result[key].append(
|
||||
{
|
||||
"question": question,
|
||||
"answer": answer,
|
||||
"response1": response1,
|
||||
"response2": response2,
|
||||
"category": category,
|
||||
"speaker1_memory_time": speaker1_memory_time,
|
||||
"speaker2_memory_time": speaker2_memory_time,
|
||||
"response_time": response_time,
|
||||
"response": generated_answer,
|
||||
}
|
||||
)
|
||||
|
||||
return result
|
||||
|
||||
# Use multiprocessing to process conversations in parallel
|
||||
with mp.Pool(processes=10) as pool:
|
||||
results = list(tqdm(
|
||||
pool.imap(process_conversation, list(self.data.items())),
|
||||
total=len(self.data),
|
||||
desc="Processing conversations"
|
||||
))
|
||||
results = list(
|
||||
tqdm(
|
||||
pool.imap(process_conversation, list(self.data.items())),
|
||||
total=len(self.data),
|
||||
desc="Processing conversations",
|
||||
)
|
||||
)
|
||||
|
||||
# Combine results from all workers
|
||||
for result in results:
|
||||
@@ -189,5 +181,5 @@ class LangMemManager:
|
||||
OUTPUT[key].extend(items)
|
||||
|
||||
# Save final results
|
||||
with open(output_file_path, 'w') as f:
|
||||
with open(output_file_path, "w") as f:
|
||||
json.dump(OUTPUT, f, indent=4)
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
from mem0 import MemoryClient
|
||||
import json
|
||||
import time
|
||||
import os
|
||||
import threading
|
||||
from tqdm import tqdm
|
||||
import time
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
|
||||
from dotenv import load_dotenv
|
||||
from tqdm import tqdm
|
||||
|
||||
from mem0 import MemoryClient
|
||||
|
||||
load_dotenv()
|
||||
|
||||
|
||||
# Update custom instructions
|
||||
custom_instructions ="""
|
||||
custom_instructions = """
|
||||
Generate personal memories that follow these guidelines:
|
||||
|
||||
1. Each memory should be self-contained with complete context, including:
|
||||
@@ -45,7 +47,7 @@ class MemoryADD:
|
||||
self.mem0_client = MemoryClient(
|
||||
api_key=os.getenv("MEM0_API_KEY"),
|
||||
org_id=os.getenv("MEM0_ORGANIZATION_ID"),
|
||||
project_id=os.getenv("MEM0_PROJECT_ID")
|
||||
project_id=os.getenv("MEM0_PROJECT_ID"),
|
||||
)
|
||||
|
||||
self.mem0_client.update_project(custom_instructions=custom_instructions)
|
||||
@@ -57,15 +59,16 @@ class MemoryADD:
|
||||
self.load_data()
|
||||
|
||||
def load_data(self):
|
||||
with open(self.data_path, 'r') as f:
|
||||
with open(self.data_path, "r") as f:
|
||||
self.data = json.load(f)
|
||||
return self.data
|
||||
|
||||
def add_memory(self, user_id, message, metadata, retries=3):
|
||||
for attempt in range(retries):
|
||||
try:
|
||||
_ = self.mem0_client.add(message, user_id=user_id, version="v2",
|
||||
metadata=metadata, enable_graph=self.is_graph)
|
||||
_ = self.mem0_client.add(
|
||||
message, user_id=user_id, version="v2", metadata=metadata, enable_graph=self.is_graph
|
||||
)
|
||||
return
|
||||
except Exception as e:
|
||||
if attempt < retries - 1:
|
||||
@@ -76,13 +79,13 @@ class MemoryADD:
|
||||
|
||||
def add_memories_for_speaker(self, speaker, messages, timestamp, desc):
|
||||
for i in tqdm(range(0, len(messages), self.batch_size), desc=desc):
|
||||
batch_messages = messages[i:i+self.batch_size]
|
||||
batch_messages = messages[i : i + self.batch_size]
|
||||
self.add_memory(speaker, batch_messages, metadata={"timestamp": timestamp})
|
||||
|
||||
def process_conversation(self, item, idx):
|
||||
conversation = item['conversation']
|
||||
speaker_a = conversation['speaker_a']
|
||||
speaker_b = conversation['speaker_b']
|
||||
conversation = item["conversation"]
|
||||
speaker_a = conversation["speaker_a"]
|
||||
speaker_b = conversation["speaker_b"]
|
||||
|
||||
speaker_a_user_id = f"{speaker_a}_{idx}"
|
||||
speaker_b_user_id = f"{speaker_b}_{idx}"
|
||||
@@ -92,7 +95,7 @@ class MemoryADD:
|
||||
self.mem0_client.delete_all(user_id=speaker_b_user_id)
|
||||
|
||||
for key in conversation.keys():
|
||||
if key in ['speaker_a', 'speaker_b'] or "date" in key or "timestamp" in key:
|
||||
if key in ["speaker_a", "speaker_b"] or "date" in key or "timestamp" in key:
|
||||
continue
|
||||
|
||||
date_time_key = key + "_date_time"
|
||||
@@ -102,10 +105,10 @@ class MemoryADD:
|
||||
messages = []
|
||||
messages_reverse = []
|
||||
for chat in chats:
|
||||
if chat['speaker'] == speaker_a:
|
||||
if chat["speaker"] == speaker_a:
|
||||
messages.append({"role": "user", "content": f"{speaker_a}: {chat['text']}"})
|
||||
messages_reverse.append({"role": "assistant", "content": f"{speaker_a}: {chat['text']}"})
|
||||
elif chat['speaker'] == speaker_b:
|
||||
elif chat["speaker"] == speaker_b:
|
||||
messages.append({"role": "assistant", "content": f"{speaker_b}: {chat['text']}"})
|
||||
messages_reverse.append({"role": "user", "content": f"{speaker_b}: {chat['text']}"})
|
||||
else:
|
||||
@@ -114,11 +117,11 @@ class MemoryADD:
|
||||
# add memories for the two users on different threads
|
||||
thread_a = threading.Thread(
|
||||
target=self.add_memories_for_speaker,
|
||||
args=(speaker_a_user_id, messages, timestamp, "Adding Memories for Speaker A")
|
||||
args=(speaker_a_user_id, messages, timestamp, "Adding Memories for Speaker A"),
|
||||
)
|
||||
thread_b = threading.Thread(
|
||||
target=self.add_memories_for_speaker,
|
||||
args=(speaker_b_user_id, messages_reverse, timestamp, "Adding Memories for Speaker B")
|
||||
args=(speaker_b_user_id, messages_reverse, timestamp, "Adding Memories for Speaker B"),
|
||||
)
|
||||
|
||||
thread_a.start()
|
||||
@@ -132,10 +135,7 @@ class MemoryADD:
|
||||
if not self.data:
|
||||
raise ValueError("No data loaded. Please set data_path and call load_data() first.")
|
||||
with ThreadPoolExecutor(max_workers=max_workers) as executor:
|
||||
futures = [
|
||||
executor.submit(self.process_conversation, item, idx)
|
||||
for idx, item in enumerate(self.data)
|
||||
]
|
||||
futures = [executor.submit(self.process_conversation, item, idx) for idx, item in enumerate(self.data)]
|
||||
|
||||
for future in futures:
|
||||
future.result()
|
||||
future.result()
|
||||
|
||||
@@ -1,25 +1,26 @@
|
||||
import json
|
||||
import os
|
||||
import time
|
||||
from collections import defaultdict
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
from tqdm import tqdm
|
||||
from mem0 import MemoryClient
|
||||
import json
|
||||
import time
|
||||
|
||||
from dotenv import load_dotenv
|
||||
from jinja2 import Template
|
||||
from openai import OpenAI
|
||||
from prompts import ANSWER_PROMPT_GRAPH, ANSWER_PROMPT
|
||||
import os
|
||||
from dotenv import load_dotenv
|
||||
from prompts import ANSWER_PROMPT, ANSWER_PROMPT_GRAPH
|
||||
from tqdm import tqdm
|
||||
|
||||
from mem0 import MemoryClient
|
||||
|
||||
load_dotenv()
|
||||
|
||||
|
||||
class MemorySearch:
|
||||
|
||||
def __init__(self, output_path='results.json', top_k=10, filter_memories=False, is_graph=False):
|
||||
def __init__(self, output_path="results.json", top_k=10, filter_memories=False, is_graph=False):
|
||||
self.mem0_client = MemoryClient(
|
||||
api_key=os.getenv("MEM0_API_KEY"),
|
||||
org_id=os.getenv("MEM0_ORGANIZATION_ID"),
|
||||
project_id=os.getenv("MEM0_PROJECT_ID")
|
||||
project_id=os.getenv("MEM0_PROJECT_ID"),
|
||||
)
|
||||
self.top_k = top_k
|
||||
self.openai_client = OpenAI()
|
||||
@@ -40,11 +41,18 @@ class MemorySearch:
|
||||
try:
|
||||
if self.is_graph:
|
||||
print("Searching with graph")
|
||||
memories = self.mem0_client.search(query, user_id=user_id, top_k=self.top_k,
|
||||
filter_memories=self.filter_memories, enable_graph=True, output_format='v1.1')
|
||||
memories = self.mem0_client.search(
|
||||
query,
|
||||
user_id=user_id,
|
||||
top_k=self.top_k,
|
||||
filter_memories=self.filter_memories,
|
||||
enable_graph=True,
|
||||
output_format="v1.1",
|
||||
)
|
||||
else:
|
||||
memories = self.mem0_client.search(query, user_id=user_id, top_k=self.top_k,
|
||||
filter_memories=self.filter_memories)
|
||||
memories = self.mem0_client.search(
|
||||
query, user_id=user_id, top_k=self.top_k, filter_memories=self.filter_memories
|
||||
)
|
||||
break
|
||||
except Exception as e:
|
||||
print("Retrying...")
|
||||
@@ -55,64 +63,86 @@ class MemorySearch:
|
||||
|
||||
end_time = time.time()
|
||||
if not self.is_graph:
|
||||
semantic_memories = [{'memory': memory['memory'],
|
||||
'timestamp': memory['metadata']['timestamp'],
|
||||
'score': round(memory['score'], 2)}
|
||||
for memory in memories]
|
||||
semantic_memories = [
|
||||
{
|
||||
"memory": memory["memory"],
|
||||
"timestamp": memory["metadata"]["timestamp"],
|
||||
"score": round(memory["score"], 2),
|
||||
}
|
||||
for memory in memories
|
||||
]
|
||||
graph_memories = None
|
||||
else:
|
||||
semantic_memories = [{'memory': memory['memory'],
|
||||
'timestamp': memory['metadata']['timestamp'],
|
||||
'score': round(memory['score'], 2)} for memory in memories['results']]
|
||||
graph_memories = [{"source": relation['source'], "relationship": relation['relationship'], "target": relation['target']} for relation in memories['relations']]
|
||||
semantic_memories = [
|
||||
{
|
||||
"memory": memory["memory"],
|
||||
"timestamp": memory["metadata"]["timestamp"],
|
||||
"score": round(memory["score"], 2),
|
||||
}
|
||||
for memory in memories["results"]
|
||||
]
|
||||
graph_memories = [
|
||||
{"source": relation["source"], "relationship": relation["relationship"], "target": relation["target"]}
|
||||
for relation in memories["relations"]
|
||||
]
|
||||
return semantic_memories, graph_memories, end_time - start_time
|
||||
|
||||
def answer_question(self, speaker_1_user_id, speaker_2_user_id, question, answer, category):
|
||||
speaker_1_memories, speaker_1_graph_memories, speaker_1_memory_time = self.search_memory(speaker_1_user_id, question)
|
||||
speaker_2_memories, speaker_2_graph_memories, speaker_2_memory_time = self.search_memory(speaker_2_user_id, question)
|
||||
speaker_1_memories, speaker_1_graph_memories, speaker_1_memory_time = self.search_memory(
|
||||
speaker_1_user_id, question
|
||||
)
|
||||
speaker_2_memories, speaker_2_graph_memories, speaker_2_memory_time = self.search_memory(
|
||||
speaker_2_user_id, question
|
||||
)
|
||||
|
||||
search_1_memory = [f"{item['timestamp']}: {item['memory']}"
|
||||
for item in speaker_1_memories]
|
||||
search_2_memory = [f"{item['timestamp']}: {item['memory']}"
|
||||
for item in speaker_2_memories]
|
||||
search_1_memory = [f"{item['timestamp']}: {item['memory']}" for item in speaker_1_memories]
|
||||
search_2_memory = [f"{item['timestamp']}: {item['memory']}" for item in speaker_2_memories]
|
||||
|
||||
template = Template(self.ANSWER_PROMPT)
|
||||
answer_prompt = template.render(
|
||||
speaker_1_user_id=speaker_1_user_id.split('_')[0],
|
||||
speaker_2_user_id=speaker_2_user_id.split('_')[0],
|
||||
speaker_1_user_id=speaker_1_user_id.split("_")[0],
|
||||
speaker_2_user_id=speaker_2_user_id.split("_")[0],
|
||||
speaker_1_memories=json.dumps(search_1_memory, indent=4),
|
||||
speaker_2_memories=json.dumps(search_2_memory, indent=4),
|
||||
speaker_1_graph_memories=json.dumps(speaker_1_graph_memories, indent=4),
|
||||
speaker_2_graph_memories=json.dumps(speaker_2_graph_memories, indent=4),
|
||||
question=question
|
||||
question=question,
|
||||
)
|
||||
|
||||
t1 = time.time()
|
||||
response = self.openai_client.chat.completions.create(
|
||||
model=os.getenv("MODEL"),
|
||||
messages=[
|
||||
{"role": "system", "content": answer_prompt}
|
||||
],
|
||||
temperature=0.0
|
||||
model=os.getenv("MODEL"), messages=[{"role": "system", "content": answer_prompt}], temperature=0.0
|
||||
)
|
||||
t2 = time.time()
|
||||
response_time = t2 - t1
|
||||
return response.choices[0].message.content, speaker_1_memories, speaker_2_memories, speaker_1_memory_time, speaker_2_memory_time, speaker_1_graph_memories, speaker_2_graph_memories, response_time
|
||||
return (
|
||||
response.choices[0].message.content,
|
||||
speaker_1_memories,
|
||||
speaker_2_memories,
|
||||
speaker_1_memory_time,
|
||||
speaker_2_memory_time,
|
||||
speaker_1_graph_memories,
|
||||
speaker_2_graph_memories,
|
||||
response_time,
|
||||
)
|
||||
|
||||
def process_question(self, val, speaker_a_user_id, speaker_b_user_id):
|
||||
question = val.get('question', '')
|
||||
answer = val.get('answer', '')
|
||||
category = val.get('category', -1)
|
||||
evidence = val.get('evidence', [])
|
||||
adversarial_answer = val.get('adversarial_answer', '')
|
||||
question = val.get("question", "")
|
||||
answer = val.get("answer", "")
|
||||
category = val.get("category", -1)
|
||||
evidence = val.get("evidence", [])
|
||||
adversarial_answer = val.get("adversarial_answer", "")
|
||||
|
||||
response, speaker_1_memories, speaker_2_memories, speaker_1_memory_time, speaker_2_memory_time, speaker_1_graph_memories, speaker_2_graph_memories, response_time = self.answer_question(
|
||||
speaker_a_user_id,
|
||||
speaker_b_user_id,
|
||||
question,
|
||||
answer,
|
||||
category
|
||||
)
|
||||
(
|
||||
response,
|
||||
speaker_1_memories,
|
||||
speaker_2_memories,
|
||||
speaker_1_memory_time,
|
||||
speaker_2_memory_time,
|
||||
speaker_1_graph_memories,
|
||||
speaker_2_graph_memories,
|
||||
response_time,
|
||||
) = self.answer_question(speaker_a_user_id, speaker_b_user_id, question, answer, category)
|
||||
|
||||
result = {
|
||||
"question": question,
|
||||
@@ -123,67 +153,63 @@ class MemorySearch:
|
||||
"adversarial_answer": adversarial_answer,
|
||||
"speaker_1_memories": speaker_1_memories,
|
||||
"speaker_2_memories": speaker_2_memories,
|
||||
'num_speaker_1_memories': len(speaker_1_memories),
|
||||
'num_speaker_2_memories': len(speaker_2_memories),
|
||||
'speaker_1_memory_time': speaker_1_memory_time,
|
||||
'speaker_2_memory_time': speaker_2_memory_time,
|
||||
"num_speaker_1_memories": len(speaker_1_memories),
|
||||
"num_speaker_2_memories": len(speaker_2_memories),
|
||||
"speaker_1_memory_time": speaker_1_memory_time,
|
||||
"speaker_2_memory_time": speaker_2_memory_time,
|
||||
"speaker_1_graph_memories": speaker_1_graph_memories,
|
||||
"speaker_2_graph_memories": speaker_2_graph_memories,
|
||||
"response_time": response_time
|
||||
"response_time": response_time,
|
||||
}
|
||||
|
||||
# Save results after each question is processed
|
||||
with open(self.output_path, 'w') as f:
|
||||
with open(self.output_path, "w") as f:
|
||||
json.dump(self.results, f, indent=4)
|
||||
|
||||
return result
|
||||
|
||||
def process_data_file(self, file_path):
|
||||
with open(file_path, 'r') as f:
|
||||
with open(file_path, "r") as f:
|
||||
data = json.load(f)
|
||||
|
||||
for idx, item in tqdm(enumerate(data), total=len(data), desc="Processing conversations"):
|
||||
qa = item['qa']
|
||||
conversation = item['conversation']
|
||||
speaker_a = conversation['speaker_a']
|
||||
speaker_b = conversation['speaker_b']
|
||||
qa = item["qa"]
|
||||
conversation = item["conversation"]
|
||||
speaker_a = conversation["speaker_a"]
|
||||
speaker_b = conversation["speaker_b"]
|
||||
|
||||
speaker_a_user_id = f"{speaker_a}_{idx}"
|
||||
speaker_b_user_id = f"{speaker_b}_{idx}"
|
||||
|
||||
for question_item in tqdm(qa, total=len(qa), desc=f"Processing questions for conversation {idx}", leave=False):
|
||||
result = self.process_question(
|
||||
question_item,
|
||||
speaker_a_user_id,
|
||||
speaker_b_user_id
|
||||
)
|
||||
for question_item in tqdm(
|
||||
qa, total=len(qa), desc=f"Processing questions for conversation {idx}", leave=False
|
||||
):
|
||||
result = self.process_question(question_item, speaker_a_user_id, speaker_b_user_id)
|
||||
self.results[idx].append(result)
|
||||
|
||||
# Save results after each question is processed
|
||||
with open(self.output_path, 'w') as f:
|
||||
with open(self.output_path, "w") as f:
|
||||
json.dump(self.results, f, indent=4)
|
||||
|
||||
# Final save at the end
|
||||
with open(self.output_path, 'w') as f:
|
||||
with open(self.output_path, "w") as f:
|
||||
json.dump(self.results, f, indent=4)
|
||||
|
||||
def process_questions_parallel(self, qa_list, speaker_a_user_id, speaker_b_user_id, max_workers=1):
|
||||
def process_single_question(val):
|
||||
result = self.process_question(val, speaker_a_user_id, speaker_b_user_id)
|
||||
# Save results after each question is processed
|
||||
with open(self.output_path, 'w') as f:
|
||||
with open(self.output_path, "w") as f:
|
||||
json.dump(self.results, f, indent=4)
|
||||
return result
|
||||
|
||||
with ThreadPoolExecutor(max_workers=max_workers) as executor:
|
||||
results = list(tqdm(
|
||||
executor.map(process_single_question, qa_list),
|
||||
total=len(qa_list),
|
||||
desc="Answering Questions"
|
||||
))
|
||||
results = list(
|
||||
tqdm(executor.map(process_single_question, qa_list), total=len(qa_list), desc="Answering Questions")
|
||||
)
|
||||
|
||||
# Final save at the end
|
||||
with open(self.output_path, 'w') as f:
|
||||
with open(self.output_path, "w") as f:
|
||||
json.dump(self.results, f, indent=4)
|
||||
|
||||
return results
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
from openai import OpenAI
|
||||
import os
|
||||
import argparse
|
||||
import json
|
||||
from jinja2 import Template
|
||||
from tqdm import tqdm
|
||||
import os
|
||||
import time
|
||||
from collections import defaultdict
|
||||
|
||||
from dotenv import load_dotenv
|
||||
import argparse
|
||||
from jinja2 import Template
|
||||
from openai import OpenAI
|
||||
from tqdm import tqdm
|
||||
|
||||
load_dotenv()
|
||||
|
||||
@@ -58,23 +59,19 @@ class OpenAIPredict:
|
||||
self.results = defaultdict(list)
|
||||
|
||||
def search_memory(self, idx):
|
||||
|
||||
with open(f'memories/{idx}.txt', 'r') as file:
|
||||
with open(f"memories/{idx}.txt", "r") as file:
|
||||
memories = file.read()
|
||||
|
||||
return memories, 0
|
||||
|
||||
def process_question(self, val, idx):
|
||||
question = val.get('question', '')
|
||||
answer = val.get('answer', '')
|
||||
category = val.get('category', -1)
|
||||
evidence = val.get('evidence', [])
|
||||
adversarial_answer = val.get('adversarial_answer', '')
|
||||
question = val.get("question", "")
|
||||
answer = val.get("answer", "")
|
||||
category = val.get("category", -1)
|
||||
evidence = val.get("evidence", [])
|
||||
adversarial_answer = val.get("adversarial_answer", "")
|
||||
|
||||
response, search_memory_time, response_time, context = self.answer_question(
|
||||
idx,
|
||||
question
|
||||
)
|
||||
response, search_memory_time, response_time, context = self.answer_question(idx, question)
|
||||
|
||||
result = {
|
||||
"question": question,
|
||||
@@ -85,7 +82,7 @@ class OpenAIPredict:
|
||||
"adversarial_answer": adversarial_answer,
|
||||
"search_memory_time": search_memory_time,
|
||||
"response_time": response_time,
|
||||
"context": context
|
||||
"context": context,
|
||||
}
|
||||
|
||||
return result
|
||||
@@ -94,43 +91,35 @@ class OpenAIPredict:
|
||||
memories, search_memory_time = self.search_memory(idx)
|
||||
|
||||
template = Template(ANSWER_PROMPT)
|
||||
answer_prompt = template.render(
|
||||
memories=memories,
|
||||
question=question
|
||||
)
|
||||
answer_prompt = template.render(memories=memories, question=question)
|
||||
|
||||
t1 = time.time()
|
||||
response = self.openai_client.chat.completions.create(
|
||||
model=os.getenv("MODEL"),
|
||||
messages=[
|
||||
{"role": "system", "content": answer_prompt}
|
||||
],
|
||||
temperature=0.0
|
||||
model=os.getenv("MODEL"), messages=[{"role": "system", "content": answer_prompt}], temperature=0.0
|
||||
)
|
||||
t2 = time.time()
|
||||
response_time = t2 - t1
|
||||
return response.choices[0].message.content, search_memory_time, response_time, memories
|
||||
|
||||
def process_data_file(self, file_path, output_file_path):
|
||||
with open(file_path, 'r') as f:
|
||||
with open(file_path, "r") as f:
|
||||
data = json.load(f)
|
||||
|
||||
for idx, item in tqdm(enumerate(data), total=len(data), desc="Processing conversations"):
|
||||
qa = item['qa']
|
||||
qa = item["qa"]
|
||||
|
||||
for question_item in tqdm(qa, total=len(qa), desc=f"Processing questions for conversation {idx}", leave=False):
|
||||
result = self.process_question(
|
||||
question_item,
|
||||
idx
|
||||
)
|
||||
for question_item in tqdm(
|
||||
qa, total=len(qa), desc=f"Processing questions for conversation {idx}", leave=False
|
||||
):
|
||||
result = self.process_question(question_item, idx)
|
||||
self.results[idx].append(result)
|
||||
|
||||
# Save results after each question is processed
|
||||
with open(output_file_path, 'w') as f:
|
||||
with open(output_file_path, "w") as f:
|
||||
json.dump(self.results, f, indent=4)
|
||||
|
||||
# Final save at the end
|
||||
with open(output_file_path, 'w') as f:
|
||||
with open(output_file_path, "w") as f:
|
||||
json.dump(self.results, f, indent=4)
|
||||
|
||||
|
||||
@@ -140,4 +129,3 @@ if __name__ == "__main__":
|
||||
args = parser.parse_args()
|
||||
openai_predict = OpenAIPredict()
|
||||
openai_predict.process_data_file("../../dataset/locomo10.json", args.output_file_path)
|
||||
|
||||
|
||||
+41
-55
@@ -1,13 +1,14 @@
|
||||
from openai import OpenAI
|
||||
import json
|
||||
import numpy as np
|
||||
from tqdm import tqdm
|
||||
from jinja2 import Template
|
||||
import tiktoken
|
||||
import os
|
||||
import time
|
||||
from collections import defaultdict
|
||||
import os
|
||||
|
||||
import numpy as np
|
||||
import tiktoken
|
||||
from dotenv import load_dotenv
|
||||
from jinja2 import Template
|
||||
from openai import OpenAI
|
||||
from tqdm import tqdm
|
||||
|
||||
load_dotenv()
|
||||
|
||||
@@ -32,10 +33,7 @@ class RAGManager:
|
||||
|
||||
def generate_response(self, question, context):
|
||||
template = Template(PROMPT)
|
||||
prompt = template.render(
|
||||
CONTEXT=context,
|
||||
QUESTION=question
|
||||
)
|
||||
prompt = template.render(CONTEXT=context, QUESTION=question)
|
||||
|
||||
max_retries = 3
|
||||
retries = 0
|
||||
@@ -46,19 +44,21 @@ class RAGManager:
|
||||
response = self.client.chat.completions.create(
|
||||
model=self.model,
|
||||
messages=[
|
||||
{"role": "system",
|
||||
"content": "You are a helpful assistant that can answer "
|
||||
"questions based on the provided context."
|
||||
"If the question involves timing, use the conversation date for reference."
|
||||
"Provide the shortest possible answer."
|
||||
"Use words directly from the conversation when possible."
|
||||
"Avoid using subjects in your answer."},
|
||||
{"role": "user", "content": prompt}
|
||||
{
|
||||
"role": "system",
|
||||
"content": "You are a helpful assistant that can answer "
|
||||
"questions based on the provided context."
|
||||
"If the question involves timing, use the conversation date for reference."
|
||||
"Provide the shortest possible answer."
|
||||
"Use words directly from the conversation when possible."
|
||||
"Avoid using subjects in your answer.",
|
||||
},
|
||||
{"role": "user", "content": prompt},
|
||||
],
|
||||
temperature=0
|
||||
temperature=0,
|
||||
)
|
||||
t2 = time.time()
|
||||
return response.choices[0].message.content.strip(), t2-t1
|
||||
return response.choices[0].message.content.strip(), t2 - t1
|
||||
except Exception as e:
|
||||
retries += 1
|
||||
if retries > max_retries:
|
||||
@@ -68,21 +68,16 @@ class RAGManager:
|
||||
def clean_chat_history(self, chat_history):
|
||||
cleaned_chat_history = ""
|
||||
for c in chat_history:
|
||||
cleaned_chat_history += (f"{c['timestamp']} | {c['speaker']}: "
|
||||
f"{c['text']}\n")
|
||||
cleaned_chat_history += f"{c['timestamp']} | {c['speaker']}: " f"{c['text']}\n"
|
||||
|
||||
return cleaned_chat_history
|
||||
|
||||
def calculate_embedding(self, document):
|
||||
response = self.client.embeddings.create(
|
||||
model=os.getenv("EMBEDDING_MODEL"),
|
||||
input=document
|
||||
)
|
||||
response = self.client.embeddings.create(model=os.getenv("EMBEDDING_MODEL"), input=document)
|
||||
return response.data[0].embedding
|
||||
|
||||
def calculate_similarity(self, embedding1, embedding2):
|
||||
return np.dot(embedding1, embedding2) / (
|
||||
np.linalg.norm(embedding1) * np.linalg.norm(embedding2))
|
||||
return np.dot(embedding1, embedding2) / (np.linalg.norm(embedding1) * np.linalg.norm(embedding2))
|
||||
|
||||
def search(self, query, chunks, embeddings, k=1):
|
||||
"""
|
||||
@@ -100,10 +95,7 @@ class RAGManager:
|
||||
"""
|
||||
t1 = time.time()
|
||||
query_embedding = self.calculate_embedding(query)
|
||||
similarities = [
|
||||
self.calculate_similarity(query_embedding, embedding)
|
||||
for embedding in embeddings
|
||||
]
|
||||
similarities = [self.calculate_similarity(query_embedding, embedding) for embedding in embeddings]
|
||||
|
||||
# Get indices of top-k most similar chunks
|
||||
if k == 1:
|
||||
@@ -117,7 +109,7 @@ class RAGManager:
|
||||
combined_chunks = "\n<->\n".join([chunks[i] for i in top_indices])
|
||||
|
||||
t2 = time.time()
|
||||
return combined_chunks, t2-t1
|
||||
return combined_chunks, t2 - t1
|
||||
|
||||
def create_chunks(self, chat_history, chunk_size=500):
|
||||
"""
|
||||
@@ -138,7 +130,7 @@ class RAGManager:
|
||||
|
||||
# Split into chunks based on token count
|
||||
for i in range(0, len(tokens), chunk_size):
|
||||
chunk_tokens = tokens[i:i+chunk_size]
|
||||
chunk_tokens = tokens[i : i + chunk_size]
|
||||
chunk = encoding.decode(chunk_tokens)
|
||||
chunks.append(chunk)
|
||||
|
||||
@@ -158,13 +150,9 @@ class RAGManager:
|
||||
chat_history = value["conversation"]
|
||||
questions = value["question"]
|
||||
|
||||
chunks, embeddings = self.create_chunks(
|
||||
chat_history, self.chunk_size
|
||||
)
|
||||
chunks, embeddings = self.create_chunks(chat_history, self.chunk_size)
|
||||
|
||||
for item in tqdm(
|
||||
questions, desc="Answering questions", leave=False
|
||||
):
|
||||
for item in tqdm(questions, desc="Answering questions", leave=False):
|
||||
question = item["question"]
|
||||
answer = item.get("answer", "")
|
||||
category = item["category"]
|
||||
@@ -173,22 +161,20 @@ class RAGManager:
|
||||
context = chunks[0]
|
||||
search_time = 0
|
||||
else:
|
||||
context, search_time = self.search(
|
||||
question, chunks, embeddings, k=self.k
|
||||
)
|
||||
response, response_time = self.generate_response(
|
||||
question, context
|
||||
)
|
||||
context, search_time = self.search(question, chunks, embeddings, k=self.k)
|
||||
response, response_time = self.generate_response(question, context)
|
||||
|
||||
FINAL_RESULTS[key].append({
|
||||
"question": question,
|
||||
"answer": answer,
|
||||
"category": category,
|
||||
"context": context,
|
||||
"response": response,
|
||||
"search_time": search_time,
|
||||
"response_time": response_time,
|
||||
})
|
||||
FINAL_RESULTS[key].append(
|
||||
{
|
||||
"question": question,
|
||||
"answer": answer,
|
||||
"category": category,
|
||||
"context": context,
|
||||
"response": response,
|
||||
"search_time": search_time,
|
||||
"response_time": response_time,
|
||||
}
|
||||
)
|
||||
with open(output_file_path, "w+") as f:
|
||||
json.dump(FINAL_RESULTS, f, indent=4)
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user