在技​​能意图中使用插槽来搜索dynamodb [英] using slots in skill intent to search dynamodb

查看:89
本文介绍了在技​​能意图中使用插槽来搜索dynamodb的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是alexa,nodejs和编码方面的新手,但是我目前正在尝试创建一种使用日期和时间从我的dynamodb表中查找机器状态的技能。



我目前已经设置了获取alexa和lambda的技能,以了解我的广告位值,但是我不确定如何将这些值用于dynamodb查询,并让alexa调用相应时间的状态



我的表是用主键和排序键设置的,它们是日期和时间,我在机器状态的第三列。



I我不确定是否应该为机器状态设置自定义插槽,因为这只有4种可能的状态,所以这很容易做到。



这是代码i当前拥有,请随时清理零件或解释您如何使用我的解决方案。



  const awsSDK = require('aws-sdk'); const updateincident ='updatedincident'; const docClient = new awsSDK.DynamoDB.DocumentClient(); var AWSregion ='us-east-1'; // us-east-1var AWS = require('aws-sdk'); var dbClient = new AWS.DynamoDB.DocumentClient(); AWS.config.update({region:'us-east-1'}) ; const params = {TableName: updatedincident,键:{日期: 2018-03-28,时间: 04:23,状态: Blocked Primary}};让GetMachineStateIntent =(上下文,回调)= > {var params = {TableName: updatedincident,键:{日期: 2018-03-28,时间: 04:23,状态: Blocked Primary}}; dbClient.get(params,function(err,data){if(err){//由于某种原因无法从表中读取。.console.log('无法加载数据项:\n'+ JSON.stringify( err,null,2)); //让技能告诉用户找不到数据sendResponse(context,callback,{输出:无法从数据库加载数据,endSession:false}); } else {console.log('loaded data item:\n'+ JSON.stringify(data.Item,null,2)); //假设该项目具有名为 state的属性。.sendResponse(context,callback ,{输出:data.Item.state,endSession:false});}});};函数sendResponse(context,callback,responseOptions){if(typeof callback ==='undefined'){context.succeed(buildResponse( responseOptions)); } else {callback(null,buildResponse(responseOptions)); }}函数buildResponse(options){var alexaResponse = {版本: 1.0,响应:{outputSpeech:{ type: SSML, ssml:`< speak><韵律率= slow> ; $ {options.output}< / prosody>< / speak>`},shouldEndSession:options.endSession}}; if(options.repromptText){alexaResponse.response.reprompt = {outputSpeech:{ type: SSML, ssml:`< speak><韵律率= slow> $ {options.reprompt} < / prosody>< / speak>`}}; } return alexaResponse;} exports.handler =(事件,上下文,回调)=> {尝试{var request = event.request;如果(request.type === LaunchRequest){sendResponse(context,callback,{输出:欢迎您,我可以告诉您不同时间机器的状态。您要寻找什么数据?, endSession:false}); } else if((request.type === IntentRequest){if((request.type === IntentRequest // //确保意图名称与交互模型&& request.intent.name中的意图相匹配== GetMachineStateIntent){var dateSlot = request.intent.slots.Date!= null? request.intent.slots.Date.value:未知日期; var timeSlot = request.intent.slots.Time!= null吗? request.intent.slots.Time.value:未知时间; //以语音回应,并说出技能对用户的要求:sendResponse(context,callback,{输出:您想要机器状态为+ dateSlot +上的+ dateSlot,endSession:false}); var ConfirmationHandlers = Alexa.CreateStateHandler(states.CONFIRMATIONMODE,{'YesIntent':function(){this.emit( GetMachineStateIntent);},'AMAZON.NoIntent':function(){this.response.speak(GetMachineStateIntent); this.emit(':responseReady');}});}让options = {};如果(request.intent.name === GetMachineStateIntent){GetMachineStateIntent(上下文,回调); }否则,如果(request.intent.name === AMAZON.StopIntent || request.intent.name === AMAZON.CancelIntent){sendResponse(上下文,回调,{输出:确定,再见! ,endSession:true}); }否则,如果(request.intent.name === AMAZON.HelpIntent){sendResponse(上下文,回调,{输出:您可以向我询问过去发生的事件或机器的状态,则提示:我能为您提供什么帮助?,endSession:false}); } else {sendResponse(上下文,回调,{输出:我不知道那个!请再试一次!,endSession:false}); }} if if(request.type === SessionEndedRequest){sendResponse(context,callback,); //无需响应} else {//收到意外的请求类型..只是说我不知道​​.. sendResponse(context,callback,{输出:我不知道一个!请重试!, endSession:false}); }} catch(e){//通过记录错误并发送回故障控制台来处理错误。log(技能处理程序中发生意外错误!,e); if(typeof callback ==='undefined'){context.fail(意外错误); } else {callback(意外错误); }}};  



