Enhancing A Cognitive Assistant With "Backend" Data
Hickmat 100000QA3T Visits (3142)
As I've been working on a number of cognitive assistants over the last year a common theme emerges which is how to bring data in for "backend" systems as part of the response to a users question. Now this is not an unusual request and I've seen several examples of how to achieve this but I thought I would document my approach in case its of use to others. For me the main challenge I wanted to address was how to access data stores in systems running behind a corporate firewall and in doing this have an approach which would be generic.
Before getting into the details of the solution I want to explain that a key approach I take when helping to design / implement Cognitive Assistants is to avoid adding complex logic to the dialog flow element of a Watson Assistant workspace. Doing this allows the cognitive engineer to focus on addressing the understanding of the consumers utterance and reaching a conclusion as to what the next action should be. This action could be...
Implementing logic for these actions in the dialog flow can be complex and can lead to a far more intricate flow in the dialog structure making debugging harder. To address this the pattern I've used is the enrich - fulfil pattern which is implemented in code used to wrapper the call to Watson Assistant. At a high level this flow looks as follows:
Here the enrich phase is used to bring in any additional information into the context before the utterance is passed to Watson Assistant (e.g. a look up of customer preferences to help inform the way a question is addressed). After Watson Assistant has completed processing the fulfil phase is use to "action" any commands issued as response from Watson Assistant. These commands are supplied as the response text and the framework I've used uses an XML style syntax. Once complete the fulfil phase will either return to the caller or will re-invoke the enrich phase to further process the conversational flow logic (e.g. a customer may be asking to complete a task and by looking up some backend data some of the "slots" can be populated meaning Watson Assistant can focus on prompting for the missing data). Based on this the natural extension point for me was to create a fulfil action which would invoke a "callout" to an API to retrieve the data.
The next area I needed to focus on was how to join an IBM Cloud based Conversational Assistant with backend data hosted behind a corporate firewall. To achieve this I decided to look at using a combination of IBM API Connect in the Cloud running a Secure Gateway and connecting to this gateway as a client from a Datapower Gateway appliance running behind the corporate firewall. This is the standard design pattern for using the Secure Gateway but does require port 9000 as well as port 443 to be open in the firewall for outbound calls. The following shows the architecture that I set up:
To simplify the coding required at the conversation AI layer I decided to use HTTP POST as the invocation method for all calls to API Connect passing the full conversation context. In this way the power of API Connect can be used to handle the mapping and routing the appropriate target API. In addition I decided to implement my fulfilment "Action" with parameters to allow the target API, product and catalog to be specified which again meant that the conversation layer code could be simplified as to create the target URL for the API its only needed to know about the base URL for the API Connect service instance and the secret for calling the API's. The resulting XML string looked like:
<callAPI api='motor/get' product='sports' catalog='general' />
In the API Connect service I created a Product call "sports" and to this added an API called motor with a POST path of "/get" which accepts a parameter of type "object" called "context" which is located in the http request "Body". In the API assembly I could simply map the information from the conversation context object into the necessary format for the downstream API and then "Invoke" the API via the secure gateway. Once the the call was complete I mapped the response back into the context and returned the updated context to the "Conversation AI" where the next appropriate action could be taken.
Through this approach I have been able to abstract away the complexity of calling a backend API from the "Conversation AI" and by leveraging API Connect have been able to use a more declarative approach to fulfilling the actually transformation and mapping required to invoke the required API (or if necessary APIs).