Archived content

Archived date: 2019-05-22

This content is no longer being updated or maintained. The content is provided “as is.” Given the rapid evolution of technology, some content, steps, or illustrations may have changed.

Watson Conversation is now Watson Assistant. Although some illustrations in this tutorial may show the service as Watson Conversation, the steps and processes will still work.

This tutorial series shows how you can create a chatbot that can be deployed on two messaging applications: Facebook and Slack. In this final tutorial, I explain how you can enhance the chatbot by using IBM Watson Services. The news chatbot in this series uses developerWorks content as an example, but you can modify the content source to meet your own needs.

In a previous tutorial, I described the importance of artificial intelligence (AI) in your chatbots and explained how it’s hard to build your own AI—it requires not only rock stars in data science, but also a massive amount of data to train models. A small company typically does not have these kinds of resources. Fortunately, you can use the advanced AI research that is done by companies such as IBM in your applications.

IBM provides its AI functions through Watson services on its IBM Cloud platform. These services let you incorporate AI into your application by simply calling web services. In the previous two articles in this series, I left some empty service keys in the BaseServlet class. Those keys are for the Watson services that I use in the chatbot. Specifically, I use:

  • Watson Assistant to determine the user’s intent when the user says something not in the command keyword list.
  • Watson Retrieve and Rank that combines a search engine with a trained rank model to provide customized and domain-specific search results. (Now part of Watson Discovery.)
  • Watson Speech to Text to interpret what the user says when sending a voice recording.
  • Watson Text to Speech to read the article summary aloud to the user.
  • Watson Tradeoff Analytics (No longer available.)

Note: Watson Assistant does more than detect a user’s intent. It also detects entities in a message (that is, concepts or objects with synonyms) and keeps track of the conversation state. You can script the service to generate automated responses based on the current intent, entities, and conversation state—making it a mini chatbot on its own.

Of course, many more AI services exist in the Watson catalog, but I will focus on these five services as examples in this tutorial.

IBM Cloud setup

Before starting, you must have access to IBM Cloud. You can try it out for free with IBM Cloud Lite. Your free account never expires, and you get 256 MB of Cloud Foundry runtime memory, plus 2 GB with Kubernetes Clusters. This memory should be sufficient for testing and personal projects.

  1. After you sign in to IBM Cloud, select a service from the Watson catalog to add to your account. IBM Cloud catalog screen
  2. Configure and create the service. For each service, create a credential—a user name and password—to access the service. The user name and password are passed to the web service by using HTTP headers.
  3. The auto-generated credentials access the Watson service.

You can test the web services by using command-line tools such as curl or by using a web-based API explorer. (In this tutorial, I use curl.) The API explorer can access web service endpoints by using an interactive web page. You can construct a request and see details of the response that is generated by the Watson API explorer, as shown in the following figure. (Note the user name and password at the upper right.)

Watson API explorer Tradeoff Analytics results

Watson Assistant

Let’s look at the Watson Assistant service. One of its functions is to detect user intent in a message, which is useful in chatbot conversations. The chatbot can map the user input to one of several “actions” it knows how to perform and then give the appropriate response. It is the essence of making the chatbot seem “intelligent.”

Note: If you only need a natural language intent classifier, you can use the Watson Natural Language Classifier service instead. However, the Watson Assistant service offers many useful features and tools for chatbot development.

In the Watson Assistant service dashboard, click the launch icon to open a web-based console for the service. (If you need to know how to get to the Watson Assistant service dashboard, you can follow the instructions on the Watson Developer Cloud.)

Launching the Conversation service from the dashboard

Create a workspace for your project, and then in the workspace, add intent, entity, and dialog services. In this example, I will show how the intent works.

Adding the workspace window

To detect intents, you must first “train” a model. You give the model a few sample sentences and their intents. After the model “learns” a few examples, it is able to classify new sentences. The more training a model has, the more accurately it will classify new sentences.

You can either upload a CSV file for the training data or create your own intents. My training data is in a CSV file. The first column has sample sentences, and the second column has the classifications. Following are a few example training sentences. The first several lines are classified as “help” and the last several lines are classified as “search.”


Can you help me?,help
Please help!,help
Someone help,help
I want to know how this works,help
How does this work?,help
I would like to know why,search
Can you search for this for me?,search
I have a question,search
I'd like to ask a question,search

Under the Intents tab, enter your intents or upload your CSV file, and the web console is populated with your stated intents and phase examples. You can adjust the intents and examples interactively on the web console.

Screen showing the entered intents