更新******** ****



当前在Alexa的技能I / O中响应



  request:{ type: IntentRequest, requestId: amzn1.echo-api.request.c515c39e-4ce1-4f28-97ed-30536fa593b9 , timestamp: 2018-05-15T08:55:25Z, locale: en-GB, intent:{ name: GetMachineStateIntent, confirmationStatus: NONE, slot:{ Time:{ name: Time, value: 04:23, confirmationStatus: NONE}, Date:{ name: Date, value: 2018-03-28, confirmationStatus: NONE}}}, dialogState: STARTED}}  

解决方案

一些观察结果:



第一
在c的分支中处理 GetMachineStateIntent 的ode,您已经添加了创建状态处理程序的代码,但未正确连接它们。最好的情况是代码什么都不做,最坏的情况实际上可能会引起一些问题。

  //删除以下代码行
var ConfirmationHandlers = Alexa.CreateStateHandler(states.CONFIRMATIONMODE ,{
'YesIntent':function(){
this.emit( GetMachineStateIntent);
},
'AMAZON.NoIntent':function(){
this.response.speak(GetMachineStateIntent);
this.emit(':responseReady');
}
});






第二查询传递给DynamoDB查询的参数是硬编码的。这意味着您将始终获得相同的结果。您需要将意图接收的插槽值传递到查询的参数中。

  var params = {
TableName: updatedincident,
键:{
日期: 2018-03-28,
时间: 04:23,
状态:已阻止小学
}
};

这些都是硬编码的。您只需要指定主键(日期)和排序键(时间),即可删除状态。对于日期时间,您必须更改要从动态传递的值dateSlot timeSlot






