Spaces:
Runtime error
Runtime error
File size: 4,792 Bytes
9d9e4e8 1df4bc7 1ade648 9d9e4e8 1df4bc7 1ade648 9d9e4e8 1ade648 1df4bc7 ab97cfb 1ade648 ab97cfb 1ade648 ab97cfb 1df4bc7 9d9e4e8 1ade648 9d9e4e8 1ade648 9d9e4e8 1ade648 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
from fastapi import FastAPI, HTTPException, Header
from contextlib import asynccontextmanager
import pandas as pd
import os
import joblib
import time
import requests
from huggingface_hub import hf_hub_download
from prometheus_client import Counter, Histogram, Gauge, generate_latest
# Global variables
model = None
encoders = {}
scaler = None
feature_columns = []
categorical_columns = []
boolean_columns = []
loaded = False
# Environment variables
API_KEY = os.getenv("API_KEY", "test-key-123")
HF_MODEL_REPO = os.getenv("HF_MODEL_REPO")
PROM_PUSHGATEWAY = os.getenv("PROM_PUSHGATEWAY")
# Prometheus metrics
REQS = Counter("pred_requests_total", "Total prediction requests")
LAT = Histogram("pred_request_latency_seconds", "Request latency")
LATEST = Gauge("latest_prediction", "Last predicted value")
@asynccontextmanager
async def lifespan(app: FastAPI):
# Startup
global model, encoders, scaler, feature_columns, categorical_columns, boolean_columns, loaded
print("π Starting FastAPI application...")
print(f"API_KEY: {'Set' if API_KEY else 'Not set'}")
print(f"HF_MODEL_REPO: {HF_MODEL_REPO}")
if not HF_MODEL_REPO:
print("β οΈ WARNING: HF_MODEL_REPO not set. Using mock mode.")
loaded = False
else:
try:
print(f" Downloading model from {HF_MODEL_REPO}...")
m = hf_hub_download(repo_id=HF_MODEL_REPO, filename="best_model.joblib")
e = hf_hub_download(repo_id=HF_MODEL_REPO, filename="models/encoders.joblib")
s = hf_hub_download(repo_id=HF_MODEL_REPO, filename="models/scaler.joblib")
f = hf_hub_download(repo_id=HF_MODEL_REPO, filename="models/feature_columns.joblib")
c = hf_hub_download(repo_id=HF_MODEL_REPO, filename="models/categorical_columns.joblib")
b = hf_hub_download(repo_id=HF_MODEL_REPO, filename="models/boolean_columns.joblib")
print(" Loading artifacts...")
model = joblib.load(m)
encoders = joblib.load(e)
scaler = joblib.load(s)
feature_columns = joblib.load(f)
categorical_columns = joblib.load(c)
boolean_columns = joblib.load(b)
loaded = True
print(" Model loaded successfully!")
print(f" Features: {len(feature_columns)}")
except Exception as ex:
print(f" Model load error: {ex}")
loaded = False
print(" FastAPI app initialized and ready!")
yield # Server runs here
# Shutdown (cleanup if needed)
print("π Shutting down...")
app = FastAPI(title="Loan Approval API", version="1.0", lifespan=lifespan)
@app.get("/")
def health():
return {
"status": "ok",
"model_loaded": loaded,
"features": feature_columns if loaded else []
}
@app.post("/predict")
def predict(payload: dict, x_api_key: str = Header(None)):
if x_api_key != API_KEY:
raise HTTPException(status_code=401, detail="Invalid API key")
if not loaded:
raise HTTPException(status_code=503, detail="Model not loaded")
try:
df = pd.DataFrame([payload])
for col in feature_columns:
if col not in df.columns:
df[col] = 0
for col in boolean_columns:
if col in df.columns:
if df[col].dtype == bool:
df[col] = df[col].astype(int)
elif df[col].dtype == 'object':
df[col] = df[col].map({
'True': 1, 'true': 1, True: 1, 1: 1,
'False': 0, 'false': 0, False: 0, 0: 0
}).fillna(0).astype(int)
for col in categorical_columns:
if col in df.columns and col in encoders:
try:
df[col] = encoders[col].transform(df[col])
except:
df[col] = 0
df = df[feature_columns]
df_scaled = scaler.transform(df)
start = time.time()
pred = model.predict(df_scaled)[0]
latency = time.time() - start
LAT.observe(latency)
REQS.inc()
LATEST.set(pred)
if PROM_PUSHGATEWAY:
try:
requests.post(f"{PROM_PUSHGATEWAY}/metrics/job/loan_model", data=generate_latest(), timeout=2)
except:
pass
return {
"prediction": int(pred),
"prediction_label": "Approved" if pred == 1 else "Rejected",
"latency_seconds": round(latency, 4)
}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@app.get("/metrics")
def metrics():
return generate_latest() |