Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

alexa not recognizing intent

I'm trying to add my own responses to custom intents. The LaunchRequest text works, but other than the AMAZON.HelpIntent and other default intents, my own do not get recognized.

Intents:

{
    "interactionModel": {
        "languageModel": {
            "invocationName": "my personal heartbeat",
            "intents": [
                {
                    "name": "AMAZON.FallbackIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.CancelIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.HelpIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.StopIntent",
                    "samples": []
                },
                {
                    "name": "start",
                    "slots": [],
                    "samples": [
                        "Talk to my personal heartbeat"
                    ]
                },

                {
                    "name": "currentbpm",
                    "slots": [],
                    "samples": [
                        "what's my current BPM",
                        "how fast is my heart beating right now",
                        "How many beats per minute is my heart making at the moment"
                    ]
                }

            ],
            "types": []
        }
    }
}

index.js (adapted example from the nodejs tutorial found here: https://github.com/alexa/skill-sample-nodejs-fact/blob/en-US/lambda/custom/index.js I added the CurrentBPM function and added it to the addRequestHandlers at the bottom. The intent name it looks to match is the currentbpm intent in the list above.

/* eslint-disable  func-names */
/* eslint-disable  no-console */

const Alexa = require('ask-sdk');

const GetNewFactHandler = {
  canHandle(handlerInput) {
    const request = handlerInput.requestEnvelope.request;
    return request.type === 'LaunchRequest'
      || (request.type === 'IntentRequest'
        && request.intent.name === 'GetNewFactIntent');
  },
  handle(handlerInput) {
    const speechOutput = "Welcome to your personal heart health monitor. What would you like to know?";

    return handlerInput.responseBuilder
      .speak(speechOutput)
      .withSimpleCard(speechOutput)
      .getResponse();
  },
};

const CurrentBPMHandler = {
  canHandle(handlerInput) {
    const request = handlerInput.requestEnvelope.request;
    return request.type === 'IntentRequest'
      && request.intent.name === 'currentbpm';
  },
  handle(handlerInput) {
    return handlerInput.responseBuilder
      .speak('seventy five bpm')
      .reprompt('seventy five bpm')
      .getResponse();
  },
};

const HelpHandler = {
  canHandle(handlerInput) {
    const request = handlerInput.requestEnvelope.request;
    return request.type === 'IntentRequest'
      && request.intent.name === 'AMAZON.HelpIntent';
  },
  handle(handlerInput) {
    return handlerInput.responseBuilder
      .speak(HELP_MESSAGE)
      .reprompt(HELP_REPROMPT)
      .getResponse();
  },
};

const ExitHandler = {
  canHandle(handlerInput) {
    const request = handlerInput.requestEnvelope.request;
    return request.type === 'IntentRequest'
      && (request.intent.name === 'AMAZON.CancelIntent'
        || request.intent.name === 'AMAZON.StopIntent');
  },
  handle(handlerInput) {
    return handlerInput.responseBuilder
      .speak(STOP_MESSAGE)
      .getResponse();
  },
};

const SessionEndedRequestHandler = {
  canHandle(handlerInput) {
    const request = handlerInput.requestEnvelope.request;
    return request.type === 'SessionEndedRequest';
  },
  handle(handlerInput) {
    console.log(`Session ended with reason: ${handlerInput.requestEnvelope.request.reason}`);

    return handlerInput.responseBuilder.getResponse();
  },
};

const ErrorHandler = {
  canHandle() {
    return true;
  },
  handle(handlerInput, error) {
    console.log(`Error handled: ${error.message}`);

    return handlerInput.responseBuilder
      .speak('Sorry, an error occurred.')
      .reprompt('Sorry, an error occurred.')
      .getResponse();
  },
};

const HELP_MESSAGE = 'You can say tell me a space fact, or, you can say exit... What can I help you with?';
const HELP_REPROMPT = 'What can I help you with?';
const STOP_MESSAGE = 'Goodbye!';


const skillBuilder = Alexa.SkillBuilders.standard();

exports.handler = skillBuilder
  .addRequestHandlers(
    GetNewFactHandler,
    CurrentBPMHandler,
    HelpHandler,
    ExitHandler,
    SessionEndedRequestHandler
  )
  .addErrorHandlers(ErrorHandler)
  .lambda();

When I invoke the skill: 'Alexa start my personal heartbeat.' It does speak the welcome sentence from the script. But when I ask then 'how fast is my heart beating right now', it only responds 'Sorry, not sure' instead of speaking the hardcoded response.

like image 389
DaReal Avatar asked Jul 28 '18 23:07

DaReal


People also ask

How do I add intents to Alexa?

Open the Alexa developer console, and then sign in. On the Skills tab, in the SKILL NAME column, click the name of your custom skill. From the left-hand sidebar, click Custom > Interaction Model > Intents. On the Intents page, click +Add Intent.

What is intent slot annotation?

“Intent” describes the action that the skill is being asked to perform, such as PlayTune or ActivateAppliance. And “slot” describes the entities and classes of entities on which the action is to operate, such as “song,” “'Thriller,'” and “Michael Jackson” in the command “Play 'Thriller' by Michael Jackson.”

How do you fix there was a problem with the requested skill's response?

One simple way to debug this issue is copying the input JSON from Alexa skill simulator and paste it in the lambda's configure test events. Now run test and it'll generate all the error logs in the lambda itself, for your easy reference.

What is Reprompt?

(transitive) To prompt again. The system reprompts the user at every logon.


3 Answers

The solution is to add a line to the response in the LaunchRequest:

.withShouldEndSession(false)

If you don't add it, the default is set to true, so the skill will end right after giving the first response (welcome intent). See the documentation:https://ask-sdk-for-nodejs.readthedocs.io/en/latest/Response-Building.html

Thanks to Suneet Patil I updated the script accordingly (see below) At first only this worked:

  • User: 'Alexa, ask my personal heartbeat how fast my heart is beating right now.'
  • Alexa: '75 bpm'

But I could not reach the intent:

  • User: 'Alexa talk to my personal heartbeat'
  • Alexa: 'Welcome to your personal heart health monitor. What would you like to know?'(exits skill by default)
  • User: 'How fast is my heart beating right now?'
  • Alexa: 'Sorry, I'm not sure.'

With the new script below:

/* eslint-disable  func-names */
/* eslint-disable  no-console */

const Alexa = require('ask-sdk');

const GetNewFactHandler = {
  canHandle(handlerInput) {
    const request = handlerInput.requestEnvelope.request;
    return request.type === 'LaunchRequest'
      || (request.type === 'IntentRequest'
        && request.intent.name === 'start');
  },
  handle(handlerInput) {
    const speechOutput = "Welcome to your personal heart health monitor. What would you like to know?";

    return handlerInput.responseBuilder
      .speak(speechOutput)
      .withSimpleCard(speechOutput)
      .withShouldEndSession(false)
      .getResponse();

  },
};

const CurrentBPMHandler = {
  canHandle(handlerInput) {
    const request = handlerInput.requestEnvelope.request;
    return request.type === 'IntentRequest'
      && request.intent.name === 'currentbpm';
  },
  handle(handlerInput) {
    return handlerInput.responseBuilder
      .speak('seventy five bpm')
      .reprompt('seventy five bpm')
      .getResponse();
  },
};


const HelpHandler = {
  canHandle(handlerInput) {
    const request = handlerInput.requestEnvelope.request;
    return request.type === 'IntentRequest'
      && request.intent.name === 'AMAZON.HelpIntent';
  },
  handle(handlerInput) {
    return handlerInput.responseBuilder
      .speak(HELP_MESSAGE)
      .reprompt(HELP_REPROMPT)
      .getResponse();
  },
};

const ExitHandler = {
  canHandle(handlerInput) {
    const request = handlerInput.requestEnvelope.request;
    return request.type === 'IntentRequest'
      && (request.intent.name === 'AMAZON.CancelIntent'
        || request.intent.name === 'AMAZON.StopIntent');
  },
  handle(handlerInput) {
    return handlerInput.responseBuilder
      .speak(STOP_MESSAGE)
      .getResponse();
  },
};

const SessionEndedRequestHandler = {
  canHandle(handlerInput) {
    const request = handlerInput.requestEnvelope.request;
    return request.type === 'SessionEndedRequest';
  },
  handle(handlerInput) {
    console.log(`Session ended with reason: ${handlerInput.requestEnvelope.request.reason}`);

    return handlerInput.responseBuilder.getResponse();
  },
};

const ErrorHandler = {
  canHandle() {
    return true;
  },
  handle(handlerInput, error) {
    console.log(`Error handled: ${error.message}`);

    return handlerInput.responseBuilder
      .speak('Sorry, an error occurred.')
      .reprompt('Sorry, an error occurred.')
      .getResponse();
  },
};

const HELP_MESSAGE = 'You can say tell me a space fact, or, you can say exit... What can I help you with?';
const HELP_REPROMPT = 'What can I help you with?';
const STOP_MESSAGE = 'Goodbye!';


const skillBuilder = Alexa.SkillBuilders.standard();

exports.handler = skillBuilder
  .addRequestHandlers(
    GetNewFactHandler,
    CurrentBPMHandler,
    HelpHandler,
    ExitHandler,
    SessionEndedRequestHandler
  )
  .addErrorHandlers(ErrorHandler)
  .lambda();

This works now:

  • User: 'Alexa talk to my personal heartbeat'
  • Alexa: 'Welcome to your personal heart health monitor. What would you like to know?'
  • User:'How fast is my heart beating right now?'
  • Alexa: 'seventy-five bpm.'(skill stays open to ask another question)
like image 66
DaReal Avatar answered Oct 15 '22 06:10

DaReal


For any request, if not provided, shouldEndSession defaults to true. In your case, the response to LaunchRequest will not have this shouldEndSession parameter and the session closes.

Though you can always use ask-nodejs-sdk's shouldEndSession(false) to keep-alive the session, you don't have to specifically set this to false every time. Instead, a better approach would be to use a reprompt in your LaunchRequest. And if you include a reprompt() then, the sdk will automatically add "shouldEndSession": false in your response.

With your code as it is right now, your LaunchRequest will wait for 8 seconds and if there is no user response the session will close. But, for CurrentBPMHandler or HelpHandler you have included a reprompt and it will wait another additional 8 seconds after the reprompt. It's always a good idea to include a reprompt when you expect a response from the user.

Your interaction model has an AMAZON.FallbackIntent intent defined, but you haven't handled it in your code. The AMAZON.FallbackIntent helps you handle unexpected utterances, or when a user says something that doesn’t map to any intents in your skill. If there is no handler, then it will be caught in your error handler. There is no issue to handle it as an error, but a better approach would be to add a handler specifically for this and give a response like "Sorry, I didn't understand, can you please rephrase your question" or something similar.

like image 43
johndoe Avatar answered Oct 15 '22 05:10

johndoe


Please make these below changes it works. 1. In interaction model, for intent start just give same utterance as “to start” instead of current. Ex: Alexa, ask my personal heartbeat to start.

  1. In your lambda code, in lambda code in getnewfact method you forgot to change the name of intent from getnewfactintent to start.

  2. For invoking currentbpm intent, use “ Alexa, ask my personal heartbeat how fast is my heart beating right now.

Hope this helps.

like image 36
Suneet Patil Avatar answered Oct 15 '22 06:10

Suneet Patil