Contents


Build a chatbot in the IBM Cloud

Easily build a chatbot with Watson technologies

Comments

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.

Chatbots are a great way to interact with users. When you combine the natural language understanding and conversational capabilities of the Watson platform, you can build sophisticated chatbots.

Here's what you'll do in this tutorial:

  1. Create an instance of the Watson Assistant service.
  2. Learn the basics of chatbots, including intents, entities, and dialogs.
  3. Create a simple chatbot.
  4. Use more advanced techniques in your chatbot.
  5. Deploy your chatbot as part of a stand-alone application.

Creating an instance of the Watson Conversation service

The first thing you'll need to do is create an instance of the Watson Conversation service. This is where you'll build your chatbot. The service features a friendly web UI for building the chatbot and a test panel that lets you see how your chatbot handles various user inputs.

To get started, go to the IBM Cloud catalog:

  1. Go to console.bluemix.net, click Catalog at the top of the page, and type conversation in the search bar. You'll see the Conversation service in the Watson section. The Watson                 Conversation service in the IBM Cloud catalog
    The Watson Conversation service in the IBM Cloud catalog
  2. Click the catalog item to get started. On the next panel, you'll see the name of the new service at the top. You can take the existing name (which will be something like Conversation-n1) or enter your own name. Scroll down to the Pricing Plans section and make sure that the Lite plan (the Free plan) is selected. The Lite                     pricing plan for the service
    The Lite pricing plan for the service
  3. Click Create to create your new Conversation service.
  4. Click Launch tool to start building your chatbot. The management screen                     for the conversation service
    The management screen for the conversation service

    Notice that the Conversation service is named dwtv-convo instead of the far less memorable Conversation-n1. You'll see the Workspaces panel.

    The workspaces                 panel
    The workspaces panel

    Your service includes a sample chatbot for a car's dashboard and a pane to create a new workspace. Each workspace contains a chatbot and all of the resources it needs to do its work. If you're using an IBM Cloud Lite account, you can create up to five new workspaces.

  5. Click Create to create a new workspace. Complete the details like this:
    • Name: Royal Valet
    • Description: Rameses II's personal valet chatbot
    The name and                 description of the new chatbot
    The name and description of the new chatbot

The scenario

The example scenario you'll build here is a Royal Valet chatbot for Pharaoh Rameses II of ancient Egypt. (Work with us here. At least it's not "Hello World.") There are three things that Rameses might want to do on any given day:

  • Hold a feast
  • Build a monument of some kind (he was really into that sort of thing)
  • Start a war

Your chatbot will help the king plan his day. If Rameses wants to hold a feast, you need to know what kind of feast. If he wants to build something, you need to know what he wants to build (an altar, a temple, an obelisk) and where he wants to build it. Finally, if he wants to start a war, you need to know who he wants to fight and where the battle will take place.

That's the chatbot you'll build here, although you should definitely feel free to make up your own scenario if you want.

Creating a simple chatbot

After you've created your workspace, you should see the following screen.

The intro screen for                 your new chatbot

The intro screen for your new chatbot

As you can see in the upper left, there are three things that you'll define as you build your chatbot:

  • Intents: The actions the Pharaoh might want to take (think verbs here).
  • Entities: The things Rameses II might ask for or select, such as a monument type or a feast type or a battle site (similarly, think nouns).
  • Dialogs: The interactions (or conversations, if you like) between the king and your chatbot. You'll use dialogs to identify intents and entities from the king's input.

The pharaoh will interact with your chatbot through dialogs. When the chatbot identifies the king's intent and all of the entities needed for that intent, it says "Long live the king" or something similar. After that, we'll agree to imagine that the chatbot delivers the king's request to the Royal IT Department for implementation.

Creating intents

In the previous image, you'll notice that the Conversation service is waiting for you to create some intents. Click Create new to get started.

