如何回答问题 - Alexa

时间:2017-05-22 12:31:47

标签: alexa alexa-skills-kit alexa-skill alexa-slot

我正在尝试构建一个alexa自定义技能。我正面临一个问题,我试图从用户那里得到一个技能问用户的问题的回复。

User : Tell me marks of student1 ?
Alexa: Subject
User: Maths
Alexa : student1 marks in maths is {xyz}

或者如果用户没有提供任何输入:

User : Tell me marks of student1 ?
Alexa: Subject
User: No Answer
Alexa : Gives marks of all subject for student1.

我正在使用Node.js. 请告诉我怎么做。

3 个答案:

答案 0 :(得分:2)

嗯,这很复杂。这里有几种方法可以遵循对话方案

https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/dialog-interface-reference

或者你可以使用意图。

您将拥有学生意图和主题意图。

  "intents": [
    {
      "intent": "Student",
      "slots": [
        {
          "name": "Students",
          "type": "LIST_OF_STUDENTS"
        }
      ]
    },
    {
      "intent": "Subject",
      "slots": [
        {
          "name": "Subjects",
          "type": "LIST_OF_SUBJECTS"
        }
      ]
    }

您将需要一个发电机数据库表,您可以在其中保留学生姓名,在您的技能计划中,您将获得学生和科目列表。

我无法为你写出整个技能,这太复杂了。

只需按照教程然后询问具体问题即可。 https://github.com/alexa/alexa-skills-kit-sdk-for-nodejs

让我做技能不是一个问题......

答案 1 :(得分:2)

在需要注意的事情上,Alexa没有回答“没有回答”。因此,您需要指导用户回复“全部”或“无”。

答案 2 :(得分:1)

这是你的幸运日。这就是我在Node.js中使用多个MODES的方法。

  

免责声明:我提供这个冗长的回复,因为我渴望获得声望点,并希望成为   开发人员传道者。 ;)

鉴于Node.js SDK及其许多功能,这是我将使用的格式。

// To zip and upload to lambda
// cd Desktop/StudentSkill
// sudo rm -r foo.zip
// zip -r foo.zip .s

'use strict';
var Alexa = require("alexa-sdk");
var appId = 'YOUR-AMAZON-ALEXA-SKILL-ID';

exports.handler = function(event, context, callback) {
    var alexa = Alexa.handler(event, context);
    alexa.appId = appId;
    alexa.registerHandlers(newSessionHandlers, studentSkillSessionHandlers, specificClassSessionHandlers, functionHandlers);
    alexa.execute();
};


var states = {
    STUDENTMODE:    '_STUDENTMODE',
    CLASSMODE:      '_CLASSMODE',
};

//Variables
var myStudents = {'josh':{'math':'A Plus','english':'A Plus','gym':'C'},'sam':{'math':'A Plus','english':'A minus','gym':'B Plus'}}; //add more classes. 

//Could add an intent to create new students.
//var newStudent = {name:{'math':null,'english':null,'gym':null}};

//Could also add an intent to set grades

