ASI-Engineer commited on
Commit
c49544d
·
verified ·
1 Parent(s): 50dc1d6

Upload folder using huggingface_hub

Browse files
Files changed (2) hide show
  1. README.md +320 -77
  2. src/schemas.py +13 -12
README.md CHANGED
@@ -1,106 +1,349 @@
1
- ---
2
- title: Employee Turnover Prediction API
3
- emoji: 👔
4
- colorFrom: blue
5
- colorTo: purple
6
- sdk: gradio
7
- pinned: true
8
- license: mit
9
- app_port: 7860
10
- ---
11
 
 
12
 
13
- # Employee Turnover Prediction API 🚀 (v3.2.1)
14
 
15
- API de prédiction du turnover des employés (XGBoost + SMOTE) avec endpoints batch, validation stricte et documentation à jour.
16
 
17
- ## 🎯 Fonctionnalités
18
-
19
- - ✅ Prédiction de turnover (0 = reste, 1 = part)
20
  - 📦 Endpoint batch CSV (3 fichiers bruts)
21
- - 🎛️ Sliders Gradio et schémas Pydantic alignés sur les min/max réels
22
- - 📊 Probabilités et niveau de risque (Low/Medium/High)
23
- - 🔐 Authentification API Key (obligatoire)
24
- - 📝 Logs structurés JSON
25
- - 🛡️ Rate limiting (20 req/min)
26
- - 📚 Documentation OpenAPI/Swagger
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
 
 
 
28
 
29
- ## 🔗 Endpoints
30
 
31
- | Endpoint | Description |
32
- |----------|-------------|
33
- | `/docs` | Documentation interactive Swagger |
34
- | `/health` | Status de l'API |
35
- | `/ui` | Interface Gradio interactive |
36
- | `/predict` | Prédiction unitaire (JSON, contraintes réelles) |
37
- | `/predict/batch` | Prédiction batch (3 fichiers CSV bruts) |
38
 
 
39
 
40
- ## 🚀 Utilisation
 
 
41
 
42
- ### Prédiction unitaire (toutes contraintes appliquées)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
  ```bash
44
- curl -X POST https://asi-engineer-oc-p5-dev.hf.space/predict \
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
  -H "Content-Type: application/json" \
46
- -H "X-API-Key: your-key" \
47
- -d '{
48
- "nombre_participation_pee": 0,
49
- "nb_formations_suivies": 2,
50
- "nombre_employee_sous_responsabilite": 1,
51
- "distance_domicile_travail": 15,
52
- "niveau_education": 3,
53
- "domaine_etude": "Infra & Cloud",
54
- "ayant_enfants": "Y",
55
- "frequence_deplacement": "Occasionnel",
56
- "annees_depuis_la_derniere_promotion": 2,
57
- "annes_sous_responsable_actuel": 5,
58
- "satisfaction_employee_environnement": 3,
59
- "note_evaluation_precedente": 4,
60
- "niveau_hierarchique_poste": 2,
61
- "satisfaction_employee_nature_travail": 3,
62
- "satisfaction_employee_equipe": 3,
63
- "satisfaction_employee_equilibre_pro_perso": 2,
64
- "note_evaluation_actuelle": 4,
65
- "heure_supplementaires": "Non",
66
- "augementation_salaire_precedente": 5.5,
67
- "age": 35,
68
- "genre": "M",
69
- "revenu_mensuel": 4500.0,
70
- "statut_marital": "Marié(e)",
71
- "departement": "Commercial",
72
- "poste": "Manager",
73
- "nombre_experiences_precedentes": 3,
74
- "nombre_heures_travailless": 80,
75
- "annee_experience_totale": 10,
76
- "annees_dans_l_entreprise": 5,
77
- "annees_dans_le_poste_actuel": 2
78
- }'
79
  ```
80
 
81
- ### Prédiction batch (3 fichiers CSV bruts)
 
 
 
82
  ```bash
83
- curl -X POST https://asi-engineer-oc-p5-dev.hf.space/predict/batch \
84
- -H "X-API-Key: your-key" \
85
- -F "sondage_file=@extrait_sondage.csv" \
86
- -F "eval_file=@extrait_eval.csv" \
87
- -F "sirh_file=@extrait_sirh.csv"
 
 
 
 
88
  ```
89
 
90
- **Réponse :**
91
- ```json
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
  {
93
  "total_employees": 1470,
94
- "predictions": [...],
 
 
 
95
  "summary": {
96
  "total_stay": 1169,
97
  "total_leave": 301,
98
- "high_risk_count": 222
 
 
99
  }
100
  }
101
  ```
