feat: chat unifié, GestureCatalog, Copilot, Léa UI, extraction données, vérification replay
Refonte majeure du système Agent Chat et ajout de nombreux modules : - Chat unifié : suppression du dual Workflows/Agent Libre, tout passe par /api/chat avec résolution en 3 niveaux (workflow → geste → "montre-moi") - GestureCatalog : 38 raccourcis clavier universels Windows avec matching sémantique, substitution automatique dans les replays, et endpoint /api/gestures - Mode Copilot : exécution pas-à-pas des workflows avec validation humaine via WebSocket (approve/skip/abort) avant chaque action - Léa UI (agent_v0/lea_ui/) : interface PyQt5 pour Windows avec overlay transparent pour feedback visuel pendant le replay - Data Extraction (core/extraction/) : moteur d'extraction visuelle de données (OCR + VLM → SQLite), avec schémas YAML et export CSV/Excel - ReplayVerifier (agent_v0/server_v1/) : vérification post-action par comparaison de screenshots, avec logique de retry (max 3) - IntentParser durci : meilleur fallback regex, type GREETING, patterns améliorés - Dashboard : nouvelles pages gestures, streaming, extractions - Tests : 63 tests GestureCatalog, 47 tests extraction, corrections tests existants - Dépréciation : /api/agent/plan et /api/agent/execute retournent HTTP 410, suppression du code hardcodé _plan_to_replay_actions Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -29,6 +29,7 @@ class IntentType(Enum):
|
||||
LIST = "list" # Lister les workflows disponibles
|
||||
CONFIGURE = "configure" # Configurer un paramètre
|
||||
HELP = "help" # Demander de l'aide
|
||||
GREETING = "greeting" # Salutation
|
||||
STATUS = "status" # Vérifier le statut
|
||||
CANCEL = "cancel" # Annuler l'exécution en cours
|
||||
HISTORY = "history" # Voir l'historique
|
||||
@@ -74,27 +75,64 @@ class IntentParser:
|
||||
# Patterns pour la détection d'intentions par règles
|
||||
INTENT_PATTERNS = {
|
||||
IntentType.EXECUTE: [
|
||||
r"(?:lance|exécute|démarre|fait|run|start|execute)\s+(.+)",
|
||||
# Verbes d'action explicites
|
||||
r"(?:lance|exécute|démarre|fai[st]|run|start|execute)\s+(.+)",
|
||||
r"(?:je veux|je voudrais|peux-tu)\s+(.+)",
|
||||
r"(?:facturer?|créer?|générer?|exporter?)\s+(.+)",
|
||||
r"^(.+)\s+(?:maintenant|tout de suite|svp|stp)$",
|
||||
# Gestes courants (UI actions) — doivent rester EXECUTE
|
||||
r"(?:ferme[rz]?|ouvr[eir]+[sz]?|clique[rz]?|sélectionne[rz]?|coche[rz]?|décoche[rz]?)\s+(.+)",
|
||||
r"(?:copie[rz]?|colle[rz]?|coupe[rz]?|supprime[rz]?|efface[rz]?)\s+(.+)",
|
||||
r"(?:tape[rz]?|écri[rstv]+[sz]?|saisi[rstv]*[sz]?|rempli[rstv]*[sz]?|entre[rz]?)\s+(.+)",
|
||||
r"(?:scroll(?:e[rz]?)?|défile[rz]?|fait(?:es)?\s+défiler)\s*(.+)?",
|
||||
r"(?:glisse[rz]?|drag(?:ue)?[rz]?|déplace[rz]?|bouge[rz]?)\s+(.+)",
|
||||
r"(?:double[- ]?clique[rz]?|clic\s+droit)\s+(.+)?",
|
||||
r"(?:enregistre[rz]?|sauvegarde[rz]?|save)\s+(.+)?",
|
||||
r"(?:imprime[rz]?|print)\s+(.+)?",
|
||||
r"(?:envoie[rz]?|send|mail(?:e[rz]?)?|transmet[sz]?)\s+(.+)",
|
||||
r"(?:télécharge[rz]?|download|upload)\s+(.+)?",
|
||||
r"(?:actualise[rz]?|rafraîchi[rstv]*[sz]?|refresh|recharge[rz]?)\s*(.+)?",
|
||||
r"(?:valide[rz]?|confirme[rz]?|soumets?|submit)\s+(.+)",
|
||||
r"(?:connecte[rz]?|login|log\s*in|sign\s*in)\s*(.+)?",
|
||||
r"(?:déconnecte[rz]?|logout|log\s*out|sign\s*out)\s*(.+)?",
|
||||
# Raccourcis clavier
|
||||
r"(?:ctrl|alt|shift|maj)\s*\+\s*\w+",
|
||||
],
|
||||
IntentType.LIST: [
|
||||
r"(?:liste|montre|affiche|quels sont)\s+(?:les\s+|des\s+)?(?:workflows?|processus|automatisations?)",
|
||||
r"(?:liste|montre|affiche|quels?\s+sont)\s+(?:les\s+|des\s+)?(?:workflows?|processus|automatisations?)",
|
||||
r"(?:quels?|quelles?)\s+(?:workflows?|processus|automatisations?)",
|
||||
r"liste\s+des\s+workflows?",
|
||||
r"(?:qu'est-ce que|que)\s+(?:je peux|tu peux)\s+faire",
|
||||
r"(?:workflows?|processus)\s+disponibles?",
|
||||
r"(?:voir|afficher)\s+(?:les\s+|tous\s+les\s+)?workflows?",
|
||||
],
|
||||
IntentType.QUERY: [
|
||||
r"(?:comment|pourquoi|quand|où|qui)\s+(.+)\?",
|
||||
# Questions directes avec mots interrogatifs
|
||||
r"(?:comment|pourquoi|quand|où|qui)\s+(.+)\??",
|
||||
r"(?:explique|décris|détaille)\s+(.+)",
|
||||
r"(?:qu'est-ce que|c'est quoi)\s+(.+)",
|
||||
# Questions avec "quel/quelle/quels/quelles" (exclure workflows → LIST)
|
||||
r"(?:quels?|quelles?)\s+(?!workflows?|processus|automatisations?)(.+)\??",
|
||||
# "quoi" comme question (pas une commande, pas "quoi faire" = HELP)
|
||||
r"^(?:c'est\s+)?quoi\s+(?!faire)(.+)\??$",
|
||||
r"^quoi\s*\?+$",
|
||||
# Questions indirectes
|
||||
r"(?:dis[- ]moi|raconte|informe[- ]moi)\s+(.+)",
|
||||
r"(?:je\s+(?:me\s+)?demande|je\s+(?:ne\s+)?comprends?\s+pas)\s+(.+)",
|
||||
],
|
||||
IntentType.HELP: [
|
||||
r"(?:aide|help|assistance|sos)",
|
||||
r"(?:comment ça marche|comment utiliser)",
|
||||
r"^(?:aide|help|assistance|sos)$",
|
||||
r"comment ça (?:marche|fonctionne)\s*\??",
|
||||
r"comment (?:utiliser|ça s'utilise|on fait)\s*\??",
|
||||
r"\?{2,}",
|
||||
# "que peux-tu faire", "quoi faire" = demande d'aide
|
||||
r"(?:qu'est-ce que|que)\s+(?:je peux|tu peux)\s+faire",
|
||||
r"^quoi\s+faire\s*\??$",
|
||||
r"(?:que\s+)?(?:puis-je|peux-tu|peut-on)\s+faire\s*\??",
|
||||
r"(?:besoin\s+d'aide|j'ai\s+besoin\s+d'aide)",
|
||||
],
|
||||
IntentType.GREETING: [
|
||||
r"^(?:bonjour|bonsoir|salut|hello|hi|hey|coucou|yo|wesh)(?:\s.*)?$",
|
||||
r"^(?:bonne?\s+(?:journée|soirée|nuit|matinée))$",
|
||||
],
|
||||
IntentType.STATUS: [
|
||||
r"(?:statut|status|état|où en est)",
|
||||
@@ -119,6 +157,35 @@ class IntentParser:
|
||||
],
|
||||
}
|
||||
|
||||
# Verbes d'action reconnus pour le fallback EXECUTE
|
||||
# Si aucun pattern ne matche, on vérifie la présence d'un de ces verbes
|
||||
# avant de classifier en EXECUTE
|
||||
ACTION_VERBS = {
|
||||
# Actions de workflow/exécution
|
||||
"lance", "lancer", "exécute", "exécuter", "démarre", "démarrer",
|
||||
"fait", "fais", "run", "start", "execute",
|
||||
# Actions métier
|
||||
"facture", "facturer", "crée", "créer", "génère", "générer",
|
||||
"exporte", "exporter", "importe", "importer",
|
||||
# Actions UI / gestes
|
||||
"ferme", "fermer", "ouvre", "ouvrir", "clique", "cliquer",
|
||||
"sélectionne", "sélectionner", "coche", "cocher", "décoche", "décocher",
|
||||
"copie", "copier", "colle", "coller", "coupe", "couper",
|
||||
"supprime", "supprimer", "efface", "effacer",
|
||||
"tape", "taper", "écris", "écrire", "saisis", "saisir",
|
||||
"remplis", "remplir", "entre", "entrer",
|
||||
"scroll", "scroller", "défile", "défiler",
|
||||
"glisse", "glisser", "déplace", "déplacer", "drag",
|
||||
"enregistre", "enregistrer", "sauvegarde", "sauvegarder", "save",
|
||||
"imprime", "imprimer", "print",
|
||||
"envoie", "envoyer", "send", "transmet", "transmettre",
|
||||
"télécharge", "télécharger", "download", "upload",
|
||||
"actualise", "actualiser", "rafraîchis", "rafraîchir", "refresh",
|
||||
"valide", "valider", "confirme", "confirmer", "soumets", "soumettre",
|
||||
"connecte", "connecter", "déconnecte", "déconnecter",
|
||||
"login", "logout",
|
||||
}
|
||||
|
||||
# Patterns pour l'extraction d'entités
|
||||
ENTITY_PATTERNS = {
|
||||
"client": [
|
||||
@@ -280,11 +347,18 @@ class IntentParser:
|
||||
best_confidence = confidence
|
||||
best_intent = intent_type
|
||||
|
||||
# Si aucune intention trouvée mais la requête ressemble à une commande
|
||||
# Fallback durci : ne classifier en EXECUTE que si un verbe d'action est présent
|
||||
if best_intent == IntentType.UNKNOWN and len(query.split()) >= 2:
|
||||
# Supposer que c'est une demande d'exécution
|
||||
best_intent = IntentType.EXECUTE
|
||||
best_confidence = 0.4
|
||||
words = query.lower().split()
|
||||
# Vérifier si au moins un mot est un verbe d'action connu
|
||||
has_action_verb = any(word in self.ACTION_VERBS for word in words)
|
||||
if has_action_verb:
|
||||
best_intent = IntentType.EXECUTE
|
||||
best_confidence = 0.40
|
||||
else:
|
||||
# Pas de verbe d'action reconnu → demander clarification
|
||||
best_intent = IntentType.CLARIFY
|
||||
best_confidence = 0.30
|
||||
|
||||
return best_intent, best_confidence
|
||||
|
||||
@@ -389,13 +463,14 @@ REQUÊTE: "{query}"
|
||||
{f"Contexte conversation: {json.dumps(context, ensure_ascii=False)}" if context else ""}
|
||||
|
||||
INTENTIONS POSSIBLES:
|
||||
- execute: l'utilisateur veut lancer/exécuter un workflow
|
||||
- execute: l'utilisateur veut lancer/exécuter un workflow ou une action UI (geste)
|
||||
- list: l'utilisateur veut voir les workflows disponibles (mots-clés: liste, quels, workflows, disponibles, montrer)
|
||||
- query: l'utilisateur pose une question sur un workflow
|
||||
- query: l'utilisateur pose une question (comment, pourquoi, c'est quoi, quel)
|
||||
- status: l'utilisateur demande le statut d'exécution
|
||||
- cancel: l'utilisateur veut annuler
|
||||
- history: l'utilisateur veut voir l'historique
|
||||
- help: l'utilisateur demande de l'aide
|
||||
- help: l'utilisateur demande de l'aide ou ce qu'il peut faire
|
||||
- greeting: l'utilisateur dit bonjour/salut/hello
|
||||
- confirm: l'utilisateur confirme (oui, ok, go)
|
||||
- deny: l'utilisateur refuse (non, annule)
|
||||
- unknown: impossible à déterminer
|
||||
@@ -504,16 +579,37 @@ if __name__ == "__main__":
|
||||
parser = IntentParser(use_llm=False)
|
||||
|
||||
test_queries = [
|
||||
# EXECUTE — actions explicites
|
||||
"facturer le client Acme",
|
||||
"lance le workflow de facturation",
|
||||
"quels workflows sont disponibles ?",
|
||||
"aide",
|
||||
"oui",
|
||||
"annule",
|
||||
"statut",
|
||||
"exporter le rapport en PDF pour Client ABC",
|
||||
"créer une facture de 1500€ pour Société XYZ",
|
||||
"facturer les clients de A à Z",
|
||||
# EXECUTE — gestes UI
|
||||
"ferme la fenêtre",
|
||||
"ouvre un nouvel onglet",
|
||||
"copier le texte",
|
||||
"lance la facturation",
|
||||
# LIST
|
||||
"quels workflows sont disponibles ?",
|
||||
"liste des workflows",
|
||||
# QUERY — questions
|
||||
"comment ça marche ?",
|
||||
"c'est quoi ce workflow",
|
||||
"pourquoi ce processus est lent ?",
|
||||
# HELP
|
||||
"aide",
|
||||
"quoi faire ?",
|
||||
"que peux-tu faire ?",
|
||||
# GREETING
|
||||
"bonjour",
|
||||
"salut",
|
||||
# Confirmations / annulations
|
||||
"oui",
|
||||
"annule",
|
||||
"statut",
|
||||
# Fallback — ne doit PAS être EXECUTE
|
||||
"blah blah test",
|
||||
]
|
||||
|
||||
print("=== Tests IntentParser ===\n")
|
||||
|
||||
Reference in New Issue
Block a user