Go to Hackademy website

Un chatbot, une API et Recast.AI

Hugo Fabre

Posté par Hugo Fabre dans les catégories dev

Cet article est publié sous licence CC BY-NC-SA

Les chatbots c’est un peu à la mode en ce moment, on en voit de plus en plus sur beaucoup de sites. Aujourd’hui je vous propose de nous intéresser à Recast.AI.

Recast.AI

C’est une plateforme qui vous permet de créer et déployer vos bots facilement. Il y a pas mal d’avantages à l’utilisation de Recast, notamment l’intégration avec plusieurs canaux de discussion (Slack, Skype…), l’utilisation du traitement automatique du langage naturel intégré (NLP ou natural language processing). D’autre part, Recast fait partie des outils qui gèrent le mieux la langue française.

Recast c’est aussi une plateforme communautaire, vous pourrez donc sans problème récupérer des fonctionnalités d’autres bots s’ils sont publics.

Il faut savoir que c’est un outil très complet, donc l’objectif de cet article ne sera pas d’en présenter toutes les fonctionnalités. Nous allons rester sur un domaine assez précis, l’utilisation d’un bot Recast avec une API personnelle (hébergée en local).

Avant toute chose il est important de comprendre quelques notions qui sont à la base de Recast.

Fonctionnement de base

Le traitement automatique du langage de Recast se base sur plusieurs principes. Pour commencer, il faut bien comprendre que ce traitement est fait par du machine learning et nécessite donc un entraînement pour fonctionner correctement. Pour l’entraîner nous avons à notre disposition plusieurs outils, voici ceux qui nous intéressent :

Les intentions sont centrales, car très souvent utilisées pour déclencher une action spécifique chez notre bot. Concrètement avec Recast elles sont représentées comme une boîte dans laquelle vous mettrez des types de phrases qui apprendront au bot (via du machine learning) à reconnaître votre intention. Il faut garder en tête que plus vous avez de phrases avec des constructions grammaticales différentes, plus votre bot sera précis dans sa reconnaissance d’intention :

Salut, je m’appelle Toto.

Je me présente, moi c’est Toto.

Les entités sont des mots-clés qui peuvent être extraits d’une expression donnée. Par exemple dans la phrase suivante :

Je mange un abricot.

On pourrait extraire le mot-clé « fruit » depuis le mot « abricot ». En réalité il existe aussi ce qu’on appelle des gold entities qui sont des entités que Recast est entraîné à reconnaître par lui-même sans action de votre part :

Capture%20d%E2%80%99e%CC%81cran%202018-03-09%20a%CC%80%2010.10.53.png

Dans notre exemple nous n’aurons pas besoin d’entités personnalisées, mais pour aller plus loin, je vous invite à regarder la documentation sur les entités et les gazettes.

Enfin, Recast intègre son propre bot builder qui est une interface web qui vous permettra de créer le flux de conversation de votre bot, c’est ici que vous pourrez créer vos fonctionnalités et expliquer à Recast comment elles doivent s’enchaîner.

Capture%20d%E2%80%99e%CC%81cran%202018-03-09%20a%CC%80%2010.31.47.png

Chaque brique présente dans le bot builder représente une fonctionnalité (skill dans Recast).

Pour chacune nous pouvons définir un déclenchement, en général c’est la détection d’une intention spécifique :

Capture%20d%E2%80%99e%CC%81cran%202018-03-09%20a%CC%80%2010.35.19.png

La deuxième étape d’un skill est très importante, en effet tant que tous vos requirements ne seront pas remplis, le bot ne passera pas à la dernière étape de votre skill (dans notre cas un appel à notre API). Il est aussi bien de savoir que pour chaque requirement vous pouvez enregistrer des phrases dans le cas où il est présent (“Merci de m’avoir donné votre nom”), ou dans le cas où il n’est pas présent (“Il me faut votre nom pour continuer”).

Capture%20d%E2%80%99e%CC%81cran%202018-03-09%20a%CC%80%2011.08.51_thumb_650.png

Ici par exemple, on va récupérer l’entité (gold) person dans une variable appelée name qui une fois extraite de la conversation par Recast sera stockée dans la mémoire de votre conversation. La mémoire est un outil important pour Recast, elle sera envoyée lors d’un appel de votre bot à votre API et c’est là-dedans que vous pourrez récupérer les informations qui vous intéressent.

Parlons enfin de la dernière étape d’un skill, les actions, qui se déclencheront une fois que tout vos requirements seront remplis.

Il y a plusieurs types d’actions disponibles, comme renvoyer un réponse en texte ou avec des boutons, etc. Dans notre cas, nous allons choisir de faire appel à notre API.

Capture%20d%E2%80%99e%CC%81cran%202018-03-09%20a%CC%80%2011.12.03_thumb_650.png

Encore une fois, il est possible de conditionner les différentes actions de votre bot selon plusieurs paramètres comme ce qu’il y a dans la mémoire ou bien si la personne est passée trop de fois dans le même skill :

Capture%20d%E2%80%99e%CC%81cran%202018-03-09%20a%CC%80%2011.14.21.png

Contact bot

