Aurélie GABU commited on
Commit
73401e0
·
1 Parent(s): 77950e7

API: exposition du model ML avec les éléments nécessaires, mise en place tests API, mise à jour readme

Browse files
App/main.py CHANGED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI
2
+ from App.schemas import EmployeeFeatures
3
+ from App.predict import predict_employee
4
+
5
+ app = FastAPI(
6
+ title = "Futurisys ML API",
7
+ description = "API de prédiction du départ des employés",
8
+ version="0.1.0"
9
+ )
10
+
11
+ @app.post("/predict")
12
+ def predict(data: EmployeeFeatures):
13
+ """
14
+ Prédit la probabilité de départ d'un employé à partir de ses caractéristiques.
15
+ """
16
+ return predict_employee(data.model_dump())
App/model/mapping_classes.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"0": "Reste", "1": "Part"}
App/model/preprocesseur_fitted.joblib ADDED
Binary file (8.04 kB). View file
 
App/model/variables_entree.json CHANGED
@@ -1 +1 @@
1
- ["genre", "statut_marital", "departement", "poste", "domaine_etude", "frequence_deplacement", "heure_supplementaires", "evolution_cat_evol", "categorie_employe", "exp_hors_entreprise", "annees_dans_l_entreprise", "ecart_note_evaluation", "age", "ratio_sans_promotion", "distance_domicile_travail", "revenu_mensuel", "satisfaction_employee_environnement", "revenu_par_annee_experience_totale", "nombre_experiences_precedentes", "niveau_education", "mobilite_promotion", "satisfaction_employee_nature_travail", "note_evaluation_actuelle", "annees_depuis_la_derniere_promotion", "satisfaction_employee_equilibre_pro_perso", "revenu_par_annee_experience_interne", "nombre_participation_pee", "satisfaction_globale", "satisfaction_employee_equipe", "nb_formations_suivies"]
 
1
+ ["genre", "statut_marital", "departement", "poste", "domaine_etude", "frequence_deplacement", "heure_supplementaires", "evolution_cat_evol", "categorie_employe", "satisfaction_employee_nature_travail", "nombre_participation_pee", "ecart_note_evaluation", "revenu_mensuel", "distance_domicile_travail", "satisfaction_globale", "niveau_education", "note_evaluation_actuelle", "satisfaction_employee_equipe", "age", "revenu_par_annee_experience_interne", "satisfaction_employee_equilibre_pro_perso", "nombre_experiences_precedentes", "annees_dans_l_entreprise", "nb_formations_suivies", "revenu_par_annee_experience_totale", "ratio_sans_promotion", "satisfaction_employee_environnement", "exp_hors_entreprise", "mobilite_promotion", "annees_depuis_la_derniere_promotion"]
App/predict.py CHANGED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import joblib
2
+ import pandas as pd
3
+ from App.schemas import EmployeeFeatures
4
+ import json
5
+
6
+
7
+ model = joblib.load("App/model/modele_final_xgb.joblib")
8
+
9
+ FEATURES = list(EmployeeFeatures.model_fields.keys())
10
+ with open("App/model/mapping_classes.json") as f:
11
+ CLASS_MAPPING = json.load(f)
12
+
13
+ def predict_employee(data: dict):
14
+ df = pd.DataFrame([data])[FEATURES]
15
+
16
+ print("Colonnes API :", df.columns.tolist())
17
+ print("Nombre colonnes API :", len(df.columns))
18
+
19
+ pred = model.predict(df)[0]
20
+ proba = model.predict_proba(df)[0][1]
21
+
22
+ return {
23
+ "Prediction": CLASS_MAPPING[str(pred)],
24
+ "Probabilite_depart": float(proba)
25
+ }
App/schemas.py CHANGED
@@ -1,5 +1,4 @@
1
  from pydantic import BaseModel
2
- from typing import Optional
3
 
4
  class EmployeeFeatures(BaseModel):
5
  genre: str
 
1
  from pydantic import BaseModel
 
2
 
3
  class EmployeeFeatures(BaseModel):
4
  genre: str
README.md CHANGED
@@ -18,7 +18,6 @@ versionnage, tests, base de données et automatisation.
18
  - Préparer une base solide pour un déploiement en production
19
 
20
 
21
-
22
  ## Périmètre fonctionnel
23
  Le projet inclut :
24
  - Une API développée avec **FastAPI**
@@ -40,9 +39,60 @@ le pipeline exécute automatiquement les étapes suivantes :
40
 
41
  L’objectif est de garantir que :
42
  - le projet reste installable
