De zéro à héros "Actions sur Google": commencer

image

Hackathon Google, et tout ce dont vous avez besoin pour commencer à développer vos applications pour un assistant.


Google a organisé un hackathon dédié à la technologie Actions On Google. C'est une bonne occasion d'acquérir de l'expérience et de réfléchir à la façon de commencer à créer une interface utilisateur de conversation (CUI) pour nos applications. Par conséquent, nous avons réuni une équipe de deux développeurs Android: shipa_o , raenardev et designer camaradeguest, et nous sommes allés participer.


Qu'est-ce que les actions sur Google?


Actions sur Google (AoG) est un moyen d'ajouter votre action à l'assistant.
Vous pouvez le faire en utilisant 4 outils:



Lors du hackathon, nous avons créé une compétence - une application qui étend les capacités d'un assistant, nous allons donc nous arrêter là.


Après l'appel, "Ok Google. Je veux parler avec ${_} », l'assistant ouvre la compétence avec laquelle l'utilisateur mène un dialogue:


image

Comment écrire une compétence?


Vous aurez besoin de deux compétences:
- compréhension de l'interface utilisateur conversationnelle (CUI), la capacité de les concevoir;
- Capacité à travailler avec Natural Language Processing (NLP), par exemple, Dialogflow.


Étape 1: Conception


Pour que votre compétence ait un interlocuteur protéique, il vaut mieux penser à l'avenir maintenant. La demande sera celle qui tiendra compte du contexte d'utilisation. Les interfaces de dialogue seront utilisées lorsqu'il sera possible de parler à haute voix et d'interagir avec des appareils avec la voix plus facilement et plus rapidement qu'avec les mains, les yeux et d'autres parties du corps.


L'interface vocale est série. S'il est possible de montrer la forme entière de la commande sur un graphique et que la personne choisira elle-même ce qu'il faut regarder en premier et ensuite quoi, alors vous ne pourrez poser des questions que l'une après l'autre à voix haute. Pour trouver une application populaire et pratique, trouvez l'intersection entre les besoins de l'utilisateur et la possibilité d'utiliser l'interface vocale (ou l'impossibilité d'utiliser les autres).


La première chose qui me vient à l'esprit est un assistant vocal pour les aveugles, qui aide à résoudre les problèmes quotidiens. Par exemple, passez une commande dans un magasin, appelez un taxi, appelez des proches. Le second est un livre de recettes parlant pour les femmes au foyer avec les mains dans la farine. Troisièmement, les jeux dans lesquels vous devez expliquer quelque chose.


Nous avons décidé de commencer par un simple et avons développé un robot qui conseille les gens sur les bons films. Nous avons battu l'imperfection des synthétiseurs vocaux: notre assistant ne prétend même pas être un homme et met l'accent sur sa personnalité électronique vivante dans tous les sens.


Google a rédigé d'excellentes lignes directrices sur la façon de développer des interfaces interactives. Et nous parlerons de la façon dont nous avons conçu notre premier-né parlant.


1. Invocation


Tout d'abord, vous devez appeler un assistant. L'appel peut être explicite (invocation explicite) et indirect (invocation implicite). Les gens utiliseront un traitement explicite lorsqu'ils connaissent déjà l'application. Indirectement, l'Assistant Google peut recommander une application appropriée dans une situation spécifique. Les options choisies correctement pour l'attrait indirect - comme les bons mots clés dans la publicité contextuelle, ne sont que plus «humaines».


Type d'appel

La description


Exemple
Invocation expliciteAvec le nom de l'assistant


Ok Google, je veux parler au robot Red Passionate Movie.
Appelez-moi un robot de cinéma.
Où est rouge et passionné là-bas?



Invocation implicite

Dans le contexte où vous avez besoin d'un assistant

Ok Google, conseille-moi un film.
Je veux voir une drôle de comédie.
Quel genre de film regarder avec une fille?

Il est important que les appels indirects ne soient pas trop généraux. Comme les mots-clés généraux dans la publicité contextuelle, ils ne vous empêchent que de trouver la bonne application et abaissent la note de l'application lors de l'émission de l'Assistant.


