Aller au contenu principal

Module 10 — Modèles de fondation et jardin de modèles

Les neuf premiers modules ont construit un modèle tabulaire de bout en bout. Mais chaque transaction bloquée par la fraude déclenche un commentaire écrit par le client au support : « Je n'ai jamais fait ce paiement », « C'est bien moi, la carte fonctionne mal ». Ces textes ne se coulent dans aucune variable. C'est le terrain naturel d'un modèle de fondation, et Vertex en propose un catalogue entier via le Model Garden.

Le Model Garden en un tour

Le Model Garden est une vitrine dans la console Vertex. On y trouve :

  • Les modèles Gemini de Google (gemini-2.5-pro, gemini-2.5-flash) : texte, code, vision, audio.
  • Les modèles Anthropic (claude-opus-4) et Meta (llama-4), accessibles par une même API Vertex.
  • Des modèles spécialisés : Imagen pour la génération d'images, Chirp pour la parole, Codey pour le code.
  • Des modèles ouverts (gemma, mistral) préconfigurés pour un déploiement en un clic.

L'unification est le point clé : quel que soit le modèle, on l'appelle par la même API google-cloud-aiplatform, on le facture sur la même ligne, on le journalise dans les mêmes traces. Passer de Gemini à Claude est une ligne de configuration, pas une intégration nouvelle.

Le premier appel

Pour classifier un commentaire de litige, Gemini Flash suffit :

from vertexai.generative_models import GenerativeModel
import vertexai

vertexai.init(project="paiement-fraude-prod", location="europe-west1")
modele = GenerativeModel("gemini-2.5-flash")

CONSIGNE = """Tu es un analyste antifraude. Classe le commentaire client suivant dans une catégorie :
- FRAUDE_AVEREE : le client dit qu'il n'a pas fait la transaction
- REFUS_LEGITIME : la transaction est du client mais il conteste le motif du blocage
- SIMPLE_QUESTION : demande d'information, pas de contestation
Réponds uniquement par la catégorie, en un seul mot."""

reponse = modele.generate_content(
[CONSIGNE, "Commentaire : Cette transaction n'est pas moi, ma carte a été volée ce matin."],
generation_config={"temperature": 0.0, "max_output_tokens": 8},
)
print(reponse.text) # FRAUDE_AVEREE

Trois détails opérationnels. La température à 0 rend la sortie déterministe — indispensable pour un classifieur en production. La limite max_output_tokens=8 évite qu'une réponse verbeuse consomme des jetons inutiles. Enfin, le prompt système est envoyé à chaque appel : c'est le prix d'une architecture sans état.

Consignes structurées et sortie contrainte

Un modèle qui « répond en un seul mot » finit tôt ou tard par ajouter un point ou une phrase d'explication. La bonne approche est de contraindre la sortie par un schéma JSON :

reponse = modele.generate_content(
[CONSIGNE, "Commentaire : ..."],
generation_config={
"temperature": 0.0,
"response_mime_type": "application/json",
"response_schema": {
"type": "object",
"properties": {
"categorie": {"type": "string", "enum": ["FRAUDE_AVEREE", "REFUS_LEGITIME", "SIMPLE_QUESTION"]},
"confiance": {"type": "number", "minimum": 0, "maximum": 1},
},
"required": ["categorie", "confiance"],
},
},
)
donnees = json.loads(reponse.text) # {"categorie": "FRAUDE_AVEREE", "confiance": 0.92}

Vertex garantit que la sortie respecte le schéma. Aucun try/except pour parser du texte libre, aucun risque qu'une virgule cassée fasse tomber l'API aval.

L'affinage géré

Sur mille commentaires étiquetés par l'équipe conformité, on peut affiner Gemini Flash pour améliorer la précision sur notre vocabulaire métier. Vertex expose un affinage supervisé géré, sans écrire de boucle d'entraînement :

from vertexai.tuning import sft

