File size: 18,728 Bytes
8972476
1efa2f5
 
b008a5a
 
8972476
 
 
 
1efa2f5
b008a5a
1efa2f5
f0ea434
1efa2f5
 
 
36200e2
1efa2f5
 
 
 
 
 
 
36200e2
1efa2f5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b008a5a
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
---
title: Agritech Answers - API de Prédiction
emoji: 🌾
colorFrom: yellow
colorTo: purple
sdk: docker
pinned: false
---

# Application de prédiction de rendement agricole

Ce projet implémente une API (backend) de prédiction de rendement agricole basée sur un model Random Forest pour Agritech Answers, ainsi qu'un dashboard Streamlit (frontend)
pour visualiser les prédictions et les recommandations de culture. Les deux services sont conteneurisés avec Docker et déployés sur Hugging Face Spaces.

## Fonctionnalités

[BACKEND] l'API offre 4 endpoints : https://cedm-oc-mlops-projet-4-api.hf.space/docs
- '/health' : endpoint de santé pour vérifier que l'API est opérationnelle
- '/columns' : endpoint pour récupérer les noms des colonnes d'entrée attendues par le modèle
- '/predict' : endpoint pour faire une prédiction de rendement agricole à partir de la saisie de caractéristiques agricoles pour une culture
- '/recommend' : endpoint pour faire une recommandation de culture à partir de la saisie de caractéristiques agricoles

La documentation automatique de l'API (swagger) est disponible avec : /docs

[FRONTEND] le dashboard Streamlit offre les fonctionnalités suivantes : https://huggingface.co/spaces/CedM/oc_mlops_projet_4_dashboard
- 🌾 **Prédiction individuelle** : saisie des caractéristiques agricoles pour une culture
- 🏆 **Recommandation** : saisie des caractéristiques agricoles pour obtenir une recommandation de culture
- 📡 **Santé de l'API** : vérification de la disponibilité du backend

## Prérequis

