Making of a Smart Business Chatbot - Part 2

Published

Chatbots are a great way to interact with your customers in real-time and gain insights into your users. In this second in our series on building smart business chatbots, we’ll learn how to give our Slackbot from Part 1 some intelligence by connecting it to a Watson Conversation dialog.

In our previous article, we took a look at building a slack chatbot using Node-RED and Compose. If you haven't gone through that article already, now's your chance. Go ahead - I'll wait....

Ok, now that you're back, it’s time to make our chatbot look far more intelligent than it really is by connecting it to IBM Watson Conversation and giving it some realistic dialog.

Let’s get started...

Understanding a Conversation

Before we jump in, there are a couple of vocabulary terms we should be familiar with. You can find more details in the Watson Conversation documentation. In this section, we’ll just quickly cover the basics you need to start building our chatbot.

Workspaces are how Watson organizes your conversation applications. Basically, each application is going to have its own workspace. If you’re building chatbots, this means that each chatbot gets its own workspace.

Intents are the first level of your conversation that uses Artificial Intelligence. When your user sends a request to your chatbot, Watson attempts to figure out what kind of conversation the user is trying to have so it can respond with the appropriate dialog. It does this by having you supply a list of phrases that could be used to initiate a conversation and then training on those phrases.

Entities act like variables in a programming language and provide context for your conversation. In an application that looks for business locations across a country, an entity might represent the specific city a user is searching in.

Finally, we have Dialogs which are the actual text your chatbot will respond to users with. Your chatbot can respond with multiple different dialogs for each intent and can include entities in the response for things like confirming the users’ selection.

Let’s explore how these fit together by creating our first conversation.

Creating a Conversation

The first step to creating a conversation is to create a workspace in Watson Conversation. You’ll need to sign up for Watson Conversation using your Bluemix account before we start.

Once you’ve logged in, you’ll be dropped directly into the workspaces page. Workspaces are how Watson organizes different conversation applications, and you’ll want to create a new workspace for each chatbot you make. Click the create button at the top to create a new workspace, then give your workspace a name and description.

Once we’ve created a new workspace, we should see a page with a tab for each element of a conversation (intents, entities, and dialogs). In general, we’ll want to start with some Intents to provide an entry point for users in to our conversation. Let’s add a new intent called welcome that provides a simple greeting to our users. Click on the Create new button in the intent tab.

