DavidJyes commited on
Commit
fb20e0e
·
verified ·
1 Parent(s): facc00a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +160 -160
app.py CHANGED
@@ -1,161 +1,161 @@
1
- import pandas as pd
2
- import joblib
3
- import uvicorn
4
- from fastapi import FastAPI, Body, Request
5
- from fastapi.responses import JSONResponse, RedirectResponse
6
- from fastapi.exceptions import RequestValidationError
7
- from pydantic import BaseModel, Field
8
- from typing import Literal
9
-
10
-
11
- # Charger le modèle
12
- model = joblib.load("get_around_v1.pkl")
13
-
14
- # Classe Pydantic pour les entrées
15
- class CarData(BaseModel):
16
- mileage: float = Field(..., ge=0, description="Kilométrage doit être >= 0")
17
- engine_power: float = Field(..., ge=1, le=423, description="Puissance moteur entre 1 et 423")
18
- car_brand: Literal[
19
- "Citroën", "Peugeot", "PGO", "Renault", "Audi", "BMW", "Ford", "Mercedes",
20
- "Opel", "Porsche", "Volkswagen", "KIA Motors", "Alfa Romeo", "Ferrari",
21
- "Fiat", "Lamborghini", "Maserati", "Lexus", "Honda", "Mazda", "Mini",
22
- "Mitsubishi", "Nissan", "SEAT", "Subaru", "Suzuki", "Toyota", "Yamaha"
23
- ]
24
- fuel: Literal["diesel", "petrol", "hybrid_petrol", "electro"]
25
- paint_color: Literal[
26
- "black", "grey", "white", "red", "silver", "blue",
27
- "orange", "beige", "brown", "green"
28
- ]
29
- car_type: Literal[
30
- "convertible", "coupe", "estate", "hatchback", "sedan", "subcompact", "suv", "van"
31
- ]
32
- private_parking_available: bool
33
- has_gps: bool
34
- has_air_conditioning: bool
35
- automatic_car: bool
36
- has_getaround_connect: bool
37
- has_speed_regulator: bool
38
- winter_tires: bool
39
-
40
- # Initialisation FastAPI
41
- app = FastAPI(
42
- title="🚙🚕 API de Prédiction de Prix GetAround 🚗🚑 ",
43
- docs_url="/docs",
44
- description="""
45
-
46
- Bienvenue sur l'API de prédiction de prix de location de véhicules GetAround !
47
-
48
- 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.
49
-
50
- 📌 **Règles pour certaines colonnes :**
51
-
52
- - **car_brand** : choisissez parmi les marques listées :
53
- "Citroën", "Peugeot", "PGO", "Renault", "Audi", "BMW", "Ford", "Mercedes",
54
- "Opel", "Porsche", "Volkswagen", "KIA Motors", "Alfa Romeo", "Ferrari",
55
- "Fiat", "Lamborghini", "Maserati", "Lexus", "Honda", "Mazda", "Mini",
56
- "Mitsubishi", "Nissan", "SEAT", "Subaru", "Suzuki", "Toyota", "Yamaha".
57
-
58
- - **fuel** : "diesel", "petrol", "hybrid_petrol", "electro".
59
-
60
- - **paint_color** : "black", "grey", "white", "red", "silver", "blue",
61
- "orange", "beige", "brown", "green".
62
-
63
- - **car_type** : "convertible", "coupe", "estate", "hatchback", "sedan",
64
- "subcompact", "suv", "van".
65
-
66
- ✅ Pour les autres options (private_parking_available, has_gps, etc.), utilisez **true** pour Oui et **false** pour Non.
67
-
68
- 💡 Exemple d'utilisation :
69
-
70
- ```json
71
- {
72
- "car_brand": "Renault",
73
- "mileage": 50000,
74
- "engine_power": 120,
75
- "fuel": "diesel",
76
- "paint_color": "white",
77
- "car_type": "estate",
78
- "private_parking_available": false,
79
- "has_gps": true,
80
- "has_air_conditioning": false,
81
- "automatic_car": false,
82
- "has_getaround_connect": false,
83
- "has_speed_regulator": false,
84
- "winter_tires": true
85
- }
86
-
87
- """,
88
- version="1.0"
89
- )
90
-
91
-
92
- @app.get("/")
93
- def root():
94
- return RedirectResponse(url="/docs")
95
-
96
- # Gestionnaire d'erreurs personnalisé
97
- @app.exception_handler(RequestValidationError)
98
- async def validation_exception_handler(request: Request, exc: RequestValidationError):
99
- errors = []
100
- for e in exc.errors():
101
- field = e.get("loc")[-1]
102
- expected = e.get("ctx", {}).get("expected")
103
- msg = e.get("msg")
104
- if expected:
105
- errors.append({
106
- "field": field,
107
- "message": f"Valeur incorrecte pour '{field}'. Valeurs possibles : {expected}"
108
- })
109
- else:
110
- errors.append({
111
- "field": field,
112
- "message": f"Erreur sur '{field}': {msg}"
113
- })
114
- return JSONResponse(
115
- status_code=422,
116
- content={
117
- "error": "Certaines valeurs ne sont pas valides",
118
- "details": errors
119
- }
120
- )
121
-
122
- # Endpoint de prédiction
123
- @app.post(
124
- "/predict",
125
- summary="Prédire le prix journalier d'une voiture",
126
- description="Fournir toutes les caractéristiques de la voiture pour obtenir le prix prédictif."
127
- )
128
- def predict(
129
- data: CarData = Body(
130
- ...,
131
- examples={
132
- "valid_example": {
133
- "summary": "Exemple valide",
134
- "value": {
135
- "mileage": 15000,
136
- "engine_power": 100,
137
- "car_brand": "Citroën",
138
- "fuel": "diesel",
139
- "paint_color": "white",
140
- "car_type": "sedan",
141
- "private_parking_available": True,
142
- "has_gps": True,
143
- "has_air_conditioning": True,
144
- "automatic_car": True,
145
- "has_getaround_connect": True,
146
- "has_speed_regulator": True,
147
- "winter_tires": True
148
- }
149
- }
150
- }
151
- )
152
- ):
153
- df = pd.DataFrame([data.model_dump()])
154
- df.rename(columns={'car_brand': 'model_key'}, inplace=True)
155
- prediction = model.predict(df)
156
- return {"prediction": round(float(prediction[0]), 2)}
157
-
158
-
159
- # Lancer localement (utile pour tests)
160
- if __name__ == "__main__":
161
  uvicorn.run(app, host="0.0.0.0", port=7860)
 
