memory contexte

This commit is contained in:
2026-04-27 16:09:08 +02:00
parent b23a1de6f3
commit 3ff5bf4d25
2 changed files with 106 additions and 4 deletions

89
app.py
View File

@@ -15,6 +15,7 @@ from memory import (
add_memory,
add_repository,
add_task,
close_task,
init_db,
search_memory,
upsert_client,
@@ -43,6 +44,7 @@ init_db()
client = Groq(api_key=GROQ_API_KEY)
histories = {}
session_contexts = {}
SYSTEM_PROMPT = """Tu es l'assistant personnel vocal de Laurent.
Tu peux discuter normalement en francais et aider a envoyer des emails via Gmail.
@@ -63,6 +65,7 @@ Actions disponibles :
{"action": "ajouter_client", "nom": "...", "notes": "...", "statut": "actif"}
{"action": "ajouter_projet", "nom": "...", "client": "...", "statut": "...", "resume": "...", "prochaine_action": "..."}
{"action": "ajouter_tache", "titre": "...", "client": "...", "projet": "...", "details": "...", "echeance": "..."}
{"action": "terminer_tache", "id": 123}
{"action": "ajouter_repo", "nom": "...", "projet": "...", "chemin": "...", "url": "...", "branche": "..."}
{"action": "ajouter_note", "contenu": "...", "sujet": "...", "client": "...", "projet": "...", "type": "note"}
{"action": "chercher_memoire", "requete": "..."}
@@ -125,6 +128,7 @@ ACTIONS = {
"ajouter_client",
"ajouter_projet",
"ajouter_tache",
"terminer_tache",
"ajouter_repo",
"ajouter_note",
"chercher_memoire",
@@ -176,7 +180,7 @@ def demander_au_llm(session_id, texte):
return contenu
def detecter_action_directe(texte):
def detecter_action_directe(texte, session_id=None):
texte_nettoye = texte.strip()
texte_min = texte_nettoye.lower()
@@ -202,6 +206,10 @@ def detecter_action_directe(texte):
if recherche_taches:
return recherche_taches
suppression_tache = detecter_suppression_tache(texte_nettoye, session_id)
if suppression_tache:
return suppression_tache
recherche_match = re.search(
r"(?:qu(?:'| )?est[- ]?ce que tu sais sur|que sais[- ]?tu sur|cherche dans la memoire|memoire sur)\s+(.+)",
texte_nettoye,
@@ -309,6 +317,40 @@ def detecter_recherche_taches(texte):
return {"action": "chercher_memoire", "requete": client_nom}
def detecter_suppression_tache(texte, session_id):
if not re.search(r"\b(enleve|enlève|supprime|retire|efface|termine|marque.*faite)\b", texte, flags=re.IGNORECASE):
return None
if not re.search(r"\btaches?\b", texte, flags=re.IGNORECASE):
return None
contexte = session_contexts.get(session_id or "", {})
taches = contexte.get("tasks") or []
if not taches:
return None
client_match = re.search(
r"\b(?:pour|sur)\s+(?:mon\s+client\s+|le\s+client\s+)?([A-Z0-9][A-Z0-9&.\- ]{1,40})",
texte,
flags=re.IGNORECASE,
)
client_nom = nettoyer_nom_client(client_match.group(1)) if client_match else contexte.get("last_client", "")
candidates = [
tache for tache in taches
if not client_nom or (tache.get("client_name") or "").lower() == client_nom.lower()
]
if not candidates:
candidates = taches
if re.search(r"\b(derniere|dernière|dernier|derniere affichee|dernière affichée)\b", texte, flags=re.IGNORECASE):
task_id = candidates[-1].get("id")
else:
task_id = candidates[0].get("id") if len(candidates) == 1 else None
if not task_id:
return None
return {"action": "terminer_tache", "id": task_id}
def extraire_liste_clients(texte):
if not re.search(r"\bclients?\b", texte, flags=re.IGNORECASE):
return []
@@ -459,6 +501,13 @@ def executer_action(action):
)
return f"Tache ajoutee : {tache['title']}.", {"memorySaved": True}
if nom_action == "terminer_tache":
tache = close_task(action.get("id"))
if not tache:
return "Je n'ai pas retrouve cette tache ouverte.", {"memoryRead": True}
contexte = tache.get("client_name") or tache.get("project_name") or "memoire professionnelle"
return f"C'est fait : j'ai retire la tache {tache['title']} pour {contexte}.", {"memorySaved": True}
if nom_action == "ajouter_repo":
repo = add_repository(
action.get("nom", ""),
@@ -482,7 +531,7 @@ def executer_action(action):
if nom_action == "chercher_memoire":
resultat = search_memory(action.get("requete", ""))
return formater_memoire(resultat), {"memoryRead": True}
return formater_memoire(resultat), {"memoryRead": True, "memoryResult": resultat, "memoryQuery": action.get("requete", "")}
return "", {}
@@ -498,6 +547,8 @@ def executer_actions(action_data):
"contactSaved": False,
"memorySaved": False,
"memoryRead": False,
"memoryResult": None,
"memoryQuery": "",
}
actions_executees = []
for action in actions:
@@ -507,8 +558,11 @@ def executer_actions(action_data):
actions_executees.append(action)
if reponse:
reponses.append(reponse)
for cle in flags:
for cle in ("emailSent", "contactSaved", "memorySaved", "memoryRead"):
flags[cle] = flags[cle] or bool(action_flags.get(cle))
if action_flags.get("memoryResult"):
flags["memoryResult"] = action_flags["memoryResult"]
flags["memoryQuery"] = action_flags.get("memoryQuery", "")
if actions_executees and all(action.get("action") == "ajouter_client" for action in actions_executees):
noms = [action.get("nom", "").strip() for action in actions_executees if action.get("nom", "").strip()]
@@ -518,6 +572,29 @@ def executer_actions(action_data):
return " ".join(reponses), flags
def mettre_a_jour_contexte(session_id, texte, reponse, flags):
historique = histories.setdefault(session_id, [])
if not historique or historique[-1].get("content") != texte:
historique.append({"role": "user", "content": texte})
historique.append({"role": "assistant", "content": reponse})
del historique[:-20]
resultat = flags.get("memoryResult")
if not resultat:
return
contexte = session_contexts.setdefault(session_id, {})
if flags.get("memoryQuery"):
contexte["last_query"] = flags["memoryQuery"]
if resultat.get("clients"):
contexte["last_client"] = resultat["clients"][0].get("name", "")
elif flags.get("memoryQuery"):
contexte["last_client"] = flags["memoryQuery"]
if resultat.get("projects"):
contexte["last_project"] = resultat["projects"][0].get("name", "")
contexte["tasks"] = resultat.get("tasks", [])
def formater_memoire(resultat):
lignes = []
for client_mem in resultat["clients"][:5]:
@@ -554,7 +631,7 @@ def formater_memoire(resultat):
def traiter_message(session_id, texte, avec_audio=False):
action_directe = detecter_action_directe(texte)
action_directe = detecter_action_directe(texte, session_id)
reponse = json.dumps(action_directe, ensure_ascii=False) if action_directe else demander_au_llm(session_id, texte)
action = extraire_action(reponse)
flags = {
@@ -562,10 +639,13 @@ def traiter_message(session_id, texte, avec_audio=False):
"contactSaved": False,
"memorySaved": False,
"memoryRead": False,
"memoryResult": None,
"memoryQuery": "",
}
if action:
reponse, flags = executer_actions(action)
mettre_a_jour_contexte(session_id, texte, reponse, flags)
audio_url = None
if avec_audio and TTS_PROVIDER == "groq":
@@ -632,6 +712,7 @@ def reset():
data = request.get_json(silent=True) or {}
session_id = data.get("sessionId") or "default"
histories.pop(session_id, None)
session_contexts.pop(session_id, None)
return jsonify({"ok": True})