watch·ia
AccueilActusTutosGlossaireCette semaineTendancesSources
/
ACTUS
1 aoûtUn juge américain valide l'interdiction des applications 'nudify' au Minnesota malgré xAI·1 aoûtReddit envisage de rompre son accord avec Google pour ses AI Overviews·31 juil.OpenAI et Google renforcent les alertes sur les risques des outils IA autonomes·31 juil.Reddit maintient un procès DMCA contre un scraper malgré l'échec de Google·31 juil.L'Inde dépasse 345 millions de dollars de revenus applicatifs au T2 2026·31 juil.Anthropic révèle que son IA Claude a accédé à trois réseaux sans autorisation·31 juil.Google Earth retire en un jour un outil d'édition d'images par IA après des détournements·31 juil.Google Earth ajoute un générateur d'images IA avec filigrane SynthID·31 juil.Snapchat modifie ses algorithmes pour limiter les récompenses aux contenus Spotlight 100 % générés par IA·31 juil.Les majors musicales veulent exclure les morceaux 100 % générés par IA des classements·1 aoûtUn juge américain valide l'interdiction des applications 'nudify' au Minnesota malgré xAI·1 aoûtReddit envisage de rompre son accord avec Google pour ses AI Overviews·31 juil.OpenAI et Google renforcent les alertes sur les risques des outils IA autonomes·31 juil.Reddit maintient un procès DMCA contre un scraper malgré l'échec de Google·31 juil.L'Inde dépasse 345 millions de dollars de revenus applicatifs au T2 2026·31 juil.Anthropic révèle que son IA Claude a accédé à trois réseaux sans autorisation·31 juil.Google Earth retire en un jour un outil d'édition d'images par IA après des détournements·31 juil.Google Earth ajoute un générateur d'images IA avec filigrane SynthID·31 juil.Snapchat modifie ses algorithmes pour limiter les récompenses aux contenus Spotlight 100 % générés par IA·31 juil.Les majors musicales veulent exclure les morceaux 100 % générés par IA des classements·1 aoûtUn juge américain valide l'interdiction des applications 'nudify' au Minnesota malgré xAI·1 aoûtReddit envisage de rompre son accord avec Google pour ses AI Overviews·31 juil.OpenAI et Google renforcent les alertes sur les risques des outils IA autonomes·31 juil.Reddit maintient un procès DMCA contre un scraper malgré l'échec de Google·31 juil.L'Inde dépasse 345 millions de dollars de revenus applicatifs au T2 2026·31 juil.Anthropic révèle que son IA Claude a accédé à trois réseaux sans autorisation·31 juil.Google Earth retire en un jour un outil d'édition d'images par IA après des détournements·31 juil.Google Earth ajoute un générateur d'images IA avec filigrane SynthID·31 juil.Snapchat modifie ses algorithmes pour limiter les récompenses aux contenus Spotlight 100 % générés par IA·31 juil.Les majors musicales veulent exclure les morceaux 100 % générés par IA des classements·1 aoûtUn juge américain valide l'interdiction des applications 'nudify' au Minnesota malgré xAI·1 aoûtReddit envisage de rompre son accord avec Google pour ses AI Overviews·31 juil.OpenAI et Google renforcent les alertes sur les risques des outils IA autonomes·31 juil.Reddit maintient un procès DMCA contre un scraper malgré l'échec de Google·31 juil.L'Inde dépasse 345 millions de dollars de revenus applicatifs au T2 2026·31 juil.Anthropic révèle que son IA Claude a accédé à trois réseaux sans autorisation·31 juil.Google Earth retire en un jour un outil d'édition d'images par IA après des détournements·31 juil.Google Earth ajoute un générateur d'images IA avec filigrane SynthID·31 juil.Snapchat modifie ses algorithmes pour limiter les récompenses aux contenus Spotlight 100 % générés par IA·31 juil.Les majors musicales veulent exclure les morceaux 100 % générés par IA des classements·

Construire un chatbot en streaming sur son site avec une API IA

vendredi 10 juillet 202613:364 min de lecture
L'essentiel — 3 points
  • 01Le streaming affiche la réponse au fur et à mesure : perçu comme bien plus rapide qu'une réponse d'un bloc
  • 02La clé API reste côté serveur : le client parle à TA route, jamais directement au fournisseur
  • 03Côté client, on lit le corps de la réponse comme un flux et on concatène les morceaux
