AMAZON.FallbackIntent не работает ask-sdk: 2.0.10

Я пытаюсь использовать встроенные функции Amazon для запросов за пределами диапазона в моем навыке Custom Alexa. Alexa могла бы использовать для этого "AMAZON.FallbackIntent", я нашел здесь базовую настройку: https://developer.amazon.com/it/blogs/alexa/post/f6bb7c54-de0d-4abe-98c3-cf3fc75c32f8/how-to-add-fallbackintent-processing-to-your-alexa-skill

Эта возможность теперь доступна для всех локалей "en", во всяком случае после многочисленных попыток я создал "en-GB.json" и "en-US.json" с такой же структурой, как показано ниже:

"intents": [
            {
                "name": "AMAZON.FallbackIntent",
                "samples": []
            },
            {
                "name": "AMAZON.CancelIntent",
                "samples": []
            },
            {
                "name": "AMAZON.HelpIntent",
                "samples": [
                    "I don't know",
                    "What can you do",
                    "What are you capable of",
                    "What is this",
                    "help"
                ]
            },
            {
                "name": "AMAZON.StopIntent",
                "samples": []
            },

Все встроенные намерения работают нормально, за исключением резервного. Вот пример из фрагментов index.js для навыка:

const Alexa = require('ask-sdk');
const dbHelper = require('./helpers/dbHelper');
const GENERAL_REPROMPT = "What would you like to do?";

const dynamoDBTableName = "movies";
const LaunchRequestHandler = 
{ 
    canHandle(handlerInput) {
        const request = handlerInput.requestEnvelope.request;
        return request.type === 'LaunchRequest';
    },
    handle(handlerInput) {
        const speechText = 'Welcome to the X ' + '&' + 'Y Customer Service, my name is Natalia, how may I help you today?';
        const repromptText = 'What would you like to do? You can say HELP to get available options';

        return handlerInput.responseBuilder
        .speak(speechText)
        .reprompt(repromptText)
        .getResponse();
    }
};
const InProgressAddMovieIntentHandler = {
canHandle(handlerInput) {
    const request = handlerInput.requestEnvelope.request;
    return request.type === 'IntentRequest' &&
    request.intent.name === 'AddMovieIntent' &&
    request.dialogState !== 'COMPLETED';
},
handle(handlerInput) {
    const currentIntent = handlerInput.requestEnvelope.request.intent;
    return handlerInput.responseBuilder
    .addDelegateDirective(currentIntent)
    .getResponse();
}
};
const AddMovieIntentHandler = {
canHandle(handlerInput) {
    return handlerInput.requestEnvelope.request.type === 'IntentRequest'
    && handlerInput.requestEnvelope.request.intent.name === 'AddMovieIntent';
},
async handle(handlerInput) {
    const {responseBuilder } = handlerInput;
    const userID = handlerInput.requestEnvelope.context.System.user.userId; 
    const slots = handlerInput.requestEnvelope.request.intent.slots;
    const movieName = slots.MovieName.value;
    return dbHelper.addMovie(movieName, userID)
    .then((data) => {
        const speechText = `You have added movie ${movieName}. You can say add to add another one or remove to remove movie`;
        return responseBuilder
        .speak(speechText)
        .reprompt(GENERAL_REPROMPT)
        .getResponse();
    })
    .catch((err) => {
        console.log("Error occured while saving movie", err);
        const speechText = "we cannot save your movie right now. Try again!"
        return responseBuilder
        .speak(speechText)
        .getResponse();
    })
},
};
const GetMoviesIntentHandler = {
canHandle(handlerInput) {
    return handlerInput.requestEnvelope.request.type === 'IntentRequest'
    && handlerInput.requestEnvelope.request.intent.name === 'GetMoviesIntent';
},
async handle(handlerInput) {
    const {responseBuilder } = handlerInput;
    const userID = handlerInput.requestEnvelope.context.System.user.userId; 
    return dbHelper.getMovies(userID)
    .then((data) => {
        var speechText = "Your movies are "
        if (data.length == 0) {
        speechText = "You do not have any favourite movie yet, add movie by saving add moviename "
        } else {
        speechText += data.map(e => e.movieTitle).join(", ")
        }
        return responseBuilder
        .speak(speechText)
        .reprompt(GENERAL_REPROMPT)
        .getResponse();
    })
    .catch((err) => {
        const speechText = "we cannot get your movie right now. Try again!"
        return responseBuilder
        .speak(speechText)
        .getResponse();
    })
}
};
const InProgressRemoveMovieIntentHandler = {
canHandle(handlerInput) {
    const request = handlerInput.requestEnvelope.request;
    return request.type === 'IntentRequest' &&
    request.intent.name === 'RemoveMovieIntent' &&
    request.dialogState !== 'COMPLETED';
},
handle(handlerInput) {
    const currentIntent = handlerInput.requestEnvelope.request.intent;
    return handlerInput.responseBuilder
    .addDelegateDirective(currentIntent)
    .getResponse();
}
};
const RemoveMovieIntentHandler = {
canHandle(handlerInput) {
    return handlerInput.requestEnvelope.request.type === 'IntentRequest'
    && handlerInput.requestEnvelope.request.intent.name === 'RemoveMovieIntent';
}, 
handle(handlerInput) {
    const {responseBuilder } = handlerInput;
    const userID = handlerInput.requestEnvelope.context.System.user.userId; 
    const slots = handlerInput.requestEnvelope.request.intent.slots;
    const movieName = slots.MovieName.value;
    return dbHelper.removeMovie(movieName, userID)
    .then((data) => {
        const speechText = `You have removed movie with name ${movieName}, you can add another one by saying add`
        return responseBuilder
        .speak(speechText)
        .reprompt(GENERAL_REPROMPT)
        .getResponse();
    })
    .catch((err) => {
        const speechText = `You do not have movie with name ${movieName}, you can add it by saying add`
        return responseBuilder
        .speak(speechText)
        .reprompt(GENERAL_REPROMPT)
        .getResponse();
    })
}
};
const HelpIntentHandler = {
canHandle(handlerInput) {
    return handlerInput.requestEnvelope.request.type === 'IntentRequest'
    && handlerInput.requestEnvelope.request.intent.name === 'AMAZON.HelpIntent';
},
handle(handlerInput) {
    const speechText = 'You can access information about products, place an order or raise and issue';
    const repromptText = 'What would you like to do? You can say HELP to hear the options again';

    return handlerInput.responseBuilder
    .speak(speechText)
    .reprompt(repromptText)
    .getResponse();
},
};
const CancelAndStopIntentHandler = {
canHandle(handlerInput) {
    return handlerInput.requestEnvelope.request.type === 'IntentRequest'
    && (handlerInput.requestEnvelope.request.intent.name === 'AMAZON.CancelIntent'
        || handlerInput.requestEnvelope.request.intent.name === 'AMAZON.StopIntent');
},
handle(handlerInput) {
    const speechText = 'Goodbye! See you later!';

    return handlerInput.responseBuilder
    .speak(speechText)
    .getResponse();
},
};
const FallbackHandler = {
canHandle(handlerInput) {
    const request = handlerInput.requestEnvelope.request;
    return request.type === 'IntentRequest' && request.intent.name === 'AMAZON.FallbackIntent';
},
handle(handlerInput) {
    const output = "I am sorry, I can't help with that";
    return handlerInput.responseBuilder
    .speak(output)
    .reprompt(output)
    .getResponse();
},
};
const SessionEndedRequestHandler = {
canHandle(handlerInput) {
    return handlerInput.requestEnvelope.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) {
    console.log(`Error handled: ${error.message}`);

    return handlerInput.responseBuilder
    .speak('Sorry, I can\'t understand the command. Please say again.')
    .reprompt('Sorry, I can\'t understand the command. Please say again.')
    .getResponse();
},
};
const skillBuilder = Alexa.SkillBuilders.standard();
exports.handler = skillBuilder
.addRequestHandlers(
    LaunchRequestHandler,
    InProgressAddMovieIntentHandler,
    AddMovieIntentHandler,
    GetMoviesIntentHandler,
    InProgressRemoveMovieIntentHandler,
    RemoveMovieIntentHandler,
    HelpIntentHandler,
    CancelAndStopIntentHandler,
    SessionEndedRequestHandler,
    FallbackHandler
)
.addErrorHandlers(ErrorHandler)
.withTableName(dynamoDBTableName)
.withAutoCreateTable(true)
.lambda();

После запуска навыка оно выполняет:

SpeechText

для которого я пытаюсь сказать, какая погода, навык игнорирует этот ввод и просто выполняет:

repromptText

а потом, если я снова запрошу погоду, он просто закроет навык ...

Как сделать так, чтобы это работало для моделей на английском языке?


person G Tuli    schedule 18.02.2019    source источник


Ответы (1)


Ваш сеанс заканчивается сразу после того, как вы отправите свой SpeechText в обработчике LanunchRequest. По окончании сеанса Алекса не знает, что вы пытаетесь задействовать свой навык, говоря: «Какая погода?» и, следовательно, не вызывает ваш резервный обработчик.

Используйте withShouldEndSession(false), и он будет держать сеанс открытым, и любой неверный ввод попадет в обработчик Fallback.

Код ниже должен работать.

const LaunchRequestHandler = 
{ 
    canHandle(handlerInput) {
        const request = handlerInput.requestEnvelope.request;
        return request.type === 'LaunchRequest';
    },
    handle(handlerInput) {
        const speechText = 'Welcome to the X ' + '&' + 'Y Customer Service, my name is Natalia, how may I help you today?';
        const repromptText = 'What would you like to do? You can say HELP to get available options';

        return handlerInput.responseBuilder
        .speak(speechText)
        .withShouldEndSession(false) 
        .reprompt(repromptText)
        .getResponse();
    }
};
person Shailesh Pratapwar    schedule 19.02.2019
comment
К сожалению, это не работает. Журнал устройства по-прежнему говорит, что намерение является резервным, но оно не запускает его на лямбде. - person G Tuli; 19.02.2019
comment
Поскольку вы можете видеть журнал устройства для этого вызова, это означает, что ваш резервный обработчик был обнаружен и использован. Можете ли вы попробовать добавить несколько операторов журнала консоли, а также попробовать удалить повторную подсказку в обработчике отката? - person Shailesh Pratapwar; 19.02.2019
comment
Просто добавил политику для Clouwatch в свою лямбду, я также добавил console.logs для запроса на запуск, но внутри FallbackHandler ничего не срабатывает. - person G Tuli; 19.02.2019