Build a chatbot in the IBM Cloud
Easily build a chatbot with Watson technologies
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:
- Create an instance of the Watson Assistant service.
- Learn the basics of chatbots, including intents, entities, and dialogs.
- Create a simple chatbot.
- Use more advanced techniques in your chatbot.
- 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:
- 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.
- 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.
- Click Create to create your new Conversation service.
- Click Launch tool to start building your chatbot.
Notice that the Conversation service is named dwtv-convo instead of the far less memorable Conversation-n1. You'll see 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.
- Click Create to create a new
workspace. Complete the details like this:
- Name: Royal Valet
- Description: Rameses II's personal valet chatbot
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.
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.
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.
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.
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.
Notice that "food truck rodeo" is a synonym for "food chariot rodeo."
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 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.
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.
Name the dialog "Have a feast" and set the dialog to fire when the system
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.
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.
As you can see, if the intent is
#have_a_feast, the Watson
Conversation service checks to see whether the
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.
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
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.
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!"
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.
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"
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
We'll use conditional entities, conditional responses, multiple responses, and the JSON source of dialogs to make the magic happen.
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.
Select the file from your machine, make sure the Import Everything radio button is checked, then click Import.
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:
|have a feast|
how about a food truck rodeo?
ring the dinner bell
sound the feasting horn
|let's build something|
go to battle
I'm really annoyed with the Sumerians lately.
start a war
|I'm done. |
It's a plan.
Make it so.
|give me a hand here |
help me out here
how do I get started?
what do I do next?
With those intents defined, add the following entities:
|Entity name||Values (and synonyms)|
|Canaan (Samaria) |
sea (ocean, Mediterranean)
Sherdan pirates (pirates)
|food chariot rodeo (food truck rodeo) |
pot luck (potlach)
|Abu Simbel |
|alter (alter) |
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
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
- Enable slots for this dialog.
- 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.
- Define a conditional slot. If the king wants to build something that
isn't a pyramid, the chatbot processes the slot for
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_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
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.
Add a response for
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.
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.
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
The completed dialog works like this.
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)|
|Hittites||Canaan (Samaria) or Judea|
|Sherdan pirates (pirates)||sea (ocean, Mediterranean)|
|Sumerians||Ur or Uruk|
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.
You'll define those responses in a minute. For now, create three 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
@battle_site if possible. The second and third slots
handle the cases of
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.
The strategy here is to return a different response for the four enemies
that can only be fought in a single place. So for
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
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.
In the JSON editor, add an object called
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 (
all, is always
true). You don't know the battle site, so just
return the text "Woe be upon the
@enemy!" This response fires
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.
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
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
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.
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.
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.
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.
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.
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.
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
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
WORKSPACE_ID, go back to the Conversation workspace,
click the three dots icon on the tile for your chatbot, and select
The tile shows you the workspace ID.
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_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
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.
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,
npm start to run the app.
Your app is running on port 3000, so go to your browser and open localhost:3000 to see the magic happen.
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:
- Using Docker images and containers on your machine
- Building a Kubernetes cluster in the IBM Cloud
- Using Kubernetes secrets to manage credentials
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.
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.