ASI-Engineer commited on
Commit
5709d57
·
verified ·
1 Parent(s): ae1ce25

Upload folder using huggingface_hub

Browse files
Files changed (4) hide show
  1. README.md +225 -35
  2. app.py +9 -0
  3. requirements.txt +18 -0
  4. src/gradio_ui.py +492 -0
README.md CHANGED
@@ -1,49 +1,239 @@
1
- ---
2
- title: Employee Turnover Prediction API
3
- emoji: 👔
4
- colorFrom: blue
5
- colorTo: purple
6
- sdk: docker
7
- pinned: true
8
- license: mit
9
- app_port: 8000
10
- ---
11
 
12
- # Employee Turnover Prediction API 🚀
13
 
14
- API de prédiction du turnover des employés avec XGBoost + SMOTE.
15
 
16
- ## 🎯 Fonctionnalités
17
-
18
- - Prédiction de turnover (0 = reste, 1 = part)
19
- - 📊 Probabilités et niveau de risque (Low/Medium/High)
 
20
  - 🔐 Authentification API Key
21
- - 📝 Logs structurés JSON
22
- - 🛡️ Rate limiting (20 req/min)
23
- - 📚 Documentation OpenAPI/Swagger
24
 
25
- ## 🔗 Endpoints
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
 
27
- - **Docs** : `/docs` - Documentation interactive
28
- - **Health** : `/health` - Status de l'API
29
- - **Predict** : `/predict` - Prédiction de turnover
30
 
31
- ## 🚀 Utilisation
32
 
33
  ```bash
34
- # Health check
35
- curl https://asi-engineer-employee-turnover-api.hf.space/health
 
 
 
36
 
37
- # Prédiction
38
- curl -X POST https://asi-engineer-employee-turnover-api.hf.space/predict \
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
  -H "Content-Type: application/json" \
40
- -d '{
41
- "satisfaction_employee_environnement": 3,
42
- "satisfaction_employee_nature_travail": 4,
43
- ...
44
- }'
45
  ```
46
 
47
- ## 📚 Documentation complète
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
48
 
