使用node.js,Alexa技能中的用户输入未按意图进行调用

时间:2018-07-29 19:52:08

标签: alexa alexa-skills-kit alexa-skill alexa-voice-service

我已经创建了一种技能,并且测试用例的代码如下。

(1)用户针对这两种意图输入的3-4次输入后,我面临无效输入的问题。

(2)如果用户调用CustomerWiseProductPriceIntent可以正常工作,但如果用户输入“否”或“返回”,则应提示输入LaunchRequest并再次启动所有内容,但提示输入“请提供客户名称或帐号”。

当前正在发生:
当用户输入CustomerWiseProductPriceIntent时,它会提示输入Account no.product name,然后它会弹出一个插槽:confirmation(是/否/后退)

如果用户输入是:
它工作正常,再次要求输入account no.product name

如果用户输入NO:
然后,它输入inside No,控制台日志“ Inside No .....”,但是下一行:this.emit('AMAZON.StopIntent');不执行。 然后,它再次询问account no.product name

如果用户输入“返回”: 然后它输入inside go back,但是下一行:this.emit('LaunchRequest');不执行。 然后,它再次询问account no.product name

这是我的代码:

Lambda函数:

'use strict';
const Alexa = require('alexa-sdk');
const APP_ID = undefined;
const SKILL_NAME = 'CustomerSupportVA';
const HELP_MESSAGE = 'You can say Item name to get On hand quantity or stop to exit';
const HELP_REPROMPT = 'What can I help you with?';
const STOP_MESSAGE = 'Thank for using EBS, Goodbye!';
const WELCOME_MESSAGE = "Welcome to EBS Speech Assistance, what do you like to know about <break time=\"1s\"/>  On hand stock , past due or customer wise product price";

