Le Google Assistant pour les développeurs Android - PART 2

le 16/04/2020 par Nicolas Telera
Tags: Software Engineering

Cet article fait suite à un premier article “Le Google Assistant pour les développeurs Android - PART 1”.

Dans le premier article, nous avons exploré la partie “Solutions” offerte par Google à travers la réalisation d’une application simple. Nous avons mis en place une App Action permettant de lancer directement une feature spécifique de notre application au travers d’une commande vocale, puis nous l’avons améliorée avec l’affichage d’une Slice.

Bien que très simple à mettre en place, nous avons rapidement constaté les limites de cette partie. En effet, celle-ci ne permet que le lancement d’une feature ou, au mieux, un affichage modeste des données de l’application dans l’Assistant.

Cependant, lorsqu’on pense Assistant Google, on pense “conversation”. Dans ce second article, nous allons découvrir la deuxième possibilité pour le développement sur Android, à savoir les “Custom Conversations”, à travers la mise en place d’une Action Conversationnelle qui nous permettra d’échanger avec l’Assistant et d’obtenir des réponses construites à partir d’une API.

Les Actions Conversationnelles

Les App Actions nous permettent d’interagir avec l’Assistant Google. Cependant, on ne peut pas à proprement parler de conversation dans le sens où il n’y a pas de suite d’échanges entre ce dernier et l’utilisateur. On ne distingue pas réellement le début de la fin de l’interaction. Par exemple, si je veux jouer à un jeu ou réserver un billet d’avion, il sera compliqué d’obtenir le résultat voulu en une seule commande vocale.

Les Actions Conversationnelles sont des actions plus poussées qui vont nous permettre de créer avec beaucoup plus de précision nos interactions. Elles sont déclenchées lorsque l’utilisateur les invoque et continuent jusqu’à ce que la fin de la conversation soit identifiée tout en tenant compte des différents facteurs d’une conversation réelle tels que l’adaptation du discours à l’interlocuteur ou encore la prise en compte de l’absence de réponse à une question.

Elles fonctionnent au travers d’échanges de données au format JSON. En effet, lorsque l’utilisateur envoie une requête vocale à l’Assistant, celui-ci déclenche une série d’étapes qui permettront de retourner une réponse adaptée :

  • l’input de l’utilisateur est transformé en texte par l’Assistant
  • ce texte est utilisé pour créer des requêtes JSON
  • ces requêtes sont envoyées à un “conversation fulfillment” par requête HTTPS
  • le conversation fulfillment parse la requête en données structurées puis déclenche un webhook
  • puis il retourne la réponse du webook au format JSON à l’Assistant
  • l’Assistant traite cette réponse afin d’afficher une réponse à l’utilisateur

Il existe deux façons de construire des actions conversationnelles : l’utilisation de l’Actions SDK, qui va demander de fournir sa propre solution de Natural Language Understanding (NLU), ou celle de Dialogflow, grandement recommandée par Google.

Nous ne nous pencherons ici que sur la partie Dialogflow et son interface web qui nous simplifiera grandement le travail.

Dialogflow ?

Dialogflow est un service web proposé par Google permettant de construire des interfaces conversationnelles en utilisant le machine learning. C’est l’outil le plus largement utilisé pour la mise en place d’Actions sur plus de 400 millions d’Assistants Google.

L’utilisation de ce service nous permet de laisser un agent Dialogflow gérer la transformation de nos requêtes avec le NLU, en se basant à la fois sur des phrases d’entraînement que nous lui fournissons ainsi que sur le contexte de la conversation. Une fois qu’une requête est identifiée, il va pouvoir l’associer à un événement et en extraire les paramètres dans des entités Dialogflow.

Ce sont ces évènements qui sont associés à des “fulfillments”, à savoir des webhooks faisant le lien avec des Cloud Functions sur Firebase, au sein desquelles on pourra effectuer toute la logique nécessaire à notre requête, comme par exemple appeler un web service.

