from fastapi import APIRouter from pydantic import BaseModel import joblib import pandas as pd from typing import Optional, Any from .config_huggingface import build_model_url, download_artifact_if_needed router = APIRouter(tags=["Machine Learning"]) class RandomForestClassifierRequest(BaseModel): income_k: float = 65.0 debt_k: float = 15.0 employment_years: float = 5.0 credit_score: float = 710.0 MODEL_STATE: dict[str, Optional[Any]] = { "model": None, "error": None, } MODEL_URL = build_model_url("ML_RandomForestClassifier_CreditApproval.joblib") def _ensure_model_loaded() -> None: if MODEL_STATE["model"] is not None: return try: model_path = download_artifact_if_needed(MODEL_URL) MODEL_STATE["model"] = joblib.load(model_path) MODEL_STATE["error"] = None except Exception as e: MODEL_STATE["error"] = str(e) raise @router.post("/models/random_forest_classifier", summary="Predict loan approval with Random Forest") def predict_random_forest_classifier(data: RandomForestClassifierRequest): import traceback try: _ensure_model_loaded() except Exception: detail = "Model not loaded." if MODEL_STATE["error"]: detail = f"Model not loaded: {MODEL_STATE['error']}" return {"error": detail, "traceback": traceback.format_exc(), "status": 500} model = MODEL_STATE["model"] if model is None: return {"error": f"Model is None after loading. Error: {MODEL_STATE['error']}", "status": 500} input_df = pd.DataFrame( [[data.income_k, data.debt_k, data.employment_years, data.credit_score]], columns=["income_k", "debt_k", "employment_years", "credit_score"], ) try: pred = int(model.predict(input_df)[0]) proba = model.predict_proba(input_df)[0] except Exception as e: return {"error": f"Prediction failed: {str(e)}", "traceback": traceback.format_exc(), "status": 500} return { "prediction": "Approved" if pred == 1 else "Denied", "confidence": f"{max(proba):.0%}", }