Aller au contenu
Craft Solution Tech

J'ai buildé un SaaS IA sans savoir ce que mon LLM faisait vraiment

Luny-AI marchait, mais je n'avais aucune visibilité entre le prompt et le résultat. Ce que des traces, un coût par génération et un golden set m'auraient montré.

7 min de lecture

Illustration : un prompt utilisateur traverse un LLM puis quatre étapes — analyse du prompt, génération du layout, création des composants, assemblage et export — chacune chiffrée en millisecondes et en tokens, jusqu'à l'export Figma.
Ce que j'aurais voulu voir sur Luny-AI : chaque étape d'une génération, chronométrée et chiffrée.

En 2024, j'ai buildé Luny-AI, un SaaS qui permettait de générer des maquettes Figma exportables à partir d'un simple prompt. Tu décris ton interface, le LLM génère le design, tu l'exportes dans Figma.

Ça marchait. Les gens l'utilisaient. Mais il y avait un truc que je ne voyais pas du tout : ce qui se passait entre le prompt de l'utilisateur et le résultat final.

J'avais des logs basiques. Du Sentry pour les crashs. Mais côté LLM ? Rien. Et aujourd'hui, en creusant sur comment maîtriser les LLM, je réalise tout ce que je ratais.


Ce que je ne voyais pas

Pourquoi certaines générations prenaient 10 secondes et d'autres 3 ?

J'appelais l'API Claude, je recevais la réponse, je mesurais le temps total. Mais entre le prompt et la réponse, je n'avais aucune idée de ce qui se passait.

Est-ce que le modèle "réfléchissait" plus longtemps sur certains prompts ? Est-ce que c'était la complexité de la maquette demandée ? La longueur du prompt ? Un problème de latence côté API ?

Je ne pouvais pas répondre. J'avais un chrono global, pas un détail par étape.

Quel appel exactement avait une erreur ?

Quand ça plantait, Sentry me disait qu'il y avait une erreur. OK. Mais quand le LLM me répondait sans planter mais avec un résultat inutilisable — une maquette incohérente, un layout cassé, des composants mal placés — je n'avais rien.

Pas d'erreur HTTP. Pas de crash. Juste un résultat mauvais. Et aucun moyen de comprendre pourquoi le modèle avait produit ça plutôt qu'autre chose.

Combien coûtait chaque génération ?

Je savais combien je payais l'API Claude à la fin du mois. Mais je ne savais pas combien coûtait chaque génération individuellement. Est-ce qu'un prompt complexe ("génère-moi un dashboard avec 6 widgets, des graphiques et un sidebar") coûtait 10x plus qu'un simple ("génère un formulaire de login") ? Probablement. Mais je n'avais pas les chiffres.

Comment améliorer un résultat "pas terrible" ?

C'est le point qui me manquait le plus. Quand le LLM répondait mais que le résultat ne me satisfaisait pas, je retouchais le prompt à l'instinct. J'essayais une formulation, puis une autre, puis une autre. Sans métrique. Sans score. Sans savoir objectivement si la v2 de mon prompt était meilleure que la v1.


Ce que j'aurais pu voir

Aujourd'hui, je sais qu'il existe des outils et des patterns pour tout tracer. Voici ce que j'aurais pu mettre en place sur Luny-AI.

Des traces, pas juste des logs

Un log te dit "il s'est passé quelque chose". Une trace te dit l'histoire complète d'une requête, étape par étape.

Sur Luny-AI, une génération de maquette passait par plusieurs étapes logiques (analyse du prompt, structuration du layout, génération des composants, assemblage). Chaque étape aurait pu être un span dans une trace :

Génération maquette "dashboard analytics"
│
├─ Analyse du prompt          [120ms]
├─ Structuration du layout    [350ms, 800 tokens]
├─ Génération des composants  [1200ms, 2400 tokens]  ← le plus lent
├─ Assemblage final           [200ms, 600 tokens]
│
Total: 1870ms, 3800 tokens, ~$0.04

D'un coup, je verrais que la génération des composants prend 65% du temps. C'est là qu'il faut optimiser, pas ailleurs.

Un coût par génération

En taggant chaque appel API avec le nombre de tokens consommés, j'aurais pu voir :