For each intent, you'll give it a meaningful name such as #have_a_feast (intents are prefixed with hash marks) and several examples of things the king might say to indicate that this intent is what he wants to do. So for #have_a_feast, some examples might be "let's eat!," "ring the dinner bell," or "sound the feasting horn." The more examples that you define, the more likely it is that the Watson natural language understanding service will catch the king's meaning.

Type a name for the intent and enter some examples. After typing each example, press Enter, and Conversation adds the example to the list under the entry field. Here is a start.

An intent with a name                 and several examples

Creating entities

Now it's time to create some entities that relate to the #have_a_feast intent. Click the Entities tab at the top of the workspace. As you would expect, the Watson Assistant service lets you know you don't have any entities defined.

The start screen                 for defining entities
The start screen for defining entities

As with intents, click Create new to create a new entity. Define a new entity called @feast_type (entities are prefixed with at signs). When you define the entity, you define all of the possible values for that entity as well as synonyms for any or all of those values. As with intents, the more examples you provide, the better results you'll get from Watson's natural language processing system.

This example defines three values for @feast_type, one of which has a synonym: sed, pot luck, and food chariot rodeo.

An entity with                 three possible values
An entity with three possible values

Notice that "food truck rodeo" is a synonym for "food chariot rodeo."

Creating dialogs

Now it's time to round out your chatbot with some dialogs. Click the Dialog tab at the top of the workspace. Every chatbot has two default dialogs: Welcome and Anything else.

The two default                 dialogs for every chatbot
The two default dialogs for every chatbot

The Welcome dialog is the greeting that displays when the user starts the chatbot. Anything else is used as the default response, which is typically some variation of "Sorry, I didn't understand that."

To get started, click the box for the Welcome dialog and change the message to something befitting a king.

A more suitable                 message for the pharaoh
A more suitable message for the pharaoh

When the chatbot starts, this dialog fires and the message is displayed. You can define multiple variations of this response, so you could define several greetings and have the system pick one at random whenever the chatbot starts.

You can do the same thing for the Anything else dialog. "Your humble servant was unable to make any sense whatsoever out of what you just said" might be a more suitable response for the king. (Or maybe not.)

That covers the default dialogs. Now it's time to create one of your own. Click the three dots icon in the Welcome dialog and select Add node below to create a new node below it.

Adding a new node                 beneath the Welcome node
Adding a new node beneath the Welcome node

Name the dialog "Have a feast" and set the dialog to fire when the system recognizes the #have_a_feast intent.

Associating the                 dialog with the #have_a_feast intent

Note: It's a matter of style, but your author prefers to associate all of the dialogs with intents. You can create dialogs that respond to entities if you prefer.

This dialog fires when Watson determines that the king said that he wants to have a feast. If that's the case, the chatbot needs to ask the king what kind of feast he wants to have. But what if the king types something like this:

Sound the feasting horn! Let there be a food truck rodeo for all my people!

Watson recognizes the #have_a_feast intent and the @feast_type entity in this case, so we don't want to respond by asking the king what kind of feast he wants to have. To handle this, we use a Watson Assistant service feature called slots. To define them, click the Customize link in the upper right. Click the slider to enable slots.

Enabling slots for a                 dialog
Enabling slots for a dialog

The idea behind slots is that you define all of the entities that Watson must recognize before this dialog is finished. Here's the updated dialog with a single slot defined.

An updated dialog                 with a single slot defined
An updated dialog with a single slot defined

As you can see, if the intent is #have_a_feast, the Watson Conversation service checks to see whether the @feast_type entity is defined. The value of the entity is stored as a local variable named $feast_type (variables are prefixed with dollar signs). If the entity does not exist, there is a question that the chatbot will ask the king. (The complete question is "What kind of feast would your excellency like to have?" but only part of the text appears here.) Finally, this slot is required, so the dialog won't complete until this entity has a value.

The last piece of the dialog is the response. The following image shows what your chatbot says to the pharaoh after all of the required entities are defined.

Excellent! I will make plans for the <feast type> right away. Long live the king!
Excellent! I will make plans for the <feast type> right away. Long live the king!

