Lección 6 — Exploiter

Métadonnées, coûts, nettoyage

6 min de lectura

Este contenido aún no está traducido. Se muestra la versión original.

Trois mois après la mise en place, l'audit interne d'Assurances Ventoux demande pour la version en production : quel jeu, quel score, quelle exécution, qui l'a déclenchée. La réponse est dans ML Metadata, à condition de ne pas l'avoir effacée en nettoyant. À l'inverse, un projet de test qui garde des centaines d'exécutions, d'artefacts et un TensorBoard oublié coûte et encombre. Il faut savoir ce que le pipeline laisse derrière lui, ce qui se paie, et comment tout retirer avec preuve.

Le mécanisme

Chaque exécution laisse quatre types de traces dans Vertex AI, plus les fichiers du bucket :

RessourceCréée parContenuFacturé
PipelineJobjob.submit()paramètres, état des tâches, labels0,03 $ par exécution
Contexte ML Metadatachaque exécution, chaque expérience, chaque run d'expérienceregroupement logiquenon (stockage de métadonnées)
Artefact ML Metadatachaque Output[...]URI, métadonnées (accuracy, fingerprint…)non
Exécution ML Metadatachaque tâcheentrées, sorties, étatnon
CustomJobchaque tâche démarréela machineau temps machine
Objets Cloud Storagecloud-up, racine du pipelinedonnées, registre, artefactsau stockage
flowchart LR
  E["Contexte<br/>expérience lab-vertex-ai-pipelines"] --> R1["Contexte<br/>run local-v2"]
  E --> R2["Contexte<br/>run local-v1"]
  E --> PJ["Contexte<br/>exécution prompt-gate-20261016151726"]
  PJ --> X1["Exécution<br/>prepare-dataset"]
  PJ --> X2["Exécution<br/>load-production"]
  X1 -.-> A1["Artefact<br/>dataset (empreinte)"]
  BK[("Bucket gs://…-lab-vertex-ai-pipelines")]

Le nettoyage du lab procède dans l'ordre inverse de la création : exécutions, artefacts, exécutions ML Metadata, contextes, expérience en dernier, puis le bucket. Il identifie ce qui appartient au lab par le label formation-lab=vertex-ai-pipelines (jobs, bucket) et par le préfixe lab-vertex-ai-pipelines (contextes, dont le filtre de l'API ne fait pas de « commence par » : run.py filtre côté client).

La mise en œuvre

make cloud-status PROJECT=mon-projet   # ce qui existe encore
make cloud-down PROJECT=mon-projet     # supprime tout, puis échoue si quelque chose subsiste
files/run.py (extrait de cleanup)
jobs, contexts, artifacts, executions = lab_resources()
# Les expériences en dernier : leur suppression emporte leurs runs, déjà traités ici.
contexts.sort(key=lambda c: c.schema_title == "system.Experiment")
for r in [*jobs, *artifacts, *executions, *contexts]:
    try:
        if getattr(r, "schema_title", "") == "system.Experiment":
            aiplatform.Experiment(r.name).delete()
        else:
            r.delete()
    except NotFound:  # déjà supprimé en cascade (contexte d'un job supprimé, par exemple)
        pass

La cible cloud-down se termine par run.py status --strict, qui renvoie un code non nul si un seul job, contexte, artefact ou exécution du lab subsiste, et par une vérification que plus aucun bucket ne porte le label.

Coûts mesurés et estimés

PosteMesure du 2026-10-16Ordre de grandeur pour une exécution Vertex complète
Gemini 2.5 Flash38 appels, 19 374 tokens (make run)identique : moins d'un centime
Frais Vertex AI Pipelines1 exécution soumise0,03 $ par exécution
Machinesaucune (quota)6 tâches de 1 à 3 minutes sur e2-standard-4 à environ 0,15 $/h : quelques centimes
Stockage2 objets, quelques Konégligeable

Pour 400 tickets de référence au lieu de 19, le poste Gemini passe à quelques dizaines de centimes par exécution ; c'est lui qui domine, pas l'orchestration.

Résultat obtenu (2026-10-16)

État avant nettoyage, puis make cloud-down :

