Chat, extraire: l'architecture des chatbots complexes

Les utilisateurs, après avoir parlé avec des assistants vocaux intelligents, attendent de l'intelligence des robots de discussion. Si vous développez un bot pour les entreprises, les attentes sont encore plus élevées: le client veut que l'utilisateur suive le scénario pré-prescrit souhaité, et l'utilisateur veut que le robot réponde intelligemment et de préférence avec humanité aux questions posées, aide à résoudre les problèmes, et parfois ne supporte que les petites conversations.


Nous proposons des robots de discussion en anglais qui communiquent avec les utilisateurs via différents canaux - Facebook Messenger, SMS, Amazon Alexa et le Web. Nos robots remplacent les services d'assistance, les agents d'assurance et peuvent simplement discuter. Chacune de ces tâches nécessite sa propre approche de développement.

Dans cet article, nous vous expliquerons de quels modules est composé notre service, comment chacun d'eux est réalisé, quelle approche nous avons choisie et pourquoi. Nous partagerons notre expérience dans l'analyse de différents outils: lorsque les réseaux neuronaux génératifs ne sont pas le meilleur choix, pourquoi au lieu de Doc2vec nous utilisons Word2vec, quel est le charme et l'horreur de ChatScript et ainsi de suite.


À première vue, il peut sembler que les problèmes que nous résolvons sont plutôt insignifiants. Cependant, dans le domaine du traitement du langage naturel, il existe un certain nombre de difficultés liées à la fois à la mise en œuvre technique et au facteur humain.
  1. Un milliard de personnes parlent anglais, et chaque locuteur natif l'utilise à sa manière: il existe différents dialectes, différentes fonctionnalités vocales.
  2. De nombreux mots, phrases et expressions sont ambigus: un exemple typique est dans cette image.
  3. Une interprétation correcte du sens des mots nécessite un contexte. Cependant, le bot qui pose des questions de clarification au client n'a pas l'air aussi cool que celui qui peut passer à n'importe quel sujet à la demande de l'utilisateur et répondre à n'importe quelle question.
  4. Souvent, dans la parole et la correspondance vivantes, les gens négligent les règles de grammaire ou répondent si brièvement qu'il est presque impossible de restaurer la structure de la phrase.
  5. Parfois, pour répondre à la question d'un utilisateur, il est nécessaire de comparer sa demande avec les textes de la FAQ. Dans le même temps, vous devez vous assurer que le texte trouvé dans la FAQ est bien la réponse, et ne contient pas seulement plusieurs mots qui correspondent à la demande.


Ce ne sont que quelques-uns des aspects les plus évidents, et il y a l'argot, le jargon, l'humour, le sarcasme, les erreurs d'orthographe et de prononciation, les abréviations et d'autres problèmes qui rendent difficile le travail dans ce domaine.

Pour résoudre ces problèmes, nous avons développé un bot qui utilise un ensemble d'approches. La partie IA de notre système se compose d'un gestionnaire de dialogue, d'un service de reconnaissance et d'importants microservices complexes qui résolvent des problèmes spécifiques: Intent Classifier, FAQ-service, Small Talk.

Lancez une conversation. Gestionnaire de dialogue


La tâche de Dialog Manager dans le bot est une simulation logicielle de communication avec un agent en direct: elle doit guider l'utilisateur à travers un scénario de conversation vers un objectif utile.
Pour ce faire, premièrement, recherchez ce que l'utilisateur veut (par exemple, calculer le coût de l'assurance pour les voitures), et deuxièmement, trouvez les informations nécessaires (adresse et autres données utilisateur, données sur les conducteurs et les voitures). Après cela, le service devrait donner une réponse utile - remplissez le formulaire et donnez au client le résultat de ces données. En même temps, nous ne devons pas demander à l'utilisateur ce qu'il a déjà indiqué.