Les appels peuvent contenir un lien profond vers les fonctionnalités individuelles de l'assistant vocal. Par exemple, généralement notre robot-film commence à communiquer avec le fait qu'il propose à une personne de choisir un genre. Mais s'il est appelé sur un appel indirect, "Je veux voir une comédie drôle", il est logique d'entamer un dialogue avec l'offre d'un bon film garanti du genre mentionné.


2. Premier message d'accueil


Le premier message d'accueil est ce que l'application indique à la personne immédiatement après l'appel.
Vous devez d'abord informer l'utilisateur que l'assistant est déjà là:


Salut, une forme de vie protéique. Je suis un robot-cinéaste passionné de Red. Le but de mon existence est de conseiller les films biologiques sur les bons films.

Et puis - suggérez quoi faire ensuite. Notre robot recherche des films par genre, nous proposons donc à quelle demande une personne peut aller plus loin:
Que voulez-vous voir: peut-être de la comédie, de l'action ou de l'horreur?


Les utilisateurs nouveaux et expérimentés peuvent être accueillis de plusieurs façons. Si une personne parle avec votre assistant pour la première fois, vous pouvez parler un peu de vous. Si ce n'est pas le premier - une longue salutation l'ennuiera. Par conséquent, vous pouvez immédiatement passer aux choses sérieuses:


Première fois

À plusieurs reprises


Salut, une forme de vie protéique. Je suis un robot-cinéaste passionné de Red. Le but de mon existence est de conseiller les films biologiques sur les bons films. Que voulez-vous voir: peut-être de la comédie, de l'action ou de l'horreur?
Salutations, mec! Quel genre vous intéresse?

3. Conversation humaine


Apprenez à votre assistant à comprendre la parole naturelle et à poursuivre la conversation. La façon la plus simple de le faire est de communiquer avec des personnes du public cible avant même le début du développement. De plus, il est souhaitable verbalement, et non par écrit, car le discours familier écrit est plus rare qu'oral. Jouez le rôle du robot et demandez à l'interlocuteur d'imaginer qu'il utilise votre future application. Enregistrez toutes les boîtes de dialogue sur l'enregistreur, puis déchiffrez. Cela vous aidera à concevoir un diagramme de conversation typique et à trouver où les branches peuvent apparaître.


Étape 2: Développement


Il existe plusieurs façons de développer votre action pour un assistant:


  • Avec Dialogflow.
  • Avec Actions sur le SDK Google.
  • Le texte peut être traité indépendamment - par exemple, si vous avez votre propre solution pour le traitement du langage naturel (NLP - Natural Language Processing).

Ce qui suit est l'interaction d'un assistant avec votre compétence.
La boîte de dialogue ressemble à ceci:


  1. L'assistant traduit le discours en texte et l'envoie à votre action.


  2. Le texte est traité de l'une des manières ci-dessus. Dans ce diagramme, via Dialogflow.


  3. Dialogflow définit l'intention (l'intention spécifique de l'utilisateur) et reçoit
    à partir de lui des entités (paramètres).


  4. (Facultatif) Dialogflow peut appeler le webhook correspondant, traiter les données sur le backend et obtenir une réponse.


  5. Dialogflow constitue la réponse.


  6. L'assistant exprime la réponse, allume le microphone et écoute ce que l'utilisateur dira.



image

Diagramme d'action de l'assistant


Dialogflow


Nous ne détaillerons pas les bases de Dialogflow - Google a publié de bonnes vidéos de tutoriel.


  1. Intentions - sur la reconnaissance de l'intention, comment Dialogflow comprend exactement ce que l'utilisateur demande ou quelle action il veut effectuer.
  2. Entités - sur la reconnaissance des paramètres à l'intérieur d'une phrase. Par exemple, dans le cas de la recommandation de films, il s'agit d'un genre spécifique.
  3. Dialog Control - sur le mécanisme de contexte (à ce sujet ci-dessous) et la satisfaction: sur la façon de traiter la demande de l'utilisateur lui-même en accédant à votre backend, et comment renvoyer quelque chose de plus intéressant qu'une réponse textuelle.

