Chapter 4. A Conversational Bot

In the last chapter we implemented a virtual shopping assistant bot to interact with the users’ offers. Athough the structured messages make the conversation easier by allowing users to quickly make selections instead of typing a message, it doesn’t make our bot conversational.

In our example, users only have to select two options, gender and size, to see matching t-shirts, but what if we have more options. Instead of exchanging multiple messages to make a selection, what if a user can simply type “I am looking for large size t-shirts for men,” and our bot responds with matching t-shirts. Or, what if a user types, “I’m looking for a men’s t-shirt,” and then we can guide them to select a size. Instead of having a predefined workflow, a conversational interface can allow us to change our interaction based on a user’s message. This not only provides a better user experience to our customers, but also makes the interaction more human like.

In this chapter, we will learn how to make our bot smarted and conversational. We will learn about wit.ai, which offers a natural language processing API to convert text and voice into actionable data, and also update our bot engine to use wit.ai to process a user’s text messages.

Wit AI

Natural Language Processing uses software to analyze, understand, and synthesize language that humans use. It allows human machine interaction using natural language by enabling machines to derive meaning for the natural language. Natural language processors are used for many things like translation, sentimental analysis, automated summarization of books/text, and information extraction.

There are many libraries and tools availale for natural language processing, and wit.ai is one of them. Wit.AI is an AI start-up that aims to help developers with NLP tasks through the API. Facebook acquired it in January 2015. At the F8 conference in April 2016, Facebook introduced the major update to their platform and deployed their own version of the Bot Engine.

Wit.ai offers a SaaS platform that allows developers to create conversational interfaces using natural language processing. Wit.ai works with either text or speech inputs, helps developers manage conversational intent, and allows custom business logic to be implemented using JavaScript.

The platform is free for commercial and noncommercial use and encourages the creation of open applications in 39 different languages. Wit.ai can help you parse a message into structured data (Understand) or predict the next action your bot should perform (Converse). While at first glance it may look easier to just use scripts, AIML, or slot-based workflow templates to build bots, we believe that these approaches soon lead to bottlenecks.

A cool feature in Wit.ai is that you can test and talk to your bot without leaving the Wit Console. Press ~ or click on the launcher at the bottom-right corner of the screen to start a conversation with your bot.

Key concepts

Stories in Wit are conversations’ instances. Bot Engines trains with these stories. Your bot must have conversations paths to start with. When you create a bot, you can train it with your most frequent stories.

At this level, Bot Engines create a machine-learning model that intentionally over-learn the stories dataset (Overfitting). The more you train your bot the more conversations are built and the machine learning will acquire stories, which lead to a better model.

Unlike rules, which are imperative approaches, stories are independent. If you have a new use case, you can add the story matching it without taking into consideration the predecessors.

Create your first story: Say "Hi, I am looking for large size men’s t-shirts"

  1. Click Create a Story.
  2. Type "Hi, I am looking for large size men’s t-shirts" in the User says field and press Enter.
  3. In the Add a new entity field, type “intent”, then Enter, and Enter again.
  4. Click on the Value dropdown and type “shop”, then Enter.
  5. Click again on Add a new entity, then type “product” and hit Enter, then highlight “t-shirt” in the sentence.
  6. Click again on Add a new entity, then type "size" and hit Enter, then highlight “large” in the sentence.
  7. Click again on Add a new entity, then type "user" and hit Enter, then highlight “men” in the sentence.
  8. Click Bot sends and type “Here are your results for : {product} for {user} size : {size}.”
  9. Save your story.

In this story, we have taught several things:

• Steps 2 to 5: the natural language sentence “Hi, I am looking for large size men’s t-shirts” should be understood as an intent “shop”, product: “t-shirt”, size “large” and user “men”. Product, size and user are intents too, but they don’t follow the same strategy as “shop”. Strategies are explained in a forthcoming section. • Step 6: when an intent “shop” is detected, the bot send a message back to the user with the confirmation of what the user just asked for.

Note that the more expressions you validate for each value, the better it will work.

  • Actions

Actions serve to modify the context of a conversation when you need to predict the next action. They also help Wit train efficient models before you have hundreds of Stories, because they can encapsulate some business logic that requires a huge dataset to acquire.

  • Inbox