job = sft.train(
source_model="gemini-2.5-flash-001",
train_dataset="gs://paiement-fraude-donnees/litige/train.jsonl",
validation_dataset="gs://paiement-fraude-donnees/litige/valid.jsonl",
epochs=3,
learning_rate_multiplier=1.0,
adapter_size=8, # LoRA rang 8
tuned_model_display_name="gemini-flash-fraude-litige",
)

Le jeu d'entraînement est au format JSONL, une ligne par exemple :

{"contents": [{"role": "user", "parts": [{"text": "Commentaire : cette transaction n'est pas moi..."}]}, {"role": "model", "parts": [{"text": "FRAUDE_AVEREE"}]}]}

L'affinage tourne quelques heures et produit un modèle affiné inscrit dans le Model Registry (module 6). On l'appelle ensuite comme n'importe quel modèle Vertex, avec la même API GenerativeModel(...).

adapter_size=8 active un affinage LoRA léger — quelques millions de paramètres seulement, pas le modèle complet. Le coût est de l'ordre de 50 $ pour mille exemples et trois époques, contre plusieurs milliers de dollars pour un affinage complet — sans gain de qualité prouvé pour un problème de classification simple.

Coût par jeton, à comprendre à l'avance

Les modèles de fondation ne se facturent pas au temps mais au jeton — l'unité de sous-mot vue par le modèle. Un jeton fait en moyenne 4 caractères en français ; « commentaire » vaut environ 3 jetons.

Tarifs indicatifs de Gemini Flash au moment de rédiger ce cours :

TypePrix par million de jetons
Entrée0,15 $
Sortie0,60 $

Le prompt de classification fait environ 100 jetons ; le commentaire, 30 à 80 ; la réponse, 5. Un appel coûte donc ~0,00003 $, soit 30 $ pour un million d'appels. À dix mille commentaires par jour, la facture mensuelle du modèle tourne autour de 9 $ — négligeable devant le coût de l'analyse humaine que le classifieur permet d'éviter.

Le calcul se retourne pour des cas verbeux. Une génération longue (rédiger un email de synthèse par ticket) monte vite : 2 000 jetons de sortie × 0,60 = 0,0012 $ par appel. À 10 000 appels/jour, on est à 360 $/mois — encore raisonnable, mais à surveiller. Toujours mesurer avant de brancher.

Compter les jetons avant l'appel

Le SDK expose count_tokens pour dimensionner à l'avance :

compte = modele.count_tokens([CONSIGNE, commentaire])
print(compte.total_tokens, compte.total_billable_characters)

C'est indispensable dans deux cas : quand on approche de la fenêtre de contexte (1 million de jetons pour Gemini Pro, à ne pas dépasser sans découpage), et quand on veut estimer la facture d'un batch avant de le lancer.

Batch et lot pour les fondations

Le module 8 s'applique aussi ici. Pour scorer les 300 000 commentaires en attente de l'année, un BatchPredictionJob sur un modèle Gemini est 60 % moins cher que l'appel individuel de chaque commentaire — Vertex regroupe les requêtes, l'infrastructure est mieux utilisée. C'est le même pattern que pour un modèle tabulaire.

La température à 0 n'est pas la reproductibilité

Même à temperature=0, deux appels identiques à Gemini peuvent renvoyer des sorties légèrement différentes : arithmétique flottante, changement de version de modèle côté Google, changement de partition GPU. Pour une reproductibilité totale, il faut journaliser la version exacte du modèle (gemini-2.5-flash-001, pas gemini-2.5-flash) et le prompt intégral. C'est la seule façon de rejouer un incident à l'identique six mois plus tard.

En résumé

  • Le Model Garden unifie Gemini, Claude, Llama, Imagen sous une même API et une même facturation Vertex.
  • La sortie contrainte par schéma JSON évite toute logique de parsing fragile en aval.
  • sft.train affine un modèle en LoRA sans boucle d'entraînement à écrire ; ~50 $ pour mille exemples.
  • La facturation est au jeton ; compter à l'avance avec count_tokens pour éviter les surprises.
  • Un batch de prédictions sur un modèle de fondation coûte 60 % de moins que les appels individuels.

Module suivant : la récapitulation du cours et l'examen de 40 questions.