We’ll start out by giving our intent a name (which automatically starts with a # sign) and add some phrases that the user can type to call this intent. You can add as many phrases as you feel are necessary to cover your users’ conversational needs. Watson will automatically train on those phrases as well as handle things like spelling errors and pluralizations, so there’s no need to include different spellings or pluralizations of the same words.

Create an intent called #greeting and add some phrases that a user might enter to initiate conversation with the chatbot.

Next, we’ll create a dialog of responses that the user can receive when they trigger the #welcome intent we made above. Navigate to the dialogs tab and click the Create button.

Watson will automatically create two dialog branches: the first is named welcome, which contains a simple phrase when a user initiates a conversation and Anything Else which is the default flow if a conversation doesn’t match against an intent.

Now, let’s connect up an Intent to one of our newly-created dialogs. We’ll use the welcome intent and tell it to trigger if the bot recognizes #greeting. When we use the name of an Intent in the if field, Watson will use that chain of dialog when the Intent is encountered. We’ll also add a few more response phrases, and click on the Set to random link that appears when we add our second phrase so we get back a random response every time the user triggers the Intent.

We now have enough pieces together that we can start testing our conversation bot. Click on the Deploy button in the left-hand menu and you’ll be taken to the deployment page. This page has the information we’ll need to connect our slackbot up to the Conversation API.

Connecting Our Slackbot to Conversation

Now that we have a brain behind our bot, let’s wire the two together. In the Deploy section of Conversation, click on the credentials tab. Make a note of these credentials - we’re going to use them in a moment.

Now, we’re going to head back to the Node-RED application we set up in Part 1. If you’re using Bluemix-Hosted Node-RED, you’ll already have a couple of Watson Conversation nodes installed.

Drag the conversation node onto the canvas and double-click it to configure. Enter the Username, Password, and Workspace ID you noted from your conversation credentials and click done.

We’ll need to do some processing of the message coming in from slack before we can send it off to Watson conversation. Drag a function node between the HTTP IN node and the conversation node. In the function node, add the following code to format the message for conversation.

if (msg.payload.event.username != "DrWatson") { // Check to make sure bot isn’t responding self  
    msg._payload = msg.payload; // Save the event for later use
    msg.payload = msg._payload.event.text; // Set the text to send to conversation.
    node.send(msg); // Send the message long to the next node
}

In this function, we first check to make sure that the message didn’t come from our bot - otherwise, it ends up responding to its own messages in an infinite loop.

So far, our flow should look like this:

Before we send the message out to Slack, we’ll need to format it to match the Slack Events API. This means updating the content-type of the message to x-www-form-urlencoded and formatting our msg.payload so we can send it to the chat.postMessage API call.

Drag another function node on the canvas on the output side of the conversation node and double-click to add the following code:

msg.headers = {  
    "content-type": "application/x-www-form-urlencoded"
}

msg.payload = {  
    "token": "<your_bot_user_access_token>",
    "channel": msg._payload.event.channel,
    "text": msg.payload.output.text[0],

};

return msg;  

When you enter the above, make sure to replace the <your_bot_user_access_token> with the actual access token for your bot user. You can find that in the OAuth and Permissions section of your slack app.

While you’re there, you’ll also want to make sure that you have the correct app permissions to send messages to our slack team. In the OAuth and Permissions section of your slack app, scroll down to the Permission Scopes section and type chat in the search box. Click on the option that says chat:write:bot and click Save Changes on the bottom. Slack will prompt you to re-install your app to accommodate the new permissions. Once that’s done, you’ll now be able to send messages from the chatbot to Slack.

Now that we have our message formatted for the Events API, it’s time to send it off to slack. Grab an HTTP Request node and drag it onto the canvas near the output of our last function node. Double click the node and put https://slack.com/api/chat.postMessage in the URL field and set the Method to POST:

Once you click Deploy, you should have everything in place for your chatbot to receive and send messages from slack. Navigate over to Slack, open a private message with your bot user, and type in some text. Your bot should now respond to messages that match your Intents with responses from your dialog tree.

Adding Some Personality

Once we have our users' chats, and we can respond to them using Watson Conversation, the sky's the limit on what we can do with that information! Anything from training new Artificial Intelligence models to finding better business FAQ's.

Let's try out a this out in a small way first: by doing some simple sentiment analysis. Sentiment analysis will allow us to find a general sentiment of the conversation, giving us a score based on how positive or negative the language is. We'll save this information along with our chats in the database, and use it later to provide more interesting text analysis.

First, let's switch out the stock MongoDB Node-RED node with one that allows us to do a little more processing. In Node-RED, open the side menu and click on the menu option that says Manage Palette

This will allow you to install a new Node-RED node. Click on the install tab, and search for mongodb2. Then, click the install button.

Once that's done, replace the mongodb node you added in our previous article with the mongodb2 node and configure it with your database credentials. Then, configure your connection to use the insert operation and click done.

With the MongoDB2 node, we'll be able to take continue the flow even after our data has been inserted into the database. For now, we'll use it to spot-check the data inserted, but in a future tutorial we'll send that info off to Watson to be processed later.

Now, let's add some simple Sentiment anlysis. First, we'll search for the sentiment node into the palette and drag it onto the canvas. The sentiment node assumes that your message will be in the msg.payload object, but since we've already created a function to move that data for the conversation node, we'll wire up our sentiment node after that.

The sentiment node analyzes the text and adds a score to the message in the msg.sentiment object. The last thing we'll need to do is put that sentiment in the msg.payload object so it will save in the database. Add a function node and double-click it to add the following code:

msg.payload = msg._payload;  
msg.payload.sentiment = msg.sentiment;  
return msg;  

Your final flow should look something like the following:

Now, when we start sending messages to our chatbot, we should see an additional sentiment object in our chat log. The sentiment object breaks down the text and provides a sentiment score for the phrase, with negative numbers representing more negative language, and positive numbers representing more affirmative language.

{
  "token":"XXXXXXXXX",
  "team_id":"XXXXXXXXX",
  "api_app_id":"XXXXXXXXX",
  "event":{
    "type":"message",
    "user":"XXXXXXXXX",
    "text":"I’m having a bad day",
    "ts":"1501602893.311521",
    "channel":"XXXXXXXXX",
    "event_ts":"1501602893.311521"
  },
  "type":"event_callback",
  "authed_users":[
    "XXXXXXXXX"
  ],
  "event_id":"Ev6GK9UYKW",
  "event_time":1501602893,
  "sentiment":{
    "score":-3,
    "comparative":-0.6,
    "tokens":[
      "im","having","a","bad","day"
    ],
    "words":["bad"],
    "positive":[],
    "negative":["bad"]
  }
}

With a basic sentiment analysis, we can determine whether a message had a positive, negative, or neutral sentiment. This can be used for a number of different reasons, such as automatically redirecting a frustrated customer to a service representative or prompting a satisfied customer to rate your business on social media.

Wrapping Up

We now have a slack chatbot that saves our conversations and responds to our users in a realistic way. We can also save and analyze the messages our customers are sending to us to determine their sentiment. In the next article in this series, we'll look at how to use our chatbot to provide answers to users' questions using a JanusGraph-backed knowledge base.


If you have any feedback about this or any other Compose article, drop the Compose Articles team a line at articles@compose.com. We're happy to hear from you.

attribution Clem Onojeghuo

John O'Connor
John O'Connor is a code junky, educator, and amateur dad that loves letting the smoke out of gadgets, turning caffeine into code, and writing about it all. Love this article? Head over to John O'Connor’s author page to keep reading.

Conquer the Data Layer

Spend your time developing apps, not managing databases.