DEV Community đŸ‘©â€đŸ’»đŸ‘šâ€đŸ’»

Cover image for Chat Bot SFEIR Brain: découverte du Natural Language Processing
Thibault Henry for SFEIR

Posted on

Chat Bot SFEIR Brain: découverte du Natural Language Processing

Bonjour Ă  tous les lecteurs,

[...]

J'ai écrit cet article sur Medium fin 2021 alors l'introduction est un peu datée. Voici le lien original

[...]

L'année 2021 touche à sa fin, et pour moi, voilà déjà deux ans que j'ai signé mon premier CDI chez SFEIR Luxembourg.
Deux ans, ça paraßt loin : on ne parlait pas encore du Covid et de tous ses variants à ce moment-là !

Pour l'occasion, je vous propose un retour d'expérience sur le sujet principal de mon stage de fin d'études que j'ai réalisé chez SFEIR avant de devenir un véritable collaborateur en novembre 2019.

Comme vous avez pu le comprendre avec le titre de cet article, ce stage portait sur la réalisation d'un assistant conversationnel dénommé SFEIR Brain.

Avant de plonger dans le vif du sujet, je souhaite créditer les 3 autres personnes avec qui j'ai travaillé sur ce projet : Julien Derigny, Sullivan Vanet & Sylvain BruyÚre.

SFEIR Brain, qu'est-ce que c'est, à quoi ça sert ?

Vous le savez sûrement, SFEIR utilise pour sa gestion interne la « G Suite », qui est une suite d'outils de productivité destinée aux professionnels. En particulier, elle utilise Google Agenda, Gmail, Google Drive, pour manager son organisation et gagner en agilité : création de groupes de partage de documents, planification des échéances sur l'agenda de ses collaborateurs.

Cependant, la gestion de ces nombreux fichiers partagĂ©s peut parfois ĂȘtre laborieuse pour les collaborateurs et l'Ă©quipe administrative.
De là est née l'idée que pour certaines tùches rébarbatives, nous pouvions mettre en place un chat bot qui serait en mesure d'interpréter des informations et effectuer de la collecte des données.

Par exemple, on peut penser à la demande de congés des sfeiriens, ou à la réservation des places de parking de l'ancienne location de SFEIR à Leudelange (Luxembourg).

L'objectif Ă©tait donc le suivant : rĂ©aliser un outil d'aide pour les sfeiriens permettant de leur libĂ©rer du temps, afin rĂ©aliser des tĂąches spĂ©cifiques Ă  leur cƓur de mĂ©tier, Ă  plus haute valeur ajoutĂ©e.

Définition du besoin

Pour faire gagner du temps aux sfeiriens, il fallait d'abord savoir ce dont ils avaient réellement besoin.

J'ai transmis aux personnes prĂ©sentes Ă  l'agence diffĂ©rents questionnaires oĂč elles devaient renseigner leur rĂŽle dans l'entreprise et ce qui pourrait les aider dans la vie de tous les jours.
Une fois la liste des besoins complétée, il était nécessaire de sélectionner une application capable de comprendre les demandes des utilisateurs en langage naturel, de déterminer des intentions à travers des discussions simples ou complexes, mais aussi de collecter des données et paramÚtres à prendre en compte afin de formuler une réponse adéquate.

Comme la durée de stage était limitée, nous avons choisi une solution toute faite proposée par Google, à savoir : DialogFlow.

En plus de développer les fonctionnalités demandées, Guillaume Homberg (notre maßtre de stage), nous a demandé de rendre l'application malléable, pour que n'importe quel développeur puisse facilement fournir davantage de fonctionnalités réalisables par l'assistant.

Autant dire que pour les stagiaires à peine sortis d'école que nous étions, la barre était haute pour fournir une application évolutive, disponible sur le Cloud et interfaçable avec une messagerie instantanée.

Contexte et origine du projet

