feat: Léa humanisée — plus de jargon technique, ton chaleureux

- "Workflow" → "tâche" partout
- Vouvoiement, ton de collègue bienveillante
- Noms de tâches lisibles (Bloc-notes — Écriture et sauvegarde)
- Notifications féminisées (Connectée, prête)
- Boutons : Apprenez-moi, Lancer, Données, Arrêter, Aide
- Intent parser enrichi (langage naturel humain)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Dom
2026-03-17 23:36:28 +01:00
parent 4e217e30dd
commit 32c6808afb
2 changed files with 99 additions and 91 deletions

View File

@@ -60,39 +60,40 @@ class ResponseGenerator:
"""
# Templates de réponses par type d'intention
# Ton : collègue chaleureuse et professionnelle, vouvoiement
RESPONSE_TEMPLATES = {
IntentType.EXECUTE: {
"success": [
"J'ai lancé le workflow '{workflow}'. {details}",
"Le workflow '{workflow}' est en cours d'exécution. {details}",
"C'est parti pour '{workflow}' ! {details}"
"C'est parti, je lance '{workflow}'. {details}",
"Je m'occupe de '{workflow}'. {details}",
"'{workflow}' est en cours ! {details}"
],
"error": [
"Impossible d'exécuter '{workflow}': {error}",
"Erreur lors du lancement de '{workflow}': {error}",
"Le workflow '{workflow}' a échoué: {error}"
"Hmm, je n'ai pas réussi à faire '{workflow}' : {error}",
"Désolée, '{workflow}' a rencontré un souci : {error}",
"Oups, '{workflow}' n'a pas fonctionné : {error}"
],
"not_found": [
"Je ne sais pas encore faire '{query}'. Montre-moi comment faire et je l'apprendrai !",
"'{query}' m'est inconnu pour l'instant. Tu peux me montrer en enregistrant un workflow.",
"Je ne connais pas '{query}'. Montre-moi et je m'en souviendrai !"
"Je ne connais pas encore '{query}'. Montrez-moi comment faire et je l'apprendrai !",
"'{query}' m'est inconnu pour l'instant. Vous pouvez me montrer en cliquant sur « Apprenez-moi ».",
"Je ne sais pas encore faire '{query}'. Montrez-moi et je m'en souviendrai !"
],
"gesture": [
"{gesture_name} ({gesture_keys}) envoyé !",
"Raccourci {gesture_name} ({gesture_keys}) exécuté.",
],
"copilot": [
"Mode pas-à-pas activé pour '{workflow}'. Validez chaque étape.",
"Mode pas-à-pas activé pour '{workflow}'. Je vous demande de valider chaque étape.",
]
},
IntentType.LIST: {
"success": [
"Voici les workflows disponibles :\n{list}",
"J'ai trouvé {count} workflows :\n{list}",
"Voici les tâches que je sais faire :\n{list}",
"J'ai {count} tâches en mémoire :\n{list}",
],
"empty": [
"Aucun workflow n'est configuré pour le moment.",
"La liste des workflows est vide."
"Je n'ai encore appris aucune tâche. Montrez-moi quelque chose !",
"Ma liste est vide pour le moment. Apprenez-moi une première tâche !"
]
},
IntentType.QUERY: {
@@ -101,77 +102,78 @@ class ResponseGenerator:
"À propos de '{topic}' :\n{answer}"
],
"not_found": [
"Je n'ai pas d'information sur '{topic}'.",
"Je ne peux pas répondre à cette question sur '{topic}'."
"Je n'ai pas d'information sur '{topic}'. Pouvez-vous préciser ?",
"Désolée, je ne peux pas vous répondre sur '{topic}'."
]
},
IntentType.HELP: {
"general": [
"Je suis votre assistant RPA. Voici ce que je peux faire :\n\n"
"Exécuter des workflows : \"lance facturation client Acme\"\n"
"Lister les workflows : \"quels workflows sont disponibles ?\"\n"
"• Voir le statut : \"où en est l'exécution ?\"\n"
"Annuler : \"annule\"\n\n"
"Tapez votre commande en langage naturel !",
"Je suis Léa, votre assistante. Voici ce que je peux faire :\n\n"
"Apprendre une tâche : cliquez sur « Apprenez-moi »\n"
"Refaire une tâche : \"lance facturation\" ou cliquez sur « Lancer »\n"
"• Voir mes tâches : \"qu'est-ce que tu sais faire ?\"\n"
"Importer des données : \"importe le fichier Excel\"\n"
"• Arrêter : \"arrête\"\n\n"
"Parlez-moi naturellement, je fais de mon mieux pour comprendre !",
]
},
IntentType.GREETING: {
"default": [
"Bonjour ! Je suis votre assistant RPA. Comment puis-je vous aider ?",
"Salut ! Que puis-je faire pour vous ?",
"Bonjour ! Tapez une commande ou 'aide' pour voir ce que je peux faire.",
"Bonjour ! Je suis Léa. Que puis-je faire pour vous ?",
"Bonjour ! Comment puis-je vous aider aujourd'hui ?",
"Bonjour ! Dites-moi ce dont vous avez besoin, ou tapez « aide ».",
]
},
IntentType.STATUS: {
"running": [
"Exécution en cours : '{workflow}'\nProgression : {progress}%\n{message}",
"Le workflow '{workflow}' s'exécute ({progress}%): {message}"
"Je suis en train de faire '{workflow}' — progression : {progress}%\n{message}",
"'{workflow}' est en cours ({progress}%) : {message}"
],
"idle": [
"Aucune exécution en cours. Système prêt.",
"Tout est calme. Que puis-je faire pour vous ?"
"Tout est calme, je suis disponible. Que puis-je faire pour vous ?",
"Rien en cours. Je suis prête !"
],
"completed": [
"Dernière exécution : '{workflow}' - {status}",
"La dernière tâche '{workflow}' est terminée : {status}",
"'{workflow}' est terminé : {status}"
]
},
IntentType.CANCEL: {
"success": [
"Exécution annulée.",
"J'ai arrêté le workflow en cours.",
"Annulation effectuée."
"C'est arrêté.",
"J'ai tout arrêté.",
"Annulation faite."
],
"nothing": [
"Rien à annuler, aucune exécution en cours.",
"Il n'y a pas d'exécution active."
"Il n'y a rien en cours à arrêter.",
"Rien à annuler, je suis disponible."
]
},
IntentType.HISTORY: {
"success": [
"Voici vos dernières commandes :\n{history}",
"Voici vos dernières actions :\n{history}",
"Historique récent :\n{history}"
],
"empty": [
"Pas encore d'historique.",
"Vous n'avez pas encore exécuté de commandes."
"Vous n'avez encore rien fait avec moi."
]
},
IntentType.CONFIRM: {
"accepted": [
"Très bien, j'exécute '{workflow}'.",
"Très bien, je m'en occupe : '{workflow}'.",
"C'est parti pour '{workflow}' !",
"Confirmé. Lancement de '{workflow}'."
"Entendu. Je lance '{workflow}'."
],
"no_pending": [
"Il n'y a rien à confirmer.",
"Aucune action en attente de confirmation."
"Il n'y a rien à confirmer pour le moment.",
"Aucune action en attente."
]
},
IntentType.DENY: {
"cancelled": [
"Action annulée.",
"D'accord, j'annule.",
"D'accord, c'est annulé.",
"Entendu, j'annule.",
"Compris, on oublie."
]
},
@@ -186,15 +188,15 @@ class ResponseGenerator:
"Fichier **{filename}** prêt : {total_rows} lignes avec les colonnes {columns}. On crée la table '{table_name}' ?",
],
"imported": [
"Table **'{table_name}'** créée avec {row_count} lignes et {col_count} colonnes ({columns}). Vous pouvez maintenant utiliser 'Pour chaque ligne' dans un workflow !",
"Table **'{table_name}'** créée avec {row_count} lignes et {col_count} colonnes ({columns}). Vous pouvez maintenant l'utiliser dans une tâche !",
"Import réussi ! Table **'{table_name}'** : {row_count} lignes, {col_count} colonnes ({columns}).",
],
"list_tables": [
"Voici les tables disponibles :\n{tables_list}",
"Tables dans la base :\n{tables_list}",
"Voici vos tables de données :\n{tables_list}",
"Tables disponibles :\n{tables_list}",
],
"no_tables": [
"Aucune table n'a été importée pour l'instant. Envoyez-moi un fichier Excel pour commencer !",
"Vous n'avez pas encore de données importées. Envoyez-moi un fichier Excel pour commencer !",
"La base est vide. Importez un fichier Excel pour créer votre première table.",
],
"table_info": [
@@ -204,15 +206,15 @@ class ResponseGenerator:
"J'ai trouvé {count} fichiers Excel dans le dossier :\n{files_list}\n\nDites-moi lequel importer !",
],
"folder_empty": [
"Aucun fichier Excel trouvé dans le dossier '{folder}'. Vérifiez le chemin.",
"Je n'ai trouvé aucun fichier Excel dans '{folder}'. Vérifiez le chemin.",
],
"file_not_found": [
"Je n'ai pas trouvé le fichier '{file_path}'. Vérifiez le chemin ou envoyez-le via le bouton 📎.",
"Je n'ai pas trouvé le fichier '{file_path}'. Vérifiez le chemin ou envoyez-le directement.",
"Fichier introuvable : '{file_path}'. Vous pouvez aussi glisser un fichier dans le chat.",
],
"error": [
"Erreur lors de l'import : {error}",
"L'import a échoué : {error}",
"Désolée, l'import a échoué : {error}",
"Oups, un souci lors de l'import : {error}",
],
"uploaded": [
"Fichier **{filename}** reçu ! Je l'analyse...",
@@ -220,9 +222,9 @@ class ResponseGenerator:
},
IntentType.UNKNOWN: {
"default": [
"Je n'ai pas compris. Pouvez-vous reformuler ?",
"Désolé, je ne comprends pas '{query}'. Tapez 'aide' pour voir les commandes.",
"'{query}' ? Je ne suis pas sûr de comprendre."
"Je n'ai pas bien compris. Pouvez-vous reformuler ?",
"Désolée, je ne comprends pas. Tapez « aide » pour voir ce que je sais faire.",
"Hmm, je n'ai pas saisi votre demande. Pouvez-vous préciser ?"
]
}
}
@@ -231,21 +233,21 @@ class ResponseGenerator:
CONTEXTUAL_SUGGESTIONS = {
"after_execute": [
"voir le statut",
"annuler",
"liste des workflows"
"arrêter",
"mes tâches"
],
"after_error": [
"aide",
"liste des workflows",
"mes tâches",
"réessayer"
],
"after_list": [
"exécuter un workflow",
"lancer une tâche",
"aide"
],
"idle": [
"facturer client X",
"liste des workflows",
"qu'est-ce que tu sais faire ?",
"apprenez-moi",
"aide"
],
"after_import": [
@@ -334,7 +336,7 @@ class ResponseGenerator:
Générer un message de progression.
Args:
workflow_name: Nom du workflow
workflow_name: Nom de la tâche
progress: Pourcentage de progression
step: Étape actuelle
current: Numéro de l'étape
@@ -348,11 +350,11 @@ class ResponseGenerator:
filled = int(bar_length * progress / 100)
bar = "" * filled + "" * (bar_length - filled)
message = f"**{workflow_name}** [{bar}] {progress}%\n\nÉtape {current}/{total}: {step}"
message = f"**{workflow_name}** [{bar}] {progress}%\n\nÉtape {current}/{total} : {step}"
return GeneratedResponse(
message=message,
suggestions=["annuler"] if progress < 100 else [],
suggestions=["arrêter"] if progress < 100 else [],
action_required=False,
metadata={
"workflow": workflow_name,
@@ -372,7 +374,7 @@ class ResponseGenerator:
Générer un message de résultat d'exécution.
Args:
workflow_name: Nom du workflow
workflow_name: Nom de la tâche
success: Succès ou échec
message: Message détaillé
duration: Durée d'exécution en secondes
@@ -381,18 +383,14 @@ class ResponseGenerator:
GeneratedResponse avec le résultat
"""
if success:
emoji = ""
status = "terminé avec succès"
response_message = f"C'est fait ! **{workflow_name}** s'est bien passé.\n\n{message}"
suggestions = self.CONTEXTUAL_SUGGESTIONS["idle"]
else:
emoji = ""
status = "échoué"
response_message = f"Hmm, **{workflow_name}** n'a pas fonctionné.\n\n{message}"
suggestions = self.CONTEXTUAL_SUGGESTIONS["after_error"]
response_message = f"{emoji} **{workflow_name}** {status}\n\n{message}"
if duration:
response_message += f"\n\nDurée: {duration:.1f}s"
response_message += f"\n\nDurée : {duration:.1f}s"
return GeneratedResponse(
message=response_message,
@@ -446,7 +444,7 @@ class ResponseGenerator:
template = random.choice(templates["not_found"])
query = result.get("query", intent.raw_query)
message = template.format(query=query)
suggestions = ["lister les workflows", "aide", "enregistrer un workflow"]
suggestions = ["mes tâches", "aide", "apprenez-moi"]
else:
template = random.choice(templates["error"])
@@ -764,7 +762,7 @@ class ResponseGenerator:
suggestions = self.CONTEXTUAL_SUGGESTIONS["after_error"]
else:
message = "Je n'ai pas compris la demande d'import. Précisez le fichier ou dites 'montre les tables'."
message = "Je n'ai pas compris votre demande. Précisez le fichier ou dites « montre les tables »."
suggestions = ["montre les tables", "aide"]
return GeneratedResponse(
@@ -788,7 +786,7 @@ class ResponseGenerator:
return GeneratedResponse(
message=message,
suggestions=["aide", "liste des workflows"],
suggestions=["aide", "mes tâches"],
action_required=False
)