What if in the middle of the conversation the user changes mind?

Bots that can survive human contact

User: "Wats PaaS?"

Bot: "Oracle Cloud Platform has the most comprehensive suite of PaaS 
solutions to help you increase business agility and drive innovation in 
the cloud. The most popular are Integration Cloud, Mobile & Chatbots and 
Blockchain"

User: "Oops! I meant SaaS"

Bot: "Oracle Cloud Platform has the most comprehensive suite of [....]

User: "Sure... See you later"

I believe machines are very good at doing repeatable and predictable tasks. Humans by nature are everything but predictable. This is why it takes a lot of work to build a Bot that can survive human contact….

This post is a deep technical dive into sub-intents, System components and how we combine them to build a dialog flow that attempts to maintain a conversation even when the user “goes off script”.

What are we trying to achieve?

paas

This post assumes you’re familiar with Bots, Natural Language Processing, Intents, Entities, YAML – if you’re not and you’re interested in Chatbots this is a good time to read my previous blogs  “Entities and Intents: crawling through Natural Language Processing“, “Let’s all raise a cup of coffee to toast the success of Oracle Mobile and Chatbot!“.

In the above example “What is PaaS?” triggers the resolution of the intent tellMeMoreAboutOracleCloud. The resolution of an intent involves several stages (called states), every state is a call to a System component or a custom component. In the scenario System.List lists three PaaS services. If the user selects one of the options the flow will move into the next state which is likely to be a description of the selected PaaS service. Great, what should the Bot respond if the user types something different like “Oops! I meant SaaS”?  The definition of SaaS and the three main SaaS Services. Basically what the Bot would respond if the same question was asked at the beginning of the conversation.

What is NOT a good user experience?

  • Responding with the same answer
  • Responding with “Please use one of the options above”
  • Responding with “Oops! I’m encountering a spot of trouble”
  • Responding with what Blockchain or Mobile Chatbots or Integration Cloud is (in other words just transitioning to the next state in the dialog flow)
  • Worst of all…. not responding

How do we achieve it?

Intents and Entities

Yes, the identification of the right intents and entities for a ChatBot is as important as the determination of the right assets model for a Web Experience Management System. If we fail to identify the right intents and the corresponding entities our Bot will be dump.

Intent: tellMeMoreAboutOracleCloud

Two Entities of type List: Pillars (PaaS,SaaS) and Services (Integration Cloud, Blockchain, Mobile Chatbots etc..)

Dialog Flow – System.Intent:

Once the NLP engine has worked out the intent of the user how do we program the Bot to trigger the subsequent state? Answer below.

Intent:
  component: "System.Intent"
    properties:
      variable: "iResult"
      confidenceThreshold: 0.3
  transitions:
    actions:
      tellMeMoreAboutOracleCloud: "resetVariables"
      cancel: "neverMind"
      unresolvedIntent: "unresolved"


Dialog Flow – How we implement the intent resolution:

I’ll explain what resetVariables does later on – ignore it for now. We want to be able to extract the name of the PaaS or SaaS Service from the user utterance. Let’s imagine the user asks “what is blockchain?

setService:
  component: "System.SetVariable"
  properties:
    variable: "service"
    value: "${iResult.value.entityMatches['Services'][0]}"
  transitions: {}

This state saves “blockchain” in service variable. Then we check if this variable is set and we use System.Switch to identify the service and provide the correct answer to the user question.

checkService:
  component: "System.Switch"
  properties:
    variable: "service"
    values:
    - "Integration Cloud" 
    - "Mobile & Chatbots"
    - "Blockchain"
    - "ERP" 
    - "Customer Experience"
    - "HCM"
  transitions:
    actions:
     Integration Cloud: "IntegrationCloud" 
     Mobile & Chatbots: "Mobile&Chatbots"
     Blockchain: "Blockchain"
     ERP: "ERP"
     Customer Experience: "CX"
     HCM: "HCM"
     NONE: "checkPillar"

What is checkPillar ? In the scenario where the user asks about PaaS (Platform as a Service) or SaaS (Software as a Service) instead of a specific service we display the list of services belonging to the pillar.  This is pretty straightforward: System.Switch and System.List to display all the services.

Now let’s explore something more interesting: let’s assume our user asks “hey there, what’s in the Oracle cloud?“. No problem, we tell him Oracle offers three models of cloud service including: Platform as a Service (PaaS), Software as a Service (SaaS). If he picks PaaS we’ll list the main three PaaS services: Integration Cloud, Mobile & Chatbots and Blockchain. Too easy 🙂

First

