There may stories that require multiple dialogue turns between the user and Diatheke.
For example, what if Diatheke asks “What filter do you want?” and the user doesn’t know what the options are?
We can include other intents to allow them to ask what filters are available.
Rather than give a long list of filters all in one reply (which is not a great user experience), the model will return a few at a time, pausing to let the user decide whether to keep listing them, apply a filter they’ve already heard, or open a popup to read the list on the screen.
This example illustrates several action types available to use within Diatheke models:
First we’ll remove the required_slots from main.yaml because we don’t just want to prompt to fill the slot, we want to let the user ask questions. Instead, the apply_filter_story will start with a conditional action: if image_filter is undefined, it will go to an input action that accepts either the apply_filter_intent with a required slot or a new intent called list_filters_intent.
The list_filters_intent matches utterances like “List available filters” and “What are my options” so the interaction can feel more conversational:
User: Apply filter.
Diatheke: What filter would you like to apply?
User: What are the choices?
Diatheke: There are 21 filters available, including vintage, lomo, and clarity. Would you like me to list more? Or open the help panel with a full list?
The user may respond in a variety of ways to list_filters_reply, so the list_filters_story defines an input action that can handle having the user say “yes” or “no”, or say “apply vintage filter”, or “open help”, or “list more”, or “cancel”. Each of those is a different intent with its own list of sample utterances, though both “yes” and “list more” have the same action list. If the user applies a filter, that exits the list_filters_story and returns to the apply_filter_story. The cancel_intent returns to the main story. Any other response keeps looping through the list of filters until the user finally chooses a valid one.
User: List more
Diatheke: sin city, sunrise, cross process, orange peel. Want to hear more?
User: Yes
Diatheke: love, grungy, jarques, pinhole, old boot. Should I keep going?
User: OK
Diatheke: glowing sun, hazy days, her majesty, nostalgia. There’s still more if you want.
User: List more
Diatheke: black and white, hemingway, concentrate, and bright. That’s all the filters. Which one do you want?
User: List more
Diatheke: No, really. That’s all the filters.
User: Apply nostalgia.
Diatheke: Applying nostalgia filter.
This looping is accomplished by having the list_more_filters_intent call a conditional action that sets a parameter in memory to keep track of which filters have already been listed. It returns a different reply based on that parameter, and calls the same input action again.
What happens if the user says something that matches a different intent, such as “zoom in”? That’s not a valid intent for this point in the dialogue, so Diatheke responds with the list_filters_reply_invalid and keeps listening for an appropriate intent to continue or end the interaction regarding filters.
init_actions:
- type: reply
id: welcome_message
- type: input
id: main_input
start_actions:
- type: command
id: at_start
- type: memory
id: reset_all
- type: input
id: main_input
input_actions:
- name: main_input
intents:
- intent_id: apply_filter_intent
actions:
- type: story
id: apply_filter_story
- intent_id: list_filters_intent
actions:
- type: story
id: list_filters_story
- intent_id: zoom_intent
actions:
- type: story
id: zoom_story
defaults:
no_intent_actions:
- type: reply
id: no_intent_reply
# Specify what to do if the user says the cancel intent
# at any time.
cancel_intent:
intent_id: undo_intent
actions:
- type: reply
id: cancel_reply
start_actions:
- type: conditional
id: parameters_specified
conditional_actions:
- name: parameters_specified
conditions:
- condition: ${image_filter}.undefined
actions:
- type: reply
id: prompt_for_image_filter
- type: input
id: prompt_for_filter
default_actions:
- type: reply
id: apply_filter_reply
- type: command
id: apply_filter_command
input_actions:
- name: prompt_for_filter
intents:
- intent_id: apply_filter_intent
required_slots:
- image_filter
actions:
- type: story
id: apply_filter_story
- intent_id: list_filters_intent
actions:
- type: story
id: list_filters_story
language_data:
en_US:
example_utterances:
- What filters are available
- What image filters are available
- What filters can I use
- What image filters can I use
- What filters are there
- What image filters are there
- What are my choices
- What are my options
- List the options
- Available filters
start_actions:
- type: conditional
id: list_filters_condition
input_actions:
- name: show_or_tell_input
intents:
- intent_id: apply_filter_intent
required_slots:
- image_filter
actions:
- type: story
id: apply_filter_story
- intent_id: slot_fill_intent
actions:
- type: story
id: apply_filter_story
- intent_id: open_help_intent
actions:
- type: command
id: open_help_command
- type: input
id: show_or_tell_input
- intent_id: list_more_filters_intent
actions:
- type: conditional
id: list_filters_condition
- intent_id: yes_intent
actions:
- type: conditional
id: list_filters_condition
- intent_id: no_intent
actions:
- type: reply
id: prompt_for_image_filter
- type: input
id: show_or_tell_input
conditional_actions:
- name: list_filters_condition
conditions:
- condition: ${filter_list_index}.undefined
actions:
- type: memory
id: set
param_map:
filter_list_index: 1
- type: reply
id: list_filters_reply
- type: input
id: show_or_tell_input
- condition: ${filter_list_index}.is(1)
actions:
- type: memory
id: set
param_map:
filter_list_index: 2
- type: reply
id: list_filters_reply2
- type: input
id: show_or_tell_input
- condition: ${filter_list_index}.is(2)
actions:
- type: memory
id: set
param_map:
filter_list_index: 3
- type: reply
id: list_filters_reply3
- type: input
id: show_or_tell_input
- condition: ${filter_list_index}.is(3)
actions:
- type: memory
id: set
param_map:
filter_list_index: 4
- type: reply
id: list_filters_reply4
- type: input
id: show_or_tell_input
- condition: ${filter_list_index}.is(4)
actions:
- type: memory
id: set
param_map:
filter_list_index: 5
- type: reply
id: list_filters_reply5
- type: input
id: show_or_tell_input
- condition: ${filter_list_index}.is(5)
actions:
- type: reply
id: list_filters_reply6
- type: input
id: show_or_tell_input
default_actions:
- type: input
id: show_or_tell_input
defaults:
invalid_intent_actions:
- type: reply
id: list_filters_reply_invalid
- type: input
id: show_or_tell_input
language_data:
en_US:
example_utterances:
- No
- No thanks
- No thank you
- Nope
language_data:
en_US:
example_utterances:
- Yes
- Yes please
- Yeah
- ok
- okay
- Sure
language_data:
en_US:
- There are 21 filters available, including vintage, lomo, and clarity.
Would you like me to list more? Or open the help panel with a full list?
language_data:
en_US:
- sin city, sunrise, cross process, orange peel. Want to hear more?
language_data:
en_US:
- love, grungy, jarques, pinhole, old boot. Should I keep going?
language_data:
en_US:
- glowing sun, hazy days, her majesty, nostalgia. There's still more if you want.
language_data:
en_US:
- black and white, hemingway, concentrate, and bright. That's all the filters.
Which one do you want?
language_data:
en_US:
- No, really. That's all the filters.
language_data:
en_US:
- I thought we were talking about filters.
Note This particular example intentionally keeps all the logic explicitly within the Diatheke model so it can be self-contained for demonstration purposes. In most production systems, multi-turn stories execute commands to look up various pieces of information from back-end systems outside Diatheke.