Mem0 1.0.0 (#3545)
This commit is contained in:
+120
-63
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user