我已经创建了一种技能,并且测试用例的代码如下。
(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”,则出现诸如启动请求之类的提示消息。
答案 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。当您尝试退出时,这将产生一个错误。要么不设置它,要么使其正确。