This article shows how to build chatbots that support complex dialog interactions using Watson Conversation service. As an illustration, we will build a chat-bot for booking a one-way flight ticket by gathering user information such as departure city, destination city, preferred date and time of departure.

The chat-bot would support various ways in which a user could interact with it, For example:

  • Can you book me a flight from Bangalore to Delhi starting tomorrow morning?

Has all the required information: FromCity, ToCity, DepartureDate, DepartureTime.

  • I want to go to Mumbai next Wednesday.

Has information on destination city and departure date. Gather information on departure city and departure time through subsequent questions to user.

  • Would you please book me a flight from Bangalore to Paris?

Has information on departure city and destination city. Gather information on date and time of departure through subsequent questions to user.

  • Book a flight for me

Gather information on departure date, time and city along with destination city through subsequent questions to user.

We assume that you are already familiar with building basic dailogs using Watson Conversation service. If not, please go through the getting started guide of Watson Conversation service.

Intents and Entities

For flight booking chatbot, let us create an intent #FlightBooking with examples as below:

Can you book a flight
I want to book a flight
Book a flight
Book a plane
I want to go to
I want to go from
I want to travel
I would prefer to travel to

Please note that Watson Conversation service uses the above examples to train its Natural Language Processing (NLP) modules and would be able to handle other possible ways in which the users could express their flight booking intent.

The next step in building our chatbot is to add entities to capture information on FromCity, ToCity, Departure Date and Time from user’s interactions with chatbot. Watson Conversation gives in-built entities to handle date and time. To use this, under Entities tab, click on System Entities and switch on @sys-date and @sys-time.

Then switch back to “My entities” and create new entities @City, @FromCity and @ToCity as below:

City,Bangalore
City,Delhi
City,Mumbai
City,Stockholm
City,Paris
...
FromCity,from Bangalore
FromCity,from Delhi
FromCity,from Mumbai
FromCity,from Stockholm
FromCity,from Paris
...
ToCity,to Bangalore
ToCity,to Delhi
ToCity,to Mumbai
ToCity,to Stockholm
ToCity,to Paris
...

Instead of manually creating entities, Watson Conversation tool allows us to import the entities from a CSV file. One can programmatically create a CSV file containing entity information on all possible cities and then import it into Watson Conversation service.

Simple dialog flow

The final and important step in building our chatbot, is to create the dialog flow.

Let us see how to create the dialog for a simple conversation flow as below:

Bot: Hello, how can I help you?
User: I want to book a flight
Bot: Sure, I can help in booking a flight. Which city do you want to travel to?
User: Bangalore
Bot: OK, I got that you want to travel to Bangalore. Which city would you be starting from?
User: Stockholm
Bot: OK, I can help in booking a flight from Stockholm to Bangalore. When would you like to depart?
User: Apr 20
Bot: OK, I got that you want me to book a flight from Stockholm to Bangalore on April 20. What time would you like to depart?
User: 2pm
Bot: OK, I am searching for flights from Stockholm to Bangalore on April 20 starting at 2 PM.

The simple dialog flow above can easily be implemented using following logic:

Watson Conversation tool further simplifies the creation of the dialog flow. For example, the equivalent nodes in Watson Conversation Dialog for following flowchart blocks is shown below:

  • Flowchart blocks:

  • Equivalent nodes in Watson Conversation Dialog:

However, the above dialog flow cannot handle other possible ways in which the users could interact with our chat-bot, like

  • Can you book me a flight from Bangalore to Delhi starting tomorrow morning
  • Would you please book me a flight from Bangalore to Paris
  • I want to go to Mumbai next Wednesday

This needs the design of a more complex dialog flow.

Complex Dialog flows

A complex dialog flow that supports all the above interaction patterns is shown in the flowcharts below:

Below is a snippet from the Watson Conversation dialog that implements the above complex flow:

Reformatting @sys-date and @sys-time and extracting only the city portion from ToCity and FromCity

By default @sys-date returns date in yyyy-MM-dd format and @sys-time returns time in HH:mm:ss format. However we can use .reformatDateTime(String format) method to parse date and time into required format. The snippet below shows an example where input date is formatted to “month day” format (ex. Apr 20) and time is formatted to “hours:minutes am/pm” format (ex. 2 PM).

The FromCity and ToCity entities, that we have defined for our complex dialog flow, have prefixes “from ” and “to “. When saving the entity values to context, we want to ignore those prefixes and extract only the city names. This can easily be achieved by using the function String.substring(int beginIndex, int endIndex) method as shown below:

  "context": {
    "Date": "<?@sys-date?>",
    "Time": "<?@sys-time?>",
    "FormattedDate": "<?@sys-date.reformatDateTime('MMMMM dd')?>",
    "FormattedTime": "<?@sys-time.reformatDateTime('h:mm aaa').replaceAll(':00', '')?>",
    "ToCity": "<? @ToCity.substring(3, @ToCity.length()) ?>",
    "FromCity": "<? @FromCity.substring(5, @FromCity.length()) ?>"
  },

