Quickstart
Cinq etapes pour passer du zero a une reponse RAG citoyenne, citations incluses. Reproduit ce parcours en local pour valider ton integration avant de pointer la production.
1. Recuperer un JWT
Toutes les routes acceptent un JWT bearer signe avec JWT_SECRET. Le frontend de reference utilise NextAuth pour le generer ; en server-to-server, signe ton propre token avec la cle partagee et le claim iss="knowb". Consulte Authentication pour la structure exacte.
export BANGRE_JWT="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."2. Premiere requete chat
Appelle POST /api/v1/chat-rag/stream avec un message et, idealement, un filtre domaine. Sans filtre, le serveur prend le premier domaine actif (en MVP : impots).
curl -N -X POST http://localhost:8000/api/v1/chat-rag/stream \
-H "Authorization: Bearer $BANGRE_JWT" \
-H "Content-Type: application/json" \
-d '{
"message": "Quel est le taux de TVA en vigueur ?",
"filters": { "domaine": "impots" }
}'3. Parser le stream SSE
Le flux suit le standard Server-Sent Events. Les frames sont separes par \r\n\r\n. Chaque frame contient une ligne event: et une ligne data: (JSON serialise).
event: message
data: {"delta": "La TVA "}
event: message
data: {"delta": "est de 18% "}
event: final
data: {"citations":[{"document_id":"...","article_number":"Article 318","snippet":"..."}],"validation":{"ok":true,"warning":null},"latency_ms":842,"disclaimer":"Ceci ne constitue pas un avis juridique.","conversation_id":null}const reader = res.body!.getReader();
const decoder = new TextDecoder();
let buf = "";
while (true) {
const { value, done } = await reader.read();
if (done) break;
buf += decoder.decode(value, { stream: true });
let idx;
while ((idx = buf.indexOf("\r\n\r\n")) !== -1) {
const frame = buf.slice(0, idx);
buf = buf.slice(idx + 4);
const lines = frame.split("\r\n");
const event = lines.find((l) => l.startsWith("event: "))?.slice(7) ?? "message";
const data = lines.find((l) => l.startsWith("data: "))?.slice(6) ?? "{}";
const payload = JSON.parse(data);
if (event === "message") onDelta(payload.delta);
else if (event === "final") onFinal(payload);
}
}\r\n\r\n) entre evenements. Tout parser SSE standard fonctionne. Les tokens arrivent en plusieurs message, l'evenement final n'arrive qu'une fois.4. Exploiter les citations
L'evenement final porte un tableau citations. Chaque entree donne un document_id a croiser avec GET /api/v1/documents/{id} pour reconstruire le titre complet, l'URL Journal Officiel et la date d'entree en vigueur.
{
"citations": [
{
"document_id": "f3a0c1...",
"article_number": "Article 318",
"snippet": "Le taux normal de la taxe sur la valeur ajoutee est fixe a 18%."
}
],
"validation": { "ok": true, "warning": null },
"latency_ms": 842,
"disclaimer": "Ceci ne constitue pas un avis juridique. Consultez les textes officiels.",
"conversation_id": "5c2a..."
}5. Aller plus loin
- Persistance : passe un JWT pour que Bangré sauvegarde la conversation (voir Conversations).
- Filtres avances :
statut,doc_type,top_k. - Modeles : liste les modeles disponibles via
GET /api/v1/models. - Erreurs : table complete dans Erreurs et statuts.