49
- Voir [GitHub Repository](https://github.com/chaton59/OC_P5) pour la documentation complète.
 
 
1
+ # 🚀 Employee Turnover Prediction API - v2.1.0
 
 
 
 
 
 
 
 
 
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
+ **✨ Nouveautés v2.1.0** :
8
+ - 📝 Logging structuré JSON
9
+ - 🛡️ Rate limiting (20 req/min par IP)
10
+ - Gestion d'erreurs améliorée
11
+ - 📊 Monitoring des performances
12
  - 🔐 Authentification API Key
 
 
 
13
 
14
+ ## 🏗️ Architecture
15
+
16
+ ```
17
+ OC_P5/
18
+ ├── app.py # Point d'entrée FastAPI
19
+ ├── src/
20
+ │ ├── auth.py # Authentification API Key
21
+ │ ├── config.py # Configuration centralisée
22
+ │ ├── logger.py # Logging structuré (NOUVEAU)
23
+ │ ├── models.py # Chargement modèle HF Hub
24
+ │ ├── preprocessing.py # Pipeline preprocessing
25
+ │ ├── rate_limit.py # Rate limiting (NOUVEAU)
26
+ │ └── schemas.py # Validation Pydantic
27
+ ├── tests/ # Suite pytest (33 tests, 88% couverture)
28
+ ├── logs/ # Logs JSON (NOUVEAU)
29
+ │ ├── api.log # Tous les logs
30
+ │ └── error.log # Erreurs uniquement
31
+ ├── docs/ # Documentation
32
+ ├── ml_model/ # Scripts training
33
+ └── data/ # Données sources
34
+ ```
35
+
36
+ ## 🚀 Installation
37
+
38
+ ### Prérequis
39
+ - Python 3.12+
40
+ - Poetry 1.7+
41
+ - Git
42
+
43
+ ### Setup rapide
44
+
45
+ ```bash
46
+ # 1. Cloner le repo
47
+ git clone https://github.com/chaton59/OC_P5.git
48
+ cd OC_P5
49
+
50
+ # 2. Installer les dépendances
51
+ poetry install
52
+
53
+ # 3. Configurer l'environnement
54
+ cp .env.example .env
55
+ # Éditer .env avec vos valeurs
56
+
57
+ # 4. Lancer l'API
58
+ poetry run uvicorn app:app --reload
59
 
60
+ # 5. Accéder à la documentation
61
+ # http://localhost:8000/docs
62
+ ```
63
 
64
+ ## 📝 Configuration (.env)
65
 
66
  ```bash
67
+ # Mode développement (désactive auth + active logs détaillés)
68
+ DEBUG=true
69
+
70
+ # API Key (requis en production)
71
+ API_KEY=your-secret-key-here
72
 
73
+ # Logging (DEBUG, INFO, WARNING, ERROR, CRITICAL)
74
+ LOG_LEVEL=INFO
75
+
76
+ # HuggingFace Model
77
+ HF_MODEL_REPO=ASI-Engineer/employee-turnover-model
78
+ MODEL_FILENAME=model/model.pkl
79
+ ```
80
+
81
+ ## 🔒 Authentification
82
+
83
+ ### Mode DEBUG (développement)
84
+ ```bash
85
+ # L'API Key n'est PAS requise
86
+ curl http://localhost:8000/predict -H "Content-Type: application/json" -d '{...}'
87
+ ```
88
+
89
+ ### Mode PRODUCTION
90
+ ```bash
91
+ # L'API Key est REQUISE
92
+ curl http://localhost:8000/predict \
93
+ -H "X-API-Key: your-secret-key" \
94
  -H "Content-Type: application/json" \
95
+ -d '{...}'
 
 
 
 
96
  ```
97
 
98
+ ## 📡 Endpoints
99
+
100
+ ### 🏥 Health Check
101
+ ```bash
102
+ GET /health
103
+
104
+ # Réponse
105
+ {
106
+ "status": "healthy",
107
+ "model_loaded": true,
108
+ "model_type": "Pipeline",
109
+ "version": "2.1.0"
110
+ }
111
+ ```
112
+
113
+ ### 🔮 Prédiction
114
+ ```bash
115
+ POST /predict
116
+ Content-Type: application/json
117
+ X-API-Key: your-key (en production)
118
+
119
+ # Exemple payload (voir docs/API_GUIDE.md pour tous les champs)
120
+ {
121
+ "satisfaction_employee_environnement": 3,
122
+ "satisfaction_employee_nature_travail": 4,
123
+ "satisfaction_employee_equipe": 5,
124
+ "satisfaction_employee_equilibre_pro_perso": 3,
125
+ "note_evaluation_actuelle": 85,
126
+ "annees_depuis_la_derniere_promotion": 2,
127
+ "nombre_formations_realisees": 3,
128
+ ...
129
+ }
130
+
131
+ # Réponse
132
+ {
133
+ "prediction": 0, # 0 = reste, 1 = part
134
+ "probability_0": 0.85, # Probabilité de rester
135
+ "probability_1": 0.15, # Probabilité de partir
136
+ "risk_level": "Low" # Low, Medium, High
137
+ }
138
+ ```
139
+
140
+ ## 📊 Logging
141
+
142
+ ### Logs structurés JSON
143
+
144
+ **Fichiers** :
145
+ - `logs/api.log` : Tous les logs
146
+ - `logs/error.log` : Erreurs uniquement
147
+
148
+ **Format** :
149
+ ```json
150
+ {
151
+ "timestamp": "2025-12-26T10:30:45",
152
+ "level": "INFO",
153
+ "logger": "employee_turnover_api",
154
+ "message": "Request POST /predict",
155
+ "method": "POST",
156
+ "path": "/predict",
157
+ "status_code": 200,
158
+ "duration_ms": 23.45,
159
+ "client_host": "127.0.0.1"
160
+ }
161
+ ```
162
+
163
+ ## 🛡️ Rate Limiting
164
+
165
+ **Configuration** :
166
+ - **Développement** : Désactivé (DEBUG=true)
167
+ - **Production** : 20 requêtes/minute par IP ou API Key
168
+
169
+ **En cas de dépassement** :
170
+ ```json
171
+ {
172
+ "error": "Rate limit exceeded",
173
+ "message": "20 per 1 minute"
174
+ }
175
+ ```
176
+
177
+ ## ✅ Tests
178
+
179
+ ```bash
180
+ # Tous les tests
181
+ poetry run pytest tests/ -v
182
+
183
+ # Avec couverture
184
+ poetry run pytest tests/ --cov --cov-report=html
185
+
186
+ # Voir rapport HTML
187
+ open htmlcov/index.html
188
+ ```
189
+
190
+ **Résultats** :
191
+ - ✅ 33 tests passés
192
+ - 📊 88% de couverture globale
193
+
194
+ ## 🚀 Déploiement
195
+
196
+ ### Variables d'environnement requises
197
+ ```bash
198
+ DEBUG=false
199
+ API_KEY=<votre-clé-sécurisée>
200
+ LOG_LEVEL=INFO
201
+ ```
202
+
203
+ ### HuggingFace Spaces
204
+ Prêt pour déploiement avec `app.py` et `requirements.txt`
205
+
206
+ ## 📚 Documentation
207
+
208
+ - **API Interactive** : http://localhost:8000/docs
209
+ - **ReDoc** : http://localhost:8000/redoc
210
+ - **Guide complet** : [docs/API_GUIDE.md](docs/API_GUIDE.md)
211
+ - **Standards** : [docs/standards.md](docs/standards.md)
212
+ - **Couverture tests** : [docs/TEST_COVERAGE.md](docs/TEST_COVERAGE.md)
213
+
214
+ ## 📦 Dépendances principales
215
+
216
+ - **FastAPI** 0.115.14 : Framework web
217
+ - **Pydantic** 2.12.5 : Validation données
218
+ - **XGBoost** 2.1.3 : Modèle ML
219
+ - **SlowAPI** 0.1.9 : Rate limiting
220
+ - **python-json-logger** 4.0.0 : Logs structurés
221
+ - **pytest** 9.0.2 : Tests
222
+
223
+ ## 🔄 Changelog
224
+
225
+ ### v2.1.0 (26 décembre 2025)
226
+ - ✨ Système de logging structuré JSON
227
+ - 🛡️ Rate limiting avec SlowAPI
228
+ - ⚡ Amélioration gestion d'erreurs
229
+ - 📊 Monitoring des performances
230
+
231
+ ### v2.0.0 (26 décembre 2025)
232
+ - ✅ Suite de tests complète (33 tests)
233
+ - 🔐 Authentification API Key
234
+ - 📊 88% de couverture de code
235
+
236
+ ## 👥 Auteurs
237
 
238
+ - **Projet** : OpenClassrooms P5
239
+ - **Repo** : [github.com/chaton59/OC_P5](https://github.com/chaton59/OC_P5)
app.py CHANGED
@@ -7,10 +7,12 @@ Cette API expose le modèle de prédiction de départ des employés avec :
7
  - Preprocessing automatique
8
  - Health check pour monitoring
9
  - Documentation OpenAPI/Swagger automatique
 
10
  """
11
  import time
12
  from contextlib import asynccontextmanager
13
 
 
14
  from fastapi import Depends, FastAPI, HTTPException, Request
15
  from fastapi.middleware.cors import CORSMiddleware
16
  from slowapi import _rate_limit_exceeded_handler
@@ -18,6 +20,7 @@ from slowapi.errors import RateLimitExceeded
18
 
19
  from src.auth import verify_api_key
20
  from src.config import get_settings
 
21
  from src.logger import logger, log_model_load, log_request
22
  from src.models import get_model_info, load_model
23
  from src.preprocessing import preprocess_for_prediction
@@ -237,11 +240,17 @@ async def predict(request: Request, employee: EmployeeInput):
237
  )
238
 
239
 
 
 
 
 
 
240
  if __name__ == "__main__":
241
  import uvicorn
242
 
243
  print("🚀 Lancement de l'API en mode développement...")
244
  print("📖 Documentation : http://localhost:8000/docs")
 
245
 
246
  uvicorn.run(
247
  "app:app",
 
7
  - Preprocessing automatique
8
  - Health check pour monitoring
9
  - Documentation OpenAPI/Swagger automatique
10
+ - Interface Gradio pour utilisation interactive
11
  """
12
  import time
13
  from contextlib import asynccontextmanager
14
 
15
+ import gradio as gr
16
  from fastapi import Depends, FastAPI, HTTPException, Request
17
  from fastapi.middleware.cors import CORSMiddleware
18
  from slowapi import _rate_limit_exceeded_handler
 
20
 
21
  from src.auth import verify_api_key
22
  from src.config import get_settings
23
+ from src.gradio_ui import create_gradio_interface
24
  from src.logger import logger, log_model_load, log_request
25
  from src.models import get_model_info, load_model
26
  from src.preprocessing import preprocess_for_prediction
 
240
  )
241
 
242
 
243
+ # Monter l'interface Gradio sur /ui
244
+ gradio_app = create_gradio_interface()
245
+ app = gr.mount_gradio_app(app, gradio_app, path="/ui")
246
+
247
+
248
  if __name__ == "__main__":
249
  import uvicorn
250
 
251
  print("🚀 Lancement de l'API en mode développement...")
252
  print("📖 Documentation : http://localhost:8000/docs")
253
+ print("🎨 Interface Gradio : http://localhost:8000/ui")
254
 
255
  uvicorn.run(
256
  "app:app",
requirements.txt CHANGED
@@ -1,7 +1,10 @@
 
1
  alembic==1.17.2 ; python_version >= "3.12" and python_version < "4.0"
2
  annotated-types==0.7.0 ; python_version >= "3.12" and python_version < "4.0"
3
  anyio==4.12.0 ; python_version >= "3.12" and python_version < "4.0"
 
4
  blinker==1.9.0 ; python_version >= "3.12" and python_version < "4.0"
 
5
  cachetools==6.2.4 ; python_version >= "3.12" and python_version < "4.0"
6
  certifi==2025.11.12 ; python_version >= "3.12" and python_version < "4.0"
7
  cffi==2.0.0 ; python_version >= "3.12" and python_version < "4.0" and platform_python_implementation != "PyPy"
@@ -16,6 +19,7 @@ databricks-sdk==0.76.0 ; python_version >= "3.12" and python_version < "4.0"
16
  deprecated==1.3.1 ; python_version >= "3.12" and python_version < "4.0"
17
  docker==7.1.0 ; python_version >= "3.12" and python_version < "4.0"
18
  fastapi==0.115.14 ; python_version >= "3.12" and python_version < "4.0"
 
19
  filelock==3.20.1 ; python_version >= "3.12" and python_version < "4.0"
20
  flask-cors==6.0.2 ; python_version >= "3.12" and python_version < "4.0"
21
  flask==3.1.2 ; python_version >= "3.12" and python_version < "4.0"
@@ -24,10 +28,13 @@ fsspec==2025.12.0 ; python_version >= "3.12" and python_version < "4.0"
24
  gitdb==4.0.12 ; python_version >= "3.12" and python_version < "4.0"
25
  gitpython==3.1.45 ; python_version >= "3.12" and python_version < "4.0"
26
  google-auth==2.45.0 ; python_version >= "3.12" and python_version < "4.0"
 
 
27
  graphene==3.4.3 ; python_version >= "3.12" and python_version < "4.0"
28
  graphql-core==3.2.7 ; python_version >= "3.12" and python_version < "4.0"
29
  graphql-relay==3.2.0 ; python_version >= "3.12" and python_version < "4.0"
30
  greenlet==3.3.0 ; python_version >= "3.12" and python_version < "4.0" and (platform_machine == "aarch64" or platform_machine == "ppc64le" or platform_machine == "x86_64" or platform_machine == "amd64" or platform_machine == "AMD64" or platform_machine == "win32" or platform_machine == "WIN32")
 
31
  gunicorn==23.0.0 ; python_version >= "3.12" and python_version < "4.0" and platform_system != "Windows"
32
  h11==0.16.0 ; python_version >= "3.12" and python_version < "4.0"
33
  hf-xet==1.2.0 ; python_version >= "3.12" and python_version < "4.0" and (platform_machine == "x86_64" or platform_machine == "amd64" or platform_machine == "AMD64" or platform_machine == "arm64" or platform_machine == "aarch64")
@@ -45,8 +52,10 @@ joblib==1.5.3 ; python_version >= "3.12" and python_version < "4.0"
45
  kiwisolver==1.4.9 ; python_version >= "3.12" and python_version < "4.0"
46
  limits==5.6.0 ; python_version >= "3.12" and python_version < "4.0"
47
  mako==1.3.10 ; python_version >= "3.12" and python_version < "4.0"
 
48
  markupsafe==3.0.3 ; python_version >= "3.12" and python_version < "4.0"
49
  matplotlib==3.10.8 ; python_version >= "3.12" and python_version < "4.0"
 
50
  mlflow-skinny==3.8.1 ; python_version >= "3.12" and python_version < "4.0"
51
  mlflow-tracing==3.8.1 ; python_version >= "3.12" and python_version < "4.0"
52
  mlflow==3.8.1 ; python_version >= "3.12" and python_version < "4.0"
@@ -56,6 +65,7 @@ opentelemetry-api==1.39.1 ; python_version >= "3.12" and python_version < "4.0"
56
  opentelemetry-proto==1.39.1 ; python_version >= "3.12" and python_version < "4.0"
57
  opentelemetry-sdk==1.39.1 ; python_version >= "3.12" and python_version < "4.0"
58
  opentelemetry-semantic-conventions==0.60b1 ; python_version >= "3.12" and python_version < "4.0"
 
59
  packaging==25.0 ; python_version >= "3.12" and python_version < "4.0"
60
  pandas==2.3.3 ; python_version >= "3.12" and python_version < "4.0"
61
  pillow==12.0.0 ; python_version >= "3.12" and python_version < "4.0"
@@ -66,17 +76,23 @@ pyasn1==0.6.1 ; python_version >= "3.12" and python_version < "4.0"
66
  pycparser==2.23 ; python_version >= "3.12" and python_version < "4.0" and platform_python_implementation != "PyPy" and implementation_name != "PyPy"
67
  pydantic-core==2.41.5 ; python_version >= "3.12" and python_version < "4.0"
68
  pydantic==2.12.5 ; python_version >= "3.12" and python_version < "4.0"
 
 
69
  pyparsing==3.3.1 ; python_version >= "3.12" and python_version < "4.0"
70
  python-dateutil==2.9.0.post0 ; python_version >= "3.12" and python_version < "4.0"
71
  python-dotenv==1.2.1 ; python_version >= "3.12" and python_version < "4.0"
72
  python-json-logger==4.0.0 ; python_version >= "3.12" and python_version < "4.0"
 
73
  pytz==2025.2 ; python_version >= "3.12" and python_version < "4.0"
74
  pywin32==311 ; python_version >= "3.12" and python_version < "4.0" and sys_platform == "win32"
75
  pyyaml==6.0.3 ; python_version >= "3.12" and python_version < "4.0"
76
  requests==2.32.5 ; python_version >= "3.12" and python_version < "4.0"
 
77
  rsa==4.9.1 ; python_version >= "3.12" and python_version < "4.0"
 
78
  scikit-learn==1.6.1 ; python_version >= "3.12" and python_version < "4.0"
79
  scipy==1.16.3 ; python_version >= "3.12" and python_version < "4.0"
 
80
  shellingham==1.5.4 ; python_version >= "3.12" and python_version < "4.0"
81
  six==1.17.0 ; python_version >= "3.12" and python_version < "4.0"
82
  sklearn-compat==0.1.5 ; python_version >= "3.12" and python_version < "4.0"
@@ -86,8 +102,10 @@ sqlalchemy==2.0.45 ; python_version >= "3.12" and python_version < "4.0"
86
  sqlparse==0.5.5 ; python_version >= "3.12" and python_version < "4.0"
87
  starlette==0.46.2 ; python_version >= "3.12" and python_version < "4.0"
88
  threadpoolctl==3.6.0 ; python_version >= "3.12" and python_version < "4.0"
 
89
  tqdm==4.67.1 ; python_version >= "3.12" and python_version < "4.0"
90
  typer-slim==0.21.0 ; python_version >= "3.12" and python_version < "4.0"
 
91
  typing-extensions==4.15.0 ; python_version >= "3.12" and python_version < "4.0"
92
  typing-inspection==0.4.2 ; python_version >= "3.12" and python_version < "4.0"
93
  tzdata==2025.3 ; python_version >= "3.12" and python_version < "4.0"
 
1
+ aiofiles==24.1.0 ; python_version >= "3.12" and python_version < "4.0"
2
  alembic==1.17.2 ; python_version >= "3.12" and python_version < "4.0"
3
  annotated-types==0.7.0 ; python_version >= "3.12" and python_version < "4.0"
4
  anyio==4.12.0 ; python_version >= "3.12" and python_version < "4.0"
5
+ audioop-lts==0.2.2 ; python_version >= "3.13" and python_version < "4.0"
6
  blinker==1.9.0 ; python_version >= "3.12" and python_version < "4.0"
7
+ brotli==1.2.0 ; python_version >= "3.12" and python_version < "4.0"
8
  cachetools==6.2.4 ; python_version >= "3.12" and python_version < "4.0"
9
  certifi==2025.11.12 ; python_version >= "3.12" and python_version < "4.0"
10
  cffi==2.0.0 ; python_version >= "3.12" and python_version < "4.0" and platform_python_implementation != "PyPy"
 
19
  deprecated==1.3.1 ; python_version >= "3.12" and python_version < "4.0"
20
  docker==7.1.0 ; python_version >= "3.12" and python_version < "4.0"
21
  fastapi==0.115.14 ; python_version >= "3.12" and python_version < "4.0"
22
+ ffmpy==1.0.0 ; python_version >= "3.12" and python_version < "4.0"
23
  filelock==3.20.1 ; python_version >= "3.12" and python_version < "4.0"
24
  flask-cors==6.0.2 ; python_version >= "3.12" and python_version < "4.0"
25
  flask==3.1.2 ; python_version >= "3.12" and python_version < "4.0"
 
28
  gitdb==4.0.12 ; python_version >= "3.12" and python_version < "4.0"
29
  gitpython==3.1.45 ; python_version >= "3.12" and python_version < "4.0"
30
  google-auth==2.45.0 ; python_version >= "3.12" and python_version < "4.0"
31
+ gradio-client==2.0.2 ; python_version >= "3.12" and python_version < "4.0"
32
+ gradio==6.2.0 ; python_version >= "3.12" and python_version < "4.0"
33
  graphene==3.4.3 ; python_version >= "3.12" and python_version < "4.0"
34
  graphql-core==3.2.7 ; python_version >= "3.12" and python_version < "4.0"
35
  graphql-relay==3.2.0 ; python_version >= "3.12" and python_version < "4.0"
36
  greenlet==3.3.0 ; python_version >= "3.12" and python_version < "4.0" and (platform_machine == "aarch64" or platform_machine == "ppc64le" or platform_machine == "x86_64" or platform_machine == "amd64" or platform_machine == "AMD64" or platform_machine == "win32" or platform_machine == "WIN32")
37
+ groovy==0.1.2 ; python_version >= "3.12" and python_version < "4.0"
38
  gunicorn==23.0.0 ; python_version >= "3.12" and python_version < "4.0" and platform_system != "Windows"
39
  h11==0.16.0 ; python_version >= "3.12" and python_version < "4.0"
40
  hf-xet==1.2.0 ; python_version >= "3.12" and python_version < "4.0" and (platform_machine == "x86_64" or platform_machine == "amd64" or platform_machine == "AMD64" or platform_machine == "arm64" or platform_machine == "aarch64")
 
52
  kiwisolver==1.4.9 ; python_version >= "3.12" and python_version < "4.0"
53
  limits==5.6.0 ; python_version >= "3.12" and python_version < "4.0"
54
  mako==1.3.10 ; python_version >= "3.12" and python_version < "4.0"
55
+ markdown-it-py==4.0.0 ; python_version >= "3.12" and python_version < "4.0"
56
  markupsafe==3.0.3 ; python_version >= "3.12" and python_version < "4.0"
57
  matplotlib==3.10.8 ; python_version >= "3.12" and python_version < "4.0"
58
+ mdurl==0.1.2 ; python_version >= "3.12" and python_version < "4.0"
59
  mlflow-skinny==3.8.1 ; python_version >= "3.12" and python_version < "4.0"
60
  mlflow-tracing==3.8.1 ; python_version >= "3.12" and python_version < "4.0"
61
  mlflow==3.8.1 ; python_version >= "3.12" and python_version < "4.0"
 
65
  opentelemetry-proto==1.39.1 ; python_version >= "3.12" and python_version < "4.0"
66
  opentelemetry-sdk==1.39.1 ; python_version >= "3.12" and python_version < "4.0"
67
  opentelemetry-semantic-conventions==0.60b1 ; python_version >= "3.12" and python_version < "4.0"
68
+ orjson==3.11.5 ; python_version >= "3.12" and python_version < "4.0"
69
  packaging==25.0 ; python_version >= "3.12" and python_version < "4.0"
70
  pandas==2.3.3 ; python_version >= "3.12" and python_version < "4.0"
71
  pillow==12.0.0 ; python_version >= "3.12" and python_version < "4.0"
 
76
  pycparser==2.23 ; python_version >= "3.12" and python_version < "4.0" and platform_python_implementation != "PyPy" and implementation_name != "PyPy"
77
  pydantic-core==2.41.5 ; python_version >= "3.12" and python_version < "4.0"
78
  pydantic==2.12.5 ; python_version >= "3.12" and python_version < "4.0"
79
+ pydub==0.25.1 ; python_version >= "3.12" and python_version < "4.0"
80
+ pygments==2.19.2 ; python_version >= "3.12" and python_version < "4.0"
81
  pyparsing==3.3.1 ; python_version >= "3.12" and python_version < "4.0"
82
  python-dateutil==2.9.0.post0 ; python_version >= "3.12" and python_version < "4.0"
83
  python-dotenv==1.2.1 ; python_version >= "3.12" and python_version < "4.0"
84
  python-json-logger==4.0.0 ; python_version >= "3.12" and python_version < "4.0"
85
+ python-multipart==0.0.21 ; python_version >= "3.12" and python_version < "4.0"
86
  pytz==2025.2 ; python_version >= "3.12" and python_version < "4.0"
87
  pywin32==311 ; python_version >= "3.12" and python_version < "4.0" and sys_platform == "win32"
88
  pyyaml==6.0.3 ; python_version >= "3.12" and python_version < "4.0"
89
  requests==2.32.5 ; python_version >= "3.12" and python_version < "4.0"
90
+ rich==14.2.0 ; python_version >= "3.12" and python_version < "4.0"
91
  rsa==4.9.1 ; python_version >= "3.12" and python_version < "4.0"
92
+ safehttpx==0.1.7 ; python_version >= "3.12" and python_version < "4.0"
93
  scikit-learn==1.6.1 ; python_version >= "3.12" and python_version < "4.0"
94
  scipy==1.16.3 ; python_version >= "3.12" and python_version < "4.0"
95
+ semantic-version==2.10.0 ; python_version >= "3.12" and python_version < "4.0"
96
  shellingham==1.5.4 ; python_version >= "3.12" and python_version < "4.0"
97
  six==1.17.0 ; python_version >= "3.12" and python_version < "4.0"
98
  sklearn-compat==0.1.5 ; python_version >= "3.12" and python_version < "4.0"
 
102
  sqlparse==0.5.5 ; python_version >= "3.12" and python_version < "4.0"
103
  starlette==0.46.2 ; python_version >= "3.12" and python_version < "4.0"
104
  threadpoolctl==3.6.0 ; python_version >= "3.12" and python_version < "4.0"
105
+ tomlkit==0.13.3 ; python_version >= "3.12" and python_version < "4.0"
106
  tqdm==4.67.1 ; python_version >= "3.12" and python_version < "4.0"
107
  typer-slim==0.21.0 ; python_version >= "3.12" and python_version < "4.0"
108
+ typer==0.21.0 ; python_version >= "3.12" and python_version < "4.0"
109
  typing-extensions==4.15.0 ; python_version >= "3.12" and python_version < "4.0"
110
  typing-inspection==0.4.2 ; python_version >= "3.12" and python_version < "4.0"
111
  tzdata==2025.3 ; python_version >= "3.12" and python_version < "4.0"
src/gradio_ui.py ADDED
@@ -0,0 +1,492 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Interface Gradio pour l'API Employee Turnover Prediction.
4
+
5
+ Cette interface permet de:
6
+ - Tester les prédictions de manière interactive
7
+ - Visualiser la documentation de l'API
8
+ - Comprendre les champs requis
9
+ """
10
+ import gradio as gr
11
+
12
+ from src.models import load_model, get_model_info
13
+ from src.preprocessing import preprocess_for_prediction
14
+ from src.schemas import EmployeeInput
15
+
16
+
17
+ def predict_turnover(
18
+ # SONDAGE
19
+ nombre_participation_pee: int,
20
+ nb_formations_suivies: int,
21
+ nombre_employee_sous_responsabilite: int,
22
+ distance_domicile_travail: int,
23
+ niveau_education: int,
24
+ domaine_etude: str,
25
+ ayant_enfants: str,
26
+ frequence_deplacement: str,
27
+ annees_depuis_la_derniere_promotion: int,
28
+ annes_sous_responsable_actuel: int,
29
+ # EVALUATION
30
+ satisfaction_employee_environnement: int,
31
+ note_evaluation_precedente: int,
32
+ niveau_hierarchique_poste: int,
33
+ satisfaction_employee_nature_travail: int,
34
+ satisfaction_employee_equipe: int,
35
+ satisfaction_employee_equilibre_pro_perso: int,
36
+ note_evaluation_actuelle: int,
37
+ heure_supplementaires: str,
38
+ augementation_salaire_precedente: float,
39
+ # SIRH
40
+ age: int,
41
+ genre: str,
42
+ revenu_mensuel: float,
43
+ statut_marital: str,
44
+ departement: str,
45
+ poste: str,
46
+ nombre_experiences_precedentes: int,
47
+ nombre_heures_travailless: int,
48
+ annee_experience_totale: int,
49
+ annees_dans_l_entreprise: int,
50
+ annees_dans_le_poste_actuel: int,
51
+ ) -> str:
52
+ """Effectue une prédiction de turnover."""
53
+ try:
54
+ # Créer l'objet EmployeeInput
55
+ employee = EmployeeInput(
56
+ nombre_participation_pee=nombre_participation_pee,
57
+ nb_formations_suivies=nb_formations_suivies,
58
+ nombre_employee_sous_responsabilite=nombre_employee_sous_responsabilite,
59
+ distance_domicile_travail=distance_domicile_travail,
60
+ niveau_education=niveau_education,
61
+ domaine_etude=domaine_etude,
62
+ ayant_enfants=ayant_enfants,
63
+ frequence_deplacement=frequence_deplacement,
64
+ annees_depuis_la_derniere_promotion=annees_depuis_la_derniere_promotion,
65
+ annes_sous_responsable_actuel=annes_sous_responsable_actuel,
66
+ satisfaction_employee_environnement=satisfaction_employee_environnement,
67
+ note_evaluation_precedente=note_evaluation_precedente,
68
+ niveau_hierarchique_poste=niveau_hierarchique_poste,
69
+ satisfaction_employee_nature_travail=satisfaction_employee_nature_travail,
70
+ satisfaction_employee_equipe=satisfaction_employee_equipe,
71
+ satisfaction_employee_equilibre_pro_perso=satisfaction_employee_equilibre_pro_perso,
72
+ note_evaluation_actuelle=note_evaluation_actuelle,
73
+ heure_supplementaires=heure_supplementaires,
74
+ augementation_salaire_precedente=augementation_salaire_precedente,
75
+ age=age,
76
+ genre=genre,
77
+ revenu_mensuel=revenu_mensuel,
78
+ statut_marital=statut_marital,
79
+ departement=departement,
80
+ poste=poste,
81
+ nombre_experiences_precedentes=nombre_experiences_precedentes,
82
+ nombre_heures_travailless=nombre_heures_travailless,
83
+ annee_experience_totale=annee_experience_totale,
84
+ annees_dans_l_entreprise=annees_dans_l_entreprise,
85
+ annees_dans_le_poste_actuel=annees_dans_le_poste_actuel,
86
+ )
87
+
88
+ # Préprocessing
89
+ features = preprocess_for_prediction(employee)
90
+
91
+ # Prédiction
92
+ model = load_model()
93
+ prediction = model.predict(features)[0]
94
+ proba = model.predict_proba(features)[0]
95
+
96
+ # Résultat
97
+ risk_level = "🔴 RISQUE ÉLEVÉ" if prediction == 1 else "🟢 RISQUE FAIBLE"
98
+ confidence = max(proba) * 100
99
+
100
+ result = f"""
101
+ ## {risk_level}
102
+
103
+ ### Résultat de la prédiction
104
+ - **Prédiction**: {"Départ probable" if prediction == 1 else "Maintien probable"}
105
+ - **Confiance**: {confidence:.1f}%
106
+ - **Probabilité de départ**: {proba[1] * 100:.1f}%
107
+ - **Probabilité de maintien**: {proba[0] * 100:.1f}%
108
+
109
+ ### Interprétation
110
+ {"⚠️ Cet employé présente des facteurs de risque de départ. Il est recommandé d'engager un dialogue pour comprendre ses attentes." if prediction == 1 else "✅ Cet employé semble stable. Continuez à maintenir un environnement de travail positif."}
111
+ """
112
+ return result
113
+
114
+ except Exception as e:
115
+ return f"❌ **Erreur**: {str(e)}"
116
+
117
+
118
+ # Documentation de l'API
119
+ API_DOCS = """
120
+ # 🚀 Employee Turnover Prediction API
121
+
122
+ ## Description
123
+ Cette API prédit le risque de départ (turnover) d'un employé en utilisant un modèle
124
+ de Machine Learning entraîné sur des données RH.
125
+
126
+ ## Endpoints disponibles
127
+
128
+ ### `GET /`
129
+ Page d'accueil avec informations sur l'API.
130
+
131
+ ### `GET /health`
132
+ Vérification de l'état de l'API.
133
+ ```bash
134
+ curl https://asi-engineer-oc-p5-dev.hf.space/health
135
+ ```
136
+
137
+ ### `GET /docs`
138
+ Documentation Swagger interactive.
139
+
140
+ ### `POST /predict`
141
+ Effectue une prédiction de turnover.
142
+
143
+ ## Exemple d'utilisation avec curl
144
+
145
+ ```bash
146
+ curl -X POST https://asi-engineer-oc-p5-dev.hf.space/predict \\
147
+ -H "Content-Type: application/json" \\
148
+ -d '{
149
+ "nombre_participation_pee": 0,
150
+ "nb_formations_suivies": 2,
151
+ "nombre_employee_sous_responsabilite": 1,
152
+ "distance_domicile_travail": 15,
153
+ "niveau_education": 3,
154
+ "domaine_etude": "Infra & Cloud",
155
+ "ayant_enfants": "Y",
156
+ "frequence_deplacement": "Occasionnel",
157
+ "annees_depuis_la_derniere_promotion": 2,
158
+ "annes_sous_responsable_actuel": 5,
159
+ "satisfaction_employee_environnement": 3,
160
+ "note_evaluation_precedente": 4,
161
+ "niveau_hierarchique_poste": 2,
162
+ "satisfaction_employee_nature_travail": 3,
163
+ "satisfaction_employee_equipe": 3,
164
+ "satisfaction_employee_equilibre_pro_perso": 2,
165
+ "note_evaluation_actuelle": 4,
166
+ "heure_supplementaires": "Non",
167
+ "augementation_salaire_precedente": 5.5,
168
+ "age": 35,
169
+ "genre": "M",
170
+ "revenu_mensuel": 4500.0,
171
+ "statut_marital": "Marié(e)",
172
+ "departement": "Commercial",
173
+ "poste": "Manager",
174
+ "nombre_experiences_precedentes": 3,
175
+ "nombre_heures_travailless": 45,
176
+ "annee_experience_totale": 10,
177
+ "annees_dans_l_entreprise": 5,
178
+ "annees_dans_le_poste_actuel": 2
179
+ }'
180
+ ```
181
+
182
+ ## Exemple avec Python
183
+
184
+ ```python
185
+ import requests
186
+
187
+ url = "https://asi-engineer-oc-p5-dev.hf.space/predict"
188
+
189
+ data = {
190
+ "nombre_participation_pee": 0,
191
+ "nb_formations_suivies": 2,
192
+ "nombre_employee_sous_responsabilite": 1,
193
+ "distance_domicile_travail": 15,
194
+ "niveau_education": 3,
195
+ "domaine_etude": "Infra & Cloud",
196
+ "ayant_enfants": "Y",
197
+ "frequence_deplacement": "Occasionnel",
198
+ "annees_depuis_la_derniere_promotion": 2,
199
+ "annes_sous_responsable_actuel": 5,
200
+ "satisfaction_employee_environnement": 3,
201
+ "note_evaluation_precedente": 4,
202
+ "niveau_hierarchique_poste": 2,
203
+ "satisfaction_employee_nature_travail": 3,
204
+ "satisfaction_employee_equipe": 3,
205
+ "satisfaction_employee_equilibre_pro_perso": 2,
206
+ "note_evaluation_actuelle": 4,
207
+ "heure_supplementaires": "Non",
208
+ "augementation_salaire_precedente": 5.5,
209
+ "age": 35,
210
+ "genre": "M",
211
+ "revenu_mensuel": 4500.0,
212
+ "statut_marital": "Marié(e)",
213
+ "departement": "Commercial",
214
+ "poste": "Manager",
215
+ "nombre_experiences_precedentes": 3,
216
+ "nombre_heures_travailless": 45,
217
+ "annee_experience_totale": 10,
218
+ "annees_dans_l_entreprise": 5,
219
+ "annees_dans_le_poste_actuel": 2
220
+ }
221
+
222
+ response = requests.post(url, json=data)
223
+ print(response.json())
224
+ ```
225
+
226
+ ## Réponse attendue
227
+
228
+ ```json
229
+ {
230
+ "prediction": 0,
231
+ "probability": {
232
+ "stay": 0.85,
233
+ "leave": 0.15
234
+ },
235
+ "risk_level": "low",
236
+ "model_version": "1.0.0"
237
+ }
238
+ ```
239
+
240
+ ## Codes d'erreur
241
+
242
+ | Code | Description |
243
+ |------|-------------|
244
+ | 200 | Succès |
245
+ | 422 | Données invalides (validation Pydantic) |
246
+ | 429 | Trop de requêtes (rate limit: 20/min) |
247
+ | 500 | Erreur serveur |
248
+
249
+ ## Modèle utilisé
250
+
251
+ - **Type**: XGBoost Pipeline
252
+ - **Source**: HuggingFace Hub (`ASI-Engineer/employee-turnover-model`)
253
+ - **Features**: 25 variables RH (sondage, évaluation, SIRH)
254
+ """
255
+
256
+
257
+ def create_gradio_interface():
258
+ """Crée l'interface Gradio complète."""
259
+
260
+ # Obtenir les infos du modèle
261
+ try:
262
+ model_info = get_model_info()
263
+ model_status = f"✅ Modèle chargé: {model_info.get('type', 'Unknown')}"
264
+ except Exception:
265
+ model_status = "⏳ Modèle en cours de chargement..."
266
+
267
+ with gr.Blocks(
268
+ title="Employee Turnover Prediction",
269
+ ) as demo:
270
+ gr.Markdown(
271
+ """
272
+ # 🏢 Employee Turnover Prediction
273
+
274
+ Prédisez le risque de départ d'un employé grâce au Machine Learning.
275
+
276
+ **Naviguez entre les onglets** pour utiliser l'interface de prédiction
277
+ ou consulter la documentation de l'API.
278
+ """
279
+ )
280
+
281
+ gr.Markdown(f"**Statut**: {model_status}")
282
+
283
+ with gr.Tabs():
284
+ # Onglet Prédiction
285
+ with gr.TabItem("🎯 Prédiction"):
286
+ gr.Markdown("### Remplissez les informations de l'employé")
287
+
288
+ with gr.Row():
289
+ # Colonne SONDAGE
290
+ with gr.Column():
291
+ gr.Markdown("#### 📋 Données Sondage")
292
+ nombre_participation_pee = gr.Slider(
293
+ 0, 10, value=0, step=1, label="Participations PEE"
294
+ )
295
+ nb_formations_suivies = gr.Slider(
296
+ 0, 10, value=2, step=1, label="Formations suivies"
297
+ )
298
+ nombre_employee_sous_responsabilite = gr.Slider(
299
+ 0, 20, value=0, step=1, label="Employés sous responsabilité"
300
+ )
301
+ distance_domicile_travail = gr.Slider(
302
+ 0, 50, value=15, step=1, label="Distance domicile (km)"
303
+ )
304
+ niveau_education = gr.Slider(
305
+ 1, 5, value=3, step=1, label="Niveau éducation (1-5)"
306
+ )
307
+ domaine_etude = gr.Dropdown(
308
+ ["Infra & Cloud", "Transformation Digitale", "Autre"],
309
+ value="Infra & Cloud",
310
+ label="Domaine d'études",
311
+ )
312
+ ayant_enfants = gr.Radio(
313
+ ["Y", "N"], value="N", label="A des enfants"
314
+ )
315
+ frequence_deplacement = gr.Dropdown(
316
+ ["Aucun", "Occasionnel", "Frequent"],
317
+ value="Occasionnel",
318
+ label="Fréquence déplacements",
319
+ )
320
+ annees_depuis_la_derniere_promotion = gr.Slider(
321
+ 0, 15, value=2, step=1, label="Années depuis promotion"
322
+ )
323
+ annes_sous_responsable_actuel = gr.Slider(
324
+ 0, 20, value=3, step=1, label="Années sous responsable"
325
+ )
326
+
327
+ # Colonne EVALUATION
328
+ with gr.Column():
329
+ gr.Markdown("#### 📊 Données Évaluation")
330
+ satisfaction_employee_environnement = gr.Slider(
331
+ 1, 5, value=3, step=1, label="Satisfaction environnement"
332
+ )
333
+ note_evaluation_precedente = gr.Slider(
334
+ 1, 5, value=3, step=1, label="Évaluation précédente"
335
+ )
336
+ niveau_hierarchique_poste = gr.Slider(
337
+ 1, 5, value=2, step=1, label="Niveau hiérarchique"
338
+ )
339
+ satisfaction_employee_nature_travail = gr.Slider(
340
+ 1, 5, value=3, step=1, label="Satisfaction nature travail"
341
+ )
342
+ satisfaction_employee_equipe = gr.Slider(
343
+ 1, 5, value=3, step=1, label="Satisfaction équipe"
344
+ )
345
+ satisfaction_employee_equilibre_pro_perso = gr.Slider(
346
+ 1, 5, value=3, step=1, label="Équilibre pro/perso"
347
+ )
348
+ note_evaluation_actuelle = gr.Slider(
349
+ 1, 5, value=3, step=1, label="Évaluation actuelle"
350
+ )
351
+ heure_supplementaires = gr.Radio(
352
+ ["Oui", "Non"], value="Non", label="Heures supplémentaires"
353
+ )
354
+ augementation_salaire_precedente = gr.Slider(
355
+ 0,
356
+ 25,
357
+ value=5.0,
358
+ step=0.5,
359
+ label="Augmentation précédente (%)",
360
+ )
361
+
362
+ # Colonne SIRH
363
+ with gr.Column():
364
+ gr.Markdown("#### 👤 Données SIRH")
365
+ age = gr.Slider(18, 65, value=35, step=1, label="Âge")
366
+ genre = gr.Radio(["M", "F"], value="M", label="Genre")
367
+ revenu_mensuel = gr.Slider(
368
+ 1500,
369
+ 15000,
370
+ value=4500,
371
+ step=100,
372
+ label="Revenu mensuel (€)",
373
+ )
374
+ statut_marital = gr.Dropdown(
375
+ ["Célibataire", "Marié(e)", "Divorcé(e)"],
376
+ value="Célibataire",
377
+ label="Statut marital",
378
+ )
379
+ departement = gr.Dropdown(
380
+ ["Commercial", "Consulting"],
381
+ value="Commercial",
382
+ label="Département",
383
+ )
384
+ poste = gr.Textbox(value="Consultant", label="Poste")
385
+ nombre_experiences_precedentes = gr.Slider(
386
+ 0, 10, value=2, step=1, label="Expériences précédentes"
387
+ )
388
+ nombre_heures_travailless = gr.Slider(
389
+ 35, 80, value=40, step=1, label="Heures travaillées/sem"
390
+ )
391
+ annee_experience_totale = gr.Slider(
392
+ 0, 40, value=10, step=1, label="Années d'expérience totale"
393
+ )
394
+ annees_dans_l_entreprise = gr.Slider(
395
+ 0, 30, value=5, step=1, label="Années dans l'entreprise"
396
+ )
397
+ annees_dans_le_poste_actuel = gr.Slider(
398
+ 0, 20, value=2, step=1, label="Années dans le poste"
399
+ )
400
+
401
+ # Bouton et résultat
402
+ predict_btn = gr.Button(
403
+ "🔮 Prédire le risque de départ", variant="primary"
404
+ )
405
+ result = gr.Markdown(label="Résultat")
406
+
407
+ predict_btn.click(
408
+ fn=predict_turnover,
409
+ inputs=[
410
+ nombre_participation_pee,
411
+ nb_formations_suivies,
412
+ nombre_employee_sous_responsabilite,
413
+ distance_domicile_travail,
414
+ niveau_education,
415
+ domaine_etude,
416
+ ayant_enfants,
417
+ frequence_deplacement,
418
+ annees_depuis_la_derniere_promotion,
419
+ annes_sous_responsable_actuel,
420
+ satisfaction_employee_environnement,
421
+ note_evaluation_precedente,
422
+ niveau_hierarchique_poste,
423
+ satisfaction_employee_nature_travail,
424
+ satisfaction_employee_equipe,
425
+ satisfaction_employee_equilibre_pro_perso,
426
+ note_evaluation_actuelle,
427
+ heure_supplementaires,
428
+ augementation_salaire_precedente,
429
+ age,
430
+ genre,
431
+ revenu_mensuel,
432
+ statut_marital,
433
+ departement,
434
+ poste,
435
+ nombre_experiences_precedentes,
436
+ nombre_heures_travailless,
437
+ annee_experience_totale,
438
+ annees_dans_l_entreprise,
439
+ annees_dans_le_poste_actuel,
440
+ ],
441
+ outputs=result,
442
+ )
443
+
444
+ # Onglet Documentation
445
+ with gr.TabItem("📚 Documentation API"):
446
+ gr.Markdown(API_DOCS)
447
+
448
+ # Onglet À propos
449
+ with gr.TabItem("ℹ️ À propos"):
450
+ gr.Markdown(
451
+ """
452
+ ## À propos de ce projet
453
+
454
+ ### 🎓 Contexte
455
+ Ce projet a été réalisé dans le cadre du **Projet 5 OpenClassrooms** :
456
+ "Déployez votre modèle de Machine Learning".
457
+
458
+ ### 🎯 Objectif
459
+ Développer une API de prédiction du turnover (départ) des employés,
460
+ permettant aux équipes RH d'anticiper et de prévenir les départs.
461
+
462
+ ### 🛠️ Technologies utilisées
463
+ - **FastAPI** : Framework API REST performant
464
+ - **XGBoost** : Modèle de Machine Learning
465
+ - **Gradio** : Interface utilisateur
466
+ - **HuggingFace Hub** : Hébergement du modèle
467
+ - **HuggingFace Spaces** : Déploiement de l'application
468
+ - **GitHub Actions** : CI/CD automatisé
469
+
470
+ ### 📊 Le modèle
471
+ Le modèle a été entraîné sur des données RH comprenant :
472
+ - Données de sondage de satisfaction
473
+ - Données d'évaluation de performance
474
+ - Données administratives SIRH
475
+
476
+ ### 🔗 Liens utiles
477
+ - [GitHub Repository](https://github.com/chaton59/OC_P5)
478
+ - [API Documentation (Swagger)](/docs)
479
+ - [HuggingFace Model](https://huggingface.co/ASI-Engineer/employee-turnover-model)
480
+
481
+ ### 👤 Auteur
482
+ Projet OpenClassrooms - Formation Data Scientist
483
+ """
484
+ )
485
+
486
+ return demo
487
+
488
+
489
+ # Pour lancer en standalone
490
+ if __name__ == "__main__":
491
+ demo = create_gradio_interface()
492
+ demo.launch(server_name="0.0.0.0", server_port=7860)