from fastapi import APIRouter, FastAPI, HTTPException, Depends from fastapi.exceptions import RequestValidationError from fastapi.middleware.cors import CORSMiddleware from dotenv import load_dotenv load_dotenv(".env") from api.health import HealthController, SystemService from api.model import ModelController, ModelService from api.schema import InputData, preprocess_input_data from constants import ( APP_TITLE, APP_VERSION, FEATURE_FILE, METADATA_FILE, MODEL_FILE, MODEL_REPO ) from packages import ( APIException, UnauthorizedException, unauthorized_exception_handler, api_exception_handler, general_exception_handler, http_exception_handler, request_validation_exception_handler, verify_token ) api = FastAPI(title=APP_TITLE, version=APP_VERSION) api.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) model_service = ModelService( model_repo=MODEL_REPO, model_file=MODEL_FILE, feature_file=FEATURE_FILE, metadata_file=METADATA_FILE, ) system_service = SystemService() health_controller = HealthController( model_service=model_service, system_service=system_service, app_title=APP_TITLE, app_version=APP_VERSION, ) model_controller = ModelController(model_service=model_service) api.add_exception_handler(UnauthorizedException, unauthorized_exception_handler) api.add_exception_handler(APIException, api_exception_handler) api.add_exception_handler(HTTPException, http_exception_handler) api.add_exception_handler(RequestValidationError, request_validation_exception_handler) api.add_exception_handler(Exception, general_exception_handler) # API Router api_router = APIRouter(prefix="/api", tags=["API"]) @api_router.get("/") async def root(_: None = Depends(verify_token)): return {"message": "Welcome to SmartBank Predictor Model API"} @api_router.get("/health") async def health_check(_: None = Depends(verify_token)): return await health_controller.check_health() @api_router.get("/model-info") async def model_info(_: None = Depends(verify_token)): return await model_controller.get_complete_model_info() @api_router.post("/predict") async def predict(data: InputData, _: None = Depends(verify_token)): try: model_input = preprocess_input_data(data, model_service) return await model_controller.predict(model_input) except ValueError as e: raise APIException( status_code=400, message="Invalid input data", error_type="ValidationError", details={"validation_error": str(e)}, ) except RuntimeError as e: raise APIException( status_code=500, message="Model prediction failed", error_type="PredictionError", details={"runtime_error": str(e)}, ) api.include_router(api_router)