diff --git a/README.fr.md b/README.fr.md
new file mode 100644
index 0000000..86ea4c9
--- /dev/null
+++ b/README.fr.md
@@ -0,0 +1,62 @@
+# Projet Air Paradis – Analyse de sentiments
+
+📘 Ce projet est également disponible en [anglais 🇬🇧](./README.md)
+
+Ce dépôt contient les notebooks et le code source du projet d’analyse de sentiments sur des tweets, réalisé dans le cadre du programme OpenClassrooms **"Air Paradis"**.
+
+---
+
+## Contexte métier
+
+L’objectif est de prédire si un tweet (ou une courte expression écrite) est perçu comme **positif ou négatif**, dans le contexte d’une compagnie aérienne.
+Le projet repose sur le jeu de données public **Sentiment140**.
+
+---
+
+## Description du projet
+
+Le projet vise à développer un système complet d’analyse de sentiments, comprenant :
+
+- Une analyse exploratoire des données textuelles,
+- Une comparaison de plusieurs modèles de classification (classiques, avancés et à l’état de l’art),
+- Le déploiement d’une API REST exposant un modèle avancé (embeddings + LSTM),
+- La mise en place d’un pipeline CI/CD pour automatiser les tests et le déploiement,
+- Un hébergement local sur un serveur NAS pour garantir la souveraineté des données.
+
+---
+
+## Structure du dépôt
+
+- `notebooks/` : notebooks d’analyse et de modélisation,
+- `deployment/` : code de l’API, tests, Dockerfile et fichiers liés au déploiement,
+- `docs/` : documentation et ressources associées,
+- `../.github/workflows/` : pipelines CI/CD.
+
+---
+
+## Entraînement des modèles
+
+Les phases d’entraînement ont principalement été réalisées sur **Google Colab**, afin de bénéficier de ressources GPU nécessaires aux modèles de deep learning.
+
+---
+
+## Utilisation
+
+Les notebooks détaillent les étapes d’analyse et d’entraînement.
+L’API est disponible dans le dossier `deployment/api`.
+
+---
+
+## Remarques
+
+- Les fichiers `requirements.txt` dans `notebooks/` proviennent des environnements Google Colab et peuvent contenir des dépendances peu optimisées pour un usage local.
+- Le fichier `.env`, exclu du dépôt, contient les variables d’environnement nécessaires.
+
+---
+
+Ce README sera mis à jour progressivement au fur et à mesure de l’avancement du projet.
+Certains commentaires de code peuvent rester en français (ainsi que les cellules Markdown des notebooks). Tout sera traduit en anglais ultérieurement.
+
+---
+
+**Projet réalisé dans le cadre du parcours "Data Scientist – Projet 7" d’OpenClassrooms**
\ No newline at end of file
diff --git a/README.md b/README.md
index ada6dff..1accfaa 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,6 @@
-# Air Paradis Project - Sentiment Analysis
+# Air Paradis Project – Sentiment Analysis
+
+📘 This project is also available in [French 🇫🇷](./README.fr.md)
This repository contains the notebooks and source code for the sentiment analysis project on tweets, carried out as part of the OpenClassrooms "Air Paradis" program.
@@ -6,7 +8,8 @@ This repository contains the notebooks and source code for the sentiment analysi
## Business Context
-The goal is to predict whether a tweet, or a short written expression, is perceived as positive or negative, in the context of an airline company. The project is based on the public **Sentiment140** dataset.
+The goal is to predict whether a tweet, or a short written expression, is perceived as **positive or negative**, in the context of an airline company.
+The project is based on the public **Sentiment140** dataset.
---
@@ -50,9 +53,9 @@ The notebooks detail the analysis and training steps. The API is available in `d
---
-This README will be updated progressively as the project advances.
-Some code comments can remain in french language (as well as the notebooks markdowns etc.). All will be changed into english in the future.
+This README will be updated progressively as the project advances.
+Some code comments can remain in French (as well as notebook markdowns). All will be translated into English later.
---
-**Project completed as part of the OpenClassrooms "Data Scientist - Project 7" program**
+**Project completed as part of the OpenClassrooms "Data Scientist – Project 7" program**
diff --git a/deployment/README.fr.md b/deployment/README.fr.md
new file mode 100644
index 0000000..c4b67d2
--- /dev/null
+++ b/deployment/README.fr.md
@@ -0,0 +1,128 @@
+# Déploiement de l’API – Projet Air Paradis
+
+📘 Cette documentation est aussi disponible en [anglais 🇬🇧](./README.md)
+
+Ce dossier contient le code et la configuration nécessaires au déploiement de l’API de prédiction de sentiment.
+
+---
+
+## 🎯 Objectif
+
+Déployer une API REST permettant de :
+
+- Prédire le **sentiment d’un tweet** (positif ou négatif) à partir d’un modèle LSTM entraîné sur des embeddings (Word2Vec ou GloVe),
+- Signaler les erreurs de prédiction.
+
+L’API utilise le **meilleur modèle enregistré** dans MLflow et le sert via **FastAPI**.
+
+---
+
+## 📦 Architecture globale
+
+Schéma :
+
+```
+ ┌──────────────────────────────┐
+ │ Utilisateur final (UI) │
+ │ (interface Streamlit) │
+ └────────────┬─────────────────┘
+ │
+ [Appel HTTP vers /predict]
+ │
+ ┌────────────▼─────────────┐
+ │ API FastAPI │
+ │ (serveur lancé via │
+ │ Uvicorn) │
+ └────────────┬─────────────┘
+ │
+ Chargement du modèle (MLflow)
+ │
+ Prétraitement du tweet
+ │
+ Prédiction (inférence)
+ │
+ Réponse JSON avec le sentiment
+```
+
+---
+
+## 🧪 Fonctionnement de l’API
+
+1. **Chargement du modèle**
+ - Le meilleur modèle est enregistré dans MLflow sous le nom `SentimentAnalysisLSTM`, avec le stage `Production`.
+ - L’API le charge au démarrage via l’URI :
+
+ ```
+ models:/SentimentAnalysisLSTM/Production
+ ```
+
+2. **Prétraitement du texte**
+ - Nettoyage, tokenisation, lemmatisation, puis conversion en vecteurs d’embedding.
+
+3. **Prédiction**
+ - Le modèle LSTM prédit le sentiment.
+ - Le résultat (`positive` ou `negative`) est retourné en JSON.
+
+4. **Interface utilisateur (optionnelle)**
+ - Une interface Streamlit permet une interaction visuelle avec l’API.
+
+---
+
+## 🐳 Déploiement via Docker
+
+Un `Dockerfile` est fourni pour simplifier le déploiement sur tout hôte compatible Docker (NAS, cloud, etc.).
+
+L’image Docker est poussée sur DockerHub à chaque version validée (voir CI/CD plus bas).
+
+Par souci de **souveraineté des données**, le déploiement est préféré sur un **NAS équipé d’un processeur Intel N100** (peu énergivore et suffisant pour l’inférence LSTM).
+
+Le redéploiement peut être automatisé via :
+- une tâche `cron` simple, ou
+- un conteneur **Watchtower** (dans docker-compose ou kubernetes).
+
+**Commande pour test local :**
+
+```bash
+docker build -t sentiment-api .
+docker run --rm --env-file ../../.env -p 8000:8000 -p 8080:8080 sentiment-api
+```
+
+En production, les variables d’environnement doivent être définies dans le `docker-compose.yml` ou via un gestionnaire de secrets.
+
+---
+
+## 🛠 Problèmes AVX2 / Déploiement cloud
+
+**Mise à jour :** au départ, le NAS ne supportait pas les instructions AVX2 nécessaires à TensorFlow.
+En réalité, les CPU N100 les prennent en charge, mais certains fabricants désactivent cette option dans le BIOS.
+
+En attendant un accès physique au NAS, nous avons opté pour un déploiement sur **Google Cloud**.
+Problème : un seul port peut être exposé publiquement sur ces services.
+
+Deux solutions possibles :
+- Séparer le backend (FastAPI) et le frontend (Streamlit) en deux conteneurs,
+- Utiliser un **reverse proxy** (ex. : nginx) pour rediriger les ports.
+
+➡️ Nous avons choisi la **deuxième solution**, pour garder une **seule image Docker**.
+
+**Mise à jour 2 :** AVX2 a été activé via le BIOS. Le déploiement est donc opérationnel **à la fois en local (NAS)** et **sur le cloud**, avec déploiement automatique pour le NAS (voir section suivante).
+
+---
+
+## 🔁 CI/CD – GitHub Actions
+
+Un pipeline est défini dans `.github/workflows/` pour :
+
+- Lancer les tests unitaires à chaque `push`,
+- Vérifier la stabilité de l’API avant déploiement (NAS ou cloud),
+- Construire et pousser l’image Docker sur DockerHub.
+
+Les tests sont situés dans :
+
+```
+deployment/api/tests/
+```
+
+Le redéploiement automatique sur le NAS est géré via **Watchtower**, qui surveille les mises à jour de l’image Docker (fonctionne comme un `cron`, avec logs).
+
+---
diff --git a/deployment/README.md b/deployment/README.md
index 202b079..bde374f 100644
--- a/deployment/README.md
+++ b/deployment/README.md
@@ -1,14 +1,19 @@
-# API Deployment - Air Paradis Project
+# API Deployment – Air Paradis Project
+
+📘 This documentation is also available in [French 🇫🇷](./README.fr.md)
This folder contains the code and configuration necessary to deploy the sentiment prediction API.
+---
+
## 🎯 Objective
Deploy a REST API that allows to:
-- predict the sentiment of a tweet (positive or negative) based on an LSTM model trained on embeddings (Word2Vec or GloVe).
-- report prediction errors
-The API uses the best-performing model, registered on MLflow, and serves it via FastAPI.
+- Predict the sentiment of a tweet (positive or negative) using an LSTM model trained on embeddings (Word2Vec or GloVe),
+- Report prediction errors.
+
+The API uses the best-performing model registered on MLflow and serves it via FastAPI.
---
@@ -16,6 +21,7 @@ The API uses the best-performing model, registered on MLflow, and serves it via
Diagram:
+```
┌──────────────────────────────┐
│ End user (UI) │
│ (Streamlit interface) │
@@ -36,72 +42,85 @@ Diagram:
Prediction (inference)
│
Sentiment response (JSON)
+```
---
## 🧪 API Workflow
-1. Model loading
- - The best performing model is registered in MLflow under a fixed name (`SentimentAnalysisLSTM`) and a stage `Production`.
- - The API loads this model at startup using a stable URI:
+1. **Model loading**
+ - The best performing model is registered in MLflow under a fixed name (`SentimentAnalysisLSTM`) and a `Production` stage.
+ - The API loads this model at startup using the URI:
+ ```
models:/SentimentAnalysisLSTM/Production
+ ```
-2. Text preprocessing
- - The text sent by the user is cleaned, tokenized, lemmatized, and transformed into vectors (embeddings).
+2. **Text preprocessing**
+ - Text is cleaned, tokenized, lemmatized, and converted into vectors (embeddings).
-3. Prediction
- - The LSTM model (loaded from MLflow) performs inference.
- - The result (`positive` or `negative`) is returned as a JSON response.
+3. **Prediction**
+ - The LSTM model (loaded from MLflow) makes a prediction.
+ - The result (`positive` or `negative`) is returned as JSON.
-4. User interface (optional)
+4. **User interface (optional)**
- A Streamlit interface allows visual interaction with the API.
---
## 🐳 Deployment with Docker
-A Dockerfile is provided to facilitate deploying the API on any Docker-compatible host (NAS, cloud, etc.).
+A `Dockerfile` is provided for easy deployment on any Docker-compatible host (NAS, cloud, etc.).
-This Docker image should be pushed to DockerHub at each validated versioning (see the CI/CD section below).
+This Docker image should be pushed to DockerHub with every validated version (see CI/CD below).
-For data sovereignty reasons, deployment will preferably be done on a NAS equipped with an Intel N100 processor (energy efficient but probably sufficient for LSTM inference).
-Docker can be redeployed each time the docker image on DockerHub is updated. Man can use `cron` instruction (simple) or `Watchtower` docker (docker-compose / kubernetes context).
+For data sovereignty, deployment is preferably done on a **NAS with Intel N100** CPU (energy-efficient, sufficient for inference).
+Docker can be automatically redeployed using:
+- `cron` (simple), or
+- `Watchtower` in docker-compose/kubernetes setups.
-For running the Docker image locally (development), it is important to provide the `.env` file containing environment variables and to open the FastAPI and Streamlit ports for testing the application.
+**Development command (local test):**
-Example commands to build and run:
+```bash
+docker build -t sentiment-api .
+docker run --rm --env-file ../../.env -p 8000:8000 -p 8080:8080 sentiment-api
+```
- docker build -t sentiment-api .
- docker run --env-file ../../.env -p 8000:8000 -p 8080:8080 sentiment-api
-
-For deployment on a personal or public cloud (with docker-compose, Kubernetes), it is preferable to specify the necessary environment variables in `docker-compose.yml` or in secrets.
-
-Add the `--rm` argument so that the container is removed after stopping.
-
-**UPDATE** : in our case, we encountered some issues with the NAS which CPU is not able to run AVX2 instructions so we are obliged to deploy it on a "standard" public cloud service. To be precise, N100 CPU is normally able to run AXV2 instructions but some NAS/home server motherboard manufacturers sometimes disable this feature. Maybe is it possible to renable it on the BIOS, but I am away from my NAS so it will have to wait.
-
-So, we decided to use Google Cloud. A common issue arises here: we cannot expose multiple ports (contrary to the instruction above) on a cloud service.
-
-Two options are possible:
-
-- Separate the service into two dockers (one for FastAPI backend and one for Streamlit frontend)
-- Configure a reverse proxy like nginx to redirect requests to different internal ports
-
-We decided to keep the second solution to install the API from a single Docker container.
-
-**UPDATE 2** : AVX2 instructions have been enabled by accessing the home server motherboard BIOS. So the deployment is also done here and complete continuous deployment will be done as well.
+In production (e.g. via docker-compose or cloud services), environment variables must be defined in the compose file or secret manager.
---
-## 🔁 Continuous Integration / Continuous Deployment
+## 🛠 Notes on AVX2 / Cloud Deployment
-A GitHub Actions pipeline (CI/CD) is planned at the very root of the repo to:
+**Update:** the NAS initially failed due to lack of AVX2 support. Some N100-based NAS motherboards disable AVX2 in BIOS.
-- Automatically run unit tests at every push on the GitHub repository.
-- Ensure API stability before any deployment (NAS or cloud).
-- Update the Dockerfile and push it to DockerHub.
+When not accessible, fallback deployment is done on **Google Cloud**.
+Issue: public cloud services do **not allow multiple ports** to be exposed easily.
-Unit tests will be defined in `./deployment/api/tests/`
+Two solutions:
+- Split into two containers: FastAPI + Streamlit,
+- Use a **reverse proxy** (e.g., Nginx) to map ports.
-- API docker is automatically updated on home server docker using watchtower docker (= cron with logging options)
+➡️ We chose the second option to keep a **single Docker image**.
+
+**Update 2:** AVX2 was enabled via BIOS. Deployment is now active **both locally (NAS)** and **on cloud**, with continuous deployment on NAS (see section below).
+
+---
+
+## 🔁 CI/CD – GitHub Actions
+
+A pipeline is defined in `.github/workflows/` to:
+
+- Run unit tests on every push,
+- Check API health before deployment (local/cloud),
+- Build and push Docker image to DockerHub.
+
+Tests are defined in:
+
+```
+deployment/api/tests/
+```
+
+Docker image auto-redeployment on NAS is handled by **Watchtower**, which checks DockerHub updates (like a cron job, with logs).
+
+---
diff --git a/docs/blog.fr.md b/docs/blog.fr.md
new file mode 100644
index 0000000..e8fed94
--- /dev/null
+++ b/docs/blog.fr.md
@@ -0,0 +1,235 @@
+# ✨ Analyse de sentiments et déploiement MLOps : retour d’expérience complet
+
+Dans le cadre du projet *Air Paradis*, nous avons mis en œuvre une chaîne complète d’analyse de sentiments à partir de tweets, depuis la modélisation jusqu’au déploiement MLOps. Ce billet de blog revient sur les étapes clés du projet : choix méthodologiques, comparaison des modèles, mise en production d’une API robuste, et déploiement sur deux environnements (local + cloud). 🧠🔧
+
+---
+
+## 🔍 Trois approches de modélisation supervisée
+
+Nous avons testé trois approches complémentaires pour prédire le sentiment d’un tweet. Chacune repose sur une représentation textuelle différente et un algorithme d’apprentissage adapté :
+
+### 1. 🧱 Approche simple : Bag-of-Words (BoW) + modèles de machine learning
+
+On vectorise les tweets via BoW ou BoW + TF-IDF, qui comptent la fréquence des mots.
+Contrairement à d'autres projets NLP, nous avons évité LDA (non supervisé, orienté topic modeling).
+
+➡️ **Modèles testés** :
+- Régression Logistique
+- Naive Bayes
+- SVM
+- Random Forest
+
+Ces modèles sont entraînés avec **GridSearchCV**, en optimisant la **précision (`precision`)**, notre KPI métier. Différents KPI ont été calculés sur l'ensemble de test.
+
+
+
+---
+
+### 2. 🔥 Approche avancée : Word Embeddings + LSTM
+
+Nous utilisons des vecteurs denses Word2Vec (entraînés) et GloVe 300d (préentraînés par Stanford), qui capturent les similarités sémantiques entre mots. Ces représentations ne prennent toutefois **pas en compte le contexte** exact (ex : "annulé" est probablement un mot très négatif pour un vol mais positif pour un procès contenant des charges contre vous).
+
+La classification est réalisée par un **LSTM**, capable d'exploiter la séquentialité des mots.
+Le **modèle déployé est automatiquement sélectionné** entre Word2Vec + LSTM et GloVe + LSTM, selon la **précision maximale enregistrée dans MLFlow**.
+
+Modèle `Word2Vec + LSTM` (`test_precision : 0.797 , val_precision : 0.795`):
+
+Modèle `GloVe 300d + LSTM` (`test_precision : 0.792 , val_precision : 0.798`):
+
+
+Bien que GloVe 300d + LSTM présente un score de précision légèrement supérieur à Word2Vec + LSTM sur l'ensemble de validation, il reste inférieur pour l'ensemble de test (relativement négligeable dans l'absolu).
+
+---
+
+### 3. 🤖 Approche transformer : DistilBERT, embeddings contextuels allégés
+
+Nous avons utilisé **DistilBERT**, une version plus légère et plus rapide de BERT (créée par Hugging Face).
+Il conserve **95 % de la performance de BERT** tout en étant **40 % plus petit** et **60 % plus rapide**, ce qui le rend particulièrement adapté à un **entraînement sur GPU limité** (Google Colab) et à une **inférence plus rapide**.
+
+Comme BERT, DistilBERT produit des **embeddings contextuels**, c’est-à-dire que le sens des mots varie selon leur contexte. Par exemple, *"banque"* dans *"je vais à la banque"* et *"banque de données"* n’aura pas le même vecteur.
+
+Il a été **fine-tuné** ici pour une classification binaire (positif/négatif), avec un tokenizer et un encodage spécifiques à son architecture.
+
+> **Modèle `DistilBERT`** (`test_precision : 0.861 , val_precision : 0.858`)
+
+
+
+
+
+⚠️ **Limites** : comme tous les modèles préentraînés, DistilBERT **n’est pas sensible à l’ironie, aux jeux de mots, ni aux références culturelles implicites**.
+Or, Twitter est un terrain de jeu idéal pour ce genre de contenus détournés. Ces limites s’appliquent aussi à Word2Vec, GloVe et aux modèles classiques.
+
+---
+
+## 🎯 Pourquoi optimiser la précision (et non l'accuracy) ?
+
+**Accuracy** = proportion de bonnes prédictions globales.
+**Precision** = proportion de tweets *prévus positifs* qui sont *vraiment positifs*.
+
+> Exemple : sur 100 tweets, si le modèle prédit 30 positifs, mais 15 sont des erreurs, la précision est de 50 %.
+
+Nous avons préféré **minimiser les faux positifs**, car dans un contexte sensible, **annoncer un tweet positif alors qu’il est négatif peut être problématique**.
+
+- Modèles classiques : **GridSearchCV optimisé sur la précision**
+- Modèles DL : **EarlyStopping sur val_loss**, mais **sélection finale sur la précision**
+
+---
+
+## ⚙️ Environnement MLOps souverain
+
+### 🖥️ Serveur personnel NAS + OpenMediaVault
+
+MLFlow est installé sur un **NAS personnel (Intel N100)**, sous **OpenMediaVault (Debian)**.
+Nous utilisons **MinIO** pour stocker artefacts et modèles, garantissant une gestion locale, souveraine et compatible S3.
+
+> Les notebooks, exécutés sur Google Colab pour bénéficier de GPU, loggent dans MLFlow et envoient les modèles vers MinIO via des **variables d’environnement**.
+
+Dashboard Expériences MLFlow :
+
+
+Modèles en production (registre de modèles):
+
+
+Meilleur modèle non BERT retenu :
+
+
+---
+
+## 🧪 CI, tests et versioning
+
+### ✅ Tests unitaires
+
+- Vérifient le bon fonctionnement du prétraitement, des prédictions et de la gestion d’erreurs.
+- Intégrés à **GitHub Actions**, **ils bloquent le déploiement si les tests échouent.**
+
+### 🐳 Conteneurisation & CI/CD
+
+L’API FastAPI est packagée via Docker, puis poussée sur DockerHub.
+Un [pipeline CI/CD](https://github.com/GrgMdmn/OpenClassrooms_AI_Projects/blob/main/.github/workflows/p7_ci-cd.yml) complet garantit **un déploiement reproductible**. Il assure:
+- La validation de tests unitaires
+- La construction et le push de l'api conteneurisée sur dockerhub
+
+
+---
+
+## 🚀 Déploiement de l’API FastAPI (double)
+
+### 🔧 Backend : FastAPI
+
+- Expose un endpoint `/predict`
+- Charge dynamiquement le **meilleur modèle Word Embedding + LSTM** via le *Model Registry* MLFlow
+- Applique les bons embeddings selon le tag `embedding_type`
+
+### 💻 Interface Streamlit
+
+Interface locale pour tester les requêtes, debug, démonstrations.
+
+
+
+---
+
+### 🌐 Double déploiement (NAS + Google Cloud)
+
+#### 🔧 Problème AVX2
+
+Initialement, l’API ne fonctionnait pas sur le NAS (processeur Intel N100), car celui-ci ne prenait pas en charge les instructions **AVX2**, requises par TensorFlow.
+
+> 🛠️ **Solution** : activation manuelle du support AVX2 dans le BIOS. Cette option est souvent désactivée par défaut sur les cartes mères orientées NAS pour des raisons de consommation énergétique ou de stabilité.
+
+Depuis cette modification, le NAS peut exécuter l’API sans erreurs.
+
+---
+
+#### 🚀 API déployées
+
+Le projet propose un **double déploiement** de l’API, en local et dans le cloud :
+
+- 🏠 **NAS local** : [sentiment-api.greg-madman-nas.duckdns.org](https://sentiment-api.greg-madman-nas.duckdns.org)\
+Interface Docker Compose sur le NAS :
+
+
+- ☁️ **Google Cloud Run** : [sentiment-api-service-7772256003.europe-west1.run.app](https://sentiment-api-service-7772256003.europe-west1.run.app)\
+Interface de déploiement Google Cloud :
+
+
+---
+
+#### 🔄 Déploiement continu automatisé (NAS uniquement)
+
+Pour assurer un **déploiement continu** sur le NAS, il a été choisi d'installer [**Watchtower**](https://containrrr.dev/watchtower/arguments/) pour rester dans un logique d'environnement 100% `docker`. Cet outil surveille toutes les **10 minutes** l’image Docker de l’API (`sentiment_api`) et, en cas de nouvelle version disponible sur DockerHub, redémarre automatiquement le conteneur avec la dernière image.
+
+
+> Un **système d’alerte mail** notifie automatiquement toute mise à jour effectuée.
+
+
+Ce mécanisme garantit que la version déployée sur le NAS reste toujours synchronisée avec la dernière version validée par les tests sur GitHub Actions, **sans intervention manuelle**.
+
+
+---
+
+## 📊 Monitoring maison
+
+Une logique d’alerte légère embarquée dans l’API :
+
+
+
+
+
+
+
+
+Si **3 erreurs de prédiction** consécutives sont détectées sur une **fenêtre de 5 min**, un rapport est généré automatiquement.
+
+
+
+
+
+---
+
+## 🧠 Schéma global du pipeline MLOps
+
+### Schéma synthétique
+```
+ ┌────────────┐
+ │ Données │
+ │ (tweets) │
+ └─────┬──────┘
+ │
+ Prétraitement (regex, tokenisation, lemmatisation, stopwords)
+ │
+ ┌─────────▼──────────┐
+ │ Entraînement ML │
+ └─────────┬──────────┘
+ │
+ Log via MLFlow + artefacts MinIO
+ │
+ Sélection du meilleur modèle "avancé" (hors BERT) selon précision
+ │
+ ┌─────────▼──────────┐
+ │ API FastAPI │
+ │ + Streamlit │
+ └─────────┬──────────┘
+ │
+ Déploiement :
+ ├─ Google Cloud Run (manuel)
+ └─ NAS local (automatisé via Watchtower)
+ │
+┌──────────▼─────────────┐
+│ Monitoring léger maison│
+│ (alertes sur mauvaises │
+│ prédictions) │
+└────────────────────────┘
+```
+### Schéma détaillé
+
+
+---
+
+## ✨ Conclusion
+
+Ce projet démontre comment construire une chaîne MLOps complète, autonome et reproductible pour du NLP appliqué à Twitter.
+Il souligne les **forces et limites des modèles** (y compris BERT), la nécessité d’une métrique adaptée au contexte (précision vs accuracy), et l’importance d’un **déploiement maîtrisé**, même sur une infrastructure personnelle.
+
+---
+
+💬 Merci pour votre lecture !
\ No newline at end of file
diff --git a/docs/blog.md b/docs/blog.md
index e8fed94..f2eac36 100644
--- a/docs/blog.md
+++ b/docs/blog.md
@@ -1,235 +1,244 @@
-# ✨ Analyse de sentiments et déploiement MLOps : retour d’expérience complet
+# ✨ Sentiment Analysis and MLOps Deployment: A Complete Experience Report
-Dans le cadre du projet *Air Paradis*, nous avons mis en œuvre une chaîne complète d’analyse de sentiments à partir de tweets, depuis la modélisation jusqu’au déploiement MLOps. Ce billet de blog revient sur les étapes clés du projet : choix méthodologiques, comparaison des modèles, mise en production d’une API robuste, et déploiement sur deux environnements (local + cloud). 🧠🔧
+As part of the *Air Paradis* project, we implemented a full sentiment analysis pipeline from tweets, covering everything from modeling to MLOps deployment. This blog post reviews the key project stages: methodological choices, model comparison, deployment of a robust API, and deployment on two environments (local + cloud). 🧠🔧
---
-## 🔍 Trois approches de modélisation supervisée
+## 🔍 Three Supervised Modeling Approaches
-Nous avons testé trois approches complémentaires pour prédire le sentiment d’un tweet. Chacune repose sur une représentation textuelle différente et un algorithme d’apprentissage adapté :
+We tested three complementary approaches to predict the sentiment of a tweet. Each relies on a different text representation and a suitable learning algorithm:
-### 1. 🧱 Approche simple : Bag-of-Words (BoW) + modèles de machine learning
+### 1. 🧱 Simple Approach: Bag-of-Words (BoW) + Machine Learning Models
-On vectorise les tweets via BoW ou BoW + TF-IDF, qui comptent la fréquence des mots.
-Contrairement à d'autres projets NLP, nous avons évité LDA (non supervisé, orienté topic modeling).
+Tweets are vectorized using BoW or BoW + TF-IDF, which count word frequencies.
+Unlike other NLP projects, we avoided LDA (unsupervised, topic modeling oriented).
-➡️ **Modèles testés** :
-- Régression Logistique
+➡️ **Tested models**:
+- Logistic Regression
- Naive Bayes
- SVM
- Random Forest
-Ces modèles sont entraînés avec **GridSearchCV**, en optimisant la **précision (`precision`)**, notre KPI métier. Différents KPI ont été calculés sur l'ensemble de test.
+These models are trained with **GridSearchCV**, optimizing **precision (`precision`)**, our key business KPI. Various KPIs were computed on the test set.
-
+
---
-### 2. 🔥 Approche avancée : Word Embeddings + LSTM
+### 2. 🔥 Advanced Approach: Word Embeddings + LSTM
-Nous utilisons des vecteurs denses Word2Vec (entraînés) et GloVe 300d (préentraînés par Stanford), qui capturent les similarités sémantiques entre mots. Ces représentations ne prennent toutefois **pas en compte le contexte** exact (ex : "annulé" est probablement un mot très négatif pour un vol mais positif pour un procès contenant des charges contre vous).
+We use dense Word2Vec vectors (trained) and GloVe 300d (pretrained by Stanford), which capture semantic similarities between words. However, these representations **do not take into account the exact context** (e.g., "cancelled" is probably very negative for a flight but positive in a legal case with charges against you).
-La classification est réalisée par un **LSTM**, capable d'exploiter la séquentialité des mots.
-Le **modèle déployé est automatiquement sélectionné** entre Word2Vec + LSTM et GloVe + LSTM, selon la **précision maximale enregistrée dans MLFlow**.
+Classification is done by an **LSTM**, capable of exploiting word sequentiality.
+The **deployed model is automatically selected** between Word2Vec + LSTM and GloVe + LSTM, according to the **highest precision recorded in MLFlow**.
-Modèle `Word2Vec + LSTM` (`test_precision : 0.797 , val_precision : 0.795`):
-
-Modèle `GloVe 300d + LSTM` (`test_precision : 0.792 , val_precision : 0.798`):
-
+Model `Word2Vec + LSTM` (`test_precision: 0.797, val_precision: 0.795`):
+
+Model `GloVe 300d + LSTM` (`test_precision: 0.792, val_precision: 0.798`):
+
-Bien que GloVe 300d + LSTM présente un score de précision légèrement supérieur à Word2Vec + LSTM sur l'ensemble de validation, il reste inférieur pour l'ensemble de test (relativement négligeable dans l'absolu).
+Although GloVe 300d + LSTM shows a slightly better precision score on the validation set than Word2Vec + LSTM, it remains lower on the test set (relatively negligible overall).
---
-### 3. 🤖 Approche transformer : DistilBERT, embeddings contextuels allégés
+### 3. 🤖 Transformer Approach: DistilBERT, Lightweight Contextual Embeddings
-Nous avons utilisé **DistilBERT**, une version plus légère et plus rapide de BERT (créée par Hugging Face).
-Il conserve **95 % de la performance de BERT** tout en étant **40 % plus petit** et **60 % plus rapide**, ce qui le rend particulièrement adapté à un **entraînement sur GPU limité** (Google Colab) et à une **inférence plus rapide**.
+We used **DistilBERT**, a lighter and faster version of BERT (created by Hugging Face).
+It retains **95% of BERT's performance** while being **40% smaller** and **60% faster**, making it especially suited for **training on limited GPUs** (Google Colab) and **faster inference**.
-Comme BERT, DistilBERT produit des **embeddings contextuels**, c’est-à-dire que le sens des mots varie selon leur contexte. Par exemple, *"banque"* dans *"je vais à la banque"* et *"banque de données"* n’aura pas le même vecteur.
+Like BERT, DistilBERT produces **contextual embeddings**, meaning word meanings vary depending on context. For example, *"bank"* in *"I go to the bank"* and *"database bank"* will not have the same vector.
-Il a été **fine-tuné** ici pour une classification binaire (positif/négatif), avec un tokenizer et un encodage spécifiques à son architecture.
+It was **fine-tuned** here for binary classification (positive/negative), with a tokenizer and encoding specific to its architecture.
-> **Modèle `DistilBERT`** (`test_precision : 0.861 , val_precision : 0.858`)
+> **Model `DistilBERT`** (`test_precision: 0.861, val_precision: 0.858`)
-
-
+
+

-⚠️ **Limites** : comme tous les modèles préentraînés, DistilBERT **n’est pas sensible à l’ironie, aux jeux de mots, ni aux références culturelles implicites**.
-Or, Twitter est un terrain de jeu idéal pour ce genre de contenus détournés. Ces limites s’appliquent aussi à Word2Vec, GloVe et aux modèles classiques.
+⚠️ **Limits**: Like all pretrained models, DistilBERT **is not sensitive to irony, puns, or implicit cultural references**.
+Twitter is an ideal playground for this kind of nuanced content. These limits also apply to Word2Vec, GloVe, and classical models.
---
-## 🎯 Pourquoi optimiser la précision (et non l'accuracy) ?
+## 🎯 Why Optimize Precision (Not Accuracy)?
-**Accuracy** = proportion de bonnes prédictions globales.
-**Precision** = proportion de tweets *prévus positifs* qui sont *vraiment positifs*.
+**Accuracy** = overall proportion of correct predictions.
+**Precision** = proportion of *predicted positive* tweets that are *actually positive*.
-> Exemple : sur 100 tweets, si le modèle prédit 30 positifs, mais 15 sont des erreurs, la précision est de 50 %.
+> Example: out of 100 tweets, if the model predicts 30 positives but 15 are wrong, precision is 50%.
-Nous avons préféré **minimiser les faux positifs**, car dans un contexte sensible, **annoncer un tweet positif alors qu’il est négatif peut être problématique**.
+We preferred to **minimize false positives**, because in a sensitive context, **announcing a tweet as positive when it is negative can be problematic**.
-- Modèles classiques : **GridSearchCV optimisé sur la précision**
-- Modèles DL : **EarlyStopping sur val_loss**, mais **sélection finale sur la précision**
+- Classical models: **GridSearchCV optimized for precision**
+- Deep Learning models: **EarlyStopping on val_loss**, but **final selection based on precision**
---
-## ⚙️ Environnement MLOps souverain
+## ⚙️ Sovereign MLOps Environment
-### 🖥️ Serveur personnel NAS + OpenMediaVault
+### 🖥️ Personal NAS Server + OpenMediaVault
-MLFlow est installé sur un **NAS personnel (Intel N100)**, sous **OpenMediaVault (Debian)**.
-Nous utilisons **MinIO** pour stocker artefacts et modèles, garantissant une gestion locale, souveraine et compatible S3.
+MLFlow is installed on a **personal NAS (Intel N100)** running **OpenMediaVault (Debian)**.
+We use **MinIO** to store artifacts and models, ensuring local, sovereign, and S3-compatible management.
-> Les notebooks, exécutés sur Google Colab pour bénéficier de GPU, loggent dans MLFlow et envoient les modèles vers MinIO via des **variables d’environnement**.
+> Notebooks, run on Google Colab to leverage GPUs, log in MLFlow and send models to MinIO via **environment variables**.
-Dashboard Expériences MLFlow :
-
+MLFlow Experiments Dashboard:
+
-Modèles en production (registre de modèles):
+Production Models (model registry):

-Meilleur modèle non BERT retenu :
-
-
+Best non-BERT selected model:
+
+
+
---
-## 🧪 CI, tests et versioning
+## 🧪 CI, Testing and Versioning
-### ✅ Tests unitaires
+### ✅ Unit Tests
-- Vérifient le bon fonctionnement du prétraitement, des prédictions et de la gestion d’erreurs.
-- Intégrés à **GitHub Actions**, **ils bloquent le déploiement si les tests échouent.**
+- Check correct preprocessing, predictions, and error handling.
+- Integrated into **GitHub Actions**, **blocking deployment if tests fail.**
-### 🐳 Conteneurisation & CI/CD
+### 🐳 Containerization & CI/CD
-L’API FastAPI est packagée via Docker, puis poussée sur DockerHub.
-Un [pipeline CI/CD](https://github.com/GrgMdmn/OpenClassrooms_AI_Projects/blob/main/.github/workflows/p7_ci-cd.yml) complet garantit **un déploiement reproductible**. Il assure:
-- La validation de tests unitaires
-- La construction et le push de l'api conteneurisée sur dockerhub
+The FastAPI API is packaged with Docker, then pushed to DockerHub.
+A full [CI/CD pipeline](https://github.com/GrgMdmn/OpenClassrooms_AI_Projects/blob/main/.github/workflows/p7_ci-cd.yml) guarantees **reproducible deployment**, ensuring:
+- Validation of unit tests
+- Build and push of the containerized API to DockerHub
+
+
-
---
-## 🚀 Déploiement de l’API FastAPI (double)
+## 🚀 FastAPI API Deployment (Dual)
-### 🔧 Backend : FastAPI
+### 🔧 Backend: FastAPI
-- Expose un endpoint `/predict`
-- Charge dynamiquement le **meilleur modèle Word Embedding + LSTM** via le *Model Registry* MLFlow
-- Applique les bons embeddings selon le tag `embedding_type`
+- Exposes a `/predict` endpoint
+- Dynamically loads the **best Word Embedding + LSTM model** via MLFlow Model Registry
+- Applies appropriate embeddings according to the `embedding_type` tag
-### 💻 Interface Streamlit
+### 💻 Streamlit Interface
-Interface locale pour tester les requêtes, debug, démonstrations.
+Local interface for request testing, debugging, demonstrations.

---
-### 🌐 Double déploiement (NAS + Google Cloud)
+### 🌐 Dual Deployment (NAS + Google Cloud)
-#### 🔧 Problème AVX2
+#### 🔧 AVX2 Issue
-Initialement, l’API ne fonctionnait pas sur le NAS (processeur Intel N100), car celui-ci ne prenait pas en charge les instructions **AVX2**, requises par TensorFlow.
+Initially, the API did not run on the NAS (Intel N100 CPU) because it did not support **AVX2 instructions**, required by TensorFlow.
-> 🛠️ **Solution** : activation manuelle du support AVX2 dans le BIOS. Cette option est souvent désactivée par défaut sur les cartes mères orientées NAS pour des raisons de consommation énergétique ou de stabilité.
+> 🛠️ **Solution**: manual activation of AVX2 support in BIOS. This option is often disabled by default on NAS motherboards for power consumption or stability reasons.
-Depuis cette modification, le NAS peut exécuter l’API sans erreurs.
+Since this change, the NAS can run the API without errors.
---
-#### 🚀 API déployées
+#### 🚀 Deployed APIs
-Le projet propose un **double déploiement** de l’API, en local et dans le cloud :
+The project offers a **dual API deployment**, locally and in the cloud:
-- 🏠 **NAS local** : [sentiment-api.greg-madman-nas.duckdns.org](https://sentiment-api.greg-madman-nas.duckdns.org)\
-Interface Docker Compose sur le NAS :
-
+- 🏠 **Local NAS**: [sentiment-api.greg-madman-nas.duckdns.org](https://sentiment-api.greg-madman-nas.duckdns.org)
+Docker Compose interface on the NAS:
+
-- ☁️ **Google Cloud Run** : [sentiment-api-service-7772256003.europe-west1.run.app](https://sentiment-api-service-7772256003.europe-west1.run.app)\
-Interface de déploiement Google Cloud :
-
+- ☁️ **Google Cloud Run**: [sentiment-api-service-7772256003.europe-west1.run.app](https://sentiment-api-service-7772256003.europe-west1.run.app)
+Google Cloud deployment interface:
+
---
-#### 🔄 Déploiement continu automatisé (NAS uniquement)
+#### 🔄 Automated Continuous Deployment (NAS only)
-Pour assurer un **déploiement continu** sur le NAS, il a été choisi d'installer [**Watchtower**](https://containrrr.dev/watchtower/arguments/) pour rester dans un logique d'environnement 100% `docker`. Cet outil surveille toutes les **10 minutes** l’image Docker de l’API (`sentiment_api`) et, en cas de nouvelle version disponible sur DockerHub, redémarre automatiquement le conteneur avec la dernière image.
-
+To ensure **continuous deployment** on the NAS, we chose to install [**Watchtower**](https://containrrr.dev/watchtower/arguments/) to maintain a 100% `docker` environment. This tool checks every **10 minutes** the Docker image of the API (`sentiment_api`) and, if a new version is available on DockerHub, automatically restarts the container with the latest image.
+
-> Un **système d’alerte mail** notifie automatiquement toute mise à jour effectuée.
-
+> An **email alert system** automatically notifies any update performed.
+
-Ce mécanisme garantit que la version déployée sur le NAS reste toujours synchronisée avec la dernière version validée par les tests sur GitHub Actions, **sans intervention manuelle**.
-
+This mechanism ensures that the version deployed on the NAS always stays synchronized with the latest version validated by GitHub Actions tests, **without manual intervention**.
+
---
-## 📊 Monitoring maison
+## 📊 Home-made Monitoring
-Une logique d’alerte légère embarquée dans l’API :
+A lightweight alert logic embedded in the API:
-
-
-
-
-
-
-
-Si **3 erreurs de prédiction** consécutives sont détectées sur une **fenêtre de 5 min**, un rapport est généré automatiquement.
-
-
+
+
+
+If **3 consecutive prediction errors** are detected within a **5-minute window**, a report is automatically generated.
+
---
-## 🧠 Schéma global du pipeline MLOps
+## 🧠 Overall MLOps Pipeline Diagram
+
+### Summary Diagram
-### Schéma synthétique
```
┌────────────┐
- │ Données │
- │ (tweets) │
+ │ Data │
+ │ (tweets) │
└─────┬──────┘
│
- Prétraitement (regex, tokenisation, lemmatisation, stopwords)
+ Preprocessing (regex, tokenization, lemmatization, stopwords)
│
┌─────────▼──────────┐
- │ Entraînement ML │
+ │ ML Training │
└─────────┬──────────┘
│
- Log via MLFlow + artefacts MinIO
+ Logging via MLFlow + artifacts MinIO
│
- Sélection du meilleur modèle "avancé" (hors BERT) selon précision
+ Select best "advanced" model (excluding BERT) by precision
│
┌─────────▼──────────┐
- │ API FastAPI │
- │ + Streamlit │
+ │ FastAPI │
+ │ + Streamlit │
└─────────┬──────────┘
│
- Déploiement :
- ├─ Google Cloud Run (manuel)
- └─ NAS local (automatisé via Watchtower)
+ Deployment:
+ ├─ Google Cloud Run (manual)
+ └─ Local NAS (automated via Watchtower)
│
┌──────────▼─────────────┐
-│ Monitoring léger maison│
-│ (alertes sur mauvaises │
-│ prédictions) │
+│ Lightweight in-house │
+│ Monitoring │
+│ (alerts on bad │
+│ predictions) │
└────────────────────────┘
+
```
-### Schéma détaillé
-
+
+### Detailed Diagram
+
---
## ✨ Conclusion
-Ce projet démontre comment construire une chaîne MLOps complète, autonome et reproductible pour du NLP appliqué à Twitter.
-Il souligne les **forces et limites des modèles** (y compris BERT), la nécessité d’une métrique adaptée au contexte (précision vs accuracy), et l’importance d’un **déploiement maîtrisé**, même sur une infrastructure personnelle.
+This project demonstrates how to build a complete, autonomous, and reproducible MLOps pipeline for NLP applied to Twitter.
+It highlights the **strengths and limitations of the models** (including BERT), the need for a **metric adapted to the context** (precision vs accuracy), and the importance of **controlled deployment**, even on personal infrastructure.
---
-💬 Merci pour votre lecture !
\ No newline at end of file
+💬 Thank you for reading!
+
+
+
+
+
+
+
+Demander à ChatGPT
diff --git a/docs/diagram.drawio b/docs/diagram.drawio
index 25afb79..3fe871f 100644
--- a/docs/diagram.drawio
+++ b/docs/diagram.drawio
@@ -83,7 +83,7 @@
-
+
diff --git a/docs/diagram.drawio.png b/docs/diagram.drawio.png
index 34e1716..9e4d6c5 100644
Binary files a/docs/diagram.drawio.png and b/docs/diagram.drawio.png differ
diff --git a/notebooks/README.fr.md b/notebooks/README.fr.md
new file mode 100644
index 0000000..c59b4fc
--- /dev/null
+++ b/notebooks/README.fr.md
@@ -0,0 +1,46 @@
+# Notebooks
+
+Ce dossier contient les notebooks Jupyter utilisés pour le développement des modèles et les analyses du projet.
+
+## Contenu
+
+- Analyse exploratoire des données
+- Modèles classiques (régression logistique, SVM, etc.)
+- Modèles avancés (LSTM avec embeddings GloVe)
+- Modèle BERT
+
+## Note concernant les fichiers requirements
+
+Les fichiers `*requirements.txt` ont été générés depuis un environnement Google Colab. Cet environnement inclut de nombreuses librairies préinstallées, dont toutes ne sont pas nécessaires au projet.
+
+Un nettoyage manuel ou une génération spécifique des fichiers requirements sera nécessaire pour alléger ces fichiers avant un usage en production ou un déploiement.
+
+---
+
+## Résumé des performances des modèles
+
+### Modèles classiques (entraînés sur 200 000 tweets)
+
+| Modèle | Précision | Temps d'entraînement|
+|--------------------------------|-----------|---------------------|
+| Random Forest + BoW | 0,7798 | ~5 heures |
+| Régression logistique + TF-IDF | 0,7796 | <2 minutes |
+
+### Modèles avancés basés sur des embeddings (entraînés sur 200 000 tweets, accélérés GPU sur Google Colab)
+
+| Modèle | Précision | Temps d'entraînement|
+|------------------------|-----------|---------------------|
+| Word2Vec + LSTM | 0,797 | 57 secondes |
+| GloVe (300d) + LSTM | 0,792 | 47 secondes |
+
+### Modèle de pointe (entraîné sur 100 000 tweets en raison des limites RAM)
+
+| Modèle | Précision | Temps d'entraînement|
+|---------|-----------|---------------------|
+| BERT | 0,882 | 1,3 minutes |
+
+---
+
+Ce résumé met en lumière les compromis entre précision des modèles et temps d’entraînement. Si les modèles classiques sont plus rapides à entraîner, les modèles avancés utilisant des embeddings et LSTM offrent une meilleure précision, avec BERT qui atteint la meilleure précision malgré un jeu de données plus restreint.
+
+L’écart de précision entre BERT et les modèles à embeddings peut s’expliquer principalement par la capacité bidirectionnelle de BERT à comprendre le contexte.
diff --git a/notebooks/README.md b/notebooks/README.md
index f55baa9..b58630e 100644
--- a/notebooks/README.md
+++ b/notebooks/README.md
@@ -22,7 +22,7 @@ Manual cleanup or specific generation of requirements files will be needed to sl
### Classical Models (trained on 200,000 tweets)
| Model | Precision | Training Time |
-|-----------------------------|-----------|-----------------|
+|------------------------------|-----------|-----------------|
| Random Forest + BoW | 0.7798 | ~5 hours |
| Logistic Regression + TF-IDF | 0.7796 | <2 minutes |
diff --git a/presentation/git_cd_docker.png b/presentation/git_cd_docker.png
new file mode 100644
index 0000000..b954482
Binary files /dev/null and b/presentation/git_cd_docker.png differ
diff --git a/presentation/git_ci_tests.png b/presentation/git_ci_tests.png
new file mode 100644
index 0000000..20a3b41
Binary files /dev/null and b/presentation/git_ci_tests.png differ
diff --git a/presentation/git_commands.png b/presentation/git_commands.png
new file mode 100644
index 0000000..19b6c66
Binary files /dev/null and b/presentation/git_commands.png differ