Dialog Manager vous permet de créer un tel scénario: décrivez-le par programme, construisez à partir de petites briques - problèmes ou actions spécifiques qui devraient se produire à un certain point. En fait, le scénario est un graphe orienté, où chaque nœud est un message, une question, une action, et le bord détermine l'ordre et les conditions de la transition entre ces nœuds, s'il y a un choix multiple de transition d'un nœud à un autre.
Les principaux types de nœuds
  • Les nœuds attendent jusqu'à ce qu'ils atteignent la file d'attente et ils apparaîtront dans les messages.
  • Les nœuds attendent que l'utilisateur montre une certaine intention (par exemple, écrivez: «Je veux souscrire une assurance»).
  • Noeuds en attente de validation et d'enregistrement des données par l'utilisateur.
  • Nœuds pour l'implémentation de différentes conceptions algorithmiques (boucles, branches, etc.).

Si le nœud est fermé, le contrôle ne lui sera plus transféré et l'utilisateur ne verra pas la question déjà posée. Ainsi, si nous effectuons une recherche approfondie dans un tel graphique sur le premier nœud ouvert, nous obtenons une question qui doit être posée à l'utilisateur à un moment donné. Répondant à son tour aux questions générées par Dialog Manager, l'utilisateur fermera progressivement tous les nœuds du graphique et il sera considéré qu'il a exécuté le script prescrit. Ensuite, par exemple, nous donnons à l'utilisateur une description des options d'assurance que nous pouvons offrir.


"J'ai déjà tout dit!"


Supposons que nous demandions un nom à l'utilisateur, et dans un message, il donnera également sa date de naissance, son nom, son sexe, son état civil, son adresse ou enverra une photo de son permis de conduire. Le système extraira toutes les données pertinentes et fermera les nœuds correspondants, c'est-à-dire que les questions sur la date de naissance et le sexe ne seront plus posées.

"Au fait ..."


Dialog Manager offre également la possibilité de communiquer simultanément sur plusieurs sujets. Par exemple, un utilisateur dit: "Je veux souscrire une assurance". Puis, sans terminer ce dialogue, il ajoute: «Je veux effectuer un paiement sur une police précédemment jointe.» Dans de tels cas, Dialog Manager enregistre le contexte du premier sujet et, une fois le deuxième script terminé, il propose de reprendre la boîte de dialogue précédente à l'endroit où elle a été interrompue.

Il est possible de revenir aux questions auxquelles l'utilisateur a déjà répondu. Pour cela, le système enregistre l'instantané du graphique à la réception de chaque message du client.

Quelles sont les options?


En plus de la nôtre, nous avons envisagé une autre approche de l'IA pour la mise en œuvre du gestionnaire de dialogue: l'intention et les paramètres de l'utilisateur sont alimentés à l'entrée du réseau neuronal, et le système lui-même génère les états correspondants, la question suivante qui doit être posée. Cependant, dans la pratique, cette méthode nécessite l'ajout d'une approche basée sur des règles. Peut-être que cette option de mise en œuvre convient à des scénarios triviaux - par exemple, pour commander de la nourriture, où vous devez obtenir seulement trois paramètres: ce que l'utilisateur veut commander, quand il veut recevoir la commande et où l'apporter. Mais dans le cas de scénarios complexes, comme dans notre domaine, ce n'est toujours pas possible. À l'heure actuelle, les technologies d'apprentissage automatique ne sont pas en mesure de guider qualitativement l'utilisateur vers l'objectif dans un scénario complexe.

Dialog Manager est écrit en Python, framework Tornado, car initialement notre partie AI a été écrite en tant que service unique. Une langue a été choisie dans laquelle tout cela peut être réalisé sans dépenser de ressources pour la communication.

"Décidons." Service de reconnaissance


Notre produit est capable de communiquer via différents canaux, mais la partie IA est complètement indépendante du client: cette communication se présente uniquement sous forme de texte mandaté. Le gestionnaire de boîte de dialogue transfère le contexte, la réponse de l'utilisateur et les données collectées au service de reconnaissance, qui est chargé de reconnaître l'intention de l'utilisateur et de récupérer les données nécessaires.
Aujourd'hui, le service de reconnaissance se compose de deux parties logiques: le gestionnaire de reconnaissance, qui gère le pipeline de reconnaissance, et les extracteurs.