Whenever a user converses with your bot, you will receive all of the messages in the Wit Inbox. This will help you discover your users’ expectations and logic. Wit advises developers to make the first version of their bots as lightweight as possible.

When you check your messages in the Inbox, you can validate, or not, the result of Wit processing on a message. Each time you validate a processing, it is added automatically to your learning dataset and your bot’s model is rebuilt in real time.

  • Strategies

Some built-in entities are already defined in the Wit AI like temporal expressions, locations, temperatures, etc. Apps in Wit are already trained to recognise these entities. It’s more practical and recommended to use them whenever it is possible. All built-in entities are prefixed by wit/.

When the entities we need are not built-in, we can create our own. The Wit AI provides three Search Strategies for entities:

  • Trait (previously known as Spanless) This strategy is used when the whole sentence is needed to determine the meaning because there is no association between words in the sentence. The entity value is not inferred from a keyword or specific phrase in the sentence. For example, you can use Traits to extract sentiment analysis or politeness or ask for weather.
  • Free Text It’s used when you need to extract a substring of the message and this substring does not belong to a predefined list of possible values. For example, you can use it to extract a contact Name, a Message body, and more.
  • Keywords Contrary to Free Text, this strategy requires a predefined list to which a substring of user’s message matches. You can use it to extract a Countries name.

Integrate Wit.ai with the Bot engine

In this section, we will update our bot engine to use wit.ai to process a user’s text messages. We will use Wit.ai’s Node.js SDK.

Let’s start by installing and adding the SDK to package.json.

npm install --save node-wit

To talk to the Wit API, our bot engine will need a Wit server access token. This is available from the Wit app’s setting page. Create a new environment variable, WIT_TOKEN, in Heroku and set the value as our server access token.

Next, we update bot-engine.js to use Wit.ai for processing all incoming text messages from our bot users.

Add the following code to bot-engine.js:

const Wit = require('node-wit').Wit;
const WIT_TOKEN = process.env.WIT_TOKEN;

const actions = {
  send({sessionId}, {text}) { 
    return postMessage(sessionId, { text: text });
  },
  getMatchingProducts(request) {
    const { sessionId, entities } = request;
    const newFilter = {};
    if (!!entities.size && entities.size[0] && entities.size[0].value) {
      newFilter.size = storeApi.getSizeValue(entities.size[0].value);
    }
    if (!!entities.gender && entities.gender[0] && entities.gender[0].value) {
      newFilter.gender = storeApi.getGenderValue(entities.gender[0].value);
    }
    return sendMessageBasedOnFilter(sessionId, newFilter);
  }
};

const wit = new Wit({
  accessToken: WIT_TOKEN,
  actions
});

Here, we imported the Wit SDK and created a new constant for a Wit server access token. Then we defined the actions object, which has an action name as key, and an action function as the value. Our action object has a send action, which is a mandatory action that takes request and response parameters. We also have our custom getMatchingProducts action, which we defined in our Wit.ai stories. A custom action takes only a request parameter.

Our send action takes the response text from Wit and sends it to the user using the existing postMessage function. Action functions should return a promise, so we will update the postMessage to return a promise.

The getMatchingProducts action will be invoked by Wit.ai if the user message matches the story to show matching products. Wit.ai will send a list of entities as part of the request. We will check if entities size and gender are defined and have a value. Then we call the sendMessageBasedOnFilter function to take action based on the new filter value.

We also construct a new instance of Wit by passing our server accesss token and actions. We will use this to process incoming text messages.

Next, we add the following functions to the bot-engine.js:

sendMessageBasedOnFilter = (recipientId, newFilter) => {
  return updateUserFilter(recipientId, newFilter)
    .then(filter => {
      if (filter.size && filter.gender) {
        sendMatchingProducts(recipientId, filter);
      } else if (filter.gender) {
        sendSizeOptions(recipientId);
      } else {
        sendGenderOptions(recipientId);
      }
    });
}

const sendGenderOptions = (sender) => {
  postMessage(sender, buildButtonTemplateMessage('What are you looking for ?', getGenderOptionButtons()));
}

const handleTextMessage = (sender, text) => {
  wit.runActions( 
    sender, 
    text, 
    {} 
  ).then((context) => {
    console.log('Context recieved from wit', context);
  }).catch((error) => {
    console.error('Failed to run wit action', error);
  })
}