var newSessionHandlers = {
    'NewSession': function() {
        this.handler.state = states.STUDENTMODE;
        var message = `Welcome to the School Skill, You may add students, edit grades, and review grades. For a list of uses say information. `; //this skill only contains reviewing grades.
        var reprompt = ` try saying, grades for josh. `;
        this.emit(':ask',message,reprompt);
    },
    'Unhandled': function() {
        console.log("UNHANDLED");
        this.emit('NewSession');
    }
};
/////////////////////////////////
var studentSkillSessionHandlers = Alexa.CreateStateHandler(states.STUDENTMODE, {//Your location
    'NewSession': function () {
        this.emit('NewSession'); // Uses the handler in newSessionHandlers
    },
    //Primary Intents
    'GetGradeIntent': function () { // Sampe Utterance: Tell me the marks of {student}    or    Grades for {student}
      this.handler.state = states.CLASSMODE;  //Change mode to accept a class, the intent handler getClassIntent is only available in CLASSMODE
      this.attributes['CURRENTSTUDENT'] = this.event.request.intent.slots.student.value;
      var message = ` which of `+this.attributes['CURRENTSTUDENT']+`'s classes would you like the grade for, name a class or say all. `;
      var reprompt = message;
      this.emit(':ask',message,reprompt);
    },
    //Help Intents
    "InformationIntent": function() {
      console.log("INFORMATION");
      var message = ` Try saying, Tell me the marks of josh.  `;
      this.emit(':ask', message, message);
    },
    "AMAZON.StopIntent": function() {
      console.log("STOPINTENT");
      this.emit(':tell', "Goodbye!");
    },
    "AMAZON.CancelIntent": function() {
      console.log("CANCELINTENT");
      this.emit(':tell', "Goodbye!");
    },
    'AMAZON.HelpIntent': function() {
        var message = helpMessage;
        this.emit(':ask', message, message);
    },
    //Unhandled
    'Unhandled': function() {
        console.log("UNHANDLED");
        var reprompt = ` That was not an appropriate response. which student would you like grades for.  Say, grades for josh. `;
        this.emit(':ask', reprompt, reprompt);
    }
});

