Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions mem0/client/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def wrapper(*args, **kwargs):
return func(*args, **kwargs)
except httpx.HTTPStatusError as e:
logger.error(f"HTTP error occurred: {e}")

# Extract error details from response
response_text = ""
error_details = {}
Expand All @@ -47,7 +47,7 @@ def wrapper(*args, **kwargs):
"url": str(e.request.url),
"method": e.request.method,
}

try:
response_text = e.response.text
# Try to parse JSON response for additional error details
Expand All @@ -59,7 +59,7 @@ def wrapper(*args, **kwargs):
except (json.JSONDecodeError, AttributeError):
# Fallback to plain text response
pass

# Add rate limit information if available
if e.response.status_code == 429:
retry_after = e.response.headers.get("Retry-After")
Expand All @@ -68,26 +68,26 @@ def wrapper(*args, **kwargs):
debug_info["retry_after"] = int(retry_after)
except ValueError:
pass

# Add rate limit headers if available
for header in ["X-RateLimit-Limit", "X-RateLimit-Remaining", "X-RateLimit-Reset"]:
value = e.response.headers.get(header)
if value:
debug_info[header.lower().replace("-", "_")] = value

# Create specific exception based on status code
exception = create_exception_from_response(
status_code=e.response.status_code,
response_text=response_text,
details=error_details,
debug_info=debug_info,
)

raise exception

except httpx.RequestError as e:
logger.error(f"Request error occurred: {e}")