const handlers = {
    'LaunchRequest': function() {
        this.response.speak(WELCOME_MESSAGE).listen("Please provide input");
        this.response.shouldEndSession(false);
        this.emit(':responseReady');
    },
    'OnHandQuantityIntent': function() {
        var intentObj = this.event.request.intent;
        var self = this;
        var slotToElicit = "";
        console.log("this.event.request  : "+JSON.stringify(this.event.request))
        var promptForProductName = "please, provide Product name";
        var confirmationStr = "<break time=\"1s\"/> " + " Would you like to know for other product on hand quantity?";
        console.log("Request Object  : "+JSON.stringify( this.event.request));
        if (this.event.request.dialogState == "STARTED") {
            slotToElicit = "productName";
            this.emit(':elicitSlot', slotToElicit, promptForProductName, promptForProductName, intentObj);
        }else if (this.event.request.dialogState == "IN_PROGRESS") {
            console.log("=============>>>>>>>>>>>>0000000  "+intentObj.slots.productName.value)
            if (intentObj.slots.productName.value) {
                var productName = intentObj.slots.productName.value;
                productName = productName.replace(' ', '');
                getOnHandQuatitySrv(productName, function(result) {
                    intentObj.slots.productName.value = undefined;
                    slotToElicit = "confirmation";
                    self.response.shouldEndSession(false);
                    self.emit(':elicitSlot', slotToElicit, result + confirmationStr, confirmationStr, intentObj);
                });

            }else if ("yes" == intentObj.slots.confirmation.value) {
                console.log("Inside Yes .....");
                intentObj = this.event.request.intent;
                slotToElicit = "productName";
                this.emit(':elicitSlot', slotToElicit, promptForProductName, promptForProductName, intentObj);
                intentObj.slots.confirmation.value = undefined;
            }else if ("no" == intentObj.slots.confirmation.value) {
                console.log("Inside No .....");
                this.emit('AMAZON.StopIntent');
            }else if ("go back" == intentObj.slots.confirmation.value) {
                this.emit('LaunchRequest');
            }
        }    
    },
    'CustomerWiseProductPriceIntent': function() {
        var intentObj = this.event.request.intent;
        var self = this;
        var promptForCustomerName = "please, provide customer name or account number";
        var promptForProductName = "please, provide product name";
        var confirmationStr = "<break time=\"1s\"/> " + "Would you like to know for product price for other customer?";
        var slotToElicit = "custAccountNameNo";
        var slotToElicitProd = "productName";

        if (this.event.request.dialogState == "STARTED") {
            console.log("Inside STARTED .....");
            if (!intentObj.slots.custAccountNameNo.value) {
                this.emit(':elicitSlot', slotToElicit, promptForCustomerName, promptForCustomerName, intentObj);
            }
        }else if (this.event.request.dialogState == "IN_PROGRESS") {
            console.log("Inside IN PROGRESS .....");
            if(""==intentObj.slots.custAccountNameNo.value || intentObj.slots.custAccountNameNo.value==undefined){
                this.emit(':elicitSlot', slotToElicit, promptForCustomerName, promptForCustomerName, intentObj);
            }else if (""==intentObj.slots.productName.value || intentObj.slots.productName.value==undefined) {
                this.emit(':elicitSlot', slotToElicitProd, promptForProductName, promptForProductName, intentObj);
            }

             if (intentObj.slots.custAccountNameNo.value!="" && intentObj.slots.productName.value!="") { 
                var custAccountNameNo = intentObj.slots.custAccountNameNo.value;
                var productName = intentObj.slots.productName.value;
                var speechOut="";
                getCustomerWiseProductPriceSrv(custAccountNameNo, productName,      function(itemPrice) {
                    if (itemPrice == undefined) {
                        itemPrice = 0;
                    }
                    else {
                        if (itemPrice == -333) {
                            speechOut = "Please provide valid Product Name";
                            slotToElicit="productName";
                        }
                        else if (itemPrice == -666) {
                            speechOut = "Please provide valid Account Number";
                            slotToElicit="custAccountNameNo";
                        }
                        else {
                            speechOut = "Price of " + productName + " is  " + itemPrice + " for " + custAccountNameNo + " customer  " + confirmationStr;
                            console.log("resultStr  : " + speechOut);
                            slotToElicit = "confirmation";
                            intentObj.slots.productName.value = "";
                            intentObj.slots.custAccountNameNo.value = "";
                        }

                    }
                    slotToElicit = "confirmation";
                    intentObj.slots.productName.value = "";
                    intentObj.slots.custAccountNameNo.value="";
                    self.response.shouldEndSession(false);
                    intentObj = self.event.request.intent;
                    self.emit(':elicitSlot', slotToElicit, speechOut, speechOut, intentObj);
                });

            }else if ("yes" == intentObj.slots.confirmation.value) {
                console.log("Inside Yes .....");
                slotToElicit = "custAccountNameNo";
                slotToElicitProd = "productName";
                intentObj.slots.confirmation.value = "";
                intentObj = this.event.request.intent;
                this.response.shouldEndSession(false);              
            }
            else if ("no" == intentObj.slots.confirmation.value) {
                console.log("Inside No .....");
                this.response.shouldEndSession(false);
                this.emit('AMAZON.StopIntent');
            }
            else if ("go back" == intentObj.slots.confirmation.value) {
                this.emit('LaunchRequest');
            }
        }    
    },
    'AMAZON.HelpIntent': function() {
        const speechOutput = HELP_MESSAGE;
        const reprompt = HELP_REPROMPT;

        this.response.speak(speechOutput).listen(reprompt);
        this.emit(':responseReady');
    },
    'AMAZON.CancelIntent': function() {
        this.response.speak(STOP_MESSAGE);
        this.emit(':responseReady');
    },
    'AMAZON.StopIntent': function() {
        this.response.speak(STOP_MESSAGE);
        this.emit(':responseReady');
    },
    'Unhandled': function() {
        this.response.speak("Invalid Input");
        console.log("this.event.request  :  "+JSON.stringify(this.event.request))
        this.emit(':responseReady');
    },
};

exports.handler = function(event, context, callback) {
    const alexa = Alexa.handler(event, context, callback);
    alexa.APP_ID = APP_ID;
    alexa.registerHandlers(handlers);
    alexa.execute();
};

var getOnHandQuatitySrv = function(productName, callback) {
    var totalOnHandQuanity = Math.floor(Math.random() * Math.floor(999))    
    //web service call 
    var resultStr = "Total " + totalOnHandQuanity + " available for Product    " + productName + "<break time=\"1s\"/> " + resultStr;
    callback(resultStr);
}
var getCustomerWiseProductPriceSrv = function(customerAccountNameNo, ProductName, callback) {
    var custWiseItemPrice = Math.floor(Math.random() * Math.floor(999));
    //web service call 
    callback(custWiseItemPrice);
}

这是我的Model JSON:

