import pandas as pd import joblib import uvicorn from fastapi import FastAPI, Body, Request from fastapi.responses import JSONResponse, RedirectResponse from fastapi.exceptions import RequestValidationError from pydantic import BaseModel, Field from typing import Literal # Charger le modèle model = joblib.load("get_around_v1.pkl") # Classe Pydantic pour les entrées class CarData(BaseModel): mileage: float = Field(..., ge=0, description="Kilométrage doit être >= 0") engine_power: float = Field(..., ge=45, le=423, description="Puissance moteur entre 45 et 423") car_brand: Literal[ "Citroën", "Peugeot", "PGO", "Renault", "Audi", "BMW", "Ford", "Mercedes", "Opel", "Porsche", "Volkswagen", "KIA Motors", "Alfa Romeo", "Ferrari", "Fiat", "Lamborghini", "Maserati", "Lexus", "Honda", "Mazda", "Mini", "Mitsubishi", "Nissan", "SEAT", "Subaru", "Suzuki", "Toyota", "Yamaha" ] fuel: Literal["diesel", "petrol", "hybrid_petrol", "electro"] paint_color: Literal[ "black", "grey", "white", "red", "silver", "blue", "orange", "beige", "brown", "green" ] car_type: Literal[ "sedan", "convertible", "coupe", "estate", "hatchback", "subcompact", "suv", "van" ] private_parking_available: bool has_gps: bool has_air_conditioning: bool automatic_car: bool has_getaround_connect: bool has_speed_regulator: bool winter_tires: bool # Initialisation FastAPI app = FastAPI( title="🚙🚕 API de Prédiction de Prix GetAround 🚗🚑 ", docs_url="/docs", description=""" Bienvenue sur l'API de prédiction de prix de location de véhicules GetAround ! Grâce à notre modèle prédictif entraîné sur les données du partenaire GetAround, vous pouvez estimer rapidement le prix journalier d'un véhicule en fournissant ses caractéristiques. 📌 **Règles pour certaines colonnes :** - **car_brand** : choisissez parmi les marques listées : "Citroën", "Peugeot", "PGO", "Renault", "Audi", "BMW", "Ford", "Mercedes", "Opel", "Porsche", "Volkswagen", "KIA Motors", "Alfa Romeo", "Ferrari", "Fiat", "Lamborghini", "Maserati", "Lexus", "Honda", "Mazda", "Mini", "Mitsubishi", "Nissan", "SEAT", "Subaru", "Suzuki", "Toyota", "Yamaha". - **fuel** : "diesel", "petrol", "hybrid_petrol", "electro". - **paint_color** : "black", "grey", "white", "red", "silver", "blue", "orange", "beige", "brown", "green". - **car_type** : "convertible", "coupe", "estate", "hatchback", "sedan", "subcompact", "suv", "van". ✅ Pour les autres options (private_parking_available, has_gps, etc.), utilisez **true** pour Oui et **false** pour Non. 💡 Exemple d'utilisation : ```json { "car_brand": "Renault", "mileage": 50000, "engine_power": 120, "fuel": "diesel", "paint_color": "white", "car_type": "estate", "private_parking_available": false, "has_gps": true, "has_air_conditioning": false, "automatic_car": false, "has_getaround_connect": false, "has_speed_regulator": false, "winter_tires": true } """, version="1.0" ) @app.get("/") def root(): return RedirectResponse(url="/docs") # Gestionnaire d'erreurs personnalisé @app.exception_handler(RequestValidationError) async def validation_exception_handler(request: Request, exc: RequestValidationError): errors = [] for e in exc.errors(): field = e.get("loc")[-1] expected = e.get("ctx", {}).get("expected") msg = e.get("msg") if expected: errors.append({ "field": field, "message": f"Valeur incorrecte pour '{field}'. Valeurs possibles : {expected}" }) else: errors.append({ "field": field, "message": f"Erreur sur '{field}': {msg}" }) return JSONResponse( status_code=422, content={ "error": "Certaines valeurs ne sont pas valides", "details": errors } ) # Endpoint de prédiction @app.post( "/predict", summary="Prédire le prix journalier d'une voiture", description="Fournir toutes les caractéristiques de la voiture pour obtenir le prix prédictif." ) def predict( data: CarData = Body( ..., examples={ "valid_example": { "summary": "Exemple valide", "value": { "mileage": 120000, "engine_power": 100, "car_brand": "Citroën", "fuel": "diesel", "paint_color": "white", "car_type": "sedan", "private_parking_available": True, "has_gps": True, "has_air_conditioning": True, "automatic_car": True, "has_getaround_connect": True, "has_speed_regulator": True, "winter_tires": True } } } ) ): df = pd.DataFrame([data.model_dump()]) df.rename(columns={'car_brand': 'model_key'}, inplace=True) prediction = model.predict(df) return {"prediction": round(float(prediction[0]), 2)} # Lancer localement (utile pour tests) if __name__ == "__main__": uvicorn.run(app, host="0.0.0.0", port=7860)