diff --git a/DEPLOY_NOTES.md b/DEPLOY_NOTES.md index 62f2fb3..96adc9b 100644 --- a/DEPLOY_NOTES.md +++ b/DEPLOY_NOTES.md @@ -262,3 +262,88 @@ Attention cache mobile: - `index.html` charge `/app.js?v=7`. - Service worker: `opensquared-assistant-v7`. - Si Android garde l'ancien JS, fermer/rouvrir Chrome ou reinstaller la PWA. + +## Session memoire professionnelle et routeur SQL - 2026-04-27 + +Objectif: + +- Construire une memoire professionnelle utilisable par l'assistant vocal. +- Stocker clients, projets, taches, notes et repos associes. +- Permettre des questions naturelles du type: + - `Quels sont mes clients ?` + - `Que dois-je faire pour ICT ?` + - `Pour quel client ai-je le plus de taches ?` + - `Note que pour FAIRCOT je dois tester le lien vers le PDF.` + +Problemes observes pendant les tests: + +- Les premieres versions etaient trop basees sur des regex et des actions en dur. +- Les formulations vocales variables, les typos et les phrases de suivi rendaient cette approche fragile. +- Exemple: `note le comme une tache pour FAIRCOT` devait comprendre que `le` faisait reference au message precedent, pas a une regle specifique. +- Les actions de lecture specialisees se multipliaient trop vite: liste clients, liste taches, taches par client, client avec le plus de taches, etc. +- Risque identifie: creer une action rigide pour chaque question probable au lieu de laisser le modele raisonner sur le schema. + +Architecture retenue: + +- SQLite reste le stockage principal. +- Le modele recoit: + - le schema de la base, + - un extrait de memoire actuelle, + - l'historique recent de conversation, + - le dernier message utilisateur. +- Un routeur LLM decide entre trois sorties: + - `action`: ecriture controlee, par exemple ajouter client, ajouter tache, terminer tache, ajouter repo. + - `interroger_base`: lecture SQL readonly generee par le modele. + - `clarification`: question a Laurent si la cible ou l'intention est ambigue. +- Les lectures globales ne doivent plus devenir une explosion d'actions codees en dur. +- Pour une question analytique, le modele genere un `SELECT`, puis l'app execute uniquement ce SQL en lecture seule. + +Pourquoi ce choix: + +- Les questions metier sont ouvertes et evoluent vite. +- Le modele est meilleur pour mapper une demande naturelle vers une intention ou une requete SQL que des regex fragiles. +- Le dernier message reste prioritaire, mais le modele doit raisonner avec l'historique recent pour comprendre `lui`, `le`, `cette tache`, `ce client`. +- Les ecritures restent controlees par une liste d'actions permises afin d'eviter qu'un SQL genere ne modifie la base. +- Les lectures sont flexibles via SQL readonly, mais protegees par validation. + +Securite SQL readonly: + +- `memory.execute_read_query()` accepte uniquement une seule requete `SELECT`. +- Les points-virgules, commentaires SQL, `PRAGMA`, `INSERT`, `UPDATE`, `DELETE`, `DROP`, etc. sont rejetes. +- SQLite `set_authorizer` bloque les operations non autorisees. +- Les tables lisibles sont limitees a: + - `clients` + - `projects` + - `tasks` + - `repositories` + - `memories` +- Le resultat est limite pour eviter les sorties trop longues. + +Corrections importantes de la session: + +- Le routeur utilise maintenant davantage d'historique recent pour les phrases de suivi. +- Le prompt de secours ne demande plus au modele de produire du JSON d'action; cela evite de concurrencer le routeur. +- Les anciennes fonctions regex sont considerees comme heritage/code mort si elles ne sont plus appelees. +- Correction du bug `"'id'"` en rouge: + - cause: des lignes SQL de synthese etaient stockees dans le contexte comme si elles etaient toujours des taches completes avec `id` et `title`; + - fix: le contexte n'assume plus que chaque ligne possede ces champs. + +Decision importante: + +- Ne pas ajouter de micro-regles specifiques comme `pending_note` pour chaque cas de suivi. +- Preferer un routeur LLM qui evalue l'intention avec toute la conversation recente. +- Si le modele doute, il doit demander une precision plutot que choisir une action au hasard. + +Limite actuelle: + +- La qualite depend beaucoup du modele Groq utilise pour le routage. +- Si les references implicites continuent a echouer, tester un modele plus fort ou separer en deux appels: + - appel 1: comprendre l'intention et la cible avec l'historique; + - appel 2: generer l'action ou le SQL readonly. + +Etat mental a garder pour la suite: + +- Pour les ecritures: actions explicites, schema stable, confirmation si doute. +- Pour les lectures: SQL readonly genere par le modele. +- Pour les phrases ambigues: clarification utilisateur. +- Eviter de transformer chaque bug conversationnel en regex supplementaire. diff --git a/README.md b/README.md index 2b0159b..88f0a35 100644 --- a/README.md +++ b/README.md @@ -162,6 +162,23 @@ Qu'est-ce que tu sais sur SAFTCO ? La memoire peut contenir des clients, projets, taches, notes et depots Git associes a un projet. +### Architecture de la memoire + +L'assistant utilise une architecture en deux niveaux : + +- les ecritures passent par des actions controlees (`ajouter_client`, `ajouter_tache`, `terminer_tache`, etc.) ; +- les lectures et analyses passent par un routeur LLM qui peut generer une requete SQL readonly sur le schema SQLite. + +Ce choix evite de coder une action specifique pour chaque question possible. Par exemple, `quel client a le plus de taches ?`, `quelles sont mes taches a faire ?` ou `cette tache est pour quel client ?` peuvent etre resolus en lisant la base plutot qu'en ajoutant des routes rigides. + +Le routeur recoit le dernier message, l'historique recent, le schema de la base et un extrait de la memoire. Il decide entre : + +- executer une action d'ecriture autorisee ; +- lancer une lecture SQL readonly ; +- demander une clarification si la cible est ambigue. + +Les requetes SQL generees sont limitees a des `SELECT` et passent par une validation readonly dans `memory.py`. + ## Notes - Groq Orpheus TTS doit etre accepte dans la console Groq pour fonctionner :