43
- - les transformations et composants critiques ne régressent pas
44
  - toute fusion vers la branche `develop` est validée automatiquement
45
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
 
47
  ## Stack technique
48
  - **Langage** : Python
 
18
  - Préparer une base solide pour un déploiement en production
19
 
20
 
 
21
  ## Périmètre fonctionnel
22
  Le projet inclut :
23
  - Une API développée avec **FastAPI**
 
39
 
40
  L’objectif est de garantir que :
41
  - le projet reste installable
42
+ - les transformations et composants (chargement du modèle, prédiction) ne régressent pas
43
  - toute fusion vers la branche `develop` est validée automatiquement
44
 
45
+ ## Architecture de l’API
46
+
47
+ L’API est développée avec **FastAPI** et repose sur :
48
+ - un schéma d’entrée validé avec **Pydantic**
49
+ - un préprocesseur entraîné et sauvegardé
50
+ - un modèle de machine learning sérialisé avec **joblib**
51
+
52
+ Les artefacts du modèle sont stockés dans le dossier `App/model/` :
53
+ - `preprocesseur_fitted.joblib`
54
+ - `model_final_xgb.joblib`
55
+ - `mapping_classes.json`
56
+
57
+ ## Lancer l’API en local
58
+
59
+ Depuis la racine du projet :
60
+
61
+ ```bash
62
+ uvicorn App.main:app --reload --log-level debug
63
+ ```
64
+ L’API est alors accessible à l’adresse http://127.0.0.1:8000/
65
+
66
+ La documentation interactive à http://127.0.0.1:8000/docs
67
+
68
+ ### Endpoint principal
69
+ `POST /predict`
70
+
71
+ Cet endpoint reçoit les caractéristiques d’un employé et retourne :
72
+
73
+ - une prédiction lisible ("Reste" ou "Part")
74
+ - la probabilité associée au départ
75
+
76
+ Exemple de réponse :
77
+ ```json
78
+ {
79
+ "prediction": "Part",
80
+ "probabilite_depart": 0.79
81
+ }
82
+ ```
83
+ Les données d’entrée sont validées automatiquement avant l’appel au modèle,
84
+ garantissant la cohérence avec les variables utilisées lors de l’entraînement.
85
+
86
+ ## Documentation des endpoints
87
+
88
+ L’API expose un endpoint principal de prédiction.
89
+
90
+ **POST /predict**
91
+ - Description : retourne une prédiction de départ d’un employé
92
+ - Validation des données : Pydantic
93
+ - Réponses possibles :
94
+ - 200 : prédiction valide
95
+ - 422 : données invalides
96
 
97
  ## Stack technique
98
  - **Langage** : Python
tests/test_api.py ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi.testclient import TestClient
2
+ from App.main import app
3
+
4
+ client = TestClient(app)
5
+
6
+ def test_predict_endpoint():
7
+
8
+ emp_caract = {
9
+ "genre": "M",
10
+ "statut_marital": "Marié(e)",
11
+ "departement": "Commercial",
12
+ "poste": "Cadre Commercial",
13
+ "domaine_etude": "Infra & Cloud",
14
+ "frequence_deplacement": "Occasionnel",
15
+ "heure_supplementaires": "false",
16
+ "evolution_cat_evol": "hausse",
17
+ "categorie_employe": "employe-experimente",
18
+ "satisfaction_employee_nature_travail": 3,
19
+ "nombre_participation_pee": 0,
20
+ "ecart_note_evaluation": 1,
21
+ "revenu_mensuel": 10609,
22
+ "distance_domicile_travail": 1,
23
+ "satisfaction_globale": 2.00,
24
+ "niveau_education": 2,
25
+ "note_evaluation_actuelle": 3,
26
+ "satisfaction_employee_equipe": 3,
27
+ "age": 37,
28
+ "revenu_par_annee_experience_interne": 9093,
29
+ "satisfaction_employee_equilibre_pro_perso": 1,
30
+ "nombre_experiences_precedentes": 5,
31
+ "annees_dans_l_entreprise": 14,
32
+ "nb_formations_suivies": 2,
33
+ "revenu_par_annee_experience_totale": 7488,
34
+ "ratio_sans_promotion": 0,
35
+ "satisfaction_employee_environnement": 1,
36
+ "exp_hors_entreprise": 3,
37
+ "mobilite_promotion": -10,
38
+ "annees_depuis_la_derniere_promotion": 11}
39
+
40
+ response = client.post("/predict", json = emp_caract)
41
+
42
+ assert response.status_code == 200
43
+ assert "prediction" in response.json()
44
+ assert "probabilite_depart" in response.json()