Gestionnaire de reconnaissance


Le gestionnaire de reconnaissance est responsable de toutes les étapes de base de la reconnaissance du sens de la parole: tokenisation, lemmatisation, etc. Il détermine également l'ordre des extracteurs (objets qui reconnaissent les entités et les attributs dans les textes) par lesquels un message sera ignoré, et décide quand arrêter la reconnaissance et le retour résultat final. Cela vous permet d'exécuter uniquement les extracteurs nécessaires dans l'ordre le plus attendu.

Si nous avons demandé quel est le nom de l'utilisateur, il est logique de vérifier d'abord si le nom est entré dans la réponse. Le nom est venu et il n'y a plus de texte utile - ce qui signifie que la reconnaissance peut être complétée à cette étape. D'autres entités utiles sont venues, ce qui signifie que la reconnaissance doit être poursuivie. Très probablement, la personne a ajouté d'autres données personnelles - en conséquence, vous devez exécuter l'extracteur pour traiter les données personnelles.

Selon le contexte, l'ordre de démarrage des extracteurs peut varier. Cette approche nous permet de réduire considérablement la charge sur l'ensemble du service.

Extracteurs


Comme mentionné ci-dessus, les extracteurs sont capables de reconnaître certaines entités et attributs dans les textes. Par exemple, un extracteur reconnaît les numéros de téléphone; un autre détermine si une personne a répondu positivement ou négativement à une question; le troisième - reconnaît et vérifie l'adresse dans le message; le quatrième est des données sur le véhicule de l'utilisateur. Passer un message à travers un ensemble d'extracteurs - c'est le processus de reconnaissance de nos messages entrants.

Pour le fonctionnement optimal de tout système complexe, il est nécessaire de combiner les approches. Nous avons respecté ce principe lorsque nous travaillions sur des extracteurs. Je vais souligner certains des principes de travail que nous avons utilisés dans les extracteurs.