第三在处理 IntentRequest 类型的请求的代码分支中,您正在处理 GetMachineStateIntent 两次,代码有点多余。重写如下:

  ... 
}否则,如果(request.type === IntentRequest) {
if(request.intent.name === GetMachineStateIntent){
GetMachineStateIntent(上下文,回调);
}否则,如果(request.intent.name === AMAZON.StopIntent || request.intent.name === AMAZON.CancelIntent){
sendResponse(context,callback,{
输出:好,再见!,
endSession:true
});
}
else if(request.intent.name === AMAZON.HelpIntent){
sendResponse(上下文,回调,{
输出:您可以向我询问发生过的事件或过去的机器状态,
提示:我能为您提供什么帮助?,
endSession:false
});
}
else {
sendResponse(上下文,回调,{
输出:我不知道!请再试一次!,
endSession:false
});
}
}否则,如果(request.type === SessionEndedRequest){






第四
这是最难解释的。查询计算机状态时,将提供日期和时间,但大概是,计算机状态可能不会以与查询中的时间值完全匹配的时间戳存储在数据库中。因此,您必须执行一个查询,该查询基本上等效于日期X上,在等于或小于Y的最近时间的机器状态是什么



是在Y之前或等于Y的最近时间部分很棘手。您必须在表上创建一个表达该查询的查询,还必须将表中存储时间戳的方式从字符串更改为数字格式,以便可以轻松地表达这种不等式。



我将在这里展示如何传递dateSlot和timeSlot来进行查询,但是我建议您研究一下如何使它起作用(如果遇到问题,可能会问一些具体问题)。 / p>




这是您提到的修改代码:



  const awsSDK = require('aws-sdk'); const Updatedincident ='updatedincident'; const docClient = new awsSDK.DynamoDB.DocumentClient(); var AWSregion ='us-east-1'; // us-east-1var AWS = require('aws-sdk'); var dbClient = new AWS.DynamoDB.DocumentClient(); AWS.config.update({region:'us-east-1'}) ; let GetMachineStateIntent =(上下文,回调,dateSlot,timeSlot)=> {var params = {TableName: updatedincident,KeyConditionExpression:’#d =:dVal和#t< :tVal',ExpressionAttributeValues:{':dVal':dateSlot,':tVal':timeSlot},ExpressionAttributeNames:{'#d':'date','#t':'time'},ScanIndexForward:false //获取值按时间反向排序}; dbClient.query(params,function(err,data){if(err){//由于某种原因无法从表中读取。.console.log('无法加载数据项:\n'+ JSON.stringify( err,null,2)); //让技能告诉用户找不到数据sendResponse(context,callback,{输出:无法从数据库加载数据,endSession:false}); } else {let dataItem = data.Items [0]; console.log('loaded data item:\n'+ JSON.stringify(dataItem,null,2)); //假设该项目具有一个称为状态的属性 .. sendResponse(上下文,回调,{输出:dataItem.state,endSession:false});}});};函数sendResponse(上下文,回调,responseOptions){if(typeof callback ==='undefined'){ context.succeed(buildResponse(responseOptions)); } else {callback(null,buildResponse(responseOptions)); }}函数buildResponse(options){var alexaResponse = {版本: 1.0,响应:{outputSpeech:{ type: SSML, ssml:`< speak><韵律率= slow> ; $ {options.output}< / prosody>< / speak>`},shouldEndSession:options.endSession}}; if(options.repromptText){alexaResponse.response.reprompt = {outputSpeech:{ type: SSML, ssml:`< speak><韵律率= slow> $ {options.reprompt} < / prosody>< / speak>`}}; } return alexaResponse;} exports.handler =(事件,上下文,回调)=> {尝试{var request = event.request;如果(request.type === LaunchRequest){sendResponse(context,callback,{输出:欢迎您,我可以告诉您不同时间机器的状态。您要寻找什么数据?, endSession:false}); } else if(request.type === IntentRequest){if(request.intent.name === GetMachineStateIntent){var dateSlot = request.intent.slots.Date!= null? request.intent.slots.Date.value:null; var timeSlot = request.intent.slots.Time!= null吗? request.intent.slots.Time.value:null; //将广告位值传递给GetMachineStateIntent函数GetMachineStateIntent(context,callback,dateSlot,timeSlot); }否则,如果(request.intent.name === AMAZON.StopIntent || request.intent.name === AMAZON.CancelIntent){sendResponse(上下文,回调,{输出:确定,再见! ,endSession:true}); }否则,如果(request.intent.name === AMAZON.HelpIntent){sendResponse(上下文,回调,{输出:您可以向我询问过去发生的事件或机器的状态,则提示:我能为您提供什么帮助?,endSession:false}); } else {sendResponse(上下文,回调,{输出:我不知道那个!请再试一次!,endSession:false}); }} if if(request.type === SessionEndedRequest){sendResponse(context,callback,); //无需响应} else {//收到意外的请求类型..只是说我不知道​​.. sendResponse(context,callback,{输出:我不知道一个!请重试!, endSession:false}); }} catch(e){//通过记录错误并发送回故障控制台来处理错误。log(技能处理程序中发生意外错误!,e); if(typeof callback ==='undefined'){context.fail(意外错误); } else {callback(意外错误); }}};  


I'm new to alexa, nodejs and coding in general but i am currently trying to create a skill to find machine states from my dynamodb table using date and time.

I currently have set up my skill to get alexa and lambda to understand my slot values but im not sure how i can use these values for a dynamodb query and have alexa call out the state for that corresponding time

My table is setup with a primary and sort key which are date and time and i have a third column for machine state.

I'm not sure if i should set up a custom slot for machine state as it would be easy to do since there are only 4 possible states.

Here is the code i currently have, please feel free to clean parts up or explain how you came to my solution.

const awsSDK = require('aws-sdk');
const updatedincident = 'updatedincident';
const docClient = new awsSDK.DynamoDB.DocumentClient();

var AWSregion = 'us-east-1';  // us-east-1
var AWS = require('aws-sdk');
var dbClient = new AWS.DynamoDB.DocumentClient();
AWS.config.update({
    region: "'us-east-1'"
});

const params = {
    TableName: "updatedincident",
    Key:{ date: "2018-03-28",
      time: "04:23",
      state: "Blocked Primary"
    }
};

let GetMachineStateIntent = (context, callback) => {    
  var params = {
    TableName: "updatedincident",
    Key: {
      date: "2018-03-28",
      time: "04:23",
      state: "Blocked Primary"
    }
  };
  dbClient.get(params, function (err, data) {
    if (err) {
       // failed to read from table for some reason..
       console.log('failed to load data item:\n' + JSON.stringify(err, null, 2));
       // let skill tell the user that it couldn't find the data 
       sendResponse(context, callback, {
          output: "the data could not be loaded from your database",
          endSession: false
       });
    } else {
       console.log('loaded data item:\n' + JSON.stringify(data.Item, null, 2));
       // assuming the item has an attribute called "state"..
       sendResponse(context, callback, {
          output: data.Item.state,
          endSession: false
       });
    }
  });
};


function sendResponse(context, callback, responseOptions) {
  if(typeof callback === 'undefined') {
    context.succeed(buildResponse(responseOptions));
  } else {
    callback(null, buildResponse(responseOptions));
  }
}

function buildResponse(options) {
  var alexaResponse = {
    version: "1.0",
    response: {
      outputSpeech: {
        "type": "SSML",
        "ssml": `<speak><prosody rate="slow">${options.output}</prosody></speak>`
      },
      shouldEndSession: options.endSession
    }
  };
  if (options.repromptText) {
    alexaResponse.response.reprompt = {
      outputSpeech: {
        "type": "SSML",
        "ssml": `<speak><prosody rate="slow">${options.reprompt}</prosody></speak>`
      }
    };
  }
  return alexaResponse;
}

exports.handler = (event, context, callback) => {
  try {
    var request = event.request;
    if (request.type === "LaunchRequest") {
      sendResponse(context, callback, {
        output: "welcome to my skill, I can tell you about the status of machines at different times. what data are you looking for?",
        endSession: false
      });
  }
    else if (request.type === "IntentRequest") {
      if (request.type === "IntentRequest" 
      // make sure the name of the intent matches the one in interaction model
   && request.intent.name == "GetMachineStateIntent") {
    var dateSlot = request.intent.slots.Date != null ?
                   request.intent.slots.Date.value : "unknown date";
    var timeSlot = request.intent.slots.Time != null ?
                   request.intent.slots.Time.value : "unknown time";
                   
    // respond with speech saying back what the skill thinks the user requested
    sendResponse(context, callback, {
       output: "You wanted the machine state at " 
              + timeSlot + " on " + dateSlot,
       endSession: false
    });
    
    
    var ConfirmationHandlers = Alexa.CreateStateHandler(states.CONFIRMATIONMODE, {
    'YesIntent': function () { 
        this.emit("GetMachineStateIntent"); 
    }, 
    'AMAZON.NoIntent': function () { 
        this.response.speak(GetMachineStateIntent); 
        this.emit(':responseReady'); 
    } 
    });


}
      let options = {};         
      if (request.intent.name === "GetMachineStateIntent") {
        GetMachineStateIntent(context, callback);
      } else if (request.intent.name === "AMAZON.StopIntent" || request.intent.name === "AMAZON.CancelIntent") {
        sendResponse(context, callback, {
          output: "ok. good bye!",
          endSession: true
        });
      }
      else if (request.intent.name === "AMAZON.HelpIntent") {
        sendResponse(context, callback, {
          output: "you can ask me about incidents that have happened or states of machines in the past",
          reprompt: "what can I help you with?",
          endSession: false
        });
      }
      else {
        sendResponse(context, callback, {
          output: "I don't know that one! please try again!",
          endSession: false
        });
      }
    }
    else if (request.type === "SessionEndedRequest") {
      sendResponse(context, callback, ""); // no response needed
    }
    else {
      // an unexpected request type received.. just say I don't know..
      sendResponse(context, callback, {
          output: "I don't know that one! please try again!",
          endSession: false
      });
    }
  } catch (e) {
    // handle the error by logging it and sending back an failure
    console.log('Unexpected error occurred in the skill handler!', e);
    if(typeof callback === 'undefined') {
       context.fail("Unexpected error");
    } else {
       callback("Unexpected error");
    }
  }
};

Update ************

Response im getting currently in Skill I/O in alexa

	"request": {
		"type": "IntentRequest",
		"requestId": "amzn1.echo-api.request.c515c39e-4ce1-4f28-97ed-30536fa593b9",
		"timestamp": "2018-05-15T08:55:25Z",
		"locale": "en-GB",
		"intent": {
			"name": "GetMachineStateIntent",
			"confirmationStatus": "NONE",
			"slots": {
				"Time": {
					"name": "Time",
					"value": "04:23",
					"confirmationStatus": "NONE"
				},
				"Date": {
					"name": "Date",
					"value": "2018-03-28",
					"confirmationStatus": "NONE"
				}
			}
		},
		"dialogState": "STARTED"
	}
}

