Reputation: 23
I am trying to implement a check that gives the user an option to update the value of a specific slot within an intent after user Denies at confirmIntent step.
I have a newUser intent that has the following slots:
The updateNewUser is a custom slot type (expand values) with following entries:
Now, when a user Denies at confirmIntent step, I ask the user the slot which he/she wants to update/change, and store the user input value in updateNewUser slot using Lambda function elicitSlot. But here comes the problem.
Following is my Lambda code:
def newUser(intent_request):
slot_details = intent_request['currentIntent']['slotDetails']
slots = intent_request['currentIntent']['slots']
f_name = slots['f_name']
l_name = slots['l_name']
cellNum = slots['cellNum']
emailAdd = slots['emailAdd']
updateSlot = slots['updateNewUser']
session_attributes = intent_request['sessionAttributes'] if intent_request['sessionAttributes'] is not None else {}
confirmation_status = intent_request['currentIntent']['confirmationStatus']
if intent_request['invocationSource'] == 'DialogCodeHook':
validation_result = validate_newusr(intent_request['currentIntent']['slots'], intent_request['currentIntent']['slotDetails'])
if not validation_result['isValid']:
slots = intent_request['currentIntent']['slots']
slots[validation_result['violatedSlot']] = None
slots['updateNewUser'] = None
return elicit_slot(
session_attributes,
intent_request['currentIntent']['name'],
slots,
validation_result['violatedSlot'],
validation_result['message']
)
if confirmation_status == 'Denied':
slots = intent_request['currentIntent']['slots']
return elicit_slot(
session_attributes,
intent_request['currentIntent']['name'],
slots,
'updateNewUser',
{
'contentType': 'SSML',
'content': '<speak>Which value do you want to change?</speak>'
}
)
return delegate(
session_attributes,
intent_request['currentIntent']['slots']
)
return close(
session_attributes,
'Fulfilled',
{
'contentType': 'SSML',
'content': '<speak>Your account has been created, and you will shortly receive an email to set up your password. Now, would you like to make a reservation for yourself, or for somone else?</speak>'
}
)
And following is the validation code:
def validate_newusr(slots, slot_details):
f_name = slots['f_name']
l_name = slots['l_name']
cellNum = slots['cellNum']
emailAdd = slots['emailAdd']
updateSlot = slots['updateNewUser']
if f_name:
if ' ' in f_name:
f_name = f_name.replace(' ', '')
slots['f_name'] = f_name
if l_name:
if ' ' in l_name:
l_name = l_name.replace(' ', '')
slots['l_name'] = l_name
if cellNum and (len(cellNum) != 10):
return build_validation_result(
False,
'cellNum',
'<speak>Please provide a valid, 10 digit phone number.</speak>'
)
return build_validation_result( #I use this to check whether updateNewUser stores something or not. But of course I only paste this code here at confirmIntent step; not before.
False,
'updateNewUser',
str(updateSlot)
)
if updateSlot: # this code won't run because updateSlot is empty
return build_validation_result(
False,
'updateNewUser',
str(updateSlot)
)
if len(slot_details['updateNewUser']['resolutions']) == 1 and str(list(slot_details['updateNewUser']['resolutions'][0].values())[0]).lower() in ['last name','first name', 'cell phone number', 'email address']:
slots['updateNewUser'] = list(slot_details['updateNewUser']['resolutions'][0].values())[0]
if len(slot_details['updateNewUser']['resolutions']) == 0 or str(list(slot_details['updateNewUser']['resolutions'][0].values())[0]).lower() not in ['last name','first name', 'cell phone number', 'email address']:
return build_validation_result(
False,
'updateNewUser',
'<speak>Sorry, I could not understand. Please say first name, last name, phone number, or email address.</speak>'
)
if slots['updateNewUser'] == 'first name':
return build_validation_result(
False,
'f_name',
'<speak>Please say your updated first name.</speak>'
)
if slots['updateNewUser'] == 'last name':
return build_validation_result(
False,
'l_name',
'<speak>Please say your updated last name.</speak>'
)
if slots['updateNewUser'] == 'cell phone number':
return build_validation_result(
False,
'cellNum',
'<speak>Please say, or type your updated phone number.</speak>'
)
if slots['updateNewUser'] == 'email address':
return build_validation_result(
False,
'emailAdd',
'<speak>Please say your updated email address.</speak>'
)
return {'isValid': True}
Here are some screenshots of the chat:
It only accepts exact match in my case. But if I make updateNewUser slot as mandatory/required, it starts to accept similar words too and works fine. But I need this slot as optional. My goal is to update a single slot instead of repeating the whole intent. What am I doing wrong?
Upvotes: 1
Views: 1078
Reputation: 579
At first glance, I would suggest changing the resolution of the updateNewUser
slot type to restricted values and synonyms. That will enable you to add synonyms that match with your base value.
Ensure that your valueSelectionStrategy
is TOP_RESOLUTION
so that you get the base value rather than the user's raw input.
This simplifies your lambda as you would only need to cater for a single value per line.
Upvotes: 0