Tuesday, December 13, 2016

Chatbots and Oracle Cloud Services

Thanks to Oracle A-Team, I had a chance to work with Chatbots.
3 pure NodeJS applications, on couple of Oracle Cloud platforms and Facebook messenger, and my chatbot was running.

Let me explain, the architecture a bit. To start with, following is the simple representation of how it works.

Message Platform Server : Is a NodeJS application, deployed on Oracle Application Container cloud, acts as a channel between Facebook Messenger and the chatbot engine. It simply converts the incoming messages from Facebook and sends it to chatbot readable format. Also, when chatbot replies, it converts to Facebook readable formats and passes it to messenger.

Chatbot Engine : Is a NodeJS application, which communicate with some REST APIs based on a conversation flow document and moves the flow of the conversation from one state to another.

Flow JSON : Where we document, every state of a conversation and which APIs to call to generate a response. For example, at the beginning of the conversation, start from "menu" state, and call "/start" API. The flow metadata file is driving the behavior of the bot engine.  The bot engine uses a finite-state-machine (FSM) to drive the conversation. Every step in the conversation is modeled as a state, and all possible next steps to move the conversation to a next state are defined as state transitions.  Every time a state is entered, the response elements defined for this state in the flow metadata are processed and the response is constructed and returned to the messaging platform.

Component APIs : Where several microservices are running, In my case I create a set of APIs, named Airport API which returns, starting from get flight info based on flight number, where is the check-in gate, baggage information, delayed flights etc.

Every component api should have a flow json, which defines that state transitions in the conversation and which APIs to call inorder to generate the response of the chat.

Now a bit more details about Component APIs and Flow JSON relationship.
In my case, Airport API, so I will explain my flow json in context to that.

First of all, below is the structure of each "state" in the flow json.

Each state has a "stateName", which generates a "response", using one or multiple component APIs. Optionally, it can also provides some options, which user can choose to further communicate with the chatbot.
Each of these options, generates an Event, which is mapped to another "state".

There is a special "state" called "stateTransitionError", it gets invoked when chatbot engine cannot translate/understand user input and it gives user option to navigate to the "start" state.

This is a simple, state transition map, only depicting a single flow.

The flow is written in Mustache(https://mustache.github.io/mustache.5.html). It is a simple “logic-less” template engine. It works by expanding tags in a template using values provided in a JSON object. It is "logic-less" because there are no if statements, else clauses, or for loops. Instead there are only tags. Some tags are replaced with a value, some nothing, and others a series of values. A state definition in mustache looks like this :

{"name": "flightDetails", "type" : "response"
             ,"responseItems" :
            [ { "type":"prompt", "languages":
                 [{"language":"en","prompt": "Your flight departs at {{flowScope.departureTime}} , {{#isDelayed}} And, it looks like, your flight has reported a delay in departure. Sorry about that. {{/isDelayed}}"}
                 [{"language":"en","prompt": "Do you want, the following info on your flight?"}]
                ,"options" :
                     [{"payload" : { "event" : "immigrationInfo" }
                        ,"languages" :
                          [{"language": "en", "prompt": "Immigration Info"}]  
                      ,{"payload" : { "event" : "checkinInfo" }
                        ,"languages" :
                          [{"language": "en", "prompt": "Check-in Counter/Gate"}]  
                      ,{"payload" : { "event" : "onlineCheckin" }
                        ,"languages" :
                          [{"language": "en", "prompt": "Online Check-in URL"}]  
            ,"componentServices" : [{"name" : "getFlightDepartureTime"
                               ,"inputParams":[{"name" : "flightNo", "value": "{{flowScope.enterFlightNo}}"}]
                               ,"outputParams": [{"name" : "departureTime","scope": "flow"}]
                               ,{"name" : "getIsFlightDelayed"
                               ,"inputParams":[{"name" : "flightNo", "value": "{{flowScope.enterFlightNo}}"}]
                               ,"outputParams": [{"name" : "isDelayed","scope": "request"}]

Regarding the Flow, a multiple approach can be used, rather than writing a huge JSON document :
  1. Use Oracle Policy Automation to write the rules and state transitions
  2. Use Oracle BPM to define human taskflows
  3. Use a custom application where admin/business users can define the states and transitions, as well as pick up APIs from a catalog.
Either way, we have to make sure the end result is readable by the chatbot engine.

Here is a GIF of the running bot :

According to Oracle A Team, Oracle will soon release an intelligent bot cloud, which will be used then to replace the messaging platform server and chatbot engine.