L'idée de réaliser un tel chat bot n'est pas récente, car en 2018 une précédente équipe de stagiaires avait déjà tenté l'expérience.

Ils avaient utilisé des services sur le cloud Google (GCP pour Google Cloud Platform), le tout organisé autour une architecture en microservices communiquant à travers l'agent de message broker Pub/Sub. 
Chaque microservice était déployé grùce à l'outil App Engine. Ce service permet d'administrer des applications sans avoir à s'occuper de la gestion des infrastructures serveur sous-jacentes.

Le renouvellement de ce projet a donc débuté à partir de la fin juin 2019 sur la GCP.
Nous avons premiÚrement cherché à comprendre l'interaction entre les différents services utilisés par nos prédécesseurs et l'architecture du code implémenté. 
Ensuite, nous avons migrĂ© sur une base de donnĂ©es Firestore (un autre service de la plateforme), les donnĂ©es du prĂ©cĂ©dent projet hĂ©bergĂ©es sur le service Datastore (ancĂȘtre de Firestore).
En parallÚle au travail effectué sur la GCP, une partie de l'équipe a démarré la reprise du service DialogFlow pour le traitement du langage naturel. 
L'atout majeur de DialogFlow, c'est son large panel d'intégrations à des services de messagerie, dont Workplace, la messagerie utilisée en interne chez SFEIR.

Nos prĂ©dĂ©cesseurs utilisaient Ă©galement Dialogflow, mais il s'agissait de la premiĂšre version. Malheureusement, cette version 1 Ă©tait une bĂȘta et est rapidement devenue obsolĂšte.

Quand nous avons repris le flambeau, une année plus tard, plus rien ne fonctionnait. Notre sujet reposait donc sur la reprise de ce projet innovant.

Reprise du projet et contraintes

Au dĂ©but du projet, il a Ă©tĂ© dĂ©cidĂ© que nous reprendrions la mĂȘme base technologique que celle dĂ©finie par la prĂ©cĂ©dente Ă©quipe.
Pour vous donner une idée plus précise, voici un graphique sur la structure du projet à ce moment-là :

Architecture du chat bot en 2018

Voici une description ce graphique :

  • le systĂšme dispose de plusieurs canaux de communication, ou « Topic », par lesquels circulent des instructions sous forme de messages JSON.
  • via le canal « GatewayTopic », des instructions circulent entre le systĂšme central et le service DialogFlow qui traite les intentions des utilisateurs.
  • les messages envoyĂ©s vers DialogFlow traversent d'abord le service « format » qui construit un JSON dĂ©crivant comment la rĂ©ponse sera affichĂ©e sur la messagerie de l'utilisateur (Workplace chat).
  • chaque fonctionnalitĂ© (tĂąche, scĂ©nario) du chat bot dispose de son propre microservice dĂ©ployĂ© via un App engine (sur la droite du graphique).
  • le service « orchestrator » va interprĂ©ter les messages en provenance de Dialogflow pour dĂ©terminer le type de tĂąche Ă  exĂ©cuter, et transmettra cette information au service concernĂ© via le canal « MainTopic ».
  • le systĂšme dispose d'un traitement des journaux global pour pouvoir dĂ©boguer en cas de soucis.

Comme vous pouvez le voir, l'architecture déjà en place faisait sens et était déjà bien pensée à l'époque. 
Seulement voilà, aprÚs quelques semaines d'études et de tentatives pour redémarrer le tout, nous ne parvenions pas à refaire fonctionner le chat bot comme à l'origine.

Nous avions notamment des gros problÚmes de temps de réponse dus au fait que l'échange des messages entre les multiples microservices était lent.  
En fonction de la requĂȘte de l'utilisateur, plusieurs microservices pouvaient ĂȘtre impliquĂ©s et les dĂ©lais de rĂ©ponse Ă©taient encore plus grand lorsque les App engines Ă©taient en mode « sommeil ».

