Aller au contenu principal
William Balance
← Retour au blog

Pourquoi (et comment) intégrer un LLM dans une app SaaS

Publié le 1 avril 2026 · 4 min de lecture
  • LLM
  • SaaS
  • TypeScript
  • Claude
  • Intégration

“On voudrait mettre de l’IA dans notre app.” Je reçois cette demande chaque semaine. La plupart du temps, ce que le client veut vraiment, c’est résoudre un problème métier concret — pas coller un chatbot dans un coin. Voici comment je tranche.

Pourquoi le faire maintenant

Trois raisons, pas une de plus :

  • Gagner du temps utilisateur. Résumer, classer, extraire, reformuler. Des tâches qu’ils font à la main aujourd’hui.
  • Débloquer des cas d’usage nouveaux. Recherche sémantique, assistant contextuel, génération de brouillons. Infaisable il y a trois ans.
  • Tenir la comparaison. Tes concurrents l’ont déjà intégré. Six mois de retard, c’est un an à rattraper.

En revanche, un chatbot générique planté dans un coin de l’UI n’est pas une stratégie. C’est de la friction sans valeur.

Les trois cas d’usage qui marchent

Sur mes projets, ce sont les seuls qui produisent un ROI mesurable.

Transformation de texte ciblée

L’utilisateur a un texte, il en veut un autre. Résumé de ticket, reformulation d’email, extraction depuis un PDF. Invocation à la demande, contexte clair, sortie structurée. Simple, rentable.

Recherche et Q&A sur tes données

Question en langage naturel, réponse basée sur les données du compte. C’est du RAG. Utile pour la doc interne, les bases de connaissance, les archives de tickets. À ne pas confondre avec “un chatbot sur le site”.

Génération structurée assistée

L’utilisateur veut créer un objet métier : produit, campagne, template. Le LLM pré-remplit à partir d’un brief court. L’humain corrige. Taux d’acceptation mesuré, pas d’automatisation aveugle.

Architecture minimale

La structure que je déploie en premier sur un projet Next.js ou Hono :

// app/api/llm/summarize/route.ts
import Anthropic from "@anthropic-ai/sdk";

const client = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });

export async function POST(req: Request) {
  const { text, userId } = await req.json();

  // 1. Quotas par utilisateur
  const allowed = await checkQuota(userId);
  if (!allowed) {
    return Response.json({ error: "quota_exceeded" }, { status: 429 });
  }

  // 2. Appel LLM avec system prompt versionné
  const response = await client.messages.create({
    model: "claude-sonnet-4-5",
    max_tokens: 1024,
    system: SUMMARIZE_SYSTEM_PROMPT,
    messages: [{ role: "user", content: text }],
  });

  // 3. Log usage pour le pricing interne
  await logUsage(userId, response.usage);

  const summary = response.content[0].type === "text"
    ? response.content[0].text
    : "";

  return Response.json({ summary });
}

Quatre points non négociables :

  1. Quotas par utilisateur. Sinon un seul client vide ton compte en une nuit. Je l’ai vu.
  2. System prompt versionné. Tu le changeras dix fois le premier mois.
  3. Logging d’usage. Tokens, coût, latence. Sans ça, tu pilotes à l’aveugle.
  4. Gestion d’erreur propre. Retry avec backoff, fallback provider. Les 500 d’Anthropic existent.

Les pièges classiques

Tout streamer sans réfléchir

Le streaming est utile sur les réponses longues interactives. Inutile sur une extraction structurée de 200 ms. Choisis en fonction de l’UX, pas de la mode.

Oublier le cache

Deux utilisateurs, même question, même document. Payer deux fois n’a aucun sens. Un cache Redis avec clé hash(prompt + contexte) coupe 30 à 70 % des coûts sur les features répétitives.

Ignorer la latence perçue

Un LLM met 2 à 10 secondes. Sans skeleton ni streaming, tes utilisateurs pensent que l’app est cassée. Teste en 4G, pas sur ta fibre.

Se coder contre un seul provider

Je branche Claude et OpenAI derrière la même interface dès le jour 1. Quand un provider est down (ça arrive) ou triple ses prix (ça arrive aussi), je switche en une variable d’env.

interface LLMProvider {
  complete(prompt: string, opts: CompleteOpts): Promise<string>;
}

class ClaudeProvider implements LLMProvider { /* ... */ }
class OpenAIProvider implements LLMProvider { /* ... */ }

const llm: LLMProvider = pickProvider(process.env.LLM_PROVIDER);

Le vrai sujet : les coûts

Une feature LLM qui marche techniquement peut ruiner ton unit economics. Avant la prod :

  • Estime le nombre d’appels par utilisateur et par jour.
  • Multiplie par le coût moyen (tokens input + output).
  • Compare à ta marge par utilisateur.

Au-dessus de 20 à 30 % de la marge, il faut trancher : cache, modèle plus petit sur les cas simples, rate limit par plan, facturation à l’usage. Je préfère un plan “IA en option payante” plutôt que de diluer la marge du plan standard — c’est plus honnête pour le client et pour la boîte.

Par où commencer

Mon protocole en 2 à 4 semaines :

  1. Semaine 1. Un cas d’usage qui remplace une action manuelle claire. Pas “un chatbot”, mais “résumer automatiquement les rapports hebdo”.
  2. Semaine 2. Prototype local, itération sur le prompt, 10 à 20 cas réels.
  3. Semaine 3. Intégration avec quotas, logs, fallback provider.
  4. Semaine 4. Mise en prod derrière un feature flag, rollout progressif.

C’est le cadre que j’utilise pour livrer des intégrations LLM sur du SaaS B2B européen en moins d’un mois, sans exploser les coûts. Si tu as un cas concret, on en parle sur un appel de 30 minutes.

Un projet en tête ?

30 minutes gratuites pour en discuter, IA ou full-stack.