Nous allons construire un bot très simple. Il aura deux skills :

  • Enregistrer un utilisateur et son email en base de données
  • Récupérer un email de contact depuis un nom

L’API

Avant de commencer, nous allons mettre en place notre API. Je vous propose d’utiliser une API toute simple en Ruby, mais vous êtes libre de faire la vôtre. Pour faire fonctionner cette API, vous aurez besoin de Ruby, de la gem Sinatra et de la gem Sequel.

# api.rb

require "sinatra"
require "json"
require "sequel"

# Setup SQLite3 database with sequel
DB = Sequel.sqlite("database.sqlite3")
DB.create_table? :contacts do
  primary_key :id
  String      :fullname
  String      :email
end

class RecastResponse
  def initialize
    @response = { replies: [] }
  end

  def add_text_reply(msg)
    add_reply(type: "text", content: msg)
  end

  # Ici on vide la mémoire pour éviter que d'anciennes données ne viennent nous gêner.
  # Il est aussi possible de le faire depuis l'interface de Recast
  def clear_memory!
    @response[:conversation] = { memory: {} }
  end

  def generate
    @response.to_json
  end

  private

  def add_reply(reply)
    @response[:replies] << reply
  end
end

class RecastParams
  attr_reader :fullname, :email

  def initialize(payload)
    # On va chercher les informations dont on a besoin dans la mémoire.
    @fullname = payload["conversation"]["memory"]["name"]["fullname"]
    @email = payload.dig("conversation", "memory", "email", "raw")
  end
end

before do
  @body = JSON.parse(request.body.read) rescue {}
end

set :port, 5000
set :bind, "0.0.0.0"

post "/register_contact" do
  content_type :json
  params = RecastParams.new(@body)
  contacts = DB[:contacts]
  contacts.insert(fullname: params.fullname, email: params.email)
  response = RecastResponse.new
  response.clear_memory!
  response.add_text_reply("Merci, j'ai enregistré votre email: #{params.email}")
  response.generate
end

post "/search_contact" do
  content_type :json
  params = RecastParams.new(@body)
  contacts = DB[:contacts].where(Sequel.ilike(:fullname, "%#{params.fullname}%"))
  response = RecastResponse.new
  response.clear_memory!
  if contacts.count <= 0
    response.add_text_reply("Je n'ai pas trouvé avec: #{params.fullname}")
  elsif contacts.count == 1
    response.add_text_reply("#{params.fullname} - #{contacts.first[:email]}")
  else
    response.add_text_reply("Il y a beaucoup de #{params.fullname}:")
    contacts.each do |contact|
      response.add_text_reply("#{contact[:fullname]} - #{contact[:email]}")
    end
  end
  response.generate
end

Les services de Recast étant automatiquement hébergés et déployés chez eux, nous aurons besoin d’exposer notre API. Pour cela nous allons utiliser ngrok.

Dès que vous avez tous les outils, nous pouvons lancer l’API :

ruby api.rb

Puis ngrok pour exposer notre API :

ngrok http localhost:5000

Pensez à changer le port si vous avez choisi d’utiliser un autre port que celui proposé ici.

Le bot

Je vous invite d’abord à créer un compte sur Recast.

Ensuite, rendez-vous sur la page de création de bot, puis sélectionnez la première option (Create a complete chatbot). Ensuite Recast nous propose d’intégrer directement des fonctionnalités à notre bot, nous allons prendre la première qui est la plus légère (Greetings). Il ne nous reste plus qu’à remplir les dernières options, j’ai personnellement mis mon bot public et en français.

Capture%20d%E2%80%99e%CC%81cran%202018-03-07%20a%CC%80%2016.21.44.png

Vous arrivez donc sur la page de votre bot, il y a plusieurs onglets disponibles. En premier lieu, nous allons dans les settings pour y remplir l’URL de notre API exposée par ngrok.

Capture%20d%E2%80%99e%CC%81cran%202018-03-09%20a%CC%80%2011.38.15_thumb_650.png

Ensuite, nous allons dans la partie Train pour enregistrer les deux intentions dont nous aurons besoin. On voit qu’il y a déjà deux intentions fournies par Recast, mais nous n’en aurons pas besoin. Commençons par créer nos deux intentions :

Capture%20d%E2%80%99e%CC%81cran%202018-03-09%20a%CC%80%2011.41.59_thumb_650.png

Le petit nombre à droite correspond au nombre de phrases données au bot pour l’entrainer. Pour le moment nous en avons donc zéro. J’en profite pour faire une petite remarque là-dessus, on voit en regardant les intentions fournies par Recast qu’elles ont environ 80 expressions d’entraînement, donc si vous trouvez que votre bot ne reconnaît pas assez facilement votre intention, n’hésitez pas à lui rajouter beaucoup de phrase d’entraînement (et je le répète : avec une construction grammaticale différente).

C’est parti, allons entraîner notre bot. Pour notre exemple, nous allons enregistrer entre cinq et dix phrases par intention.

Pour l’intention register-user, j’ai mis :

Capture%20d%E2%80%99e%CC%81cran%202018-03-13%20a%CC%80%2014.39.12_thumb_650.png

Si on regarde en haut, on voit que Recast a été capable de détecter tout seul les entités person et email. Et on passe à notre deuxième intention, search-user :

Capture%20d%E2%80%99e%CC%81cran%202018-03-13%20a%CC%80%2014.40.03_thumb_650.png

Si vous avez bien regardé l’interface, vous avez vu le bouton fork. C’est lui qui permet de récupérer des intentions ou des fonctionnalités depuis des bots existants.

Voilà pour nos intentions, maintenant on va expliquer au bot ce qu’il doit en faire, pour ça rendez-vous sur l’onglet build.

Il y a déjà un skill fourni par Recast, nous allons le supprimer pour éviter toute interférence avec les nôtres.

Commençons à créer notre premier skill. On remarque que lors de la création, on a trois choix :

  • Business : ce sont les skills représentant votre logique métier ;
  • Floating : ce sont les petits skills destinés à rendre vos bots plus vivants (savoir répondre à une insulte ou un compliment par exemple) ;
  • Fallback : c’est le skill dans lequel on va tomber si aucun autre skill n’est déclenché par une phrase.

Dans notre cas, nous aurons seulement besoin de business.

Capture%20d%E2%80%99e%CC%81cran%202018-03-09%20a%CC%80%2012.05.12.png

Ensuite pour les éditer, il suffit de cliquer sur leur nom et on arrive sur les trois étapes d’un skill dont on a parlé plus haut.

Dans notre cas, le déclencheur de chacun de nos skills sera l’intention correspondante :

Capture%20d%E2%80%99e%CC%81cran%202018-03-09%20a%CC%80%2012.07.37.png

Les requirements en revanche seront différents, pour enregistrer un utilisateur nous aurons besoin d’un email et d’un nom :

Capture%20d%E2%80%99e%CC%81cran%202018-03-09%20a%CC%80%2012.09.25_thumb_650.png On note qu’à gauche on met l’entité voulue, et à droite un alias pour récupérer la valeur en mémoire.

Pour rechercher un utilisateur, nous n’aurons ici besoin que du nom :

Capture%20d%E2%80%99e%CC%81cran%202018-03-09%20a%CC%80%2012.11.27_thumb_650.png

Et enfin on peut définir nos actions qui seront dans chaque cas un appel à l’endpoint correspondant de notre API. (Il faut cliquer sur add new message group puis sur call webhook).

Capture%20d%E2%80%99e%CC%81cran%202018-03-09%20a%CC%80%2012.13.43_thumb_650.png

Ici, si on peut se contenter de mettre juste notre endpoint c’est parce qu’au début nous avons enregistré l’adresse de notre API dans les paramètres, sinon il aurait fallu mettre l’URL complète :

https://f6841964.ngrok.io/search_contact

Puis l’action qui va permettre d’enregistrer un utilisateur :

Capture%20d%E2%80%99e%CC%81cran%202018-03-09%20a%CC%80%2012.16.44_thumb_650.png

Et voilà, il n’y a plus qu’à tester, on clique sur chat with your bot et on enregistre quelques utilisateurs :

Capture%20d%E2%80%99e%CC%81cran%202018-03-09%20a%CC%80%2012.19.28.png

Et on peut les récupérer :

Capture%20d%E2%80%99e%CC%81cran%202018-03-09%20a%CC%80%2012.25.03.png

Vous êtes arrivé au bout, vous voilà un bot qui vous servira pour le reste de votre vie ! Je vous invite bien sûr à bidouiller ce que nous avons fait pour voir tout ce qu’il est possible de faire avec Recast.

Aller plus loin

Pour connecter votre bot à un canal de communication tout est indiqué dans la partie connect :

Capture%20d%E2%80%99e%CC%81cran%202018-03-09%20a%CC%80%2014.19.32_thumb_650.png

Évidemment, si quelque chose ne vous paraît pas clair ou que vous souhaitez en savoir plus, je vous invite à regarder la documentation officielle de Recast. Et surtout, n’hésitez pas à rejoindre leur Slack, ils sont très présents pour aider leur communauté.


L’équipe Synbioz.
Libres d’être ensemble.

Articles connexes

Résolution de bug — parlons méthodologie

15/06/2018

Véritable ascenseur émotionnel pour tout développeur, le faisant passer successivement du déni à la frustration, de l’incrédulité à la résignation, puis de l’espoir au soulagement, le débogage est un...

Du e-commerce avec React & Stripe

13/04/2018

Le e-commerce est un canal de vente qui a le vent en poupe. De plus en plus de personnes achètent en ligne sur des plateformes telles qu’Amazon ou CDiscount pour ne citer que celles-ci. Pour vous...

La magie de Rake

13/10/2017

Lecteur aguerri, vous devez savoir que nous sommes, chez Synbioz, une bande de Ruby Lovers comme tant d’autres ! Au cœur de notre activité quotidienne réside Ruby, aussi nous prenons un certain...

Les chaînes de caractères en Ruby

26/07/2017

Parce qu’il est bon de se rafraichir la mémoire de temps en temps, aujourd’hui nous allons nous intéresser aux différentes possibilités que nous offre Ruby pour le formatage des chaînes de...