Spaces:
Sleeping
Sleeping
| # core/exceptions.py | |
| from fastapi import Request, status | |
| from fastapi.responses import JSONResponse | |
| from core.logger import setup_logger | |
| logger = setup_logger("exception_handler") | |
| # --------------------------------------------------- | |
| # Base Exception (Parent class of all custom errors) | |
| # --------------------------------------------------- | |
| class KnowledgeEngineException(Exception): | |
| """Base custom exception class for the Knowledge Engine application""" | |
| def __init__(self, message: str, status_code: int = status.HTTP_500_INTERNAL_SERVER_ERROR): | |
| self.message = message | |
| self.status_code = status_code | |
| super().__init__(self.message) | |
| # --------------------------------------------------- | |
| # Domain Specific Exceptions (Hierarchical error) | |
| # --------------------------------------------------- | |
| class ModelLoadError(KnowledgeEngineException): | |
| """models/ layer where model (Embedder/Reranker) loading fails""" | |
| def __init__(self, message: str): | |
| super().__init__(message, status_code=status.HTTP_503_SERVICE_UNAVAILABLE) | |
| class DatabaseError(KnowledgeEngineException): | |
| """storage/ layer where Qdrant or SQLite integration fails""" | |
| def __init__(self, message: str): | |
| super().__init__(message, status_code=status.HTTP_503_SERVICE_UNAVAILABLE) | |
| class SearchExecutionError(KnowledgeEngineException): | |
| """services/ layer where the search pipeline (Hybrid Search) encounters a logical error""" | |
| def __init__(self, message: str): | |
| super().__init__(message, status_code=status.HTTP_500_INTERNAL_SERVER_ERROR) | |
| class InvalidQueryError(KnowledgeEngineException): | |
| """api/ layer where user input is invalid (e.g., empty query, unsupported parameters)""" | |
| def __init__(self, message: str): | |
| super().__init__(message, status_code=status.HTTP_400_BAD_REQUEST) | |
| # ----------------------------------- | |
| # FastAPI Exception Handler | |
| # ----------------------------------- | |
| async def custom_exception_handler(request: Request, exc: KnowledgeEngineException): | |
| """ | |
| When a custom exception occurs in a FastAPI app, | |
| catch it and convert it into a consistent JSON error response. | |
| """ | |
| logger.error(f"[{exc.status_code}] {request.method} {request.url} - {exc.message}") | |
| return JSONResponse( | |
| status_code=exc.status_code, | |
| content={ | |
| "error": exc.__class__.__name__, | |
| "message": exc.message, | |
| "path": str(request.url.path) | |
| } | |
| ) | |
| async def global_exception_handler(request: Request, exc: Exception): | |
| """Catch any unhandled exceptions that are not instances of KnowledgeEngineException, | |
| log them, and return a generic error response.""" | |
| logger.critical(f"Unhandled Exception: {str(exc)}", exc_info=True) # Log stack trace for debugging | |
| return JSONResponse( | |
| status_code=500, | |
| content={"error": "InternalServerError", "message": "An unexpected error occurred."} | |
| ) | |
| def setup_exception_handlers(app): | |
| """Register custom exception handlers to the FastAPI app.""" | |
| app.add_exception_handler(KnowledgeEngineException, custom_exception_handler) | |
| app.add_exception_handler(Exception, global_exception_handler) |