Build A Chatbot with Rasa NLU — Part One
Part 1 — Installation, Education, and Model Training
Since writing this tutorial we’ve released a complete open-source chatbot platform — built on Rasa NLU — called Articulate. Be sure to check it out!
Getting Started
If you’re in the market to build a chatbot then there’s a chance you’ve already come across Rasa NLU. If not then it’s best summarized as an Open source language understanding for bots. Rasa puts a programmer friendly interface on top of several other machine learning libraries, and provides complex functionality, but packaged with ease of use in mind. The team at Rasa.ai has put together an amazing product, but you’ll need more than just NLU to make a chatbot. This tutorial will walk you through one potential path to pull it all together.
This post is the first in a multi-part series tutorial, and will take you through the steps to build a complete chatbot and integrate it with Slack and Twilio.
- Part 1 — Installation, Education, and Model Training
- Part 2 — Backend Fulfillment using Node-Red
- Part 3 — Integrating our bot with Slack using Node-RED
Specifically we’re going to use Rasa NLU to turn spoken/typed text into a computer readable object.We’re going to use Node-RED to take that object and follow it up with specific actions. This includes making API calls for fulfillment. Once we have the response from the API we will format in a readable way and return it to the user.
1. Setup
We’ve packaged everything up for you quite neatly in this github repository. To follow along you will need the following tools installed:
- Git — If you don’t have or want this installed, then just download and extract the repo linked above. If you’re on a Mac you are likely to already have this installed. On Windows you’ll need to install this.
- Docker — We’re going to launch multiple services and docker is an easy way to wrap all of these together.
Once you’ve got those installed, then we’re ready to get started.
☞ Open a terminal or command prompt
First, open a terminal or command prompt and enter the below commands.
git clone https://github.com/samtecspg/rasa-tutorials.git
cd rasa-tutorials
docker-compose up
Docker will download the necessary components and start them. Once the downloading and startup is finished, we need to do a quick test to make sure that everything is working as expected.
☞ Click this link to test that Rasa NLU is working
Or copy and paste this link into your browser. http://localhost:5000 if you get a message like the below then everything is working.
hello from Rasa NLU: 0.10.0a2
If all looks right, then you’re ready to continue; if not then join the conversation on the Rasa gitter and I’ll see if I can help get you going.
The end goal here is a chatbot that does a few silly things like look up Chuck Norris facts and dish out questionably good advice. In subsequent tutorials we’ll plug this into Slack and Twilio so that my and your whole team can enjoy it. For this part of the tutorial we are going to be training Rasa NLU to gather intents and entities so that we can pass them to our fulfillment services.
2. Quick NLU Education
Intents and entities are two things we can gather to help computers understand the meaning of the text. Given the example of, “I want to order a cheese pizza”, the intent is fairly clear: order pizza. An example of an entity would be cheese, which is a topping choice. If you’re familiar with functions then think of intents as the function name and entities as it’s parameters:
function orderPizza(toppings, crust) {
... Implement code to order pizza
}
But this isn’t just some sort of a lookup, we’re going to train a machine learning model (SVM for Intent classification and CRF for entity classification if you want to know) using machine learning that can generalize how users might ask a question. To do this we’re going to create a training data set with several examples and from those examples Rasa will learn how to do the rest.
This training data set looks like this, just with more examples.
{
"rasa_nlu_data": {
"common_examples": [
{
"text": "I want to order a cheese pizza.",
"intent": "order-pizza
"entities": [
{
"start": 18,
"end": 24,
"value": "cheese",
"entity": "topping"
}
]
}
]
}
}
Inside of common examples we see that we give an example of how a user would ask to order a pizza which is called the text. We label the intent, and then we specify any entities found in the sentence.
Rather than just modifying a bunch of JSON to create our training data set we’re going to use a tool produced by a member of the Rasa community and adopted officially by Rasa.
☞ Click here to open the Rasa NLU trainer
Or copy and paste this link into a browser. https://rasahq.github.io/rasa-nlu-trainer/ (Image 1)
When the page loads you will see a bunch of examples have already been loaded for you. This is the default training data that Rasa uses. We’re quickly going to replace this, but first let’s check it out.
The main screen contains a list of training examples, better known as ‘utterances’. The Intent column is essentially the label for our training data. While the Text column is the example we want the bot to be able to generalize from.
☞ Inspect entity definition in the Rasa NLU trainer
Click the + next to the restaurant_search example with the text of show me a mexican place in the centre (Image 2)
This is a great example of how we train entities. Any word or group of words can be highlighted and as a particular entity by clicking the purple button that shows up when you highlight a word.
In this example mexican has been labeled as a cuisine type and centre has been labeled as a location.
It’s not obvious from this view, but we also have the option of changing the value that an entity is mapped to. For example, we could change the value from ‘centre’ to ‘central’ and that would be trained as a synonym. Using this approach common ways of referring to a single thing can be consolidated to make it easier for a computer to act on.
But since we’re not going to be searching for restaurants we need to create or load in a different training set.
☞ Click the clear button to start with a clean slate
Click on the Clear button in the top right hand corner to remove all of the training examples. (Image 3)
You should now have a clean slate. Now is a good time to spend some time getting to know this interface, just make sure you clear before you continue.
☞ Upload your training data .json file
Click the Click to Upload and find the rasa-tutorial-training-data.json file, which is located in the folder that you cloned or downloaded from Github in the setup step above.(Image 3)
I’ve got about 10 examples in each of our two primary intents. I’ve also added greet and goodbye.
Take a look at everything that I’ve entered and maybe add a few more examples yourself.
☞ Add a new example into the trainer
Click the purple button in the top right hand corner Add new example (Image 3) Type a new example: “Is there a Chuck Norris joke about school?”(Image 4) Click in the intent field and label it with an intent, in this case we’re using a chuckNorris example. (Image 4)
☞ Highlight the entity in your example
Highlight the word school in the text box and click the purple button add an entity for “school” then label it as a query entity. (Image 4) Click Add to finish adding a new example. (Image 4)
Once you’ve finished adding new examples and seeing how they are added let’s go ahead and take this training data and use it to train a new model.
The first thing we need to do is download the actual json file.
☞ Download your new training data file
In the upper right hand corner click the purple Download button. (Image 3) Save the file as my-data.json in the same folder where the original training data was.
The next command assumes that you’ve navigated in the terminal or command prompt to the same folder where you saved your training data.
☞ Execute the command below
From a new command line or terminal execute the below command. Make sure you use the correct path and file name from above. The path and filename of your file go after the @ sign and wrapped in quotes. This shouldn’t take too long, maybe 15–30 seconds.
curl -X POST -d "@./my-data.json" "localhost:5000/train?name=rasaTutorialBot"
This command takes the json file and uses it to make an HTTP POST request to Rasa’s API. Also notice that in the url we are providing a name for our new model rasaTutorialBot.
Whenever it completes it will return something like this below. If it doesn’t return or doesn’t look like this message then something else has gone wrong. Jump into the Gitter or message me and I’ll try to help you out.
{
"info": "new model trained: rasaTutorialBot"
}
Okay great so now that we have a trained model it’s time to take it for a test drive.
☞ Execute the below command
This command is asking Rasa to /parse
the phrase I want to hear a chuck norris joke about school.
curl --request POST \
--url http://localhost:5000/parse \
--header 'content-type: application/json' \
--data '{
"q": "I want to hear a chuck norris joke about school",
"model": "rasaTutorialBot"
}' | python -mjson.tool
Again this can take 30–45 seconds depending on your computer. During this time our trained model is loaded into memory. This is a one time delay and subsequent requests should be faster.
If everything goes to plan then this should be the payload you receive back:
{
"entities": [
{
"start": 41,
"extractor": "ner_crf",
"end": 47,
"value": "school",
"entity": "query"
}
],
"intent": {
"confidence": 0.6952268632974917,
"name": "chuckNorris"
},
"text": "I want to hear a chuck norris joke about school",
"intent_ranking": [
{
"confidence": 0.6952268632974917,
"name": "chuckNorris"
},
{
"confidence": 0.16440379749679015,
"name": "greet"
},
{
"confidence": 0.1403693392057183,
"name": "advice"
}
]
}
We’ll actually use this payload to generate responses in the next section of this tutorial, but for now here is a quick rundown:
- entities — These are the entities Rasa found in the sentence we gave it. Notice it found school, even though that wasn’t one of the examples we provided. This gives you an idea of the generalization that happens.
- intent — This is the intent that had the highest confidence. Don’t worry that the confidence was only 70%, if you’re model accurately parses the correct intent each time then it is working.
- text — This is just returning the sentence that was provided.
- intent_ranking — This shows you all of the intents in your model and the confidence value associated with each of them. This is probably more important than the sheer confidence number. How much margin do you have between the correct intent and the next closest. We have > 50% so we’re doing fine.
3. Recap
I encourage you to keep trying different ways of asking for a Chuck Norris joke or some great advice. Get a feel for how much Rasa has generalized based on the relatively few ways we provided in the training data.
Try to see how many different ways you can ask for things without breaking our model. For example
curl --request POST \
--url http://localhost:5000/parse \
--header 'content-type: application/json' \
--data '{
"q": "I want a joke about Mr. Norris.",
"model": "rasaTutorialBot"
}' | python -mjson.tool
is successful even though we don’t have an example similar to it in our training data. See if you can come up with a way to ask for Chuck Norris jokes or advice that fails to be matched as the correct intent and entities.
Just as a quick recap, here’s what we did.
Step 1 — We downloaded and started up Rasa NLU using git and docker.
Step 2 — We created some training data using the online Rasa NLU Trainer.
Step 3 — We used that training data to create a new model using Rasa’s HTTP API.
In the next tutorial we’ll use Node-RED to connect Rasa NLU with the backend APIs to create a fulfillment service.
If you had any trouble message me or leave a comment below. You can also join the Rasa NLU gitter and you’re sure to find some help there.