Nous supposons que vous avez déjà regardé la vidéo et compris la console Dialogflow. Examinons les problèmes qui se sont posés dans chacune des parties du processus de mise en œuvre, et ce qui est intéressant peut être noté.


Rappelez-vous également les règles pour construire un bon dialogue lorsque vous passez à la mise en œuvre - cela affectera le groupe d'intentions, l'ensemble d'entités et leur utilisation dans les réponses, l'utilisation des contextes et tout le reste.


Intentions


Il y a des recommandations - pour faire un message d'accueil plus détaillé pour le nouvel utilisateur, et pour le reste pour le rendre plus concis. Comment mettre cela en œuvre?


Dans la console Dialogflow, cette logique ne peut pas être déterminée. Cela peut être fait dans l'accomplissement d'une intention bienvenue. En d'autres termes, vous devrez le faire avec vos mains.


Cela s'applique également à la gestion des erreurs. Par exemple, pour la première fois, vous pouvez simplement demander à nouveau, et la deuxième fois, vous pouvez dire quel type de réponse vous attendez de l'utilisateur.


Vous ne le ferez pas par le biais des réponses - une réponse aléatoire sera sélectionnée. Vous pouvez le faire par l'accomplissement ou un peu plus compliqué en le liant au contexte (plus de détails ci-dessous).


Entités


"Autoriser l'expansion automatisée" et sys.Any


Si la phrase est de structure similaire, lorsque "Autoriser l'expansion automatisée" est activé en tant qu'entité reconnue, quelque chose peut y entrer qui ne peut toujours pas être traité avec profit.


Par exemple, votre application reconnaît la phrase "Suggérez-moi quelque chose de <genre>" pour obtenir des conseils sur les films. Si vous dites «Conseillez-moi quelque chose de la nourriture», alors en tant que paramètre «genre», vous n'obtiendrez pas ce que vous attendez. Cela a du sens si l'ensemble des genres vous est constamment mis à jour dynamiquement sur le backend, et que la réponse de l'utilisateur y est traitée, mais vous n'avez pas le temps de mettre à jour l'entité.


Une autre solution consiste à utiliser sys.Any. Dans ce cas, il transmettra tout ce qui était après la conception attendue, ce qui peut être l'ensemble de la proposition. Cela donne plus d'opportunités que l'expansion automatisée, mais il y a aussi plus d'inconvénients.


Singulier et pluriel, cas, sexe


Voyons un exemple simple. Nous parlerons de vos fruits préférés et l'application répondra à quel point ils sont cool. Dans les exemples ci-dessous, P est l'utilisateur, A est notre action.


P: Les ananas sont les plus savoureux.
R: Oui, les ananas sont les fruits les plus cool!

Dans cet exemple, nous avons l'entité: Ananas
Mais que se passe-t-il si l'utilisateur dit "Ananas"? Nous pouvons ajouter un synonyme.


P: J'ai aimé l'ananas.
R: Oui, les ananas sont les fruits les plus cool!

La valeur par défaut est le formulaire de référence - c'est-à-dire c'est la forme originale, pas ses synonymes. C'est pourquoi l'application ne dit pas "Oui, l'ananas est le fruit le plus cool!"


Il convient également d'en tenir compte lors de la rédaction des réponses. Si nous avions la réponse «Oui, $ fruit est le plus cool!», Alors nous obtiendrions ce qui suit:


P: J'ai aimé l'ananas.
R: Oui, les ananas sont les plus cool!

Et n'oubliez pas les cas:


P: Je veux du drame
R: Voici un drame cool ...

Par conséquent, vous devez écrire à la fois les valeurs initiales de l'entité et les réponses sous une forme cohérente. Par exemple, nous pouvons faire toutes les formes d'entité originales pour les fruits au pluriel et les synonymes dans n'importe quel.


Nous ferons des genres en russe dans le cas nominatif, mais en nombre (drames, horreurs).


