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éthode | Endpoint | Description |
|---|---|---|
| POST | /api/assistant/message | Poser une question |
| GET | /api/assistant/conversations | Les 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}/evaluation | Noter une réponse |
| GET | /api/assistant/statistiques | Usage 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": {} }
}
| Champ | Requis | Description |
|---|---|---|
message | Oui | Question (400 Message requis si vide) |
conversationId | Non | Pour poursuivre une conversation ; le serveur garde l'historique |
langue | Non | fr, en, pt ou cr (kriol) |
projet | Non | Projet sélectionné dans l'interface |
page | Non | Écran courant, pour le contexte |
carte | Non | Couches et emprise de la carte |
plainte | Non | É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êteRetry-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.