Spaces:
No application file
No application file
| from fastapi import FastAPI, HTTPException | |
| import joblib | |
| import pandas as pd | |
| from typing import Dict | |
| app = FastAPI( | |
| title="Spending Risk ML Backend", | |
| description="Predicts future spend, spike risk, and spending acceleration", | |
| version="1.0.0" | |
| ) | |
| # ----------------------------- | |
| # Load models ONCE at startup | |
| # ----------------------------- | |
| try: | |
| future_spend_model = joblib.load("future_spend_7d.pkl") | |
| spike_model = joblib.load("spike_probability.pkl") | |
| acceleration_model = joblib.load("acceleration.pkl") | |
| FEATURES = joblib.load("model_features.pkl") | |
| except Exception as e: | |
| raise RuntimeError(f"❌ Model loading failed: {e}") | |
| # ----------------------------- | |
| # Health check (HF requirement) | |
| # ----------------------------- | |
| def health_check(): | |
| return { | |
| "status": "running", | |
| "service": "spending-risk-backend" | |
| } | |
| # ----------------------------- | |
| # Prediction endpoint | |
| # ----------------------------- | |
| def predict(payload: Dict): | |
| try: | |
| # 1. Build feature vector safely | |
| # Missing features -> default 0 | |
| input_row = {feat: payload.get(feat, 0) for feat in FEATURES} | |
| X = pd.DataFrame([input_row]) | |
| # 2. Predictions | |
| future_spend = float(future_spend_model.predict(X)[0]) | |
| spike_prob = float(spike_model.predict_proba(X)[0][1]) | |
| acceleration = float(acceleration_model.predict(X)[0]) | |
| # 3. Response (frontend-friendly) | |
| return { | |
| "future_7d_spend": round(future_spend, 2), | |
| "spike_probability": round(spike_prob, 3), | |
| "acceleration": round(acceleration, 2) | |
| } | |
| except Exception as e: | |
| raise HTTPException( | |
| status_code=400, | |
| detail=f"Prediction failed: {str(e)}" | |
| ) | |