Quand nous arriverons aux réponses, nous n'écrirons pas "Oui, $ fruit est le fruit le plus cool!" et "Oui, $ fruit est le plus cool!" - les fruits sont toujours au pluriel.


Dans le cas de la langue russe, il vaut la peine d'aller encore plus loin et de réfléchir à la manière de rédiger une réponse convenue - nous avons non seulement des cas (drame / drame), mais aussi le genre (drame / western).


P: Je veux un western
R: Voici un western cool ...

P: Je veux un western
A: Western? Ok, voici un film sympa ...

Mais comment retourner exactement le formulaire d'entité que l'utilisateur a dit?


Dans le cas des genres, le synonyme de «science-fiction» pourrait être «extraterrestres». Ensuite, si l'utilisateur disait «extraterrestres», la «science-fiction» reviendrait comme paramètre.
Si nous voulons obtenir l'entité sous la forme dans laquelle l'utilisateur l'a dit, alors il vaut la peine de choisir la valeur de $ entity.original


image

Mais alors il peut y avoir des problèmes avec l'incohérence du nombre et (surtout) l'incohérence des cas. Est-ce vraiment nécessaire? Si tel est le cas, créez une entité pour le singulier, le pluriel et la casse. Les réponses doivent également être cohérentes avec le formulaire d'entité qu'elles utilisent.


Contextes


Peut-être avec cela le plus de problèmes.


Contexte d'entrée


C'est le contexte auquel une intention particulière est liée. Plusieurs intentions peuvent répondre à la même phrase, et celle avec le contexte d'entrée actif fonctionnera très probablement.
Ainsi, par exemple, vous pouvez joindre une réponse oui / non à une question spécifique, ce qui se fait en utilisant l'intention de suivi dans Dialogflow


Contexte de sortie


C'est le contexte qui est activé lorsque l'intention est déclenchée. C'est ainsi que les contextes sont activés dans la console Dialogflow (cela peut également être fait en cours d'exécution). Nous indiquons le nombre de tours du dialogue pendant lequel il sera actif, et après la remise à zéro du compteur ou après 20 minutes il est désactivé. Cela signifie que les données dans ce contexte ne seront plus disponibles et les intentions pour lesquelles elles sont entrées ne fonctionneront pas.


Une autre astuce est liée au même: vous pouvez activer un contexte avec une intention et le désactiver manuellement avec une autre, en le plaçant simplement comme contexte de sortie pour la deuxième intention avec le nombre de réponses 0.


Si vous ne voulez pas écrire de code en exécution, vous pouvez ainsi implémenter une logique intéressante, par exemple, en utilisant le contexte comme compteur, implémenter la gestion des erreurs lorsque l'assistant ne comprend pas l'utilisateur.


Conseils de dialogue


  • Il n'est pas nécessaire de redémarrer la page avec l'aperçu de l'assistant - lorsque vous avez apporté des modifications à l'agent dialogflow, vous pouvez attendre la fin de sa formation et répéter immédiatement la phrase non reconnue dans le simulateur. Dialogflow peut être considéré comme un backend auquel se réfère un assistant.


  • Utilisez des agents prédéfinis - vous pouvez voir ici comment implémenter un scénario typique.


  • Soyez prudent avec la section Small talk. Son utilisation ne désactive pas le microphone à la fin de la conversation, et ces réponses ne contiennent généralement pas d'appel à l'action. Vous ne dirigez pas l'utilisateur vers le prochain cycle de dialogue, et il ne sait pas tout à fait ce qu'il convient de dire plus loin. Avec une forte probabilité, à cause de cela, vous ne pouvez pas passer l'examen. Il est préférable de créer des intentions distinctes pour cela si vous pouvez les saisir dans la boîte de dialogue.


  • Ne modifiez pas la même intention en même temps. Maintenant, le travail simultané de plusieurs personnes n'est pas pris en charge - on ne sait pas dont les modifications seront écrasées.


  • S'il est nécessaire de paralléliser le travail avec intention, il peut être effectué dans des projets séparés, puis il suffit de sélectionner ceux qui sont nécessaires et de les transférer. Importez et exportez également des entités dans json / xml et importez / exportez à dessein.


  • Immédiatement, il convient de considérer que vous écrivez une action pour une langue particulière. Écrire des réponses en russe a des nuances supplémentaires. La localisation de l'action semble donc plus difficile qu'avec l'interface graphique de l'application mobile.


  • Tenez compte des règles de conception des interfaces vocales - elles affectent non seulement l'ensemble des répliques, mais également la structure dans son ensemble. Vous construisez un dialogue, donc chaque réponse doit laisser un appel à l'action pour que l'utilisateur comprenne quoi dire.


  • Une fois que tout est prêt et que vous commencez à tester, n'ayez pas peur d'abandonner des branches individuelles du dialogue ou des formulaires de questions. Peut-être qu'au stade des tests, vous comprendrez comment connecter les intentions et ce qui manque pour en faciliter l'utilisation.