Prenons le cas suivant : l’utilisateur veut demander à l’Assistant une anecdote au sujet d’un nombre. Il va donc falloir qu’il lui pose une question adaptée à partir de laquelle un événement sera associé par Dialogflow et une entité extraite sous la forme d’un nombre. De cet événement sera déclenchée une Cloud Function prenant ce nombre en paramètre et qui fera un appel vers une API afin de construire une réponse. Enfin, cette réponse sera retournée à l’Assistant qui n’aura plus qu’à l’afficher et la dire à l’utilisateur.

Ainsi, la majeure partie du travail nécessaire à la mise en place de cette Action Conversationnelle sera la création de la Cloud Function.

C’est parti !

Pré-requis

Pour pouvoir commencer à construire une Action Conversationnelle à travers Dialogflow, il va falloir se rendre sur la page de son compte Google relative aux données dans l’Assistant afin d’activer les paramètres nécessaires, à savoir :

  • les activités sur le Web et les applications
  • les enregistrements vocaux et audio
  • les informations sur les applications provenants de vos appareils

Puis il faut se rendre dans “Activité sur le Web et les applications” pour cocher les deux cases “Inclure l’historique Chrome” et “Inclure le enregistrements vocaux et audio”.

Aussi, un minimum de connaissances en JavaScript est recommandé afin de pouvoir comprendre le code des Cloud Functions.

Enfin, si l’on utilise Chrome avec plusieurs comptes associés, il faut s’assurer que l’on utilise le même compte sur les différentes consoles que nous allons voir par la suite.

Mise en place d’une Action Conversationnelle avec Dialogflow

La première étape à suivre lorsqu’on veut mettre en place une Action Conversationnelle est de se rendre sur l’Actions Console. C’est sur cette console que nous allons pouvoir gérer nos actions, les tester et à terme les publier.

Créons notre projet.

Cette action crée également un projet sur Firebase pour pouvoir y déployer les Cloud Functions à déclencher à partir des webhooks qui seront créés.

Une fois le projet créé, on constate qu’il existe un certain nombre d’expériences prévues par Google et utilisables sous la forme de Built-in Intents. Attention, bien que très similaires, les Built-in Intents présents ici ne sont pas ceux des App Actions vus dans l’article précédent. Ils permettent en effet de faire le lien avec certains évènements spécifiques de Dialogflow et contiennent donc des ensembles de données différents.

Le but de ces Built-in Intents est d’indiquer l’Assistant que notre Action peut remplir une catégorie spécifique de requêtes utilisateur (jouer à un jeu, obtenir un horoscope…). Cependant, afin de mieux comprendre ce que nous faisons, nous allons directement sélectionner la catégorie “Conversational”. Cette catégorie va nous permettre de mettre un place une action vide que nous allons associer à un fulfillment Dialogflow personnalisé.

Notre premier projet étant créé, ajoutons notre première Action Conversationnelle en cliquant sur Build your Action > Add Action(s) > Custom intent > Build.

La création de cet intent personnalisé nous redirige alors automatiquement vers la console Dialogflow sur la page de création de l’agent afin de valider sa création. On peut alors constater que notre agent est bien lié à notre projet sur l’Actions Console.

Au sein de la console Dialogflow, on trouve les principales catégories qui vont nous intéresser dans cet article :

**Intents**on y trouve les différents intents que l’on va associer à notre Action (début et fin de conversation, demande de permissions, questions et traitement des réponses...)
**Entities**on y trouve les différentes entités qui seront identifiées dans notre Action et utilisées au sein de nos intents
**Fulfillment**c’est ici que seront gérés les fulfillments de nos intents, notamment sous la forme de webhooks
**Integrations**c’est ici que l’on pourra intégrer notre action à différents services (Slack, Twitter etc.) mais c’est surtout ici que l’on pourra configurer le déploiement de nos modifications sur la console de test

Démarrer une conversation