The value of the $feast_type variable is included in the response.

If the king types something that indicates he wants to have a feast ("ring the dinner bell" would do the trick), the @feast_type entity won't be defined, so the chatbot asks the king what kind of feast he wants. On the other hand, if the king types a complete request ("let's have a feast. I'm thinking a pot luck."), your dialog has everything that it needs to complete the king's request. It responds "Excellent! I will make the plans for a pot luck right away. Long live the king!" without any further questions for the pharaoh.

Testing your chatbot

Enough with setting things up already. Let's see how your chatbot works. Click the Conversation icon in the upper right corner to start the testing dialog.

The Conversation icon

You can play the role of the pharaoh and see how your chatbot responds. For example, the following image shows what happens when you type "let's have a feast!"

Watson recognizes the king's intent
Watson recognizes the king's intent

Notice that the interface makes it clear what Watson recognized in the input. It correctly identified the king's intent as #have_a_feast. Also, notice the drop-down arrow next to the identified intent. If Watson got it wrong, you can click the arrow and select the correct intent. Watson learns from the correction, so it's a good idea to do this whenever Watson misses the mark.

Because the king did not specify what kind of feast he wants, your chatbot responds with a follow-up question.

Here's an example of what happens when the king makes a complete request.

A complete request from the king, followed by a response from the                 chatbot
A complete request from the king, followed by a response from the chatbot

Watson correctly identified the intent, but it also identified the @feast_type. The interface highlights the text that Watson recognized in the input and the conclusion it reached based on that input. Because you defined "food truck rodeo" as a synonym for "food chariot rodeo," Watson understands what the king meant. The response from the dialog includes the value of the entity as the original value, not the synonym: "I will make the plans for a food chariot rodeo..." is the response, despite the fact that the king typed "food truck rodeo" instead.

Using more advanced techniques in your chatbot

At this point, your chatbot handles one of the three things the king might want to do. In this section, you'll implement the rest of the intents that you need to create a full-featured chatbot. There are three more complicated scenarios your chatbot needs to handle.

  • Disallow certain values for an entity: In Rameses II's day, pyramids were terribly out of fashion. (The last one was built roughly 1,500 years before his time.) If the king says that he wants to build a pyramid, the chatbot needs to insist politely that he build something else.
  • Infer an entity's value based on intents and other entities: If the king wants to fight a war, your chatbot needs to know who the king wants to fight and where. For some enemies, you can infer the battle site from the enemy. As an example, if the king wants to fight the Sherdan pirates, the battle will obviously be at sea. On the other hand, if the king wants to fight the Hittites, the battle can take place in Judea or Canaan (aka Samaria). Your chatbot needs to infer the battle site whenever possible and only ask the king where the battle should take place if it is unclear.
  • Reset the chatbot's state: As your chatbot identifies an entity, its value sticks around unless the king types something that overwrites it. You need to implement an intent to reset the values of all of the entities. The code to do this will be associated with the intent #start_over.

We'll use conditional entities, conditional responses, multiple responses, and the JSON source of dialogs to make the magic happen.

Some background

What you'll do in this section assumes that more intents and entities have been set up. One way to get those intents and entities set up is to import them. You can find the JSON version of the final chatbot at gist.github.com/DougTidwell. (Look for the gist named RoyalValet.json.) Save the file to your machine, then go to your workspace and click the Import icon.

The import icon in the Conversation service workspace
The import icon in the Conversation service workspace

Select the file from your machine, make sure the Import Everything radio button is checked, then click Import.

Importing a workspace
Importing a workspace

This adds to your workspace a new chatbot that has all of the intents, entities, and advanced features we'll cover here. The chatbot is also called Royal Valet, so you might want to rename it to distinguish it from the chatbot you created earlier.

On the other hand, if you'd rather build everything yourself, add the following intents:

