Sint Kaas: Een conversationele Google Assistant Action in 30 minuten

-

Het is november, op mijn route richting werk zie ik de eerste Kerstbomen al in de huiskamers staan en het winkelcentrum bij mij in de buurt is al versierd met lichten en Kerstkransen. Het kan niet anders, Sinterklaas is in het land. Voor mij is de tijd van de schoen zetten voorbij, ik vier Sinterklaas de laatste jaren door (te veel) chocolade kruidnoten te eten. Dit jaar wil ik het Sinterklaasfeest niet alleen vieren door een paar kilo aan te komen, maar wil ik de Sint ook een beetje helpen met zijn zware werk.

Ik ga voor de Sint een Google Assistant Action maken die door kinderen gebruikt kan worden om naar cadeaus voor in de schoen te vragen via Google Assistant. Aangezien Sinterklaas al in het land is heb ik niet veel tijd om deze Action te maken, daarom wil ik snel een Proof of Concept voor de Sint ontwikkelen. Als hij onder de indruk is zal er volgend jaar wellicht een volwaardige Google Assistant Action beschikbaar zijn. In deze blog zal ik een aantal onderdelen uitlichten waarmee binnen 30 minuten een simpele conversationele Google Assistant Action opgezet kan worden. Een gebruiker kan de Action aanroepen via Google Assistant om een gesprek te beginnen. Vervolgens kan de gebruiker bepaalde commando’s uitspreken waar de Action op zal reageren. Om te beginnen met het bouwen van de Action moet een Google Action project aangemaakt worden.

Google Action

Met een Google Action wordt, in het geval van een conversationele Action, een dialoog begonnen. De gebruiker kan hiervoor het commando “praat met <Naam Action>” in Google Assistant gebruiken. Voor het aanmaken van de Action kan de Google Assistant pagina bezocht worden, hier is een knop te vinden waarmee de Actions console geopend wordt. Binnen de Actions Console kan een nieuw project aangemaakt worden, hiervoor moet de taal en de regio van de Action ingesteld worden.

Aanmaken van een nieuw project in de Actions Console. Vervolgens kan een categorie gekozen worden, maar dat is niet verplicht. Ik heb voor de “Conversational” optie gekozen.

De verschillende categorieën voor een Google Action. Voor een conversationele Action hoeft niet veel ingesteld te worden binnen de Action Console. Er is een “Quick Setup” beschikbaar waar ingesteld moet worden hoe de Action aangeroepen wordt, dit kan bij de optie “Decide how your Action is invoked”. Hier moet de naam die in het “Praat met <Naam Action>” commando gebruikt wordt ingesteld worden en gekozen worden voor de stem die Google Assistant gebruikt.

Instellen van de naam en stem, ook te vinden onder het Develop tabblad bij Invocation. Ik heb 30 minuten om de Action te maken, hierdoor heb ik geen tijd om een grote hoeveelheid aan cadeaus te ondersteunen. Voor de Proof of Concept zal ik daarom beginnen met iets dat ieder kind wil hebben, kaas. Ik had mijn Action graag “Sinterkaas” genoemd, maar Google Assistant doet aan autocorrectie en zal die naam opvangen als “Sinterklaas”. Bij het kiezen van de naam voor een Action moet dus rekening mee gehouden worden met de uitspraak. Ik heb uiteindelijk gekozen om mijn Action aan te roepen met de naam “Sint Kaas”. Momenteel zijn voor de Nederlandse versie van Google Assistant vier stemmen beschikbaar, maar helaas klinkt geen van deze stemmen als Sinterklaas. Ik heb uiteindelijk maar voor “Male 2” gekozen”. Nu moet een actie toegevoegd worden, anders gebeurt er weinig na het aanroepen van de Action in Google Assistant. In de Actions Console kan op de “Add action(s)” link geklikt worden, gevolgd door de “Add your first action” knop. Kies daarna voor de “Custom Intent” optie, dit zal Dialogflow openen.

Toevoegen van een actie, ook te vinden onder het Develop tabblad bij Actions.

Dialogflow

Met Dialogflow kunnen conversationele interfaces gebouwd worden. Het mooie aan Dialogflow is dat programmeerkennis niet vereist is, een groot deel van het gesprek kan op de website in elkaar gezet worden. Ik zal de minimale onderdelen voor het bouwen van een gesprek uitlichten, maar eerst moet begonnen worden met het aanmaken van een Dialogflow project. Na het kiezen van de “Custom Intent” optie moet ingelogd worden met een Google Account. Vervolgens zal automatisch een pagina geopend worden waar een nieuwe “Agent”, oftewel een project, aangemaakt kan worden. Hier hoeft alleen maar een naam voor het project en een taal gekozen worden.

Aanmaken van een Agent in Dialogflow.

Intents

Na het aanmaken van het project wordt de “Intents” pagina geopend. Een intent is een actie die door een gebruiker aangeroepen kan worden, meestal door middel van een spraakcommando. Op de Intents pagina zullen twee standaard intents staan, een hiervan is de “Default Welcome Intent”.

De “Default Welcome Intent”. Notitie: Amerigo is met pensioen, Ozosnel is het nieuwe paard van Sinterklaas. Wanneer het “Welcome” event binnenkomt, wat in dit geval het aanroepen van de Action in Google Assistant is, zal Google Assistant reageren met een van de ingestelde teksten onder “Responses”. De zinnen die standaard ingevuld zijn bij Responses heb ik natuurlijk aangepast. Een intent kan ook aangeroepen worden door middel van een spraakcommando. Ik heb een nieuwe intent met de naam “Cadeau” aangemaakt die er als volgt uitziet:

De “Cadeau” intent. Bij deze intent zijn “Training phrases” ingevuld, dit zijn zinnen die door een gebruiker uitgesproken kunnen worden om de intent aan te roepen. Dialogflow zal na het opslaan van de intent de training phrases gebruiken om een machine learning model te trainen. Dit model zorgt ervoor dat de intent ook aangeroepen kan worden met zinnen die lijken op de training phrases. In dit geval roept de zin “Kan ik een cadeautje krijgen” de Cadeau intent aan, maar de zin “Kan ik een presentje krijgen” ook. Deze intent geeft een willekeurig antwoord uit de lijst van Responses terug, maar het is ook mogelijk om met iets anders dan tekst te antwoorden. Zo kan bijvoorbeeld een afbeelding naar de gebruiker gestuurd worden of een link naar een video. Om een intent te testen kan aan de rechterkant van de pagina een zin ingevuld worden, vervolgens zal het antwoord van de aangesproken intent weergegeven worden. Het is ook mogelijk om het aanroepen van intents te testen in de Google Assistant Simulator, hiervoor kan op de “See how it works in Google Assistant” link geklikt worden. Intents kunnen ook getest worden op een fysiek apparaat dat Google Assistant ondersteunt en gekoppeld is aan het Google Account waarop de Google Action is aangemaakt. Hiervoor moet het “praat met <Naam Action>” commando in Google Assistant uitgesproken worden.

Testen van een intent in het zijmenu en via de Google Assistant Simulator Met training phrases en responses is al veel mogelijk, maar ik wil dat kinderen met de Sint Kaas Action naar hun favoriete kaassoort kunnen vragen. De gebruiker moet dus in staat zijn om een specifieke kaassoort in te spreken, hiervoor ga ik “Entities” gebruiken.

Entities

Entities zijn een soort variabelen, ze hebben een naam en bestaan uit een lijst van mogelijke waarden. Entities kunnen gebruikt worden in de responses van intents of samen met de intent meegestuurd worden naar een webhook, maar daar kom ik nog op terug. Voor de Sint Kaas Action heb ik een entity genaamd “Kazen” aangemaakt die een lijst van verschillende kaassoorten bevat:

De Kazen entity. De Entity bevat een lijst van negen verschillende kaassoorten, voor sommige van deze kazen heb ik een synoniem ingevuld. Wanneer de term “oude”, “bejaarde” of “overjarig” gebruikt wordt zal Dialogflow de waarde “Oude Kaas” gebruiken. Er zijn ook opties voor het gebruik van regular expressions en “Fuzzy matching”, waarbij Dialogflow een bepaalde waarde kiest als die ongeveer overeenkomt met wat de gebruiker zegt. Een andere interessante optie is het automatisch uitbreiden van de lijst met waarden, als een gebruiker bijvoorbeeld de term “Schapenkaas” gebruikt zal het opgepikt worden als een mogelijke waarde voor de Kazen entity. Na het aanmaken van een entity kan deze gebruikt worden in een intent. Ik heb een nieuwe intent met de naam “Kaas Verzoek” aangemaakt die gebruik maakt van de Kazen entity:

De “Kaas Verzoek” intent. Bij de training phrases heb ik weer een aantal zinnen ingevuld, maar deze keer geef ik aan dat er entities in de zin zitten. Dit kan gedaan worden door een stuk tekst te selecteren en vervolgens een entity aan te klikken. De entity wordt vervolgens automatisch onder de kop “Action and parameters” toegevoegd. In mijn geval wordt de waarde van de Kazen entity opgeslagen in de “$Kazen” variabele, deze variabele heb ik verplicht gemaakt. Wanneer de gebruiker geen of een onbekende kaassoort noemt bij het aanroepen van de intent vraagt Sinterklaas om verduidelijking, anders weet hij niet welke kaas zijn Pieten in de schoen moeten stoppen. De variabele kan vervolgens gebruikt worden in de Responses.

Responses van de “Kaas Verzoek” intent. Dit is een simpele toepassing van entities, maar zoals ik eerder al heb aangegeven is het ook mogelijk om de intent en entities naar een webhook te sturen, dit kan door middel van “Fulfillment”.

