Comment développer un ChatBot en Python

Suivez le déroulé de notre POC en Data Science sur le développement d’un Chatbot avec l’utilisation de Python.

CBTW
L’Actualité Tech — Blog CBTW
8 min readJan 16, 2017

--

Développer un ChatBot en Python

Introduction aux chatbots

Le Natural language processing

Il s’agit d’un champ du machine learning permettant de modéliser et reproduire à l’aide de machines la capacité humaine à communiquer à travers le langage naturel. On parle donc ici d’entraîner des modèles à donner des représentations (sous forme de vecteur) proches aux mots / phrases / documents ayant des sens similaires et au contraire, des représentations éloignées aux mots / phrases / documents ayant des sens opposés.

Sans titre1

Une représentation vectorielle de la quasi-totalité des mots de la langue anglaise existe et est accessible : il s’agit de word2vec. Ce modèle de transformation de mots en vecteurs a été implémenté et entraîné sur des milliards de mots et en s’intéressant au contexte d’apparition de chacun des mots — les autres mots qui les entourent. Dans cette représentation, on peut par exemple se rendre compte que le chemin à parcourir pour passer d’ “homme” à “femme” est exactement le même que pour passer de “roi” à “reine”.

Les chatbots

Il faut, à mon avis, commencer par se poser la question de la définition des différents types de “chatbots”. Beaucoup de “bots” ne sont pas basés sur l’interprétation du langage naturel. Et la plupart du temps, ils ne le sont pas car ils n’en ont pas besoin. Les exemples les plus courants sont les chatbots développés sur Messenger pour des groupes d’e-commerce ou pour des médias. Ce sont des parcours d’arbres pour guider l’interlocuteur jusqu’aux éléments qui permettront de répondre à sa requête : le “bot” vous pose une question avec plusieurs boutons de réponses et en fonction de votre choix, vous guide vers une autre question sous la même forme. Ces bots représentent une nouvelle forme de parcours clients pour répondre à leurs besoins. Sur Slack, les “bots” sont des interfaces de commandes : ils ne réagissent qu’à l’apparition de mots-clés ou d’enchaînements définis par des règles. Dans ce POC, l’idée était de développer un chatbot avec lequel on puisse échanger librement, par le langage naturel. L’interlocuteur n’est donc pas censé connaître de règles avant de commencer à interagir avec un bot. Sa seule déclaration au bot devrait permettre à ce dernier de pouvoir “comprendre” quelle réponse donner ou quelle question retourner.

Exemple de chatbot de type parcours d’arbres
Exemple de chatbot de type parcours d’arbres

Présentation de la librairie Chatterbot

La librairie chatterbot permet d’implémenter une interface conversationnelle basée sur de l’analyse de langage.

Logic Adapter

Le cœur de la librairie se situe dans le choix et/ou l’implémentation de ses Logic Adapters. Ils définissent la logique que suit l’application pour donner une réponse à l’entrée donnée par l’utilisateur. Plusieurs Logic Adapters sont pré-implémentés par la librairie. Par exemple le Best Match va chercher dans le corpus historique des interactions la question la plus proche à la nouvelle entrée donnée et choisir une réponse parmi les réponses associées dans cet historique. La distance peut être réimplémentée mais une fois de plus, certaines distances sémantiques “dures” (ne tenant pas compte des représentations vectorielles présentées plus haut) sont déjà présentes comme la Jaccard similarity*. On peut aussi paramétrer la prise en compte ou non de stopwords : ce sont les mots très courant dans un langage donné, qui vont finalement avoir peu d’influence sur le sens de la phrase. Exemple : en français, {le, de, la, est} peuvent être définis comme stopwords dans la phrase “le chat de la voisine est parti dehors”. On comprend donc que dans les Logic Adapters proposés par Chatterbot, l’utilisation des modèles de représentations vectorielles issus d’apprentissage profond n’est malheureusement pas présente. Je reviendrai dessus dans la dernière partie. Chaque Logic Adapter renvoie un couple (réponse, taux de confiance). On peut activer dans les paramètres d’entrée du chatbot plusieurs adapters. Chacun d’entre eux sera questionné et la réponse associée au plus grand taux de confiance sera retournée.

