Alexa getting response from user after prompt - alexa

So we are setting up a system in which a user can set reminders. Currently my intent is set up to provide a Day and a Time. If I say something like set reminder for next tuesday at 9pm, in my intent I see the values coming in fine. The issue is if let's say they say something like set reminder for next tuesday, they gave us the day but not time. So in my intent, I have this response:
else if(obj.Day.value && !obj.Time.value) {
this.response.speak(`Looks like you requested a reminder on ${obj.Day.value}, what time would you like the reminder set for?`).listen('Thanks');
console.log(JSON.stringify(this.response, null, 2));
this.emit(':responseReady');
}
The issue I am having is... how do I get what they said? I've also tried this.emit(':ask', '...') but I still don't see what they actually say.
I'm sorry if this is confusing, essentially this is a simplified question.
How do we get the response from the user (for missing information) after Alexa asks something in an intent?

For this, you will want to use the elicitSlot Directive. Docs found here.
Try:
this.emit(':elicitSlot','slotName','intentName');
Alexa will know that you want to fill the next user's response to the Time slot, if you put "Time" into the slotName property above.
In the Alexa Console, you can specify how Alexa should elicit that slot. You can even provide multiple ways of asking and Alexa will choose one.

Related

Accept any user input for Alexa Custom Skill, but include only part of that input in confirmation

I'm trying to build a custom Alexa skill for a gratitude diary. The goal is to have an interaction in which the Alexa device asks the user what they're grateful for, and repeats it back as confirmation.
I'm encountering a problem when it comes to repeating back what the user has said. I'd like the conversation to go like this:
Alexa: What are you grateful for today?
User I'm grateful for dogs
Alexa: You said you're grateful for dogs. Is that correct?
I've set this up as a single intent, as follows:
gratitude_object as a required slot, of type AMAZON.SearchQuery
user utterances for this slot are I'm grateful for {gratitude_object} (and a few variations)
confirmation message for this slot is You're feeling grateful for {gratitude_object}. Is that correct?
The problem I'm encountering is that when I test this model in the Utterance Profiler, it goes like this:
Alexa: What are you grateful for today?
User I'm grateful for dogs
Alexa: You said you're grateful for I'm grateful for dogs. Is that correct?
I'm guessing this is something to do with the fact that AMAZON.SearchQuery will accept anything as valid input, but I'm not sure how to go about resolving this.
I've also tried creating a custom slot for the I'm grateful for phrase:
slot name: gratitude_phrase_initiator
slot type: custom slot type
slot values: "I'm grateful for", "I am grateful for" (etc)
However, if I then try to use this slot in my intent, by making the user utterance for the gratitude_object slot:
{gratitude_phrase_initiator} {gratitude_object}
...then I get the following error:
Sample utterance "{gratitude_statement_initiator} {gratitude_object}" for slot "gratitude_object" in intent "NewEntryIntent" cannot include both a phrase slot and another intent slot. Error code: InvalidSlotSamplePhraseSlot
.
I'd really like to keep the interaction as it is currently, with the user starting by saying "I'm grateful for...". Any suggestions for how I could make this work using the interaction model, or is it just impossible? Is this something I could handle in the code instead of the interaction model?
Looks like you set it up perfectly but you would expect SearchQuery to do a better job of excluding the initial utterance phrase. So you'll have to parse it some more in code. You should use a Lambda Function to string replace the slot value to remove any initial phrases.
Example in Node.js:
var gratitude_object = this.event.request.intent.slots.gratitude_object.value;
var initial_phrases = [
"i'm grateful for",
"i am grateful for",
];
initial_phrases.forEach(function(value){
gratitude_object = gratitude_object.toLowerCase().replace(value,"");
});
Notice the array of intitial phrases are written in lowercase and the forEach loop also makes the slot value lowercase before checking to replace. That way you don't have to worry about case matching when writing the initial phrases you want to remove.

Ask user for input from LaunchIntent

I'm writing a skill in Node JS 8. I have an intent set up with slots and it works properly if I say
Ask {skill name} to {utterance}.
I'd like to design my skill so that the user can just say
Open {skill Name}
and on opening it will ask them for input that will then be handled and passed to the intent. I've seen multiple people say that you can't do this. But I've used 2 skills today that did exactly this. I'm just looking for the correct syntax to do this.
I have:
'LaunchRequest': function() {
this.response.speak("What note would you like?");
this.emit(':responseReady');
}
Which seems like it should work, but I'm pretty new to JS and Alexa.
Yes, it is possible.
When the skill user open your skill, you can give a welcome message followed by a question.
Ex:
[user] : open note skill
[Alexa] : Welcome to note skill. What note would you like?
----------<Alexa will wait for users input>--------
[user] : ABC note.
[Alexa] : <response>
In order for Alexa to wait for users input after it says the welcome message, you need to keep the session alive. The session is kept alive based on shouldEndSession parameter in the response. For any request, if not provided, shouldEndSession defaults to true. In your case, the response to LaunchRequest should have this shouldEndSession parameter set to false. Only by which the session remains open and users can continue interaction.
Ex:
'LaunchRequest': function() {
const speech = "Welcome to note skill. What note would you like?";
const reprompt = "What note would you like?";
this.emit(':ask', speech, reprompt);
}
Read this answer to know more about how you can keep the session alive using ask-nodejs-sdk.
Using Dialog Model
Another way to achieve this is to use Dialog directives. Dialog directives helps you to fill and validate slot values easily. You can use the directives to ask the user for the information you need to fulfill their request.
More information on Dialog directives here

