Lesson 5 — Réduire les coûts sans perdre en qualité

Batch, compression de prompts et budget par requête

6 min read

This content is not translated yet. Showing the original version.

Batch, compression de prompts et budget par requête

L'API Batch : moitié prix, mais pas tout de suite

L'API Batch de Gemini traite un lot de requêtes de façon asynchrone : vous soumettez, vous revenez chercher le résultat plus tard (l'objectif annoncé est 24 h, souvent beaucoup moins). En échange, le prix est divisé par deux (flash-lite : 0,15 aulieude0,30au lieu de 0,30 par million de tokens d'entrée, relevé le 2026-10-15).

flowchart LR
  subgraph TR["Temps réel"]
    U["Client au chat"] --> A["generate_content : < 2 s, plein tarif"]
  end
  subgraph BA["Différé"]
    N["Tâche de nuit : résumer 10 000 tickets"] --> J["batches.create : -50 %"]
    J --> W["attente : minutes à heures"]
    W --> RES["résultats"]
  end
ChargeTemps réelBatch
Réponse au client dans le chatouinon
Classer les tickets de la veillepossibleoui
Générer des réponses types pour la FAQpossibleoui
Évaluer un nouveau prompt sur 500 questionspossibleoui
Pré-remplir un cache sémantiquepossibleoui
files/extras.py (extrait)
job = client.batches.create(model=R.SMALL_MODEL, src=reqs, config={"display_name": "lab-perf-batch"})
while job.state.name not in ("JOB_STATE_SUCCEEDED", "JOB_STATE_FAILED", "JOB_STATE_CANCELLED",
                             "JOB_STATE_EXPIRED") and time.time() - t0 < 900:
    time.sleep(20)
    job = client.batches.get(name=job.name)
for r in job.dest.inlined_responses:
    print(r.response.text)

La compression de prompt : mesurer avant de couper

Chaque token d'entrée est payé à chaque requête. Deux familles de compression :

TechniqueExempleRisque
Compaction sans perteretirer puces, titres, espacesquasi nul
Sélection de contexten'envoyer que la section utile de la FAQ (via embeddings, c'est du RAG)rater la section qui contenait la réponse
Compression apprise (LLMLingua et apparentés)un petit modèle supprime les tokens peu informatifsperte de sens, à évaluer
files/extras.py (extrait)
variants = {
    "FAQ complète (markdown)": R.SYSTEM,
    "FAQ complète compactée": base + "\n" + compact(R.KB),
    "Section « Livraison » seule": base + "\n" + sections(R.KB)["Livraison"],
}
for name, text in variants.items():
    n = client.models.count_tokens(model=R.SMALL_MODEL, contents=text).total_tokens

La compaction de la FAQ fait gagner 4 % de tokens, la sélection de la seule section utile 74 %. Pourquoi ne pas toujours sélectionner ?

Un budget par requête

Un budget par requête borne ce qu'une seule question peut coûter : max_output_tokens, nombre d'étapes d'un agent, et dans notre routeur, le droit d'escalader.

files/router.py (extrait)
# Coût estimé du grand modèle : mêmes tokens, sortie doublée par prudence.
big_estimate = cost_usd(BIG_MODEL, small.prompt_tokens, small.cached_tokens, 2 * small.output_tokens)
if small.confidence < self.conf_min and small.cost + big_estimate <= self.max_cost:
    big = await ask(self.client, BIG_MODEL, question)

Avec MAX_COST_USD=0.01, une question de FAQ (environ 0,0004 enflash−liteet0,001en flash-lite et 0,001 en flash) passe largement. Le budget mord sur les cas anormaux : un prompt gonflé par un document de 200 000 tokens collé par l'utilisateur ne déclenchera pas, en plus, un appel au grand modèle.

Pourquoi le routeur estime-t-il le coût du grand modèle AVANT de l'appeler, au lieu de le mesurer après ?

Exercice

Les 16 questions du banc coûtent 0,00683 $ en flash-lite temps réel. Estimez le coût du même lot en Batch, puis dites pour quelles questions de Lumen & Co le Batch serait acceptable.

Voir la solution

Le Batch divise par deux les prix d'entrée et de sortie : environ 0,0034 $ pour le lot (16 503 × 0,15 + 753 × 1,25, divisé par un million).

Acceptable : aucune des questions du chat (un client attend). En revanche, on peut utiliser le Batch pour pré-calculer les réponses aux 50 questions les plus fréquentes chaque nuit, à moitié prix, et les charger dans le cache sémantique : le jour, ces questions coûtent 0 en LLM. C'est le même modèle, moins cher, et plus rapide pour l'utilisateur.

Résultat obtenu

Exécutions réelles du 2026-10-15 :

$ python extras.py tokens
FAQ complète (markdown)          1014 tokens
FAQ complète compactée            972 tokens
Section « Livraison » seule       266 tokens

$ python extras.py batch
état=JOB_STATE_SUCCEEDED après 143 s
-> Oui, nous livrons en Belgique pour un montant de 12,00 €, avec un délai de 5 à 8 jours ouvrés (cette livraison n'est jam
-> Les ampoules LED sont garanties 3 ans, sur présentation de la facture.

Le lot de 2 requêtes a été traité en 2 min 23 s : acceptable pour une tâche de nuit, rédhibitoire pour un chat.

Je sais faire

  • Choisir entre temps réel et Batch selon l'urgence
  • Soumettre un lot et récupérer ses résultats
  • Mesurer un gain de compression avec count_tokens avant de couper
  • Borner le coût d'une requête avant d'engager la dépense
Next