* Rapport de la taille de l’intersection des deux phrases sur la taille de leur union

Développer un naive bot

Première prise en main de la librairie : développement d’un bot naïf en deux temps :

  1. Création d’un corpus d’entraînement pour le bot en ne lui indiquant aucun Logic Adapter. Bêtement, le bot répétera donc la déclaration qui lui est faite. Cette première étape a pour but de fournir au bot des exemples de réponses aux questions qu’on lui pose.
from chatterbot import ChatBotbot = ChatBot(
"NaiveBot", # Nom
storage_adapter="chatterbot.adapters.storage.JsonFileStorageAdapter",
input_adapter="chatterbot.adapters.input.TerminalAdapter",
output_adapter="chatterbot.adapters.output.TerminalAdapter",
logic_adapters=[ # Desactiver le logic_adapters pour le learning
"chatterbot.adapters.logic.ClosestMatchAdapter",
],
database="naive_database.db", # nom de la base d'échanges
silence_performance_warning=True
)while True:
try:
bot_input = bot.get_response(None)
except(KeyboardInterrupt, EOFError, SystemExit):
break

2. Après l’entraînement, on ajoute un ou plusieurs Logic Adapter au bot et on relance la conversation. Il va, si on active le Closest Match Adapter, chercher dans le corpus d’historique rempli à la phase 1 les réponses à donner. Bien sûr, plus le corpus d’entraînement est grand, plus les réponses du bot seront précises puisque dans tous les cas, il donnera une réponse.

À gauche : entraînement : le bot ne fait que répéter ce qu’on lui envoie et enregistre les interactions
À droite : on active le logic adapter : le bot donne une réponse basée sur le corpus d’entraînement

Implémentation de Botvalue

Création de la BDD à partir des infographies

Pour le test de la librairie sur un use case concret, l’idée est de pouvoir converser avec le chatbot pour connaître des informations sur les Partners de Linkvalue (métier, ville, hobbies, etc.). Il fallait donc une base de données contenant ces informations. Ce qui est bien, c’est que chez Linkvalue, chaque Partner a une infographie contenant toutes ses informations. Ce qui est moins bien, c’est que ce sont des images, il faut donc en extraire toutes les infos. Je ne rentrerai pas dans les détails ici, mais on a implémenté un reader en utilisant tesserocr, un wrapper Python du framework Tesseract dont la spécificité est de faire de l’OCR (Optical Character Recognition).

Infographie d’Arnaud, Data scientist à Linkvalue
Infographie d’Arnaud, Data scientist à Linkvalue

Structure de Botvalue

Pour cadrer le bot, on a donc implémenté un Logic Adapter qui va fonctionner en deux temps :

  1. On entraîne un classifieur binaire qui va différencier une question liée à une requête dans la base de données des Partners (“Que fait Pierre ?”, “Quelle est la date d’anniversaire de Vincent ?”, etc.) à tout autre type de déclaration. Dans le cas d’une requête sur les Partners, on passe à l’étape
  2. Sinon, on définit une réponse ou une liste de réponses par défaut pour recadrer l’interlocuteur. On a utilisé un classifieur naïf Bayésien qu’on entraîne sur une base de questions types qu’on a imaginées. Ce genre de classifieur est assez simple et n’est pas connu pour sa précision mais a l’avantage de s’entraîner très rapidement car il ne calcule que quelques métriques statistiques indépendantes sur la base entraînement.
  3. On sait que la requête concerne une demande d’information sur les Partners. On va chercher à définir la classe des mots présents dans la déclaration :
Sans titre7

On process la déclaration à la recherche de “mots” - ça peut être des unigrammes, des bigrammes ou plus - correspondants aux champs (noms des colonnes de notre base comme nom, ville, etc.) et des mots correspondants aux valeurs. Dans cette première version, si on tombe sur un champ, on sait que c’est l’élément recherché. Et si on tombe sur une valeur, on sait que c’est notre filtre dans la recherche.