$ make cloud-status PROJECT=<projet>
Bucket :
<projet>-lab-vertex-ai-pipelines
Vertex AI :
  PipelineJob  1
  Context      7
  Artifact     1
  Execution    3
$ make cloud-down PROJECT=<projet>
Supprimés : 1 exécutions, 7 contextes, 1 artefacts, 3 exécutions ML Metadata
Removing gs://<projet>-lab-vertex-ai-pipelines/data/reference.jsonl#1792156634460218...
Removing gs://<projet>-lab-vertex-ai-pipelines/registry/production.json#1792156637227920...
Removing gs://<projet>-lab-vertex-ai-pipelines/...
  PipelineJob  0
  Context      0
  Artifact     0
  Execution    0
Vérifié : plus aucune ressource du lab.

Vérification indépendante, avec d'autres outils que ceux du lab :

$ gcloud storage ls gs://<projet>-lab-vertex-ai-pipelines
ERROR: (gcloud.storage.ls) gs://<projet>-lab-vertex-ai-pipelines not found: 404.
$ curl ... /pipelineJobs?filter=labels.formation-lab="vertex-ai-pipelines"
{}
$ curl ... /schedules
{}
$ gcloud ai tensorboards list --region europe-west1
Listed 0 items.

Les 7 contextes : l'expérience, quatre runs d'expérience issus de deux make run, et deux contextes créés par l'exécution Vertex.

Ce qui casse en production

  • TensorBoard créé sans le vouloir. aiplatform.init(experiment=...) peut créer une instance TensorBoard de sauvegarde, facturée au stockage, que la suppression de l'expérience laisse en place. Parade : experiment_tensorboard=False, et gcloud ai tensorboards list dans les vérifications.
  • Nettoyer la production avec le lab. Un filtre trop large (startswith("lab")) supprimerait le lignage d'autres équipes. Parade : préfixe complet du lab et label dédié ; en production, une politique de rétention plutôt qu'une suppression.
  • Suppression partielle silencieuse. Une erreur à mi-chemin laisse des contextes orphelins que plus personne ne liste. Parade : la vérification stricte en fin de cloud-down, qui échoue tant qu'il reste quelque chose.
  • Bucket versionné ou verrouillé. Une politique de rétention empêche la suppression des objets. Parade : cloud-up crée un bucket sans rétention ; sur un bucket existant, vérifiez gcloud storage buckets describe avant de l'utiliser comme racine.

La règle de décision

En production, gardez le lignage : c'est votre preuve d'audit, et son stockage ne coûte presque rien. Dans un projet de test, supprimez tout à la fin et vérifiez par un outil indépendant. Le poste de coût à surveiller est l'évaluation par le modèle, proportionnelle à la taille du jeu et au nombre d'exécutions, pas l'orchestration.

Pratique

make cloud-down affiche « Supprimés : 1 exécutions, 7 contextes… » puis échoue sur la vérification stricte avec Context 1. Que faites-vous ?

Votre directeur financier s'inquiète du coût de Vertex AI Pipelines si l'on passe à une exécution par fusion, soit environ 60 par mois, avec un jeu de 400 tickets. Quel poste regardez-vous en premier ?

Exercice. Ajoutez à run.py status le décompte des planifications du lab (aiplatform.PipelineJobSchedule.list) pour que make cloud-down échoue si une planification subsiste.

Voir la solution

Dans lab_resources() :

schedules = [s for s in aiplatform.PipelineJobSchedule.list()
             if s.display_name.startswith(f"lab-{SLUG}")]
return jobs, contexts, artifacts, executions, schedules

puis ajoutez "Schedule" aux noms de status() et *schedules en tête de la liste supprimée par cleanup() : une planification active recréerait des exécutions pendant le nettoyage. C'est pourquoi elle se supprime en premier.

  • Je sais ce qu'une exécution laisse dans Vertex AI et dans Cloud Storage.
  • Je supprime dans l'ordre inverse de la création, avec un nettoyage relançable.
  • Je termine par une vérification qui échoue s'il reste une ressource, et par un outil indépendant.
  • Je chiffre une exécution, et je sais que le poste Gemini domine.