{
"interactionModel": {
    "languageModel": {
        "invocationName": "product details",
        "intents": [
            {
                "name": "AMAZON.FallbackIntent",
                "samples": []
            },
            {
                "name": "AMAZON.CancelIntent",
                "samples": []
            },
            {
                "name": "AMAZON.HelpIntent",
                "samples": []
            },
            {
                "name": "AMAZON.StopIntent",
                "samples": []
            },
            {
                "name": "OnHandQuantityIntent",
                "slots": [
                    {
                        "name": "productName",
                        "type": "ProductName",
                        "samples": [
                            "on hand stock for {productName}",
                            "{productName}"
                        ]
                    },
                    {
                        "name": "confirmation",
                        "type": "AMAZON.Genre",
                        "samples": [
                            "go back",
                            "No",
                            "yes"
                        ]
                    }
                ],
                "samples": [
                    "provide me on hand stock ",
                    "on hand quantity  ",
                    "on hand stock "
                ]
            },
            {
                "name": "CustomerWiseProductPriceIntent",
                "slots": [
                    {
                        "name": "custAccountNameNo",
                        "type": "CustomerAccountNameNo",
                        "samples": [
                            "{custAccountNameNo}"
                        ]
                    },
                    {
                        "name": "productName",
                        "type": "ProductName",
                        "samples": [
                            "{productName}"
                        ]
                    },
                    {
                        "name": "confirmation",
                        "type": "AMAZON.Genre",
                        "samples": [
                            "go back",
                            "No",
                            "Yes"
                        ]
                    }
                ],
                "samples": [
                    "customer wise product price "
                ]
            }
        ],
        "types": [
            {
                "name": "ProductName",
                "values": [
                    {
                        "id": "CM080901",
                        "name": {
                            "value": "CM080901",
                            "synonyms": [
                                "CM o eight o nine o one",
                                "CM zero eight zero nine zero one",
                                "CM080901"
                            ]
                        }
                    },
                    {
                        "id": "f30000",
                        "name": {
                            "value": "f30000",
                            "synonyms": [
                                "F three O O O O",
                                "F thirty thousand",
                                "F three zero zero zero zero"
                            ]
                        }
                    },
                    {
                        "id": "AT23808",
                        "name": {
                            "value": "AT23808",
                            "synonyms": [
                                "A T two three eight zero eight",
                                "AT twentythree thousand and eight hundred and eight",
                                "AT two three eight zero eight"
                            ]
                        }
                    }
                ]
            },
            {
                "name": "CustomerAccountNameNo",
                "values": [
                    {
                        "id": "1004",
                        "name": {
                            "value": "1004",
                            "synonyms": [
                                "one o o four",
                                "one zero zero four",
                                "One thousand four"
                            ]
                        }
                    },
                    {
                        "name": {
                            "value": "AT&T Universal Card",
                            "synonyms": [
                                "A T and T Universal Card",
                                "atandt Universal Card",
                                "AT&T Universal Card",
                                "AT and T Universal Card"
                            ]
                        }
                    },
                    {
                        "name": {
                            "value": "hilman and associates",
                            "synonyms": [
                                "hilman and associates",
                                "hilman  associates"
                            ]
                        }
                    },
                    {
                        "name": {
                            "value": "American Telephone & Telegraph - GOLD",
                            "synonyms": [
                                "american telephone and telegraph dash gold",
                                "american telephone and telegraph   gold",
                                "american telephone and telegraph - gold"
                            ]
                        }
                    },
                    {
                        "name": {
                            "value": "A. C. NETWORKS",
                            "synonyms": [
                                "A CNetworks",
                                "ACNETWORKS",
                                "A C Networks"
                            ]
                        }
                    },
                    {
                        "name": {
                            "value": "1001",
                            "synonyms": [
                                "one zero zero one",
                                "one o o one",
                                "one thousand one",
                                "1001"
                            ]
                        }
                    }
                ]
            }
        ]
    },
    "dialog": {
        "intents": [
            {
                "name": "OnHandQuantityIntent",
                "confirmationRequired": false,
                "prompts": {},
                "slots": [
                    {
                        "name": "productName",
                        "type": "ProductName",
                        "confirmationRequired": false,
                        "elicitationRequired": true,
                        "prompts": {
                            "elicitation": "Elicit.Slot.979240528726.539427738586"
                        }
                    },
                    {
                        "name": "confirmation",
                        "type": "AMAZON.Genre",
                        "confirmationRequired": false,
                        "elicitationRequired": true,
                        "prompts": {
                            "elicitation": "Elicit.Slot.979240528726.1367676676111"
                        }
                    }
                ]
            },
            {
                "name": "CustomerWiseProductPriceIntent",
                "confirmationRequired": false,
                "prompts": {},
                "slots": [
                    {
                        "name": "custAccountNameNo",
                        "type": "CustomerAccountNameNo",
                        "confirmationRequired": false,
                        "elicitationRequired": true,
                        "prompts": {
                            "elicitation": "Elicit.Slot.160438293908.60972362882"
                        }
                    },
                    {
                        "name": "productName",
                        "type": "ProductName",
                        "confirmationRequired": false,
                        "elicitationRequired": true,
                        "prompts": {
                            "elicitation": "Elicit.Slot.160438293908.513106626751"
                        }
                    },
                    {
                        "name": "confirmation",
                        "type": "AMAZON.Genre",
                        "confirmationRequired": false,
                        "elicitationRequired": true,
                        "prompts": {
                            "elicitation": "Elicit.Slot.160438293908.1422666600589"
                        }
                    }
                ]
            }
        ]
    },
    "prompts": [
        {
            "id": "Elicit.Slot.979240528726.539427738586",
            "variations": [
                {
                    "type": "PlainText",
                    "value": "Please provide product name"
                }
            ]
        },
        {
            "id": "Elicit.Slot.979240528726.1367676676111",
            "variations": [
                {
                    "type": "PlainText",
                    "value": "would you like to know for other product on hand quantity?"
                }
            ]
        },
        {
            "id": "Elicit.Slot.160438293908.1422666600589",
            "variations": [
                {
                    "type": "PlainText",
                    "value": "DO you like to continue?"
                }
            ]
        },
        {
            "id": "Elicit.Slot.160438293908.60972362882",
            "variations": [
                {
                    "type": "PlainText",
                    "value": "provide customer account name or number"
                }
            ]
        },
        {
            "id": "Elicit.Slot.160438293908.513106626751",
            "variations": [
                {
                    "type": "PlainText",
                    "value": "provide product name"
                }
            ]
        }
    ]
}
} 

