diff --git a/docs/images/platform/activity.png b/docs/images/platform/activity.png new file mode 100644 index 00000000..bdd6c537 Binary files /dev/null and b/docs/images/platform/activity.png differ diff --git a/docs/images/platform/api-key.png b/docs/images/platform/api-key.png new file mode 100644 index 00000000..611f16ac Binary files /dev/null and b/docs/images/platform/api-key.png differ diff --git a/docs/mint.json b/docs/mint.json index 5a5c9ef0..4325b049 100644 --- a/docs/mint.json +++ b/docs/mint.json @@ -20,6 +20,10 @@ { "name": "💡 Examples", "url": "examples" + }, + { + "name": "🖥️ Platform", + "url": "platform" } ], "topbarLinks": [ @@ -73,6 +77,13 @@ "examples/customer-support-agent", "examples/personal-travel-assistant" ] + }, + { + "group": "🖥️ Platform", + "pages": [ + "platform/overview", + "platform/quickstart" + ] } ], "footerSocials": { diff --git a/docs/platform/overview.mdx b/docs/platform/overview.mdx new file mode 100644 index 00000000..424f8cb4 --- /dev/null +++ b/docs/platform/overview.mdx @@ -0,0 +1,45 @@ +--- +title: Introduction +description: 'Empower your AI applications with long-term memory and personalization' +--- + +## Welcome to Mem0 Platform + +Mem0 Platform is a managed service that revolutionizes the way AI applications handle memory. By providing a smart, self-improving memory layer for Large Language Models (LLMs), we enable developers to create personalized AI experiences that evolve with each user interaction. + +## Why Choose Mem0 Platform? + +1. **Enhanced User Experience**: Deliver tailored interactions that make your AI applications truly stand out. +2. **Simplified Development**: Our API-first approach streamlines integration, allowing you to focus on building great features. +3. **Scalable Solution**: Designed to grow with your application, from prototypes to production-ready systems. + +## Key Features + +- **Comprehensive Memory Management**: Easily manage long-term, short-term, semantic, and episodic memories for individual users, agents, and sessions through our robust APIs. +- **Self-Improving Memory**: Our adaptive system continuously learns from user interactions, refining its understanding over time. +- **Cross-Platform Consistency**: Ensure a unified user experience across various AI platforms and applications. +- **Centralized Memory Control**: Store, update, and delete memories effortlessly, taking away the hassle of memory management. + +## Common Use Cases + +- Personalized Learning Assistants +- Customer Support AI Agents +- Healthcare Assistants +- Virtual Companions +- Productivity Tools +- Gaming AI + +## Getting Started +Ready to supercharge your AI application with Mem0? Follow these steps: + +1. **Sign Up**: Create your Mem0 account at our platform. +2. **API Key**: Generate your API key in the dashboard. +3. **Installation**: Install our Python SDK using pip: `pip install mem0ai` +4. **Quick Implementation**: Check out our [Quickstart Guide](/platform/quickstart) to start using Mem0 quickly. + +## Next Steps + +- Explore our API Reference for detailed endpoint documentation. +- Join our [slack](https://mem0.ai/slack) or [discord](https://mem0.ai/discord) 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! diff --git a/docs/platform/quickstart.mdx b/docs/platform/quickstart.mdx new file mode 100644 index 00000000..b4171b51 --- /dev/null +++ b/docs/platform/quickstart.mdx @@ -0,0 +1,358 @@ +--- +title: Quickstart +description: 'Get started with Mem0 Platform in minutes' +--- + +## 1. Installation + +Install the Mem0 Python package: + +```bash +pip install mem0ai +``` + +## 2. API Key Setup + +1. Sign in to [Mem0 Platform](https://app.mem0.ai/dashboard/api-keys) +2. Copy your API Key from the dashboard + +![Get API Key from Mem0 Platform](/images/platform/api-key.png) + +## 3. Instantiate Client + +```python +from mem0 import MemoryClient +client = MemoryClient(api_key="your-api-key") +``` + +## 4. Memory Operations + +We provide a simple yet customizable interface for performing CRUD operations on memory. Here is how you can create and get memories: + + +### 4.1 Create Memories + +For users (long-term memory): + +```python +# create long-term memory for users +client.add("Remember my name is Deshraj Yadav.", user_id="deshraj") +client.add("I like to eat pizza and go out on weekends.", user_id="deshraj") +client.add("Oh I am actually allergic to cheese to cannot eat pizza anymore.", user_id="deshraj") +``` + +Output: +```python +{'message': 'Memory added successfully!'} +``` + +You can see all the memory operations happening on the platform itself. + +![Mem0 Platform Activity](/images/platform/activity.png) + + +You can also add memories for a particular session or for an AI agent that you are building: + +- For user sessions (short-term memory): + +```python +client.add("Deshraj is building Gmail AI agent", user_id="deshraj", session_id="session-1") +``` + +- For agents (long-term memory): + +```python +client.add("Return short responses when responding to emails", agent_id="gmail-agent") +``` + +### 4.2 Retrieve Memories + + + + +```python Code +client.get_all(user_id="deshraj") +``` + +```python Output +[ + { + 'id': 'dbce6e06-6adf-40b8-9187-3d30bd13b741', + 'agent': None, + 'consumer': { + 'id': 8, + 'user_id': 'deshraj', + 'metadata': None, + 'created_at': '2024-07-17T16:47:23.899900-07:00', + 'updated_at': '2024-07-17T16:47:23.899918-07:00' + }, + 'app': None, + 'run': None, + 'hash': '57288ac8a87c4ac8d3ac7f2075d264ca', + 'input': 'Remember my name is Deshraj Yadav.', + 'text': 'My name is Deshraj Yadav.', + 'metadata': None, + 'created_at': '2024-07-17T16:47:25.670180-07:00', + 'updated_at': '2024-07-17T16:47:25.670197-07:00' + }, + { + 'id': 'f6dec5d1-b5db-45f5-a2fb-3979a0f27d30', + 'agent': None, + 'consumer': { + 'id': 8, + 'user_id': 'deshraj', + # ... other consumer fields ... + }, + # ... other fields ... + 'text': 'I am allergic to cheese so I cannot eat pizza anymore.', + # ... remaining fields ... + }, + # ... additional memory entries ... +] +``` + + +Similarly, you can get all memories for an agent: + +```python +agent_memories = client.get_all(agent_id="gmail-agent") +``` + +Get specific memory: + + + +```python Code +memory = client.get(memory_id="dbce6e06-6adf-40b8-9187-3d30bd13b741") +``` + +```python Output +{ + 'id': 'dbce6e06-6adf-40b8-9187-3d30bd13b741', + 'agent': None, + 'consumer': { + 'id': 8, + 'user_id': 'deshraj', + 'metadata': None, + 'created_at': '2024-07-17T16:47:23.899900-07:00', + 'updated_at': '2024-07-17T16:47:23.899918-07:00' + }, + 'app': None, + 'run': None, + 'hash': '57288ac8a87c4ac8d3ac7f2075d264ca', + 'input': 'Remember my name is Deshraj Yadav.', + 'text': 'My name is Deshraj Yadav.', + 'metadata': None, + 'created_at': '2024-07-17T16:47:25.670180-07:00', + 'updated_at': '2024-07-17T16:47:25.670197-07:00' +} +``` + + +### 4.3 Update Memory + +You can also update specific memory by using the following method: + + + +```python Code +client.update(memory_id, data="Updated name is Deshraj Kumar") +``` + +```python Output +{ + 'id': 'dbce6e06-6adf-40b8-9187-3d30bd13b741', + 'agent': None, + 'consumer': { + 'id': 8, + 'user_id': 'deshraj', + 'metadata': None, + 'created_at': '2024-07-17T16:47:23.899900-07:00', + 'updated_at': '2024-07-17T16:47:23.899918-07:00' + }, + 'app': None, + 'run': None, + 'hash': '57288ac8a87c4ac8d3ac7f2075d264ca', + 'input': 'Updated name is Deshraj Kumar.', + 'text': 'Name is Deshraj Kumar.', + 'metadata': None, + 'created_at': '2024-07-17T16:47:25.670180-07:00', + 'updated_at': '2024-07-17T16:47:25.670197-07:00' +} +``` + + + +### 4.4 Memory History + +Get history of how a memory has changed over time + + + +```python Code +history = client.history(memory_id) +``` + +```python Output +[ + { + 'id': '51193804-2ee6-4f81-b4e7-497e98b70858', + 'memory': { + 'id': 'dbce6e06-6adf-40b8-9187-3d30bd13b741', + 'agent': None, + 'consumer': { + 'id': 8, + 'user_id': 'deshraj', + 'metadata': None, + 'created_at': '2024-07-17T16:47:23.899900-07:00', + 'updated_at': '2024-07-17T16:47:23.899918-07:00' + }, + 'app': None, + 'run': None, + 'hash': '57288ac8a87c4ac8d3ac7f2075d264ca', + 'input': 'Remember my name is Deshraj Yadav.', + 'text': 'My name is Deshraj Yadav.', + 'metadata': None, + 'created_at': '2024-07-17T16:47:25.670180-07:00', + 'updated_at': '2024-07-17T16:47:25.670197-07:00' + }, + 'hash': '57288ac8a87c4ac8d3ac7f2075d264ca', + 'event': 'ADD', + 'input': 'Remember my name is Deshraj Yadav.', + 'previous_text': None, + 'text': 'My name is Deshraj Yadav.', + 'metadata': None, + 'created_at': '2024-07-17T16:47:25.686899-07:00', + 'updated_at': '2024-07-17T16:47:25.670197-07:00', + 'change_description': 'Memory ADD event' + } +] +``` + + +### 4.5 Search for relevant memories + + + +```python Code +client.search("What does Deshraj like to eat?", user_id="deshraj", limit=3) +``` + +```python Output +[ + { + "id": "dbce6e06-6adf-40b8-9187-3d30bd13b741", + "agent": null, + "consumer": { + "id": 8, + "user_id": "deshraj", + "metadata": null, + "created_at": "...", + "updated_at": "..." + }, + "app": null, + "run": null, + "hash": "57288ac8a87c4ac8d3ac7f2075d264ca", + "input": "Remember my name is Deshraj Yadav.", + "text": "My name is Deshraj Yadav.", + "metadata": null, + "created_at": "2024-07-17T16:47:25.670180-07:00", + "updated_at": "..." + }, + { + "id": "091dbed6-74b4-4e15-b765-81be2abe0d6b", + "agent": null, + "consumer": { + "id": 8, + "user_id": "deshraj", + "metadata": null, + "created_at": "...", + "updated_at": "..." + }, + "app": null, + "run": null, + "hash": "622a5a24d5ac54136414a22ec12f9520", + "input": "Oh I am actually allergic to cheese to cannot eat pizza anymore.", + "text": "I like to eat pizza and go out on weekends.", + "metadata": null, + "created_at": "2024-07-17T16:49:24.276695-07:00", + "updated_at": "..." + }, + { + "id": "5fb8f85d-3383-4bad-9d46-f171272478a4", + "agent": null, + "consumer": { + "id": 8, + "user_id": "deshraj", + "metadata": null, + "created_at": "...", + "updated_at": "..." + }, + "app": null, + "run": { + "id": 1, + "run_id": "session-1", + "name": "", + "metadata": null, + "created_at": "...", + "updated_at": "..." + }, + "hash": "179ced9649ac2b85350ece4946b1ee9b", + "input": "Deshraj is building Gmail AI agent", + "text": "Deshraj is building Gmail AI agent", + "metadata": null, + "created_at": "2024-07-17T16:52:41.278920-07:00", + "updated_at": "..." + }, + { + "id": "f6dec5d1-b5db-45f5-a2fb-3979a0f27d30", + "agent": null, + "consumer": { + "id": 8, + "user_id": "deshraj", + "metadata": null, + "created_at": "...", + "updated_at": "..." + }, + "app": null, + "run": null, + "hash": "19248f0766044b5973fc0ef1bf3955ef", + "input": "Oh I am actually allergic to cheese to cannot eat pizza anymore.", + "text": "I am allergic to cheese so I cannot eat pizza anymore.", + "metadata": null, + "created_at": "2024-07-17T16:49:38.622084-07:00", + "updated_at": "..." + } +] +``` + + + +### 4.6 Delete Memory + +Delete specific memory: + + + +```python Code +client.delete(memory_id) +``` + +```python Output +{'message': 'Memory deleted successfully!'} +``` + + + +Delete all memories of a user: + + + +```python Code +client.delete_all(user_id="alex") +``` + +```python Output +{'message': 'Memories deleted successfully!'} +``` + diff --git a/mem0/__init__.py b/mem0/__init__.py index dd185ecf..0433062e 100644 --- a/mem0/__init__.py +++ b/mem0/__init__.py @@ -3,3 +3,4 @@ import importlib.metadata __version__ = importlib.metadata.version("mem0ai") from mem0.memory.main import Memory # noqa +from mem0.client.main import MemoryClient # noqa diff --git a/mem0/client/__init__.py b/mem0/client/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/mem0/client/main.py b/mem0/client/main.py new file mode 100644 index 00000000..54df4709 --- /dev/null +++ b/mem0/client/main.py @@ -0,0 +1,243 @@ +import httpx +import os +import logging +import warnings +from typing import Optional, Dict, Any +from mem0.memory.setup import setup_config +from mem0.memory.telemetry import capture_client_event + +logger = logging.getLogger(__name__) + +# Setup user config +setup_config() + + +class MemoryClient: + def __init__(self, api_key: Optional[str] = None, host: Optional[str] = None): + """ + Initialize the Mem0 client. + + Args: + api_key (Optional[str]): API Key from Mem0 Platform. Defaults to environment variable 'MEM0_API_KEY' if not provided. + host (Optional[str]): API host URL. Defaults to 'https://api.mem0.ai/v1'. + """ + self.api_key = api_key or os.getenv("MEM0_API_KEY") + self.host = host or "https://api.mem0.ai/v1" + self.client = httpx.Client( + base_url=self.host, + headers={"Authorization": f"Token {self.api_key}"}, + ) + self._validate_api_key() + capture_client_event("client.init", self) + + def _validate_api_key(self): + if not self.api_key: + warnings.warn("API Key not provided. Please provide an API Key.") + response = self.client.get("/memories/", params={"user_id": "test"}) + if response.status_code != 200: + raise ValueError( + "Invalid API Key. Please get a valid API Key from https://app.mem0.ai" + ) + + def add( + self, + data: str, + user_id: Optional[str] = None, + agent_id: Optional[str] = None, + session_id: Optional[str] = None, + metadata: Optional[Dict[str, Any]] = None, + filters: Optional[Dict[str, Any]] = None, + ) -> Dict[str, Any]: + """ + Create a new memory. + + Args: + data (str): The data to be stored in the memory. + user_id (Optional[str]): User ID to save the memory specific to a user. Defaults to None. + agent_id (Optional[str]): Agent ID for agent-specific memory. Defaults to None. + session_id (Optional[str]): Run ID to save memory for a specific session. Defaults to None. + metadata (Optional[Dict[str, Any]]): Metadata to be saved with the memory. Defaults to None. + filters (Optional[Dict[str, Any]]): Filters to apply to the memory. Defaults to None. + + Returns: + Dict[str, Any]: The response from the server. + """ + capture_client_event("client.add", self) + payload = {"text": data} + if metadata: + payload["metadata"] = metadata + if filters: + payload["filters"] = filters + if user_id: + payload["user_id"] = user_id + if agent_id: + payload["agent_id"] = agent_id + if session_id: + payload["run_id"] = session_id + + response = self.client.post("/memories/", json=payload, timeout=60) + if response.status_code != 200: + logger.error(response.json()) + raise ValueError(f"Failed to add memory. Response: {response.json()}") + return response.json() + + def get(self, memory_id: str) -> Dict[str, Any]: + """ + Get a memory by ID. + + Args: + memory_id (str): Memory ID. + + Returns: + Dict[str, Any]: The memory data. + """ + capture_client_event("client.get", self) + response = self.client.get(f"/memories/{memory_id}/") + return response.json() + + def get_all( + self, + user_id: Optional[str] = None, + agent_id: Optional[str] = None, + session_id: Optional[str] = None, + limit: int = 100, + ) -> Dict[str, Any]: + """ + Get all memories. + + Args: + user_id (Optional[str]): User ID to filter memories. Defaults to None. + agent_id (Optional[str]): Agent ID to filter memories. Defaults to None. + session_id (Optional[str]): Run ID to filter memories. Defaults to None. + limit (int): Number of memories to return. Defaults to 100. + + Returns: + Dict[str, Any]: The list of memories. + """ + params = { + "user_id": user_id, + "agent_id": agent_id, + "run_id": session_id, + "limit": limit, + } + response = self.client.get( + "/memories/", params={k: v for k, v in params.items() if v is not None} + ) + capture_client_event( + "client.get_all", self, {"filters": len(params), "limit": limit} + ) + return response.json() + + def search( + self, + query: str, + user_id: Optional[str] = None, + agent_id: Optional[str] = None, + session_id: Optional[str] = None, + limit: int = 100, + filters: Optional[Dict[str, Any]] = None, + ) -> Dict[str, Any]: + """ + Search memories. + + Args: + query (str): Query to search for in the memories. + user_id (Optional[str]): User ID to filter memories. Defaults to None. + agent_id (Optional[str]): Agent ID to filter memories. Defaults to None. + session_id (Optional[str]): Run ID to filter memories. Defaults to None. + limit (int): Number of memories to return. Defaults to 100. + filters (Optional[Dict[str, Any]]): Filters to apply to the search. Defaults to None. + + Returns: + Dict[str, Any]: The search results. + """ + payload = { + "text": query, + "limit": limit, + "filters": filters, + "user_id": user_id, + "agent_id": agent_id, + "run_id": session_id, + } + response = self.client.post("/memories/search/", json=payload) + capture_client_event("client.search", self, {"limit": limit}) + return response.json() + + def update(self, memory_id: str, data: str) -> Dict[str, Any]: + """ + Update a memory by ID. + + Args: + memory_id (str): Memory ID. + data (str): Data to update in the memory. + + Returns: + Dict[str, Any]: The response from the server. + """ + capture_client_event("client.update", self) + response = self.client.put(f"/memories/{memory_id}/", json={"text": data}) + return response.json() + + def delete(self, memory_id: str) -> Dict[str, Any]: + """ + Delete a memory by ID. + + Args: + memory_id (str): Memory ID. + + Returns: + Dict[str, Any]: The response from the server. + """ + capture_client_event("client.delete", self) + response = self.client.delete(f"/memories/{memory_id}/") + return response.json() + + def delete_all( + self, + user_id: Optional[str] = None, + agent_id: Optional[str] = None, + session_id: Optional[str] = None, + ) -> Dict[str, Any]: + """ + Delete all memories. + + Args: + user_id (Optional[str]): User ID to filter memories. Defaults to None. + agent_id (Optional[str]): Agent ID to filter memories. Defaults to None. + session_id (Optional[str]): Run ID to filter memories. Defaults to None. + + Returns: + Dict[str, Any]: The response from the server. + """ + params = {"user_id": user_id, "agent_id": agent_id, "run_id": session_id} + response = self.client.delete( + "/memories/", params={k: v for k, v in params.items() if v is not None} + ) + capture_client_event("client.delete_all", self, {"params": len(params)}) + return response.json() + + def history(self, memory_id: str) -> Dict[str, Any]: + """ + Get history of a memory by ID. + + Args: + memory_id (str): Memory ID. + + Returns: + Dict[str, Any]: The memory history. + """ + response = self.client.get(f"/memories/{memory_id}/history/") + capture_client_event("client.history", self) + return response.json() + + def reset(self): + """ + Reset the client. (Not implemented yet) + """ + raise NotImplementedError("Reset is not implemented yet") + + def chat(self): + """ + Start a chat with the Mem0 AI. (Not implemented yet) + """ + raise NotImplementedError("Chat is not implemented yet") diff --git a/mem0/memory/telemetry.py b/mem0/memory/telemetry.py index 804e0be3..b894e257 100644 --- a/mem0/memory/telemetry.py +++ b/mem0/memory/telemetry.py @@ -59,3 +59,13 @@ def capture_event(event_name, memory_instance, additional_data=None): event_data.update(additional_data) telemetry.capture_event(event_name, event_data) + + +def capture_client_event(event_name, instance, additional_data=None): + event_data = { + "function": f"{instance.__class__.__module__}.{instance.__class__.__name__}", + } + if additional_data: + event_data.update(additional_data) + + telemetry.capture_event(event_name, event_data) diff --git a/pyproject.toml b/pyproject.toml index 83bce0ab..ee437af6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "mem0ai" -version = "0.0.4" +version = "0.0.5" description = "Long-term memory for AI Agents" authors = ["Deshraj Yadav ", "Taranjeet Singh "] exclude = [