# TP02 - Comparer et tracer des experimentations ML (DVC + MLflow)

Fil rouge : prediction de la consommation electrique. Ce module compare des strategies
de features et de split, en versionnant les datasets avec **DVC** (remote S3 = Garage de la VM)
et en tracant les experiences avec **MLflow** (serveur de la VM).

## Prerequis (sur la VM)

- venv : `/opt/venvs/mlops`
- donnees source : `/data/modelling/features.parquet` + `target.parquet`
- `.env` renseigne (voir `.env.example`), puis :

```bash
cd /home/user/tp
set -a; source .env; set +a
alias py=/opt/venvs/mlops/bin/python
alias dvc=/opt/venvs/mlops/bin/dvc
```

## Package

- `lab/constants.py` : strategies de split (`full_history`, `recent_history`), strategies de
  features (`short_memory`, `seasonality`, `tendency`, `mixed`, `full`), `RIDGE_ALPHAS`.
- `lab/split/cli.py` : lit `/data/modelling`, ecrit `data/{train,validation,test}.parquet`
  selon `CHOSEN_SPLIT_STRATEGY`.
- `lab/modeling/cli.py` : `py -m lab.modeling.cli <strategy>` -> regression lineaire -> MLflow.
- `lab/modeling_ridge/cli.py` : `py -m lab.modeling_ridge.cli [--strategy <s>]` -> Ridge sur `RIDGE_ALPHAS`.

## Versionner un dataset avec DVC

```bash
py -m lab.split.cli
dvc add data/train.parquet data/validation.parquet data/test.parquet
git add data/*.dvc data/.gitignore lab .gitignore
git commit -m "split <strategie>"
git tag dataset-<version>
dvc push
```

Restaurer une version anterieure du dataset :

```bash
git checkout dataset-v1-full-history -- data/train.parquet.dvc data/validation.parquet.dvc data/test.parquet.dvc
dvc checkout
```

## Entrainements

```bash
for s in short_memory seasonality tendency mixed; do py -m lab.modeling.cli $s; done   # Parties 1 et 2
py -m lab.modeling_ridge.cli --strategy mixed                                          # Partie 3
```

Resultats et comparaisons : https://mlflow.192-168-122-143.nip.io (experience `tp02_electricity_consumption`).

## Livrable

Synthese des resultats et reponses aux questions : `SYNTHESE.md`.

---

# TP03 - Exposer un modele via une API REST (Model Registry + FastAPI)

Prolonge le TP02 : on enregistre le meilleur modele dans le **MLflow Model Registry**, on le
**promeut via un alias**, puis on l'expose par une **API REST FastAPI**.

## Prerequis (en plus du TP02)

`.env` complete avec les creds S3 Garage (voir `.env.example`) : `AWS_ACCESS_KEY_ID`,
`AWS_SECRET_ACCESS_KEY`, `MLFLOW_S3_ENDPOINT_URL`. Necessaires pour `log_model` (upload de
l'artefact) et pour le chargement du modele par l'API (download depuis `s3://mlflow-artifacts`).

## Enregistrer et promouvoir (Partie 1)

```bash
set -a; source .env; set +a
py -m lab.modeling.cli full  --register     # v1 -> Registry (champion vise)
py -m lab.modeling.cli mixed --register      # v2 -> Registry (comparaison)
py -m lab.registry.cli versions              # lister versions + alias
py -m lab.registry.cli promote --version 1 --alias champion
```

`log_model` est appele a **chaque** run (artefact sauvegarde) ; `--register` empile en plus une
version dans le Registry sous le nom `electricity-consumption`.

## Servir l'API (Parties 2 a 4)

```bash
./serve.sh                                    # uvicorn 0.0.0.0:8000, charge models:/...@champion
curl -s localhost:8000/health                 # {"status":"ok"}
curl -s -X POST localhost:8000/predict \
     -H 'content-type: application/json' -d '{"client_id":"MT_124"}'
curl -s -X POST localhost:8000/predict/batch \
     -H 'content-type: application/json' -d '{"client_ids":["MT_124","MT_158"]}'
```

- Endpoints : `GET /health`, `POST /predict`, `POST /predict/batch`, Swagger `GET /docs`.
- Feature store **simule** par un dictionnaire (`lab/serving/features.py`) ; client inconnu -> **404**.
- Depuis le poste (cert ENI de confiance) : **https://api.192-168-122-143.nip.io/docs**
  (reverse-proxy Caddy vers uvicorn). Unite systemd transitoire : `sudo systemctl status tp03-api`.

## Livrable TP03

Reponses aux questions et recap : `SYNTHESE_TP03.md`.

---

# TP04 - Automatiser le pipeline avec la CI/CD (pipeline.py + Forgejo Actions)

Prolonge les TP precedents : les etapes manuelles (split -> entrainement -> enregistrement/promotion
Registry) sont orchestrees en une seule commande, puis rejouees automatiquement en CI.

## Pipeline (Parties 2-3)

`pipeline.py` (racine) enchaine, via des sous-processus (`check=True`, arret au premier echec) :

```bash
set -a; source .env; set +a
python pipeline.py     # split -> train full --register -> promote champion
```

- 1. `lab.split.cli` : (re)cree `data/{train,validation,test}.parquet` (deterministe) ;
- 2. `lab.modeling.cli full --register` : entraine + `log_model` + nouvelle version au Registry ;
- 3. `lab.registry.cli promote` : repointe l'alias `champion` sur cette version.

`requirements.txt` fige les dependances runtime (env de reference de la VM, Python 3.14).

## CI/CD (Partie 4)

`.forgejo/workflows/pipeline.yml` : declenche sur **pull_request vers `main`**, installe les
dependances puis lance `pipeline.py`. Execute par les runners du **Forgejo de la VM**
(`forgejo.192-168-122-143.nip.io`), mode docker sur `mlops-net` (les donnees `/data/modelling` et la
CA du host sont montees en lecture seule). Secrets (MLflow + S3 Garage) dans les secrets Actions du repo.

Livrable : `SYNTHESE_TP04.md`.
