getaroundapi / app.py
ericjedha's picture
Update app.py
4e0eb62 verified
import pandas as pd
import numpy as np
import mlflow
import mlflow.pyfunc
import logging
import os
import traceback
from contextlib import asynccontextmanager
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
# --- Configuration des logs ---
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
# --- Dictionnaire pour stocker les modèles chargés ---
# On le remplit au démarrage de l'application
ml_models = {}
# --- Configuration du Lifespan de l'application ---
@asynccontextmanager
async def lifespan(app: FastAPI):
# Code exécuté au démarrage de l'application
logger.info("Démarrage de l'application: chargement du modèle...")
# 1. Configurer l'URI du serveur MLflow (LA PARTIE LA PLUS IMPORTANTE)
# Cette variable doit être définie dans les "Secrets" de votre Space FastAPI
MLFLOW_TRACKING_URI = os.getenv("MLFLOW_TRACKING_URI")
if not MLFLOW_TRACKING_URI:
raise ValueError("La variable d'environnement MLFLOW_TRACKING_URI n'est pas définie !")
mlflow.set_tracking_uri(MLFLOW_TRACKING_URI)
logger.info(f"MLflow tracking URI configuré sur: {MLFLOW_TRACKING_URI}")
# 2. Configurer l'authentification si votre Space MLflow est privé
# Le token doit aussi être dans les "Secrets" du Space FastAPI
HF_TOKEN = os.getenv("HF_TOKEN")
if HF_TOKEN:
os.environ['MLFLOW_TRACKING_USERNAME'] = "ericjedha" # ou tout autre nom d'utilisateur
os.environ['MLFLOW_TRACKING_PASSWORD'] = HF_TOKEN
logger.info("Authentification MLflow configurée avec un token.")
# 3. Charger le modèle
try:
logged_model_uri = 'runs:/8d6657ebb69943f298f1124df0db622f/xgboost_ridge_pipeline'
# Charger le modèle et le stocker dans notre dictionnaire
ml_models["getaround_model"] = mlflow.pyfunc.load_model(logged_model_uri)
logger.info("Modèle chargé avec succès et prêt à être utilisé.")
except Exception as e:
logger.error(f"Erreur critique lors du chargement du modèle: {e}")
logger.error(traceback.format_exc())
# Si le modèle ne se charge pas, l'application ne peut pas fonctionner.
# On pourrait choisir d'arrêter l'application ici, mais pour l'instant on logue l'erreur.
yield
# Code exécuté à l'arrêt de l'application (cleanup)
logger.info("Arrêt de l'application: nettoyage...")
ml_models.clear()
# --- Initialisation de l'application FastAPI avec le lifespan ---
app = FastAPI(lifespan=lifespan)
# --- Modèle de données Pydantic pour la requête ---
class Item(BaseModel):
model_key: str
mileage: int
engine_power: int
fuel: str
paint_color: str
car_type: str
private_parking_available: int
has_gps: int
has_air_conditioning: int
automatic_car: int
has_getaround_connect: int
has_speed_regulator: int
winter_tires: int
# --- Endpoints ---
@app.get("/")
def read_root():
return {"message": "Bienvenue sur l'API de prédiction GetAround"}
@app.post("/predict/")
async def predict(item: Item):
# Vérifier si le modèle est bien chargé
if "getaround_model" not in ml_models:
raise HTTPException(
status_code=503,
detail="Le modèle n'est pas disponible. L'application n'a pas pu le charger au démarrage."
)
try:
# Créer un DataFrame à partir des données de la requête
car_df = pd.DataFrame([item.model_dump()])
logger.info(f"Données reçues pour la prédiction : \n{car_df.to_string()}")
# Utiliser le modèle DÉJÀ en mémoire pour faire la prédiction
prediction = ml_models["getaround_model"].predict(car_df)
# Formater la réponse
response = {"prediction": prediction.tolist()[0]}
logger.info(f"Prédiction effectuée : {response}")
return response
except Exception as e:
logger.error(f"Erreur lors de la prédiction : {e}")
logger.error(traceback.format_exc())
raise HTTPException(status_code=500, detail=f"Erreur serveur lors de la prédiction : {str(e)}")