List in custom Alexa skills

I'm new to Alexa Skills but meanwhile I've read tons of information and tutorials.
Fortunately, I'm currently able to create my own custom skill (based on PHP) on my own server and it already works using different intents, utterances, slots etc..
Now, I want Alexa to read a list of items (I send via JSON) in PlainText but I can't find any information how to do this.
I assume there are two options (please correct me if I'm wrong):
Sending a JSON answer including one item - Alexa reads this item - the user says e.g. "next" - Alexa requests my server for the next item - my server sends the next JSON answer ... and so on.
Sending a JSON answer including all items in an array - Alexa reads each item one after another.
I'm not sure which solution is possible and how it can be solved.
So, can anyone help me on this or point me to some information?
Both ways are possible and which one to choose depends on what you are listing.
Using AMAZON.NextIntent
If a single list item include item name and some details about it, then reading out it in one go won't be a good user experience. In this case you can use AMAZON.NextIntent to handle users "next" request.
When the user asks for the list, give the first item in your response and keep a track of the item index in response sessionAttributes. You can also set a STATE attribute too, so that you can check this state in AMAZON.NextIntent handler before you give the next item.
"sessionAttributes": {
"index": 1,
"STATE": "LIST_ITEMS"
}
When the user say "next"
check whether the state is LIST_ITEMS and based on the index give the next item from your list. And in sessionAttributes increment the index
More on sessionAttributes and Response Parameters here
Now, if your items are just names then you can read it one after the other.
In both these solutions it is always good to use SSML rather than just PlainText. SSML gives you more control on how your response is spoken.
More on SSML here

Using sessionAttributes in Alexa Skill

I am building an Alexa skill and not quite sure if I am using sessionAtrributes correctly. I know sessionAttributes are used to carry-forward a session's data to next invocation.
So I have these two intents
1) ListToDoItem
In this intent my skill will look into a database and list out the
to-do items stored in the database. After listing the items, Alexa
will go on to say "do you want me to list detailed info on these
to-do items?", to handle this I will pass the items retrieved in the
previous session as sessionAttributes. When asked to list detailed
info on the items, I will extract the previously forwarded
sessionAtrributes and compose a detailed speech response.
So for this intent I have to sample utterances
list my to-do items
yes
The utterance 'yes' will be used so that the sessionAttributes can be extracted to create a detailed speech response.
2) ListDoneItems
This intent will be used to list out completed items. It is similar to the previous intent, the only difference being, this intent will list out completed items.
For this intent will have 2 sample utterances
list my completed items
yes
Like before it has an 'yes' to generate a detailed speech response based on the sessionAttributes.
But the problem I have is that when I reply 'yes' to the ListDoneItems intent's 'Do you want me to list the completed items'?, the next intent request generated is of type ListToDoItems instead of ListDoneItems, even though I have set shouldEndSession to false in my skill response. This is happening because there is a crossover between sample utterances between my intents. So is having similar intents in different intents wrong? How to design interaction model to create a multi-turn dialog in order to use in sessionAttributes?
I think this will be of use to someone searching for answer.
Basically in the sample utterance you should not include phrases for your re-prompts; i.e. in my case I should not add 'yes' as an utterance. Instead I should be using Amazon.YesIntent.
When using Amazon.YesIntent, you should maintain a state machine in your SessionAttributes pointing to the last invoked intent. For example if two or more of your intents have a possible case where the user response could invoke a YesIntent, you should store the last invoked intent name and the associated session data in the SessionAttributes. So in the function which handles the YesIntent, you should check the state of your previous invocations and delegate to control to the corresponding intent handler.
In my case I will store previously invoked intent name as key and its associated data as it's value in the session.attributes;
"session": {
"new":"false",
"sessionId": "sessionId",
"application": {
"applicationId": "applicationId"
},
"attributes": {
"PreviousIntent": {
"PreviousIntentData"
}
}
In the function which handles YesIntent, check the for the previous state (session.attributes.PreviousIntent) and delegate the control to the function which handles that intent.

Alexa custom skill not giving answers to the default queries

I have created a custom skill for Alexa. I can able to get the response for custom skills also. But I'm getting one issue.
I have created a simple skill with invocation FullName and intent FullNameIntent which has the utterance like What is my full name, then it's returning my full name. But next query, if I'm asking what is the time now, it's giving answers again full name only.
My expected answer is current time as response.
You will have to create separate intent and sample utterances for 'what is the time now'. As you didn't mention anything about the intent for the time I believe you don't have an intent and sample utterance for the same.

Resources