////////////////////////////
/////////////////////////////////
var specificClassSessionHandlers = Alexa.CreateStateHandler(states.CLASSMODE, {//Your location
    'NewSession': function () {
        this.emit('NewSession'); // Uses the handler in newSessionHandlers
    },
    //Primary Intents
    'GetClassIntent': function () { // {className} class. ex: gym class, math class, english class.  It helps to have a word that's not a slot. but amazon may pick it up correctly if you just say {className}
      this.attributes['CLASSNAME'] = this.event.request.intent.slots.className.value;
      var message = ``;
      var reprompt = ``;
      if(this.attributes['CLASSNAME'] != undefined){
        message = ` I didn't get that class name.  would you please repeat it. `;
        reprompt = message;
      }else{
        grade = myStudents[this.attributes['CURRENTSTUDENT']][this.attributes['CLASSNAME']];
        if(grade != undefined){
          this.handler.state = states.STUDENTMODE; //Answer was present. return to student mode.
          message = this.attributes['CURRENTSTUDENT']+`'s `+[this.attributes['CLASSNAME']+` grade is `+aAn(grade)+` `+grade+`. What else would you like to know?`; //Josh's math grade is an A plus.
          reprompt = `what else would you like to know?`;
        }else{
          message = this.attributes['CURRENTSTUDENT']+` does not appear to have a grade for `+[this.attributes['CLASSNAME']+` please try again with a different class or say back.`;
          reprompt = `please try again with a different class or say back.`;
        }
      }
      var message = this.attributes['FROM'] + ' .. '+ ProFirstCity;
      var reprompt = ProFirstReprompt;
      this.emit(':ask',message,reprompt);
    },
    "AllIntent": function() {// Utterance: All, All Classes
      message = ``;
      //Not going to code.
      //Pseudo code
      // for each in json object myStudents[this.attributes['CURRENTSTUDENT']] append to message class name and grade.
      this.emit(':ask', message, message);
    },
    "BackIntent": function() {// Utterance: Back, go back
      var message = ` Who's grade would you like to know. try saying, grades for josh. `;
      this.emit(':ask', message, message);
    },
    //Help Intents
    "InformationIntent": function() {
      console.log("INFORMATION");
      var message = ` You've been asked for which of `+this.attributes['CURRENTSTUDENT']+`'s classes you'd his grade. Please name a class or say back. `;
      this.emit(':ask', message, 'Name a class or say back.');
    },
    "AMAZON.StopIntent": function() {
      console.log("STOPINTENT");
      this.emit(':tell', "Goodbye!");
    },
    "AMAZON.CancelIntent": function() {
      console.log("CANCELINTENT");
      this.emit(':tell', "Goodbye!");
    },
    'AMAZON.HelpIntent': function() {
        var message = helpMessage;
        this.emit(':ask', message, message);
    },
    //Unhandled
    'Unhandled': function() {
        console.log("UNHANDLED");
        var reprompt = ' That was not an appropriate response. Name a class or say back.';
        this.emit(':ask', reprompt, reprompt);
    }
});

////////////////////////////////////////////////////////////

var functionHandlers = {//NOT USED IN THIS APP //Note tied to a specific mode.

};


//#############################HELPERS VVVV#########################
function getRandomInt(min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
}
function clone(a) {
   return JSON.parse(JSON.stringify(a));
}
function responseRandomizer(responseType){
  let len = responseType.length;
  let index = getRandomInt(0,len-1);
  return responseType[index];
}
var vowels = {}
function aAn(word){
  if(word != ''){
    let first = word[0];
    if(/[aAeEiIoOuU]/.test(first)){
      return 'an';
    }else{
      return 'a';
    }
  }else{
    return '';
  }
}

请注意:此代码是根据现场技能改编的,但尚未经过自己的测试。

要开始请求跟进问题,您需要了解不同的stateHandlers。当您调用新技能时,它会从那里转到newSessionHandlers,您可以运行某种设置代码,然后将MODE更改为大厅以捕获该技能的主要意图。我把这个大厅命名为STUDENTMODE。在STUDENTMODE里面,您可以询问学生的成绩,理论上您可以创建一个新学生或添加一个课程或什么不是。如果您使用现有的intent GetGradeIntent并为其提供一个合适的名称,它将保存学生在会话状态中的名称,并将模式更改为CLASSMODE,它只接受Intents ClassNameIntent和BackIntent。如果您尝试调用其他一些意图,您将被UnhandledIntent重新命名为类的名称。提供适当的课程或说“全部”后,您将收到回复,模式将更改回STUDENTMODE。这会让你回到大厅,在那里你可以提出有关其他学生的问题。瞧!

这种改变模式的过程要比Multi Part Intent Schema好得多,比如“在{mathClass}中告诉我{studentName}的成绩”。虽然这肯定有效,但模式更好的一个原因是,如果其中一个输入值不正确,它们允许您正确处理错误,例如学生姓名或班级名称。您可以轻松地询问单条信息,而不是要求用户重新表示整个多部分意图。它还允许您一次处理一小块信息,并提供充足的说明,以便允许Alexa继续询问重新提问,直到填满所有必需的广告位。

我没有报道过的一件事 你在哪里存放学生?我把它们硬编码到lambda函数中。您可以连接到amazon的dynamodb并将会话状态存储在那里,以便在下一个会话中可用。这实际上就像添加一样简单。

alexa.dynamoDBTableName = 'NAME-OF-YOUR-DynamoDB-TABLE'; //You literally dont need any other code it just does the saving and loading??!! WHAT?

到这里的功能。

exports.handler = function(event, context, callback) {
    var alexa = Alexa.handler(event, context);
    alexa.appId = appId;
    alexa.dynamoDBTableName = 'NAME-OF-YOUR-DynamoDB-TABLE'; //You literally don't need any other code it just does the saving and loading??!! WHAT?
    alexa.registerHandlers(newSessionHandlers, studentSkillSessionHandlers, specificClassSessionHandlers, functionHandlers);
    alexa.execute();
};

您需要创建一个dynamoDB数据表和一个IAm权限,以允许您的lambda函数访问它。然后,奇迹般地,Alexa将在数据表中为每个唯一用户创建一行。一位老师可以轻松地在课堂上添加学生。但是,如果您正在寻找学校中的每位教师访问一个主数据库,这可能不是正确的方法。关于如何将Alexa连接到多个用户的单个数据表,可能还有其他教程。

  

我相信你的问题的核心问题已得到了回答   不同的MODES,您可以阻止不需要的意图。如果你   发现这个回复很有帮助我在三叉戟图层中付款   声誉。谢谢!