Tout cela nous a mené à une contrainte technique majeure sur Dialogflow : si le délai de réponse aprÚs un message dépasse les 5 secondes, alors aucune réponse n'est envoyée.

L'origine du problÚme vient du fait les instances du service App Engine, qui représentent chacune un microservice, sont mises en veille lorsqu'elles ne sont pas utilisées pendant une certaine période. 
Or, l'Ă©mission d'une requĂȘte sur DialogFlow provoque l'Ă©veil des instances impliquĂ©es, qui dure parfois jusqu'Ă  une seconde. DĂšs qu'une requĂȘte parcourt une petite chaĂźne de microservices endormis, elle doit les rĂ©veiller un par un.
Ce faisant, la réponse ne parvient pas jusqu'à l'utilisateur, car son traitement dépasse la limite instaurée par DialogFlow.

Nous avons d'abord pensé à contourner ce problÚme en envoyant un message via un autre flux pour simuler une réponse plus tardive, mais tout compte fait, qui voudrait utiliser un chat bot qui met trop de temps à répondre ?
Il fallait trouver une solution plus robuste au problĂšme.

Une architecture hybride : l'approche microlithique

Afin d'améliorer les performances de l'application SFEIR Brain, il a fallu réduire le chaßnage des microservices pour réduire le temps d'activation des services aprÚs une période d'inactivité prolongée.
Avant de mettre en place une telle solution qui bouleverserait grandement l'architecture du projet, nous avons pris la décision de migrer le code source à l'identique, sans modifier la structure en microservices, sur un nouveau service prometteur de la GCP : les Cloud Functions.

Le service des Cloud Functions correspond à un outil avec lequel il est possible de définir des environnements d'exécution destinés à lancer des programmes simples et légers. Avec ces fonctions, il est possible d'implémenter des programmes courts directement via l'interface web sur la GCP, et qui se déclenchent grùce à des événements émis par d'autres services cloud de la plate-forme ou plus simplement par un événement externe. Il est possible d'utiliser différents langages de programmation parmi lesquels le Go (version 1.11 à l'époque), qui est celui que nous avons décidé d'utiliser.

Les Cloud Functions semblent ĂȘtre une solution adĂ©quate pour dĂ©ployer un environnement d'exĂ©cution unique pour chacun des microservices dĂ©veloppĂ©s en 2018, Ă  l'image des instances du service App Engine.

L'idée de cette premiÚre investigation n'était pas de migrer l'intégralité des microservices existants pour possiblement revenir en arriÚre en cas d'échec. Au contraire, j'ai choisi de cibler une fonctionnalité de l'assistant précise et relativement peu complexe, impliquant un petit nombre
de microservices.

J'ai donc choisi de tester le cheminement de la requĂȘte de demande d'anciennetĂ© d'un collaborateur, impliquant les microservices suivants :

  1. Point d'entrĂ©e DialogFlow : il rĂ©cupĂšre la requĂȘte Ă©mise par DialogFlow Ă  l'application interne.
  2. Gateway : il rĂ©cupĂšre la requĂȘte transformĂ©e et utilisable dans le systĂšme interne afin de la diriger vers l'entrĂ©e ou la sortie de l'application.
  3. Orchestrator : il dĂ©finit l'ensemble des microservices que va parcourir la requĂȘte jusqu'Ă  l'Ă©mission d'une rĂ©ponse.
  4. Identification : il identifie le collaborateur dont on veut connaßtre l'ancienneté.
  5. Collaborator : il récupÚre l'ancienneté du collaborateur identifié.
  6. Format : il met en forme la réponse pour qu'elle soit lisible par l'utilisateur final.

L'objectif est clair : que la requĂȘte traverse l'ensemble de ces microservices, dĂ©ployĂ©s grĂące Ă  des Cloud Functions, en moins de cinq secondes.

