Building a multi-lingual chatbot using Rasa and Chatfuel

Souvik Ghosh
8 min readSep 4, 2018

--

I have been a great enthusiast of the Rasa stack and their ability to demystify Conversational AI for many of us who have started out venturing into Machine learning. Chatbots personally for me was a great place to start my adventure as being in the retail banking industry there are many relatable cases of using such great research and seeing them into action.

But yes, Rasa is an open-source chatbot framework that breaks down the building blocks of how exactly a chatbot works so with this there are also some shortcomings, one of which I have noticed many struggle with is scaling. There are many aspect of scaling, and this tutorial of sorts, i am going to cover the topic of a multi bot ecosystem.

If you live in a country where you could possibly find multiple languages spoken officially, it is understandable why there is such a need of chatbots existing in more than one language. Working in Belgium for past few years certainly makes me understand this beautiful world of multilingual identity. So here building chatbots is taking it up a notch.

The architecture is going to be quite simple for this tutorial, I will be using the existing Rasa APIs and I will wrap the entire stack with Docker and use ngrok to connect it to Chatfuel.

Architecture View

The schema here is quite simple. Chatfuel provides a straight in connector for Facebook messenger, this is where you will hook your Facebook page to Chatfuel. Then using ngrok to open up my localhost, I will run up two Rasa servers in each language and behind a Redis cache, keeping track of the state of both containers

Why Chatfuel?

Well for simplicity’s sake, Chatfuel comes with a bunch of features one of which is providing a messenger channel to receive messages from facebook along with other attributes including what we need, user’s profile language. It also gives you a nice get started button so you can provide a nice welcome message for the user. Chatfuel also provides a backend integration webhook namely JSON API to pass the user message to the Rasa servers that i am running in my backend. Goal is to interpret the message from Chatfuel and provide a response back

Step 1 — Create a Chatfuel bot

Go to chatfuel.com, you can use any other interface that allows you to connect to a particular channel. here my goal is to route message to the right bot in the backend and i am using Chatfuel as a dispatcher. Chatfuel comes with an easy dashboard

Go Ahead and Create a bot.

Use the blank bot template. There is a lot you could already do with Chatfuel, if you want a simple chatbot with No or Basic NLU but my goal here is to demonstrate how do we orchestrate a multilingual chatbot.

As you can see, there are two blocks already provided

Welcome message and Default Answer.

We will add two blocks for Welcome message in French and English

Now, we will add a card in the Welcome Message block, where we will route the user to the right Welcome message given the user’s facebook profile language.

It is important to provide a good welcome message to indicate what can you help the user with. In my case, since i am from banking domain, I will take an example of what happens when my is card is lost. My goal is not to validate a chatbot case, I am sure you have thought of many potential use-cases for chatbots already.

Once I have the welcome message set-up, Let’s go to the Default Answer. Here we will add two default answer block, one for French and one for English. Default answer is basically taking every message the user types and forwarding it to our Rasa server in the locale of the user as defined by us (en_US and fr_FR) , based on this we will call two of our Rasa servers running French and English models respectively

Now in each of the block, you need to provide two cards, first one is to save the user input into a custom attribute “query” which is needed by the Rasa server

Next we will use the JSON API card of chatfuel to pass the query to our server

We will be using the /respond endpoint to simplify things. This means that the action will be executed at Rasa side. you can choose to use /parse and /continue and execute the templates at Chatfuel since this gives you a lot of flexibility to connect to several Integrations

Here are some integrations from Chatfuel

Step 2 : Configuring the backend

First things first, Let’s add some training data and train our NLU plus Core model. I won’t need to explain too much of it here.

You need two models to be built

A. NLU model — here i will be using the tensorflow embedding pipeline to train my NLU model, i am only doing intent classification in this case

B. Core model — having a simple story in two languages and getting replies back for each

Once the models are trained, it is time to test the API in local. I will use the /respond API to see if i receive a response and everything is running

You will find all the code in this Github repo

I test this using Postman, best way to test out an API.

POST /conversations/1/respond HTTP/1.1
Host: localhost:5005
Content-Type: application/json
Cache-Control: no-cache
Postman-Token: a7b54456-f12a-51a8-26c3-93ff3eb65a97
{
"query":"i have lost my debit card"
}

and here’s what i got back

[
{
"recipient_id": "1",
"text": "So you have lost your debit card. Please contact 080012345 to have it blocked immediately"
}
]

I tried the same in french

POST /conversations/1/respond HTTP/1.1
Host: localhost:5006
Content-Type: application/json
Cache-Control: no-cache
Postman-Token: e8f4c8b1-bc2e-6ecc-adeb-4b4a3f584a7c
{
"query":"j'ai perdu mon carte de credit"
}

here’s the reply in french

[
{
"recipient_id": "1",
"text": "ok,vous avez perdu votre carte de credit. Veuiilez trouvez notre numero 088000 pour blocker votre carte"
}
]

Notice for each of these requests, the localhost is different. I have used docker-compose to stitch everything up.

Step 3: Exposing the server for Chatfuel

Now, there are several ways to expose your rasa core servers. I have ngrok , keep in mind ngrok only allows one host to be exposed at one moment unless you have the pro version, but here i am just testing if it works, in reality you will need them deployed in some cluster, Heroku or Kubernetes or any VPS.

Also note, i am using the JSON API of chatfuel and sending a request via GET, you can also choose to send a POST request, however since the content-type coming from chatfuel is of form type, you will need to parse it at your server side before calling rasa core’s agent.handle_message().

As you have exposed your connection via ngrok, we will place it in the JSON API like this

I have used the messenger-id as the unique user-id for rasa.

Time to test

Now i will have to change my language setting in user’s profile to french in order to chat in french. you can have other ways to do this as well

Here’s the french version

Conclusion

The idea is really quite simple, i demonstrated with Chatfuel but you can consider any routing middleware, could be an API gateway where you have some transformation logic.

There are many ways, one can detect languages, the simplest of all specially when it comes to Facebook is user’s profile language. There is a reason why people tend to chat in the language they want and since most people use facebook absolutely daily, their profile language is what suits them the most. However, it is true that you can’t really build a bot in every language but you can go local to an extent. Say you are in France and your bot is serving a restaurant in the middle of Paris and there is a portion of your users who are coming from all over the world. You can build a multi-lingual bot for french users whose user profile is in FR and for the rest in EN. This helps local get a service more catered to them while does not block away your other users who are visiting the country.

More and more conversational services will be offered in localised languages and it is important to understand how to technically orchestrate them.

Side note : Redis Tracker

You have seen that in the beginning, i have added a Redis queque, well first of all Rasa allows you to store the conversational context( tracker ) in an externalised store and there is already a Redis integration. You will find information about the trackers here

Why it is important here, in some cases where some of us polyglots would like to switch conversations in the middle , you will probably use some lang-detect mechanism to figure out which language the user is writing, it is important for the two bot system that they are both in sync with the context coming from the same user. Meaning if a user says — I am currently in Paris and switch to next question — trouve-moi un petit cafe mais pas trop cher. You have to make sure he is still talking about Paris. a shared tracker_store helps you keep context in between bots.

However this applies even to multi-domain bots as well. if you would like to improve accuracy in a vast domain like FAQ, you will probably like many bots deployed however they should all share the same state for the same user.

Code is available at Github

More where this came from

This story is published in Noteworthy, where thousands come every day to learn about the people & ideas shaping the products we love.

Follow our publication to see more product & design stories featured by the Journal team.

--

--