--- title: Futurisys ML API emoji: 🚀 colorFrom: blue colorTo: green sdk: docker pinned: false --- # Futurisys – DĂ©ploiement d’un modĂšle de Machine Learning via API ## Contexte **Futurisys** est une entreprise innovante souhaitant rendre ses modĂšles de machine learning opĂ©rationnels et accessibles via une API performante. Ce projet correspond Ă  un **Proof of Concept (POC)** visant Ă  dĂ©ployer un modĂšle de machine learning en production en appliquant les bonnes pratiques d’ingĂ©nierie logicielle: versionnage, tests, base de donnĂ©es et automatisation. ## Objectifs du projet - DĂ©ployer un modĂšle de machine learning via une API REST - Rendre le modĂšle accessible de maniĂšre fiable et documentĂ©e - Mettre en place une architecture maintenable et Ă©volutive - Appliquer un workflow Git professionnel - PrĂ©parer une base solide pour un dĂ©ploiement en production ## PĂ©rimĂštre fonctionnel Le projet inclut: - Une API dĂ©veloppĂ©e avec **FastAPI** - L’exposition d’un modĂšle de machine learning via des endpoints REST - Une base de donnĂ©es **PostgreSQL** pour stocker les entrĂ©es/sorties du modĂšle - Des tests unitaires et fonctionnels avec **Pytest** - Un pipeline **CI/CD** pour automatiser les tests et le dĂ©ploiement - Une documentation technique centralisĂ©e dans ce README ## Architecture du projet L’architecture du projet repose sur une sĂ©paration claire des responsabilitĂ©s afin de garantir la lisibilitĂ©, la maintenabilitĂ© et l’évolutivitĂ© de l’application. ### `Vue d’ensemble` ┌──────────────────────────────┐ │ Utilisateur │ │ (Client) │ └───────────────┬──────────────┘ │ â–Œ ┌────────────────────────────────────────────┐ │ API FastAPI │ │ (endpoint - POST /predict) │ └┬────────────────────┬─────────────────────┬┘ | │ | â–Œ â–Œ â–Œ ┌────────────────┐ ┌──────────────┐ ┌───────────────────────────┐ │ VĂ©rification & | | ModĂšle ML | | Base PostgreSQL (stockage)| | Validation │ | - Chargement | | - Inputs | | | | - PrĂ©diction | | - PrĂ©dictions | └────────────────┘ └──────────────┘ └───────────────────────────┘ â–Č | | ┌────────────────────────────────────────┐ │ CI/CD – GitHub Actions │ │ - Tests unitaires │ │ - Tests fonctionnels │ │ - Rapport de couverture │ │ - DĂ©ploiement sur HF Space │ └────────────────────────────────────────┘ ### `Description du flux` 1. Un utilisateur envoie une requĂȘte `POST /predict` Ă  l’API 2. L’API FastAPI agit comme point d’entrĂ©e: - validation des donnĂ©es via **Pydantic** - orchestration du traitement 3. Le module de prĂ©diction: - charge dynamiquement le modĂšle ML depuis **Hugging Face Hub** - gĂ©nĂšre la prĂ©diction et la probabilitĂ© associĂ©e 4. Les donnĂ©es d’entrĂ©e et les rĂ©sultats sont enregistrĂ©s dans une base **PostgreSQL** afin d’assurer la traçabilitĂ© 5. La rĂ©ponse est retournĂ©e au client sous forme JSON 6. Le cycle de dĂ©veloppement, de test et de dĂ©ploiement est automatisĂ© via un pipeline **CI/CD GitHub Actions** avec dĂ©ploiement sur **Hugging Face Spaces**. Cette architecture permet une exposition fiable du modĂšle de Machine Learning, tout en respectant les bonnes pratiques MLOps et d’ingĂ©nierie logicielle. ## ModĂšle de Machine Learning (ML) ### `ProblĂ©matique` Le modĂšle vise Ă  rĂ©soudre un problĂšme de classification binaire : - `0`: l’employĂ© reste dans l’entreprise - `1`: l’employĂ© prĂ©sente un risque de dĂ©part L’objectif mĂ©tier est d’anticiper le turnover afin de permettre aux Ă©quipes RH de prioriser des actions de rĂ©tention. ### `DonnĂ©es et features` Le modĂšle s’appuie sur un dataset RH prĂ©parĂ© et nettoyĂ© en amont contenant des: - donnĂ©es professionnelles et contextuelles (poste, dĂ©partement, anciennetĂ©, etc.) - variables comportementales et organisationnelles Dataset final composĂ© de **32 features**: ```text RangeIndex: 1470 entries, 0 to 1469 Data columns (total 32 columns) ``` Les prĂ©traitements incluent : - le nettoyage et la normalisation des donnĂ©es brutes (3 bases distinctes brutes reçues) - le feature engineering: enrichissement des donnĂ©es - le choix des variables non redondantes (corrĂ©lation infĂ©rieure Ă  70% entre les features numĂ©riques & les plus correlĂ©es avec la cible) - normalisation des variables numĂ©riques & encodage des variables catĂ©gorielles: ```python transfo_colonnes = ColumnTransformer( transformers=[ ('num', StandardScaler(), colonnes_quantitatives), ('cat', OneHotEncoder(handle_unknown='ignore', max_categories=15, sparse_output=False), colonnes_qualitatives), ('ord', OrdinalEncoder(handle_unknown="use_encoded_value", unknown_value=-1), colonnes_ordinales)]) ``` La table `employees_dataset` sert de rĂ©fĂ©rence documentaire du schĂ©ma attendu par le modĂšle. ### `Choix du modĂšle` Le modĂšle retenu est un algorithme de gradient boosting (**XGBoost**) entraĂźnĂ© avec des hyperparamĂštres optimisĂ©s: ```python # Les hyperparamĂštrs trouvĂ©s Meilleurs paramĂštres : {'classifier__colsample_bytree': 0.8, 'classifier__gamma': 1, 'classifier__learning_rate': 0.3, 'classifier__max_depth': 3, 'classifier__min_child_weight': 5, 'classifier__n_estimators': 400, 'classifier__reg_lambda': 1, 'classifier__subsample': 0.8} ``` Ce choix est justifiĂ© par: - de bonnes performances sur des donnĂ©es tabulaires - un compromis efficace entre prĂ©cision et capacitĂ© de gĂ©nĂ©ralisation - un temps d’infĂ©rence compatible avec une exposition via API ![Comparaison des modĂšles](https://raw.githubusercontent.com/Diaure/Futurisys_ML_API/develop/Other/comp_modeles.PNG) ### `SĂ©rialisation et versionnage` - Le modĂšle est sĂ©rialisĂ© au format `joblib` - Une version du modĂšle est associĂ©e Ă  chaque prĂ©diction dans la table correspondante(`v1`) - Les artefacts ML: - en **environnement local**, ils peuvent ĂȘtre prĂ©sents pour les tests - en **production**, ils sont systĂ©matiquement tĂ©lĂ©chargĂ©s depuis un espace Hugging Face Hub dĂ©diĂ© au stockage des artefacts. ### `Performance et Ă©valuation du modĂšle` - SĂ©paration du dataset en ensembles train / test - Validation basĂ©e sur des mĂ©triques adaptĂ©es au contexte mĂ©tier: - **Recall (0.70)**: limiter les faux nĂ©gatifs (dĂ©parts non dĂ©tectĂ©s) - **F1-score (0.52 - validation croisĂ©e)**: Ă©quilibre entre prĂ©cision et rappel - **ROC-AUC (0.80 - validation croisĂ©e)**: capacitĂ© de discrimination globale du modĂšle Le recall est volontairement privilĂ©giĂ© afin de maximiser la dĂ©tection des employĂ©s Ă  risque, mĂȘme au prix de quelques faux positifs. ### `Limites` - Le modĂšle fournit une probabilitĂ©, ***pas une dĂ©cision finale*** - Les prĂ©dictions doivent ĂȘtre interprĂ©tĂ©es comme une aide Ă  la dĂ©cision - Les performances dĂ©pendent fortement de la qualitĂ© et de l’actualitĂ© des donnĂ©es RH - Des biais peuvent exister si les donnĂ©es historiques sont dĂ©sĂ©quilibrĂ©es. ## CI/CD et DĂ©ploiement Ce projet met en Ɠuvre une approche CI/CD complĂšte, sĂ©parant: - l’intĂ©gration continue (**CI**): garantir la qualitĂ© du code - le dĂ©ploiement continu (**CD**): rendre l’API accessible publiquement ### `IntĂ©gration Continue (CI) – GitHub Actions` À chaque **push** ou **pull request** sur les branches de travail et vers **`develop`**, le pipeline CI exĂ©cute automatiquement: - l'installation d’un environnement Python 3.11 - l'installation des dĂ©pendances dĂ©finies dans le projet - l'exĂ©cution des tests unitaires et fonctionnels L’objectif est de garantir la stabilitĂ© de l’API et d’éviter toute rĂ©gression. ### `DĂ©ploiement Continu (CD) – Hugging Face Spaces` Dans ce projet, Hugging Face est utilisĂ© comme plateforme de dĂ©monstration et de mise Ă  disposition de l’API. Le dĂ©ploiement repose sur un `Dockerfile`, qui dĂ©finit: - l’image Python utilisĂ©e (Python 3.11) - l’installation des dĂ©pendances - le lancement de l’API avec Uvicorn. A noter que les ***fichiers binaires*** ne sont pas stockĂ©s dans le dĂ©pĂŽt GiHub principal pour les raisons suivantes: - Hugging Face bloque les push Git contenant des fichiers binaires lourds - Git n’est pas conçu pour versionner des artefacts ML volumineux. Pour contourner la situation, dans le projet, les artefacts sont stockĂ©s dans un Space Hugging Face dĂ©diĂ©, sĂ©parĂ© du code. Lors du dĂ©marrage de lAPI: - le code tĂ©lĂ©charge dynamiquement les artefacts via huggingface_hub - l’API peut dĂ©marrer mĂȘme si les fichiers ne sont pas prĂ©sents localement. ### `Installation et configuration` Les prĂ©requis: - Python 3.11 - Poetry - PostgreSQL (optionnel en local) ```git bash git clone cd futurisys_ml-api poetry install ``` Les variables suivantes doivent ĂȘtre dĂ©finies pour la connexion Ă  la base SQL: - `DB_USER` - `DB_PASSWORD` - `DB_HOST` - `DB_PORT` - `DB_NAME` Elles sont chargĂ©es via un fichier `.env` non versionnĂ©. ### `Lancer l’API` - **En local**: ```python uvicorn App.main:app --reload ``` Documentation interactive (Swagger UI) - http://127.0.0.1:8000/docs - **En production (Hugging Face Spaces**): - API: https://diaure-futurisys-api-ml.hf.space - Swagger UI: https://diaure-futurisys-api-ml.hf.space/docs Le dĂ©ploiement permet de: - visualiser les endpoints - tester directement l’endpoint `/predict` - voir les schĂ©mas d’entrĂ©e et de sortie. ### `Endpoint principal` `POST /predict` Cet endpoint reçoit les caractĂ©ristiques d’un employĂ© et retourne: - une prĂ©diction lisible (`"Reste"` ou `"Part"`) - la probabilitĂ© associĂ©e au dĂ©part ```json { "Prediction": "Part", "Probabilite_depart": 0.795678996 } ``` Les donnĂ©es d’entrĂ©e sont validĂ©es via **Pydantic** avec l’appel du modĂšle. ### `Maintenance et mise Ă  jour du modĂšle` Une mise Ă  jour du modĂšle est recommandĂ©e: - pĂ©riodiquement (ex. tous les 6 Ă  12 mois) - ou en cas de dĂ©rive des donnĂ©es. Le processus inclut: - la collecte de nouvelles donnĂ©es - le rĂ©entraĂźnement du modĂšle - l'Ă©valuation des performances - la validation mĂ©tier - le dĂ©ploiement d’une nouvelle version. ## Base de donnĂ©es et traçabilitĂ© des prĂ©dictions ### `Objectifs` L’intĂ©gration d’une base de donnĂ©es PostgreSQL permet d’inscrire le projet dans une logique MLOps et de rĂ©pondre Ă  plusieurs objectifs clĂ©s: - assurer la traçabilitĂ© complĂšte des prĂ©dictions du modĂšle - conserver l’historique des donnĂ©es d’entrĂ©e utilisateur - stocker les rĂ©sultats de prĂ©diction (label, probabilitĂ©, version du modĂšle) - prĂ©parer une architecture compatible avec un dĂ©ploiement en production. ### `MĂ©thodologie utilisĂ©e` - **PostgreSQL** a Ă©tĂ© retenu pour: - sa robustesse et sa fiabilitĂ© - sa compatibilitĂ© native avec SQLAlchemy - son usage courant en environnement professionnel - **SQLAlchemy** est utilisĂ© comme couche d’abstraction: - gestion centralisĂ©e de la connexion Ă  la base - cohĂ©rence entre le schĂ©ma Python et la base SQL Les identifiants de connexion sont stockĂ©s dans des variables d’environnement (`.env`) afin d’éviter toute exposition de secrets dans le dĂ©pĂŽt Git. ### `ModĂ©lisation de la base de donnĂ©es` La base de donnĂ©es repose sur trois tables distinctes, chacune ayant un rĂŽle prĂ©cis. 1. `employees_dataset - Dataset de rĂ©fĂ©rence` Il contient le dataset final nettoyĂ© et prĂ©parĂ© lors de l'entraĂźnement du modĂšle en incluant l'ensemble des **32 features** du modĂšle. Il sert de: - rĂ©fĂ©rence de schĂ©ma - source de validation - base documentaire du modĂšle C'est une table qui n'est jamais alimentĂ©e par l'utilisateur. 2. `inputs - EntrĂ©es utilisateur` - Enregistre chaque requĂȘte utilisateur envoyĂ©e Ă  l'endpoint `/predict` - Contient exactement les features attendues par le modĂšle - Structure strictement alignĂ©e avec le schĂ©ma Pydantic(`EmployeeFeatures`) - Permet: - l'audit des predictions - l'analyse Ă  posteriori - la reproductibilitĂ© des rĂ©sultats. ```python class Input(Base): __tablename__ = "inputs" id = Column(Integer, primary_key=True, index=True) genre = Column(String) statut_marital = Column(String) departement = Column(String) poste = Column(String) ``` 3. `predictions - RĂ©sultats du modĂšle` - Continet: - le label de prĂ©diction - la probabilitĂ© associĂ©e - ReliĂ©e Ă  `inputs` via une clĂ© Ă©trangĂšre - Garantit une trçabilitĂ© complĂšte. ```python class Predictions(Base): __tablename__ = "predictions" id = Column(Integer, primary_key=True, index=True) input_id = Column(Integer, ForeignKey("inputs.id")) prediction_label = Column(String) prediction_proba = Column(Float) model_version = Column(String) ``` SQLAlchemy crĂ©e les tables au lancement de l’API grĂące au script: ```python Base.metadata.create_all(bind=engine) ``` ### `Interaction API <> Base de donnĂ©es` Lors d’un appel Ă  l’endpoint `POST /predict`: - les donnĂ©es utilisateur sont validĂ©es via **Pydantic** - les entrĂ©es sont enregistrĂ©es dans la table **inputs** - le modĂšle est exĂ©cutĂ© - la prĂ©diction est enregistrĂ©e dans la table **predictions** - la rĂ©ponse est retournĂ©e Ă  l’utilisateur. ## Tests et QualitĂ© ### `Objectifs des tests` Les tests ont Ă©tĂ© conçus pour: - valider le bon fonctionnement des composants critiques (chargement du modĂšle, validation des donnĂ©es, etc) - garantir que l’API rĂ©pond correctement dans des scĂ©narios rĂ©els - dĂ©tecter rapidement les rĂ©gressions lors du dĂ©veloppement - assurer la reproductibilitĂ© des rĂ©sultats - fournir des indicateurs de qualitĂ© (couverture de tests) L’ensemble des tests est exĂ©cutĂ© automatiquement dans le pipeline CI Ă  chaque push ou pull request. ### `Types de tests exĂ©cutĂ©s` - **Tests unitaires** qui sont des tests rapides qui permettent de dĂ©tecter immĂ©diatement les erreurs de logique. Ils se concentrent sur les composants isolĂ©s du projet comme: - la vĂ©rification du chargement du modĂšle et du mapping des classes sans levĂ©e d'erreurs (`model_loading.py`) - la validation des donnĂ©es via Pydantic et test de l'endpoint de bout en bout(`test_api.py`) - **Tests fonctionnels** qui Ă©valuent l’application dans son ensemble en simulant un usage rĂ©el de l’API et garantissant son bon comportement en production: - contrĂŽle du fonctionnement de l'API en mode CI lorsque la base est dĂ©sactivĂ©e CI (`test_db_disabled.py`) - test tout le pipeline de prĂ©diction (`test_predict_endpoint.py`) - test spĂ©cifique de l'endpoint `/predict` et vĂ©rification de la cohĂ©rence de la rĂ©ponse. **ExĂ©cution locale** des tests: ```python poetry run pytest poetry run pytest tests.units poetry run pytest tests.fonctionnel ``` ### `Rapport de couverture` GĂ©nĂ©rĂ© automatiquement dans GitHub Actions, c'est un apport qui mesure la proportion de code Ă©xĂ©cutĂ©e par les tests en indiquant: - quelles lignes ont Ă©tĂ© exĂ©cutĂ©es - quelles lignes ne l'ont pas Ă©tĂ© - le pourcentage global de couverture. Il a pour rĂŽle: - d'Ă©valuer la qualitĂ© de la suite de tests - d'identifier les zones non testĂ©es - de rĂ©duire les risques de rĂ©gression - de garantir la fiabilitĂ© du code avant dĂ©ploiement. ![Rapport de couverture](https://raw.githubusercontent.com/Diaure/Futurisys_ML_API/develop/Other/Rapport_couverture.PNG) ## Stack technique - **Langage**: Python - **API**: FastAPI - **Machine Learning**: scikit-learn - **Base de donnĂ©es**: PostgreSQL - **Tests**: Pytest, pytest-cov - **CI/CD**: GitHub Actions, Hugging Face - **Versionnage**: Git / GitHub ## Structure du projet ```text futurisys_ml-api/ ├── github/workflows │ ├── ci.yml # Description des Ă©vĂšnement dĂ©clenchants des tests ├── app/ # Code applicatif principal │ ├── database.py # Point de connexion Ă  la base PostgreSQL │ ├── main.py # Point d’entrĂ©e de l’API │ ├── model.py # DĂ©finition des tables de la database │ ├── predict.py # Application du modĂšle │ ├── schemas.py # Validation des donnĂ©es (Pydantic) │ ── model/ # Elements du modĂšle │ ├── mapping_classes.json # Correspondances des classes │ ├── modele_final_xgb.joblib # ModĂšle final avec hyperparamĂštres | ├── scripts/ # Scripts bd (BD, donnĂ©es) │ ├── create_tables.py # CrĂ©aton des tables dĂ©finies dans model.py │ ├── dataset_final.csv # Data final │ ├── insert_dataset.py # Code chargement de la table dataset_final | ├── tests/ # Tests unitaires, fonctionnels │ ├── test_sanity.py # Test de vĂ©rification rapide │ ├── test_api.py # Tests API supplĂ©mentaires │ ├── test_sanity.py # Test de vĂ©rification rapide | │ ── fonctionnel/ # Tests fonctionnels │ ├── sample_payload.py # Test automatisĂ© de l'API via Pytest │ ├── test_api.py # Tests API supplĂ©mentaires │ ├── test_sanity.py # Test de vĂ©rification rapide | │ ── units/ # Tests unitaires │ ├── test_model_loading.py # Test automatisĂ© de l'API via Pytest | ├── .env # Stockage des variables sensibles et de configuration ├── .gitignore # Nettoyage du dĂ©pĂŽt ├── Dockerfile # Reproduction du dĂ©pĂŽt ├── poetry.lock # Nettoyage du dĂ©pĂŽt ├── pyproject.toml # Librairies dĂ©pendances ML ├── README.md # PrĂ©sentation du projet └── requirements.txt # Librairies dĂ©pendances API ```