Prompt "formulaire de login"      →  800 tokens  →  $0.008
Prompt "dashboard 6 widgets"      →  4200 tokens →  $0.042
Prompt "landing page complète"    →  6800 tokens →  $0.068

Et surtout, j'aurais pu voir les anomalies : un prompt simple qui consomme autant qu'un prompt complexe, ça signifie que le modèle boucle ou génère du bruit. C'est un signal qu'il faut changer le prompt.

Des métriques de qualité

C'est ce qui me manquait le plus. Quand le résultat "n'est pas bon", c'est subjectif. Avec des métriques, ça devient mesurable :

La réponse est du JSON valide ?              → oui/non
Tous les composants demandés sont présents ? → 4/6
Le layout respecte la structure demandée ?   → oui/non

C'est ce qu'on appelle un rubric score — une liste de critères vérifiables automatiquement. Pas besoin d'un humain pour noter chaque génération. Tu définis tes règles, tu scores automatiquement, et tu vois ton taux de réussite évoluer quand tu modifies ton prompt.

Un golden set pour itérer

Au lieu de tester à l'instinct, j'aurais pu créer 10-15 prompts de référence avec les résultats attendus. À chaque modification de prompt, je rejoue ces cas et je compare les scores. Si ça monte, le changement est bon. Si ça baisse, je rollback.

C'est l'équivalent des tests unitaires pour tes prompts. Pas sexy, mais ça évite les régressions.


Ce que j'ai appris

L'observabilité c'est pas juste des logs

Un log te dit "erreur à 14h23". Une trace te dit "le span de génération des composants a pris 4 secondes parce que le prompt contenait 6 descriptions de widgets imbriquées, ce qui a généré 4200 tokens et coûté $0.04".

La différence, c'est la profondeur. Le log te dit qu'il y a un problème. La trace te dit où, pourquoi, et combien ça coûte.

Chaque "réflexion" du LLM a un prix

Quand le modèle prend plus de temps, c'est souvent parce qu'il génère plus de tokens. Plus de tokens = plus cher. Si ton prompt est ambigu, le modèle "hésite" et produit plus de texte pour couvrir les cas possibles.

Un prompt précis et structuré → moins de tokens → plus rapide → moins cher. L'observabilité te montre cette corrélation en chiffres.

Le vrai gain c'est l'itération mesurée

Modifier un prompt à l'instinct, c'est comme debugger sans logs. Tu peux y arriver, mais c'est lent et aléatoire.

Avec des métriques (rubric score, temps de réponse, coût par génération, taux de résultats valides), chaque changement est mesurable. Tu sais si ta modification a amélioré les choses ou les a dégradées. Tu itères en 10 minutes au lieu de 2 heures.


Ce que je ferais différemment

Si je rebuildais Luny-AI aujourd'hui, voici ce que j'ajouterais dès le jour 1 :

Des traces par génération — chaque appel à Claude tagué avec le type de maquette, le nombre de tokens, le temps de réponse, le coût. Pas juste un log "appel réussi".

Un rubric score automatique — le JSON de sortie est valide ? les composants demandés sont tous là ? le layout est cohérent ? Scoré automatiquement sur chaque génération.

Un golden set de 15 prompts — les cas les plus fréquents et les plus edge. Rejoués à chaque changement de prompt pour vérifier que rien ne régresse.

Un dashboard simple — coût par jour, taux de résultats valides, temps moyen de génération. Pas un dashboard de la NASA, juste les 3-4 chiffres qui comptent.

De la sanitization dès le départ — uniquement si nécessaire


Le takeaway

J'ai buildé un produit IA qui marchait. Mais "ça marche" c'est pas suffisant quand tu ne vois pas ce qui se passe à l'intérieur.

L'observabilité, c'est pas un truc que tu ajoutes quand t'as le temps. C'est ce qui te permet de comprendre, d'améliorer, et de contrôler ce que fait ton LLM au lieu de croiser les doigts à chaque appel API.

Sujets abordés

  • IA
  • LLM
  • observabilité
  • SaaS

Dites-nous ce que vous cherchez à construire.

Nous écrire sur WhatsApp
Retour au blog