How to add validation on a slot value in alexa skill - alexa

I have a single intent in my skill NoteMyDetail which has three required slots: name, age, gender.
I have various utterances like "note my details", "note my name as {name}" etc.
So if I say "note my details" it one by one asks for all the values and if I say "note my name as Joe" it asks for only the age and the gender.
Now the issue I am facing is how to add validations for these slots because when Alexa asks: "what is your age" and I reply my name is Joe or any gibberish it sends a "?" in the slot value.
How do I make sure that the value is a number only for age?
EDIT: So I used the code of the link: https://gist.github.com/stormbytes/7ee3a05aa03c0ada0621dde746f2a6f9#file-index-js-L31
I have the slots as required, so it asks for all the values and then checks for the value which disrupts the flow, so I made the slot values as not mandatory and checked if the value if defined/undefined. I am getting the following response in the simulator but it says "There was a problem with the requested skill's response"
{
"body": {
"version": "1.0",
"response": {
"outputSpeech": {
"type": "SSML",
"ssml": "<speak> Sorry I did not get the age, please say it again </speak>"
},
"directives": [
{
"type": "Dialog.ElicitSlot",
"slotToElicit": "ageValue"
}
],
"reprompt": {
"outputSpeech": {
"type": "SSML",
"ssml": "<speak> Please tell me your age </speak>"
}
},
"shouldEndSession": false
},
"sessionAttributes": {},
"userAgent": "ask-nodejs/1.0.25 Node/v6.10.3"
}
}

This is a typical case where you can use a recently released feature called Slot Validation. All you have to do is go to the page where you defined your slot as required and click on the Validations tab:
and add a validation rule. In your case where you're dealing with age, most probably and AMAZON.Number, you can set up two rules, one for the lower limit of the age (e.g. 0) and another one for the top limit (e.g. 100). Take a look at my example using a numeric slot called ownedMiles:
Once you do that anything that is not a number within the range defined by the validation rules will cause the provided prompt in the validation to be spoken and Alexa will try to collect the value again.

Related

InvalidSlotTypeLiteral: Slot type "AMAZON.LITERAL" for slot "Text" in intent "RawText" is not valid

AMAZON.LITERAL is deprecated as of October 22, 2018. Older skills built with AMAZON.LITERAL.
What is the alternative to AMAZON.LITERAL, I want each and every word spoken by user from Alexa device in my endpoint API.
I have created custom slots, but my endpoint is not called everytime.
Anyone have solution to this?
You will not get the entire user input through any inbuilt slots or intents. The closest one to your requirement that I can think of is AMAZON.SearchQuery.
AMAZON.SearchQuery
AMAZON.SearchQuery is a phrase-type slot that lets you capture less-predictable input that makes up the search query. You can use phrase slots when you cannot predict all possible values the user might say, or when there may not be an identifiable pattern that can be captured by a custom slot. The intended use of this slot is to capture short messages, comments, search queries, and other short free-form text, not the entire user spoken utterance.
Ex:
{
"intents": [
{
"name": "SearchIntent",
"slots": [
{
"name": "Query",
"type": "AMAZON.SearchQuery"
},
{
"name": "CityList",
"type": "AMAZON.US_CITY"
}
],
"samples": [
"search for {Query} near me",
"find out {Query}",
"search for {Query}",
"give me details about {CityList}"
]
}
]
}
You cannot add sample intent utterances consisting of only phrase type slots.
That means, you cannot give something like this:
{
"name": "QueryIntent",
"slots": [
{
"name": "query",
"type": "AMAZON.SearchQuery"
}
],
"samples": [
"{query}" // utterance with only phrase-type slot
]
}
More on AMAZON.SearchQuery here
Alexa will always will fire a POST request to your skill's endpoint with a payload whenever there is a user interaction.

How to use Dialog.ElicitSlot for Python as Runtime environment