API

Une réponse LLM qui apparaît d'un bloc après 5 secondes de vide donne une impression de lenteur. En streaming, le texte s'affiche token par token dès les premiers mots. À la fin de ce tuto, tu auras un chatbot qui répond en direct, avec la clé API bien planquée côté serveur. Exemple en Next.js (App Router), transposable à tout framework.

Étape 1 — Le principe

Le client ne parle jamais directement au fournisseur (sinon ta clé API fuite dans le navigateur). Le flux est :

Navigateur → TA route serveur → API du LLM (en streaming)
           ← flux relayé      ←

Ta route reçoit le message, appelle le LLM en mode stream, et relaie les morceaux au navigateur au fur et à mesure.

Étape 2 — La route serveur qui relaie le flux

// app/api/chat/route.ts
export async function POST(req: Request) {
  const { message } = await req.json();

  const upstream = await fetch("https://api.mistral.ai/v1/chat/completions", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${process.env.MISTRAL_API_KEY}`,
    },
    body: JSON.stringify({
      model: "mistral-small-latest",
      messages: [{ role: "user", content: message }],
      stream: true,
    }),
  });

  const encoder = new TextEncoder();
  const stream = new ReadableStream({
    async start(controller) {
      const reader = upstream.body!.getReader();
      const decoder = new TextDecoder();
      let buffer = "";
      while (true) {
        const { done, value } = await reader.read();
        if (done) break;
        buffer += decoder.decode(value, { stream: true });
        // Le flux arrive en lignes "data: {...}"
        for (const line of buffer.split("\n")) {
          const trimmed = line.trim();
          if (!trimmed.startsWith("data:")) continue;
          const payload = trimmed.slice(5).trim();
          if (payload === "[DONE]") { controller.close(); return; }
          try {
            const delta = JSON.parse(payload).choices[0]?.delta?.content;
            if (delta) controller.enqueue(encoder.encode(delta));
          } catch { /* ligne partielle, on attend la suite */ }
        }
        buffer = buffer.slice(buffer.lastIndexOf("\n") + 1);
      }
      controller.close();
    },
  });

  return new Response(stream, {
    headers: { "Content-Type": "text/plain; charset=utf-8" },
  });
}

On extrait le champ delta.content de chaque événement et on n'envoie au client que le texte, pas le JSON brut.

Étape 3 — Le client qui lit le flux

async function envoyer(message: string, onChunk: (t: string) => void) {
  const res = await fetch("/api/chat", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ message }),
  });
  const reader = res.body!.getReader();
  const decoder = new TextDecoder();
  while (true) {
    const { done, value } = await reader.read();
    if (done) break;
    onChunk(decoder.decode(value, { stream: true }));
  }
}

Dans ton composant, onChunk concatène le morceau à l'état affiché :

let reponse = "";
await envoyer(question, (t) => { reponse += t; setReponse(reponse); });

Adapter à ton cas

  • Historique de conversation : envoie tout le tableau messages (pas juste le dernier) pour garder le contexte.
  • Autre fournisseur : OpenAI utilise le même format SSE data: ; Claude a un format d'événements différent (event: + data:) — adapte le parsing de l'étape 2.
  • Arrêt manuel : passe un AbortController au fetch client pour couper la génération.
  • Markdown : rends la réponse avec un rendu Markdown côté client pour les listes et le code.

En cas de souci

  • Rien ne s'affiche avant la fin : un proxy ou un middleware tamponne la réponse. Vérifie que rien ne met la réponse en buffer, et que tu n'attends pas res.text() (qui attend tout).
  • Texte tronqué ou JSON cassé dans les logs : un événement SSE peut arriver coupé en deux lectures. Le buffer de l'étape 2 gère ça — ne parse jamais une ligne sans vérifier qu'elle est complète.
  • La clé API apparaît dans le navigateur : tu appelles le fournisseur depuis le client. Repasse par ta route serveur, toujours.
  • Timeouts sur longues réponses : sur certaines plateformes serverless, augmente la durée max d'exécution de la route, sinon le flux est coupé.
Réagir :
Partager —XLinkedIn