Connexion au serveur


Pour connecter le serveur, vous devez utiliser l'accomplissement. Il y a deux options pour cela:


  • Client Webhook . Plusieurs langues prises en charge.
  • Éditeur en ligne sur les fonctions cloud pour Firebase (node.js).

Prenons le plus simple: l'éditeur en ligne.


Nous ne prétendons pas être un expert en node.js; corriger les erreurs dans les commentaires est le bienvenu.


Il est important de faire attention à la version de l'API Dialogflow.
Dernière version v2. Tout ce qui est écrit pour la version v1 ne fonctionne pas avec.
En savoir plus sur la migration ici .


Liens utiles:



Analyser le modèle standard


Lorsque vous ouvrez la section Exécution, le code suivant s'affiche dans le fichier / onglet `index.js`:
 'use strict'; const functions = require('firebase-functions'); const {WebhookClient} = require('dialogflow-fulfillment'); const {Card, Suggestion} = require('dialogflow-fulfillment'); process.env.DEBUG = 'dialogflow:debug'; // enables lib debugging statements exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => { const agent = new WebhookClient({ request, response }); console.log('Dialogflow Request headers: ' + JSON.stringify(request.headers)); console.log('Dialogflow Request body: ' + JSON.stringify(request.body)); function welcome(agent) { agent.add(`Welcome to my agent!`); } function fallback(agent) { agent.add(`I didn't understand`); agent.add(`I'm sorry, can you try again?`); } // // Uncomment and edit to make your own intent handler // // uncomment `intentMap.set('your intent name here', yourFunctionHandler);` // // below to get this function to be run when a Dialogflow intent is matched // function yourFunctionHandler(agent) { // agent.add(`This message is from Dialogflow's Cloud Functions for Firebase editor!`); // agent.add(new Card({ // title: `Title: this is a card title`, // imageUrl: 'https://developers.google.com/actions/images/badges/XPM_BADGING_GoogleAssistant_VER.png', // text: `This is the body text of a card. You can even use line\n breaks and emoji! `, // buttonText: 'This is a button', // buttonUrl: 'https://assistant.google.com/' // }) // ); // agent.add(new Suggestion(`Quick Reply`)); // agent.add(new Suggestion(`Suggestion`)); // agent.setContext({ name: 'weather', lifespan: 2, parameters: { city: 'Rome' }}); // } // // Uncomment and edit to make your own Google Assistant intent handler // // uncomment `intentMap.set('your intent name here', googleAssistantHandler);` // // below to get this function to be run when a Dialogflow intent is matched // function googleAssistantHandler(agent) { // let conv = agent.conv(); // Get Actions on Google library conv instance // conv.ask('Hello from the Actions on Google client library!') // Use Actions on Google library // agent.add(conv); // Add Actions on Google library responses to your agent's response // } // // See https://github.com/dialogflow/dialogflow-fulfillment-nodejs/tree/master/samples/actions-on-google // // for a complete Dialogflow fulfillment library Actions on Google client library v2 integration sample // Run the proper function handler based on the matched Dialogflow intent name let intentMap = new Map(); intentMap.set('Default Welcome Intent', welcome); intentMap.set('Default Fallback Intent', fallback); // intentMap.set('your intent name here', yourFunctionHandler); // intentMap.set('your intent name here', googleAssistantHandler); agent.handleRequest(intentMap); }); 