Intent nameExamples
#have_a_feasthave a feast
eat!
how about a food truck rodeo?
ring the dinner bell
shindig
soirée
sound the feasting horn
#build_somethinglet's build something
#start_a_warconquer
declare war
fight
go to battle
I'm really annoyed with the Sumerians lately.
occupy
pillage
plunder
smack
start a war
#doneI'm done.
It's a plan.
Make it so.
#get_helpgive me a hand here
help me out here
how do I get started?
what do I do next?
#start_overstart over

With those intents defined, add the following entities:

Entity nameValues (and synonyms)
@battle_siteCanaan (Samaria)
Judea
Libya
Nubia
sea (ocean, Mediterranean)
Syria
Ur
Uruk
@enemyHittites
Libyans
Nubians
Sherdan pirates (pirates)
Sumerians
Syrians
@feast_typefood chariot rodeo (food truck rodeo)
pot luck (potlach)
sed
@monument_siteAbu Simbel
Pi-Ramesses (Pi-Rameses)
Qurna
Thebes
@monument_typealter (alter)
obelisk
pyramid
statue
temple

Disallowing values for an entity

The first advanced technique you'll implement is disallowing a value for an entity. You're going to disallow "pyramid" as a value for @monument_type. As we discussed earlier, pyramids are so 1,500 years ago, so your chatbot needs to politely suggest to the king that he build something else.