Fulfillment

Wanneer bij een intent aangegeven wordt dat fulfillment gebruikt moet worden zal na het aanroepen van de intent een webhook aangesproken worden. Hier worden de naam van de intent en eventuele waarden van de entities naartoe gestuurd. De webhook kan vervolgens van alles doen, denk hierbij aan het aanroepen van een API die het weer teruggeeft voor een bepaalde stad. Vergeleken met vooraf ingestelde responses is dit een stuk dynamischer, maar enige programmeerkennis is hier wel vereist. Om van fulfillment gebruik te maken moeten een aantal zaken ingesteld worden, dit kan op de fulfillment pagina.

Fulfillment pagina met de instellingen. Er zijn twee manieren om fulfillment in te stellen. Er kan een URL van een webhook ingesteld worden met eventueel authenticatie gegevens en / of headers. Het is ook mogelijk om gebruik te maken van een inline editor, hier kan met JavaScript een Cloud Function aangemaakt worden die automatisch op Firebase gezet wordt. Bij de eerste optie kan alles wat via een URL te bereiken is en voldoet aan Dialogflow’s webhook vereisten gebruikt worden. Serverless functions, zoals AWS Lambda of Firebase Cloud Functions, worden vaak gebruikt voor fulfilment. Ik heb gekozen voor een Cloud Function op Firebase, maar die ga ik zelf in een IDE schrijven en dus niet met de inline editor. Aangezien het platform een vrije keuze is zal ik niet gaan behandelen hoe een Firebase project opgezet moet worden. De code die ik met TypeScript ga schrijven zal bij ieder Cloud / Serverless Function platform er ongeveer hetzelfde uitzien. Ik heb een simpele Cloud Function geschreven die de “Kaas Verzoek” intent opvangt en reageert met een tekst die de gekozen kaassoort bevat. De code van de Cloud Function ziet er als volgt uit:

 

import * as functions from 'firebase-functions';
import { dialogflow } from 'actions-on-google';

const app = dialogflow({ debug: true });

app.intent('Kaas Verzoek', async (conv, params) => {
    conv.ask(`Mijn Pieten zullen de ${params.Kazen} persoonlijk in je schoen doen!`);
});

export const fulfillment = functions.region('europe-west1').https.onRequest(app);

Er wordt gebruik gemaakt van twee libraries. De “firebase-functions” library wordt standaard gebruikt bij Firebase Cloud Functions. De “actions-on-google” library bevat verschillende onderdelen die gebruikt kunnen worden in het dialoog met de gebruiker. Ik maak vervolgens een “app” variabele aan die een Dialogflow object bevat. Met “app.intent” wordt de “Kaas Verzoek” intent afgehandeld. Met de “conv” parameter kan gereageerd worden op de gebruiker. De “params” parameter bevat de waarden van de entities die meegestuurd zijn, in dit geval is er alleen een waarde voor de ‘Kazen’ entity. Door middel van “conv.ask” wordt een reactie naar de gebruiker gestuurd, in dit geval is dat tekst, maar de “actions-on-google” library bevat ook onderdelen waarmee bijvoorbeeld een afbeelding of lijst verstuurd kan worden. De laatste regel zorgt ervoor dat het Dialogflow object in de app variabele publiekelijk beschikbaar wordt via de webhook. Deze regel code hangt dus af van het gekozen Cloud Platform. Als bijvoorbeeld een AWS Lambda geschreven wordt kan de laatste regel er als volgt uitzien: exports.fulfillment = app; Nadat ik de Cloud Function online heb gezet en de URL heb ingevuld op de Fulfillment pagina hoef ik alleen nog maar de “Enable webhook call for this intent” optie in de “Kaas Verzoek” intent aan te zetten.

Aanzetten van de webhook in de “Kaas Verzoek” intent. Ik heb nu eigenlijk het Responses onderdeel van Dialogflow nagemaakt. Een Serverless function die gebruikt wordt voor fulfillment kan natuurlijk veel uitgebreider zijn, maar dan lukt het waarschijnlijk niet om een Action binnen 30 minuten te maken. Ik heb uiteindelijk de Cloud Function nog uitgebreid en ervoor gezorgd dat een rijm over de gekozen kaassoort teruggegeven wordt.

Tot slot

30 minuten en een halve zak chocolade kruidnoten later heb ik een vrij simpele conversationele Google Assistant Action ontwikkeld. Met Dialogflow is nog veel meer mogelijk, zoals een intent laten opvolgen door een andere intent, maar met de basisonderdelen die in deze blog besproken zijn kan een heel eind gekomen worden. Een bestand dat in Dialogflow geïmporteerd kan worden om het Sint Kaas project na te maken en de code van de Firebase Cloud Function zijn te vinden op GitHub: https://github.com/SamVanGeijn/Sinterkaas