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 |
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 #
for await (const event of gaspard.askStream(conversation.id, question)) {
if (event.type === 'delta') output.textContent += event.text;
else showSources(event.answer.sources);
}$stream = $gaspard->askStream($conversation->id, $question);
foreach ($stream as $event) {
if ($event->isDelta()) {
echo $event->text;
}
}
$answer = $stream->getReturn();await foreach (var item in gaspard.AskStreamAsync(conversation.Id, question))
{
if (item.IsDelta) Console.Write(item.Text);
else Console.WriteLine($"\n{item.Answer!.Sources.Count} source(s)");
}await for (final event in gaspard.askStream(conversation.id, question)) {
switch (event) {
case GaspardDelta(:final text):
stdout.write(text);
case GaspardAnswerEvent(:final answer):
print('\n${answer.sources.length} source(s)');
}
}gaspard.askStream(conversationId, question).collect { event ->
when (event) {
is GaspardStreamEvent.Delta -> print(event.text)
is GaspardStreamEvent.Completed -> println("\n${event.answer.sources.size} source(s)")
}
}Un flux déjà commencé n’est jamais relancé automatiquement ; sortir de la boucle (ou annuler la
coroutine, le CancellationToken…) ferme la connexion.
Sans SDK, dans un navigateur #
EventSource ne fait que des GET : lisez le flux avec fetch.
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.