Cependant, pour communiquer entre elles, les Cloud Functions utilisent le service cloud Pub/Sub de la plate-forme Google. Elles doivent pour cela utiliser une bibliothÚque en langage Go permettant de se connecter au service et envoyer des données. 
Or, l'initialisation de la connexion est non-nĂ©gligeable en termes de temps d'exĂ©cution, et puisque les fonctions sont Ă©phĂ©mĂšres, aucune variable n'est sauvegardĂ©e en mĂ©moire, ce qui entraĂźne que la connexion doit ĂȘtre rĂ©alisĂ©e Ă  chaque nouvelle requĂȘte.

Dans le parcours classique d'une requĂȘte, comme celui prĂ©sentĂ© prĂ©cĂ©demment, la connexion au service Pub/Sub est donc Ă©tablie plusieurs fois et cela a pour effet d'allonger le temps de rĂ©ponse de l'application. 
Ce laps de temps est variable, mais il s'est avéré à de multiples reprises, durant
une batterie de tests, que la réponse ne parvenait pas jusqu'à l'utilisateur, car l'incontournable limite des cinq secondes était dépassée.

Une telle architecture n'est donc pas envisageable.

AprÚs longue réflexion, il a été décidé d'instaurer une architecture originale et hybride : l'architecture microlithique.

Le principal objectif de cette approche est d'utiliser la puissance et la rapidité d'exécution des Cloud Functions en réduisant au maximum leur nombre, pour réduire les délais de communication.
En résumé, une architecture microlithique reprend les concepts d'une architecture monolithique, mais se sépare des tùches lourdes en les assignant à des cloud functions travaillant de maniÚre asynchrone.

Dans le cas précis de SFEIR Brain, il est possible d'agglomérer la majorité des anciens microservices en une seule cloud function de plus grande envergure. L'établissement de communications via Pub/Sub se marginalise ainsi à la réalisation asynchrone de travaux chronophages,
comme la génération de fichiers sur Google Drive par exemple.

Grùce à cette nouvelle maniÚre de concevoir l'application, les performances de l'assistant conversationnel ont été considérablement accrues avec des temps de réponse inférieurs à 200 millisecondes.

Voici un schéma de l'architecture réalisée :

Architecture microlithique de SFEIR Brain 2019

Voici un exemple de cheminement d'une requĂȘte au sein de SFEIR Brain : la gĂ©nĂ©ration d'une fiche de congĂ©s pour un collaborateur.

  • La requĂȘte est transmise par DialogFlow Ă  la fonction reprĂ©sentant le point d'entrĂ©e de l'application.
  • La fonction correspondante Ă  cette tĂąche sera dĂ©clenchĂ©e par l'envoi d'un message spĂ©cifique sur le service Pub/Sub de la GCP.
  • En parallĂšle, l'Ă©laboration de la rĂ©ponse pour l'utilisateur se dĂ©roule sans perturbation : ainsi, il recevra un lien temporaire redirigeant vers le fichier demandĂ© lorsque sa gĂ©nĂ©ration sera terminĂ©e.

D'autres tùches, indépendantes de DialogFlow, ont été déployées dans des fonctions cloud qui s'exécutent périodiquement grùce au service Google Scheduler. 
Ces fonctions sont destinées à mettre à jour la base de données Firestore ou à supprimer les fichiers trop datés sur le dépÎt Google Drive de l'entreprise.

Pour les requĂȘtes plus basiques, le traitement suit une dĂ©marche scĂ©narisĂ©e prĂ©dĂ©finie par notre Ă©quipe au sein de la base de donnĂ©es Firestore, qui liste l'ensemble des possibilitĂ©s du chat bot et les Ă©tapes Ă  suivre pour rĂ©pondre correctement Ă  l'utilisateur.

ScĂ©narisation des requĂȘtes

