Machinator pour les nuls

Le Lab

Matchinator est un projet réalisé pour le challenge « Lab » organisé par la société Carboat Média et dont la présentation finale s’est déroulée au cours du séminaire 2018 à Barcelone. L’objectif de ce challenge consistait à proposer un prototype à partir d’un des objets connectés mis à la disposition de tous les participants (Raspberry Pi, Google Home, Lego Mindstorms, Alexa, Horloge connectée, etc). Ces projets devaient être réalisés en équipe, et chaque équipe était mise en concurrence afin de déterminer, au travers d’un vote d’environ 70 personnes, le projet qui respectait au mieux les principaux critères, à savoir : idée innovante, qualité de la réalisation et qualité de la présentation.

Contexte du projet

Pour répondre aux différentes attentes, aussi bien les nôtres que celles d’un marché de niche en plein expansion, la décision fut de prendre le Google home. Les assistants vocaux sont de plus en plus présents dans nos foyers. Les utilisations de plus en plus diversifiées et intelligentes, et tout cela dans des environnements de plus en connectés. Dans un tel contexte, il était évident de voir arrivé sur le marché les géants américain Google et Amazon avec leur proposition d’assistant vocal. Le premier avec son Google Home, le second avec Alexa. Pour le projet Matchinator, le choix s’est porté sur le device pensé par Google : le Google Home. Ce choix se justifie principalement en rapport aux différentes technologies qui l’accompagne.

Le Google Home

Le Google Home est l’enceinte connectée développé par Google et disponible sur le marché depuis le 4 septembre 2016 en magasin (4 octobre en précommande). Il fut annoncé au cours la Google I/O qui s’est déroulé en mai 2016.  Le Google Home se décline en plusieurs versions : Google Home Mini, Google Home et Google Home Max. La différence entre ces versions s’observe principalement sur la qualité sonore, la taille et bien sûr le prix. L’intérêt principal du Google Home est son aspect « intelligent », poser des questions vocalement à la machine, comme il les posera à un être humain, et ainsi obtenir une réponse. Vous pourrez par exemple vérifier la météo, connaître l’heure qu’il est à New-York, remplir votre liste de courses, ou encore demander tout autres informations toutes plus inutiles les unes que les autres (tout ce qu’on aime quoi…).

Le Google Match

Pour comprendre le projet Matchinator, il faut avant tout savoir que les concepteurs sont tous issus de la même feature team au sein de la société : l’équipe SODA. Cette dernière est en charge d’un projet nommé CarMatch, et dont l’intérêt principal est de faire la correspondance entre les données clients (marque, modèle, version, puissance fiscale, etc.) et le référentiel DAB. Cette correspondance est déterminée à l’aide d’un algorithme de matching (Matchin…). La deuxième inspiration vient d’une application web utilisée pour trouver un individu, celui auquel pense l’utilisateur, suite à un jeu de questions/réponses successives. L’idée étant d’apporter un peu de magie à l’utilisateur en apportant une réponse finale valide tout en minimisant le nombre de question/réponse. Cette application, bien connue sous le nom d’Akinator (…ator), apporte un sens au nom Matchinator, qui n’est autre que la contraction de Matching et Akinator (oui, c’est évident, mais il fallait bien le placer quelque part).

L’intérêt de Matchinator ?

La question est désormais de comprendre l’intérêt de ce projet. Comme précisé en début d’article, le principal objectif était la qualité du projet en matière d’innovation. Quoi de plus innovant qu’un projet aussi sérieux qu’amusant ? Matchinator y répond pour vous, et à vive voix ! Un projet sérieux, car la finalité est de proposer un concept qui soit tout simplement exploitable sur le marché, et amusant, car il fait appel à des technologies qui nous font retomber en enfance, époque où chacun d’entre nous se faisait déjà une idée du futur. Alors non Matchinator n’est pas un skate volant, mais il vous fera parler, vous répéter, parfois vous énerver (on reste sur un prototype hein). De cette manière, nous avons souhaité mettre en avant une fonctionnalité intéressante proposée par La Centrale qui consiste à fournir une idée sur la côte d’un véhicule. L’utilisateur devra simplement fournir assez d’informations à Machinator pour la laisser déduire de ces dernières la version exacte de son véhicule et ainsi fournir automatiquement la côte dudit véhicule. Simple, rapide, efficace.