I want to fill a slot not at the beginning of the invocation of the intent, but at a later part in the intent request. I want to provide user some options, and I want them to select one out of those. For that I'm trying to use Dialog.ElicitSlot, but somehow I'm getting an error :
"Request to skill endpoint resulted in an error."
I'm returning this when I need the user to select an option from my list.
return {
"version": "1.0",
"sessionAttributes": {},
"response": {
"outputSpeech": {
"type": "PlainText",
"text": "These are the multiplex" + ("es" if len(multi_list) > 1 else "") + " " + outputSpeech + ". Please select one out of these."
# outputSpeech contains the list of options I want the user to select from
},
"shouldEndSession": False,
"directives": [
{
"type": "Dialog.ElicitSlot",
"slotToElicit": "MULTIPLEX",
"updatedIntent": {
"name": "GetMovieDetails",
"confirmationStatus": "NONE",
"slots": {
"CITY" : {
"name" : "CITY",
"confirmationStatus" : "NONE",
"value" : city # this is already filled, it is just anti-capitalised
},
"NAME" : {
"name" : "NAME",
"confirmationStatus" : "NONE",
"value" : movie_name # this is already filled, it is just anti-capitalised
},
"MULTIPLEX" : {
"name" : "MULTIPLEX",
"confirmationStatus" : "NONE",
}
}
}
}
]
}
I'm testing my skill using python-lambda-local, it is working fine on my local machine (I just had to change the dialogState to "COMPLETED" manually, like the one here). It returns everything written above. But It gives an error while testing it on Skill Tester. Here is the output which is returned in the Skill Tester.
PS : I did not check the Slot Filling check box in the Build Section. (As I need the slot to be filled later), and here is the complete code just in case.
Try with omitting the entire "updatedIntent" part, as this information is not required for ElicitSlot.
But more important: You have to make sure that your script returns actual text in JSON-format!
Have a look at http://flask.pocoo.org/docs/1.0/api/#flask.json.jsonify
or https://docs.python.org/2/library/json.html
God, I hate to admit this.
The Dialog.ElicitSlot works fine, and the way I expect it to do so.
The error with my code is, there is no error. I figured my skill was taking some time to fetch data from remote site and doing some calculations on it. So I increased the time out and bam, it worked.
It is always a better to test your skill locally, but it is great to test it once on the aws lambda console. I don't know why I didn't do that earlier.
So to conclude, I just had to increase the timeout in my skill.

How can Alexa take a slot-only utterance?

I'm trying to write my first Alexa skill, but the application flow is a bit confusing, even reading all the documentation about dialogue delegation etc etc. I'd really love a bit of advice.
The Flow I'm Pursuing
"Alexa, start Movietime Quiz."
Welcome to Movietime Quiz. Before we begin, what team are you on: red or blue?
"Blue."
Blue was always the best team. Question 1: which of these films was not directed by Alfred Hitchcock? A: Vertigo, B: Rope, C: Happy Gilmore.
"C."
Correct! 10 points to the blue team. Question 2...
This is a boiled-down example to illustrate my problem in the shortest, clearest way, before you wonder why teams need to be involved in this.
My Instinct/Naive Approach
Have the initial launch-request handler say welcome-and-what-team, and then have two intents. The first would obviously be AnswerQuestionIntent, which listens for "A", "B", "C" or "D." The second would be SetTeamIntent, which listens for "red" or "blue."
I'd have an array with ~100 trivia questions. When the game starts, set a session attribute 'currentQuestion' to 0. In AnswerQuestionIntent, after handling the user's correct/incorrect response, increment that number, and if it's at 9, end the game; if not, ask a random question.
My Problem
I can't actually figure out how to have Alexa use a single slot as an utterance. I mean, I'd want to have a 'team' slot type (values 'red' and 'blue') and an 'answer' slot type (values 'A', 'B', 'C', and 'D'). SetTeamIntent should be activated by the utterance {team} and AnswerQuestionIntent by {answer}, but the developer.amazon.com skill builder gives me 'Bad Request' errors when I try to set that.
I tried looking at the SDK examples on GitHub, but I'm a bit lost because I've been using the GUI skill builder while learning and am not sure exactly how it maps -- not well enough to read the solution, anyway.
There is two different ways to handle this.
1. ElicitSlot Directive WITH Dialog Model
After you launch your skill and trigger an intent you can respond with a elicitslot directive.
Interaction Model: You define a slot and an intent, for example {team} and {answer} in PlayGameIntent. Provide utterances for the intent to get triggered, for example "start a game".
Skill: After triggering the PlayGameIntent. Return a response with a elicit slot directive. Something like the following.
{
"version": "1.0",
"sessionAttributes": {},
"response": {
"outputSpeech": {
"type": "PlainText",
"text": "What team are you on? Blue or Red? "
},
"shouldEndSession": false,
"directives": [
{
"type": "Dialog.ElicitSlot",
"slotToElicit": "team",
"updatedIntent": {
"name": "PlayGameIntent",
"confirmationStatus": "NONE",
"slots": {
"team": {
"name": "team",
"confirmationStatus": "NONE"
},
"answer": {
"name": "answer",
"confirmationStatus": "NONE"
}
}
}
}
]
}
}
The User can now provide an answer for the slot {team} and Alexa sends another IntentRequest for PlayGameIntent. You reelicit as many times as you need until your game is finished.
2. Custom Intents WITHOUT Dialog Model
Without using the Dialog Model you have no restriction with only-slot-utterances. You can build your intent schema as you described. If you leave the Skill Builder Beta you automatically disable the Dialog Model for your Interaction Model.
You can then build an intent schema with sample utterances like this:
AnswerQuestionIntent {answer}
SetTeamIntent {team}

How do i extract the original date value passed from the user input

Context:
The Watson Conversation bot has a node that gets triggered by three input entities from the user, this works fine, but i want the reply from the bot to be
"Checking if you have a lecture tomorrow. Give me a moment"
then there's a query in the background building up the answer that gets replied later to the user.
the strong word tomorrow is an #sys-date entity, but i want it to reply to the user what he/she said instead of the date, because the bot can check no both weeks months ect, all valid date formats, and the reply would look much better if i could use the original text from the user.
This kind of origin retrieval will be used for other entities aswell when i get it working.
You can use the context variable in the case, and if you want to get specific data, you can use regex to extract the user input:
Example all user input
"date": "<? input.text?>"
or for exactly what the user input, ex: "this week"
"date": "<?#sys-date.literal?>"
Etc..
Use the variable with the .literal, see my complete example:
{
"context": {
"date": "<?#sys-date.literal?>"
},
"output": {
"text": {
"values": [
"Checking if you have a lecture $date. Give me a moment."
],
"selection_policy": "sequential"
}
}
}
Documentation examples
:

My custom slot type is taking on unexpected values

I noticed something strange when testing my interaction model with the Alexa skills kit.
I defined a custom slot type, like so:
CAR_MAKERS Mercedes | BMW | Volkswagen
And my intent scheme was something like:
{
"intents": [
{
"intent": "CountCarsIntent",
"slots": [
{
"name": "CarMaker",
"type": "CAR_MAKERS"
},
...
with sample utterances such as:
CountCarsIntent Add {Amount} cars to {CarMaker}
Now, when testing in the developer console, I noticed that I can write stuff like:
"Add three cars to Ford"
And it will actually parse this correctly! Even though "Ford" was never mentioned in the interaction model! The lambda request is:
"request": {
"type": "IntentRequest",
...
"intent": {
"name": "CountCarsIntent",
"slots": {
"CarMaker": {
"name": "ExpenseCategory",
"value": "whatever"
},
...
This really surprises me, because the documentation on custom slot types is pretty clear about the fact that the slot can only take the values which are listed in the interaction model.
Now, it seems that values are also parsed dynamically! Is this a new feature, or am I missing something?
Actually that is normal (and good, IMO). Alexa uses the word list that you provide as a guide, not a definitive list.
If it didn't have this flexibility then there would be no way to know if users were using words that you weren't expecting. This way you can learn and improve your list and handling.
Alexa treat the provided slot values as 'Samples'. Hence slot values which are not mentioned in interaction model will also get mapped.
When you create a custom slot type, a key concept to understand is
that this is training data for Alexa’s NLP (natural language
processing). The values you provide are NOT a strict enum or array
that limit what the user can say. This has two implications
1) words and phrases not in your slot values will be passed to you,
2) your code needs to perform any validation you require if what’s
said is unknown.
Since you know the acceptable values for that slot, always perform a slot-value validation on your code. In this way when you get something other than a valid car manufacturer or something which you don't support, you can always politely respond back like
"Sorry I didn't understand, can you repeat"
or
"Sorry we dont have in our list. can you please
select something from [give some samples from your list]"
More info here

Resources