fastapi_hf / routes /ML_MeanShift_UserBehavior.py
looh2's picture
ML Unsupervised 1
69580e3
Raw
History Blame Contribute Delete
2.09 kB
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 MeanShiftRequest(BaseModel):
session_duration_min: float = 18.0
pages_viewed: int = 10
items_purchased: int = 3
MODEL_STATE: dict[str, Optional[Any]] = {
"model": None,
"error": None,
}
MODEL_URL = build_model_url("ML_MeanShift_UserBehavior.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/mean_shift", summary="Classify user behaviour with Mean Shift clustering")
def predict_mean_shift(data: MeanShiftRequest):
import traceback
try:
_ensure_model_loaded()
except Exception:
detail = f"Model not loaded: {MODEL_STATE['error']}" if MODEL_STATE["error"] else "Model not loaded."
return {"error": detail, "traceback": traceback.format_exc(), "status": 500}
bundle = MODEL_STATE["model"]
if bundle is None:
return {"error": f"Model is None. Error: {MODEL_STATE['error']}", "status": 500}
scaler = bundle["scaler"]
ms = bundle["ms"]
cluster_name_map = bundle["cluster_name_map"]
input_df = pd.DataFrame(
[[data.session_duration_min, data.pages_viewed, data.items_purchased]],
columns=["session_duration_min", "pages_viewed", "items_purchased"],
)
try:
cluster = int(ms.predict(scaler.transform(input_df))[0])
except Exception as e:
return {"error": f"Prediction failed: {str(e)}", "traceback": traceback.format_exc(), "status": 500}
return {
"cluster": cluster,
"label": cluster_name_map.get(cluster, f"Cluster {cluster}"),
}