Blog

Pourquoi Gemini pour peupler le Quiz HP (free tier)

  • hpq
  • gemini
  • adr
  • llm
  • api

Le joueur n'attend jamais le LLM — les questions sont générées en arrière-plan par un script CLI. Ce pivot change tout sur le choix du provider : la latence par requête devient secondaire, le quota journalier free tier devient dominant.

Articles précédents : vision · intégration · design system.

Critère de choix après le pivot « populate »

Au départ, on imagine une génération en direct : vitesse d'inférence = critère n°1. Depuis HPQ-001, le flux est :

  1. Script local ou cron appelle l'API
  2. Questions validées → Neon Postgres
  3. Le joueur pioche en base — zéro appel LLM en prod

Conséquence : combien de requêtes par jour pour remplir 24 combos film × difficulté, pas combien de millisecondes par token.

Chaque question consomme deux appels : génération + validation (double passe, détaillée dans un prochain article). Peupler 50 questions ≈ 100 appels minimum, plus les rejets et doublons.

Candidats comparés

  • Gemini Flash / Flash-Lite — volume free tier le plus généreux à l'écrit de l'ADR (~1500 req/jour annoncé) ; JSON structuré natif via responseSchema
  • Groq (Llama) — inférence ultra-rapide, pas d'entraînement sur tes données ; quota journalier inférieur (~1000 req/jour) ; vitesse devenue secondaire
  • Mistral — cap mensuel tokens élevé, privacy-first ; débit ~2 req/min en free tier → peuplement très lent même en batch

Écartés sans creuser : OpenRouter (agrégateur, pas de quota propre), Cerebras (doc JSON structuré faible).

Décision : Gemini Flash-Lite pour le populate.

JSON structuré dès le SDK

Plutôt que parser du markdown libre, j'utilise @google/generative-ai avec :

  • responseMimeType: application/json
  • responseSchema — objet avec statement (string), answer (boolean), sujet (string snake_case)

Le modèle est contraint à la forme. Les erreurs de format restent possibles, d'où la validation en seconde passe — mais le taux de parsing manual tombe quasi à zéro.

Modèle retenu et chaîne de repli

Modèle par défaut : gemini-3.1-flash-lite — bon compromis qualité / débit sur le free tier actuel.

En pratique (populate Film 1, juillet 2026), Google decoupe les quotas par modèle sur ai.dev/rate-limit :

  • 3.1 Flash Lite — ~500 req/jour → épuisé en une session de bootstrap
  • 2.5 Flash — ~20 req/jour — idem
  • 3 Flash Preview — ~20 req/jour — modèle de secours utile
  • 2.5 Flash Lite — souvent en 503 (surcharge)
  • Modèles 2.x « classiques » — quota à 0

D'où une chaîne de repli implémentée dans le code :

  1. gemini-3.1-flash-lite
  2. gemini-3-flash-preview
  3. gemini-2.5-flash-lite

Quand le quota journalier d'un modèle est atteint, le script bascule au suivant. Les alias corrigent les noms dashboard vs API (ex. gemini-3-flash → gemini-3-flash-preview).

Variable optionnelle : GEMINI_MODEL ou HPQ_GEMINI_MODEL — le modèle choisi reste en tête de chaîne, les autres servent de fallback.

Où tourne Gemini (et où il ne tourne pas)

  • Local — GEMINI_API_KEY dans .env.local pour npm run hpq:populate
  • Prod Vercel — pas de clé Gemini pour jouer ; seulement Neon
  • Futur cron — HPQ_GEMINI_API_KEY prévu pour repopulation automatique (pas urgent)

Le jeu en prod ne casse pas si Google change ses quotas : pire cas, le stock ne se regarnit plus jusqu'au prochain populate manuel.

Point privacy (accepté)

En free tier, Google peut utiliser les prompts pour l'entraînement. J'ai explicitement jugé ça acceptable : le contenu généré (questions Harry Potter publiques, grounding via fiches de faits) n'est pas sensible.

Pour du contenu confidentiel, ce ne serait pas le bon tier.

Risques assumés

  • Dépendance mono-provider — pas de fallback Groq/Mistral en v1 ; surveiller les changements de quota (Google a déjà réduit le free tier sans préavis par le past)
  • Qualité Flash vs Flash-Lite — Flash-Lite pour le volume ; qualité medium/hard calibrée côté prompts (article à part)
  • Bootstrap long — 150 questions × 2 passes ≈ 300+ appels : prévoir plusieurs jours ou plusieurs modèles en rotation

Ce que j'ai appris en peuplant

Le quota annoncé « 1500 req/jour » ne se lit pas comme un pool unique : c'est par modèle, avec des plafonds très différents. Un bootstrap agressif le même jour épuise tout.

Stratégie réaliste pour un MVP solo :

  • Lancer le populate le matin, modèle par modèle
  • Laisser le script top-up avec --target=50 (stock total visé, pas batch fixe)
  • Reprendre le lendemain si 429 quota journalier

Suite de la série

  • Stockage Neon et dédup sujet (article dédié)
  • Stratégie de repopulation (cron)
  • Format JSON et double passe de validation

Quiz : andrewchicout.dev.