Skip to content

Commit

Permalink
move 5a to 3
Browse files Browse the repository at this point in the history
  • Loading branch information
avouacr committed Dec 14, 2023
1 parent 8af95f1 commit de334bb
Show file tree
Hide file tree
Showing 5 changed files with 188 additions and 185 deletions.
89 changes: 86 additions & 3 deletions slides/fr/applications/_application3.qmd
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

::::{.callout-tip collapse="true" icon=false}
## Exposer localement un modèle de ML en tant qu'API
## Partie 1 : exposer localement un modèle de ML en tant qu'API

:::::{.nonincremental}

Expand All @@ -25,7 +25,7 @@ uvicorn app.main:app
## Application 3 {.scrollable}

::::{.callout-tip collapse="true" icon=false}
## Déploiement manuel d'un modèle de ML en tant qu'API
## Partie 2 : déploiement manuel d'un modèle de ML en tant qu'API

:::::{.nonincremental}

Expand Down Expand Up @@ -85,7 +85,7 @@ kubectl apply -f formation-mlops/kubernetes/
## Application 3 {.scrollable}

::::{.callout-tip collapse="true" icon=false}
## Déploiement continu d'un modèle de ML en tant qu'API
## Partie 3 : déploiement continu d'un modèle de ML en tant qu'API

:::::{.nonincremental}

Expand Down Expand Up @@ -135,3 +135,86 @@ spec:

:::::
::::





## Application 3 {.scrollable}

::::{.callout-tip collapse="true" icon=false}
## Partie 4 : requêter votre modèle déployé

:::::{.nonincremental}

1. Créez un fichier `predict_api.py`. Ce script doit :
- Lire le fichier parquet disponible à l'adresse suivante :

```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>
</summary>

```{.python filename="predict_api.py"}
import pandas as pd
import requests
# 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()
# URL des données
data_path = "https://minio.lab.sspcloud.fr/projet-formation/diffusion/mlops/data/data_to_classify.parquet"
# Charge le fichier Parquet dans un DataFrame pandas
df = pd.read_parquet(data_path)
# Votre API URL
api_url = "https://<your_firstname>-<your_lastname>-api.lab.sspcloud.fr/predict"
# Effectue les requêtes
responses = df["text"].apply(lambda x: make_prediction(api_url, x))
# 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>

2. 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
```
</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.
::::
:::
95 changes: 52 additions & 43 deletions slides/fr/applications/_application5a.qmd
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.

::::
:::
108 changes: 48 additions & 60 deletions slides/fr/applications/_application5b.qmd
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.
:::
::::
:::
Loading

0 comments on commit de334bb

Please sign in to comment.