The sendMessageBasedOnFilter will take the new filter value and update user session data. After updating session data, we will send a response message to the user based on current filters. If the user has selected both gender and size, we will send the matching products to the user using the sendMatchingProducts function. If the size or gender is missing, we will prompt the user to make a selection by sending them the options using the sendSizeOptions and sendGenderOptions functions.

We also moved the logic to send gender options to the user in a separate function, sendGenderOptions, to allow reuse without duplication. We implement the handleTextMessage function, which will pass all of the incoming text message to the Wit runActions function for processing. The runActions function take following parameters:

  • sessionId - ID to uniquely identify user session
  • message - The text message received from the user
  • context - Current session state
  • maxStep - Optional parameter to set maximum number of actions to execute

In our bot, we are using Redis for session management, and we use sender’s id as a unique key and store the session state as a value. So in our case, we can use a sender’s id as a sessionId to uniquely identify a user, and since we manage our session outside our Wit interaction, we can simply send an empty object as the context.

Finally, we update the handleIncomingMessage function to pass all of the incoming text message to the handleTextMessage function for processing.

const handleIncomingMessage = (entries) => {
  entries.forEach(function (entry) {
    entry.messaging.forEach(function (event) {
      let sender = event.sender.id
      if (event.message && event.message.quick_reply) {
        handleQuickReplies(sender, event.message.quick_reply);
      } else if (event.postback) {
        handlePostback(sender, event.postback);
      } else if (event.message && event.message.text) {
           handleTextMessage(sender, event.message.text);
       }
    });
  });
}

Since the new sendMessageBasedOnFilter function is responsible to update user session data and send a response to the user based on their selection, we can update handleQuickReplies and handlePostback to use the sendMessageBasedOnFilter function. Our previous implementation always expected the user to select a gender before selecting a size. Using the sendMessageBasedOnFilter function not only removes some duplicate code but also allows us to handle the user selection without enforcing this workflow.

const handleQuickReplies = (sender, quickReply) => {
  if (quickReply && quickReply.payload) {
    const value = JSON.parse(quickReply.payload);
    sendMessageBasedOnFilter(sender, value);
  }
}

const handlePostback = (sender, postback) => {
  const { payload } = postback;
  if (payload === 'GET_STARTED_BUTTON_CLICKED') {
    sendWelcomeMessage(sender);
  } else if (payload === 'START_NEW_SEARCH') {
    session.setData(sender, {});
    sendGenderOptions(sender);
  } else {
    const value = JSON.parse(payload);
    sendMessageBasedOnFilter(sender, value);
  }
}

Also, since our action functions should return a promise, update the postMessage function to return the promise.

const postMessage = (recipientId, message) => {
  return axios.post(FB_MESSENGER_URL, {
    recipient: { id: recipientId }, message
  })
    .catch(function (error) {
      console.error(`Unable to post message to Facebook ${message}`, error);
    });
}

In our store-api.js, we have defined gender and size options, each with a label to display to the user, and the value that is expected by our store API. In the user session, we store the value of size and gender instead of the labels. When a user sends a text message to search for t-shirts, they will use a value for gender and size, which will match the labels for these options.

For example, if the user enters the following text, “I am looking for medium size women’s tshirt,” the entities size and gender will have a value ‘medium’ and ‘women’ respectively. We need to map these values to the values our backend expects, which in this case will be ‘M’ and ‘W.’

So, let’s add the following two methods to our store-api.js to do the conversion.

const getGenderValue = (label) => {
  const selectedGender = genders.find(gender => gender.label.toUpperCase() === label.toUpperCase());
  return selectedGender ? selectedGender.value : null;
};

const getSizeValue = (label) => {
  const selectedSize = sizes.find(size => size.label.toUpperCase() === label.toUpperCase());
  return selectedSize ? selectedSize.value : null;
};

The getGenderValue and getSizeValue are case insensitive, so if the user enters ‘men,’ ‘Men,’ or ‘MEN', the function getGenderValue will correctly map it to ‘M.’

Remeber to make these functions accessible by other modules by updating module.exports.

module.exports = {
  getSizes: sizes,
  getGender: genders,
  getGenderValue,
  getSizeValue,
  retriveProducts
}

Now that we have updated our bot engine, we can deploy the changes to Heroku.

