I'm using lambda to create the skill, the same logic in hello world example. Is possible to get what user said? In Text?
const HelloWorldIntentHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'IntentRequest'
&& handlerInput.requestEnvelope.request.intent.name === 'HelloWorldIntentHandler';
},
async handle(handlerInput) {
const speechText = 'Hello World!';
return handlerInput.responseBuilder
.speak(speechText)
//.reprompt('add a reprompt if you want to keep the session open for the user to respond')
.getResponse();
}
};
Alexa does not provide the full user input in text. So the only way to get what the user says is to use slots. Read about how to use Intents with Slots here.
Here are the different types of slots (slotTypes) that you can use to help Alexa extract the values you want from the user input. List of Slot Types.
If you don't know the specific type of data you want to get from the user, then you could use the slot type AMAZON.SearchQuery to capture phrases and sentences.
Then it should deliver at least more of the user input (as Alexa understood it) into that slot as text.
AMAZON.SearchQuery
As you think about what users are likely to ask, consider using a built-in or custom slot type to capture user input that is more predictable, and the AMAZON.SearchQuery slot type to capture less-predictable input that makes up the search query.
Related
I am new to alexa. I created a custom intent to just repeat a custom text (no slots etc). However my custom intent is never invoked. saved and deployed my code. I get empty JSON request and response - meaning my intent is never invoked. I saved the code and deployed. Adding below the intent node js code handler.
// Begin Code added by Gopalakrishnan for Handling Check Workday Inbox
const checkInboxIntentHandler = {
canHandle(handlerInput) {
return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
&& Alexa.getIntentName(handlerInput.requestEnvelope) === 'checkInbox';
},
handle(handlerInput) {
const speakOutput = 'I am here to check Workday Inbox!';
return handlerInput.responseBuilder
.speak(speakOutput)
//.reprompt('add a reprompt if you want to keep the session open for the user to respond')
.getResponse();
}
};
/*End*/
There is nothing wrong with the code provided here. Here are a couple of things I recommend checking:
Check that your handler is added to the skill with the addRequestHandlers function in the skill builder. Typically this builder is at the bottom of your index.js file.
Check that the intent name "checkInbox" is spelled the same in both your interaction model and canHandle method.
Make sure that your interaction model with the added checkInbox intent has been built in the skills console.
Make sure that you are launching your skill before trying to invoke this intent.
I am trying to create a bot that server-mutes everyone if a specific person mutes themself.
I can get the user ID or other details via message.member.
Is there any way to find out if that user is muted or even if the person is in a voice channel?
This is what I found so far:
client.on('voiceStateUpdate', (oldmember, newmember) => {
let oldvoice = oldmember.voiceChannel;
let newvoice = newmember.voiceChannel;
if (oldvoice && newvoice && oldvoice.id != newvoice.id)
var channelStatus = 'Moved'
console.log(oldvoice)
})
But I don't understand it and it just returns undefined.
Edit: Found a way easier solution:
msg.member.voice.selfMute
Old one:
client.channels.cache.get(msg.member.voice.channel.id).guild.voiceStates.cache.get(msg.author.id).selfMute
let's break it down:
client.channels.cache gives you of all text and voice channels in your discord server
get(msg.member.voice.channel.id) gives you the id of the voice channel, the user that wrote the bot command (considering, you have stored the message in a variable e.g.: msg)
.guild.voiceStates.cache gives you a list of everyone in the channel
.get(msg.author.id) takes the user that wrote the last message
.selfMute returns the mute state
btw there are other pretty useful things too like selfDeafen, streaming and more
I have created a skill with name "BuyDog" and its invocation name is "dog app"
So that should mean, I can use the intents defined inside only after the invocation name is heard. (is that correct?)
Then I have defined the Intents with slots as:
"what is {dog} price."
"Tell me the price of {dog}."
where the slot {dog} is of slot type "DogType". I have marked this slot as required to fulfill
Then I have added the endpoint to AWS lambda function where I have used the blueprint code of factskills project in node.js, and done few minor changes just to see the working.
const GET_DOG_PRICE_MESSAGE = "Here's your pricing: ";
const data = [
'You need to pay $2000.',
'You need to pay Rs2000.',
'You need to pay $5000.',
'You need to pay INR 3000.',
];
const handlers = {
//some handlers.......................
'DogIntent': function () {
const factArr = data;
const factIndex = Math.floor(Math.random() * factArr.length);
const randomFact = factArr[factIndex];
const speechOutput = GET_DOG_PRICE_MESSAGE + randomFact;
}
//some handlers.......................
};
As per the about code I was expecting when
I say: "Alexa open dog app"
It should just be ready to listen to the intent "what is {dog} price." and the other one. Instead it says a random string from the node.js code's data[] array. I was expecting this response after the Intent was spoken as the slot was required for intent to complete.
And when
I say: "open the dog app and Tell me the price of XXXX."
It asks for "which breed" (that is my defined question) But it just works fine and show the pricing
Alexa says: "Here's your pricing: You need to pay $5000."
(or other value from the data array) for any XXXX (i.e. dog or not dog type).
Why is alexa not confirming the word is in slot set or not?
And when
I say: "open the dog bark".
I expected alexa to not understand the question but it gave me a fact about barking. WHY? How did that happen?
Does alexa have a default set of skills? like search google/amazon etc...
I am so confused. Please help me understand what is going on?
Without having your full code to see exactly what is happening and provide code answers, I hope just an explanation for your problems/questions will point you in the right direction.
1. Launching Skill
I say: "Alexa open dog app"
It should just be ready to listen to the intent...
You are expecting Alexa to just listen, but actually, Alexa opens your skill and is expecting you to have a generic welcome response at this point. Alexa will send a Launch Request to your Lambda. This is different from an IntentRequest and so you can determine this by checking request.type. Usually found with:
this.event.request.type === 'LaunchRequest'
I suggest you add some logging to your Lambda, and use CloudWatch to see the incoming request from Alexa:
console.log("ALEXA REQUEST= " + event)
2. Slot Value Recognition
I say: "open the dog app and Tell me the price of XXXX."
Why is alexa not confirming the word is in slot set or not?
Alexa does not limit a slot to the slot values set in the slotType. The values you give the slotType are used as a guide, but other values are also accepted.
It is up to you, in your Lambda Function, to validate those slot values to make sure they are set to a value you accept. There are many ways to do this, so just start by detecting what the slot has been filled with. Usually found with:
this.event.request.intent.slots.{slotName}.value;
If you choose to set up synonyms in the slotType, then Alexa will also provide her recommended slot value resolutions. For example you could inlcude "Rotty" as a synonym for "Rottweiler", and Alexa will fill the slot with "Rotty" but also suggest you to resolve that to "Rottweiler".
var resolutionsArray = this.event.request.intent.slots.{slotName}.resolutions.resolutionsPerAuthority;
Again, use console.log and CloudWatch to view the slot values that Alexa accepts and fills.
3. Purposefully Fail to Launch Skill
I say: "open the dog bark".
I expected alexa to not understand the question but it gave me a fact about barking.
You must be doing this outside of your Skill, where Alexa will take any inputs and try to recognize an enabled skill, or handle with her best guess of default abilities.
Alexa does have default built-in abilities (not skills really) to answer general questions, and just be fun and friendly. You can see what she can do on her own here: Alexa - Things To Try
So my guess is, Alexa figured you were asking something about dog barks, and so provided an answer. You can try to ask her "What is a dog bark" and see if she responds with the exact same as "open the dog bark", just to confirm these suspicions.
To really understand developing an Alexa skill you should spend the time to get very familiar with this documentation:
Alexa Request and Response JSON Formats
You didn't post a lot of your code so it's hard to tell exactly what you meant but usually to handle incomplete events you can have an incomplete even handler like this:
const IncompleteDogsIntentHandler = {
// Occurs when the required slots are not filled
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'IntentRequest'
&& handlerInput.requestEnvelope.request.intent.name === 'DogIntent'
&& handlerInput.requestEnvelope.request.dialogState !== 'COMPLETED'
},
async handle(handlerInput) {
return handlerInput.responseBuilder
.addDelegateDirective(handlerInput.requestEnvelope.request.intent)
.getResponse();
}
you add this handler right above your actual handler usually in the index.js file of your lambda
This might not fix all your issues, but it will help you handle the event when a user doesn't mention a dog.
In Details:
Example:
user:- asks About Cricket News.
Alexa:- Reads about the new.
If users says come again or replay
user: Come again.
Alexa: Must read it again what it spoke earlier.
How to handle this situation using webhooks.
Thanks in advance.
You can make use of sessionAttributes to keep track of the last response that Alexa spoke. Whenever you return a response just store the speech and re-prompt in sessionAttributes and whenever a ComeAgainIntent is triggered, take the value from the sessionAttributes and respond accordingly.
Ex:
...
"sessionAttributes": {
"lastResponse": {
"speech": "This was my last speech",
"reprompt": "This was my lst reprompt"
}
}
...
Every time before building the response store the response as lastSpeech in session attributes and write a comeAgainIntent or use amazon.REPEAT intent to repeat the response by getting lastSpeech from session attributes.
I want to accomplish the following scenario:
A small dialog between Alexa and the user, with the following 2 Intents:
NameIntent: "My name is {name}"
Where {name} is AMAZON.US_FIRST_NAME and with the slot made required and a prompt defined.
ActivityIntent: "I like {activity}"
And here it becomes more difficult. I made {activity} a custom slot and defined some values for it like "fishing, sports" and the like, but obviously there are more answers to this. If I now respond with something I don't have defined (e.g. "darts"), Alexa always goes back to the first intent, as it seems to thing it is a name.
Example:
LaunchRequest: "Welcome. What is your name?"
-> My name is Peter
NameIntent: "Welcome Peter. What do you like to do?" -> Darts
-> "Welcome Darts. What do you like to do?"
I would simply like to have Alexa accept whatever value the user says there, in Dialogflow this would be simply done with an {any} entity.
I followed this blog article from the alexa blog, and there they seem to be able to capture whatever nickname you throw at it, even ones which aren't defined, which is what I want to accomplish here.
Question: How can I capture any kind of input with Alexa, phrases beyond whatever I have defined in the skill builder? How can I make sure this phrase gets directed to the correct intent?
I am a bit frustrated with this, especially if you use ElicitSlotDirectives to specifically ask the user about a slot, and then it jumps to a completely different intent.
The code for the 2 intent handlers:
const NameIntentHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'IntentRequest'
&& handlerInput.requestEnvelope.request.intent.name === 'NameIntent';
},
handle(handlerInput) {
const { intent } = handlerInput.requestEnvelope.request;
const name = intent.slots.name.value;
const speechText = `Welcome ${name}. What is your favourite activity?`;
return handlerInput.responseBuilder
.speak(speechText)
.reprompt(speechText)
.withShouldEndSession(false)
.getResponse();
},
};
const ActivityIntentHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'IntentRequest'
&& handlerInput.requestEnvelope.request.intent.name === 'ActivityIntent';
},
handle(handlerInput) {
const { intent } = handlerInput.requestEnvelope.request;
const activity = intent.slots.activity.value;
const speechText = `You like ${activity}.`;
return handlerInput.responseBuilder
.speak(speechText)
.reprompt(speechText)
.withShouldEndSession(false)
.getResponse();
},
};
It seems that Alexa is having trouble associating activity utterances with your ActivityIntent and instead is invoking the NameIntent again. Relying on Amazon to figure out which intent to use based on slot type has not consistently worked well for me. If you post your intent code that would be very helpful.
It may help to look at a JavaScript example from Amazon here and Amazon's Voice Design Guide.
You might consider using AMAZON.LITERAL built-in custom slot type. This slot type passes the spoken words without any conversion. Although official documents suggest against using it. It was also discontinued once. From the official docs.
Note: Although you can submit new and updated English (US) skills with AMAZON.LITERAL, custom slot types provide better accuracy than AMAZON.LITERAL in most cases. Therefore, we recommend that you consider migrating to custom slot types if possible. Note that AMAZON.LITERAL is not supported for any language other than English (US).
Find more about AMAZON.LITERAL here.
https://developer.amazon.com/docs/custom-skills/literal-slot-type-reference.html