# Determine the appropriate exception type based on error type
if isinstance(e, httpx.TimeoutException):
raise NetworkError(
Expand Down
26 changes: 13 additions & 13 deletions mem0/configs/llms/aws_bedrock.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,13 +95,13 @@ def get_aws_config(self) -> Dict[str, Any]:

if self.aws_access_key_id:
config["aws_access_key_id"] = self.aws_access_key_id or os.getenv("AWS_ACCESS_KEY_ID")

if self.aws_secret_access_key:
config["aws_secret_access_key"] = self.aws_secret_access_key or os.getenv("AWS_SECRET_ACCESS_KEY")

if self.aws_session_token:
config["aws_session_token"] = self.aws_session_token or os.getenv("AWS_SESSION_TOKEN")

if self.aws_profile:
config["profile_name"] = self.aws_profile or os.getenv("AWS_PROFILE")

Expand All @@ -116,27 +116,27 @@ def validate_model_format(self) -> bool:
"""
if not self.model:
return False

# Check if model follows provider.model-name format
if "." not in self.model:
return False

provider, model_name = self.model.split(".", 1)

# Validate provider
valid_providers = [
"ai21", "amazon", "anthropic", "cohere", "meta", "mistral",
"stability", "writer", "deepseek", "gpt-oss", "perplexity",
"ai21", "amazon", "anthropic", "cohere", "meta", "mistral",
"stability", "writer", "deepseek", "gpt-oss", "perplexity",
"snowflake", "titan", "command", "j2", "llama"
]

if provider not in valid_providers:
return False

# Validate model name is not empty
if not model_name:
return False

return True

def get_supported_regions(self) -> List[str]:
Expand All @@ -158,7 +158,7 @@ def get_model_capabilities(self) -> Dict[str, Any]:
"supports_streaming": False,
"supports_multimodal": False,
}

if self.provider == "anthropic":
capabilities.update({
"supports_tools": True,
Expand Down Expand Up @@ -188,5 +188,5 @@ def get_model_capabilities(self) -> Dict[str, Any]:
"supports_vision": True,
"supports_streaming": True,
})

return capabilities
12 changes: 6 additions & 6 deletions mem0/configs/vector_stores/chroma.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,24 +23,24 @@ class ChromaDbConfig(BaseModel):
def check_connection_config(cls, values):
host, port, path = values.get("host"), values.get("port"), values.get("path")
api_key, tenant = values.get("api_key"), values.get("tenant")

# Check if cloud configuration is provided
cloud_config = bool(api_key and tenant)

# If cloud configuration is provided, remove any default path that might have been added
if cloud_config and path == "/tmp/chroma":
values.pop("path", None)
return values

# Check if local/server configuration is provided (excluding default tmp path for cloud config)
local_config = bool(path and path != "/tmp/chroma") or bool(host and port)

if not cloud_config and not local_config:
raise ValueError("Either ChromaDB Cloud configuration (api_key, tenant) or local configuration (path or host/port) must be provided.")

if cloud_config and local_config:
raise ValueError("Cannot specify both cloud configuration and local configuration. Choose one.")

return values

@model_validator(mode="before")
Expand Down
4 changes: 2 additions & 2 deletions mem0/configs/vector_stores/elasticsearch.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,12 @@ def validate_headers(cls, values: Dict[str, Any]) -> Dict[str, Any]:
# Check if headers is a dictionary
if not isinstance(headers, dict):
raise ValueError("headers must be a dictionary")

# Check if all keys and values are strings
for key, value in headers.items():
if not isinstance(key, str) or not isinstance(value, str):
raise ValueError("All header keys and values must be strings")

return values

@model_validator(mode="before")
Expand Down
2 changes: 1 addition & 1 deletion mem0/configs/vector_stores/pgvector.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def check_auth_and_connection(cls, values):
# If connection_string is provided, skip validation of individual connection parameters
if values.get("connection_string") is not None:
return values

# Otherwise, validate individual connection parameters
user, password = values.get("user"), values.get("password")
host, port = values.get("host"), values.get("port")
Expand Down
2 changes: 1 addition & 1 deletion mem0/embeddings/aws_bedrock.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def __init__(self, config: Optional[BaseEmbedderConfig] = None):
aws_access_key = self.config.aws_access_key_id
if hasattr(self.config, "aws_secret_access_key"):
aws_secret_key = self.config.aws_secret_access_key

# AWS region is always set in config - see BaseEmbedderConfig
aws_region = self.config.aws_region or "us-west-2"

Expand Down
38 changes: 19 additions & 19 deletions mem0/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class MemoryError(Exception):
debug_info={"request_id": "req_456", "timestamp": "2024-01-01T00:00:00Z"}
)
"""

def __init__(
self,
message: str,
Expand All @@ -78,7 +78,7 @@ def __init__(
self.suggestion = suggestion
self.debug_info = debug_info or {}
super().__init__(self.message)

def __repr__(self) -> str:
return (
f"{self.__class__.__name__}("
Expand Down Expand Up @@ -315,8 +315,8 @@ class VectorStoreError(MemoryError):
suggestion="Please check your vector store configuration and connection"
)
"""
def __init__(self, message: str, error_code: str = "VECTOR_001", details: dict = None,
suggestion: str = "Please check your vector store configuration and connection",
def __init__(self, message: str, error_code: str = "VECTOR_001", details: dict = None,
suggestion: str = "Please check your vector store configuration and connection",
debug_info: dict = None):
super().__init__(message, error_code, details, suggestion, debug_info)

Expand All @@ -335,8 +335,8 @@ class GraphStoreError(MemoryError):
suggestion="Please check your graph store configuration and connection"
)
"""
def __init__(self, message: str, error_code: str = "GRAPH_001", details: dict = None,
suggestion: str = "Please check your graph store configuration and connection",
def __init__(self, message: str, error_code: str = "GRAPH_001", details: dict = None,
suggestion: str = "Please check your graph store configuration and connection",
debug_info: dict = None):
super().__init__(message, error_code, details, suggestion, debug_info)

Expand All @@ -355,8 +355,8 @@ class EmbeddingError(MemoryError):
suggestion="Please check your embedding model configuration"
)
"""
def __init__(self, message: str, error_code: str = "EMBED_001", details: dict = None,
suggestion: str = "Please check your embedding model configuration",
def __init__(self, message: str, error_code: str = "EMBED_001", details: dict = None,
suggestion: str = "Please check your embedding model configuration",
debug_info: dict = None):
super().__init__(message, error_code, details, suggestion, debug_info)

Expand All @@ -375,8 +375,8 @@ class LLMError(MemoryError):
suggestion="Please check your LLM configuration and API key"
)
"""
def __init__(self, message: str, error_code: str = "LLM_001", details: dict = None,
suggestion: str = "Please check your LLM configuration and API key",
def __init__(self, message: str, error_code: str = "LLM_001", details: dict = None,
suggestion: str = "Please check your LLM configuration and API key",
debug_info: dict = None):
super().__init__(message, error_code, details, suggestion, debug_info)

Expand All @@ -395,8 +395,8 @@ class DatabaseError(MemoryError):
suggestion="Please check your database configuration and connection"
)
"""
def __init__(self, message: str, error_code: str = "DB_001", details: dict = None,
suggestion: str = "Please check your database configuration and connection",
def __init__(self, message: str, error_code: str = "DB_001", details: dict = None,
suggestion: str = "Please check your database configuration and connection",
debug_info: dict = None):
super().__init__(message, error_code, details, suggestion, debug_info)

Expand All @@ -415,8 +415,8 @@ class DependencyError(MemoryError):
suggestion="Please install the required dependencies: pip install kuzu"
)
"""
def __init__(self, message: str, error_code: str = "DEPS_001", details: dict = None,
suggestion: str = "Please install the required dependencies",
def __init__(self, message: str, error_code: str = "DEPS_001", details: dict = None,
suggestion: str = "Please install the required dependencies",
debug_info: dict = None):
super().__init__(message, error_code, details, suggestion, debug_info)

Expand Down Expand Up @@ -470,11 +470,11 @@ def create_exception_from_response(
# Returns a RateLimitError instance
"""
exception_class = HTTP_STATUS_TO_EXCEPTION.get(status_code, MemoryError)

# Generate error code if not provided
if not error_code:
error_code = f"HTTP_{status_code}"

# Create appropriate suggestion based on status code
suggestions = {
400: "Please check your request parameters and try again",
Expand All @@ -491,13 +491,13 @@ def create_exception_from_response(
503: "Service unavailable. Please try again later",
504: "Gateway timeout. Please try again later",
}

suggestion = suggestions.get(status_code, "Please try again later")

return exception_class(
message=response_text or f"HTTP {status_code} error",
error_code=error_code,
details=details or {},
suggestion=suggestion,
debug_info=debug_info or {},
)
)
Loading