L’intérêt de Matchinator !!!!

Le véritable intérêt de ce projet réside dans le besoin de fournir aux clients une estimation la plus précise possible de la côte d’un véhicule. En effet, aujourd’hui, les données utilisées pour déterminer ladite côte sont celles fournis par la préfecture. Ces données sont généralement incomplètes et ne suffisent pas à déterminer la version exacte du véhicule. Sachant que deux versions partageant le même couple marque/modèle peuvent être vendues à des prix très différents (selon les options par exemple), l’estimation de la côte se voit directement impacté par la diminution de sa précision. Pour répondre à ce problème, Matchinator tentera de rentrer directement en contact avec l’utilisateur. Après la récupération des données de la préfecture, si plusieurs versions sont compatibles, Matchinator demandera directement à l’utilisateur, par le biais de questions, des informations supplémentaires sur les caractéristiques de son véhicule. Le but étant d’affiner le nombre de versions compatible jusqu’à trouver la meilleure. LaCentrale sera ensuite en mesure de fournir à l’utilisateur une estimation exacte de la côte de son véhicule.

La technologie Dialogflow

Avant de rentrer dans le détail de l’application avec un exemple d’user story et des explications plus techniques sur sa conception, il semble inévitable de faire un petit tour auprès de la technologie au cœur de l’application : Dialogflow.

Dialogflow est un Chat Bots conversationnel développé anciennement par Speaktoit sous le nom d’Api.ai. La première release est mise à disposition des développeurs en 2014, puis est racheté en 2017 par Google qui la renomme Dialogflow. Ce dernier dispose d’une interface graphique efficace pour initier l’intégralité des évènements sans avoir besoin d’une seule ligne de code. « Quoi ?! Moi, je suis, INGÉNIEUR INFORMATICIEEEEN ! ». Évidemment, le travail de reconnaissance des phrases utilisateurs est effectué de manière transparente par Dialogflow grâce au machine learning et à son api Cloud Version Language. La configuration des conversations est donc à effectuer intégralement avec l’UI. Concernant sa logique de fonctionnement, il est fortement conseillé de se diriger vers la documentation officielle. À des fins de clarté pour la suite, nous mettrons en exergue quelques mots-clefs issus de la documentation officielle :

  • Agent: l’agent est en quelque sorte un fil de discussion, une suite de questions/réponse (succession d’intent) avec l’utilisateur.overview-diagram
  • Intent: l’intent correspond à l’entité principale d’une conversation gérée par Dialogflow. Elle consiste en 3 étapes distinctes : l’utilisateur fournis l’input dans un contexte précis (voir définition suivante), Dialogflow traite cet input, puis retourne une réponse. Pour construire un intent, on commencera par fournir un ensemble de mots (phrases) qui permettront de déclencher ce dernier lorsque l’utilisateur les prononcera, on les appelle des ‘training phrases’.
  • Context: un contexte contient l’ensemble des données issues de la requête utilisateur. Ce contexte possède une durée de vie à définir et mesuré en nombre d’intent invoqué. Il permet ainsi de garder en mémoire les données d’un intent à un autre.
  • Event: permet d’invoquer un intent sans passer par la communication avec l’utilisateur. Peut être invoqué par exemple par un trigger depuis le backend de l’application.
  • Fulfillment: correspond au webhook qui sera invoqué au déclenchement d’un intent.

Contexte et cas d’utilisation

