watch·ia
AccueilActusTutosGlossaireCette semaineTendancesSources
/
ACTUS
4 sept. — Crusoe lève 3 milliards de dollars pour une valorisation de 30 milliards·3 sept. — Accel en pourparlers pour diriger une levée de 1 milliard chez Thinking Machines·3 sept. — Abliteration.ai propose des modèles IA sans restrictions via une plateforme commerciale·3 sept. — Meta propose des réductions pour partager les données d’usage de Muse Spark·3 sept. — OpenAI présente GPT-6 Astra, son modèle le plus avancé à ce jour·3 sept. — Ollie lance un assistant IA familial conforme SOC 2 pour préserver la confidentialité·3 sept. — Nvidia propose PAIR, un outil gratuit pour agréger des PC locaux en cluster d'inférence IA·3 sept. — Google ajoute des modes vocaux en temps réel pour Gmail, Docs et Keep·3 sept. — Panne simultanée de ChatGPT, Grok et Claude : trois assistants IA majeurs inaccessibles·3 sept. — Google améliore son modèle météo IA WeatherNext 3 avec une résolution cinq fois supérieure·4 sept. — Crusoe lève 3 milliards de dollars pour une valorisation de 30 milliards·3 sept. — Accel en pourparlers pour diriger une levée de 1 milliard chez Thinking Machines·3 sept. — Abliteration.ai propose des modèles IA sans restrictions via une plateforme commerciale·3 sept. — Meta propose des réductions pour partager les données d’usage de Muse Spark·3 sept. — OpenAI présente GPT-6 Astra, son modèle le plus avancé à ce jour·3 sept. — Ollie lance un assistant IA familial conforme SOC 2 pour préserver la confidentialité·3 sept. — Nvidia propose PAIR, un outil gratuit pour agréger des PC locaux en cluster d'inférence IA·3 sept. — Google ajoute des modes vocaux en temps réel pour Gmail, Docs et Keep·3 sept. — Panne simultanée de ChatGPT, Grok et Claude : trois assistants IA majeurs inaccessibles·3 sept. — Google améliore son modèle météo IA WeatherNext 3 avec une résolution cinq fois supérieure·4 sept. — Crusoe lève 3 milliards de dollars pour une valorisation de 30 milliards·3 sept. — Accel en pourparlers pour diriger une levée de 1 milliard chez Thinking Machines·3 sept. — Abliteration.ai propose des modèles IA sans restrictions via une plateforme commerciale·3 sept. — Meta propose des réductions pour partager les données d’usage de Muse Spark·3 sept. — OpenAI présente GPT-6 Astra, son modèle le plus avancé à ce jour·3 sept. — Ollie lance un assistant IA familial conforme SOC 2 pour préserver la confidentialité·3 sept. — Nvidia propose PAIR, un outil gratuit pour agréger des PC locaux en cluster d'inférence IA·3 sept. — Google ajoute des modes vocaux en temps réel pour Gmail, Docs et Keep·3 sept. — Panne simultanée de ChatGPT, Grok et Claude : trois assistants IA majeurs inaccessibles·3 sept. — Google améliore son modèle météo IA WeatherNext 3 avec une résolution cinq fois supérieure·4 sept. — Crusoe lève 3 milliards de dollars pour une valorisation de 30 milliards·3 sept. — Accel en pourparlers pour diriger une levée de 1 milliard chez Thinking Machines·3 sept. — Abliteration.ai propose des modèles IA sans restrictions via une plateforme commerciale·3 sept. — Meta propose des réductions pour partager les données d’usage de Muse Spark·3 sept. — OpenAI présente GPT-6 Astra, son modèle le plus avancé à ce jour·3 sept. — Ollie lance un assistant IA familial conforme SOC 2 pour préserver la confidentialité·3 sept. — Nvidia propose PAIR, un outil gratuit pour agréger des PC locaux en cluster d'inférence IA·3 sept. — Google ajoute des modes vocaux en temps réel pour Gmail, Docs et Keep·3 sept. — Panne simultanée de ChatGPT, Grok et Claude : trois assistants IA majeurs inaccessibles·3 sept. — Google améliore son modèle météo IA WeatherNext 3 avec une résolution cinq fois supérieure·

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