使用具有多个意图的alexa的酒店预订概念

时间:2019-08-05 06:30:17

标签: alexa alexa-skill alexa-voice-service alexa-slot alexa-app

你好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).

0 个答案:

没有答案