你好alexa开发人员,
我已经使用具有多个意图的alexa和像yelp api这样的第三方api调用创建了酒店预订概念,但是我遇到了错误,例如我需要用特定意图连接任何字符串以识别用户的特定意图。
所以请告诉我有关不连接任何字符串的任何可能方法,并在第二步之后一步一步完成处理,就像调用意图一个接一个。
// Lambda Function code for Alexa.
const Alexa = require("ask-sdk");
const axios = require('axios');
const moment = require('moment-timezone');
const yelp = require('yelp-fusion');
const invocationName = "tabletalk";
function getMemoryAttributes() {
const memoryAttributes = {
"history":[],
"launchCount":0,
"lastUseTimestamp":0,
"lastSpeechOutput":{},
"nextIntent":[]
};
return memoryAttributes;
};
const maxHistorySize = 20; // remember only latest 20 intents
// 1. Intent Handlers =============================================
const AMAZON_FallbackIntent_Handler = {
canHandle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
return request.type === 'IntentRequest' && request.intent.name === 'AMAZON.FallbackIntent' ;
},
handle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
const responseBuilder = handlerInput.responseBuilder;
let sessionAttributes = handlerInput.attributesManager.getSessionAttributes();
let previousSpeech = getPreviousSpeechOutput(sessionAttributes);
return responseBuilder
.speak('Sorry I didnt catch what you said, ' + stripSpeak(previousSpeech.outputSpeech))
.reprompt(stripSpeak(previousSpeech.reprompt))
.getResponse();
},
};
const AMAZON_CancelIntent_Handler = {
canHandle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
return request.type === 'IntentRequest' && request.intent.name === 'AMAZON.CancelIntent' ;
},
handle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
const responseBuilder = handlerInput.responseBuilder;
let sessionAttributes = handlerInput.attributesManager.getSessionAttributes();
let say = 'Okay, talk to you later! ';
return responseBuilder
.speak(say)
.withShouldEndSession(true)
.getResponse();
},
};
const AMAZON_HelpIntent_Handler = {
canHandle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
return request.type === 'IntentRequest' && request.intent.name === 'AMAZON.HelpIntent' ;
},
handle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
const responseBuilder = handlerInput.responseBuilder;
let sessionAttributes = handlerInput.attributesManager.getSessionAttributes();
let intents = getCustomIntents();
let sampleIntent = randomElement(intents);
let say = 'You asked for help. ';
// let previousIntent = getPreviousIntent(sessionAttributes);
// if (previousIntent && !handlerInput.requestEnvelope.session.new) {
// say += 'Your last intent was ' + previousIntent + '. ';
// }
// say += 'I understand ' + intents.length + ' intents, '
say += ' Here something you can ask me, ' + getSampleUtterance(sampleIntent);
return responseBuilder
.speak(say)
.reprompt('try again, ' + say)
.getResponse();
},
};
const AMAZON_StopIntent_Handler = {
canHandle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
return request.type === 'IntentRequest' && request.intent.name === 'AMAZON.StopIntent' ;
},
handle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
const responseBuilder = handlerInput.responseBuilder;
let sessionAttributes = handlerInput.attributesManager.getSessionAttributes();
let say = 'Okay, talk to you later! ';
return responseBuilder
.speak(say)
.withShouldEndSession(true)
.getResponse();
},
};
const AMAZON_NavigateHomeIntent_Handler = {
canHandle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
return request.type === 'IntentRequest' && request.intent.name === 'AMAZON.NavigateHomeIntent' ;
},
handle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
const responseBuilder = handlerInput.responseBuilder;
let sessionAttributes = handlerInput.attributesManager.getSessionAttributes();
let say = 'Hello from AMAZON.NavigateHomeIntent. ';
return responseBuilder
.speak(say)
.reprompt('try again, ' + say)
.getResponse();
},
};
const makeReservation_Handler = {
canHandle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
return request.type === 'IntentRequest' && request.intent.name === 'makeReservation' ;
},
handle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
const currentIntent = handlerInput.requestEnvelope.request.intent;
const responseBuilder = handlerInput.responseBuilder;
let sessionAttributes = handlerInput.attributesManager.getSessionAttributes();
let say = 'OK Future location or Current location?';
return responseBuilder
.speak(say)
.reprompt(say)
.getResponse();
},
};
const futureOrCurrentLocation_Handler = {
canHandle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
return request.type === 'IntentRequest' && request.intent.name === 'futureOrCurrentLocation' ;
},
handle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
const responseBuilder = handlerInput.responseBuilder;
let slotValues = getSlotValues(request.intent.slots);
let location = slotValues.location.heardAs;
let say = '';
if (location == 'future location') {
say = `Feature location not available in this moment. Please ask to current location.`;
} else if(location == 'current location'){
say = `Ok Where would you like to go?`;
} else {
say = `invalid input. Please try again`;
}
return responseBuilder
.speak(say)
.reprompt(say)
.getResponse();
},
};
const getRestaurantName_Handler = {
canHandle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
return request.type === 'IntentRequest' && request.intent.name === 'getRestaurantName' ;
},
handle(handlerInput) {
return new Promise((resolve) => {
const request = handlerInput.requestEnvelope.request;
let slotValues = getSlotValues(request.intent.slots);
getRestaurants(slotValues, handlerInput).then(say => {
resolve(handlerInput.responseBuilder.speak(say).reprompt('try again, ' + say).getResponse());
}).catch(err =>{
say = 'try again';
});
});
},
};
// Helper Functions ==========================================================================
function getRestaurants(slotValues, handlerInput) {
return new Promise((resolve, reject) => {
let resName = slotValues.restaurantname.heardAs;
if (resName) {
getRestaurantByName(resName, handlerInput).then(res => {
resolve(res);
}).catch(err => {
reject(err);
})
}
});
}
function getRestaurantByName(resName, handlerInput) {
return new Promise((resolve, reject) => {
const restaurantName = resName;
client.search({
term: restaurantName,
location: "san francisco, ca",
}).then(response => {
let restaurants = response.jsonBody.businesses;
if (restaurants && restaurants.length > 0) {
getRestaurantListByName(restaurants, restaurantName, handlerInput).then(restaurantsList => {
resolve(restaurantsList);
}).catch(e => {
console.log(e);
reject(e);
});
} else {
resolve(`not getting restaurant. you can say find restaurant near me`);
}
}).catch(e => {
console.log(e);
reject(e);
});
});
}
function getRestaurantListByName(restaurants, restaurantname, handlerInput) {
return new Promise((resolve) => {
let sessionAttributes = handlerInput.attributesManager.getSessionAttributes();
let restaurantList = 'Found restaurant near by ';
let sessionrestaurantList = [];
for (let i = 0; i < restaurants.length; i += 1) {
if (restaurants[i].name !== '' && restaurants[i].name !== null && typeof restaurants[i].name !== undefined) {
let Obj = {
[i+1] : restaurants[i]
};
let resAddress = restaurants[i].location.address1 ? restaurants[i].location.address1 : '';
let resAddress1 = restaurants[i].location.address2 ? restaurants[i].location.address2 : '';
let resAddress2 = restaurants[i].location.address3 ? restaurants[i].location.address3 : '';
restaurantList += `select ${i+1} for ${restaurants[i].name} in ${resAddress} ${resAddress1} ${resAddress2}`;
sessionrestaurantList.push(JSON.stringify(Obj));
}
}
setTimeout(() => {
resolve(restaurantList);
}, 5);
sessionAttributes.sessionrestaurantList = sessionrestaurantList;
handlerInput.attributesManager.setSessionAttributes(sessionAttributes);
});
}
const LaunchRequest_Handler = {
canHandle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
return request.type === 'LaunchRequest';
},
handle(handlerInput) {
const responseBuilder = handlerInput.responseBuilder;
let say = `Welcome to ${invocationName}. How can i help you?`;
let skillTitle = capitalize(invocationName);
return responseBuilder
.speak(say)
.reprompt('try again, ' + say)
.withStandardCard('Welcome!',
'Hello!\nThis is a card for your skill, ' + skillTitle,
welcomeCardImg.smallImageUrl, welcomeCardImg.largeImageUrl)
.getResponse();
},
};
const SessionEndedHandler = {
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) {
const request = handlerInput.requestEnvelope.request;
return handlerInput.responseBuilder
.speak('Sorry, Please say again.')
.reprompt('Sorry, Please say again.')
.getResponse();
}
};
// 2. Constants ===========================================================================
const APP_ID = undefined; // TODO replace with your Skill ID (OPTIONAL).
// 3. Helper Functions ===================================================================
function capitalize(myString) {
return myString.replace(/(?:^|\s)\S/g, function(a) { return a.toUpperCase(); }) ;
}
function randomElement(myArray) {
return(myArray[Math.floor(Math.random() * myArray.length)]);
}
function stripSpeak(str) {
return(str.replace('<speak>', '').replace('</speak>', ''));
}
function getSlotValues(filledSlots) {
const slotValues = {};
Object.keys(filledSlots).forEach((item) => {
const name = filledSlots[item].name;
if (filledSlots[item] &&
filledSlots[item].resolutions &&
filledSlots[item].resolutions.resolutionsPerAuthority[0] &&
filledSlots[item].resolutions.resolutionsPerAuthority[0].status &&
filledSlots[item].resolutions.resolutionsPerAuthority[0].status.code) {
switch (filledSlots[item].resolutions.resolutionsPerAuthority[0].status.code) {
case 'ER_SUCCESS_MATCH':
slotValues[name] = {
heardAs: filledSlots[item].value,
resolved: filledSlots[item].resolutions.resolutionsPerAuthority[0].values[0].value.name,
ERstatus: 'ER_SUCCESS_MATCH'
};
break;
case 'ER_SUCCESS_NO_MATCH':
slotValues[name] = {
heardAs: filledSlots[item].value,
resolved: '',
ERstatus: 'ER_SUCCESS_NO_MATCH'
};
break;
default:
break;
}
} else {
slotValues[name] = {
heardAs: filledSlots[item].value,
resolved: '',
ERstatus: ''
};
}
}, this);
return slotValues;
}
function getExampleSlotValues(intentName, slotName) {
let examples = [];
let slotType = '';
let slotValuesFull = [];
let intents = model.interactionModel.languageModel.intents;
for (let i = 0; i < intents.length; i++) {
if (intents[i].name == intentName) {
let slots = intents[i].slots;
for (let j = 0; j < slots.length; j++) {
if (slots[j].name === slotName) {
slotType = slots[j].type;
}
}
}
}
let types = model.interactionModel.languageModel.types;
for (let i = 0; i < types.length; i++) {
if (types[i].name === slotType) {
slotValuesFull = types[i].values;
}
}
examples.push(slotValuesFull[0].name.value);
examples.push(slotValuesFull[1].name.value);
if (slotValuesFull.length > 2) {
examples.push(slotValuesFull[2].name.value);
}
return examples;
}
function sayArray(myData, penultimateWord = 'and') {
let result = '';
myData.forEach(function(element, index, arr) {
if (index === 0) {
result = element;
} else if (index === myData.length - 1) {
result += ` ${penultimateWord} ${element}`;
} else {
result += `, ${element}`;
}
});
return result;
}
function supportsDisplay(handlerInput) // returns true if the skill is running on a device with a display (Echo Show, Echo Spot, etc.)
{ // Enable your skill for display as shown here: https://alexa.design/enabledisplay
const hasDisplay =
handlerInput.requestEnvelope.context &&
handlerInput.requestEnvelope.context.System &&
handlerInput.requestEnvelope.context.System.device &&
handlerInput.requestEnvelope.context.System.device.supportedInterfaces &&
handlerInput.requestEnvelope.context.System.device.supportedInterfaces.Display;
return hasDisplay;
}
const welcomeCardImg = {
smallImageUrl: "https://s3.amazonaws.com/skill-images-789/cards/card_plane720_480.png",
largeImageUrl: "https://s3.amazonaws.com/skill-images-789/cards/card_plane1200_800.png"
};
const DisplayImg1 = {
title: 'Jet Plane',
url: 'https://s3.amazonaws.com/skill-images-789/display/plane340_340.png'
};
const DisplayImg2 = {
title: 'Starry Sky',
url: 'https://s3.amazonaws.com/skill-images-789/display/background1024_600.png'
};
function getCustomIntents() {
const modelIntents = model.interactionModel.languageModel.intents;
let customIntents = [];
for (let i = 0; i < modelIntents.length; i++) {
if(modelIntents[i].name.substring(0,7) != "AMAZON." && modelIntents[i].name !== "LaunchRequest" ) {
customIntents.push(modelIntents[i]);
}
}
return customIntents;
}
function getSampleUtterance(intent) {
return randomElement(intent.samples);
}
function getPreviousIntent(attrs) {
if (attrs.history && attrs.history.length > 1) {
return attrs.history[attrs.history.length - 2].IntentRequest;
} else {
return false;
}
}
function getPreviousSpeechOutput(attrs) {
if (attrs.lastSpeechOutput && attrs.history.length > 1) {
return attrs.lastSpeechOutput;
} else {
return false;
}
}
function timeDelta(t1, t2) {
const dt1 = new Date(t1);
const dt2 = new Date(t2);
const timeSpanMS = dt2.getTime() - dt1.getTime();
const span = {
"timeSpanMIN": Math.floor(timeSpanMS / (1000 * 60 )),
"timeSpanHR": Math.floor(timeSpanMS / (1000 * 60 * 60)),
"timeSpanDAY": Math.floor(timeSpanMS / (1000 * 60 * 60 * 24)),
"timeSpanDesc" : ""
};
if (span.timeSpanHR < 2) {
span.timeSpanDesc = span.timeSpanMIN + " minutes";
} else if (span.timeSpanDAY < 2) {
span.timeSpanDesc = span.timeSpanHR + " hours";
} else {
span.timeSpanDesc = span.timeSpanDAY + " days";
}
return span;
}
const InitMemoryAttributesInterceptor = {
process(handlerInput) {
let sessionAttributes = {};
if(handlerInput.requestEnvelope.session['new']) {
sessionAttributes = handlerInput.attributesManager.getSessionAttributes();
let memoryAttributes = getMemoryAttributes();
if(Object.keys(sessionAttributes).length === 0) {
Object.keys(memoryAttributes).forEach(function(key) { // initialize all attributes from global list
sessionAttributes[key] = memoryAttributes[key];
});
}
handlerInput.attributesManager.setSessionAttributes(sessionAttributes);
}
}
};
const RequestHistoryInterceptor = {
process(handlerInput) {
const thisRequest = handlerInput.requestEnvelope.request;
let sessionAttributes = handlerInput.attributesManager.getSessionAttributes();
let history = sessionAttributes['history'] || [];
let IntentRequest = {};
if (thisRequest.type === 'IntentRequest' ) {
let slots = [];
IntentRequest = {
'IntentRequest' : thisRequest.intent.name
};
if (thisRequest.intent.slots) {
for (let slot in thisRequest.intent.slots) {
let slotObj = {};
slotObj[slot] = thisRequest.intent.slots[slot].value;
slots.push(slotObj);
}
IntentRequest = {
'IntentRequest' : thisRequest.intent.name,
'slots' : slots
};
}
} else {
IntentRequest = {'IntentRequest' : thisRequest.type};
}
if(history.length > maxHistorySize - 1) {
history.shift();
}
history.push(IntentRequest);
handlerInput.attributesManager.setSessionAttributes(sessionAttributes);
}
};
const RequestPersistenceInterceptor = {
process(handlerInput) {
if(handlerInput.requestEnvelope.session['new']) {
return new Promise((resolve, reject) => {
handlerInput.attributesManager.getPersistentAttributes()
.then((sessionAttributes) => {
sessionAttributes = sessionAttributes || {};
sessionAttributes['launchCount'] += 1; handlerInput.attributesManager.setSessionAttributes(sessionAttributes);
handlerInput.attributesManager.savePersistentAttributes()
.then(() => {
resolve();
})
.catch((err) => {
reject(err);
});
});
});
} // end session['new']
}
};
const ResponseRecordSpeechOutputInterceptor = {
process(handlerInput, responseOutput) {
let sessionAttributes = handlerInput.attributesManager.getSessionAttributes();
let lastSpeechOutput = {
"outputSpeech":responseOutput.outputSpeech.ssml,
"reprompt":responseOutput.reprompt.outputSpeech.ssml
};
sessionAttributes['lastSpeechOutput'] = lastSpeechOutput;
handlerInput.attributesManager.setSessionAttributes(sessionAttributes);
}
};
const ResponsePersistenceInterceptor = {
process(handlerInput, responseOutput) {
const ses = (typeof responseOutput.shouldEndSession == "undefined" ? true : responseOutput.shouldEndSession);
if(ses || handlerInput.requestEnvelope.request.type == 'SessionEndedRequest') { // skill was stopped or timed out
let sessionAttributes = handlerInput.attributesManager.getSessionAttributes();
sessionAttributes['lastUseTimestamp'] = new Date(handlerInput.requestEnvelope.request.timestamp).getTime();
handlerInput.attributesManager.setPersistentAttributes(sessionAttributes);
return new Promise((resolve, reject) => {
handlerInput.attributesManager.savePersistentAttributes()
.then(() => {
resolve();
})
.catch((err) => {
reject(err);
});
});
}
}
};
// 4. Exports handler function and setup ===================================================
const skillBuilder = Alexa.SkillBuilders.standard();
exports.handler = skillBuilder
.addRequestHandlers(
AMAZON_FallbackIntent_Handler,
AMAZON_CancelIntent_Handler,
AMAZON_HelpIntent_Handler,
AMAZON_StopIntent_Handler,
AMAZON_NavigateHomeIntent_Handler,
makeReservation_Handler,
futureOrCurrentLocation_Handler,
getRestaurantName_Handler,
LaunchRequest_Handler,
SessionEndedHandler
)
.addErrorHandlers(ErrorHandler)
.addRequestInterceptors(InitMemoryAttributesInterceptor)
.addRequestInterceptors(RequestHistoryInterceptor)
// .addResponseInterceptors(ResponseRecordSpeechOutputInterceptor)
// .addRequestInterceptors(RequestPersistenceInterceptor)
// .addResponseInterceptors(ResponsePersistenceInterceptor)
// .withTableName("askMemorySkillTable")
// .withAutoCreateTable(true)
.lambda();
// End of Skill code -------------------------------------------------------------
// Static Language Model for reference
const model = {
"interactionModel": {
"languageModel": {
"invocationName": "tabletalk",
"intents": [
{
"name": "AMAZON.FallbackIntent",
"samples": []
},
{
"name": "AMAZON.CancelIntent",
"samples": []
},
{
"name": "AMAZON.HelpIntent",
"samples": []
},
{
"name": "AMAZON.StopIntent",
"samples": []
},
{
"name": "AMAZON.NavigateHomeIntent",
"samples": []
},
{
"name": "makeReservation",
"slots": [],
"samples": [
"Create a table",
"Alexa Crete a table",
"make a reservation"
]
},
{
"name": "futureOrCurrentLocation",
"slots": [
{
"name": "location",
"type": "Location"
}
],
"samples": [
"{location}"
]
},
{
"name": "getRestaurantName",
"slots": [
{
"name": "restaurantname",
"type": "AMAZON.Person"
}
],
"samples": [
"{restaurantname}",
"go to {restaurantname}"
]
},
{
"name": "LaunchRequest"
}
],
"types": [
{
"name": "Location",
"values": [
{
"name": {
"value": "Current location"
}
},
{
"name": {
"value": "Future location"
}
},
]
}
]
}
}
};
I except output for particular intents user utterance without concat any string.
output like this:- {user utterance}.
output not like this :- prefix(anystring) {user utterance} suffix(anystring).