Writing Dialog conditions based on context variables

For example, the condition “if context has FromCity, ToCity, Date and Time” can be implemented as below:

The checks based on context variables are important as they allow the conversation to continue from the last interaction point. For example, suppose the user mentions ToCity and Departure Date in the first interaction (ex: “I want to go to Mumbai next Wednesday”), you would then want to ask the user the city from which they will be departing. If the user makes a mistake in answering that (ex: “today afternoon), then, instead of resetting the conversation and starting from beginning, the checks based on context variables allow the conversation to continue from the last interaction point (i.e. ask again “Which city would you be starting from?”) as shown below:

Bot: Hello, how can I help you?
User: I want to go to Mumbai next Wednesday
Bot: I can book a flight to Mumbai starting on April 12. Which city would you be starting from?
User: today afternoon
Bot: Which city would you be starting from?
User: Chennai
Bot: OK, I got that you want to book a flight from Chennai to Mumbai starting on April 19. What time do you prefer to leave?
...

Demo

The Watson Conversation workspace that implements above complex dialog flows for flight booking can be downloaded from here.

Examples of complex dialog scenarios handled by the above Watson Conversation workspace:

  • Scenario 1: User gives all information (FromCity, ToCity, Departure Date and Time) in one go
Bot: Hello, how can I help you?
User: Can you book me a flight from Bangalore to Delhi starting tomorrow morning
Bot: OK, I am searching for flights from Bangalore to Delhi on April 09 starting at 9 AM.
  • Scenario 2: User provides information on FromCity, ToCity and Departure Date in the first interaction
Bot: Hello, how can I help you?
User: I am looking for a flight from Stockholm to Copenhagen tomorrow
Bot: Do you want to book a flight from Stockholm to Copenhagen on April 09?
User: Yes
Bot: What time do you want to leave?
User: 10am
Bot: OK, I am searching for flights from Stockholm to Copenhagen on April 09 starting at 10 AM.
  • Scenario 3: User mentions only FromCity and ToCity in the first interaction
Bot: Hello, how can I help you?
User: Would you please book me a flight from Bangalore to Paris
Bot: Sure, I can book a flight from Bangalore to Paris. When would you like to depart?
User: May 10th
Bot: OK, I got that you want me to book a flight from Bangalore to Paris on May 10. What time would you like to depart?
User: morning
Bot: OK, I am searching for flights from Bangalore to Paris on May 10 starting at 9 AM.
  • Scenario 4: User mentions ToCity and Departure Date in the first interaction
Bot: Hello, how can I help you?
User: I want to go to Mumbai next Wednesday
Bot: I can book a flight to Mumbai starting on April 12. Which city would you be starting from?
User: Chennai
Bot: OK, I got that you want to book a flight from Chennai to Mumbai starting on April 12. What time do you prefer to leave?
User: evening
Bot: OK, I am searching for flights from Chennai to Mumbai on April 12 starting at 6 PM.

Chatbot Application

Following is a command line Java application that interacts with Watson Conversation service based on the tutorial available here.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.List;
import java.util.Map;

import com.ibm.watson.developer_cloud.conversation.v1.ConversationService;
import com.ibm.watson.developer_cloud.conversation.v1.model.MessageRequest;
import com.ibm.watson.developer_cloud.conversation.v1.model.MessageResponse;

public class FlightBookingDemo {
    public static String WORKSPACE_ID = "<your Watson Conversation workspace id>";

    public static final String FROM_CITY_KEY = "FromCity";
    public static final String TO_CITY_KEY = "ToCity";
    public static final String DATE_KEY = "Date";
    public static final String TIME_KEY = "Time";

    public static void main(String[] args) throws Exception {
        ConversationService service = new ConversationService(ConversationService.VERSION_DATE_2016_09_20);
        service.setUsernameAndPassword("<your Watson Conversation username>", "your Watson Conversation password");

        String messageFromUser = "";
        Map<String, Object> context = null;
        boolean endConversation = false;
        do {
            MessageRequest request = new MessageRequest.Builder().inputText(messageFromUser).context(context).build();
            MessageResponse response = service.message(WORKSPACE_ID, request).execute();
            context = response.getContext();
            Map<String, Object> output = response.getOutput();
            List<String> responseText = (List<String>) output.get("text");
            if (responseText.size() > 0) {
                System.out.println("Bot: " + responseText.get(0));
            }
            if (output.get("action") != null) {
                String actionString = (String) output.get("action");
                if ("bookFlight".equalsIgnoreCase(actionString)) {
                    bookFlight(context);
                    context = null;
                    endConversation = true;
                } else if ("end_conversation".equalsIgnoreCase(actionString)) {
                    endConversation = true;
                }
            }
            if (!endConversation) {
                messageFromUser = getUserInput();
            }
        } while (!endConversation);
        String exitMessage = "Exiting program. Have a nice day!";
        System.out.println(exitMessage);
    }

