Djohell commited on
Commit
b79f79f
·
1 Parent(s): ef64639
Files changed (4) hide show
  1. Dockerfile +15 -0
  2. app.py +116 -0
  3. get_around_v1.pkl +3 -0
  4. requirements.txt +12 -0
Dockerfile ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.11-slim
2
+
3
+ WORKDIR /app
4
+
5
+ # Copier tous les fichiers
6
+ COPY . /app
7
+
8
+ # Installer les dépendances
9
+ RUN pip install --no-cache-dir -r requirements.txt
10
+
11
+ # Exposer le port attendu par HF
12
+ EXPOSE 7860
13
+
14
+ # Lancer FastAPI
15
+ CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
app.py ADDED
@@ -0,0 +1,116 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI, Body, Request
2
+ from fastapi.responses import JSONResponse, RedirectResponse
3
+ from fastapi.exceptions import RequestValidationError
4
+ from pydantic import BaseModel, Field
5
+ from typing import Literal
6
+ import pandas as pd
7
+ import joblib
8
+ import uvicorn
9
+
10
+ # Charger le modèle
11
+ model = joblib.load("get_around_v1.pkl")
12
+
13
+ # Classe Pydantic pour les entrées
14
+ class CarData(BaseModel):
15
+ mileage: float = Field(..., ge=0, description="Kilométrage doit être >= 0")
16
+ engine_power: float = Field(..., ge=1, le=423, description="Puissance moteur entre 1 et 423")
17
+ car_brand: Literal[
18
+ "Citroën", "Peugeot", "PGO", "Renault", "Audi", "BMW", "Ford", "Mercedes",
19
+ "Opel", "Porsche", "Volkswagen", "KIA Motors", "Alfa Romeo", "Ferrari",
20
+ "Fiat", "Lamborghini", "Maserati", "Lexus", "Honda", "Mazda", "Mini",
21
+ "Mitsubishi", "Nissan", "SEAT", "Subaru", "Suzuki", "Toyota", "Yamaha"
22
+ ]
23
+ fuel: Literal["diesel", "petrol", "hybrid_petrol", "electro"]
24
+ paint_color: Literal[
25
+ "black", "grey", "white", "red", "silver", "blue",
26
+ "orange", "beige", "brown", "green"
27
+ ]
28
+ car_type: Literal[
29
+ "convertible", "coupe", "estate", "hatchback", "sedan", "subcompact", "suv", "van"
30
+ ]
31
+ private_parking_available: bool
32
+ has_gps: bool
33
+ has_air_conditioning: bool
34
+ automatic_car: bool
35
+ has_getaround_connect: bool
36
+ has_speed_regulator: bool
37
+ winter_tires: bool
38
+
39
+ # Initialisation FastAPI
40
+ app = FastAPI(
41
+ title="GetAround Prediction API",
42
+ description="API de prédiction du prix de location par jour pour GetAround",
43
+ version="1.0"
44
+ )
45
+
46
+
47
+ @app.get("/")
48
+ def root():
49
+ return RedirectResponse(url="/docs")
50
+
51
+ # Gestionnaire d'erreurs personnalisé
52
+ @app.exception_handler(RequestValidationError)
53
+ async def validation_exception_handler(request: Request, exc: RequestValidationError):
54
+ errors = []
55
+ for e in exc.errors():
56
+ field = e.get("loc")[-1]
57
+ expected = e.get("ctx", {}).get("expected")
58
+ msg = e.get("msg")
59
+ if expected:
60
+ errors.append({
61
+ "field": field,
62
+ "message": f"Valeur incorrecte pour '{field}'. Valeurs possibles : {expected}"
63
+ })
64
+ else:
65
+ errors.append({
66
+ "field": field,
67
+ "message": f"Erreur sur '{field}': {msg}"
68
+ })
69
+ return JSONResponse(
70
+ status_code=422,
71
+ content={
72
+ "error": "Certaines valeurs ne sont pas valides",
73
+ "details": errors
74
+ }
75
+ )
76
+
77
+ # Endpoint de prédiction
78
+ @app.post(
79
+ "/predict",
80
+ summary="Prédire le prix journalier d'une voiture",
81
+ description="Fournir toutes les caractéristiques de la voiture pour obtenir le prix prédictif."
82
+ )
83
+ def predict(
84
+ data: CarData = Body(
85
+ ...,
86
+ examples={
87
+ "valid_example": {
88
+ "summary": "Exemple valide",
89
+ "value": {
90
+ "mileage": 15000,
91
+ "engine_power": 100,
92
+ "car_brand": "Citroën",
93
+ "fuel": "diesel",
94
+ "paint_color": "white",
95
+ "car_type": "sedan",
96
+ "private_parking_available": True,
97
+ "has_gps": True,
98
+ "has_air_conditioning": True,
99
+ "automatic_car": True,
100
+ "has_getaround_connect": True,
101
+ "has_speed_regulator": True,
102
+ "winter_tires": True
103
+ }
104
+ }
105
+ }
106
+ )
107
+ ):
108
+ df = pd.DataFrame([data.model_dump()])
109
+ df.rename(columns={'car_brand': 'model_key'}, inplace=True)
110
+ prediction = model.predict(df)
111
+ return {"prediction": round(float(prediction[0]), 2)}
112
+
113
+
114
+ # Lancer localement (utile pour tests)
115
+ if __name__ == "__main__":
116
+ uvicorn.run(app, host="0.0.0.0", port=7860)
get_around_v1.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:84b6fe653ddf116a6b1708e6a5bebba58f2655ca0dfe49ac96b7775ae503556f
3
+ size 7861686
requirements.txt ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ fastapi==0.111.1
2
+ pydantic==2.8.0
3
+ uvicorn==0.23.2
4
+ pandas==2.1.1
5
+ scikit-learn==1.5.1
6
+ joblib==1.3.2
7
+ typing-extensions==4.9.0
8
+ requests==2.32.0
9
+ gradio==3.44.0
10
+ xgboost
11
+ gradio
12
+ websockets