1
+ import pandas as pd
2
+ import joblib
3
+ import uvicorn
4
+ from fastapi import FastAPI, Body, Request
5
+ from fastapi.responses import JSONResponse, RedirectResponse
6
+ from fastapi.exceptions import RequestValidationError
7
+ from pydantic import BaseModel, Field
8
+ from typing import Literal
9
+
10
+
11
+ # Charger le modèle
12
+ model = joblib.load("get_around_v1.pkl")
13
+
14
+ # Classe Pydantic pour les entrées
15
+ class CarData(BaseModel):
16
+ mileage: float = Field(..., ge=0, description="Kilométrage doit être >= 0")
17
+ engine_power: float = Field(..., ge=1, le=423, description="Puissance moteur entre 1 et 423")
18
+ car_brand: Literal[
19
+ "Citroën", "Peugeot", "PGO", "Renault", "Audi", "BMW", "Ford", "Mercedes",
20
+ "Opel", "Porsche", "Volkswagen", "KIA Motors", "Alfa Romeo", "Ferrari",
21
+ "Fiat", "Lamborghini", "Maserati", "Lexus", "Honda", "Mazda", "Mini",
22
+ "Mitsubishi", "Nissan", "SEAT", "Subaru", "Suzuki", "Toyota", "Yamaha"
23
+ ]
24
+ fuel: Literal["diesel", "petrol", "hybrid_petrol", "electro"]
25
+ paint_color: Literal[
26
+ "black", "grey", "white", "red", "silver", "blue",
27
+ "orange", "beige", "brown", "green"
28
+ ]
29
+ car_type: Literal[
30
+ "convertible", "coupe", "estate", "hatchback", "sedan", "subcompact", "suv", "van"
31
+ ]
32
+ private_parking_available: bool
33
+ has_gps: bool
34
+ has_air_conditioning: bool
35
+ automatic_car: bool
36
+ has_getaround_connect: bool
37
+ has_speed_regulator: bool
38
+ winter_tires: bool
39
+
40
+ # Initialisation FastAPI
41
+ app = FastAPI(
42
+ title="🚙🚕 API de Prédiction de Prix GetAround 🚗🚑 ",
43
+ docs_url="/docs",
44
+ description="""
45
+
46
+ Bienvenue sur l'API de prédiction de prix de location de véhicules GetAround !
47
+
48
+ 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.
49
+
50
+ 📌 **Règles pour certaines colonnes :**
51
+
52
+ - **car_brand** : choisissez parmi les marques listées :
53
+ "Citroën", "Peugeot", "PGO", "Renault", "Audi", "BMW", "Ford", "Mercedes",
54
+ "Opel", "Porsche", "Volkswagen", "KIA Motors", "Alfa Romeo", "Ferrari",
55
+ "Fiat", "Lamborghini", "Maserati", "Lexus", "Honda", "Mazda", "Mini",
56
+ "Mitsubishi", "Nissan", "SEAT", "Subaru", "Suzuki", "Toyota", "Yamaha".
57
+
58
+ - **fuel** : "diesel", "petrol", "hybrid_petrol", "electro".
59
+
60
+ - **paint_color** : "black", "grey", "white", "red", "silver", "blue",
61
+ "orange", "beige", "brown", "green".
62
+
63
+ - **car_type** : "convertible", "coupe", "estate", "hatchback", "sedan",
64
+ "subcompact", "suv", "van".
65
+
66
+ ✅ Pour les autres options (private_parking_available, has_gps, etc.), utilisez **true** pour Oui et **false** pour Non.
67
+
68
+ 💡 Exemple d'utilisation :
69
+
70
+ ```json
71
+ {
72
+ "car_brand": "Renault",
73
+ "mileage": 50000,
74
+ "engine_power": 120,
75
+ "fuel": "diesel",
76
+ "paint_color": "white",
77
+ "car_type": "estate",
78
+ "private_parking_available": false,
79
+ "has_gps": true,
80
+ "has_air_conditioning": false,
81
+ "automatic_car": false,
82
+ "has_getaround_connect": false,
83
+ "has_speed_regulator": false,
84
+ "winter_tires": true
85
+ }
86
+
87
+ """,
88
+ version="1.0"
89
+ )
90
+
91
+
92
+ @app.get("/")
93
+ def root():
94
+ return RedirectResponse(url="/docs")
95
+
96
+ # Gestionnaire d'erreurs personnalisé
97
+ @app.exception_handler(RequestValidationError)
98
+ async def validation_exception_handler(request: Request, exc: RequestValidationError):
99
+ errors = []
100
+ for e in exc.errors():
101
+ field = e.get("loc")[-1]
102
+ expected = e.get("ctx", {}).get("expected")
103
+ msg = e.get("msg")
104
+ if expected:
105
+ errors.append({
106
+ "field": field,
107
+ "message": f"Valeur incorrecte pour '{field}'. Valeurs possibles : {expected}"
108
+ })
109
+ else:
110
+ errors.append({
111
+ "field": field,
112
+ "message": f"Erreur sur '{field}': {msg}"
113
+ })
114
+ return JSONResponse(
115
+ status_code=422,
116
+ content={
117
+ "error": "Certaines valeurs ne sont pas valides",
118
+ "details": errors
119
+ }
120
+ )
121
+
122
+ # Endpoint de prédiction
123
+ @app.post(
124
+ "/predict",
125
+ summary="Prédire le prix journalier d'une voiture",
126
+ description="Fournir toutes les caractéristiques de la voiture pour obtenir le prix prédictif."
127
+ )
128
+ def predict(
129
+ data: CarData = Body(
130
+ ...,
131
+ examples={
132
+ "valid_example": {
133
+ "summary": "Exemple valide",
134
+ "value": {
135
+ "mileage": 80000,
136
+ "engine_power": 100,
137
+ "car_brand": "Citroën",
138
+ "fuel": "diesel",
139
+ "paint_color": "white",
140
+ "car_type": "sedan",
141
+ "private_parking_available": True,
142
+ "has_gps": True,
143
+ "has_air_conditioning": True,
144
+ "automatic_car": True,
145
+ "has_getaround_connect": True,
146
+ "has_speed_regulator": True,
147
+ "winter_tires": True
148
+ }
149
+ }
150
+ }
151
+ )
152
+ ):
153
+ df = pd.DataFrame([data.model_dump()])
154
+ df.rename(columns={'car_brand': 'model_key'}, inplace=True)
155
+ prediction = model.predict(df)
156
+ return {"prediction": round(float(prediction[0]), 2)}
157
+
158
+
159
+ # Lancer localement (utile pour tests)
160
+ if __name__ == "__main__":
161
  uvicorn.run(app, host="0.0.0.0", port=7860)