If our user was 100% predictable (wrong assumption for humans) we would add another System.Switch that checks the selected value and if the var we’ve set is Integration Cloud we tell him all about Integration, otherwise Mobile&Bots or Blockchain. Bad design, our Bot will not be robust enough to maintain the conversation with the user. We should handle the following scenarios:

  1. user types in a random world instead of selecting PaaS or SaaS
  2. user selects PaaS/SaaS and then changes mind: “Oops, I meant SaaS” or “Wait, actually I wanted to order a gift”

Scenario 1

Second

How do we determine “pizza” is not a valid option?

listPaaSSaaS:
  component: "System.List"
  properties:
    options: "PaaS,SaaS"
    prompt: "Oracle Cloud Platform redefines how you modernize, innovate, and compete in a digital world. Oracle offers three models of cloud service including: Platform as a Service (PaaS), Software as a Service (SaaS). What are you interested in?"
    variable: "pillarAppVar"
  transitions: {}
extractPillar:
  component: "System.MatchEntity"
  properties:
    sourceVariable: "pillarAppVar"
    variable: "pillar"
  transitions:
    actions:
      match: "pillarSwitch"
      nomatch: "askOneMoreTimePillar"
 askOneMoreTimePillar:
   component: "System.Text"
   properties:
     prompt: "Yours doesn't seem to be a valid option. Please choose one of the options above"
     variable: "pillar" 
     maxPrompts: 1
   transitions:
     actions:
       cancel: "invalidOption"

The extractPillar state in the above snippet uses the System.MatchEntity component
to match the user input stored in the pillarAppVar variable value against the Pillars entity type that’s been defined for the pillar variable. If the user input contains “PaaS”,”SaaS” or a valid synonym, the component copies the value into the pillar variable. If the Intent Engine cannot match the entity from the source variable value the flow transitions to the next state askOneMoreTimePillar. This state prompts the user with the appropriate message and waits for the next input. If the user provides an invalid option again (note this time the entity slotting is implicit) we transition to the invalidOption state which marks the end of the intent resolution (maxPrompts set to 1). Otherwise pillarSwitch  switches states based on pillar variable.

Scenario 2

Cropped

How many times while being on the phone with an Airline customer representative you have changed your mind? You were about to book the 7 AM flight when you decided that 8 AM was a better choice. Our funny user inquired about SaaS but he meant PaaS! We need to get the conversation back on track, how do we do it?

listSaaS:
  component: "System.List"
    properties:
      options: "ERP,Customer Experience,HCM"
      prompt: "Oracle Cloud Applications are Complete, Innovative, and Proven enabling modern business transformations. Create differentiated products and services, enter new markets and respond to global demand, delight customers and drive loyalty. The most popular SaaS services:"
    variable: "serviceAppVar"
  transitions: {}
extractSaaS:
  component: "System.MatchEntity"
  properties:
    sourceVariable: "serviceAppVar"
    variable: "service"
  transitions:
    actions:
      match: "saasSwitch"
      nomatch: "saasSelectionIntent"

Once again we capture the user input in the generic string variable serviceAppVar. extractSaaS matches what is in the app var “Sorry I meant PaaS” against the Service entity type. No match found, therefore we transition to saasSelectionIntent. This is where the magic happens!

saasSelectionIntent:
  component: "System.Intent"
  properties:
    variable: "iResult"
    confidenceThreshold: 0.3
    sourceVariable: "serviceAppVar" 
  transitions:
    actions: 
      whatAreTheGifts: "setGift"
      tellMeMoreAboutOracleCloud: "resetVariables"
      cancelIntent: "neverMind"
      unresolvedIntent: "askOneMoreTimeSaaS"

The saasSelectionIntent state uses the System.Intent component to detect the user intent and we can control the values that the Intent Engine processes by adding the
sourceVariable property which holds the user input (“Sorry I meant PaaS”). The Intent Engine resolves the user intent tellMeMoreAboutOracleCloud and then triggers the subsequent state resetVariables that resets serviceAppVar,pillarAppVar,pillar and service. Why? Because a sub intent unlike an intent resolved at the start of the dialog flow does not reset the context therefore we need to force a reset of those session variables that hold the information the user has provided along the conversation. The state machine is now back to the same state that was triggered when the user asked “So, what’s SaaS?”.

This post doesn’t want to give any tech-recipe. The primary goal is to encourage Bots developers to take into account that human beings are really unpredictable especially when they realize they’re talking to a Bot! Your job is to design a Bot that will manage to survive the random things people on the internet will throw at it!

Happy coding and until the next post!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s