La présence ou non d’un contexte en particulier est également déterminant pour le déclenchement d’un intent. Pour l’exemple, prenons une application de musique qui pourra effectuer deux actions : lancer une musique et obtenir le nom de l’artiste auteur de cette musique. Nous créons donc deux intents : le premier se déclenchera au moment où l’utilisateur fournira une phrase du type « Musicator, lance la musique XXX », la deuxième lorsque l’utilisateur fournira une autre phrase du type « Quel est l’auteur de cette musique ? ». Maintenant, que se passe-t-il si l’utilisateur, au lancement de l’application, pose directement la deuxième question ? Comme vous l’aurez compris (enfin j’espère), le deuxième intent devrai se déclencher. Et pourtant, comment Musicator peut fournir une réponse sachant qu’aucune musique n’a été lancé ? Et c’est maintenant qu’entre en jeu les contextes. En effet, l’idée est de créer un contexte en sortie du premier intent : si l’utilisateur commence par demander le lancement de la musique XXX, l’application tentera dans un premier temps de récupérer le nom de l’artiste à partir du nom de la musique (via un appel webhook par exemple), il ouvrira ensuite un nouveau contexte dans lequel il persistera le nom de la musique et le nom de l’artiste, et enfin il lancera la musique. A présent, si la question de l’auteur est posée, Dialogflow connaîtra la réponse, stocké dans le contexte ouvert précédemment. Cela induit une nouvelle logique dans le déclenchement d’un intent, qui sera possible que si un certain contexte est présent et vivant en entrée de cet intent (si besoin évidemment). Ce dernier pourra à son tour ouvrir de nouveaux contextes en sortie, rendant possible le déclenchement d’autres éventuelles intents.

Cet exemple illustre bien tout l’intérêt des contextes et du lien étroit que ces derniers disposent avec les intents. Suivez ce lien si vous souhaitez obtenir un aperçu de la façon dont on crée un projet simple avec Dialogflow.

Matchinator et Dialogflow

Matchinator-4194-b968a693-0

Le schéma précédent présente le graphe des possibilités de l’application Machinator, dont chaque nœud illustre une étape, et chaque arête le passage d’une étape à une autre. Plus précisément :

    • Les rectangles représentent des actions : en vert, les actions effectuées sur Dialogflow (attente d’une phrase prononcée par l’utilisateur ou le bot), et en bleu, les actions effectuées côté serveur (logique de l’application).
    • Les losanges représentent quant à eux des décisions à prendre sur le serveur.
    • Les parallélépipèdes blancs représentent les contextes en entrée et en sortie. La création d’un nouveau contexte est illustrée par sa police d’écriture en gras.
  • Les labels jaunes représentent quant à eux les intents.

Instant publicité

machinator

Vous disposez d’un Google home ? Bon début. Vous avez un véhicule à vendre ? Cool. Vous désirez connaître une estimation de la côte de cette dernière ? Parfait. Plus qu’à lancer l’application Matchinator et amusez-vous ! Pour les grands et les petits, n’ayez qu’une seule et unique peur, devenir accro, car avec Matchinator, acheter pour revendre deviendra votre nouvelle passion !

Bref, installez l’application et profitez du discours de présentation par Machinator elle-même (oui oui !) :

Bonjour.
Je me présente, je m’appelle Matchinator et j’ai le pouvoir de déterminer la valeur de votre véhicule.
Pour cela rien de plus simple, donnez-moi le numéro de votre plaque d’immatriculation ainsi que votre kilométrage, et je serai apte à déterminer la côte de votre véhicule.
De plus, si vous le souhaitez, je peux déposer une annonce directement sur le site LaCentrale. L’adresse e-mail utilisée sera celle de votre compte Google associé à votre Google assistant. Je vous souhaite de bien vous amuser.

Macro-tchinator

Ainsi, le déroulement macro d’une utilisation de Matchinator peut se résumer comme suit : vous avez votre véhicule et vous connaissez la plaque d’immatriculation de ce dernier. Vous lancez l’application, le bot vous demandera l’immatriculation, que vous lui fournirez. À partir de cette immatriculation, il cherchera l’ensemble des versions associées. S’il ne trouve aucune version, déçu, il coupera la conversation. S’il trouve exactement une version, il exprimera l’intitulé exact de la version, puis demandera son kilométrage. Une fois le kilométrage connu, il vous retournera si possible la côte estimé de la version. Prenons le cas ou à partir de l’immatriculation il trouve plusieurs versions : il commencera par vous indiquer la marque et le modèle des versions trouvées, puis se suivra la fameuse succession de questions/réponses dans le but d’affiner les résultats, déterminer la bonne version, et enfin retourner la côte de cette dernière.

Micro-tchinator

A présent, disséquons chaque mécanique illustrée précédemment. N’hésitez pas à jeter un œil aux schémas associés pour mieux comprendre (petite technique de cow-boy, t’inquiète c’est free).