- Ubuntu 22.04+ ou n'importe quel système d'exploitation compatible
- Python 3.11+
- Créer un compte et un Access Token sur Hugging Face Spaces ([huggingface.co](https://huggingface.co/))
- Créer un compte, Organisation, Projet et un Write Token Logfire ([logfire.com](https://logfire.com/))

## Installation

1. **Forker et cloner le dépôt**

- Connectez-vous à votre compte GitLab/Framagit.
- Rendez-vous sur le dépôt GitLab du projet : https://framagit.org/dapa/oc_mlops_projet_4
- Cliquez sur "Fork" pour créer une copie du projet dans votre propre espace GitLab/Framagit.
- Une fois le fork créé, clonez votre fork localement avec la commande suivante (remplacez <votre_nom_utilisateur> par votre nom d'utilisateur GitLab/Framagit) :

```bash
git clone https://framagit.org/<votre_nom_utilisateur>/oc_mlops_projet_4.git
```

2. **Créer un compte sur Logfire et récupérer le Write Token**

- Rendez-vous sur [logfire.com](https://logfire.com/) et créez un compte.
- Une fois connecté, créez votre Organisation et votre projet (exemple de projet : oc-mlops-projet-4) dans Logfire (c'est ici que les logs de votre application seront envoyés).
- Dans les paramètres de votre projet Logfire, créez un Write Token : Settings > Write Tokens > New token. Copiez ce token, vous en aurez besoin pour la configuration de Hugging Face Spaces.

3. **Créer un compte sur Hugging Face et un Space**

- Rendez-vous sur [huggingface.co](https://huggingface.co/) et créez un compte.
- Une fois connecté, cliquez sur "New Space" pour créer un nouvel espace.
- Donnez un nom à votre Space (par exemple, "oc_mlops_projet_4_api") et choisissez "Docker" comme framework/SDK.
- Cliquez sur "Create Space" pour créer votre espace.
- Configurez la variable d'environnement `LOGFIRE_TOKEN` dans les paramètres de votre Space Hugging Face avec le Write Token de Logfire que vous avez créé précédemment : Settings > Secrets > New secret
- Créez un Access Token dans les paramètres de votre compte Hugging Face (Settings > Access Tokens > New token) avec les permissions "read" et "write". Copiez ce token, vous en aurez besoin pour la configuration de GitLab CI.

4. **Insérer l'Access Token d'Hugging Face Spaces dans GitLab CI**

- Rendez-vous sur votre projet sur GitLab et accédez aux paramètres : Settings > CI/CD > Variables > Project variables > New variable
- Ajoutez la nouvelle variable HF_TOKEN avec comme valeur l'Access Token de Hugging Face Spaces que vous avez créé précédemment.

5. **Modifier le fichier config.py**

- Mettez-vous sur la branche 'main' (git) du projet et modifiez les variables suivantes en fonction de votre configuration :\
`DEFAULT_FRONTEND_URL` : URL de votre Space Hugging Face où le dashboard Streamlit est déployé\
`DEFAULT_API_URL` : URL de votre Space Hugging Face où l'API est déployée

6. **Commit et push du code sur 'main'**

- Après avoir configuré les variables d'environnement et modifié le fichier config.py, committez vos changements et poussez-les sur la branche 'main' de votre dépôt GitLab/Framagit.
- Cela déclenchera automatiquement le pipeline CI/CD qui build et déploie votre API et votre dashboard sur Hugging Face Spaces.
- Si tous les Hugging Face Spaces n'ont pas été créés avant le push, le pipeline CI/CD les créera automatiquement lors de son exécution.
- Vous pouvez suivre l'exécution du pipeline CI/CD dans la section : Build > Pipelines de votre projet GitLab/Framagit.
- Une fois le pipeline terminé, votre API et votre dashboard seront accessibles via les URLs de vos Spaces Hugging Face que vous avez configurés dans le fichier config.py.

## Ré-entraînement du modèle

Si vous souhaitez entraîner à nouveau le modèle de prédiction de rendement agricole, vous pouvez suivre les étapes suivantes :

1. **Préparer les données d'entraînement**

- Vous trouverez un exemple de dataset d'entraînement dans le dossier :
'1_Data_source/OC-20250526T142605Z-1-001.zip/OC/Crop Yield Prediction Dataset.zip/yield_df.csv'.

2. **Mettre à jour le code d'entraînement**

- Vous pouvez modifier le code d'entraînement du modèle dans le fichier `9_Pipeline_train/train.py
- Vous pouvez également changer si nécessaire l'année du split entre les données d'entraînement et de test (actuellement fixé à 2009) dans le fichier config.py (variable 'YEAR_THRESHOLD').

3. **Lancer le container Docker pour l'entraînement**

- Ouvrez un terminal et naviguez jusqu'à la racine du projet.
- Lancez le container Docker avec la commande suivante :

```bash
docker build -f 9_Pipeline_train/Dockerfile_pipeline -t crop-yield-pipeline .
docker run --rm \
  -v $(pwd)/2_Data_transformed:/app/2_Data_transformed \
  -v $(pwd)/5_Notebooks:/app/5_Notebooks \
  crop-yield-pipeline
```

4. **Mettre à jour le modèle dans le pipeline CI/CD**

- Allez dans MLflow et enregistrez une nouvelle version du modèle.
- Récupérez dans MLflow le chemin du nouveau modèle dans le dossier `/mlartifacts` et mettez àjour la variable `MODEL_PATH` dans le fichier `config.py`.
- Mettez à jour le fichier `.gitlab-ci.yml` avec le nouveau chemin du modèle dans la section de déploiement de l'API.
- Mettez à jour le fichier `Dockerfile_api` avec le nouveau chemin du modèle pour qu'il soit utilisé lors du build du container de l'API.
- Faites un git add du nouveau modèle, commit et push sur main. Cela déclenchera le pipeline CI/CD...

## Diagramme d'architecture du pipeline CI/CD et de l'application

```
┌─────────────────────────────────────────────────────────────────────────────────┐
│                          CI/CD Pipeline GitLab (branche main)                   │
│                                                                                 │
│   ┌───────────────────┐                                                         │
│   │  Code push/MR     │                                                         │
│   │    sur main       │                                                         │
│   └─────────┬─────────┘                                                         │
│             │                                                                   │
│             ▼              Stage : test                                         │
│   ┌─────────────────────────────────────────┐                                   │
│   │          Tests unitaires                │                                   │
│   │          test_api.py (pytest + cov)     │                                   │
│   │          Rapport couverture → artifact  │                                   │
│   └─────────────────────┬───────────────────┘                                   │
│                         │  (si tests OK)                                        │
│                         ▼              Stage : deploy (jobs en parallèle)       │
│             ┌───────────┴──────────────────────────┐                            │
│             │                                      │                            │
│             ▼                                      ▼                            │
│   ┌──────────────────────┐          ┌───────────────────────────┐               │
│   │    Deploy API        │          │    Deploy Dashboard       │               │
│   │    vers HF Spaces    │          │    vers HF Spaces         │               │
│   │                      │          │                           │               │
│   │  1. Crée le Space    │          │  1. Crée le Space         │               │
│   │     si inexistant    │          │     si inexistant         │               │
│   │  2. Copie fichiers   │          │  2. Copie fichiers        │               │
│   │     en staging       │          │     en staging            │               │
│   │  3. Upload via       │          │  3. Upload via            │               │
│   │     HF Hub API       │          │     HF Hub API            │               │
│   └──────────┬───────────┘          └───────────────┬───────────┘               │
└──────────────┼──────────────────────────────────────┼───────────────────────────┘
               │                                      │
               ▼  Hugging Face Spaces                 ▼
  ┌─────────────────────────────┐        ┌───────────────────────┐
  │   API FastAPI – HF Space    │        │  Dashboard Streamlit  │
  │                             │◄───────│  HF Space             │
  │  Démarrage uvicorn :7860    │        │  Onglet Prédiction    │
  │                             │        │  Onglet Recommand.    │
  │  ┌─────────────────────┐    │        │  Onglet Santé API     │
  │  │  Test fonctionnel   │    │        └───────────────────────┘
  │  │  test_functional.py │    │
  │  │  • GET /health      │    │
  │  │  • modèle chargé ?  │    │
  │  │  • items/areas > 0 ?│    │
  │  └─────────────────────┘    │
  │                             │
  │  /health  /columns          │
  │  /predict /recommend /docs  │
  └─────────────────────────────┘
```


## Structure du projet

```
.
├── .dockerignore               # Fichier pour ignorer les fichiers inutiles lors du build Docker
├── .env                        # Fichier pour stocker les variables d'environnement (clés API, tokens, etc.)
├── .gitattributes              # Fichier de configuration des attributs Git (LFS, etc.)
├── .gitlab-ci.yml              # Pipeline CI/CD GitLab (build, test et déploiement sur Hugging Face Spaces)
├── config.py                   # Configuration globale du projet (chemins, variables, paramètres)
├── Dockerfile_api              # Dockerfile pour le build du container de l'API FastAPI
├── main.py                     # API FastAPI
├── README.md                   # Instructions d'installation, d'utilisation...
├── requirements_api.txt        # Dépendances Python pour l'API
├── zsh_commands.sh             # Commandes utiles pour le développement et le déploiement

├── 1_Data_source/              # Données brutes sources
│   ├── crop_yield.csv
│   ├── OC-20250526T142605Z-1-001.zip
│   ├── pesticides.csv
│   ├── rainfall.csv
│   ├── temp.csv
│   ├── yield.csv
│   └── yield_df.csv

├── 2_Data_transformed/         # Données transformées et préparées pour l'entraînement
│   ├── crop_yield_2_cleaned.pkl
│   └── crop_yield_2_train_set_simplified.csv

├── 3_Results/                  # (vide) Dossier pour les résultats des expérimentations

├── 4_Models/                   # (vide) Dossier pour les modèles entraînés exportés

├── 5_Notebooks/                # Notebooks Jupyter d'exploration et d'entraînement
│   ├── 1_Notebook_EDA_Dataset_1.ipynb
│   ├── 2_Notebook_EDA_Dataset_2.ipynb
│   ├── 3_Notebook_Linear_Regression.ipynb
│   ├── 4_Notebook_Random_Forest.ipynb
│   ├── Coefficient_Determination.png
│   ├── merge_test.py           # Script de vérification si yield_df.csv est bien la fusion des autres datasets (yield, temp, rainfall, pesticides)
│   ├── mlflow.db               # Base de données MLflow (expériences et runs)
│   ├── mlflow.log              # Logs MLflow
│   ├── notebook_fonctions.py   # Fonctions utilitaires pour les notebooks
│   └── mlartifacts/            # Artefacts MLflow (modèles, résultats CV, etc.)

├── 6_Dashboard/                # Dashboard Streamlit (frontend)
│   ├── app.py                  # Application Streamlit
│   ├── Dockerfile_dash         # Dockerfile pour le build du container du dashboard
│   ├── .dockerignore           # Fichier pour ignorer les fichiers inutiles lors du build Docker
│   ├── README.md               # Instructions d'installation, d'utilisation...
│   └── requirements_dash.txt   # Dépendances Python pour le dashboard

├── 7_Docs/                     # Dossier pour la documentation du projet

├── 8_Tests/                    # Tests automatisés
│   ├── test_api.py             # Tests unitaires de l'API
│   └── test_functional.py      # Tests fonctionnels de l'API

└── 9_Pipeline_train/           # Pipeline d'entraînement du modèle
    ├── Dockerfile_pipeline     # Dockerfile pour le build du container du pipeline
    ├── evaluate.py             # Script d'évaluation du modèle
    ├── pipeline.py             # Orchestration du pipeline d'entraînement
    ├── preprocess.py           # Prétraitement des données
    ├── requirements_pipeline.txt # Dépendances Python pour le pipeline
    └── train.py                # Script d'entraînement du modèle

```

## Utilisation du Backend et du Frontend

### 1. Faire une prédiction de rendement agricole pour une culture

**[BACKEND] API** — endpoint `POST /predict`

Envoyez une requête POST avec curl :

```bash
curl -X POST "https://cedm-oc-mlops-projet-4-api.hf.space/predict" \
     -H "Content-Type: application/json" \
     -d '{"Area":"France","Item":"Wheat","Year":2026,"average_rain_fall_mm_per_year":600.0,"pesticides_tonnes":1000.0,"avg_temp":15.0}'
```

> ℹ️ Le rendement est exprimé en **hg/ha** (hectogrammes par hectare).  
> ℹ️ Pour connaître les pays et cultures disponibles, consultez préalablement `GET /columns`.

```bash
curl "https://cedm-oc-mlops-projet-4-api.hf.space/columns"
```

**[FRONTEND] Dashboard Streamlit**

1. Accédez au dashboard : `https://cedm-oc-mlops-projet-4-dashboard.hf.space`
2. Ouvrez l'onglet **🌾 Prédiction**
3. Sélectionnez le **pays**, la **culture** (filtrée selon le pays choisi) et l'**année**
4. Renseignez les variables climatiques (précipitations, pesticides, température)
5. Cliquez sur **🔮 Lancer la prédiction**
6. Le rendement prédit s'affiche en hg/ha

---

### 2. Demander une recommandation de culture

**[BACKEND] API** — endpoint `POST /recommend`

Envoyez une requête POST **sans** le champ `Item` (l'API calcule le rendement pour toutes les cultures du pays) avec curl:

```bash
curl -X POST "https://cedm-oc-mlops-projet-4-api.hf.space/recommend" \
     -H "Content-Type: application/json" \
     -d '{"Area":"France","Year":2026,"average_rain_fall_mm_per_year":600.0,"pesticides_tonnes":1000.0,"avg_temp":15.0}'
```

> ℹ️ Les cultures sont classées par **rendement décroissant** ; la première est la meilleure recommandation.

**[FRONTEND] Dashboard Streamlit**

1. Accédez au dashboard : `https://cedm-oc-mlops-projet-4-dashboard.hf.space`
2. Ouvrez l'onglet **🏆 Recommandation**
3. Sélectionnez le **pays** et l'**année**
4. Renseignez les variables climatiques
5. Ajustez si besoin le nombre de cultures à afficher (curseur **Top N**)
6. Cliquez sur **🏆 Obtenir les recommandations**
7. Le classement s'affiche sous forme de graphique en barres et de tableau ; la meilleure culture est mise en avant

---

### 3. Interroger l'état de santé de l'API

**[BACKEND] API** — endpoint `GET /health`

```bash
curl "https://cedm-oc-mlops-projet-4-api.hf.space/health"
```

**[FRONTEND] Dashboard Streamlit**

1. Ouvrez l'onglet **📡 Santé de l'API**
2. Cliquez sur **🔄 Vérifier l'état de l'API**
3. Le statut de l'API, l'état du modèle, et les listes des pays et cultures disponibles s'affichent

---

> 💡 **Documentation interactive (Swagger)** : tous les endpoints sont documentés et testables directement depuis :  
> `https://cedm-oc-mlops-projet-4-api.hf.space/docs`