    private static void bookFlight(Map<String, Object> context) throws InterruptedException {
        String fromCity = (String) context.get(FROM_CITY_KEY);
        String toCity = (String) context.get(TO_CITY_KEY);
        String departureDate = (String) context.get(DATE_KEY);
        String departureTiime = (String) context.get(TIME_KEY);
        String responseText = "(Calling backend API to search for flights from " + fromCity + " to " + toCity
                + " on " + departureDate + " starting at " + departureTiime + ")";
        System.out.println(responseText);
    }

    static String getUserInput() {
        System.out.print("User: ");
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        try {
            return br.readLine().trim();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "";
    }
}

Following is a simple web-application chatbot built using the Node.js conversation sample application of Watson Conversation service:

http://flight-booking-demo.mybluemix.net/

References

23 comments on"Building Complex Dialogs using Watson Conversation"

  1. Hi, I really enjoyed your article. Congratulations!

    I tried to do this @sys-date.reformatDateTime(‘MMMMM dd’) and it was formatted like this : (‘MMMMM dd’) 2017-04-21 .
    I need you to stay like this 21-04-2017.

  2. Thanks Shiva Kumar H R for the tutuorial. It helped me a lot. Can you do a favour of uploading all dialogues and their mapping?

  3. Abhijit Bamishte August 03, 2017

    In the example “I want to go to Mumbai next Wednesday.”, the departure city is missing. So the sentence should be “Gather information on DEPARTURE city and departure date through subsequent questions to user.” Please correct.

  4. We are a group of volunteers and opening a new scheme in our community.
    Your site offered us with valuable information to work on. You
    have done an impressive job and our whole community will be thankful to you.

  5. Great job with this article/tutorial! If I wanted to have a yes and no confirmation child node from the parent node entitled,” Input has FromCity ToCity Date and Time,” would you recommend a “jump” from the context node entitled, “Context has FromCity ToCity Date and Time” to the confirmation child nodes. That way, if the user enters “maybe” (instead of yes or no) when asked to confirm their booking request, then we can redirect the discussion back to the confirm given that we have everything we need to make a booking? Thanks in advance.

  6. Hi shiva ,how can i integrate the watson conversation service with the buisness application i am using? Can i fetch some data from the application and use it show in the watson conversation

    • Shiva Kumar H R August 24, 2017

      Hi Ankush,
      Please note that Watson conversation is a service meant to be used within your business application. (The UI that Watson Conversation tooling gives is to ease development and testing of dialogs and the tooling UI is not meant for reuse in your business application.) Hence rather than thinking of fetching data from your business application and showing it in Watson conversation, you need to think of the reverse way i.e. call Watson conversation from inside of your business application and show appropriate business data to the user based on their natural language interactions/questions. For details please refer https://console.bluemix.net/docs/services/conversation/develop-app.html as well as the Java Chatbot Application given in this article.

      • Hi Shiva,
        Can we use the watson conversation service to update any action in my application. For e.g from watson conversation service I want to update the status of workorder in my business application. what i need to do for this

  7. Sai Sumanth August 24, 2017

    Hi shiva, thanx for the tutorial. I have a question.The values like FromCity and ToCity are pre defined in entities of FromCity and ToCity. What if i want to store any value typed by the user. For example if bots ask to “enter your the name of person”, user will type “Shiva” (there is no entity whose value is “Shiva”). now we want to store “Shiva” value in some variable. how can it be done??

  8. Fantastic Website. Really enjoyed reading.

  9. Thanx shiva,
    It really helped me. I Have another doubt regarding on conditional statement . First thing is i want to take the input from the user and store it as integer. and then give conditions on those integers like > and < conditions . can i do that watson conversation directly ??

  10. Hi Shiva, Thanks for this tutorial. I was trying to create a similar POC for the past few days – that is how I came across your awesome tutorial . But I’m stuck in a point where I need to give a response for the user based on my knowledge repository – similar to the flight search we are doing based on the user inputs. Even I have a question on this (https://stackoverflow.com/questions/46655346/android-application-powered-with-ibm-watson-api-invoke-custom-external-web-api) in stack overflow. Can you please give me some pointers to solve this issue. Basically I want to send back the the search results to the conversion service so that I can present a formatted message for the user.

    Thanks,
    Kallada

Join The Discussion

Your email address will not be published. Required fields are marked *