解决方案

A couple of observations:

First In the branch of code that handles the GetMachineStateIntent you had added code to create state handlers but they weren't properly wired. At best that code would do nothing, at worst it might actually cause some problems. Remove that.

    // take the following lines of code out
    var ConfirmationHandlers = Alexa.CreateStateHandler(states.CONFIRMATIONMODE, {
    'YesIntent': function () { 
        this.emit("GetMachineStateIntent"); 
    }, 
    'AMAZON.NoIntent': function () { 
        this.response.speak(GetMachineStateIntent); 
        this.emit(':responseReady'); 
    } 
    }); 


Second The query parameters that you are passing to your DynamoDB query are hard-coded. That means you are always going to get the same result. You need to pass the values of the slots your receive in the intent into the parameters for the query.

  var params = {
    TableName: "updatedincident",
    Key: {
      date: "2018-03-28",
      time: "04:23",
      state: "Blocked Primary"
    }
  };

Those are hard-coded. You only need to specify the primary key (date) and the sort key ('time'), so you can remove the state. And for date and time you have to change the values to be dynamically passed in from the dateSlot and timeSlot.


Third In the branch of code that handles requests of type IntentRequest you are handling the GetMachineStateIntent twice and the code is a bit redundant. Rewrite that as follows:

   ...
} else if (request.type === "IntentRequest") {
  if (request.intent.name === "GetMachineStateIntent") {
    GetMachineStateIntent(context, callback);
  } else if (request.intent.name === "AMAZON.StopIntent" || request.intent.name === "AMAZON.CancelIntent") {
    sendResponse(context, callback, {
      output: "ok. good bye!",
      endSession: true
    });
  }
  else if (request.intent.name === "AMAZON.HelpIntent") {
    sendResponse(context, callback, {
      output: "you can ask me about incidents that have happened or states of machines in the past",
      reprompt: "what can I help you with?",
      endSession: false
    });
  }
  else {
    sendResponse(context, callback, {
      output: "I don't know that one! please try again!",
      endSession: false
    });
  } 
} else if (request.type === "SessionEndedRequest") {


Fourth This is the most difficult to explain. When you query the machine state, you will be providing a date and a time but presumably, the machine state might not be stored in the database with a time stamp that matches the time value in your query exactly. So you have to do a query that is essentially the equivalent of "what is the machine state on date X, at the most recent time before or equal to Y"

It is that "most recent time before or equal to Y" part that is tricky. You have to create a query on your table that expresses that and you will also have to change the way you store timestamps in the table, from string, to a numeric format so that you can easily express this inequality.

I'm going to show here just how to pass the dateSlot and timeSlot to make the query but I recommend you look into getting this to work (perhaps ask specific questions if you get stuck).


Here's your code with the modifications I mentioned:

const awsSDK = require('aws-sdk');
const updatedincident = 'updatedincident';
const docClient = new awsSDK.DynamoDB.DocumentClient();

var AWSregion = 'us-east-1';  // us-east-1
var AWS = require('aws-sdk');
var dbClient = new AWS.DynamoDB.DocumentClient();
AWS.config.update({
    region: "'us-east-1'"
});

let GetMachineStateIntent = (context, callback, dateSlot, timeSlot) => {    
  var params = {
    TableName: "updatedincident",
    KeyConditionExpression: '#d = :dVal and #t < :tVal',
    ExpressionAttributeValues: {
       ':dVal': dateSlot,
       ':tVal': timeSlot
    },
    ExpressionAttributeNames: {
       '#d': 'date',
       '#t': 'time'
    },
    ScanIndexForward: false // gets values in reverse order by time 
  };
  dbClient.query(params, function (err, data) {
    if (err) {
       // failed to read from table for some reason..
       console.log('failed to load data item:\n' + JSON.stringify(err, null, 2));
       // let skill tell the user that it couldn't find the data 
       sendResponse(context, callback, {
          output: "the data could not be loaded from your database",
          endSession: false
       });
    } else {
       let dataItem = data.Items[0];           
console.log('loaded data item:\n' + JSON.stringify(dataItem, null, 2));
       // assuming the item has an attribute called "state"..
       sendResponse(context, callback, {
          output: dataItem.state,
          endSession: false
       });
    }
  });
};


function sendResponse(context, callback, responseOptions) {
  if(typeof callback === 'undefined') {
    context.succeed(buildResponse(responseOptions));
  } else {
    callback(null, buildResponse(responseOptions));
  }
}

function buildResponse(options) {
  var alexaResponse = {
    version: "1.0",
    response: {
      outputSpeech: {
        "type": "SSML",
        "ssml": `<speak><prosody rate="slow">${options.output}</prosody></speak>`
      },
      shouldEndSession: options.endSession
    }
  };
  if (options.repromptText) {
    alexaResponse.response.reprompt = {
      outputSpeech: {
        "type": "SSML",
        "ssml": `<speak><prosody rate="slow">${options.reprompt}</prosody></speak>`
      }
    };
  }
  return alexaResponse;
}

exports.handler = (event, context, callback) => {
  try {
    var request = event.request;
    if (request.type === "LaunchRequest") {
      sendResponse(context, callback, {
        output: "welcome to my skill, I can tell you about the status of machines at different times. what data are you looking for?",
        endSession: false
      });
    } else if (request.type === "IntentRequest") {
      if (request.intent.name === "GetMachineStateIntent") {
        var dateSlot = request.intent.slots.Date != null 
             ? request.intent.slots.Date.value : null;
        var timeSlot = request.intent.slots.Time != null
             ? request.intent.slots.Time.value : null;
        // pass the slot values to the GetMachineStateIntent function
        GetMachineStateIntent(context, callback, dateSlot, timeSlot);
      } else if (request.intent.name === "AMAZON.StopIntent" || request.intent.name === "AMAZON.CancelIntent") {
        sendResponse(context, callback, {
          output: "ok. good bye!",
          endSession: true
        });
      }
      else if (request.intent.name === "AMAZON.HelpIntent") {
        sendResponse(context, callback, {
          output: "you can ask me about incidents that have happened or states of machines in the past",
          reprompt: "what can I help you with?",
          endSession: false
        });
      }
      else {
        sendResponse(context, callback, {
          output: "I don't know that one! please try again!",
          endSession: false
        });
      }
    }
    else if (request.type === "SessionEndedRequest") {
      sendResponse(context, callback, ""); // no response needed
    }
    else {
      // an unexpected request type received.. just say I don't know..
      sendResponse(context, callback, {
          output: "I don't know that one! please try again!",
          endSession: false
      });
    }
  } catch (e) {
    // handle the error by logging it and sending back an failure
    console.log('Unexpected error occurred in the skill handler!', e);
    if(typeof callback === 'undefined') {
       context.fail("Unexpected error");
    } else {
       callback("Unexpected error");
    }
  }
};

这篇关于在技​​能意图中使用插槽来搜索dynamodb的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