L’idée, à terme, est de pouvoir, avec cette technique, convertir n’importe quelle question posée naturellement en requête en base. Si la base liée au bot dans l’exemple est une base SQL, on traduit la phrase automatiquement en requête SQL :

SELECT Birthdate FROM Partners WHERE Name = ‘Vincent’

Pour l’architecture du projet, on enrichit la librairie Chatterbot avec notre Adapter et nos bases de données des Partners. On donne accès également à des corpus pour entraîner le classifieur bayésien pour comprendre dans quel domaine de requête se situe la déclaration de l’interlocuteur. Dans notre main.py, les informations suivantes sont donc passées en paramètres :

bot = ChatBot(
'BotValue',
# store conversations locally
storage_adapter='chatterbot.adapters.storage.JsonFileStorageAdapter',
logic_adapters=[
{ # custom adapter for db queries
'import_path': 'chatterbot.adapters.logic.QueryAdapter',
# training corpus for query adapter
'training_file_for_query': 'query_adapter_training'
}
],
trainer='chatterbot.trainers.ListTrainer',
# Terminal Version
input_adapter="chatterbot.adapters.input.TerminalAdapter",
output_adapter="chatterbot.adapters.output.TerminalAdapter",
database="botvalue.db", # name of local db
silence_performance_warning=True
)

Tests

On voit dans le test la souplesse de compréhension des déclarations pour la transformer en requête en base et retourner la réponse. Aucun travail n’a été effectué sur le format de la réponse : on se contente de renvoyer la valeur du filtre et la valeur du champ recherché.

Pour approfondir…

À partir de ce POC réalisé en 2 jours, on peut imaginer améliorer la traduction des déclarations en requête pour des requêtes autre qu’un champ avec un filtre dans notre base de données. Et même aller plus loin en se disant que le Bot, ayant accès aux données en amont possiblement réparties dans diverses bases, peut, en fonction des éléments présents dans la déclaration de l’interlocuteur, savoir dans quelle base aller requêter pour trouver la réponse. Ce serait une sorte de Bot traducteur de demande naturelle en requête en base de données. Chatterbot a tout de même ses limites. On en a déjà contourné une en implémentant au sein même de la librairie notre propre Logic Adapter, intégrant nos propres corpus d’entraînement, etc. Mais il ne permet pas aisément d’intégrer un modèle non supervisé de représentation vectorielle de mots/phrases/documents comme Word2Vec ou GloVe. Ces modèles seraient à la fois pertinents à utiliser dans les deux phases de notre BotValue. Pour utiliser des modèles plus profonds de NLP dans nos ChatBots, l’idéal serait de partir sur des frameworks de Deep Learning tels TensorFlow ou Theano. Il faut alors penser matériel si on souhaite réentrainer from scratch des classifieurs ou des modèles de représentation vectorielle et donc réfléchir aux coûts de calculs et temps nécessaires à ces types d’entraînement.

Vous pouvez également retrouver plus de POCs dans nos articles Data de la rubrique Data Science de notre compte Medium, et avoir un aperçu de nos différents use cases Data depuis notre site.

Nous publions régulièrement des articles sur des sujets de développement produit web et mobile, data et analytics, sécurité, cloud, hyperautomatisation et digital workplace.
Suivez-nous pour être notifié des prochains articles et réaliser votre veille professionnelle.

Retrouvez aussi nos publications et notre actualité via notre newsletter, ainsi que nos différents réseaux sociaux : LinkedIn, Twitter, Youtube, Twitch et Instagram

Vous souhaitez en savoir plus ? Consultez notre site web et nos offres d’emploi.

L’auteur

Arnaud,
Data Scientist
Data enthusiast for social good

--

--

CBTW
L’Actualité Tech — Blog CBTW

Nos experts partagent leur vision et leur veille en développement web et mobile, data et analytics, sécurité, cloud, hyperautomation et digital workplace.