Afin de pouvoir démarrer une conversation, chaque projet Actions doit avoir un point d’entrée sous la forme d’un “welcome intent” qui sera invoqué lorsque l’utilisateur prononcera le nom de l’Action. Cet intent est créé par défaut par Dialogflow dans la section Intents vue précédemment. On constate aussi la présence d’un intent de fallback par défaut. C’est cet intent qui sera utilisé dans tous les cas où Dialogflow n’arrive pas à associer d’intent spécifique à la requête JSON reçue et qui permettra à l’Assistant de répondre une phrase type “One more time?”.

En cliquant sur notre intent de bienvenue, on peut voir les différentes réponses prévues par défaut. Afin d’avoir la main sur notre Action Conversationnelle du début à la fin de la conversation, nous allons supprimer toutes les réponses présentes afin d’y ajouter la nôtre : “Welcome! What number do you want to know about?”.

Après chaque modification, que ce soit sur les intents ou les fulfillments, il ne faut pas oublier de sauvegarder les modifications avec le bouton SAVE.

Tester une Action Conversationnelle

Nous pouvons dès à présent tester notre Action en nous rendant dans la section Integrations puis en cliquant sur Google Assistant > Integration Settings > TEST. Il est également utile d’activer Auto-preview changes pour que les changements soient automatiquement déployés vers l’Actions Console et le simulateur de test.

On arrive alors sur le simulateur de l’Assistant sur lequel on va pouvoir tester notre Action. On retrouve sur la gauche un simulateur de smartphone et sur la droite une version un peu plus configurable avec la possibilité d’afficher notre Action sur différents supports tels que les Smart Displays ou encore les enceintes. Ces différents supports seront utiles pour tester les cas à la marge tels que l’absence de réponse vocale.

On y trouve également des onglets utiles : REQUEST, RESPONSE, DEBUG et ERRORS. C’est ici que l’on pourra visualiser les requêtes et les réponses échangées au format JSON et accéder à un premier niveau de debugging de nos interactions.

Il nous suffit maintenant de taper “Talk to my test app” et de faire entrée ou bien de cliquer sur l’input suggéré pour déclencher notre “Welcome intent”.

À noter qu’à partir du moment où une Action est déployée, il est également possible de la tester directement sur un smartphone sur lequel le compte Google utilisé est authentifié (après avoir configuré la langue de l’Assistant en Anglais).

Maintenant, recommencez la même opération. Ça ne fonctionne plus ? C’est normal. Nous venons de déclencher une Action Conversationnelle et nous n’avons pas indiqué que la conversation était terminée. Notre Action est toujours en cours et attend la suite de la conversation, c’est pourquoi afin de pouvoir recommencer, il est nécessaire d’indiquer à l’Assistant que nous voulons y mettre fin en lui envoyant par exemple “cancel”.

Ajouter une réponse conversationnelle avec un webhook simple

Maintenant que notre intent de début de conversation est prêt, nous allons ajouter un nouvel intent de réponse conversationnelle avec un webhook simple basé sur une entité reconnue par Dialogflow. Les entités sont des catégories de “choses” que Dialogflow utilise afin d’extraire les valeurs des paramètres passés dans les inputs en langage naturel.

L’idée ici est de créer un nouvel intent, de l’entraîner avec des phrases spécifiques et centrées sur une entité reconnue (ici, les nombres).

Nous allons donc créer un nouvel intent que nous allons appeler “number request” (attention, le nom des intents est case-sensitive) et lui ajouter les phrases d’entraînement suivantes :

Dialogflow reconnaît alors automatiquement l’entité @sys.number qu’il associe à un paramètre number. De plus, à chaque fois que l’on sauvegarde ses modifications, on peut constater qu’un modèle de machine learning est entraîné avec les nouvelles données fournies.

Puis définir le paramètre number comme étant requis pour cet intent et y ajouter une question (“What number do you want to know about?”) :

