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 destination city and departure date 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

4 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.

Join The Discussion

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