Pour obtenir une rĂ©ponse en cohĂ©rence avec la requĂȘte effectuĂ©e par l'utilisateur, il nous a fallu dĂ©finir des scĂ©narios d'exĂ©cution pour chacune des fonctionnalitĂ©s implĂ©mentĂ©es. 
Chaque fonctionnalité est identifiée par l'action reconnue par DialogFlow, et qui correspond à une simple chaßne de caractÚre :

Scénario de l'action « GetCollaboratorSeniority »

Une fois l'action connue et identifiée dans la fonction principale, le cheminement correspondant est récupéré sur la base de données Firestore.

Un scénario est une série d'instructions à exécuter pour obtenir la réponse finale.
Par exemple, pour la connaßtre l'ancienneté d'un collaborateur, le scénario sera le suivant :

  • « IdentifyCollaborator »
  • « GetCollaboratorSeniority »

Intégrée dans la boucle scénaristique, cette liste d'instructions déclenchera un par un des modules du code source de la Cloud Function principale.
Le rĂ©sultat de chaque module liĂ© Ă  une instruction sera stockĂ© dans la requĂȘte lors de son parcours et pourra ĂȘtre utilisĂ© par les modules suivants pour construire progressivement une rĂ©ponse complĂšte.

Ce mécanisme de scénarisation a pour but de rendre l'ajout de fonctionnalités dans le code source évolutif et le plus simple possible, comme on nous l'avait demandé au début du projet.

Formatage des réponses

La derniÚre étape avant d'envoyer la réponse à l'utilisateur est d'embellir son apparence dans un processus de formatage.

En gĂ©nĂ©ral, une rĂ©ponse Ă©noncĂ©e sous la forme d'un simple texte est suffisante pour pouvoir ĂȘtre comprise facilement par l'utilisateur. 
En revanche, quand la quantité d'informations à transmettre est conséquente, la compréhension d'une réponse uniquement textuelle est complexe.

L'idĂ©e Ă©tait donc d'Ă©tendre le champ des possibles dans l'affichage des informations obtenues aprĂšs la requĂȘte d'un collaborateur.

Sullivan et Sylvain ont beaucoup travaillé sur ce sujet pour paramétrer le message transmis à l'utilisateur. Outre le texte, il est possible de créer les éléments suivants pour un message :

  • les rĂ©ponses rapides
  • les boutons
  • les cartes
  • les images
  • les vidĂ©os

RĂ©ponses rapides disponibles sur Workplace Chat

Ils ont défini un format d'affichage pour chaque action répertoriée dans la base de données Firestore, utilisé pour améliorer la compréhension de la réponse.

Plus précisément, ils ont construit un systÚme de formatage trÚs puissant qui permet de passer d'une syntaxe customisée à une réponse JSON compréhensible par DialogFlow :

<Response>
  <Cards>
    <Card>
      <Card.Title>
        Feuille de congés
      </Card.Title>

      <Card.Subtitle>
        Votre fichier sera accessible pendant 24 heures
      </Card.Subtitle>

      <Card.Buttons>
        <Button Type="Url" Data="{{obj.GetWaitingWebsiteURL()}}" ModalFormat="Medium">
          Accéder à la feuille
        </Button>
      </Card.Buttons>
    </Card>
  </Cards>
</Response>
Enter fullscreen mode Exit fullscreen mode

Format de l'action « GenerateLeaveRequest »

Une partie de ce travail a Ă©tĂ© rĂ©utilisĂ© pour le chat bot Neo Jarvis que vous avez peut-ĂȘtre dĂ©jĂ  utilisĂ©.

Configuration de DialogFlow

Pour fonctionner, DialogFlow a besoin qu'un utilisateur lui transmette des donnĂ©es Ă  traiter pour dĂ©tecter l'intention principale et en dĂ©duire ensuite les actions Ă  mettre en Ɠuvre.

L'outil se base sur la technologie du « machine learning », avec des algorithmes trÚs techniques et entraßnés par Google.