C’est cette question qui sera affichée à l’utilisateur si la requête ne contient pas ce paramètre requis.

Il nous reste à configurer le webhook.

Pour cela, il faut dans un premier temps cliquer sur Enable webhook for this intent dans la partie Fulfillment de cet intent (à ne pas confondre avec la section Fulfillment).

Puis se rendre dans la section Fulfillment. On voit deux options : Webhook, permettant de lier un webhook uploadé en tant que Cloud Function sur Firebase, et Inline Editor, plus simpliste et qui permet d’entrer directement un peu de code Node.js. Nous allons commencer par utiliser cet Inline Editor dans lequel on va entrer le code suivant :

Voir le lien github

Ici, on importe le module Dialogflow pour les Actions on Google, les fonctions firebase ainsi que le client Dialogflow puis on gère l’intent “number request” (qui prend “number” en entrée) afin d’afficher une réponse simple qui met notamment fin à la conversation.

La dernière étape est de cliquer sur DEPLOY (attention, cela peut prendre quelques minutes).

Enfin, notre première réponse conversationnelle simple est prête, testons-la.

Ajouter une réponse conversationnelle avec un webhook personnalisé

Nous avons réussi à mettre en place une réponse à notre Action. Cependant, celle-ci n’a pas beaucoup d’intérêt et nous sommes rapidement limités par l’interface de l’éditeur de webhook sur Dialogflow. Nous allons donc voir comment déployer nos propres Cloud Functions en Node.js sur Firebase afin de pouvoir tirer le meilleur parti de notre Action, ce qui nous permettra notamment d’accéder aux logs de notre code.

Pour cela, il va nous falloir installer la Firebase Command Line Interface (Firebase CLI) sur un terminal :

npm -g install firebase-tools

Puis s’y authentifier avec son compte Google :

firebase login

Pour vous simplifier les choses, le projet contenant le code de base du webhook précédent, et que l’on va faire évoluer par la suite, est disponible sur Github.

Nous pouvons à présent aller désactiver l’Inline Editor dans la section Fulfillment de Dialogflow puis déployer notre webhook à la main à l’aide de la Firebase CLI. Pour cela, définir le projet utilisé :

firebase use --project

Pour connaître l’ID du projet, il faut se rendre dans les paramètres du projet sur la Actions Console.

Installer ses dépendances après s’être placé dans le dossier functions :

npm install

Puis déployer le projet :

firebase deploy --project

Il est également possible qu’il faille mettre à jour Firebase, npm ou rafraîchir le token d’authentification Firebase.

Maintenant que notre Cloud Function est déployée, on peut constater que l’URL de celle-ci (visible dans la section Develop > Functions de la console Firebase) est déjà renseignée dans le champ URL de la partie Webhook visible dans la section Fulfillment de la console Dialogflow. Il reste simplement à activer ce webhook. Si on se rend sur le simulateur de test, on peut donc toujours tester notre Action comme si rien n’avait changé !

Afin de rendre notre action un peu plus intéressante, nous allons appeler une API dans notre Cloud Function en utilisant le paramètre number passé par l’utilisateur. Pour cela, nous allons mettre à jour notre fichier index.js et remplacer la ligne :

Voir le lien github

par le code suivant :

Voir le lien github

Après avoir déployé notre Cloud Function modifiée, notre Action nous répond une anecdote sur le nombre qu’on lui demande.

Poursuivre la conversation

Pour l’instant, la conversation est lancée et nous avons un échange entre l’utilisateur et l’Assistant. Cependant, la fin de cette conversation est un peu brutale. On voudrait pouvoir la rendre un peu plus vivante en la poursuivant, notamment en définissant une fin identifiable.

Nous allons utiliser les follow-up intents. Ce sont des intents qui vont être liés à nos intents personnalisés au sein de Dialogflow et qui proposent différentes suites telles que “Oui”, “Non”, “Répéter” etc. Nous allons donc proposer à l’utilisateur de demander une nouvelle anecdote après que l’Assistant lui en ait donnée une.