有时对于两种意图,如果用户进行多轮对话而不是对话状态更改为“已开始”,并给出响应“无效输入”。 对于CustomerWiseProductPriceIntent,如果用户输入“否”,则必须发出停止消息;如果用户输入“ go back”,则出现诸如启动请求之类的提示消息。

1 个答案:

答案 0 :(得分:0)

这是因为必须使用您的广告位(即custAccountNameNo,productName和Confirm)才能实现此目的。这是一个问题,因为在显示结果后立即清空前两个插槽值。

speechOut = "Price of " + productName + " is  " + itemPrice + " for " + custAccountNameNo + " customer  " + confirmationStr;
console.log("resultStr  : " + speechOut);
slotToElicit = "confirmation";
intentObj.slots.productName.value = "";
intentObj.slots.custAccountNameNo.value = "";

再过几行,

slotToElicit = "confirmation";
intentObj.slots.productName.value = "";
intentObj.slots.custAccountNameNo.value="";
self.response.shouldEndSession(false);
intentObj = self.event.request.intent;
self.emit(':elicitSlot', slotToElicit, speechOut, speechOut, intentObj);

正在发生的情况是,当您要求确认时,productName和custAccountNameNo的广告位值为空,因此Alexa需要您填写这些值,然后才能继续执行所需的操作。

如果在将插槽设置​​为空字符串时注释了四行,Alexa将停止尝试填充空白插槽,并且Alexa不会要求输入插槽值。

但是,由于您使用空字符串作为条件,即

if (intentObj.slots.custAccountNameNo.value!="" && intentObj.slots.productName.value!=""){
}else{...}

如果条件变为无确认码,您可能会遇到失败。

为此,我发现一种解决方法是检查确认插槽的状态。如果未定义或为空,请转到if块,否则跳至是/否/返回代码。

上述黑客的问题(要求确认时保持插槽不为空,并添加了额外条件)使您的技能适用于“不”和“退回”情况。

但是,yes代码现在有问题。您可能必须对其进行重组以维持流程。

我推荐一种替代方法。

从CustomerWiseProductPriceIntent中删除确认,并使用亚马逊内置的YesIntent,NoIntent和PreviousIntent。

显示结果后,询问用户是否要查找其他用户的价格(例如您现在正在做什么)。如果您从意图中删除确认槽,则yes / no / go-back响应将分别触发YesIntent / NoIntent / PreviousIntent。在这些意图中,复制您在else块中使用的代码。

例如。如果用户说回去,Alexa会转到PreviousIntent

'AMAZON.PreviousIntent': function(){
     this.emit('LaunchRequest');
 }

如果用户说是,只需使用this.emit('CustomerWiseProductPriceIntent')。

这样,当您要求确认时,Alexa不需要您一遍又一遍地填写必填项。这也将帮助您摆脱CustomerWiseProductPriceIntent意图中的if-else块。

由于您有两个使用确认槽的意图,因此您可能需要跟踪您刚来自哪个意图。一种解决方案是保留会话属性。

this.attributes.lastIntent = 'where you just came from'

在逻辑上要求确​​认时,即在显示结果时,请添加此内容。

这可能需要重新整理一下代码,但这是我能想到的最佳解决方案。

很抱歉这么长的答案! 额外的建议:当您停止意图时,例如您要在否后进入StopIntent时,请勿将shouldEndSession属性设置为false。当您尝试退出时,这将产生一个错误。要么不设置它,要么使其正确。