HubMix

Documentation

Réponses en flux (SSE)

Afficher la réponse de Gaspard mot à mot : les événements delta, answer et error, et comment les lire.

Gaspard peut répondre mot à mot, comme dans le widget : l’utilisateur voit la réponse se construire au lieu d’attendre qu’elle soit complète. C’est la même route que la réponse JSON, POST /gaspard/conversations/{id}/messages, avec l’en-tête Accept: text/event-stream.

Les événements #

La réponse est un flux Server-Sent Events : des blocs séparés par une ligne vide, chacun avec event: <nom> et une ligne data: <json>.

Événement Données Quand
delta {"text": "…"} Un morceau de la réponse, à ajouter au texte affiché
answer La réponse complète (mêmes champs que la réponse JSON) Une seule fois, à la fin, en cas de succès
error {"code": "…"} Une seule fois, à la fin, en cas d’échec
Texte
event: delta
data: {"text": "Ce week-end à Lyon, "}

event: delta
data: {"text": "montez aux châteaux de Valère et de Tourbillon…"}

event: answer
data: {"conversation_id": "cnv_…", "message_id": "msg_…", "text": "Ce week-end à Lyon, montez…", "sources": […], "listings": […], "remaining_messages": 58}

Le flux se termine toujours par answer ou par error : un flux qui s’arrête sans l’un des deux a été coupé (réseau, proxy) et doit être traité comme une erreur (stream_incomplete dans les SDK). Ignorez les événements inconnus et les lignes de commentaire qui commencent par :.

Codes de l’événement error #

Code Signification Que faire
assistant_busy Gaspard est très sollicité Réessayer dans quelques secondes
assistant_unavailable Aucun modèle n’a pu répondre Réessayer plus tard
conversation_full La conversation a atteint 60 messages Commencer une nouvelle conversation
internal_error Erreur inattendue Réessayer ; citer l’identifiant de requête au support

Les erreurs avant le début du flux (clé refusée, quota dépassé, texte invalide…) sont des réponses JSON ordinaires, avec leur statut HTTP : voir Erreurs, limites et quotas.

Avec un SDK #

Node.js
for await (const event of gaspard.askStream(conversation.id, question)) {
  if (event.type === 'delta') output.textContent += event.text;
  else showSources(event.answer.sources);
}

Un flux déjà commencé n’est jamais relancé automatiquement ; sortir de la boucle (ou annuler la coroutine, le CancellationToken…) ferme la connexion.

EventSource ne fait que des GET : lisez le flux avec fetch.

JavaScript
const response = await fetch(`https://hubmix.dealmood-solutions.com/v1/public/gaspard/conversations/${id}/messages`, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    Accept: 'text/event-stream',
    'X-Gaspard-Key': 'vcp_live_…',
    Authorization: `Bearer ${visitorToken}`,
  },
  body: JSON.stringify({ text }),
});

const reader = response.body.pipeThrough(new TextDecoderStream()).getReader();
let buffer = '';
for (;;) {
  const { value, done } = await reader.read();
  if (done) break;
  buffer += value.replace(/\r\n/g, '\n');
  let end;
  while ((end = buffer.indexOf('\n\n')) >= 0) {
    const block = buffer.slice(0, end);
    buffer = buffer.slice(end + 2);
    const event = /^event: (.*)$/m.exec(block)?.[1];
    const data = JSON.parse(/^data: (.*)$/m.exec(block)?.[1] ?? 'null');
    if (event === 'delta') output.textContent += data.text;
    if (event === 'answer') showSources(data.sources);
    if (event === 'error') showError(data.code);
  }
}

Relayer le flux depuis votre serveur #

Avec une clé serveur, votre backend lit le flux de Gaspard et le renvoie à votre page, au même format. Pensez à désactiver la mise en tampon des proxys : le service envoie lui-même Cache-Control: no-cache et X-Accel-Buffering: no, faites de même. Exemples complets : Laravel, Next.js, ASP.NET Core.