-
Notifications
You must be signed in to change notification settings - Fork 27
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
188 additions
and
185 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,76 +1,85 @@ | ||
::: {.nonincremental} | ||
:::{.nonincremental} | ||
:::: {.callout-tip collapse="true" icon=false} | ||
## Partie 1 : Requêter votre modèle déployé | ||
## Partie 1 : Logger des métriques métier | ||
|
||
1. Créez un fichier `predict_api.py`. Ce script doit : | ||
- Lire le fichier parquet disponible à l'adresse suivante : | ||
1. Grâce au package [logging](https://docs.python.org/3/library/logging.html), rajoutez des logs à votre API. Pour chaque requête, affichez le libellé à coder ainsi que les réponses renvoyées par votre API. Pour cela, modifiez le fichier `app/main.py`. | ||
|
||
```shell | ||
https://minio.lab.sspcloud.fr/projet-formation/diffusion/mlops/data/data_to_classify.parquet | ||
``` | ||
|
||
- Effectuer des requêtes à votre API pour chaque libellé présent dans le fichier parquet. | ||
- Afficher le résultats des prédictions | ||
|
||
<details> | ||
<summary> | ||
<font size=\"3\" color=\"darkgreen\"><b>Cliquez pour voir le contenu du script </b></font> | ||
<font size=\"3\" color=\"darkgreen\"><b>Cliquez pour voir les étapes à réaliser </b></font> | ||
</summary> | ||
|
||
```{.python filename="predict_api.py"} | ||
import pandas as pd | ||
import requests | ||
1. Importez le package logging : | ||
|
||
```{.python filename="main.py"} | ||
import logging | ||
``` | ||
|
||
# Fonction pour effectuer la requête à l'API | ||
def make_prediction(api_url: str, description: str): | ||
params = {"description": description, "nb_echoes_max": 2} | ||
response = requests.get(api_url, params=params) | ||
return response.json() | ||
2. Définissez la configuration de vos logs avant la définition de votre premier point d'entrée : | ||
|
||
```{.python filename="main.py"} | ||
logging.basicConfig( | ||
level=logging.INFO, | ||
format="%(asctime)s - %(levelname)s - %(message)s", | ||
handlers=[ | ||
logging.FileHandler("log_file.log"), | ||
logging.StreamHandler(), | ||
], | ||
) | ||
``` | ||
|
||
3. Ajoutez une le libellé et la réponse de l'API dans vos logs : | ||
|
||
# URL des données | ||
data_path = "https://minio.lab.sspcloud.fr/projet-formation/diffusion/mlops/data/data_to_classify.parquet" | ||
```{.python filename="main.py"} | ||
# Logging | ||
logging.info(f"{{'Query': {description}, 'Response': {predictions[0]}}}") | ||
``` | ||
|
||
# Charge le fichier Parquet dans un DataFrame pandas | ||
df = pd.read_parquet(data_path) | ||
</details> | ||
|
||
# Votre API URL | ||
api_url = "https://<your_firstname>-<your_lastname>-api.lab.sspcloud.fr/predict" | ||
2. Faites un commit de vos changements et poussez les sur votre dépôt distant. | ||
|
||
# Effectue les requêtes | ||
responses = df["text"].apply(lambda x: make_prediction(api_url, x)) | ||
3. Dès lors que vous réalisez un changement sur votre API, il est nécessaire de la redéployer pour que les changements soient effectifs. En théorie, il serait nécessaire de re-construire une nouvelle image pour notre API contenant les derniers ajustements. Pour simplifier, nous avons déjà construit les deux images avec et sans logs dans l'API. Jusqu'à présent vous avez utilisé l'image sans logs, redéployez votre API en utilisant l'image avec les logs dont le tag est `logs`. | ||
|
||
# Affiche le DataFrame avec les résultats des prédictions | ||
print(pd.merge(df, pd.json_normalize(responses), | ||
left_index=True, | ||
right_index=True)) | ||
<details> | ||
<summary> | ||
<font size=\"3\" color=\"darkgreen\"><b>Cliquez pour voir les étapes à réaliser </b></font> | ||
</summary> | ||
|
||
1. Dans le fichier `kubernetes/deployment.yml`, remplacer le tag `no-logs` par le tag `logs` : | ||
|
||
```{.yaml code-line-numbers="8" filename="deployment.yml"} | ||
template: | ||
metadata: | ||
labels: | ||
app: codification-api | ||
spec: | ||
containers: | ||
- name: api | ||
image: inseefrlab/formation-mlops:logs | ||
imagePullPolicy: Always | ||
``` | ||
|
||
2. Faites un commit de vos changements et poussez les sur votre dépôt distant. | ||
|
||
3. Patientez 5 minutes qu'`ArgoCD` synchronise automatiquement les changements depuis votre dépôt Github ou bien forcez la synchronisation. | ||
|
||
</details> | ||
|
||
2. Exécutez votre script `predict_api.py`. | ||
4. Exécutez votre script `predict-api.py`. | ||
|
||
<details> | ||
<summary> | ||
<font size=\"3\" color=\"darkgreen\"><b>Cliquez pour voir la commande </b></font> | ||
</summary> | ||
|
||
```shell | ||
python formation-mlops/src/predict_api.py | ||
python formation-mlops/src/predict-api.py | ||
``` | ||
</details> | ||
|
||
3. Dans ArgoCD, ouvrez votre application puis cliquez sur votre pod qui doit commencer par `"codification-api-..."`. Observez les logs. | ||
|
||
4. Quelles informations détenez-vous ? Est-ce suffisant ? | ||
|
||
:::: | ||
|
||
:::: {.callout-important collapse="true"} | ||
|
||
Nous avons ici réalisé une succession de requêtes GET car nous avons un seul point d'entrée vers notre API. Pour réaliser des requêtes en `batch` il est préférable de réaliser des requêtes POST. | ||
5. Dans ArgoCD, ouvrez votre application puis cliquez sur votre pod qui doit commencer par `"codification-api-..."`. Observez les logs. | ||
|
||
:::: | ||
::: |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,85 +1,73 @@ | ||
:::{.nonincremental} | ||
:::: {.callout-tip collapse="true" icon=false} | ||
## Partie 2 : Logger des métriques métier | ||
:::{.callout-tip collapse="true" icon=false} | ||
## Partie 2 : Création d'un tableau de bord de monitoring | ||
|
||
1. Grâce au package [logging](https://docs.python.org/3/library/logging.html), rajoutez des logs à votre API. Pour chaque requête, affichez le libellé à coder ainsi que les réponses renvoyées par votre API. Pour cela, modifiez le fichier `app/main.py`. | ||
:::::{.nonincremental} | ||
1. Nous allons utiliser [`Quarto Dashboards`](https://quarto.org/docs/dashboards/) qui fera partie de la version 1.4 de `Quarto`. Téléchargez et installez la pre-release. | ||
|
||
```sh | ||
wget https://github.com/quarto-dev/quarto-cli/releases/download/v1.4.489/quarto-1.4.489-linux-amd64.deb \ | ||
-O quarto.deb | ||
sudo dpkg -i quarto.deb | ||
quarto check install | ||
rm quarto.deb | ||
``` | ||
|
||
<details> | ||
<summary> | ||
<font size=\"3\" color=\"darkgreen\"><b>Cliquez pour voir les étapes à réaliser </b></font> | ||
</summary> | ||
|
||
1. Importez le package logging : | ||
|
||
```{.python filename="main.py"} | ||
import logging | ||
``` | ||
|
||
2. Définissez la configuration de vos logs avant la définition de votre premier point d'entrée : | ||
|
||
```{.python filename="main.py"} | ||
logging.basicConfig( | ||
level=logging.INFO, | ||
format="%(asctime)s - %(levelname)s - %(message)s", | ||
handlers=[ | ||
logging.FileHandler("log_file.log"), | ||
logging.StreamHandler(), | ||
], | ||
) | ||
``` | ||
|
||
3. Ajoutez une le libellé et la réponse de l'API dans vos logs : | ||
2. Ouvrez le fichier `dashboard/index.qmd` et inspectez le code. Pour récupérer les données nécessaires à la création du tableau de bord, on utilise un SGBD *serverless* : `DuckDB`. `DuckDB` nous permet de faire des requêtes `SQL` sur un fichier `.parquet` contenant des logs *parsés*. Ce fichier contient une ligne par prédiction, avec les variables `timestamp`, `text`, `prediction_1`, `proba_1`, `prediction_2` et `proba_2`. | ||
|
||
```{.python filename="main.py"} | ||
# Logging | ||
logging.info(f"{{'Query': {description}, 'Response': {predictions[0]}}}") | ||
``` | ||
|
||
</details> | ||
3. Pour visualiser le tableau de bord, entrez les commandes suivantes dans un `Terminal` depuis la racine du projet et cliquez sur le lien généré. | ||
|
||
2. Faites un commit de vos changements et poussez les sur votre dépôt distant. | ||
```sh | ||
cd dashboard | ||
quarto preview index.qmd | ||
``` | ||
|
||
3. Dès lors que vous réalisez un changement sur votre API, il est nécessaire de la redéployer pour que les changements soient effectifs. En théorie, il serait nécessaire de re-construire une nouvelle image pour notre API contenant les derniers ajustements. Pour simplifier, nous avons déjà construit les deux images avec et sans logs dans l'API. Jusqu'à présent vous avez utilisé l'image sans logs, redéployez votre API en utilisant l'image avec les logs dont le tag est `logs`. | ||
4. Pour l'instant le pourcentage de prédictions avec une probabilité supérieure à 0.8 ne correspond pas à la réalité. Modifiez la requête SQL permettant d'obtenir la variable `pct_predictions` pour afficher la bonne valeur. | ||
|
||
<details> | ||
<summary> | ||
<font size=\"3\" color=\"darkgreen\"><b>Cliquez pour voir les étapes à réaliser </b></font> | ||
<font size=\"3\" color=\"darkgreen\"><b>Cliquez pour voir la réponse </b></font> | ||
</summary> | ||
|
||
1. Dans le fichier `kubernetes/deployment.yml`, remplacer le tag `no-logs` par le tag `logs` : | ||
|
||
```{.yaml code-line-numbers="8" filename="deployment.yml"} | ||
template: | ||
metadata: | ||
labels: | ||
app: codification-api | ||
spec: | ||
containers: | ||
- name: api | ||
image: inseefrlab/formation-mlops:logs | ||
imagePullPolicy: Always | ||
```python | ||
pct_predictions = duckdb.sql( | ||
""" | ||
SELECT 100 * COUNT(*) / COUNT(*) | ||
FROM data; | ||
""" | ||
).fetchall()[0][0] | ||
``` | ||
|
||
2. Faites un commit de vos changements et poussez les sur votre dépôt distant. | ||
|
||
3. Patientez 5 minutes qu'`ArgoCD` synchronise automatiquement les changements depuis votre dépôt Github ou bien forcez la synchronisation. | ||
|
||
</details> | ||
|
||
4. Exécutez votre script `predict-api.py`. | ||
|
||
5. Les deux graphiques situés en bas du tableau de bord ne sont pas corrects non plus. Modifiez la requête SQL permettant d'obtenir la variable `daily_stats` pour afficher les bons graphiques. | ||
<details> | ||
<summary> | ||
<font size=\"3\" color=\"darkgreen\"><b>Cliquez pour voir la commande </b></font> | ||
<font size=\"3\" color=\"darkgreen\"><b>Cliquez pour voir la réponse </b></font> | ||
</summary> | ||
```shell | ||
python formation-mlops/src/predict-api.py | ||
```python | ||
daily_stats = duckdb.sql( | ||
""" | ||
SELECT | ||
CAST(timestamp AS DATE) AS date, | ||
COUNT(*) AS n_liasses, | ||
( | ||
COUNT( | ||
CASE WHEN data.proba_1 > 0.8 THEN 1 END | ||
) * 100.0 / COUNT(*) | ||
) AS pct_high_proba | ||
FROM data | ||
GROUP BY CAST(timestamp AS DATE); | ||
""" | ||
).to_df() | ||
``` | ||
6. Constatez les changements apportés au tableau de bord. | ||
</details> | ||
5. Dans ArgoCD, ouvrez votre application puis cliquez sur votre pod qui doit commencer par `"codification-api-..."`. Observez les logs. | ||
::: | ||
:::: | ||
::: |
Oops, something went wrong.