Spaces:
Sleeping
Sleeping
| """ | |
| Main FastAPI Application | |
| ========================= | |
| Application entry point | |
| """ | |
| import logging | |
| from contextlib import asynccontextmanager | |
| from fastapi import FastAPI | |
| from fastapi.middleware.cors import CORSMiddleware | |
| from fastapi.responses import JSONResponse | |
| from app.core.config import settings | |
| from app.core.exceptions import ToxicDetectionException | |
| from app.models.model_loader import model_loader | |
| from app.api.routes import router | |
| # Configure logging | |
| logging.basicConfig( | |
| level=getattr(logging, settings.LOG_LEVEL), | |
| format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' | |
| ) | |
| logger = logging.getLogger(__name__) | |
| async def lifespan(app: FastAPI): | |
| """ | |
| Lifespan events | |
| Startup: Load model | |
| Shutdown: Cleanup | |
| """ | |
| # Startup | |
| logger.info("Starting up...") | |
| try: | |
| logger.info("Loading model...") | |
| model_loader.load() | |
| logger.info("Model loaded successfully") | |
| except Exception as e: | |
| logger.error(f"Failed to load model: {str(e)}") | |
| # Continue anyway - health endpoint will show model not loaded | |
| yield | |
| # Shutdown | |
| logger.info("Shutting down...") | |
| # Create FastAPI app | |
| app = FastAPI( | |
| title=settings.API_TITLE, | |
| description=settings.API_DESCRIPTION, | |
| version=settings.API_VERSION, | |
| lifespan=lifespan, | |
| docs_url="/docs", | |
| redoc_url="/redoc", | |
| openapi_url="/openapi.json" | |
| ) | |
| # CORS middleware | |
| app.add_middleware( | |
| CORSMiddleware, | |
| allow_origins=settings.ALLOWED_ORIGINS, | |
| allow_credentials=True, | |
| allow_methods=["*"], | |
| allow_headers=["*"], | |
| ) | |
| # Exception handlers | |
| async def toxic_detection_exception_handler(request, exc: ToxicDetectionException): | |
| """Handle custom exceptions""" | |
| return JSONResponse( | |
| status_code=exc.status_code, | |
| content={ | |
| "success": False, | |
| "error": exc.detail, | |
| "detail": None | |
| } | |
| ) | |
| async def general_exception_handler(request, exc: Exception): | |
| """Handle general exceptions""" | |
| logger.error(f"Unhandled exception: {str(exc)}", exc_info=True) | |
| return JSONResponse( | |
| status_code=500, | |
| content={ | |
| "success": False, | |
| "error": "Internal server error", | |
| "detail": str(exc) if settings.LOG_LEVEL == "DEBUG" else None | |
| } | |
| ) | |
| # Include routers | |
| app.include_router(router, prefix="/api/v1", tags=["v1"]) | |
| app.include_router(router, prefix="", tags=["root"]) | |
| # For direct run | |
| if __name__ == "__main__": | |
| import uvicorn | |
| uvicorn.run( | |
| "app.main:app", | |
| host=settings.API_HOST, | |
| port=settings.API_PORT, | |
| reload=settings.API_RELOAD, | |
| log_level=settings.LOG_LEVEL.lower() | |
| ) | |