Improving a dialog node with slots
In this tutorial, you enhance a simple node with slots that collects the information necessary to make a restaurant reservation.
Learning objectives
By the time you finish the tutorial, you learn how to:
- Test a node with slots
- Add slot response conditions that address common user interactions.
- Anticipate and address unrelated user input.
- Handle unexpected user responses.
Duration
This tutorial takes approximately 2 to 3 hours to complete.
Prerequisite
Before you begin, complete the Adding a node with slots to a dialog. You must complete the first slots tutorial before you begin this one because you build on the node with slots that you create in the first tutorial.
Improve the format of the responses
When the date and time system entity values are saved, they are converted into a standardized format. This standardized format is useful for performing calculations on the values, but you might not want to show this reformatting to customers.
In this step, you reformat the date (2021-04-09
) and time (17:00:00
) values that are referenced by the dialog.
To reformat the $date
context variable value:
-
In your dialog, open the #reservation node.
-
Click the Customize slot icon for the
@sys-date
slot. -
From the options menu menu, select Open JSON editor, and then edit the JSON that defines the context variable. Add a method that reformats the date so that it converts the
2021-04-09
value into a full day of the week, followed by the full month and day. Edit the JSON as follows:{ "context": { "date": "<? @sys-date.reformatDateTime('EEEE, MMMM d') ?>" } }
The EEEE indicates that you want to spell out the day of the week. If you use 3 Es (EEE), the day of the week is shortened to Fri instead of Friday, for example. The MMMM indicates that you want to spell out the month. Again, if you use only 3 Ms (MMM), the month is shortened to Dec instead of December.
-
Click Save.
-
To change the format in which the time value is stored in the $time context variable to use the hour, minutes and indicate AM or PM, click the Customize slot icon for the
@sys-time
slot. -
From the options menu menu, select Open JSON editor, and then edit the JSON that defines the context variable so that it reads as follows:
{ "context": { "time": "<? @sys-time.reformatDateTime('h:mm a') ?>" } }
-
Click Save.
-
Test the node again. Open the "Try it out" pane, and click Clear to delete the slot context variable values that you specified when you tested the node with slots earlier. To see the impact of the changes you made, use the following script:
Script details Speaker Utterance You I want to make a reservation Assistant What day would you like to come in? You Friday Assistant What time do you want for the reservation? You 5pm Assistant How many people will be dining? You 6 This time the assistant responds with
OK. I am making you a reservation for 6 on Friday, April 9 at 5:00 PM.
You improved the format that the dialog uses when it references context variable values in its responses. The dialog now uses Friday, April 9
instead of the more technical, 2021-04-09
. And it uses 5:00 PM
instead of 17:00:00
.
Ask for everything at once
Now that you tested the dialog more than once, you might notice that it can be annoying to answer one slot prompt at a time. To prevent users from having to provide one piece of information at a time, you can ask for every piece of information that you need up front. Doing so gives the user a chance to provide all or some of the information in a single input.
The node with slots is designed to find and save any slot values that the user provides while the current node is being processed. You can help users to take advantage of the design by telling them what values to specify.
In this step, you learn how to prompt for everything at once.
-
Open the #reservation node.
-
Click Customize.
-
In Slots, select the Prompt for everything checkbox to enable the initial prompt, and then click Apply.
-
Back in the node edit view, scroll down to the newly added If no slots are pre-filled, ask this first section. Add the following initial prompt for the node,
I can make a reservation for you. Just tell me the day and time of the reservation, and how many people will be dining.
-
Click the Close icon to close the node edit view.
-
Test this change from the "Try it out" pane. Open the pane, and then click Clear to nullify the slot context variable values from the previous test.
-
Enter
I'd like to make a reservation
.The dialog now responds with,
I can make a reservation for you. Just tell me the day and time of the reservation, and how many people it is for.
-
Enter,
It's for Saturday. There will be 2 of us coming in at 8pm
.The assistant responds with,
OK. I am making you a reservation for 2 on Saturday at 8:00 PM.
If the user provides any one of the slot values in their initial input, then the prompt that asks for everything is not displayed. For example, the initial input from the user might be I want to make a reservation for this Friday night
.
In this case, the initial prompt is skipped because you do not want to ask for information that the user already provided. The dialog shows the prompt for the next empty slot instead.
Treat zeros properly
When you use the sys-number
system entity in a slot condition, it does not deal with zeros properly. Instead of setting the context variable that you define for the slot to 0, your assistant sets the context variable to false. As
a result, the slot does not think it is full and prompts the user for a number again and again until the user specifies a number other than zero.
-
Test the node so you can better understand the problem. Open the "Try it out" pane, and click Clear to delete the slot context variable values that you specified when you tested the node with slots earlier. Use the following script:
Script details Speaker Utterance You I want to make a reservation Assistant I can make a reservation for you. Just tell me the day and time of the reservation, and how many people will be dining. You We want to dine May 23 at 8pm. There will be 0 guests. Assistant How many people will be dining? You 0 Assistant How many people will be dining? You are stuck in this loop until you specify a number other than 0.
To ensure that the @sys-number
slot treats zeros properly:
-
Click the Customize slot icon
-
In Check for, enter
@sys-number >= 0
. -
Now, you change the context variable that is stored for the number.
The slot condition is used both to check the user input for a number value, and to store that number in a context variable. Now that you edited the condition in the Check for field, you find mention of the number zero.
However, you want to save only the number, and store it in the context variable. From the options menu menu, select Open JSON editor, and then edit the JSON that defines the context variable.
The value looks like this:
{ "context": { "guests": "@sys-number >= 0" } }
Change it to look like this:
{ "context": { "guests": "@sys-number" } }
-
Click Save.
You must edit the context variable value in the JSON editor. Do not edit the value in the slot's Check for field. The Check for field must remain set to
@sys-number >= 0
. { :important}When you edit the value in the JSON editor, you are effectively changing only what to save in the context variable. However, you do not want to change what to look for in the input. These two values will be different.
-
Test the node again. Open the "Try it out" pane, and click Clear to delete the slot context variable values that you specified when you tested the node with slots earlier. To see the impact of the changes you made, use the following script:
Script details Speaker Utterance You I want to make a reservation. Assistant I can make a reservation for you. Just tell me the day and time of the reservation, and how many people will be dining. You We want to dine May 23 at 8pm. There will be 0 guests. This time the assistant responds with,
OK. I am making you a reservation for 0 on Thursday, May 23 at 8:00 PM.
You formatted the number slot so that it treats zeros properly. But, you might not want the node to accept a zero as a valid number of guests. You will learn how to validate values that are specified by users in the next step.
Validate user input
So far, we assume that the user provides the appropriate value types for the slots. You can account for times when users might provide an invalid value by adding conditional responses to slots. In this step, you use conditional slot responses to perform the following tasks:
- Check that the date requested is not in the past.
- Check whether a requested reservation time falls within the seating time window.
- Confirm the user's input.
- Check that the number of guests provided is larger than zero.
- Indicate that you are replacing one value with another.
To validate the date, complete the following steps:
-
Click the Customize slot icon for the
@sys-date
slot. -
From the options menu menu, select Enable condition.
-
In the Found section, click Add a response, then click the Customize handler icon .
-
Add the following condition and response to check whether the date that the user specifies falls before today:
Condition details If assistant recognizes Assistant responds Then assistant should @sys-date.before(now())
You cannot make a reservation for a day in the past.
Clear slot and prompt again -
Add a second conditional response that is displayed if the user provides a valid date. This type of simple confirmation tells the user that the response was understood.
Condition details If assistant recognizes Assistant responds Then assistant should true
$date it is.
Move on
To validate the time:
-
Click the Customize slot icon for the
@sys-date
slot. -
From the options menu menu, select Enable condition.
-
In the Found section, click Add a response, then click the Customize handler icon .
-
Add the following conditions and responses to check whether the time that the user specifies falls within the allowed time window:
Condition details If assistant recognizes Assistant responds Then assistant should @sys-time.after('21:00:00')
Our last seating is at 9 PM.
Clear slot and prompt again @sys-time.before('09:00:00')
Our first seating is at 9 AM.
Clear slot and prompt again -
Add a third conditional response that is displayed if the user provides a valid time that falls within the window. This type of simple confirmation tells the user that the response was understood.
Condition details If assistant recognizes Assistant responds Then assistant should true
Ok, the reservation is for $time.
Move on
You can add conditions to validate the number of guests.
- Check that the number of guests that are specified is larger than zero.
- Anticipate and address the case when the user changes the number of guests.
If at any point while the node with slots is being processed, the user changes a slot value, the corresponding slot context variable value is updated. However, it can be useful to tell the user that the value is being replaced to give clear feedback to the user and to give the user a chance to rectify it.
-
Click the Customize slot icon for the
@sys-number
slot. -
From the options menu menu, select Enable condition.
-
In the Found section, click Add a response, then click the Customize handler icon .
-
Add the following conditions and responses to validate the number of guests:
Condition details If assistant recognizes Assistant responds Then assistant should @sys-number == 0
Please specify a number that is larger than 0.
Clear slot and prompt again (event.previous_value != null) && (event.previous_value != event.current_value)
Ok, updating the number of guests from <? event.previous_value ?> to <? event.current_value ?>.
Move on true
Ok. The reservation is for $guests guests.
Move on
Add a confirmation slot
You might want to design your dialog to call an external reservation system and book a reservation for the user in the system. Before your application completes this task, you probably want to confirm with the user that the dialog understands the details of the reservation correctly. You can do so by adding a confirmation slot to the node.
-
The confirmation slot expects a Yes or No answer from the user. You must teach the dialog to be able to recognize a Yes or No intent in the user input first.
-
Click the Intents tab to return to the Intents page.
-
Add the following intents and example utterances.
#yes
Yes
Sure
I'd like that
Please do
Yes please
Ok
That sounds good
#no
No
No thanks.
Please don't
Please do not!
That's not what I want at all
Absolutely not
No way
-
In your dialog, open the #reservation node.
-
In the Then check for section, click Add slot to add a fourth slot:
Slot details Check for Save it as If not present, ask (#yes || #no) && slot_in_focus
$confirmation
I'm going to reserve you a table for $guests on $date at $time. Should I go ahead?
This condition checks for either answer. You specify what happens next depending on whether the user answer Yes or No by using conditional slot responses. The
slot_in_focus
property forces the scope of this condition to apply to the current slot only. This setting prevents random statements that might match against a#yes
or#no
intent that the user might make from triggering this slot.For example, the user might be answering the number of guests slot, and say something like,
Yes, there will be 5 of us.
. You do not want theYes
included in this response to accidentally fill the confirmation slot. By adding theslot_in_focus
property to the condition, ayes
orno
answer from the user is applied to this slot only when the user is answering the prompt for this slot specifically. -
Click the Customize slot icon for the
yes/no
slot. -
From the options menu menu, select Enable condition.
-
In the Found section, click Add a response, then click the Customize handler icon
-
Add the following condition and response to check for a
No
response:Condition details If assistant recognizes Assistant responds Then assistant should #no
Alright. Let's start over. I'll try to keep up this time.
Clear slot and prompt again -
When the
#no
intent is found you need to reset the context variables that you saved earlier, so you can ask for the information again. From the options menu for the condition , select Open context editor. -
Set the context by using these values:
Set context Variable Value $date
null
$time
null
$guests
null
-
Click Save.
-
In the Not found section, clarify that you are expecting the user to provide a Yes or No answer.
-
Add a response with the following condition:
Condition details If assistant recognizes Assistant responds Then assistant should true
Respond with Yes to indicate that you want the reservation to be made as-is, or No to indicate that you do not.
Wait for user input -
Click Save.
Now that you have confirmation responses for slot values, and you ask for everything at once, you might notice that the individual slot responses are displayed before the confirmation slot response is displayed, which can appear repetitive. Edit the slot found responses to prevent them from being displayed under certain conditions.
-
Click the Customize slot icon for the
@sys-date
slot. -
In the Found section, replace the
true
condition. For example:Condition details If assistant recognizes Assistant responds Then assistant should !($time && $guests)
$date it is
Move on -
Click the Customize slot icon for the
@sys-time
slot. -
In the Found section, replace the
true
condition. For example:Condition details If assistant recognizes Assistant responds Then assistant should !($date && $guests)
Ok, the reservation is for $time.
Move on -
Click the Customize slot icon for the
@sys-number
slot. -
In the Found section, replace the
true
condition. For example:Condition details If assistant recognizes Assistant responds Then assistant should !($date && $time)
Ok. The reservation is for $guests guests.
Move on
If you add more slots later, you must edit these conditions to account for the associated context variables for the additional slots. If you do not include a confirmation slot, you can specify !all_slots_filled
only, and it would
remain valid no matter how many slots you add later.
Reset the slot context variable values
You might notice that before each test, you must clear the context variable values that were created during the previous test. You must do so because the node with slots prompts users only for information that it considers to be missing. If the slot context variables are all filled with valid values, no prompts are displayed. The same is true for the dialog at run time. You must build into the dialog a mechanism by which you reset the slot context variables to null so that the slots can be filled anew by the next user. To do so, you are going to add a parent node to the node with slots that sets the context variables to null.
-
From the tree view of the dialog, click the Node options icon icon on the #reservation node with slots, and then select Add node above.
-
In If assistant recognizes, enter
#reservation
as the condition. The same condition that is used by the node with slots, but you change the condition for the node with slots later in this procedure. -
In Assistant responds, click the options menu and select Open context editor.
-
Set the context by using these values:
Set context Variable Value $date
null
$time
null
$guests
null
$confirmation
null
-
Click to edit the other #reservation node, the one you created previously and to which you added the slots.
-
Change the node condition from
#reservation
to($date == null && $time == null)
. -
Click the Node options icon icon on the node with slots, and then select Move.
-
Select the
#reservation
node as the move-to location target, and then choose As child node from the menu. -
Click to edit the #reservation node. In the Then assistant should section, change from Wait for reply to Skip user input.
When a user input matches the
#reservation
intent, this node is triggered. The slot context variables are all set to null, and then the dialog jumps directly to the node with slots to process it.
Give users a way to exit the process
Adding a node with slots is powerful because it keeps users on track providing the information that you need to give them a meaningful response or perform an action on their behalf. However, the user might be in the middle of providing reservation details, but decides to not go through with placing the reservation. You must give users a way to exit the process gracefully. You can do so by adding a slot handler that can detect a user's desire to exit the process, and exit the node without saving any values that were collected.
-
In Intents, add an
#exit
intent with the following example utterances.I want to stop Exit! Cancel this process I changed my mind. I don't want to make a reservation. Stop the reservation Wait, cancel this. Never mind.
-
In Dialog, click to open the node with slots, and then click Manage handlers.
-
Add the following handler condition:
Condition details If assistant recognizes Assistant responds Then assistant should #exit
Ok, we'll stop there. No reservation will be made.
Skip to response The Skip to response action jumps directly to the node-level response without displaying the prompts associated with any of the remaining unfilled slots.
-
Click Save, and then click Save again.
Now, you need to edit the node-level response to have it recognize when a user wants to exit the process rather than make a reservation.
To add a conditional response for the node:
-
In the node with the slots, click Customize, set the Multiple conditioned responses switch to On, and then click Apply.
-
In Assistant responds, click Add response.
-
Add a response with the following condition:
Condition details If assistant recognizes Assistant responds Then assistant should has_skipped_slots
I look forward to helping you with your next reservation. Have a good day.
Default to node settings The
has_skipped_slots
condition checks the properties of the slots node to see if any of the slots were skipped. The#exit
handler skips all remaining slots to go directly to the node response. So, when thehas_skipped_slots
property is present, you know the#exit
intent was triggered, and the dialog can display an alternative response.If you configure more than one slot to skip other slots, or configure another node-level event handler to skip slots, then you need a different approach to check if the #exit intent was triggered. See Handling requests to exit a process for an alternative way to do so.
-
You want your assistant to check for the
has_skipped_slots
property before it displays the standard node-level response. Move thehas_skipped_slots
conditional response so it gets processed before the original conditional response or it is never triggered. To do so, hover on the response you just added, use the up arrow to move it up, and then click Save. -
Test this change by using the following script in the "Try it out" pane.
Script details Speaker Utterance You I want to make a reservation. Assistant I can make a reservation for you. Just tell me the day and time of the reservation, and how many people will be dining. You It's for 5 people Assistant Ok. The reservation is for 5 guests. What day would you like to come in? You Never mind Assistant Ok, we'll stop there. No reservation will be made. I look forward to helping you with your next reservation. Have a good day.
Apply a valid value if the user fails to provide one after several attempts
In some cases, a user might not understand what you are asking for. They might respond again and again with the wrong types of values. To plan for this possibility, you can add a counter to the slot, and after 3 failed attempts by the user to provide a valid value, you can apply a value to the slot on the user's behalf and move on.
For the $time
information, you define a follow-up statement that is displayed when the user does not provide a valid time. Create a context variable that can track how many times the user provides a value that does not match the
value type that the slot expects. You want the context variable to be initialized and set to 0
before the node with slots is processed, so you add it to the parent #reservation
node.
-
In Dialog, click to edit the
#reservation
node. -
In Then set context, click Add variable. (If Then set context isn't visible, click the options menu in Assistant responds and select Open context editor.)
-
Set the context by using these values:
Set context Variable Value $counter
0
-
Click the Close icon to close the node edit view.
-
From the tree view, click to edit the node with slots.
-
Click the Customize slot icon for the
@sys-time
slot. -
Click the options menu and select Enable condition. An Enable this slot if: section appears, set to
true
. -
In the Not found section, add a response with the following condition:
Condition details If assistant recognizes Assistant responds Then assistant should true
Please specify the time that you want to eat. The restaurant seats people between 9AM and 9PM.
Wait for user input
Now add a 1 to the counter
variable each time this response is triggered. This Not found response is triggered only when the user does not provide a valid time value.
-
In Assistant responds, click the options menu and select Open context editor.
-
Set the context by using these values:
Set context Variable Value $counter
"<? context['counter'] + 1 ?>"
-
Click Save.
Add a second conditional response to the Not found section that checks whether the counter is greater than 1, which indicates that the user provided an invalid response 3 times previously. In this case, the dialog assigns the time value on the user's behalf to the popular dinner reservation time of 8 PM. The user has a chance to change the time value when the confirmation slot is triggered.
-
In the Not found section, add a response with the following condition:
Condition details If assistant recognizes Assistant responds Then assistant should $counter > 1
You seem to be having trouble choosing a time. I will make the reservation at 8PM for you.
Wait for user input -
You must set the $time variable to 8 PM. In Assistant responds, click the options menu and select Open context editor.
-
Set the context by using these values:
Set context Variable Value $time
"<? '20:00:00'.reformatDateTime('h:mm a') ?>"
-
Click Save.
The conditional response that you just added has a more precise condition than the true condition that is used by the first conditional response. You must move this response so it comes before the original conditional response or it is never triggered.
-
Hover on the response you just added, use the up arrow to move it up, and then click Save.
-
Test your changes by using the following script.
Script details Speaker Utterance You I want to make a reservation. Assistant I can make a reservation for you. Just tell me the day and time of the reservation, and how many people will be dining. You Tomorrow Assistant Friday, December 29 it is. What time do you want the reservation to be made for? You orange Assistant Please specify the time that you want to eat. The restaurant seats people between 9AM and 9PM. You pink Assistant Please specify the time that you want to eat. The restaurant seats people between 9AM and 9PM. You purple Assistant You seem to be having trouble choosing a time. I will make the reservation at 8 PM for you. How many people will be dining?
Connect to an external service
Now that your dialog can collect and confirm a user's reservation details, you can call an external service to reserve a table in the restaurant's system or through a multi-restaurant online reservations service. See Making programmatic calls from a dialog node for more details.
In the logic that calls the reservation service, be sure to check for has_skipped_slots
and do not continue with the reservation if it is present.
Summary
In this tutorial, you tested a node with slots and made changes that optimize how it interacts with real users. For more information about this subject, see Gathering information with slots.