Compare commits

..
Author SHA1 Message Date
Paurush Mittal 2e09cc383b docs: clarify structured exports are not raw backups 2026-08-14 00:39:40 +05:30
5 changed files with 18 additions and 67 deletions
@@ -4,10 +4,14 @@ description: "Retrieve, review, and migrate user memories with structured export
---
Mem0 is a dynamic memory store that gives you full control over your data. Along with storing memories, it gives you the ability to retrieve, export, and migrate your data whenever you need.
Mem0 is a dynamic memory store that lets you retrieve memories as raw records or transform them into a structured export for downstream use.
This cookbook shows you how to retrieve and export your data for inspection, migration, or compliance.
<Warning>
The structured export job is not a raw backup. It uses the schema and instructions you provide to transform matching memories. Use paginated `get_all()` calls when you need the original memory records. For an account-level data access or compliance request that the API cannot complete, contact support.
</Warning>
---
## Setup
@@ -254,7 +258,7 @@ You can also export memories directly from the Mem0 platform UI:
3. Select your filters and schema
4. Download the completed export as JSON
This is useful for one-off exports or manual data reviews.
This is useful for one-off structured exports or manual data reviews. It does not create a raw backup of every memory record; use paginated `get_all()` calls for raw retrieval.
<Warning>
Exported data expires after 7 days. Download and store exports locally if you need long-term archives. After expiration, you'll need to recreate the export job.
@@ -272,13 +276,13 @@ A complete memory export system with multiple retrieval methods:
- **Export instructions** - Guide conflict resolution and data formatting
- **Platform UI exports** - One-off manual downloads via dashboard
This covers data portability, GDPR compliance, system migrations, and manual reviews.
These approaches support data inspection, portability workflows, system migrations, and manual reviews. Use raw retrieval or contact support when a compliance request requires the original records rather than a schema-transformed export.
---
## Summary
Use **`get_all()`** for bulk retrieval, **`search()`** for specific questions, and **`create_memory_export()`** for structured data exports with custom schemas. Remember exports expire after 7 days: download them locally for long-term archives.
Use **`get_all()`** for paginated raw retrieval, **`search()`** for specific questions, and **`create_memory_export()`** for schema-transformed data. Structured exports expire after 7 days, so download completed results promptly. Do not treat them as raw backups.
<CardGroup cols={2}>
<Card title="Build a Mem0 Companion" icon="users" href="/cookbooks/essentials/building-ai-companion">
+6
View File
@@ -7,6 +7,10 @@ description: 'Export memories in a structured format using customizable Pydantic
The Memory Export feature allows you to create structured exports of memories using customizable Pydantic schemas. This process enables you to transform your stored memories into specific data formats that match your needs. You can apply various filters to narrow down which memories to export and define exactly how the data should be structured.
<Warning>
Memory Export transforms matching memories into the schema you provide. It is not a raw backup or a byte-for-byte download of every stored memory record. If you need the original memory records, retrieve them with the paginated `get_all()` API instead. For an account-level data access or compliance request that cannot be completed through the API, contact support.
</Warning>
## Creating a Memory Export
To create a memory export, you'll need to:
@@ -278,6 +282,8 @@ You can apply various filters to customize which memories are included in the ex
The export process may take some time to complete, especially when dealing with a large number of memories or complex schemas.
</Note>
If an export remains in progress unexpectedly, do not submit duplicate jobs. Retrieve the job by its export ID to check its status, then contact support with that ID if it does not complete.
If you have any questions, please feel free to reach out to us using one of the following methods:
<Snippet file="get-help.mdx" />
+2 -8
View File
@@ -1,7 +1,7 @@
import hashlib
import logging
import re
from typing import Any, Dict, List, Union
from typing import Any, Dict, List
from mem0.configs.prompts import (
AGENT_MEMORY_EXTRACTION_PROMPT,
@@ -112,7 +112,7 @@ def normalize_facts(raw_facts):
return normalized
def remove_code_blocks(content: Union[str, List[Union[str, Dict[str, Any]]], None]) -> str:
def remove_code_blocks(content: str) -> str:
"""
Removes enclosing code block markers ```[language] and ``` from a given string.
@@ -120,15 +120,9 @@ def remove_code_blocks(content: Union[str, List[Union[str, Dict[str, Any]]], Non
- The function uses a regex pattern to match code blocks that may start with ``` followed by an optional language tag (letters or numbers) and end with ```.
- If a code block is detected, it returns only the inner content, stripping out the markers.
- If no code block markers are found, the original content is returned as-is.
- Block-style content (a LangChain message whose `.content` is a list of text
blocks) is flattened to its concatenated text before matching.
"""
if content is None:
return ""
if isinstance(content, list):
content = "".join(
part if isinstance(part, str) else part.get("text", "") for part in content if isinstance(part, (str, dict))
)
pattern = r"^```[a-zA-Z0-9]*\n([\s\S]*?)\n```$"
match = re.match(pattern, content.strip())
match_res=match.group(1).strip() if match else content.strip()
-18
View File
@@ -192,21 +192,3 @@ class TestProcessTelemetryFilters:
class TestRemoveCodeBlocks:
def test_none_content_returns_empty_string(self):
assert remove_code_blocks(None) == ""
def test_block_list_content_is_flattened(self):
assert remove_code_blocks([{"type": "text", "text": "step one"}]) == "step one"
def test_block_list_content_strips_code_fences(self):
content = [{"type": "text", "text": '```json\n{"a": 1}\n```'}]
assert remove_code_blocks(content) == '{"a": 1}'
def test_block_list_content_joins_multiple_blocks(self):
content = [{"type": "text", "text": "step one. "}, {"type": "text", "text": "step two"}]
assert remove_code_blocks(content) == "step one. step two"
def test_block_list_content_ignores_non_text_blocks(self):
content = [{"type": "thinking", "thinking": "hmm"}, {"type": "text", "text": "answer"}]
assert remove_code_blocks(content) == "answer"
def test_plain_string_blocks_are_supported(self):
assert remove_code_blocks(["step one. ", "step two"]) == "step one. step two"
+2 -37
View File
@@ -1235,9 +1235,8 @@ class TestHybridSearchWarning:
def test_warning_for_store_without_keyword_search(
self, mock_vs_factory, mock_emb, mock_llm, mock_sqlite, _cap, caplog
):
import logging
from mem0.vector_stores.base import VectorStoreBase
import logging
class StoreWithoutKeywordSearch(VectorStoreBase):
def create_col(self, *a, **kw): pass
@@ -1272,9 +1271,8 @@ class TestHybridSearchWarning:
def test_no_warning_for_store_with_keyword_search(
self, mock_vs_factory, mock_emb, mock_llm, mock_sqlite, _cap, caplog
):
import logging
from mem0.vector_stores.base import VectorStoreBase
import logging
class StoreWithKeywordSearch(VectorStoreBase):
def keyword_search(self, query, top_k=5, filters=None):
@@ -1538,39 +1536,6 @@ async def test_async_procedural_memory_langchain_strips_code_blocks(mock_llm_fac
assert "```" not in stored_data
@pytest.mark.asyncio
@patch("mem0.memory.main.VectorStoreFactory")
@patch("mem0.memory.main.EmbedderFactory")
@patch("mem0.memory.main.LlmFactory")
async def test_async_procedural_memory_langchain_block_list_content(mock_llm_factory, mock_emb, mock_vs):
"""Regression #6150: block-list message content must not raise AttributeError."""
mock_vs.return_value = MagicMock()
mock_emb.return_value = MagicMock()
mock_emb.return_value.embed.return_value = [0.1] * 1536
mock_llm_factory.return_value = MagicMock()
from mem0.memory.main import AsyncMemory
config = MemoryConfig()
memory = AsyncMemory(config)
memory.vector_store = MagicMock()
memory.vector_store.insert = MagicMock()
mock_langchain_llm = MagicMock()
mock_response = MagicMock()
mock_response.content = [{"type": "text", "text": '```json\n{"key": "value"}\n```'}]
mock_langchain_llm.invoke.return_value = mock_response
messages = [{"role": "user", "content": "test"}]
metadata = {"user_id": "test_user"}
await memory._create_procedural_memory(messages, metadata=metadata, llm=mock_langchain_llm)
insert_call = memory.vector_store.insert.call_args
stored_data = insert_call[1]["payloads"][0]["data"]
assert stored_data == '{"key": "value"}'
@pytest.mark.asyncio
@patch("mem0.memory.main.VectorStoreFactory")
@patch("mem0.memory.main.EmbedderFactory")