Multi-turn story example: List filters

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.

Multi-intent stories

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:

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.

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.

Multi-intent Example


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.