102
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
103
 
104
- ## 📚 Documentation complète
105
 
106
- Voir [docs/API.md](docs/API.md) ou le [GitHub Repository](https://github.com/chaton59/OC_P5) pour la documentation complète et les contraintes détaillées (min/max, enums, etc).
 
 
1
+ # 🚀 Employee Turnover Prediction API - v3.2.1
 
 
 
 
 
 
 
 
 
2
 
3
+ ## 📊 Vue d'ensemble
4
 
5
+ API REST de prédiction du turnover des employés basée sur un modèle XGBoost avec SMOTE.
6
 
 
7
 
8
+ **✨ Nouveautés v3.2.1** :
9
+ - 🎛️ Sliders Gradio et schémas Pydantic alignés sur les min/max réels des données d'entraînement
 
10
  - 📦 Endpoint batch CSV (3 fichiers bruts)
11
+ - 🔑 Authentification API Key (prod)
12
+ - 🔧 Correction preprocessing (scaling, ordre des colonnes)
13
+ - 📝 Documentation et exemples mis à jour
14
+
15
+ ## 🏗️ Architecture
16
+
17
+ ```
18
+ OC_P5/
19
+ ├── app.py # Point d'entrée FastAPI
20
+ ├── src/
21
+ │ ├── auth.py # Authentification API Key
22
+ │ ├── config.py # Configuration centralisée
23
+ │ ├── logger.py # Logging structuré (NOUVEAU)
24
+ │ ├── models.py # Chargement modèle HF Hub
25
+ │ ├── preprocessing.py # Pipeline preprocessing
26
+ │ ├── rate_limit.py # Rate limiting (NOUVEAU)
27
+ │ └── schemas.py # Validation Pydantic
28
+ ├── tests/ # Suite pytest (84 tests, 75.12% couverture)
29
+ ├── logs/ # Logs JSON (NOUVEAU)
30
+ │ ├── api.log # Tous les logs
31
+ │ └── error.log # Erreurs uniquement
32
+ ├── docs/ # Documentation
33
+ ├── ml_model/ # Scripts training
34
+ └── data/ # Données sources
35
+ ## 🗄️ Schéma de la Base de Données (PostgreSQL)
36
+
37
+ Schéma UML pour traçabilité ML (basé sur P5 prédiction turnover employé) :
38
+ ![Schéma BDD](docs/schema.png)
39
+
40
+ - **dataset** : Dataset original (référence pour tests/retraining). Colonnes adaptées au modèle de prédiction turnover.
41
+ - **ml_logs** : Logs inputs/outputs (JSON pour flexibilité, timestamp pour audits).
42
 
43
+ Choix : Structure relationnelle pour efficacité volume data ; sécurité via user dédié (ml_user).
44
+ Instructions : Voir create_db.py pour création.
45
 
46
+ 📖 **Guide complet pour débutants** : [docs/database_guide.md](docs/database_guide.md)
47
 
48
+ ### 🖥️ Outils DB Visuels
 
 
 
 
 
 
49
 
50
+ Pour une gestion visuelle de la base de données PostgreSQL, utilisez DBeaver (recommandé pour la mission POC).
51
 
52
+ #### Installation de DBeaver
53
+ 1. Téléchargez DBeaver Community depuis [dbeaver.io](https://dbeaver.io/download/).
54
+ 2. Installez l'application sur votre système (Windows/Mac/Linux).
55
 
56
+ #### Configuration de la connexion PostgreSQL
57
+ 1. Ouvrez DBeaver et cliquez sur "New Database Connection".
58
+ 2. Sélectionnez "PostgreSQL" comme type de base de données.
59
+ 3. Renseignez les paramètres de connexion :
60
+ - **Host** : `localhost` (ou l'IP de votre serveur PostgreSQL)
61
+ - **Port** : `5432` (port par défaut PostgreSQL)
62
+ - **Database** : `oc_p5_db`
63
+ - **Username** : `ml_user`
64
+ - **Password** : Le mot de passe défini dans votre fichier `.env` (variable `DB_PASSWORD`)
65
+ 4. Cliquez sur "Test Connection" pour vérifier.
66
+ 5. Enregistrez la connexion.
67
+
68
+ #### Utilisation
69
+ - Explorez les tables `dataset` et `ml_logs`.
70
+ - Exécutez des requêtes SQL directement dans l'interface.
71
+ - Visualisez les données et les schémas.
72
+
73
+ ### 💾 Insertion du Dataset
74
  ```bash
75
+ # Insérer le dataset complet (1470 employés)
76
+ poetry run python scripts/insert_dataset.py
77
+
78
+ # Vérifier l'insertion
79
+ psql -h localhost -U ml_user -d oc_p5_db -c "SELECT COUNT(*) FROM dataset;"
80
+ ```
81
+
82
+ ### Prérequis
83
+ - Python 3.12+
84
+ - Poetry 1.7+
85
+ - Git
86
+
87
+ ### Setup rapide
88
+
89
+ ```bash
90
+ # 1. Cloner le repo
91
+ git clone https://github.com/chaton59/OC_P5.git
92
+ cd OC_P5
93
+
94
+ # 2. Installer les dépendances
95
+ poetry install
96
+
97
+ # 3. Configurer l'environnement
98
+ cp .env.example .env
99
+ # Éditer .env avec vos valeurs
100
+
101
+ # 4. Lancer l'API
102
+ poetry run uvicorn app:app --reload
103
+
104
+ # 5. Accéder à la documentation
105
+ # http://localhost:8000/docs
106
+ ```
107
+
108
+ ## 📝 Configuration (.env)
109
+
110
+ ```bash
111
+ # Mode développement (désactive auth + active logs détaillés)
112
+ DEBUG=true
113
+
114
+ # API Key (requis en production)
115
+ API_KEY=your-secret-key-here
116
+
117
+ # Logging (DEBUG, INFO, WARNING, ERROR, CRITICAL)
118
+ LOG_LEVEL=INFO
119
+
120
+ # HuggingFace Model
121
+ HF_MODEL_REPO=ASI-Engineer/employee-turnover-model
122
+ MODEL_FILENAME=model/model.pkl
123
+ ```
124
+
125
+ ## 🔒 Authentification
126
+
127
+ ### Mode DEBUG (développement)
128
+ ```bash
129
+ # L'API Key n'est PAS requise
130
+ curl http://localhost:8000/predict -H "Content-Type: application/json" -d '{...}'
131
+ ```
132
+
133
+ ### Mode PRODUCTION
134
+ ```bash
135
+ # L'API Key est REQUISE
136
+ curl http://localhost:8000/predict \
137
+ -H "X-API-Key: your-secret-key" \
138
  -H "Content-Type: application/json" \
139
+ -d '{...}'
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
140
  ```
141
 
142
+
143
+ ## 📡 Endpoints
144
+
145
+ ### 🏥 Health Check
146
  ```bash
147
+ GET /health
148
+
149
+ # Réponse
150
+ {
151
+ "status": "healthy",
152
+ "model_loaded": true,
153
+ "model_type": "Pipeline",
154
+ "version": "3.2.1"
155
+ }
156
  ```
157
 
158
+ ### 🔮 Prédiction unitaire
159
+ ```bash
160
+ POST /predict
161
+ Content-Type: application/json
162
+ X-API-Key: your-key (en production)
163
+
164
+ # Payload (exemple, contraintes réelles appliquées)
165
+ {
166
+ "nombre_participation_pee": 0,
167
+ "nb_formations_suivies": 2,
168
+ "nombre_employee_sous_responsabilite": 1,
169
+ "distance_domicile_travail": 15,
170
+ "niveau_education": 3,
171
+ "domaine_etude": "Infra & Cloud",
172
+ "ayant_enfants": "Y",
173
+ "frequence_deplacement": "Occasionnel",
174
+ "annees_depuis_la_derniere_promotion": 2,
175
+ "annes_sous_responsable_actuel": 5,
176
+ "satisfaction_employee_environnement": 3,
177
+ "note_evaluation_precedente": 4,
178
+ "niveau_hierarchique_poste": 2,
179
+ "satisfaction_employee_nature_travail": 3,
180
+ "satisfaction_employee_equipe": 3,
181
+ "satisfaction_employee_equilibre_pro_perso": 2,
182
+ "note_evaluation_actuelle": 4,
183
+ "heure_supplementaires": "Non",
184
+ "augementation_salaire_precedente": 5.5,
185
+ "age": 35,
186
+ "genre": "M",
187
+ "revenu_mensuel": 4500.0,
188
+ "statut_marital": "Marié(e)",
189
+ "departement": "Commercial",
190
+ "poste": "Manager",
191
+ "nombre_experiences_precedentes": 3,
192
+ "nombre_heures_travailless": 80,
193
+ "annee_experience_totale": 10,
194
+ "annees_dans_l_entreprise": 5,
195
+ "annees_dans_le_poste_actuel": 2
196
+ }
197
+
198
+ # Réponse
199
+ {
200
+ "prediction": 0, # 0 = reste, 1 = part
201
+ "probability_0": 0.85, # Probabilité de rester
202
+ "probability_1": 0.15, # Probabilité de partir
203
+ "risk_level": "Low" # Low, Medium, High
204
+ }
205
+ ```
206
+
207
+ ### 📦 Prédiction batch (CSV)
208
+ ```bash
209
+ POST /predict/batch
210
+ X-API-Key: your-key (en production)
211
+
212
+ # Envoi des 3 fichiers CSV bruts
213
+ curl -X POST "http://localhost:8000/predict/batch" \
214
+ -H "X-API-Key: your-key" \
215
+ -F "sondage_file=@data/extrait_sondage.csv" \
216
+ -F "eval_file=@data/extrait_eval.csv" \
217
+ -F "sirh_file=@data/extrait_sirh.csv"
218
+
219
+ # Réponse
220
  {
221
  "total_employees": 1470,
222
+ "predictions": [
223
+ {"employee_id": 1, "prediction": 1, "probability_leave": 0.84, "risk_level": "High"},
224
+ {"employee_id": 2, "prediction": 0, "probability_leave": 0.11, "risk_level": "Low"}
225
+ ],
226
  "summary": {
227
  "total_stay": 1169,
228
  "total_leave": 301,
229
+ "high_risk_count": 222,
230
+ "medium_risk_count": 233,
231
+ "low_risk_count": 1015
232
  }
233
  }
234
  ```
235
 
236
+ ## 📊 Logging
237
+
238
+ ### Logs structurés JSON
239
+
240
+ **Fichiers** :
241
+ - `logs/api.log` : Tous les logs
242
+ - `logs/error.log` : Erreurs uniquement
243
+
244
+ **Format** :
245
+ ```json
246
+ {
247
+ "timestamp": "2025-12-26T10:30:45",
248
+ "level": "INFO",
249
+ "logger": "employee_turnover_api",
250
+ "message": "Request POST /predict",
251
+ "method": "POST",
252
+ "path": "/predict",
253
+ "status_code": 200,
254
+ "duration_ms": 23.45,
255
+ "client_host": "127.0.0.1"
256
+ }
257
+ ```
258
+
259
+ ## 🛡️ Rate Limiting
260
+
261
+ **Configuration** :
262
+ - **Développement** : Désactivé (DEBUG=true)
263
+ - **Production** : 20 requêtes/minute par IP ou API Key
264
+
265
+ **En cas de dépassement** :
266
+ ```json
267
+ {
268
+ "error": "Rate limit exceeded",
269
+ "message": "20 per 1 minute"
270
+ }
271
+ ```
272
+
273
+ ## ✅ Tests
274
+
275
+ ```bash
276
+ # Tous les tests
277
+ poetry run pytest tests/ -v
278
+
279
+ # Avec couverture
280
+ poetry run pytest tests/ --cov --cov-report=html
281
+
282
+ # Voir rapport HTML
283
+ open htmlcov/index.html
284
+ ```
285
+
286
+ **Résultats** :
287
+ - ✅ 84 tests passés
288
+ - 📊 75.12% de couverture globale
289
+
290
+ ## 🚀 Déploiement
291
+
292
+ ### Variables d'environnement requises
293
+ ```bash
294
+ DEBUG=false
295
+ API_KEY=<votre-clé-sécurisée>
296
+ LOG_LEVEL=INFO
297
+ ```
298
+
299
+ ### HuggingFace Spaces
300
+ Prêt pour déploiement avec `app.py` et `requirements.txt`
301
+
302
+ ## 📚 Documentation
303
+
304
+ - **API Interactive** : http://localhost:8000/docs
305
+ - **ReDoc** : http://localhost:8000/redoc
306
+ - **Guide complet** : [docs/API_GUIDE.md](docs/API_GUIDE.md)
307
+ - **Standards** : [docs/standards.md](docs/standards.md)
308
+ - **Couverture tests** : [docs/TEST_COVERAGE.md](docs/TEST_COVERAGE.md)
309
+
310
+ ## 📦 Dépendances principales
311
+
312
+ - **FastAPI** 0.115.14 : Framework web
313
+ - **Pydantic** 2.12.5 : Validation données
314
+ - **XGBoost** 2.1.3 : Modèle ML
315
+ - **SlowAPI** 0.1.9 : Rate limiting
316
+ - **python-json-logger** 4.0.0 : Logs structurés
317
+ - **pytest** 9.0.2 : Tests
318
+
319
+
320
+ ## 🔄 Changelog
321
+
322
+ ### v3.2.1 (janvier 2026)
323
+ - 🎛️ Sliders Gradio et schémas Pydantic alignés sur les min/max réels des données d'entraînement
324
+ - 📦 Endpoint batch CSV (3 fichiers bruts)
325
+ - 🔑 Authentification API Key (prod)
326
+ - 🔧 Correction preprocessing (scaling, ordre des colonnes)
327
+ - 📝 Documentation et exemples mis à jour
328
+
329
+ ### v2.2.0 (27 décembre 2025)
330
+ - 📦 Nouvel endpoint `/predict/batch` pour traitement CSV direct
331
+ - 🔧 Fix preprocessing : ajout du scaling des features
332
+ - 🔧 Fix preprocessing : correction de l'ordre des colonnes
333
+ - 📊 Amélioration précision des prédictions (~90%)
334
+
335
+ ### v2.1.0 (26 décembre 2025)
336
+ - ✨ Système de logging structuré JSON
337
+ - 🛡️ Rate limiting avec SlowAPI
338
+ - ⚡ Amélioration gestion d'erreurs
339
+ - 📊 Monitoring des performances
340
+
341
+ ### v2.0.0 (26 décembre 2025)
342
+ - ✅ Suite de tests complète (84 tests)
343
+ - 🔐 Authentification API Key
344
+ - 📊 88% de couverture de code
345
 
346
+ ## 👥 Auteurs
347
 
348
+ - **Projet** : OpenClassrooms P5
349
+ - **Repo** : [github.com/chaton59/OC_P5](https://github.com/chaton59/OC_P5)
src/schemas.py CHANGED
@@ -6,9 +6,16 @@ Ces schémas correspondent aux colonnes brutes du dataset avant preprocessing,
6
  permettant une validation stricte des inputs avec messages d'erreur clairs.
7
  """
8
  from enum import Enum
9
- from typing import Literal
10
 
11
- from pydantic import BaseModel, Field, field_validator, ConfigDict
 
 
 
 
 
 
 
12
 
13
 
14
  # Enums pour les valeurs catégorielles
@@ -132,8 +139,10 @@ class EmployeeInput(BaseModel):
132
  heure_supplementaires: Literal["Oui", "Non"] = Field(
133
  ..., description="Fait des heures supplémentaires"
134
  )
135
- augementation_salaire_precedente: float = Field(
136
- ..., ge=0, le=100, description="Augmentation salaire précédente (%)"
 
 
137
  )
138
 
139
  # === Données SIRH ===
@@ -164,14 +173,6 @@ class EmployeeInput(BaseModel):
164
  ..., ge=0, le=18, description="Années dans le poste actuel (0-18)"
165
  )
166
 
167
- @field_validator("augementation_salaire_precedente")
168
- @classmethod
169
- def validate_augmentation(cls, v: float) -> float:
170
- """Nettoie le format de l'augmentation (enlève % si présent)."""
171
- if isinstance(v, str):
172
- v = float(v.replace(" %", "").replace("%", ""))
173
- return v
174
-
175
  model_config = ConfigDict(
176
  json_schema_extra={
177
  "example": {
 
6
  permettant une validation stricte des inputs avec messages d'erreur clairs.
7
  """
8
  from enum import Enum
9
+ from typing import Annotated, Literal
10
 
11
+ from pydantic import BaseModel, BeforeValidator, ConfigDict, Field
12
+
13
+
14
+ def validate_augmentation(v):
15
+ """Nettoie le format de l'augmentation (enlève % si présent)."""
16
+ if isinstance(v, str):
17
+ v = float(v.replace(" %", "").replace("%", ""))
18
+ return v
19
 
20
 
21
  # Enums pour les valeurs catégorielles
 
139
  heure_supplementaires: Literal["Oui", "Non"] = Field(
140
  ..., description="Fait des heures supplémentaires"
141
  )
142
+ augementation_salaire_precedente: Annotated[
143
+ float, BeforeValidator(validate_augmentation)
144
+ ] = Field(
145
+ default=..., ge=0, le=100, description="Augmentation salaire précédente (%)"
146
  )
147
 
148
  # === Données SIRH ===
 
173
  ..., ge=0, le=18, description="Années dans le poste actuel (0-18)"
174
  )
175
 
 
 
 
 
 
 
 
 
176
  model_config = ConfigDict(
177
  json_schema_extra={
178
  "example": {