Partie 1 – Obtention du numéro minéralogique

1

L’application se lance sur le nœud ‘start’. L’intent ‘welcome’ est automatiquement déclenché par Dialogflow. Ce dernier lui permet de poser une question à l’utilisateur. La réponse à cette question est primordiale, nous avons donc besoin de la stocker en mémoire. C’est la raison pour laquelle nous ouvrons en sortie de cette intent le contexte ‘awaiting-license-plate’. A cet instant, l’application est mise en attente d’une réponse à l’initiative de l’utilisateur. Celle-ci donnée est valide, un intent est à nouveau déclenché, le ‘user-provide-license-plate’. Pour information, ce dernier avait besoin de deux entités pour pouvoir se déclencher: une réponse valide (par rapport au type de phrase attendu par Dialogflow) de l’utilisateur et le contexte ‘awaiting-license-plate’ vivant en entrée (à l’ouverture d’un nouveau contexte, on lui affecte une durée de vie, qui décrémente de 1 pour chaque intent déclenché depuis sa création. Si cette durée de vie tombe à zéro, le contexte est détruit, de même pour les données qui l’accompagnent).

Partie 2 – Obtention des versions

find_version

Le dernier intent déclenché aura quant à lui la tâche de vérifier si l’immatriculation fournis par l’utilisateur est valide. Pour cela, il fera appel à un webhook (application externe qui simulera un utilisateur), correspondant au backend de notre application. Ainsi, depuis ledit backend, il sera déterminé si l’immatriculation est associée à zéro, une ou plusieurs versions. Selon le résultat, et toujours depuis le server, un event sera utilisé afin de déclencher le bon intent.

Partie 3 – zéro version trouvée

find_version

Si l’immatriculation n’existe pas ou qu’elle existe mais n’est associé à aucune version, alors l’intent ‘user-provides-license-plate’ retournera comme réponse la fermeture de l’application.

Partie 4 – une version trouvée

3

Dans le cas où exactement une version est trouvée, le backend ouvrira lui-même un nouveau contexte, que l’on nommera ‘version-found’, qui permettra de stocker la version trouvée. Ensuite, à l’aide de l’event ‘version-found-event’, l’intent ‘version-found’ sera déclenché. Ce dernier permet d’exprimer le libellé exact de la version trouvée et précédemment stocké dans le contexte ‘version-found’ puis de poser la question du kilométrage. En sortie de cet intent, un nouveau contexte est ouvert, en parallèle du premier, nommé ‘awaiting-mileage’, afin de stocker la valeur de kilométrage ainsi obtenue.  Nouvelle mise en attente de l’application jusqu’à l’expression de l’utilisateur. La réponse fournis, l’intent ‘user-provide-mileage’ se déclenche, suivi par un nouvel appel webhook qui se chargera de récupérer la valeur de la côte de la version. Si la côte est introuvable, alors l’intent fournira comme seule réponse la fermeture de l’application, sinon elle exprimera cette valeur puis fermera à son tour l’application.

Partie 5 – plusieurs versions trouvées

Une partie aussi complexe qu’intéressante. L’immatriculation nous permet d’obtenir un certain nombre de versions pour un seul couple marque/modèle. Ainsi, en réponse de l’intent ‘user-provide-license-plate’ (rappelez-vous qu’à ce stade du workflow nous nous trouvons toujours dans cet intent), Matchinator nous énoncera la marque, le modèle, ainsi que le nombre de versions trouvées. C’est alors qu’on met en place la succession de question/réponse à l’instar de l’application Akinator (pour rappel, l’idée est de permettre à l’application de « deviner » la personne à laquelle pense l’utilisateur en posant un minimum de questions simples). De la même façon, Machinator se contentera de déterminer la bonne version parmi toutes les possibilités.

find_multiples_version

Pour cela, on commence par initialiser un nombre maximum de questions à poser depuis le backend de l’application, après quoi, s’il reste plusieurs versions en course, on ouvre le contexte ‘version-found’ dans lequel on stocke une version aléatoire parmi les n restantes et on se redirige vers le cas 4.