The dialog for building something (tied to #build_something) uses conditional slots and conditional responses. If some condition is met, the conditional slot fires or the conditional response is returned. Defining the dialog requires three steps:

  1. Enable slots for this dialog.
  2. Define a conditional response. If the thing the king wants to build (@monument_type) is a pyramid, the dialog responds with a polite message informing the king that pyramids are passé. If the king wants to build anything else, the conditional response doesn't fire.
  3. Define a conditional slot. If the king wants to build something that isn't a pyramid, the chatbot processes the slot for @monument_site.

Note that if the king types "let's build an obelisk in thebes" (a sentence that contains the #build_something intent and values for the @monument_type and @monument_site entities), the conditional slot should respond with "Excellent, your majesty. I will start the plans for a new obelisk in Thebes" without any further prompting.

You already know how to enable slots for this dialog, so go ahead and do that. Next, create two slots, one for @monument_type and one for @monument_site.

Two slots, one required and one conditional
Two slots, one required and one conditional

Notice that the first slot is required, while the second is conditional. To set up the slots, click the gear icon next to the @monument_type slot to configure it. Click the three dots icon, then select Enable conditional responses.

Enabling                 conditional responses for a slot
Enabling conditional responses for a slot

Add a response for $monument_type:pyramid.

A conditional                 response for a monument type of pyramid
A conditional response for a monument type of pyramid

This conditional response is only displayed when the king asks to build a pyramid. It politely suggests to his majesty that he build something else.

With the conditional response defined in the first slot, you need to make the second slot conditional. There's no point asking where the king wants to build something if what he wants to build is a pyramid, so make the whole slot (not just its responses) conditional. To do that, click the gear icon next to the @monument_site slot to configure it. Click the three dots icon, then select Enable condition.

Making a slot                 conditional
Making a slot conditional

Now that you've made this slot conditional, define the condition that enables this slot. That condition, of course, is that the pharaoh wants to build something that isn't a pyramid.

Defining the                 condition for a conditional slot
Defining the condition for a conditional slot

Notice that if the king is building an obelisk, for example, your chatbot responds by asking where the obelisk should be built. The suggestions in the response match the values that are defined for the @monument_site entity.

The completed dialog works like this.

The king wants a pyramid
The king wants a pyramid

Inferring an entity's value based on intents and other entities

The next advanced technique is figuring out the value of an entity based on the intents and other entities Watson recognized. For the intent #start_a_war, your chatbot needs to know who the king wants to fight (@enemy) and where the battle will take place (@battle_site). Depending on the enemy, your chatbot might be able to figure out where the fight will go down. Here's the scenario.

Enemy (and synonyms)Battle site (and synonyms)
HittitesCanaan (Samaria) or Judea
LibyansLibya
NubiansNubia
Sherdan pirates (pirates)sea (ocean, Mediterranean)
SumeriansUr or Uruk
SyriansSyria

As you can see, your chatbot needs to ask where the battle will take place if the king wants to fight the Hittites or Sumerians. If the king wants to fight the Sherdan pirates, for example, your chatbot shouldn't ask the king about the battle site.

You'll handle this with a combination of techniques, including conditional slots, conditional responses, multiple responses, and editing JSON code. To start, click Customize at the top of the dialog to enable slots for this dialog and enable multiple responses.

Enabling                 multiple responses
Enabling multiple responses

You'll define those responses in a minute. For now, create three slots.

Multiple slots
Multiple slots

Notice that the first one is required and the second two are conditional. The first slot looks at the value for the @enemy and sets the value of @battle_site if possible. The second and third slots handle the cases of @enemy:Hittites and @enemy:Sumerians.

Click the gear icon next to the first slot to edit it. Click the three dots icon to enable conditional responses, then add five responses.

Multiple conditional responses
Multiple conditional responses

The strategy here is to return a different response for the four enemies that can only be fought in a single place. So for @enemy:(Sherdan pirates), the conditional response is "We shall go to $battle_site and send the Sherdan pirates to a watery grave." The obvious question here is how to set $battle_site automatically. You do that with JSON. Click the gear icon to customize the response, then click the three dots icon to open the JSON editor.

Opening the JSON editor
Opening the JSON editor

In the JSON editor, add an object called context.

The JSON editor
The JSON editor

Notice that the context object defines the value of the $battle_site variable to be sea. That means the response to the king will be "We shall go to sea and send the Sherdan pirates to a watery grave." (The code has to be valid JSON, of course. If there are syntax errors, the editor won't let you save the code. You're adding a new object, so make sure you add a comma along with the object.)

Handle the other three enemies similarly, adding a response that contains a variable and writing JSON code to set the $battle_site. Notice in the earlier figure that the last response has a condition of true. This is the default response (true, after all, is always true). You don't know the battle site, so just return the text "Woe be upon the @enemy!" This response fires for @enemy:Hittites and @enemy:Sumerians. You'll define conditional slots to handle each of those two enemies next.

The two conditional slots for the Hittites and Sumerians are straightforward. Here's how your chatbot figures out where the king wants to fight the Hittites.

A conditional slot to figure out where to fight the Hittites
A conditional slot to figure out where to fight the Hittites

The question gives the pharaoh the choices for this enemy. (You could hard code the value for $enemy, of course. It will always be Hittites if you're in this conditional slot.) The Watson Conversation service recognizes the battle site in the king's response. The king can type samaria, road trip to judea!, or canaan and your chatbot will know exactly where the battle will take place. (The @battle_site entity defines Samaria as a synonym for Canaan.)

The last piece of the puzzle is to define the multiple responses for the dialog itself. You already enabled multiple responses, so create them now.

Multiple responses for this dialog
Multiple responses for this dialog

For the Hittites and Sumerians, your chatbot returns a message that mentions the battle site and the enemy. "We shall march to Judea and vanquish the Hittites. Long live the king!," for example. For every other enemy, the default is to simply return "Long live the king!" because your chatbot has already stated the battle site and the enemy.

This very involved dialog works like this.

Time to fight some pirates
Time to fight some pirates

Your chatbot figured out the @battle_site from the @enemy. Notice that the only thing highlighted by Watson is the text that identified the enemy. Your chatbot takes it from there.

Here's a more complicated case.

War against the Hittites
War against the Hittites

Notice that for the king's answer the intent identified by Watson is Irrelevant. This simply means that Watson can't infer any intent from the single word Canaan. That's not a problem because your chatbot already knows the intent.

This is about as complicated as a single dialog can get. Take a deep breath. You've only got one more advanced technique to cover, and it's easy compared to this one.

Resetting the chatbot's state

The final advanced technique is using JSON to reset the state of the chatbot. If the king types "start over," your chatbot needs to reset all of the entities to null. That's easily done. In the Start Over dialog, simply add a context object in the JSON editor.

Resetting the chatbot's state
Resetting the chatbot's state

You'll likely find the start over technique useful in all of your chatbots. It's an easy way to reset everything and, well, start over. Here's how your completed dialog looks.

Starting over
Starting over

Deploying your chatbot as part of a stand-alone application

At this point, you've built a complete chatbot that uses complex logic to respond intelligently to the pharaoh's wishes. But so far you've only run it inside the browser using the tooling for the Watson Assistant service. Now you'll implement a stand-alone chatbot application.

To keep it simple, you'll start with an existing sample application and replace its chatbot with your own. With that done, you can run the application and you can deploy your chatbot to the web. To get started, clone the GitHub repo at https://github.com/watson-developer-cloud/conversation-simple.

Importing the github repo for the simple chatbot application
Importing the github repo for the simple chatbot application

At a command line, type the following commands:

git clone https://github.com/watson-developer-cloud/conversation-simple.git
cd conversation-simple

Many thanks to the Watson Assistant team for developing, sharing, and maintaining this app.

The README.md file has lots of instructions for creating a Conversation service and other details, but you've handled those already. The next thing you need to do is set up the credentials for your chatbot and the Conversation service that hosts it. Copy the .env.example file to .env. The .env file looks like this.

# Environment variables
WORKSPACE_ID=<workspace-id>
CONVERSATION_USERNAME=<conversation-username>
CONVERSATION_PASSWORD=<conversation-password>

You need to fill in these three values before the code will work. To get the WORKSPACE_ID, go back to the Conversation workspace, click the three dots icon on the tile for your chatbot, and select View details.

Viewing the details of your chatbot

The tile shows you the workspace ID.

The workspace ID for your chatbot

Click the copy icon to put the value on the clipboard, then paste it into the .env file.

Now it's time to get the CONVERSATION_USERNAME and CONVERSATION_PASSWORD values from the Conversation service. Go to the dashboard at console.bluemix.net, find your Conversation service in the list, and click it to open the service's management page. Click the Service credentials tab on the left.

The service credentials tab
The service credentials tab

You should see a list of credentials. If you don't have any credentials, click New credential to create one. Next, click View credentials to see the values you need.

The values for a particular credential
The values for a particular credential

Copy and paste those two values into the .env file, save it, and your chatbot application is ready to go! Go to the command line and type npm install to install the NPM packages your app requires, then type npm start to run the app.

Running the standalone chatbot app
Running the standalone chatbot app

Your app is running on port 3000, so go to your browser and open localhost:3000 to see the magic happen.

The standalone chatbot app
The standalone chatbot app

The UI on the left is a straightforward conversation between the king and your chatbot. The panel on the right shows the JSON data that represents the input received by your chatbot and the intents and entities that Watson recognized in that input.

Taking it one step further

This app is running on your local machine. If you'd like to deploy your app as a Docker container running inside a Kubernetes cluster, see the following developerWorks Mailbag videos:

The first video shows you how to build a Docker image and create a Docker container from it, the second shows you how to create a Kubernetes cluster and deploy your Docker image inside the cluster, and the third shows you how to manage credentials inside the cluster. If you follow those examples, you'll have a sophisticated chatbot running in a state-of-the-art container environment, to the admiration of your friends and the consternation of your enemies.

Summary

You've come a long way, but now you know how to build a chatbot that uses logic to handle complicated situations elegantly, and you know how to deploy that chatbot inside a stand-alone application. You have all the skills you need to create chatbots that interact with your users and make the world a better place. Good luck!

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 build a configurable, retail-ready chatbot. You can also access the IBM Bot Asset Exchange, a community-driven chatbot development hub, to see bots that others have created and use them as a foundation for your own chatbot.


Downloadable resources


Comments

Sign in or register to add and subscribe to comments.

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Cognitive computing
ArticleID=1058371
ArticleTitle=Build a chatbot in the IBM Cloud
publish-date=03042018