Monday, April 24, 2017

Make your chatbot translate stuff for you! (how to use Cloud Functions with api.ai)

Hi GCP lovers!

Today I would like to talk about the cool integration you can do between api.ai and Cloud Functions.
All the code presented here is available on GitHub here.


About Api.ai

If you have never heard of api.ai, it is a promising chatbot product that has been acquired by Google recently. You can test it for free, it's code-less and it integrates flawlessly with other communication services like Google Assistant, Slack, Facebook Messenger and also offers a ML (machine learning) features to understand more than the input that you hard-programmed.


About Cloud Functions

Cloud Functions (currently in beta) is one of the serverless environment that GCP offers. Its function is extremely simple: do something when some trigger happens. Cloud Functions is an event-based function. It appears to be extremely handy when it comes to call Google APIs.

Cloud Functions offers 3 types of triggers:
  1. HTTP trigger
  2. Cloud Pub/Sub topic
  3. Cloud Storage bucket (GCS = Google Cloud Storage)
An easy use case is for instance to do some resizing (thumbnail creation) of a picture when it gets uploaded in a GCS bucket. Or even more cool, call Cloud Vision API to analyze the content of a picture when it gets uploaded in GCS.

Cloud Functions only supports Node.js.

Using the webhook feature of api.ai to call Cloud Functions

Today in this article, I will explain that integration by providing you an example: I want my chatbot to be able to translate me some text I will input in French.

To do that, we will need:
  • api.ai account (sign up for free here)
  • GCP account (sign up for free and get 300$ credit here)
    • Cloud Functions (2 million free invocation per month)
    • Cloud Translation API (don't forget to enable this API from the GCP console!)

Create a function

Open the GCP console and head to Cloud Functions and create a new function that will use HTTP trigger. I published the sample code of the function use here on GitHub.

To start with Cloud Functions, you need to define a function that will take "req" (request content) and "res" (response of this function) parameters.

exports.translatetext = function translatetext(req, res) {
 {...}
};

When calling Cloud Functions from api.ai, the "req" parameter will include a JSON request specific to api.ai. It took me some time to figure out that api.ai wasn't sending the JSON request I was expecting.

When in a normal case, you will manage a "message" and "language" parameters the way shown below. For a JSON request body like this one, you will handle the content in the code like below:

  • JSON request body:
    • {"message": "hello", "language": "french"}


  • In the code, you handle that request this way:
    • req.body.message
    • req.body.language
But for api.ai, the JSON request body is different. Here is an example of request body generated by api.ai:


{
  "id": "c9b569ef-fb6e-43ef-b40e-cfeb71ed73fa",
  "timestamp": "2017-04-24T06:28:15.744Z",
  "lang": "en",
  "result": {
    "source": "agent",
    "resolvedQuery": "translate hello in french",
    "action": "cloudFunctionsTranslate",
    "actionIncomplete": false,
    "parameters": {
      "language": "French",
      "message": "hello"
    },
  ...
}

The blue part of this request is the part we are interested in to call the Translation API.
So to handle correctly the JSON request body coming from api.ai, the code should contains:
  • req.body.result.parameters.message
  • req.body.result.parameters.language
For the response part of our function, we need again to return a JSON response format required by api.ai. To see the detail of the JSON response expected by api.ai, take a look at this doc.
This gives this answer:
  • res.json({ "speech": translation, "displayText": translation, "source": "cloud-function-translate" });
Now that our Cloud Functions is defined and triggers by HTTP, let's configure api.ai to create the correct request sent to Cloud Functions.

Configure api.ai

First, we need to enable the webhook for our bot (I won't cover how to create a bot, api.ai provides many documentation to create one).


The previous image contains:
  • URL: the URL to trigger the previously created Cloud Functions
  • HEADERS
    • Key: Content-type
    • Value: application/json
  • DOMAINS: Enable webhook for all domains
Then let's create an intent to answer to a translation request by the end-user.



The "Action" part will define the parameters to send to the webhook. To understand exactly how this intent works, please to the excellent documentation provided by api.ai.

Let's try our bot now

In the api.ai console, you can try your bot on the right side.
I tried "translate hello in french" and got the answer "bonjour", so it worked!!


You can also verify that it recognized the "message" and "language" parameters from our chat with the bot.

I tried from Facebook messenger (here is the integration doc) and it worked well as well.



Hope you find that article interesting or helpful!

2 comments: