logo
Développement
Rechercher
ÉvénementsClés

I. Qu'est-ce qu'un « Événement Clé »

Les « Événements Clés » constituent la capacité de mémoire métier à long terme intégrée à GPTBots : pendant les échanges multi-tours entre l'utilisateur et le Bot, la plateforme appelle le LLM pour identifier automatiquement, dans la conversation, des événements à valeur métier (retrait, plainte, prise de rendez-vous, remboursement, etc.), les stocke de manière structurée par utilisateur, et les réinjecte ensuite comme contexte dans le Bot, afin que celui-ci « se souvienne » de ce que cet utilisateur a vécu et de l'avancement actuel de chaque événement.

Les problèmes fondamentaux résolus sont :

  • Perte de mémoire inter-conversations : un LLM traditionnel ne voit que la fenêtre de mémoire à court terme de la conversation en cours ; entre conversations ou dans une longue conversation, les actions métier clés sont oubliées.
  • Sédimentation de données structurées : les conversations dispersées sont sédimentées en flux d'événements interrogeables, statistiquement exploitables et auditables, réutilisables par le contrôle des risques, le contrôle qualité du service client et le profil utilisateur.
  • Suivi de l'avancement de l'état : chaque événement possède un statut PENDING / IN_PROGRESS / RESOLVED / CLOSED, qui peut être continuellement progressé d'une conversation à l'autre.
    alt text

II. Philosophie de conception

1. Sédimenter la "conversation" en "flux d'événements"

Une conversation est non structurée, un événement est structuré. Les événements clés traduisent "ce que l'utilisateur a dit, ce qu'il a fait" en enregistrements d'événements de la forme « catégorie + résumé + entités + statut + priorité + confiance », rendant cette mémoire consommable par les systèmes en aval (statistiques, contrôle des risques, contrôle qualité humain) au-delà du LLM.

2. Double déclenchement, ni manque ni excès

Au sein d'une même conversation, un événement peut survenir en cours de route, ou bien nécessiter une extraction de complément après le départ de l'utilisateur. Le système adopte un schéma à trois niveaux : seuil de messages (temps réel) + délai d'inactivité (lot) + déclenchement manuel (filet de sécurité), et le développeur peut ajuster les paramètres pour arbitrer entre coût et délai.

3. Extraction LLM activée par défaut, repli vers un modèle moins coûteux possible

L'extraction d'événements nécessite elle-même une inférence LLM, qui consomme des Tokens. Le modèle d'extraction et le modèle principal de conversation du Bot peuvent donc être configurés indépendamment — par exemple, le dialogue principal peut utiliser Claude / GPT, tandis que l'extraction utilise un petit modèle moins cher, facturé et optimisé séparément.

4. Double chaîne d'identité utilisateur en filet de sécurité

Les événements sont agrégés par utilisateur. Le userId transmis par le développeur (identifiant de plus haut niveau) est utilisé en priorité ; en son absence, on retombe sur l'anonymousId généré par la plateforme (par exemple pour un utilisateur non connecté). Même si le développeur ne transmet pas de userId, les conversations des visiteurs anonymes peuvent toujours alimenter l'accumulation d'événements.

5. Isolation stricte du périmètre utilisateur, prévention de la pollution par hallucination LLM

Lors des opérations UPDATE / DELETE / MERGE, le LLM peut "fabriquer" l'eventId d'un autre utilisateur. Le code effectue une vérification matchesUserScope pour chaque opération, en imposant userId / anonymousId comme filtre dur, afin d'éviter la pollution croisée entre utilisateurs.

6. Injection dans le Prompt par deux voies : explicite + implicite

  • Explicite : écrire le placeholder {{key_event_<eventType>}} dans le Prompt pour récupérer la valeur précisément par type d'événement.
  • Implicite : si aucun placeholder n'est présent, ajouter automatiquement la section ## Recent Key Events à la fin du Prompt, utilisable sans configuration.

III. Principe de fonctionnement

3.1 Modèle de données

Rôle Remarque
Table principale des événements clés Indexée multidimensionnellement par utilisateur/type/temps
Configuration au niveau Bot (unique par Bot) Contrôle l'interrupteur, les seuils, les règles d'extraction
État d'extraction au niveau session Enregistre le nombre de messages en attente, le temps d'inactivité, l'état de concurrence
Journal d'exécution d'extraction Audit de chaque extraction + consommation Token / crédits

Structure principale d'un événement (BotEventEntity), champs essentiels :

Champ Signification
eventType Catégorie d'événement, strictement conforme au dictionnaire configuré sur le Bot (ex. withdrawal / complaint)
summary Résumé d'événement, ≤ 200 caractères
status PENDING (à traiter) / IN_PROGRESS (en cours) / RESOLVED (résolu) / CLOSED (fermé)
priority LOW / MEDIUM / HIGH / CRITICAL
confidence Confiance auto-évaluée par le LLM : HIGH (donnée API) / MEDIUM (confirmation des deux parties) / LOW (déclaration unilatérale de l'utilisateur)
credibilityLabel Étiquette de véracité en langage naturel (« Confirmé par l'API système » / « Déclaré par l'utilisateur, à vérifier » / « Confirmation des deux parties »)
disputeFlag Indique l'existence d'informations contradictoires (déclaration de l'utilisateur ↔ données système en conflit)
entities Entités structurées en KV flexible (peut stocker montant, numéro de commande, heure, etc.)
relatedEventIds ID des événements associés (typiquement utilisé comme pointeur de source après MERGE)
sourceMsgIds Liste des ID de messages ayant déclenché cet événement
createdBy Source : LLM / API / UI

3.2 Mécanisme de déclenchement à trois niveaux

┌── Niveau 1 : Déclenchement temps réel ─────────────────┐ │ Chaque message utilisateur incrémente le compteur de 1 │ │ pendingMessageCount ≥ messageThreshold │ │ Appel immédiat au LLM pour extraction │ └────────────────────────────────────────────────────────┘ ┌── Niveau 2 : Déclenchement par inactivité ─────────────┐ │ Scan périodique (cycle de 30/60/300 secondes) │ │ Conditions à remplir : │ │ - lastMessageTime > il y a idleTimeout │ │ - pendingMessageCount > 0 │ │ - extractionStatus == IDLE │ └────────────────────────────────────────────────────────┘ ┌── Niveau 3 : Déclenchement manuel ─────────────────────┐ │ Appel API : │ │ POST /bot/event/execute/.../retry │ │ Ou clic « Réessayer » dans la page de journaux │ └────────────────────────────────────────────────────────┘
                      
                      ┌── Niveau 1 : Déclenchement temps réel ─────────────────┐
│ Chaque message utilisateur incrémente le compteur de 1 │
│ pendingMessageCount ≥ messageThreshold                 │
│ Appel immédiat au LLM pour extraction                  │
└────────────────────────────────────────────────────────┘
┌── Niveau 2 : Déclenchement par inactivité ─────────────┐
│ Scan périodique (cycle de 30/60/300 secondes)          │
│ Conditions à remplir :                                 │
│   - lastMessageTime > il y a idleTimeout               │
│   - pendingMessageCount > 0                            │
│   - extractionStatus == IDLE                           │
└────────────────────────────────────────────────────────┘
┌── Niveau 3 : Déclenchement manuel ─────────────────────┐
│ Appel API :                                            │
│   POST /bot/event/execute/.../retry                    │
│ Ou clic « Réessayer » dans la page de journaux         │
└────────────────────────────────────────────────────────┘

                    
Ce bloc de code dans la fenêtre flottante

Les trois entrées convergent finalement vers un même pipeline (BotEventExtractionService.extract), et un verrou Redis (bot:event:extract:{botId}:{conversationId}, expiration 5 minutes) garantit qu'il n'y a pas d'extraction concurrente sur la même session.

3.3 Pipeline d'extraction

1. Validation de l'interrupteur → Acquisition du verrou Redis 2. Lecture de l'identité avec triple repli Track / Redis / c_conversation 3. Récupération des nouveaux messages depuis lastExtractedMessageTime (≤ 100 messages) + Ajout en amont de 10 messages historiques pour garantir un contexte complet + En cas de déclenchement temps réel, élagage de la queue de la fenêtre de mémoire à court terme (alignement avec la fenêtre du dialogue principal) 4. Récupération des N derniers événements historiques de cet utilisateur (recentEventCount) 5. Construction du Prompt selon le modèle : - Règles d'extraction personnalisées par l'utilisateur - Catégories d'événements autorisées (name + description) - Événements historiques (pour comparaison de déduplication) - Conversation à analyser 6. Sélection du modèle d'extraction, transmission du JSON Schema (uniquement effectif sur la famille OpenAI) 7. Analyse du tableau d'opérations renvoyé par le LLM : CREATE → création d'un nouvel événement UPDATE → mise à jour du statut/résumé d'un événement existant MERGE → fusion de plusieurs événements redondants DELETE → suppression douce (rétractation/négation par l'utilisateur) 8. Vérification stricte du périmètre inter-utilisateurs 9. Écriture de la consommation de crédits (type CONSUME_KEY_EVENT) 10. Écriture du journal d'exécution + réinitialisation de Track
                      
                      1. Validation de l'interrupteur → Acquisition du verrou Redis
2. Lecture de l'identité avec triple repli Track / Redis / c_conversation
3. Récupération des nouveaux messages depuis lastExtractedMessageTime (≤ 100 messages)
   + Ajout en amont de 10 messages historiques pour garantir un contexte complet
   + En cas de déclenchement temps réel, élagage de la queue de la fenêtre de mémoire à court terme (alignement avec la fenêtre du dialogue principal)
4. Récupération des N derniers événements historiques de cet utilisateur (recentEventCount)
5. Construction du Prompt selon le modèle :
   - Règles d'extraction personnalisées par l'utilisateur
   - Catégories d'événements autorisées (name + description)
   - Événements historiques (pour comparaison de déduplication)
   - Conversation à analyser
6. Sélection du modèle d'extraction, transmission du JSON Schema (uniquement effectif sur la famille OpenAI)
7. Analyse du tableau d'opérations renvoyé par le LLM :
   CREATE  → création d'un nouvel événement
   UPDATE  → mise à jour du statut/résumé d'un événement existant
   MERGE   → fusion de plusieurs événements redondants
   DELETE  → suppression douce (rétractation/négation par l'utilisateur)
8. Vérification stricte du périmètre inter-utilisateurs
9. Écriture de la consommation de crédits (type CONSUME_KEY_EVENT)
10. Écriture du journal d'exécution + réinitialisation de Track

                    
Ce bloc de code dans la fenêtre flottante

3.4 Mécanisme d'injection

Mode A : Ajout automatique (zéro configuration)

Lorsque les événements clés sont activés pour le Bot, et que aucun placeholder {{key_event_*}} n'apparaît dans le Prompt, le système ajoute automatiquement les N derniers événements à la fin du Prompt avant chaque appel LLM, sous le format suivant :

## Recent Key Events eventType: withdrawal | summary: L'utilisateur demande un retrait de 5000 yuans | status: en cours | priority: haute | confidence: haute | updateTime: 2026-04-28 09:21:33 | entities: {"amount":5000,"channel":"bank"} eventType: complaint | summary: L'utilisateur se plaint de la lenteur de réponse du service client | status: résolu | priority: moyenne | confidence: moyenne | updateTime: 2026-04-27 18:02:11
                      
                      ## Recent Key Events
eventType: withdrawal | summary: L'utilisateur demande un retrait de 5000 yuans | status: en cours | priority: haute | confidence: haute | updateTime: 2026-04-28 09:21:33 | entities: {"amount":5000,"channel":"bank"}
eventType: complaint | summary: L'utilisateur se plaint de la lenteur de réponse du service client | status: résolu | priority: moyenne | confidence: moyenne | updateTime: 2026-04-27 18:02:11

                    
Ce bloc de code dans la fenêtre flottante

Mode B : Substitution de placeholder (contrôle précis)

Dans le Prompt / les composants de workflow / les règles, écrire :

{{key_event_withdrawal}} ← Injecter uniquement les événements de type "retrait" {{key_event_complaint}} ← Injecter uniquement les événements de type "plainte"
                      
                      {{key_event_withdrawal}}     ← Injecter uniquement les événements de type "retrait"
{{key_event_complaint}}      ← Injecter uniquement les événements de type "plainte"

                    
Ce bloc de code dans la fenêtre flottante

La plateforme génère les variables correspondantes en regroupant par eventType ; les types d'événements non concordants ne sont pas injectés. Au maximum 30 événements par variable.

Flow Bot : contrôle indépendant au niveau composant

Chaque nœud LLM d'un workflow possède sa propre FlowKeyEventConfig : on peut activer/désactiver, sélectionner les types d'événements et configurer recentEventCount (5 par défaut) indépendamment. Les événements ne sont interrogés qu'une fois par session (mis en cache dans ChatContext), et plusieurs nœuds partagent les données.


IV. Guide d'utilisation

4.1 Activation dans le panneau de configuration du Bot

Chemin d'accès : Console Développeur → Détail du Bot → Gestion des Utilisateurs (User Manage) → tiroir « Événements Clés »

Étapes :

  1. Activer l'interrupteur principal
  2. Modèle d'extraction : optionnel ; si non sélectionné, le modèle de dialogue par défaut du Bot est utilisé. Il est recommandé de choisir un modèle peu coûteux (par exemple GPT-4o-mini / série Haiku).
  3. Règles d'extraction (≤ 2000 caractères) : indiquer en langage naturel au LLM ce qui constitue un « événement clé » dans le scénario de ce Bot. Exemple :
    N'extraire que les actions métier liées aux fonds (retrait, dépôt, virement, remboursement). Ignorer les bavardages et les expressions émotionnelles. Les champs d'entités doivent inclure le montant (amount), la devise (currency) et le numéro de commande (orderId).
                          
                          N'extraire que les actions métier liées aux fonds (retrait, dépôt, virement, remboursement).
    Ignorer les bavardages et les expressions émotionnelles.
    Les champs d'entités doivent inclure le montant (amount), la devise (currency) et le numéro de commande (orderId).
    
                        
    Ce bloc de code dans la fenêtre flottante
  4. Nombre d'événements récents (0 à 50) : nombre d'événements injectés dans le Prompt à chaque conversation. 0 signifie aucune injection ; valeurs courantes 5 à 10.
  5. Moments de déclenchement :
    • Seuil de messages (5 à 50) : 10 par défaut.
    • Délai d'inactivité (2 à 60 minutes) : 3 par défaut.
  6. Dictionnaire des catégories d'événements (10 maximum) : chaque catégorie comporte un « nom » (≤ 10 caractères) et une « description » (≤ 100 caractères, indiquant au LLM ce que cette catégorie regroupe).
  7. Cliquer sur Enregistrer.

⚠️ Avertissement : une fois une catégorie déployée, ne la renommez pas à la légère — les événements historiques conservent l'ancien nom et {{key_event_<ancien_nom>}} ne pourra plus récupérer de valeurs. Le frontend affichera un avertissement orange si la catégorie existe déjà.

4.2 Référencer les événements dans le Prompt

Prompt de Bot général

Vous êtes un assistant du service client financier. 【Actions financières récentes de cet utilisateur】 {{key_event_withdrawal}} 【Plaintes récentes de cet utilisateur】 {{key_event_complaint}} Veuillez répondre aux questions de l'utilisateur en vous basant sur le contexte ci-dessus.
                      
                      Vous êtes un assistant du service client financier.

【Actions financières récentes de cet utilisateur】
{{key_event_withdrawal}}

【Plaintes récentes de cet utilisateur】
{{key_event_complaint}}

Veuillez répondre aux questions de l'utilisateur en vous basant sur le contexte ci-dessus.

                    
Ce bloc de code dans la fenêtre flottante

Prompt de composant Flow Bot

  • Cliquer sur un nœud piloté par LLM dans le canevas → trouver la configuration « Mémoire - Événements Clés » dans le panneau de paramétrage.
  • Cocher enable, sélectionner les types d'événements à injecter pour le nœud courant, définir le nombre d'événements récents à rappeler (5 par défaut).

4.3 Suivre les journaux d'exécution d'extraction

Chemin d'accès : Console Développeur → Détail du Bot → Gestion des Utilisateurs → onglet Journaux d'exécution

Informations consultables :

  • Statut de chaque extraction (PENDING / RUNNING / COMPLETED / FAILED)
  • Source de déclenchement (REALTIME / SCHEDULED / MANUAL)
  • Nombre de messages traités / nombre d'événements extraits
  • Consommation de Tokens / consommation de crédits
  • Cause de l'échec + bouton « Réessayer »
  • Tiroir de détail : liste de tous les événements créés / modifiés lors de cette extraction

4.4 Facturation

Les coûts d'appel LLM des événements clés sont comptabilisés dans la rubrique Événements Clés de la facture, séparément de la facturation du flux principal de conversation, ce qui facilite le contrôle individuel des coûts.

V. Scénarios d'utilisation typiques

Scénario Exemples de types d'événements Valeur
Service client financier / paiements internationaux withdrawal retrait / deposit dépôt / kyc authentification d'identité / dispute litige Suivi inter-conversations des actions financières ; lors de la prise en main par le contrôle des risques ou un agent humain, visualisation immédiate du flux métier historique de cet utilisateur
SAV e-commerce refund remboursement / return retour / complaint plainte Maintien automatique de la machine à états SAV de l'utilisateur, progression continue sur plusieurs conversations
Rendez-vous / planification appointment rendez-vous / cancellation annulation Permet au Bot de se rappeler combien de fois l'utilisateur a modifié l'horaire et quelle plage horaire est actuellement confirmée
RH / Assistance IT interne leave_request demande de congé / it_ticket ticket Sédimentation des conversations en flux de tickets interrogeables
Éducation / accompagnement à l'apprentissage homework_submission / quiz_score / weak_topic Enregistrement à long terme de l'état d'apprentissage de l'élève, génération d'un plan de révision personnalisé
Conseil médical / santé symptom symptôme / medication médication / appointment consultation de suivi Conservation des informations sur le parcours de soins entre les consultations, amélioration de la cohérence du diagnostic

VI. Bonnes pratiques

✅ Couche configuration

  1. Renseigner les descriptions du dictionnaire de catégories — les champs name et description doivent tous deux être remplis. Le LLM s'appuie principalement sur description pour décider « si cette conversation appartient à cette catégorie ». Une description vide réduit considérablement la précision de classification.
  2. Limiter le nombre de catégories à 5–10. Trop de catégories rendent l'extraction LLM hésitante et alourdissent le Prompt. Fusionner les synonymes (« retrait » et « extraction de fonds » dans la même catégorie).
  3. Les règles d'extraction doivent décrire à la fois "ce qu'il faut faire" et "ce qu'il ne faut pas faire". Par exemple :
    N'extraire que les actions métier confirmées comme terminées ou en cours. Exclure : discussions hypothétiques (« et si... que faire »), pures émotions, bavardages.
                          
                          N'extraire que les actions métier confirmées comme terminées ou en cours.
    Exclure : discussions hypothétiques (« et si... que faire »), pures émotions, bavardages.
    
                        
    Ce bloc de code dans la fenêtre flottante
  4. Préférer un petit modèle d'extraction. L'extraction est une tâche de sortie structurée, peu exigeante en capacité de raisonnement. GPT-4o-mini / Claude Haiku / DeepSeek-V3 sont généralement suffisants, et le coût unitaire peut être inférieur d'un ordre de grandeur à celui du modèle de conversation principal.
  5. Ne pas pousser recentEventCount à fond dès le départ. Injecter trop d'événements écrase le contexte de la conversation principale. Commencer à 5, augmenter si le Bot « oublie » fréquemment.

✅ Paramètres de déclenchement

  1. Conversations longues / scénarios de service client : messageThreshold = 10, idleTimeoutMinutes = 3 est généralement adapté.
  2. Interactions courtes / Bot orienté tâche : abaisser idleTimeoutMinutes à 2, pour éviter qu'après la fin de la conversation, l'extraction d'événements tarde à se déclencher.
  3. Conversations à haute fréquence et faible valeur (par exemple Q&R basique) : monter messageThreshold à 20–30, pour éviter de lancer une extraction LLM à chaque tour et faire exploser les coûts.

✅ Référence dans le Prompt

  1. Privilégier les placeholders plutôt que de s'appuyer sur l'ajout automatique. Les placeholders sont contrôlables et permettent un découpage précis par type ; l'ajout automatique convient aux scénarios de filet de sécurité « tout récupérer ».
  2. Dans un Flow Bot, ne pas activer sur tous les nœuds. Activer uniquement sur les nœuds nécessitant réellement le contexte d'événement (par exemple nœud de réponse client, nœud de jugement de risque) ; les nœuds de reconnaissance d'intention / routage n'en ont pas besoin.
  3. Éviter de placer {{key_event_xxx}} en haut d'un Prompt système — les événements historiques tendent à croître avec le temps, et s'ils saturent le quota de Tokens, les instructions principales seront tronquées. Il est recommandé de le placer au milieu du Prompt ou avant les Few-shots.

✅ Gouvernance des données

  1. Examiner régulièrement à la main les événements de confiance LOW. Le LLM extrait également les contenus « déclarés unilatéralement par l'utilisateur » ; le métier devrait les filtrer — on peut filtrer par confidence=LOW + disputeFlag=true.
  2. Pour les flux métier critiques, combiner avec une écriture par API. Lorsque le système de commandes possède déjà des données structurées, les écrire directement avec createdBy=API est plus précis que de laisser le LLM les extraire de la conversation, et coexiste avec les résultats d'extraction LLM.
  3. Utiliser l'opération MERGE avec précaution. Le LLM fusionne parfois des événements qui ne devraient pas l'être. Il est recommandé de surveiller les opérations MERGE dans les journaux d'exécution, et de scinder via API si nécessaire pour récupérer.
  4. Tirer parti du champ entities. Demandez explicitement au LLM, dans les règles d'extraction, d'extraire les KV essentiels (montant, numéro de commande, heure, etc.), pour pouvoir ensuite faire des requêtes structurées directement, ce qui est plus fiable que de parser le texte de summary.

⚠️ Liste de vérification

Symptôme Pistes de diagnostic
Aucun événement extrait ① L'interrupteur principal est-il activé ② Le Bot dispose-t-il d'un solde de crédits ③ Y a-t-il des FAILED dans le journal d'exécution ④ Les règles d'extraction sont-elles trop strictes
Le contenu d'un certain type d'événement clé est vide ① L'utilisateur a-t-il des événements de ce type ② Les événements de ce type sont-ils correctement créés ③ L'orthographe du nom de catégorie est-elle cohérente
Interférence inter-utilisateurs Vérifier que le bon userId est transmis ; pour un utilisateur non connecté, vérifier la stabilité de l'anonymousId
Coûts d'extraction élevés ① Diminuer la fréquence d'extraction ② Passer à un modèle d'extraction moins cher
Résultats d'extraction mal classés ① Donner une description plus précise des catégories ② Fournir quelques exemples Few-shot dans le champ des règles d'extraction

VII. Limites de la capacité et points d'attention

  • L'extraction n'est pas en temps réel. Même au Niveau 1 (déclenchement temps réel), elle n'a lieu qu'après que les messages se sont accumulés jusqu'au seuil. Les activités exigeant une cohérence forte stricte (par exemple les transactions) ne doivent pas s'appuyer sur le flux d'événements pour prendre des décisions — les événements sont une mémoire auxiliaire, et non la source de vérité.
  • La fenêtre d'extraction est au maximum de 100 messages (MAX_MESSAGES_PER_BATCH). Les conversations très longues sont découpées en plusieurs fenêtres ; les relations causales inter-fenêtres sont retrouvées par « comparaison avec les événements historiques ».
  • La requête d'événements bénéficie d'une protection à 500 ms de timeout. Une requête lente ne ralentira pas la chaîne de chat, mais en cas extrême, aucun événement ne sera injecté.
  • L'ID anonyme est réinitialisé après nettoyage côté client. Un utilisateur anonyme qui change d'appareil / vide le cache est considéré comme un nouvel utilisateur ; les événements ne le suivent pas.
  • Le flux d'événements ne participe pas au mode multi-agent (cf. la déclaration d'obsolescence dans CLAUDE.md du dépôt oversea-ailab).