Et ces dépendances dans le fichier / onglet `package.json`:
 { "name": "dialogflowFirebaseFulfillment", "description": "This is the default fulfillment for a Dialogflow agents using Cloud Functions for Firebase", "version": "0.0.1", "private": true, "license": "Apache Version 2.0", "author": "Google Inc.", "engines": { "node": "~6.0" }, "scripts": { "start": "firebase serve --only functions:dialogflowFirebaseFulfillment", "deploy": "firebase deploy --only functions:dialogflowFirebaseFulfillment" }, "dependencies": { "actions-on-google": "2.0.0-alpha.4", "firebase-admin": "^4.2.1", "firebase-functions": "^0.5.7", "dialogflow": "^0.1.0", "dialogflow-fulfillment": "0.3.0-beta.3" } } 

Tout d'abord, mettez à jour les dépendances alpha et bêta vers les dernières stables.


Voici les dernières versions en ce moment.
 { "dependencies": { "actions-on-google": "^2.2.0", "firebase-admin": "^5.2.1", "firebase-functions": "^0.6.2", "dialogflow": "^0.6.0", "dialogflow-fulfillment": "^0.5.0" } } 

Et maintenant, regardons de plus près le code.


Ci-dessus se fait l'importation des dépendances
 // Cloud Functions  Firebase library const functions = require('firebase-functions'); //       const {WebhookClient} = require('dialogflow-fulfillment'); //       const {Card, Suggestion} = require('dialogflow-fulfillment'); 

Tout le point de réalisation est de remplacer le rappel-un `dialogflowFirebaseFulfillment`
 exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => { console.log('Dialogflow Request headers: ' + JSON.stringify(request.headers)); console.log('Dialogflow Request body: ' + JSON.stringify(request.body)); //   . const agent = new WebhookClient({ request, response }); //   let result = request.body.queryResult; //  action  entities https://dialogflow.com/docs/actions-and-parameters let action = result.action; let parameters = result.parameters; //    https://dialogflow.com/docs/contexts let outputContexts = result.outputContexts; //       let intentRequest = request.body.originalDetectIntentRequest; }); 

Ce rappel sera appelé pour les intentions pour lesquelles vous activez le fullfilment.


Redéfinissez maintenant la réponse à l'intention
 exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => { const agent = new WebhookClient({ request, response }); function welcome(agent) { //   agent.add(`Welcome to my agent!`); } function fallback(agent) { agent.add(`I didn't understand`); agent.add(`I'm sorry, can you try again?`); } //   ,  : // key -   intent-. // value -   ,   . let intentMap = new Map(); intentMap.set('Default Welcome Intent', welcome); intentMap.set('Default Fallback Intent', fallback); agent.handleRequest(intentMap); }); 

Dans le même temps, le code remplace complètement la réponse d'intention de la section Réponses.
Les réponses ne seront appelées qu'en cas d'échec du rappel, vous pouvez donc y traiter les erreurs.


Nous supprimons les fonctions de traitement intentionnel du rappel.
Les fonctions d'accueil et de secours sont dans la fermeture .


Pour les supprimer du rappel, vous devrez ajouter le transfert du contexte de la fonction et des paramètres via `bind`
 exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => { const agent = new WebhookClient({ request, response }); let intentMap = new Map(); //  set  Map.      intentMap .set('Default Welcome Intent', welcome.bind(this, agent)) .set('Default Fallback Intent', fallback.bind(this, agent)); agent.handleRequest(intentMap); }); function welcome(agent) { agent.add(`Welcome to my agent!`); } function fallback(agent) { //   2   add    agent.add([ `I didn't understand`, `I'm sorry, can you try again?` ]); } 

Donc, vous êtes maintenant prêt à écrire votre première compétence pour Google Assistant. Il y a une base, mais passons au hardcore dans la partie suivante.

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


All Articles