Pour cela, il suffit dans un premier temps de cliquer sur Add follow-up intent sur notre intent number request et d’ajouter :

  • un intent yes auquel on ajoute une réponse “Ok so what other number do you want to know about?”, ainsi, lorsque l’utilisateur répondra avec un input comprenant un mot identifié comme associé à l’entity @sys.number, notre intent number request sera de nouveau déclenché
  • un intent no auquel on ajoute une réponse “Goodbye!” en cochant la case “Set this intent as end of conversation” afin que cette réponse soit affichée avant de terminer la conversation

Dans un second temps, il faut mettre à jour le code de notre Cloud Function afin permettre à l’utilisateur de demander une nouvelle anecdote. Pour cela, ajouter la dépendance aux Suggestions au début du fichier index.js :

Voir le lien github

puis remplacer la réponse mettant fin à la conversation :

Voir le lien github

par l’affichage de cette même réponse suivi d’une question avec une suggestion Oui / Non :

Voir le lien github

Puis déployer de nouveau notre Cloud Function et la tester.

Ajouter une réponse riche

Pour finir notre tour des bases des Actions conversationnelles, nous allons ajouter une réponse riche à notre Action. Les réponses riches permettent d’afficher des éléments afin d’améliorer les interactions avec l’Assistant. On peut par exemple afficher des images, des carousels ou encore des medias comme un lecteur de musique.

Pour cela, nous allons ajouter quelques dépendances d’éléments visuels et remplacer l’affichage de la réponse par celui d’une carte contenant cette même réponse ainsi qu’une image.

On obtient notre code final :

Voir le lien github

Déployer puis tester. Pour voir le résultat de notre modification, il faut tester l’Action sur le simulateur de la partie droite en sélectionnant une surface adaptée (c’est-à-dire une surface avec un affichage comme Smart Display ou phone), ou tout simplement tester sur son smartphone Android.

Maintenant, nous avons une Action Conversationnelle qui couvre les bases d’une conversation en offrant un début de conversation, des échanges avec plusieurs choix de réponses ainsi qu’une fin claire, le tout avec une réponse visuelle !

Conclusion

Là où les App Actions de la partie “Solutions” nous permettait simplement d’étendre la portée de nos applications Android dans l’Assistant, les Actions Conversationnelles nous offrent une palette de possibilités impressionnante avec laquelle on a rapidement envie de “jouer” pendant des heures. On notera d’ailleurs qu’en utilisant Dialogflow, nous n’avons pas eu à toucher à une once de code Android ! On déplorera peut-être simplement le manque de clarté quant à la nécessité des différentes configurations requises sur son compte Google (enregistrements vocaux, historique Chrome…).

Il existe beaucoup d’autres possibilités que nous n’avons pas abordées ici afin de ne pas dépasser le cadre de la découverte du développement d’Actions sur l’Assistant Google. Parmi ces diverses possibilités, nous pouvons citer la gestion des sons, la détection des silences sur les enceintes, la détection d’inputs inattendus, le stockage d’informations ou encore les différentes formes d’invocations (explicites ou implicites).

Nous sommes à présent relativement habitués à lancer nos applications favorites à travers l’Assistant mais rares sont les réelles interactions qui vont au delà du simple lancement de feature. Comme je le disais dans l'introduction de l’article précédent, le développement d’Actions semble toujours un peu mystérieux pour les développeurs Android. C’est pourquoi j’espère que ces articles auront permis de démystifier un peu ce domaine et vous auront donné envie de vous lancer !

Si ce second article vous a plu, je vous invite à aller consulter la documentation officielle des Actions Conversationnelles ainsi que les excellents codelabs qu’on y trouve. Vous pourrez notamment y trouver un exemple assez avancé d’un jeu du pendu mettant en place un affichage visuel poussé.

Goodbye!

'Nicolas Telera' left the conversation