Utilisation de nos microservices avec Machine Learning inside (les extracteurs envoient un message à ce service, le complètent parfois avec les informations dont ils disposent et renvoient le résultat).

  • Utilisation du balisage POS, analyse syntaxique, analyse sémantique (par exemple, détermination de l'intention de l'utilisateur par le verbe)
  • Utilisation de la recherche en texte intégral (peut être utilisée pour trouver la marque et le modèle de la machine dans les messages)
  • Utilisation d'expressions régulières et de modèles de réponse
  • Utilisation d'API tierces (telles que l'API Google Maps, SmartyStreets, etc.)
  • Une recherche textuelle des phrases (si une personne a répondu «oui» brièvement, alors il est inutile de la passer par les algorithmes ML pour rechercher l'intention).
  • Nous utilisons également des solutions de traitement du langage naturel prêtes à l'emploi dans les extracteurs.

Quelles sont les options?


Nous avons examiné les bibliothèques NLTK, Stanford CoreNLP et SpaCy. NLTK abandonne d'abord dans Google SERPs lorsque vous démarrez un examen NLP. Il est très cool pour les solutions de prototypage, possède des fonctionnalités étendues et est assez simple. Mais ses performances sont médiocres.

Stanford CoreNLP a un sérieux inconvénient: il tire une machine virtuelle Java avec de très gros modules, des bibliothèques intégrées et consomme beaucoup de ressources. De plus, la sortie de cette bibliothèque est difficile à personnaliser.

En conséquence, nous avons opté pour SpaCy, car il a suffisamment de fonctionnalités pour nous et a le rapport optimal de légèreté et de vitesse. La bibliothèque SpaCy s'exécute des dizaines de fois plus rapidement que NLTK et propose de bien meilleurs dictionnaires. Cependant, c'est beaucoup plus facile que Stanford CoreNLP.

Pour le moment, nous utilisons spaCy pour la tokenisation, la vectorisation des messages (en utilisant le réseau neuronal formé intégré), la reconnaissance primaire des paramètres du texte. Comme la bibliothèque ne couvre que 5% de nos besoins de reconnaissance, nous avons dû ajouter de nombreuses fonctions.

"C'était autrefois ..."


Le service de reconnaissance n'a pas toujours été une structure en deux parties. La première version était la plus triviale: nous avons utilisé à tour de rôle différents extracteurs et essayé de comprendre s'il y avait des paramètres ou des intentions dans le texte. L'IA n'y sentait même pas - c'était une approche complètement basée sur des règles. La difficulté résidait dans le fait que la même intention pouvait s'exprimer de différentes manières, chacune devant être décrite dans les règles. Dans ce cas, il est nécessaire de prendre en compte le contexte, car la même phrase utilisateur, selon la question posée, peut nécessiter des actions différentes. Par exemple, à partir du dialogue: "Êtes-vous marié?" - «Déjà deux ans», vous pouvez comprendre que l'internaute est marié (sens booléen). Et du dialogue "Combien de temps conduisez-vous cette voiture?" - «Déjà deux ans», vous devez extraire la valeur «2 ans».

Dès le début, nous avons compris que la prise en charge de solutions basées sur des règles nécessiterait beaucoup d'efforts, et à mesure que le nombre d'intentions prises en charge augmente, le nombre de règles augmentera beaucoup plus rapidement que dans le cas d'un système basé sur le ML. Cependant, le point de vue des affaires. nous devions exécuter MVP, une approche basée sur des règles nous a permis de le faire rapidement. Par conséquent, nous l'avons utilisé et avons travaillé en parallèle sur le modèle ML de reconnaissance des intentions. Dès qu'elle est apparue et a commencé à donner des résultats satisfaisants, ils ont progressivement commencé à s'éloigner de l'approche fondée sur des règles.

Pour la plupart des cas d'extraction d'informations, nous avons utilisé ChatScript. Cette technologie fournit son propre langage déclaratif qui vous permet d'écrire des modèles pour extraire des données d'un langage naturel. Grâce à WordNet, cette solution est très puissante sous le capot (par exemple, vous pouvez spécifier une «couleur» dans le modèle de reconnaissance, et WordNet reconnaît tout concept de rétrécissement, tel que «rouge»). Nous n'avons pas vu d'analogues à ce moment-là. Mais ChatScript est écrit de manière très tordue et boguée, avec son utilisation, il est presque impossible d'implémenter une logique complexe.

Au final, les inconvénients ont été dépassés et nous avons abandonné ChatScript au profit des bibliothèques NLP en Python.
Dans la première version de Recognition Service, nous avons atteint le plafond de la flexibilité. L'introduction de chaque nouvelle fonctionnalité a considérablement ralenti l'ensemble du système dans son ensemble.

Nous avons donc décidé de réécrire complètement le service de reconnaissance, en le divisant en deux parties logiques: les petits extracteurs légers et le gestionnaire de reconnaissance, qui gérera le processus.

"Que veux-tu?" Classificateur d'intention


Pour que le bot communique correctement - pour fournir les informations nécessaires sur demande et pour enregistrer les données de l'utilisateur - il est nécessaire de déterminer l'intention (l'intention) de l'utilisateur sur la base du texte qui lui est envoyé. La liste des intentions par lesquelles nous pouvons interagir avec les utilisateurs est limitée par les tâches commerciales du client: il peut s'agir de connaître les conditions d'assurance, de remplir des informations vous concernant, d'obtenir une réponse à une question fréquemment posée, etc.

Il existe de nombreuses approches de la classification des intentions basées sur les réseaux de neurones, en particulier sur les LSTM / GRU récurrents. Ils ont fait leurs preuves dans des études récentes, mais ils ont un inconvénient commun: un très grand échantillon est nécessaire pour un bon fonctionnement. Sur une petite quantité de données, ces réseaux de neurones sont soit difficiles à former, soit ils produisent des résultats insatisfaisants. Il en va de même pour le framework Fast Text de Facebook (nous l'avons examiné car il s'agit d'une solution de pointe pour le traitement des phrases courtes et moyennes).

Nos échantillons de formation sont de très haute qualité: les ensembles de données sont constitués d'une équipe de linguistes à plein temps qui maîtrisent l'anglais et connaissent les spécificités du domaine de l'assurance. Cependant, nos échantillons sont relativement petits. Nous avons essayé de les diluer avec des ensembles de données publics, mais ceux-ci, à de rares exceptions près, ne correspondaient pas à nos spécificités. Nous avons également essayé d'attirer des pigistes avec Amazon Mechanical Turk, mais cette méthode s'est également avérée inopérante: les données qu'ils ont envoyées étaient partiellement de mauvaise qualité, les échantillons ont dû être revérifiés.

Par conséquent, nous recherchions une solution qui fonctionnerait sur un petit échantillon. La bonne qualité du traitement des données a été démontrée par le classificateur Random Forest, formé sur des données converties en vecteurs de notre modèle de sac de mots. En utilisant la validation croisée, nous avons sélectionné les paramètres optimaux. Parmi les avantages de notre modèle figurent la vitesse et la taille, ainsi que la relative facilité de déploiement et de recyclage.

Au cours du travail sur le classificateur d'intention, il est devenu clair que pour certaines tâches, son utilisation n'est pas optimale. Supposons qu'un utilisateur veuille changer le nom indiqué dans l'assurance ou le numéro de voiture. Pour que le classificateur détermine correctement cette intention, il faudrait ajouter manuellement à l'ensemble de données toutes les phrases de modèle utilisées dans ce cas. Nous avons trouvé un autre moyen: créer un petit extracteur pour le service de reconnaissance, qui détermine l'intention par mots-clés et méthodes NLP, et utiliser Intent Classifier pour les phrases non standard dans lesquelles la méthode avec mots-clés ne fonctionne pas.

"Ils demandent toujours à ce sujet." FAQ


Beaucoup de nos clients ont des sections FAQ. Pour que l'utilisateur reçoive ces réponses directement du chatbot, il était nécessaire de fournir une solution qui a) reconnaîtrait la demande de FAQ; b) trouverait la réponse la plus pertinente dans notre base de données et la publierait.

Il existe un certain nombre de modèles formés sur l'ensemble de données Stanford SQUAD. Ils fonctionnent bien lorsque le texte de réponse de la FAQ contient les mots de la question de l'utilisateur. Disons que la FAQ dit: "Frodon a dit qu'il amènerait l'Anneau au Mordor, bien qu'il ne connaissait pas le chemin." Si l'utilisateur demande: «Où Frodon prendra-t-il l'anneau?», Le système répondra: «Au Mordor».

Notre scénario, en règle générale, était différent. Par exemple, pour deux demandes similaires - "Puis-je payer?" et "Puis-je payer en ligne?" Le bot doit répondre différemment: dans le premier cas, proposer à une personne un mode de paiement, dans la deuxième réponse - oui, vous pouvez payer en ligne, voici l'adresse de la page.

Une autre classe de solutions pour évaluer la similitude des documents se concentre sur les réponses longues - au moins quelques phrases, parmi lesquelles contiennent des informations d'intérêt pour l'utilisateur. Malheureusement, dans les cas avec de courtes questions et réponses («Comment puis-je payer en ligne?» - «Vous pouvez payer avec PayPal»), ils fonctionnent très instables.

Une autre solution est l'approche Doc2vec: le gros texte est distillé dans une représentation vectorielle, qui est ensuite comparé à d'autres documents sous la même forme et le coefficient de similitude est révélé. Cette approche a également dû être supprimée: elle se concentre sur des textes longs, mais nous traitons principalement des questions et réponses d'une ou deux phrases.

Notre décision était basée sur deux étapes. Premièrement: en utilisant des incorporations, nous avons traduit chaque mot d'une phrase en vecteurs en utilisant le modèle Google Word2vec.Après cela, nous avons considéré le vecteur moyen pour tous les mots, représentant une phrase sous la forme d'un vecteur. La deuxième étape, nous avons pris le vecteur de la question et trouvé dans la base de données FAQ, stockée sous la même forme vectorielle, la réponse la plus proche dans une certaine mesure, dans notre cas, le cosinus.

Les avantages comprennent une facilité de mise en œuvre, une extensibilité très facile et une interprétabilité assez simple. Les inconvénients sont une faible opportunité d'optimisation: ce modèle est difficile à modifier - il fonctionne bien dans la plupart de vos cas d'utilisation, ou vous devez l'abandonner.

"Et parler?" Petite conversation


Parfois, l'utilisateur écrit quelque chose de complètement hors de propos, par exemple: "Il fait beau aujourd'hui". Ce n'est pas inclus dans la liste des intentions qui nous intéressent, mais nous voulons toujours répondre de manière significative, démontrant l'intelligence de notre système.

Pour de telles décisions, une combinaison des approches décrites ci-dessus est utilisée: elles sont basées soit sur des solutions basées sur des règles très simples, soit sur des réseaux neuronaux génératifs. Nous voulions obtenir un prototype tôt, nous avons donc pris un ensemble de données public sur Internet et utilisé une approche très similaire à celle utilisée pour la FAQ. Par exemple, un utilisateur a écrit quelque chose sur la météo - et en utilisant un algorithme comparant les représentations vectorielles de deux phrases avec une certaine mesure de cosinus, nous recherchons une phrase dans l'ensemble de données public qui sera aussi proche du thème météo que possible.

La formation


Maintenant, nous n'avons pas pour objectif de créer un bot qui sera formé sur chaque message reçu des clients: premièrement, comme l'expérience le montre, c'est le chemin vers la mort du bot (rappelez-vous comment IBM Watson a dû effacer la base car il a commencé à diagnostiquer avec un tapis et le robot Twitter de Microsoft a réussi à devenir raciste en seulement une journée). Deuxièmement, nous nous efforçons de clôturer les tâches des compagnies d'assurance aussi qualitativement que possible; un bot d'auto-apprentissage n'est pas notre tâche commerciale. Nous avons écrit un certain nombre d'outils pour les linguistes et les commandes d'assurance qualité, avec lesquels ils peuvent recycler manuellement les bots en explorant les dialogues et la correspondance avec les utilisateurs pendant la post-modération.

Néanmoins, notre bot semble déjà prêt à passer le test de Turing. Certains utilisateurs entament une conversation sérieuse avec lui, pensant qu'ils parlent avec un agent d'assurance, et l'un d'eux a même commencé à menacer de porter plainte auprès du patron lorsque le bot l'a mal compris.

Plans


Nous travaillons maintenant sur la partie visuelle: afficher l'intégralité du graphique du script et la possibilité de le composer à l'aide de l'interface graphique.

Du côté du service de reconnaissance, nous introduisons l'analyse linguistique pour reconnaître et comprendre la signification de chaque mot du message. Cela améliorera la précision de la réaction et extraira des données supplémentaires. Par exemple, si une personne remplit une assurance auto et mentionne qu'elle a une maison non assurée, le bot pourra se souvenir de ce message et le transmettre à l'opérateur pour contacter le client et lui proposer une assurance habitation.

Une autre caractéristique du travail est le traitement des commentaires. Après avoir terminé le dialogue avec le bot, nous demandons à l'utilisateur s'il a aimé le service. Si Sentiment Analysis reconnaît que l'avis de l'utilisateur est positif, nous l'invitons à partager son avis sur les réseaux sociaux. Si l'analyse montre que l'utilisateur a réagi négativement, le bot clarifie ce qui n'allait pas, corrige la réponse, dit: «OK, nous allons le réparer», et ne propose pas de partager l'avis dans le flux.

L'une des clés pour rendre la communication avec le bot aussi naturelle que possible est de rendre le bot modulaire et d'élargir la gamme de réactions à sa disposition. Nous y travaillons. Peut-être à cause de cela, l'utilisateur était prêt à prendre sincèrement notre robot pour un agent d'assurance. L'étape suivante: assurez-vous que la personne essaie de remercier le bot.



L'article a été écrit avec Sergei Kondratyuk et Mikhail Kazakov . Écrivez vos questions dans les commentaires, nous préparerons des documents plus pratiques à leur sujet.

Source: https://habr.com/ru/post/fr429638/


All Articles