Mem0 1.0.0 (#3545)

This commit is contained in:
Parshva Daftari
2025-10-16 15:50:20 +05:30
committed by GitHub
parent 8f5151c344
commit 394203d1b5
77 changed files with 3445 additions and 990 deletions
+120 -63
View File
@@ -128,16 +128,18 @@ class MemoryClient:
raise ValueError(f"Error: {error_message}")
@api_error_handler
def add(self, messages: List[Dict[str, str]], **kwargs) -> Dict[str, Any]:
def add(self, messages, **kwargs) -> Dict[str, Any]:
"""Add a new memory.
Args:
messages: A list of message dictionaries.
messages: A list of message dictionaries, a single message dictionary,
or a string. If a string is provided, it will be converted to
a user message.
**kwargs: Additional parameters such as user_id, agent_id, app_id,
metadata, filters.
metadata, filters, async_mode.
Returns:
A dictionary containing the API response.
A dictionary containing the API response in v1.1 format.
Raises:
ValidationError: If the input data is invalid.
@@ -147,19 +149,33 @@ class MemoryClient:
NetworkError: If network connectivity issues occur.
MemoryNotFoundError: If the memory doesn't exist (for updates/deletes).
"""
# Handle different message input formats (align with OSS behavior)
if isinstance(messages, str):
messages = [{"role": "user", "content": messages}]
elif isinstance(messages, dict):
messages = [messages]
elif not isinstance(messages, list):
raise ValueError(
f"messages must be str, dict, or list[dict], got {type(messages).__name__}"
)
kwargs = self._prepare_params(kwargs)
if kwargs.get("output_format") != "v1.1":
kwargs["output_format"] = "v1.1"
# Remove deprecated parameters
if "output_format" in kwargs:
warnings.warn(
(
"output_format='v1.0' is deprecated therefore setting it to "
"'v1.1' by default. Check out the docs for more information: "
"https://docs.mem0.ai/platform/quickstart#4-1-create-memories"
),
"output_format parameter is deprecated and ignored. All responses now use v1.1 format.",
DeprecationWarning,
stacklevel=2,
)
kwargs["version"] = "v2"
kwargs.pop("output_format")
# Set async_mode to True by default, but allow user override
if "async_mode" not in kwargs:
kwargs["async_mode"] = True
# Force v1.1 format for all add operations
kwargs["output_format"] = "v1.1"
payload = self._prepare_payload(messages, kwargs)
response = self.client.post("/v1/memories/", json=payload)
response.raise_for_status()
@@ -193,16 +209,15 @@ class MemoryClient:
return response.json()
@api_error_handler
def get_all(self, version: str = "v1", **kwargs) -> List[Dict[str, Any]]:
def get_all(self, **kwargs) -> Dict[str, Any]:
"""Retrieve all memories, with optional filtering.
Args:
version: The API version to use for the search endpoint.
**kwargs: Optional parameters for filtering (user_id, agent_id,
app_id, top_k).
app_id, top_k, page, page_size).
Returns:
A list of dictionaries containing memories.
A dictionary containing memories in v1.1 format: {"results": [...]}
Raises:
ValidationError: If the input data is invalid.
@@ -213,17 +228,17 @@ class MemoryClient:
MemoryNotFoundError: If the memory doesn't exist (for updates/deletes).
"""
params = self._prepare_params(kwargs)
if version == "v1":
response = self.client.get(f"/{version}/memories/", params=params)
elif version == "v2":
if "page" in params and "page_size" in params:
query_params = {
"page": params.pop("page"),
"page_size": params.pop("page_size"),
}
response = self.client.post(f"/{version}/memories/", json=params, params=query_params)
else:
response = self.client.post(f"/{version}/memories/", json=params)
params.pop("output_format", None) # Remove output_format for get operations
params.pop("async_mode", None)
if "page" in params and "page_size" in params:
query_params = {
"page": params.pop("page"),
"page_size": params.pop("page_size"),
}
response = self.client.post("/v2/memories/", json=params, params=query_params)
else:
response = self.client.post("/v2/memories/", json=params)
response.raise_for_status()
if "metadata" in kwargs:
del kwargs["metadata"]
@@ -231,25 +246,29 @@ class MemoryClient:
"client.get_all",
self,
{
"api_version": version,
"api_version": "v2",
"keys": list(kwargs.keys()),
"sync_type": "sync",
},
)
return response.json()
result = response.json()
# Ensure v1.1 format (wrap raw list if needed)
if isinstance(result, list):
return {"results": result}
return result
@api_error_handler
def search(self, query: str, version: str = "v1", **kwargs) -> List[Dict[str, Any]]:
def search(self, query: str, **kwargs) -> Dict[str, Any]:
"""Search memories based on a query.
Args:
query: The search query string.
version: The API version to use for the search endpoint.
**kwargs: Additional parameters such as user_id, agent_id, app_id,
top_k, filters.
Returns:
A list of dictionaries containing search results.
A dictionary containing search results in v1.1 format: {"results": [...]}
Raises:
ValidationError: If the input data is invalid.
@@ -261,8 +280,12 @@ class MemoryClient:
"""
payload = {"query": query}
params = self._prepare_params(kwargs)
params.pop("output_format", None) # Remove output_format for search operations
params.pop("async_mode", None)
payload.update(params)
response = self.client.post(f"/{version}/memories/search/", json=payload)
response = self.client.post("/v2/memories/search/", json=payload)
response.raise_for_status()
if "metadata" in kwargs:
del kwargs["metadata"]
@@ -270,12 +293,17 @@ class MemoryClient:
"client.search",
self,
{
"api_version": version,
"api_version": "v2",
"keys": list(kwargs.keys()),
"sync_type": "sync",
},
)
return response.json()
result = response.json()
# Ensure v1.1 format (wrap raw list if needed)
if isinstance(result, list):
return {"results": result}
return result
@api_error_handler
def update(
@@ -1062,20 +1090,34 @@ class AsyncMemoryClient:
await self.async_client.aclose()
@api_error_handler
async def add(self, messages: List[Dict[str, str]], **kwargs) -> Dict[str, Any]:
async def add(self, messages, **kwargs) -> Dict[str, Any]:
# Handle different message input formats (align with OSS behavior)
if isinstance(messages, str):
messages = [{"role": "user", "content": messages}]
elif isinstance(messages, dict):
messages = [messages]
elif not isinstance(messages, list):
raise ValueError(
f"messages must be str, dict, or list[dict], got {type(messages).__name__}"
)
kwargs = self._prepare_params(kwargs)
if kwargs.get("output_format") != "v1.1":
kwargs["output_format"] = "v1.1"
# Remove deprecated parameters
if "output_format" in kwargs:
warnings.warn(
(
"output_format='v1.0' is deprecated therefore setting it to "
"'v1.1' by default. Check out the docs for more information: "
"https://docs.mem0.ai/platform/quickstart#4-1-create-memories"
),
"output_format parameter is deprecated and ignored. All responses now use v1.1 format.",
DeprecationWarning,
stacklevel=2,
)
kwargs["version"] = "v2"
kwargs.pop("output_format")
# Set async_mode to True by default, but allow user override
if "async_mode" not in kwargs:
kwargs["async_mode"] = True
# Force v1.1 format for all add operations
kwargs["output_format"] = "v1.1"
payload = self._prepare_payload(messages, kwargs)
response = await self.async_client.post("/v1/memories/", json=payload)
response.raise_for_status()
@@ -1093,19 +1135,19 @@ class AsyncMemoryClient:
return response.json()
@api_error_handler
async def get_all(self, version: str = "v1", **kwargs) -> List[Dict[str, Any]]:
async def get_all(self, **kwargs) -> Dict[str, Any]:
params = self._prepare_params(kwargs)
if version == "v1":
response = await self.async_client.get(f"/{version}/memories/", params=params)
elif version == "v2":
if "page" in params and "page_size" in params:
query_params = {
"page": params.pop("page"),
"page_size": params.pop("page_size"),
}
response = await self.async_client.post(f"/{version}/memories/", json=params, params=query_params)
else:
response = await self.async_client.post(f"/{version}/memories/", json=params)
params.pop("output_format", None) # Remove output_format for get operations
params.pop("async_mode", None)
if "page" in params and "page_size" in params:
query_params = {
"page": params.pop("page"),
"page_size": params.pop("page_size"),
}
response = await self.async_client.post("/v2/memories/", json=params, params=query_params)
else:
response = await self.async_client.post("/v2/memories/", json=params)
response.raise_for_status()
if "metadata" in kwargs:
del kwargs["metadata"]
@@ -1113,18 +1155,28 @@ class AsyncMemoryClient:
"client.get_all",
self,
{
"api_version": version,
"api_version": "v2",
"keys": list(kwargs.keys()),
"sync_type": "async",
},
)
return response.json()
result = response.json()
# Ensure v1.1 format (wrap raw list if needed)
if isinstance(result, list):
return {"results": result}
return result
@api_error_handler
async def search(self, query: str, version: str = "v1", **kwargs) -> List[Dict[str, Any]]:
async def search(self, query: str, **kwargs) -> Dict[str, Any]:
payload = {"query": query}
payload.update(self._prepare_params(kwargs))
response = await self.async_client.post(f"/{version}/memories/search/", json=payload)
params = self._prepare_params(kwargs)
params.pop("output_format", None) # Remove output_format for search operations
params.pop("async_mode", None)
payload.update(params)
response = await self.async_client.post("/v2/memories/search/", json=payload)
response.raise_for_status()
if "metadata" in kwargs:
del kwargs["metadata"]
@@ -1132,12 +1184,17 @@ class AsyncMemoryClient:
"client.search",
self,
{
"api_version": version,
"api_version": "v2",
"keys": list(kwargs.keys()),
"sync_type": "async",
},
)
return response.json()
result = response.json()
# Ensure v1.1 format (wrap raw list if needed)
if isinstance(result, list):
return {"results": result}
return result
@api_error_handler
async def update(