article by Frank Nimphius, June 2020
In addition to natural language processing (NLP), menus are a popular means of navigation in a chatbot conversation. Action menus are typically used either as fallback when the NLP engine does not resolve a user message with predefined confidence (threshold), or when a resolved user intent has subcategories into which a conversation can be branched. To build action menus you have a choice:
- You can build action menus manually using the System.CommonResponse component and BotML.
- You can build action menus based on value-list entities that you render using the System.CommonResponse component
In this article I will try to convince you to use the latter approach to use entity based menus (or model driven, as I like to refer to this).
Behavior of manually built action menus
The action menu below has been built manually in BotML. Unlike list-of-values, which set a value to a variable when a user selects an item from the list, action menus trigger a navigation to a specific dialog flow state. With this behavior, action menus are like menus in web and mobile applications.
The sample for this article is very simple: when a user selects an item from the action list, navigation goes to a dialog flow state that confirms the user selection. If the user enters a text message that cannot be resolved to an item label or a keyword defined for the select items, then a textReceived action is triggered. Text received actions are usually directed to the NLP engine (System.Intent component) to resolve the user intent.
The image below shows a choice of three action items, one of which is "Order Pizza". Humans are humans, and because they are, they behave like humans. So if a user instead pf pressing a button (select item) or typing "Order Pizza", types "I want pizza", then the menu does not recognize the user intent to select the Order Pizza item. If the text received action was linked to the System.Intent component state, then the NLP engine probably would get it right and get the user what she wants.
But what if the user types in nonsense or a cat walked over the user's keyboard? In this case, shown in the image below, the intent engine would be challenged fro e.g. "grrmpf". Assuming the intent engine does not resolve "grrmpf", the user is actually taken off the track by this.
If the bot is run with voice in the Oracle Digital Assistant Web SDK, how would you press a select button? Probably you would try reading the button label, or more likely fallback to human conversation saying something like "I want to order pizza". This however would have the same effect as "grrmpf" in that your message would be directed to the intent engine.
Behavior of entity driven action menus
Action menus you create based on an entity (where a value list entity would be used a metadata for the menu) inherit powerful features if entities
- Ability to display multiple prompts at random to appear less robotic
- Validate user input against values and synonyms of the entity
- Ability to extract values and synonyms (keywords) from free text
- Ability to detect user input failures and display a help message in the prompt
- Disambiguate user messages: E.g "I like to cancel order pizza"
The image below shows how "gimme pizza" got resolved to that the user wants to order pizza. This did not include an intent but purely got resolved through the use of an entity with the menu.
Getting back to the "cat walks keyboard" use case: The image below shows the outcome of "grmpf". The menu shows a message that "grmpf" is not an allowed selection. The maxPrompts setting of the menu defines how many failed user input attempts are allowed before the menu follows a cancel action.
So lets try "order cancel pizza", which meets two select items in the action menu. As shown in the image below, the entity detects the ambiguity and resolves it with a dialog it displays for the user to select from.
Even the case of a user message doesn't matter using entities
How to build entity-driven action menus
As mentioned earlier, entities you build for menus are of type "value list". I suggest to mark entities as menu entities in their names to make your code readable. For each option in the action menu, you create a value entry in the list: order, cancel, openingHrs. The synonyms catch options how users could order or cancel pizza or how they would ask for opening hours. Note that synonyms don't need to anticipate the full user sentence. "gimme" that I defined for "order" would work with "gimme a pizza" as well as "could you gimme a pizza".
The error message defined on the entity is displayed whenever a user fails to provide a valid input. In the image below, the message is read from a resource bundle (which I recommend you always use for message strings) that gets the user entered string passed as an input parameter: system.message.messagePayload.text.
Notice the Prompt for Disambiguation setting in the image above. If validation of the user message results into multiple action values, then a dialog with the defined prompt will be shown. Again, the prompt uses a message bundle.
Finally, you can specify as many different prompts as you like. Each prompt will be displayed in random order dependent how many failed attempts a user has in providing a valid input.
To generate the action menu, a System.CommonResponse component is used. I explain the component properties in a table below the next image.
| Property | Comment |
|---|---|
| variable | The "variable" property of the System.CommonResponse component references a variable of the entity type (PizzaActionMenu) in the sample. This ensures that user messages that don't match a label or keyword defined for a select item are validated. |
| autoNumberPostbackAction | Setting this property to true adds a numeric value in front of each item. Typing the value as a message will then select the action. In the sample, I used a different implementation of the same so I set this property to false. |
| text | The "text" property of the response item displays the prompt. The expression associated with the property references system.entityToResolve.value.prompt to read the prompt from the entity (which then gets it from the resource bundle) |
| actions : label | The label of an action is set to a lowercase character (a, b or c) as a shortcut plus a string read from a resource bundle. The resource bundle key is <action>_label (e.g. order_label) so it can be dynamically resolved |
| actions : keyword | Keyword defines a comma separated list of short cuts that select (or virtually press) a select item. The sample creates four keywords – order, 1, a, A – for the Order Pizza select item and – cancel, 2, b, B – for the Cancel Pizza item. |
| actions : payload : action | The action of each select item is set to the value of the entity: order, cancel and openingHrs |
| actions : iteratorVariable | References system.entityToResolve.value.enumValues to obtain a sequence of entity values. For as long a there are values in the sequence, a select item is being created. |
| transitions : actions | An action mapping to a dialog flow state is created for each value in the entity: order, cancel, openingHrs. This way when the user selects a select item, navigation will be to this state. |
| next | Very important!. When a user types text that does not match a keyword or label of a select item, but that can be validated by the entity value or synonyms, then the next transition is followed. To make sure the navigation follows to the same dialog flow states as when the user selects a button, an Apache FreeMarker "switch" expression is used. |
Downloads
Download the sample skill and import it to your Oracle Digital Assistant instance. Then open it and run the conversation tester. Type "hi" to get the menu displayed.
Download the entity driven action menu skill
Related articles
TechExchange Quick-Tip: How to Intelligently Cancel Composite Bag Entity Driven User Dialog Flows
TechExchange: How-to Use the System.ResolveEntities Component in Oracle Digital Assistant