Inject context
This commit is contained in:
97
app.py
97
app.py
@@ -16,7 +16,9 @@ from memory import (
|
||||
add_repository,
|
||||
add_task,
|
||||
close_task,
|
||||
get_memory_snapshot,
|
||||
init_db,
|
||||
list_clients,
|
||||
search_memory,
|
||||
upsert_client,
|
||||
upsert_project,
|
||||
@@ -69,6 +71,7 @@ Actions disponibles :
|
||||
{"action": "ajouter_repo", "nom": "...", "projet": "...", "chemin": "...", "url": "...", "branche": "..."}
|
||||
{"action": "ajouter_note", "contenu": "...", "sujet": "...", "client": "...", "projet": "...", "type": "note"}
|
||||
{"action": "chercher_memoire", "requete": "..."}
|
||||
{"action": "lister_clients"}
|
||||
|
||||
Si une phrase contient plusieurs choses a enregistrer, utilise :
|
||||
{"actions": [{...}, {...}]}
|
||||
@@ -96,10 +99,66 @@ def sauvegarder_contacts(contacts):
|
||||
)
|
||||
|
||||
|
||||
def construire_system_prompt():
|
||||
def construire_system_prompt(session_id=None):
|
||||
contacts = charger_contacts()
|
||||
lignes = [f"- {nom.title()} : {email}" for nom, email in contacts.items()]
|
||||
return SYSTEM_PROMPT + "\n\nContacts connus :\n" + "\n".join(lignes)
|
||||
return (
|
||||
SYSTEM_PROMPT
|
||||
+ "\n\nContacts connus :\n"
|
||||
+ "\n".join(lignes)
|
||||
+ "\n\nMemoire professionnelle actuelle :\n"
|
||||
+ construire_contexte_memoire(session_id)
|
||||
)
|
||||
|
||||
|
||||
def construire_contexte_memoire(session_id=None):
|
||||
snapshot = get_memory_snapshot()
|
||||
contexte = session_contexts.get(session_id or "", {})
|
||||
lignes = []
|
||||
|
||||
clients_mem = snapshot["clients"]
|
||||
if clients_mem:
|
||||
lignes.append("Clients connus et taches ouvertes :")
|
||||
for client_mem in clients_mem:
|
||||
lignes.append(f"- {client_mem['name']} : {client_mem['open_task_count']} tache(s) ouverte(s)")
|
||||
else:
|
||||
lignes.append("Aucun client connu.")
|
||||
|
||||
if snapshot["tasks"]:
|
||||
lignes.append("Taches ouvertes recentes :")
|
||||
for tache in snapshot["tasks"][:15]:
|
||||
sujet = tache.get("client_name") or tache.get("project_name") or "general"
|
||||
lignes.append(f"- #{tache['id']} {sujet} : {tache['title']}")
|
||||
|
||||
if snapshot["projects"]:
|
||||
lignes.append("Projets recents :")
|
||||
for projet in snapshot["projects"][:10]:
|
||||
client_nom = projet.get("client_name") or "sans client"
|
||||
statut = projet.get("status") or "actif"
|
||||
lignes.append(f"- {projet['name']} ({client_nom}) : {statut}")
|
||||
|
||||
if snapshot["repositories"]:
|
||||
lignes.append("Depots Git associes :")
|
||||
for repo in snapshot["repositories"][:10]:
|
||||
cible = repo.get("project_name") or "sans projet"
|
||||
chemin = repo.get("local_path") or repo.get("remote_url") or "chemin non renseigne"
|
||||
lignes.append(f"- {repo['name']} -> {cible} : {chemin}")
|
||||
|
||||
if contexte:
|
||||
lignes.append("Contexte de la conversation en cours :")
|
||||
if contexte.get("last_client"):
|
||||
lignes.append(f"- dernier client mentionne : {contexte['last_client']}")
|
||||
if contexte.get("last_project"):
|
||||
lignes.append(f"- dernier projet mentionne : {contexte['last_project']}")
|
||||
if contexte.get("tasks"):
|
||||
ids = ", ".join(f"#{tache['id']} {tache['title']}" for tache in contexte["tasks"][:5])
|
||||
lignes.append(f"- dernieres taches affichees : {ids}")
|
||||
|
||||
lignes.append(
|
||||
"Utilise ce contexte pour repondre aux questions globales. "
|
||||
"Pour modifier la memoire, reponds avec une action JSON."
|
||||
)
|
||||
return "\n".join(lignes)
|
||||
|
||||
|
||||
def resoudre_contact(destinataire):
|
||||
@@ -132,6 +191,7 @@ ACTIONS = {
|
||||
"ajouter_repo",
|
||||
"ajouter_note",
|
||||
"chercher_memoire",
|
||||
"lister_clients",
|
||||
}
|
||||
|
||||
|
||||
@@ -171,7 +231,7 @@ def demander_au_llm(session_id, texte):
|
||||
|
||||
reponse = client.chat.completions.create(
|
||||
model=CHAT_MODEL,
|
||||
messages=[{"role": "system", "content": construire_system_prompt()}] + historique,
|
||||
messages=[{"role": "system", "content": construire_system_prompt(session_id)}] + historique,
|
||||
temperature=0.45,
|
||||
max_tokens=900,
|
||||
)
|
||||
@@ -221,8 +281,8 @@ def detecter_action_directe(texte, session_id=None):
|
||||
"requete": recherche_match.group(1).strip(" ?.,;:"),
|
||||
}
|
||||
|
||||
if re.search(r"\b(liste|affiche|montre)\b.*\bclients?\b", texte_min):
|
||||
return {"action": "chercher_memoire", "requete": ""}
|
||||
if detecter_liste_clients_demandee(texte_min):
|
||||
return {"action": "lister_clients"}
|
||||
|
||||
if re.search(r"\b(liste|affiche|montre)\b.*\b(projets?|taches?|repos?|depots?)\b", texte_min):
|
||||
return {"action": "chercher_memoire", "requete": ""}
|
||||
@@ -351,6 +411,18 @@ def detecter_suppression_tache(texte, session_id):
|
||||
return {"action": "terminer_tache", "id": task_id}
|
||||
|
||||
|
||||
def detecter_liste_clients_demandee(texte_min):
|
||||
if not re.search(r"\bclients?\b", texte_min):
|
||||
return False
|
||||
return bool(
|
||||
re.search(r"\b(liste|affiche|montre|donne)\b.*\bclients?\b", texte_min)
|
||||
or re.search(r"\bclients?\b.*\b(liste|affiche|montre|donne)\b", texte_min)
|
||||
or re.search(r"\b(quels?|qui)\s+sont\b.*\bclients?\b", texte_min)
|
||||
or re.search(r"\btous\s+mes\s+clients?\b", texte_min)
|
||||
or re.search(r"\bmes\s+clients?\b", texte_min)
|
||||
)
|
||||
|
||||
|
||||
def extraire_liste_clients(texte):
|
||||
if not re.search(r"\bclients?\b", texte, flags=re.IGNORECASE):
|
||||
return []
|
||||
@@ -533,6 +605,14 @@ def executer_action(action):
|
||||
resultat = search_memory(action.get("requete", ""))
|
||||
return formater_memoire(resultat), {"memoryRead": True, "memoryResult": resultat, "memoryQuery": action.get("requete", "")}
|
||||
|
||||
if nom_action == "lister_clients":
|
||||
clients_mem = list_clients()
|
||||
return formater_liste_clients(clients_mem), {
|
||||
"memoryRead": True,
|
||||
"memoryResult": {"clients": clients_mem, "projects": [], "tasks": [], "repositories": [], "memories": []},
|
||||
"memoryQuery": "",
|
||||
}
|
||||
|
||||
return "", {}
|
||||
|
||||
|
||||
@@ -630,6 +710,13 @@ def formater_memoire(resultat):
|
||||
return "Voici ce que j'ai trouve :\n" + "\n".join(f"- {ligne}" for ligne in lignes[:10])
|
||||
|
||||
|
||||
def formater_liste_clients(clients_mem):
|
||||
if not clients_mem:
|
||||
return "Je n'ai encore aucun client dans la memoire professionnelle."
|
||||
noms = [client_mem["name"] for client_mem in clients_mem]
|
||||
return "Voici tes clients :\n" + "\n".join(f"- {nom}" for nom in noms)
|
||||
|
||||
|
||||
def traiter_message(session_id, texte, avec_audio=False):
|
||||
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)
|
||||
|
||||
63
memory.py
63
memory.py
@@ -195,6 +195,69 @@ def add_task(title, client_name="", project_name="", details="", due_at=""):
|
||||
return row_to_dict(db.execute("SELECT * FROM tasks WHERE id = ?", (cursor.lastrowid,)).fetchone())
|
||||
|
||||
|
||||
def list_clients(limit=100):
|
||||
with connect() as db:
|
||||
rows = db.execute(
|
||||
"SELECT * FROM clients ORDER BY name COLLATE NOCASE LIMIT ?",
|
||||
(limit,),
|
||||
).fetchall()
|
||||
return [row_to_dict(row) for row in rows]
|
||||
|
||||
|
||||
def get_memory_snapshot(limit=25):
|
||||
with connect() as db:
|
||||
clients = db.execute(
|
||||
"""
|
||||
SELECT c.*,
|
||||
COUNT(t.id) AS open_task_count
|
||||
FROM clients c
|
||||
LEFT JOIN tasks t ON t.client_id = c.id AND t.done = 0
|
||||
GROUP BY c.id
|
||||
ORDER BY c.name COLLATE NOCASE
|
||||
LIMIT ?
|
||||
""",
|
||||
(limit,),
|
||||
).fetchall()
|
||||
tasks = db.execute(
|
||||
"""
|
||||
SELECT t.*, c.name AS client_name, p.name AS project_name
|
||||
FROM tasks t
|
||||
LEFT JOIN clients c ON c.id = t.client_id
|
||||
LEFT JOIN projects p ON p.id = t.project_id
|
||||
WHERE t.done = 0
|
||||
ORDER BY t.created_at DESC
|
||||
LIMIT ?
|
||||
""",
|
||||
(limit,),
|
||||
).fetchall()
|
||||
projects = db.execute(
|
||||
"""
|
||||
SELECT p.*, c.name AS client_name
|
||||
FROM projects p
|
||||
LEFT JOIN clients c ON c.id = p.client_id
|
||||
ORDER BY p.updated_at DESC
|
||||
LIMIT ?
|
||||
""",
|
||||
(limit,),
|
||||
).fetchall()
|
||||
repos = db.execute(
|
||||
"""
|
||||
SELECT r.*, p.name AS project_name
|
||||
FROM repositories r
|
||||
LEFT JOIN projects p ON p.id = r.project_id
|
||||
ORDER BY r.updated_at DESC
|
||||
LIMIT ?
|
||||
""",
|
||||
(limit,),
|
||||
).fetchall()
|
||||
return {
|
||||
"clients": [row_to_dict(row) for row in clients],
|
||||
"tasks": [row_to_dict(row) for row in tasks],
|
||||
"projects": [row_to_dict(row) for row in projects],
|
||||
"repositories": [row_to_dict(row) for row in repos],
|
||||
}
|
||||
|
||||
|
||||
def close_task(task_id):
|
||||
with connect() as db:
|
||||
row = db.execute(
|
||||
|
||||
Reference in New Issue
Block a user