alexa not recognizing intent
Asked Answered
E

3

7

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.

Eyre answered 28/7, 2018 at 23:46 Comment(0)
E
9

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)
Eyre answered 29/7, 2018 at 13:31 Comment(2)
This is the correct solution. The given code executes as expected.Drayton
Thanks a bunch. Saved me so much time.Sobel
S
4

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.

Savarin answered 30/7, 2018 at 5:24 Comment(0)
R
1

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.

Rowe answered 29/7, 2018 at 3:59 Comment(4)
All three of your suggestions work, thanks! I'm feel like I'm really close. But for number 3: what I want to achieve is use LaunchRequest to open the skill. And then ask it the currentbpm intent while in the skill, not externally. (So I won't have to ask 'Alexa ask my personal heartbeat.....' before the actual intent request.) Like with the Google Assistant, where you ask 'Ok Google talk to my personal heartbeat'. And then you can just ask 'how fast is my heart beating right now'.Eyre
By default, Alexa will end the session as soon as it responds so wen u ask any question it doesn’t reach your skill and it doesn’t give correct response you are expecting. It’s a behaviour of Alexa. So please set shudendsession(false) to response you send from Launch request intent. It will work..Rowe
thank you, this worked! I'll update the working script with your adjustments.Eyre
Cheers... hope my code and suggestions helped you. If so please accept my answerRowe

© 2022 - 2024 — McMap. All rights reserved.