This commit is contained in:
2026-04-27 15:56:25 +02:00
parent 7fb709811c
commit b23a1de6f3
2 changed files with 88 additions and 12 deletions

57
app.py
View File

@@ -71,6 +71,7 @@ Si une phrase contient plusieurs choses a enregistrer, utilise :
{"actions": [{...}, {...}]} {"actions": [{...}, {...}]}
Quand l'utilisateur demande ce que tu sais d'un client, d'un projet, d'une tache ou d'un depot, utilise chercher_memoire. Quand l'utilisateur demande ce que tu sais d'un client, d'un projet, d'une tache ou d'un depot, utilise chercher_memoire.
Si l'utilisateur dit "pour CLIENT" en ajoutant une tache, renseigne toujours le champ client avec CLIENT.
Pour tout le reste, reponds en francais naturel, avec des phrases courtes. Pour tout le reste, reponds en francais naturel, avec des phrases courtes.
N'utilise pas d'anglais sauf si l'utilisateur le demande explicitement. N'utilise pas d'anglais sauf si l'utilisateur le demande explicitement.
@@ -186,13 +187,21 @@ def detecter_action_directe(texte):
{ {
"action": "ajouter_client", "action": "ajouter_client",
"nom": nom, "nom": nom,
"notes": "Ajoute depuis une liste dictee par Laurent.", "notes": "Ajoute depuis une liste fournie par Laurent.",
"statut": "actif", "statut": "actif",
} }
for nom in clients_a_ajouter for nom in clients_a_ajouter
] ]
} }
tache_client = detecter_tache_client(texte_nettoye)
if tache_client:
return tache_client
recherche_taches = detecter_recherche_taches(texte_nettoye)
if recherche_taches:
return recherche_taches
recherche_match = re.search( recherche_match = re.search(
r"(?:qu(?:'| )?est[- ]?ce que tu sais sur|que sais[- ]?tu sur|cherche dans la memoire|memoire sur)\s+(.+)", r"(?:qu(?:'| )?est[- ]?ce que tu sais sur|que sais[- ]?tu sur|cherche dans la memoire|memoire sur)\s+(.+)",
texte_nettoye, texte_nettoye,
@@ -261,6 +270,45 @@ def detecter_action_directe(texte):
return {"actions": actions} return {"actions": actions}
def detecter_tache_client(texte):
if not re.search(r"\b(note|notes|noter|tache|doit|dois|a faire|à faire)\b", texte, flags=re.IGNORECASE):
return None
match = re.search(
r"\bpour\s+(?:mon\s+client\s+|le\s+client\s+)?([A-Z0-9][A-Z0-9&.\- ]{1,40}?)[,\s]+(?:on\s+)?(?:doit|dois|devra|faut)\s+(.+?)(?:\s+tu\s+peux\s+noter.*|\s+note.*|\s+notes.*|\s*$)",
texte,
flags=re.IGNORECASE,
)
if not match:
return None
client_nom = nettoyer_nom_client(match.group(1))
titre = nettoyer_titre_tache(match.group(2))
if not client_nom or not titre:
return None
return {
"action": "ajouter_tache",
"titre": titre,
"client": client_nom,
"details": texte,
}
def detecter_recherche_taches(texte):
match = re.search(
r"\b(?:que\s+dois[- ]?je\s+faire|quoi\s+faire|taches?|a faire|à faire)\b.*\b(?:pour|sur)\s+(?:mon\s+client\s+|le\s+client\s+)?([A-Z0-9][A-Z0-9&.\- ]{1,40})",
texte,
flags=re.IGNORECASE,
)
if not match:
return None
client_nom = nettoyer_nom_client(match.group(1))
if not client_nom:
return None
return {"action": "chercher_memoire", "requete": client_nom}
def extraire_liste_clients(texte): def extraire_liste_clients(texte):
if not re.search(r"\bclients?\b", texte, flags=re.IGNORECASE): if not re.search(r"\bclients?\b", texte, flags=re.IGNORECASE):
return [] return []
@@ -316,6 +364,13 @@ def nettoyer_nom_client(nom):
return nom return nom
def nettoyer_titre_tache(titre):
titre = titre.strip(" -\t\r.,;:?")
titre = re.sub(r"^de\s+", "", titre, flags=re.IGNORECASE)
titre = re.sub(r"\s+", " ", titre)
return titre[:1].upper() + titre[1:] if titre else ""
def transcrire_audio(fichier): def transcrire_audio(fichier):
suffix = Path(fichier.filename or "voice.webm").suffix or ".webm" suffix = Path(fichier.filename or "voice.webm").suffix or ".webm"
with tempfile.NamedTemporaryFile(delete=False, suffix=suffix) as tmp: with tempfile.NamedTemporaryFile(delete=False, suffix=suffix) as tmp:

View File

@@ -245,21 +245,34 @@ def add_memory(content, kind="note", subject="", client_name="", project_name=""
def search_memory(query="", limit=12): def search_memory(query="", limit=12):
query = clean_text(query) query = clean_text(query)
like = f"%{query}%" like = f"%{query}%"
search_long_text = int(len(query) > 4)
with connect() as db: with connect() as db:
if query: if query:
clients = db.execute( clients = db.execute(
"SELECT * FROM clients WHERE name LIKE ? OR notes LIKE ? ORDER BY updated_at DESC LIMIT ?", """
(like, like, limit), SELECT * FROM clients
WHERE name LIKE ? OR (? = 1 AND notes LIKE ?)
ORDER BY
CASE WHEN name = ? COLLATE NOCASE THEN 0 ELSE 1 END,
updated_at DESC
LIMIT ?
""",
(like, search_long_text, like, query, limit),
).fetchall() ).fetchall()
projects = db.execute( projects = db.execute(
""" """
SELECT p.*, c.name AS client_name SELECT p.*, c.name AS client_name
FROM projects p FROM projects p
LEFT JOIN clients c ON c.id = p.client_id LEFT JOIN clients c ON c.id = p.client_id
WHERE p.name LIKE ? OR p.summary LIKE ? OR p.next_action LIKE ? OR c.name LIKE ? WHERE p.name LIKE ?
ORDER BY p.updated_at DESC LIMIT ? OR c.name LIKE ?
OR (? = 1 AND (p.summary LIKE ? OR p.next_action LIKE ?))
ORDER BY
CASE WHEN p.name = ? COLLATE NOCASE OR c.name = ? COLLATE NOCASE THEN 0 ELSE 1 END,
p.updated_at DESC
LIMIT ?
""", """,
(like, like, like, like, limit), (like, like, search_long_text, like, like, query, query, limit),
).fetchall() ).fetchall()
tasks = db.execute( tasks = db.execute(
""" """
@@ -268,9 +281,12 @@ def search_memory(query="", limit=12):
LEFT JOIN clients c ON c.id = t.client_id LEFT JOIN clients c ON c.id = t.client_id
LEFT JOIN projects p ON p.id = t.project_id LEFT JOIN projects p ON p.id = t.project_id
WHERE t.done = 0 AND (t.title LIKE ? OR t.details LIKE ? OR c.name LIKE ? OR p.name LIKE ?) WHERE t.done = 0 AND (t.title LIKE ? OR t.details LIKE ? OR c.name LIKE ? OR p.name LIKE ?)
ORDER BY t.created_at DESC LIMIT ? ORDER BY
CASE WHEN c.name = ? COLLATE NOCASE OR p.name = ? COLLATE NOCASE THEN 0 ELSE 1 END,
t.created_at DESC
LIMIT ?
""", """,
(like, like, like, like, limit), (like, like, like, like, query, query, limit),
).fetchall() ).fetchall()
repos = db.execute( repos = db.execute(
""" """
@@ -278,9 +294,12 @@ def search_memory(query="", limit=12):
FROM repositories r FROM repositories r
LEFT JOIN projects p ON p.id = r.project_id LEFT JOIN projects p ON p.id = r.project_id
WHERE r.name LIKE ? OR r.local_path LIKE ? OR r.remote_url LIKE ? OR p.name LIKE ? WHERE r.name LIKE ? OR r.local_path LIKE ? OR r.remote_url LIKE ? OR p.name LIKE ?
ORDER BY r.updated_at DESC LIMIT ? ORDER BY
CASE WHEN r.name = ? COLLATE NOCASE OR p.name = ? COLLATE NOCASE THEN 0 ELSE 1 END,
r.updated_at DESC
LIMIT ?
""", """,
(like, like, like, like, limit), (like, like, like, like, query, query, limit),
).fetchall() ).fetchall()
notes = db.execute( notes = db.execute(
""" """
@@ -288,10 +307,12 @@ def search_memory(query="", limit=12):
FROM memories m FROM memories m
LEFT JOIN clients c ON c.id = m.client_id LEFT JOIN clients c ON c.id = m.client_id
LEFT JOIN projects p ON p.id = m.project_id LEFT JOIN projects p ON p.id = m.project_id
WHERE m.subject LIKE ? OR m.content LIKE ? OR c.name LIKE ? OR p.name LIKE ? WHERE c.name LIKE ?
OR p.name LIKE ?
OR (? = 1 AND (m.subject LIKE ? OR m.content LIKE ?))
ORDER BY m.created_at DESC LIMIT ? ORDER BY m.created_at DESC LIMIT ?
""", """,
(like, like, like, like, limit), (like, like, search_long_text, like, like, limit),
).fetchall() ).fetchall()
else: else:
clients = db.execute("SELECT * FROM clients ORDER BY updated_at DESC LIMIT ?", (limit,)).fetchall() clients = db.execute("SELECT * FROM clients ORDER BY updated_at DESC LIMIT ?", (limit,)).fetchall()