Now when a user sends a message like ‘Hi’ to our bot, our bot will respond with a greeting message as defined in our Wit.ai story.

Exchange greeting message

If a user sends a message to search for t-shirts for a given gender and size, our bot will directly show matching t-shirts.

Matching Result

If a user sends a message to search for t-shirts without selecting both gender and size, we can reuse the existing structured message to prompt the user to make a selection.

Hyrid approach

API.AI

In this chapter we used Wit.ai for natural language processing. Another popular framework to build conversational apps is API.AI.

API.AI was acquired by Google in 2016 and works similar to wit.ai. A bot or app sends input to the API.AI platform, API.AI matches the input to an intent, converts it to actionable data, and sends back a JSON response. To perform any custom business logic, we can provide an optional webhook to an external web service. While Wit.ai offers speech recognisation and can take both text and voice input. API.AI only accepts text input. However, we can use services like Google Speech API to convert speech to text.

Similar to wit.ai Stories, in API.AI we define agents for our app with intents, entities, actions and reponses. Both API.AI and wit.ai offers built-in entities, however API.AI also has the concept of domains. As defined by the API.AI team, domains are predefined knowledge packages. Think of them as predefined intents with entities, actions and reponses, and everything required to directly use them with our bot without any training data. There are various built-in domains for common topics like news or weather for example. You can allow developers to add the ability like reading news or making phone calls to their conversation apps without writing any code.

Another interesting feature API.AI offers is easy integration with various bot platforms like Facebook Messenger, Amazon Alexa, and Slack. With one-click integration developers can build a fully conversational bot using the platform.

You can read more about API.AI here.

Submit for review and launch

While in development only the administrators of the Facebook page associated with our bot can chat with the bot. We have to make the bot public to make it accessible to everyone. Our bot will have to go through a review process by the Facebook team before it will be made publicly accessible.

In the app dashboard, go to the ‘App Review’ page. This page will show the current status of the app and will allow us to submit our bot for review and make it public. Before the review process, it will show that the app is in development and unavailable to public.

Facebook automatically approves our bot to access information like a user’s public profile, email and list of friends. Some features or intergations need approval before public usage. Click on the ‘Start a Submission’ button, and select and add the permissions required for the bot. For our virtual shopping assistant bot, we need pages_messaging permission.

Once you have selected the required permissions, click on ‘Edit Notes’ corresponding to each of these permissions and fill out the corresponding forms. The App Review page will also show a list of things we need to complete before we can submit the app for review, like adding an app icon and privacy policy URL. Complete all of the items in the list and click on the ‘Submit for Review’ button.

Once submitted, the Facebook team will review the app. We can check the status of the approval on the App Review page.

You can read more about the review process here: here

Promote

Once the bot is approved and made public, you can promote the bot in various ways. Users can search the bot in Facebook Messenger or click on the ‘Send Message’ button on the Facebook page to start a conversation with the bot. Make sure you have the ‘Send Message’ call to action configured for your page.

You can add ‘Send to Messenger’ Or ‘Message Us’ button to your website which will allow the user to launch and start a conversation with your bot. You can also share your bot Messenger link, https://m.me/[username], via email and sms.

If you have a contact number of your users and their constent to contact them, you can also send messages to them via Messenger. For this you will need to add the pages_messaging_phone_number permission while submitting the app for review.

Lastly, If you are using Facebook ads to advertise your products or service, you can select Messenger as a destination, allowing users to directly open a Messenger chat by clicking on the ad.

You can read more about entry points here: here

Analytics

After making the bot public and promoting it, you may want to know who is interacting with your bot and how are they using it. For this you can use the Facebook Analytics for Apps tool.

Go to the Facebook Analytics for Apps dashboard and select the bot from the list of apps.

The analytics will give us information about our users, like the number of active users, the number of unique users, the demographics of the users interacting with our bot, their age, gender, country, and more. We can also track events like the number of messages sent and received by our bot, or the number of times the call to action was clicked.

There are various other reports and tools Facebook offers to get insight on who is using your bot and how it is used. See Analytics for Apps for more details.

Summary

In this chapter we made our bot conversational by using the natural language processing API Wit.ai. This allows users to talk to our bot as if they are communicating with another human. In the next chapter, we will continue the conversational interface discussion and learn how we can build a voice-based conversation bot.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset