Using the Dialogflow API in Your NodeJS App
Published: 2020-09-14 05:01:44

###Overview
Dialogflow, from Google, is a ‘natural language understanding platform’ that can allow us to easily integrate a ‘conversational interface’ in our application. It is essentially the same thing as training a robot with natural language understanding capabilities to interact with users of our application. This might come in handy if we needed a way to understand one of many possible user intents in order to fulfill the requests appropriately. Imagine we have created an application for a restaurant that takes orders and puts them into a queue. We can use a Dialogflow-type conversational interface to prompt users for input, record responses, re-prompt them if the agent could not parse their request, and finally to submit orders when all the necessary information has been recorded. Perhaps somebody wants to place an order. Maybe somebody is checking on an order to see if it is ready for pickup and so on. 

###Dialogflow Agent Breakdown
We use ‘agents’ to handle conversations with our end-user. Agents can be trained to recognize the conversational ‘intent’ of our user as well as how to respond appropriately. According to the Dialogflow-ES documentation, “An intent categorizes an end-user's intention for one conversation turn”. Finding the intent of your user allows you to understand what it is exactly that they want. The way Dialogflow agents recognize intents is through a combination of matching ‘training phrases’ with the recognition of certain ‘parameters’. We supply both training phrases and parameters to help the agent understand what we need it to understand. Here is an example of training phrases which fall under the ‘default welcome intent’, or the intent to greet,
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/6cpkzb09825b7emmwezh.png)


If one of these phrases is directly matched, a predetermined response is selected and returned to the user. The intent has been recognized, and has been responded to. 
Another way to help your agent determine intent is to provide certain parameters, which are categories for words or phrases, that help it to recognize your intent. Once a category is created, we can enumerate different possible values that fall into this category. If one of the values is recognized, the agent will assume a certain intent is being conveyed and will select an appropriate response. 

Sounds good! Now let’s see how to integrate a Dialogflow agent into a simple node.js application.
First we need the application. For this task I have created a very simple app with an Express for NodeJS back-end, and a ReactJS front-end which renders a text-box and a list of messages. This is the format we will use to communicate with our Dialogflow agent. We are going to send a message which will get passed to the server who will contact the agent, who will parse the request and send back a response. 

Since the app is ready to roll, let’s dive right in to creating our agent.

First off, we go to the Dialogflow ES console. 
We select the menu on the top left and select ‘Create new agent’
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/qnesbkkjt8rned475sbn.png)
Here I just create it with the default settings and name it DemoBot

Excellent! Our bot comes with a default welcome intent! We'll see more about using intents in the next article. When we send our initial request through the API to our agent, we will send 'hello', and it will register our intent as 'default welcome'.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/17qi83o54cnqqtwr01b6.png)
Now lets go to the google developer’s console. If you don't have a google developer's console, it is quite easy to create one. This is the console that you manage all projects from. Creating the Dialogflow agent also creates a project in your console.
In the console, I search for demo, and DemoBot pops up. I select this project. 

Now its time to enable the api. In the dashboard of our project we hit 'Enable APIs and Services
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/k42wk3kzhzk147abnvoc.png)
We can then search for Dialogflow and enable it.
Ok! Easy enough. 

Navigate to the credentials screen, and notice that we have a service account for this project. This one was created automatically. Now click on the email of the service account. We need to get the credentials we will use to call our DemoBot API from our app. 
Scroll down to where the keys are listed. Hit ‘add key’, select ‘create new key’ and select JSON option. This will automatically download a json file to your local machine. Do not lose track of this! It will be our .service.json file. 
Now we go to the NodeJS app, we have all we need here to make contact with our bot! First, we have to add .service.json in the root directory. Copy and paste the JSON file we downloaded from Dialogflow inside here.
Then, we add GOOGLE_APPLICATION_CREDENTIALS to the .env file and point it at the .service.json file we created above.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/6ll42vln01j0bk031x6l.png)

Google automatically knows to look at this file for the credentials when you are making the request. This is all baked in for you.

Then we use this file from https://github.com/googleapis/nodejs-dialogflow 
I put it into a file I called chatbot-helper.js which I then exported and imported in my request handler. This file contains a function called 'runSample' which contains all the proper config to start communicating with your agent. We will have to edit a couple of things here. 
The only thing you have to change here is your actual project id in the parameters of the function. I stored my project id in .env and imported it here. Later on, we will add a parameter called message and pass it in for the value of text.text in the queryInput object.

```javascript
const dialogflow = require('@google-cloud/dialogflow');
const uuid = require('uuid');
require("dotenv").config();

const { PROJECT_ID } = process.env;
/**
 * Send a query to the dialogflow agent, and return the query result.
 * @param {string} projectId The project to be used
 */
async function runSample(projectId = PROJECT_ID) {
  // A unique identifier for the given session
  const sessionId = uuid.v4();

  // Create a new session
  const sessionClient = new dialogflow.SessionsClient();
  const sessionPath = sessionClient.projectAgentSessionPath(projectId, sessionId);

  // The text query request.
  const request = {
    session: sessionPath,
    queryInput: {
      text: {
        // The query to send to the dialogflow agent
        text: 'hello',
        // The language used by the client (en-US)
        languageCode: 'en-US',
      },
    },
  };

  // Send request and log result
  const responses = await sessionClient.detectIntent(request);

  const result = responses[0].queryResult;

  if (result.intent) {
    console.log(`  Intent: ${result.intent.displayName}`);
  } else {
    console.log(`  No intent matched.`);
  }
  return result;
}
module.exports = {
  runSample
}
```
make sure you run
```
npm install @google-cloud/dialogflow
```

The only changes I made here were to put PROJECT_ID in dotenv(your project Id is contained in the .service.json file), to return result so that I actually returned the results from the Agent, and to export the function for use in my route handlers. I left a couple of the console.logs in because they help to illustrate some of the elements we look for. The object which contains all of our useful information is set to the variable 'result'. Let's take a look at what we get when we send a request to our new agent!
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/vxzrla0u7boq8o309lqa.png)


queryText is what we sent, and fulfillmentText is what our agent responded with. We are all set up to start communicating with our chatbot.

The next thing is add the message param in runSample so that we actually send user input to our agent.
```javascript
async function runSample(projectId = PROJECT_ID, message) {
  const sessionId = uuid.v4();
  const sessionClient = new dialogflow.SessionsClient();
  const sessionPath = sessionClient.projectAgentSessionPath(projectId, sessionId);

  const request = {
    session: sessionPath,
    queryInput: {
      text: {
        text: message,
        languageCode: 'en-US',
      },
    },
  };
  const responses = await sessionClient.detectIntent(request);

  const result = responses[0].queryResult;

  return responses[0].queryResult;
}
```

Now when we send a message via the text box, it is received in our request handler, the function runSample is called which hits the dialogflow agent's default welcome intent, and one of the default responses is relayed back to us.

```javascript
chatbot.get('/', (req, res) => {

  runSample(PROJECT_ID, req.query.message)
  .then((data) => {
    res.send(data);

  })
  .catch((err) => console.log(err));
})
```
and here's the result!
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/vfuqw3c1ro0a5yiztm3r.png)

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/8s9am7c1ehqg08k582a8.png)

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/9ejs3j5w9hhpzgiau4x8.png)

###Conclusion
In conclusion it is quite easy to set up a Dialogflow agent and just as simple to start using the agent for conversational purposes via NodeJS.