After your model is trained, you can query it with new sentences and it provides the intents that it can “think of,” and the confidence level for each intent. The WORKSPACEID is the model ID generated when I created the workspace. It is in the web console’s URL when you are inside the workspace.


curl ‑X POST ‑u "USERNAME":"PASSWORD" ‑H "Content‑Type:application/json" ‑d "{\"input\": {\"text\": \"how are you\"}}" "https://gateway.watsonplatform.net/conversation/api/v1/workspaces/WORKSPACEID/message?version=2016‑07‑11"

{"input":{"text":"how are you"},
 "context":{"conversation_id":"..." ...},
 "entities":[],
 "intents":[{"intent":"hello","confidence":1}],
 "output":{"log_messages":[…],"text":[]}
}

To make your chatbot intelligent, you must continuously collect real-world user inputs, manually classify them, and then train your natural language classifier over time (that is, build multiple models).

Watson Retrieve and Rank

In the developerWorks news delivery chatbot that I created as part of this series, I deploy a Lucene search engine (Hibernate Search) to index and search tutorials upon a user’s request. It works well for finding relevant content in an objective manner (that is, the term frequency–inverse document frequency or tf-idf approach). However, the issue with term and document frequency searching is that it does not reflect the user’s preference; it only reflects the use of search keywords in the body of documents.

The Watson Retrieve and Rank service addresses this issue by combining a search engine with machine learning. You can manually rank search results for search terms. Based on that data, it learns your preferences and is able to rank results for new search terms.

The Retrieve and Rank service needs two things: an Apache Solr cluster and a ranker. The service uses the Apache Solr stand-alone search engine, which is also based on Lucene. Setting up a Solr cluster as a service in the Watson cloud takes approximately three steps:

  1. Create a Solr cluster by using a web service call. The call returns an ID for the cluster that you can use later.
  2. Upload Solr configuration files to the cluster. The configuration files specify how the search engine behaves, such as which words are treated as synonyms, the indexing strategy, filtering, and the caching policies of the cluster.
  3. Upload a JSON document that contains all source documents to be searched. You must retrieve text from your documents, assign each document an ID, and place them into a JSON file to be uploaded to the Solr cluster by using the Watson web service.

To train a ranker, you treat it much like you train the natural language classifier. You create a CSV file that contains questions the user is likely to ask, followed by any number of columns that list the search result document ID and the relevance (rank) of each document. After the model is trained, you can make subsequent search queries. Watson will try to return results that are ordered according to your preference.

The process of setting up a Solr cluster and ranker for the Watson Retrieve and Rank service is rather complicated.

Watson Tradeoff Analytics

The Watson Tradeoff Analytics service can help your chatbot balance multiple decision factors and make recommendations to your users. This use case is very common. The simplistic approach is to filter and order results based on the user’s preference or stated criteria. But filtering and ordering often gives poor results because they are very coarse. The Tradeoff Analytics service balances conflicting criteria by using an algorithm that is called Pareto Optimization.

To use Tradeoff Analytics, you must pass in the factors to optimize for, and a list of potential choices with scores for each factor. Following is an XML data input file from an IBM official example. The columns array contains fields (keys) that must be optimized in the decision. The options array contains the choices to select from. Each options element contains all the keys in the columns.


  
{
  "subject": "phones",
  "columns": [
    {
      "key": "price",
      "type": "numeric",
      "goal": "min",
      "is_objective": true,
      "full_name": "Price",
      "range": {
        "low": 0,
        "high": 400
      },
      "format": "number:2"
    },
    {
      "key": "weight",
      "type": "numeric",
      "goal": "min",
      "is_objective": true,
      "full_name": "Weight",
      "format": "number:0"
    },
    {
      "key": "brand",
      "type": "categorical",
      "goal": "min",
      "is_objective": true,
      "full_name": "Brand",
      "range": [
        "Apple",
        "HTC",
        "Samsung",
        "Sony"
      ],
      "preference": 
        "Samsung",
        "Apple",
        "HTC"
          },
    {
      "key": "rDate",
      "type": "datetime",
      "goal": "max",
      "full_name": "Release Date",
      "format": "date: 'MMM dd, yyyy'"
    }
  ],
  "options": 
    {
      "key": "1",
      "name": "Samsung Galaxy S4",
      "values": {
        "price": 249,
        "weight": 130,
        "brand": "Samsung",
        "rDate": "2013‑04‑29T00:00:00Z"
      }
    },
    {
      "key": "2",
      "name": "Apple iPhone 5",
      "values": {
        "price": 449,
        "weight": 112,
        "brand": "Apple",
        "rDate": "2012‑09‑21T00:00:00Z"
      }
    },
    {
      "key": "3",
      "name": "HTC One",
      "values": {
        "price": 299,
        "weight": 143,
        "brand": "HTC",
        "rDate": "2013‑03‑01T00:00:00Z"
      }
    }
  }

