Developing a Google Assistant app with NodeJs, Dialogflow & Firebase Functions

Ananth Majumdar
Coinmonks
15 min readMay 31, 2018

--

What is Google Assistant?

Google Assistant is a virtual personal assistant developed by google available on variety of devices like mobile phone, smart home device, on a smart watch or on a TV or even the web. It can engage in two way conversations and can work entirely with voice.

What can it do?

With the assistant, you can control smart home devices, do most of the functions on your phone like placing a call, sending a text etc with just your voice, play content and also interact with apps. It also has routines which is a sequence of things which can be done with a single command. So existing content can be packaged into an assistant app or apps can be built without writing any code using templates or by writing custom apps.

How to develop custom apps for Google Assistant?

For more flexibility we can also develop apps using the APIs provided by Google. There are two APIs we can use are Actions SDK and Dialogflow

Using the actions SDK, your app can perform actions. An action defines an entry point into your app’s functionality and maps an intent that describes the action to the fulfillment that processes the intent. The fulfilment gets the user input as string, processes the input and provides a response. This interaction continues back and forth till the action is complete.

Dialogflow is a conversational platform that lets you design and build actions by wrapping the functionality of the Actions SDK and providing additional features such as an easy-to-use IDE, natural language understanding (NLU), machine learning, and more. So it sits above the actions SDK and works with actions SDK.

Developing the App

Here I will show how to create an app called InspireMe using the Dialogflow API. User can talk to this app to get inspirational quotes and passages.

The flow of the app works like this.

User specifies an intent to Google Assistant or explicitly asks for taking with the app → The welcome intent of the app is triggered → Fulfilment is triggered for the intent → Fulfilment picks a quote and returns in the response → That quote is played in the response -> User is given an option to listen another quote or end the conversation → If user selects Yes -> another quote is picked and played -> when user says no -> App wishes user a good day and the flow ends.

Design a conversation

Here is a sample conversation.

Default flow:

User : Hey google tell me some inspiring quotes/motivational quotes/inspirational quotes

OR if the user knows the app already, he can ask by name

User: Hey google, talk to LitInspire

App: Welcome to Lit Inspire. With great quotes and inspiring passages, I will inspire you.

Here is a quote: Real Artists ship — This was said by Steve Jobs asking us to share our work with the world and not hold back.

Do you want to hear another quote?

User: Yes Please

App: here is another one . <Another Quote>. Do you want to hear another one ?

User: Sure

App: Great. Here is another quote. <Another Quote>. Do you want to hear another one.

User: No Thanks.

App: Hope you are inspired to take on your challenges. Have a good day!

The user could cancel at any time by saying cancel.

Create a project and define actions

To create the project you should first setup a project in the actions on google console.

Then choose a category which your app belongs to. It will show a form asking you to the select the default invocation phrase, i.e the name of the app the user can explicitly ask for and save.

Next click on the ‘actions’ menu and you will be prompted to build your first action. When you click on that you will be take to a menu with many built in actions and custom action. Built in actions help you to build apps based on template or you can customize later. Here we will proceed with a custom action. Select ‘custom action’ and click Build.

You will be redirected to the dialogflow console.

Dialogflow console

This is the agent which maps user queries to intents and invokes a specific action.

If you see the conversation above, the user first starts the app by asking for a specific quote or asking for the app by name.

So the initial intent could be start_app which is triggered when either asked by name of if google matches the invocation phrase (tell me an inspiring quote) to our app.

So create an intent with name ‘start_app’ and save

It gives options below to enter

contexts: Context is a way to link the conversation. Let us come back to this later.

events: Events are a way to enter the app without matched text. i.e a way to enter the app by calling by name. Select ‘Welcome’ and ‘Google Assistant Welcome’ which says that when users ask for this app by name, start_app intent is triggered.

actions and parameters: Specifies the action that should be triggered when this intent is specified. Dialogflow can also get ask questions to get all the parameters needed before fulfilling the action. So in this screen you can specify the action and also the parameter names to use later. For e.g if you want to listen a quote in a specific category, you can have that as a parameter. Currently the app just tells a quote in any category, so there is not paremeter in this app. So just specify an action name.

training phrases: Training pharses are phrases which the user can say to match this intent without asking for the app by name. for e.g tell me a motivating quote, tell me an inspiring quote, give me some inspiration, tell me a quote etc. Enter different varieties of training phrases all of the different ways a user can ask for quotes etc.

Responses: This section can be used to provide hardcoded responses. You can enter a few quotes here and they will be used if our service fails. If you want to end the conversation here, you can select, end this conversation slider. In this example we don’t want hardcoded response, so don’t select this.

Fulfillment: This is used if we want to create a fulfillment service which can provide user response instead of hard coding. Here in this example we want to use the fulfillment service. So select ‘Enable webhook call for this intent’. Later when we have the fulfillment service ready we can enter the fulfillment url in the fulfillment section.

This action will play the introduction and also return a quote. After that it asks user either to listen to another quote or quit. So we need two more intents one to handle when the user says ‘yes’ and one when user says ‘no’.

Contexts:Though there is only one question for which the user might answer yes here, the user might say ‘yes’ to different questions in conversation, but our app should know in which context the user said yes to. So when the user says ‘yes’ since the app knows the context the user is in, it will only match the action for that context not all the intents which have yes as a triggering phrase.

So create new intents one for one_more_yes and one for one_more_no.

In the one_more_yes, we want to listen to process the yes only if he says it in the one_more context i.e after he has listened to the first quote and wants to listen more. So in the contexts section, set the input context to one_more and save. Set the training phrases to be variations of the yes response like sure, absolutely, yes,please etc. Also enable webhook call for fulfillment. Set the action to be same as the intent name.

Do the same thing for the one_more_no intent. Set the input context to one_more and set the training phrases to variations of no and enable webhook call for fulfillment. Set the action to be same as the intent name.

Fallback intent: Next there may be times where the user might say something totally unrelated to the app and we should have a way of handling that. Google already provides a ‘Default Fallback Intent’. Open that and set an action name like input.unknown and enable fulfillment so that we can handle it in our service.

This should cover all the intents which are necessary for our app. Next lets build the fulfillment service.

Build fulfillment

The fulfillment service should accept a POST request from Dialogflow with the matched intent details. Your service should handle the request and return a response as per the Dialogflow V2 specification.

We could use any language for creating the service, but Dialogflow provides a NodeJS based fulfillment SDK which will make our job very easier. So we will be using the NodeJS SDK.

Our fulfillment service will be a Google Cloud functions for firebase . Cloud Functions for Firebase lets you automatically run backend code in response to events triggered by Firebase features and HTTPS requests. Your code is stored in Google’s cloud and runs in a managed environment. There’s no need to manage and scale your own servers.

Cloud Functions runs Node v6.14.0, so install node v6.14 or higher version.

https://nodejs.org/en/download/

Once nodejs is installed, set up the firebase cli following the instructions here

The steps are

  1. Install firebase-cli. In many cases, new features and bug fixes are available only with the latest version of the Firebase CLI and thefirebase-functions SDK. So first install the latest versions of firebase-functions and firebase-admin

2. Once the dependencies are installed, do the following to initialize the project

a. Run firebase login to log in via the browser and authenticate the firebase tool.

b. Go to your Firebase project directory.

c. Run firebase init. The tool gives you an option to install dependencies with npm. We will select functions for the function and hosting for any public files. The init tool will guide through various options to choose the language, and the initialization options for functions and hosting

Once the project is initialized, we can develop our functions.

This is the package.json for the dependencies we have. We are using actions-on-google, firebase-admin, firebase-functions and google cloud datastore. We are using es-lint for linting. Code linting is a type of static analysis that is frequently used to find problematic patterns or code that doesn’t adhere to certain style guidelines.

Next let us look at the functions. When user invokes the app by name or google matches the request to any of our intents, then it sends a request to our app with the intent and other parameters. In our function we will implement the callback function for each intent.

Let us look at the intent handler for the start_app. First since we are in the app, we want the user to be able to ask for multiple quotes. Since it is in the one_more context, we will set the context to one_more. Next we need to get a quote and return it. We have the quotes stored in google cloud datastore. So we make a call to the datastore to return a random quote.

The getQuote() function returns a promise with the quote. And in the intent handler, we use the .then() function of the promise to build the message from quote and return it. In the getMessageFromQuote() method, we can see join together multiple responses and return it. Here we use the ask method, which tells the user our quote and waits for the user response. And in this method we can pass suggestions, and atmost two simple responses. The simple response converts the text to speech. We are using the SSML (speech synthesis markup lanuguage) to specify how to generate the speech. With SSML, we can specify where to pause, and add music to the text. There are other types of responses also like Basic Card, Image, Button and List (Carousel) responses.

The two other things to see are how to end the conversation and how to handle unknown input. In the below function you can see that when the user says no, we use the conv.close() function to end the conversation with a message.

When the user provides unknown input, google invokes the default fallback function. Lets look at that. We are giving options to the user two times whether to listen to a quote or not. And if the user doesn’t give a valid response even after two times, we are ending the conversation.

Now that’s it. We have written intent handlers for all possible intents and fallback handler also. Now this is ready for testing.

Use the firebase deploy command to deploy the function to firebase functions.

Once deployed you will get a functions url. Go to the dialogflow console and go to the fulfilment menu item and provide the function url as the fulfilment url.

Enter fulfilment

Test the app

Once you have entered the fulfillment url, you can test either in the dialogflow console on the right side of the console or in google assistant.

To test in google assistant, click on ‘Integrations’ in the dialogflow console and select ‘Google Assistant’. On the next screen select ‘test’.

It will open up a test window like this.

We can test each of your intent here. We can also see the request and response and any errors we might encounter.

For e.g. in this app, when I ask to ‘Talk to LitInspire’ , it will retrieve a quote and display on the simulator. It will also read the quote with appropriate pauses as specified in the SSML. It will also show the suggested replies. We can click on the suggested replies to test the next part of the conversation.

We can also view logs by following the link on the simulator. We can see the request and response and exception stack traces also. In the google cloud platform logs console, you can select the right application (actions on google app or the cloud function) to see the logs at the appropriate level.

Once we have verified the happy paths, the fallback paths and conversations and we are satisfied with the result, we can submit the app for approval.

Submit the app for approval

To prepare the app for approval, we have to provide more details so that the app can be visible in the directory. We can provide a short description, more details and invocation phrases to talk with the app.

We also have to provide images in two different sizes. I used the canva app to create these images. We have to provide a banner image and also a logo

Next we have to create a privacy policy.

Google provides a sample doc which we can copy and edit to create our own privacy policy. You can check my privacy policy here.

Lit Inpsire Privacy Policy.

Next we can select the category the app belongs to and other details helpful for review. We can also select the countries where the app is available and also the devices which can use the app. Then we can submit the app for review.

The app will be reviewed and if there are no issues, the app will be deployed to production. We will get an email informing us of the same. That completes the process of building and deployment.

Summary

In summary we have seen how to design, build and deploy an actions on google app. To summarize the steps, they are

Design a conversation

Create a project and define actions

Build a fulfillment service

Test the actions

Prepare for deployment and submit.

Thanks for staying with me. Hope this was helpful. Feel free to reach out if you have questions. You can comment here or reach out to me via twitter @thisisananth

Join Coinmonks Telegram Channel and Youtube Channel get daily Crypto News

Also, Read

--

--