[ ] Regression (a behavior that used to work and stopped working in a new release)
[ ] Bug report
[ ] Performance issue
[ ] Feature request
[x ] Documentation issue or request
[ ] Other... Please describe:
I have a skill that uses a dialog model to prompt the user for a series of inputs, all of which are required slots with the type AMAZON.NUMBER. When a user gives a numerical response, everything works fine. However, if the user gives a non-numeric response, such as "yellow", the slot value is filled in with "value": "?" and moves on to the next slot. How can I get it to reprompt the user for that slot again if they provide an invalid response? I've poured over the documentation and can't find anything. Ideally I would want the skill to reprompt the user until a valid input is given (i.e., the value isn't "?")
Strangely, if i set the type to AMAZON.DATE, it will automatically reprompt once, and then if an invalid type is provided a second time the skill will just quit out.
I used the Plan My Trip example as my starting point, if that helps.
Hi @elewin ,
I just tried with both AMAZON.NUMBER and AMAZON.DATE, and in both cases, if there Alexa couldn't resolve the value to the corresponding slot type, the value field under the slots is not populated. For example, following are the request JSON blobs for the tests :
-> Alexa, open my test and take the number ten
"request": {
"type": "IntentRequest",
"requestId": "xxxxxx",
"timestamp": "2018-08-23T16:24:00Z",
"locale": "en-US",
"intent": {
"name": "NumberIntent",
"confirmationStatus": "NONE",
"slots": {
"num": {
"name": "num",
"value": "10",
"confirmationStatus": "NONE"
}
}
},
"dialogState": "STARTED"
}
-> Alexa, open my test and take the number yellow
"request": {
"type": "IntentRequest",
"requestId": "xxxx",
"timestamp": "2018-08-23T16:28:29Z",
"locale": "en-US",
"intent": {
"name": "NumberIntent",
"confirmationStatus": "NONE",
"slots": {
"num": {
"name": "num",
"confirmationStatus": "NONE"
}
}
},
"dialogState": "STARTED"
}
Maybe you can check if the value field is present in the slot and use that to reprompt the user from your intent handler. Does that help?
The value field is present, but it looks like this, with question marks instead of a number in cases where a non-number was given:
"response": {
"directives": [
{
"type": "Dialog.Delegate",
"updatedIntent": {
"name": "MRRIntent",
"confirmationStatus": "NONE",
"slots": {
"growthValue": {
"name": "growthValue",
"value": "?",
"confirmationStatus": "NONE"
},
"churnValue": {
"name": "churnValue",
"value": "?",
"confirmationStatus": "NONE"
},
"startingValue": {
"name": "startingValue",
"value": "10",
"confirmationStatus": "NONE"
}
}
}
}
]
}
Where in intent handler would I be able to check for this value and reprompt on the particular slots that are failing? I am using the Dialog.Directive which the docs say not to use reprompt with ( https://developer.amazon.com/zh/docs/custom-skills/dialog-interface-reference.html#details ), unless I am misunderstanding it.
My intent handlers looks like this:
const InProgressPlanMyTripHandler = {
canHandle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
return request.type === 'IntentRequest' &&
request.intent.name === 'MRRIntent' &&
request.dialogState !== 'COMPLETED';
},
handle(handlerInput) {
console.log('in progrress handler', JSON.stringify(handlerInput))
const currentIntent = handlerInput.requestEnvelope.request.intent;
return handlerInput.responseBuilder
.addDelegateDirective(currentIntent)
.getResponse();
},
};
const CompletedPlanMyTripHandler = {
canHandle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
return request.type === 'IntentRequest' && request.intent.name === 'MRRIntent';
},
handle(handlerInput) {
const responseBuilder = handlerInput.responseBuilder;
const filledSlots = handlerInput.requestEnvelope.request.intent.slots;
const slotValues = getSlotValues(filledSlots);
let speechOutput = `Your values are: startingValue: ${slotValues.startingValue.synonym} growthValue: ${slotValues.growthValue.synonym}, and churnValue: ${slotValues.churnValue.synonym}`
return responseBuilder
.speak(speechOutput)
.getResponse();
},
};
Any ideas ? Thanks
Hi @elewin ,
I would suggest to check for the input value in the handle function of your InProgressPlanMyTripHandler. If handlerInput.requestEnvelope.request.intent.slots[{slotName you want to check}].value is not a valid value, instead of sending back delegate directive which hands over the control to alexa, send back a elicit directive to explicitly ask user to provide a valid value.
Regards
Thanks! That put me on the right track.
For others that may run into this in the future, this is what I added to the InProgressPlanMyTripHandler:
const InProgressPlanMyTripHandler = {
canHandle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
return request.type === 'IntentRequest' &&
request.intent.name === 'MRRIntent' &&
request.dialogState !== 'COMPLETED';
},
handle(handlerInput) {
console.log('in progrress handler', JSON.stringify(handlerInput))
const currentIntent = handlerInput.requestEnvelope.request.intent;
let slots = currentIntent.slots;
let badInputSlot;
for (let x in slots) {
if (slots.hasOwnProperty(x) && slots[x].hasOwnProperty('value')) {
if (isNaN(slots[x].value)) {
badInputSlot = x;
break;
}
}
}
if (badInputSlot) {
return handlerInput.responseBuilder.speak('I do not understand. Please respond with a number.').reprompt('Please respond with a number').addElicitSlotDirective(badInputSlot, currentIntent).getResponse();
} else {
return handlerInput.responseBuilder
.addDelegateDirective(currentIntent)
.getResponse();
}
},
};
What was also frustrating for me is that there was little to no documentation on how addElicitSlotDirective worked; the most I was able to find out about it was this:
https://ask-sdk-for-nodejs.readthedocs.io/en/latest/Building-Response.html?highlight=elicit
But I have it up and running now, so thanks!
@elewin , glad it worked. We are always working on improving our documentation. At the meantime, we appreciate any support from our community as well. We will accept PRs on improving documentation. The source files are located under the docs/ folder
Regards
We now have slot validation that you can define in the voice interaction model. For those reading here's more info: https://developer.amazon.com/docs/custom-skills/validate-slot-values.html
I came accross a similar issue which I fixed by adding a manual check via anifstatement to make sure the value is indeed a number between certain values.
As I disabled auto delegation for this intent, and never delegated the dialog back to Alexa, I had to validate the slots myself as seen below. It's explained in their documentation that validations rule work only when the dialogue is delegated to Alexa: https://developer.amazon.com/en-US/docs/alexa/custom-skills/validate-slot-values.html
...
else if (score_one < 1 || score_one > 5 || score_one==="?")
{
console.log ("DailyCheckinIntentHandler: score one rule:" + score_one)
const rule = 'I think this score is not within one and five.';
while (handlerInput.requestEnvelope.request.intent.slots.score_one.value < 1 || handlerInput.requestEnvelope.request.intent.slots.score_one.value > 5 || handlerInput.requestEnvelope.request.intent.slots.score_one.value==="?") {
return handlerInput.responseBuilder
.speak(rule)
.addElicitSlotDirective('score_one')
.reprompt("I didn't quite hear that. " + firstQuestion)
.getResponse();
}
}
...
Most helpful comment
We now have slot validation that you can define in the voice interaction model. For those reading here's more info: https://developer.amazon.com/docs/custom-skills/validate-slot-values.html