Alexa无法识别意图

Posted

技术标签:

【中文标题】Alexa无法识别意图【英文标题】:alexa not recognizing intent 【发布时间】:2019-01-05 15:35:03 【问题描述】:

我正在尝试将自己的响应添加到自定义意图。 LaunchRequest 文本有效,但除了 AMAZON.HelpIntent 和其他默认意图之外,我自己的意图没有得到识别。

意图:


    "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(改编自 nodejs 教程的示例:https://github.com/alexa/skill-sample-nodejs-fact/blob/en-US/lambda/custom/index.js 我添加了 CurrentBPM 函数并将其添加到底部的 addRequestHandlers 中。它看起来匹配的意图名称是上面列表中的 currentbpm 意图。

/* 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();

当我调用该技能时: “Alexa 开始了我的个人心跳。” 它确实说出了剧本中的欢迎词。但是当我当时问“我现在的心跳有多快”时,它只会回答“抱歉,不确定”,而不是说出硬编码的回答。

【问题讨论】:

【参考方案1】:

解决办法是在LaunchRequest的响应中加一行:

.withShouldEndSession(false)

如果不添加,则默认设置为true,因此技能会在给出第一个响应(欢迎意图)后立即结束。 见文档:https://ask-sdk-for-nodejs.readthedocs.io/en/latest/Response-Building.html

感谢Suneet Patil 我相应地更新了脚本(见下文) 起初只有这样有效:

用户:“Alexa,问问我个人的心跳,我现在的心跳有多快。” Alexa:'75 bpm'

但我无法达到目的:

用户:“Alexa 与我的个人心跳对话” Alexa:“欢迎使用您的个人心脏健康监测器。你想知道什么?'(默认退出技能) 用户:“我现在的心跳有多快?” Alexa:“抱歉,我不确定。”

使用下面的新脚本:

/* 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();

现在可以了:

用户:“Alexa 与我的个人心跳对话” Alexa:“欢迎来到您的 个人心脏健康监测器。你想知道什么?' 用户:“我现在的心跳有多快?” Alexa:'75 bpm。'(技能保持开放状态以提出另一个问题)

【讨论】:

这是正确的解决方案。给定的代码按预期执行。 非常感谢。为我节省了很多时间。【参考方案2】:

对于任何请求,如果未提供,shouldEndSession 默认为 true。在您的情况下,对 LaunchRequest 的响应将没有此 shouldEndSession 参数并且会话关闭。

尽管您始终可以使用 ask-nodejs-sdk's shouldEndSession(false) 来保持会话保持活动状态,但您不必每次都专门将其设置为 false。相反,更好的方法是在您的LaunchRequest 中使用reprompt。如果您包含reprompt(),那么sdk 会在您的回复中自动添加"shouldEndSession": false

使用您现在的代码,您的LaunchRequest 将等待 8 秒,如果没有用户响应,会话将关闭。但是,对于CurrentBPMHandlerHelpHandler,您已经包含了一个重新提示,它将在reprompt 之后再等待8 秒。当您期望用户的响应时,包含一个重新提示总是一个好主意。

您的交互模型定义了 AMAZON.FallbackIntent 意图,但您尚未在代码中处理它。 AMAZON.FallbackIntent 可帮助您处理意外的话语,或者当用户说出与您技能中的任何意图无关的内容时。如果没有处理程序,那么它将被您的错误处理程序捕获。将其作为错误处理没有问题,但更好的方法是专门为此添加一个处理程序并给出类似“对不起,我不明白,请您改写您的问题”的响应 em> 或类似的东西。

【讨论】:

【参考方案3】:

请进行以下更改以使其有效。 1. 在交互模型中,intent start 只需给出与“to start”相同的话语,而不是 current。 例如:Alexa,让我的个人心跳开始。

    在您的 lambda 代码中,在 getnewfact 方法的 lambda 代码中,您忘记将意图的名称从 getnewfactintent 更改为 start。

    要调用 currentbpm 意图,请使用“Alexa,询问我的个人心跳我现在的心跳有多快。

希望这会有所帮助。

【讨论】:

您的三个建议都有效,谢谢!我觉得我真的很亲近。但是对于第 3 点:我想要实现的是使用 LaunchRequest 来打开技能。然后在技能中询问它当前的bpm意图,而不是在外部。 (所以在实际的意图请求之前,我不必问“Alexa 询问我的个人心跳......”。)就像谷歌助手一样,你问“Ok Google 与我的个人心跳交谈”。然后你可以问“我现在的心跳有多快”。 默认情况下,Alexa 会在响应后立即结束会话,因此当您问任何问题时,它不会达到您的技能水平并且不会给出您期望的正确响应。这是 Alexa 的行为。因此,请将 shudendsession(false) 设置为您从 Launch 请求意图发送的响应。它会工作.. 谢谢,这成功了!我将根据您的调整更新工作脚本。 干杯...希望我的代码和建议对您有所帮助。如果是,请接受我的回答

以上是关于Alexa无法识别意图的主要内容,如果未能解决你的问题,请参考以下文章

如何让这个alexa技能识别两个意图

亚马逊 Alexa 无法识别号码槽

在 Echo 上测试时无法识别 Alexa Skill

RASA 无法识别正确的意图

从意图中获取 Alexa Slot 值

Alexa 自定义插槽类型:没有意图的价值