Dans l'absolu, DialogFlow peut ĂȘtre considĂ©rĂ© comme une boĂźte noire dont on ne connaĂźt pas le fonctionnement exact, c'est-Ă -dire, la description des algorithmes de traitement du langage naturel, mais qui peut ĂȘtre configurĂ©e afin de rĂ©pondre Ă  un besoin prĂ©cis.

De cette maniÚre, il est possible à partir d'une simple phrase, de déterminer des paramÚtres comme un nom, prénom, ou une date, d'identifier des entités listées au préalable, de répondre immédiatement à l'utilisateur en suivant des schémas de dialogue prédéfinis, dans le but de réaliser une action.

Bien que l'aspect technique des algorithmes de machine learning ne nous soit pas accessible, le parcours d'une requĂȘte est lui bien connu :

Schéma de communication de DialogFlow

Diaflow va alors essayer de comprendre la requĂȘte pour extraire une intention :

  1. Soit l'intention est trĂšs simple : par exemple si l'utilisateur Ă©crit ou dit "Bonjour", le chat bot pourra rĂ©pondre directement et par lui-mĂȘme Ă  l'utilisateur grĂące Ă  l'option Small Talks de l'outil DialogFlow.
  2. Soit l'intention est liée à un dialogue : le chat bot va donc répondre directement à l'utilisateur en poursuivant la conversation pour obtenir des informations supplémentaires.
  3. Soit l'intention est complexe et nĂ©cessite un traitement spĂ©cifique : dans ce cas, le chat bot dirige la requĂȘte vers l'application interne.

Pour le processus d'identification de l'intention, il est nécessaire de définir une liste d'intentions possibles du systÚme. 
Chaque intention dispose d'une liste de phrases d'entraßnement, de paramÚtres et d'une action. 
Les paramĂštres peuvent ĂȘtre utilisĂ©s dans les phrases d'entraĂźnement, ce qui permet d'affiner la dĂ©tection de l'intention exacte de l'utilisateur :

Définition des phrases d'entraßnement pour l'action « GetCollaboratorTrigram »

Ainsi, pour déterminer quelle est l'intention la plus probable que souhaite transmettre l'utilisateur, DialogFlow compare la phrase en entrée du systÚme avec l'ensemble des phrases d'entraßnement existantes dans la liste des intentions. 
Une fois la bonne intention ciblĂ©e, le processus se poursuit et s'il s'agit d'une requĂȘte complexe, une action pourra ĂȘtre exĂ©cutĂ©e par le backend de SFEIR Brain.

Vidéo de démonstration

Pour finir cet article en beauté, je vous propose de regarder cette courte vidéo présentant le chat bot en action :

DĂ©monstration du chat bot Sfeir Brain

(petite précision: la partie formattage n'était pas encore finalisé au moment de la vidéo, et c'est pour cela que les réponses du bot sont brutes)

Conclusion

Aujourd'hui, le chat bot SFEIR Brain n'est plus actif à cause d'une politique de sécurisation de Workplace qui a rendu difficile l'intégration de chat bot customisé. Le code, les données, les Cloud Functions, etc, sont toujours disponibles sur la GCP mais inutilisés.

Malgré tout, cette aventure était vraiment intéressante, je ne pensais pas travaillé sur un projet aussi complexe techniquement que celui-ci pour un stage de fin d'études.

Ce que j'ai le plus apprécié, c'est que nous avons eu un paquet de soucis pour mettre en place ce chat bot, mais nous avons toujours réussi à nous en sortir. En plus de ça, on avait une équipe de choc avec une bonne ambiance, c'était vraiment un projet cool à réaliser !

Je vous remercie d'avoir lu cet article et j'espÚre que vous avez pu en apprendre un peu plus sur la conception d'un chat bot hébergé sur le Cloud Google, à travers les yeux de novices stagiaires.

À bientît,
Thibault HENRY

Top comments (0)

We want your help! Become a Tag Moderator.
Check out this survey and help us moderate our community by becoming a tag moderator here at DEV.