Skip to main content

API Assistant Bemba

Bemba répond en langage naturel. Le modèle ne lit jamais la base de données : il appelle des outils typés que le serveur exécute avec les droits de l'utilisateur (permissions d'écran, institution, projets et région). Il n'écrit jamais de SQL.

Endpoints du SIG​

Toutes ces routes demandent un utilisateur connecté.

MéthodeEndpointDescription
POST/api/assistant/messagePoser une question
GET/api/assistant/conversationsLes 30 dernières conversations
GET/api/assistant/conversations/{id}Messages d'une conversation
DELETE/api/assistant/conversations/{id}Archiver une conversation
POST/api/assistant/messages/{id}/evaluationNoter une réponse
GET/api/assistant/statistiquesUsage par jour et par utilisateur (jours, 30 par défaut, 365 au plus ; permission admin.settings)

POST /api/assistant/message​

{
"message": "combien de ménages par région ?",
"conversationId": null,
"langue": "fr",
"projet": "<uuid du projet sélectionné ou null>",
"page": "/menages",
"carte": { "couches": ["menages"], "bounds": { "north": 12.6, "south": 11.9, "east": -14.9, "west": -15.6 } },
"plainte": { "mode": true, "step": "ask_name", "data": {} }
}
ChampRequisDescription
messageOuiQuestion (400 Message requis si vide)
conversationIdNonPour poursuivre une conversation ; le serveur garde l'historique
langueNonfr, en, pt ou cr (kriol)
projetNonProjet sélectionné dans l'interface
pageNonÉcran courant, pour le contexte
carteNonCouches et emprise de la carte
plainteNonÉtat du dépôt de plainte guidé, à renvoyer tant que la réponse porte plainte_mode: true

Réponse (data) :

{
"conversationId": "…",
"messageId": "…",
"answer": "Texte en Markdown léger",
"suggestions": ["…"],
"outils": [{ "nom": "statistiques", "statut": "ok", "dureeMs": 120 }],
"usage": { "tokensEntree": 0, "tokensSortie": 0, "latenceMs": 0, "conversationCout": 0.0 },
"mapData": [],
"navigation": { "url": "/menages/…", "page": "menages" },
"articles": [{ "reference": "KB-001", "titre": "…", "page": "/knowledge-base?article=…" }],
"erreur": null
}

Les champs après usage sont facultatifs. erreur prend l'une des valeurs limite, indisponible, reseau, non_configure, requete, delai ou refus ; la réponse contient alors un message adapté dans la langue demandée.

Limites​

  • 40 questions par 10 minutes et par utilisateur. Au-delà, 429 avec retryAfter (secondes) et l'en-tête Retry-After.
  • Un tour dure au plus 50 secondes.

Évaluation​

{ "evaluation": 1, "commentaire": "Réponse exacte" }

evaluation vaut 1, -1 ou null (400 sinon).

Base documentaire​

Pour les questions de procédure, l'assistant cherche dans cette documentation et dans les articles publiés de la base de connaissances (/api/knowledge-base/*). L'index est reconstruit par la commande app:assistant:indexer ; il n'a pas d'endpoint.

Assistant du site public​

POST /api/public/assistant/message

Route anonyme, sans jeton ni en-tête CSRF. Elle sert uniquement à présenter le projet et à aider à déposer une réclamation. Elle n'accède à aucune donnée de ménage, de bénéficiaire, de paiement ou de plainte.

{
"message": "Comment déposer une réclamation ?",
"langue": "pt",
"historique": [{ "role": "user", "contenu": "…" }, { "role": "assistant", "contenu": "…" }]
}

Le serveur ne garde rien : le navigateur renvoie lui-même ses derniers échanges dans historique. Réponse (data) : answer, suggestions, outils, usage, et plainte_reference quand une réclamation a été transmise.

Limites : 20 messages par 10 minutes et par adresse IP (429, "error": "limite"), et 500 messages par jour pour tout le site (429, "error": "plafond"). Les deux réponses portent retryAfter et l'en-tête Retry-After.