Post the following XML content as an HTTP POST body to the Tradeoff Analytics service.


curl ‑X POST ‑u USERNAME":"PASSWORD"
‑‑header "Content‑Type: application/json"
‑‑data @problem.json
https://gateway.watsonplatform.net/tradeoff‑
analytics/api/v1/dilemmas?generate_visualization=false"

The service returns a suggestion for each of the potential choices. Your chatbot can now return the results to the user. In this case, the best choice is options 1, which is Samsung Galaxy S4.


{
  "problem": {
    … …
    "resolution": {
    "solutions": 
      {
        "solution_ref": "1",
        "status": "FRONT"
      },
      {
        "solution_ref": "2",
        "status": "INCOMPLETE",
        "status_cause": {
          "message": "A column of a option is out of range. Option \"2\" has a value in column \"price\" which is:\"449\" while the column range is: \"[0.0,400.0]\"",
          "error_code": "RANGE_MISMATCH",
          "tokens": 
            "price",
            "449",
            "[0.0,400.0]"
                  }
      },
      {
        "solution_ref": "3",
        "status": "EXCLUDED"
      }
      }
}

Watson Text to Speech

With the Watson Text to Speech service, your chatbot reads aloud to your users. This method is a good way to communicate information to the user when it’s not convenient for the user to read the information. It is also useful in conveying a large paragraph of text in a mobile messaging environment. In the developerWorks news bot sample code, I use the Watson Text to Speech service to read the tutorial abstract aloud.

Note: The “Hear it” button is only available in the sample application in GitHub. It is not on the live demo applications on Facebook Messenger and Slack.

Screen showing the option to read the tutorial summary

The service is simple. You just pass in your text as an HTTP parameter, and the service returns a WAV file that contains the audio. You can save the binary WAV data and make it available to the messaging app as a web link to play back.


curl ‑X GET ‑u "USERNAME":"PASSWORD"
‑‑output output.wav
"https://stream.watsonplatform.net/text‑to‑speech/api/v1/synthesize?accept=audio/wav&text=TEXT_TO_READ_ALOUD&voice=en‑US_AllisonVoice"

However, the WAV audio is minimally compressed and takes a long time for the messaging client to download. My strategy is to pass the WAV content through a web-based media encoder service, and turn it into an MP3 link.

In my example code, I choose to use the zencoder service for this purpose. The WAV content from Watson is cached on the server, and the cached link is passed to zencoder by using a web service call for MP3 encoding. After zencoder completes its encoding work, the bot application is able to retrieve an MP3 link and redirect the user there.

Watson Speech to Text

The Watson Speech to Text service turns a voice audio recording into text. It is useful in developing voice-based chatbots, where the bot can respond to the user’s voice commands. These voice command applications appeal to many users. The web API is simple. You just need to upload the speech audio content in the body of your HTTP post request.


curl ‑X POST ‑u "USERNAME":"PASSWORD"
‑‑header "Content‑Type: audio/ogg"
‑‑data‑binary @audio.ogg
"https://stream.watsonplatform.net/speech‑to‑text/api/v1/recognize"

In most modern messaging applications, users can send recorded voice messages to each other. The message shows up in the chat session as a “playable” audio clip. When the user sends a voice message to a chatbot, the API sends an MP3 link of the audio file to the bot’s webhook.

alt

In the developerWorks news bot, I turn the audio into a text command.

alt

In the BaseServlet class of my code, I handle all the voice processing automatically. If the user sends a voice message, the BaseServlet class turns it into text and passes the text into the converse() method, which the bot developer implements. Therefore, in the converse() method, you can focus on dealing with text messages.

Depending on your messenger platform, you might have to do a few more steps. For example, the Facebook Messenger platform sends voice audio links to an MP3 file. In this case, I first transcode the MP3 file into an OGG audio file, which Watson supports, and then pass the OGG file to Watson. The transcoding is done by using the zencoder web service.

Summary

In this tutorial series, I describe the basic principles and techniques for building chatbots on modern mobile messaging platforms. IBM Watson cognitive services can play a crucial role in making the chatbots smarter and easier to use.

Ready to go deeper? Access code patterns and learn how to hook it all together. Take it to the next step by learning how to create a cognitive news alerting app.