A l’inverse, dans le cas où le nombre maximum de questions n’est pas atteint, on calcule, côté backend toujours, le mot le plus représenté parmi les versions restantes. Tant qu’un mot est présent dans toutes les versions, on le supprime. Nous nous chargeons ensuite de sélectionner la finition présente le plus grand nombre de fois afin de filtrer un maximum de versions pour chaque question. Pour cela, à l’aide d’un event porté par le backend, l’intent ‘ask-for-word-candidate’ se déclenchera et ouvrira un nouveau contexte : ‘awaiting-word-candidate’.

Machinator demandera ensuite si le mot précédemment sélectionné apparaît en tant que finition dans la version de l’utilisateur. Nouvelle attente. Avec l’ouverture du dernier contexte, deux intents sont fins prêts à se déclencher, et ce en fonction de la réponse de l’utilisateur. Si l’utilisateur répond oui, c’est l’intent ‘user-provides-word-candidate-yes’ qui se déclanchera, sinon l’intent ‘user-provides-word-candidate-no’. Quel que soit la réponse, les versions présentes dans le contexte ‘matched-versions’ (toujours persistant) se mettrons à jour. Selon s’il répond oui ou non, on supprimera toutes les versions ne possédant pas le mot sélectionné, sinon toutes les versions le possédant. Les versions mise à jour, on renouvelle le contexte ‘matched-versions’ en incrémentant sa durée de vie de 1 (qui, pour rappel, se décrémente toute seule à mesure que les questions défilent). L’idée étant de garder ce contexte ouvert tant qu’il reste plus d’une version. A nouveau, on vérifie le nombre de versions restantes, s’il est supérieur à un, on réitère depuis le début, sinon on stocke la dernière version dans le contexte ‘matched-version’, est on redirige l’application vers le cas 4.

Architecture de l’application

Blank Diagram

L’utilisateur est en lien avec Google et ses serveurs par l’intermédiaire de son objet connecté le Google Home. Ce dernier communique ensuite avec Dialogflow au travers du Google assistant. Dialogflow, comme décrit précédemment, a plusieurs possibilités : traiter la requête utilisateur et envoyer une réponse directement depuis ses propres serveurs, ou bien faire appel à un webhook (en l’occurrence le backend de notre application).

La technologie Amazon AWS a été utilisée avec un certain nombre d’outils qu’elle propose. L’API REST développé est hébergée dans API Gateway, un VPC Link est ensuite intégré dans API Gateway afin d’intégrer l’API aux ressources VPC gérées par le load balancer. Le serveur web est quant à lui hébergé au sein d’une instance Amazon EC2. Ce dernier peut potentiellement communiquer avec l’application Matching Immat, elle-même hébergée sur Amazon AWS.

Le projet aujourd’hui?

Les difficultés rencontrées sont principalement liées à Dialogflow. Cette technologie repose sur des principes que nous ne rencontrons que rarement. Si vous en êtes là, alors vous avez lu les parties précédentes (attention sur WordPress un bot vous surveille, je le saurai). Si certaines phrases vous ont fait défauts, si certaines ont été relues, voir relues encore, alors vous nous comprendrez. Le principe des contextes, des intents ou des events sur Dialogflow est déroutant, rien de très compliqué, juste déroutant.

Soyons clair, le projet est encore à l’état de POC. Il s’agit simplement d’un prototype qui repose à la fois sur une idée et sur une technologie nouvelle. En tant que développeur, notre principal objectif était d’une part la participation au concours « Le Lab », mais surtout prendre du plaisir à tester de nouvelles technologies. Dans cette idée, nous avons fait, puis nous avons refait, ensuite testé, pour refaire à nouveau, recyclé, rejoué et débuggé, et ainsi de suite jusqu’au fameux dernier jour.

C’est pourquoi le projet fonctionne, et très bien même, mais reste actuellement incomplet. Les magics numbers sont là et feront de l’oeil à tout ceux qui oseront s’aventurer dans le code. Les tests unitaires sont nombreux, approximativement zéro. Des problèmes résolus en dur dans le code, peu de factorisation. Bref, pas toujours propre, certes, mais cette confidence me permettra de dormir la conscience tranquille.

Et puis de toute façon on a gagné, alors bon…