У меня есть два намерения (HelloWorldIntent и PlaceOrderIntent), в моем первом намерении речь идет о привет, мир, а во втором намерении я размещаю заказ (для этого мне нужно заполнить слоты)

user: open demo bot
Alexa: welcome!
user: place order
alexa: you can order platter, soup, and shake?
user: soup
alexa: which type of soup? tomato, onion or corn?
user: tomato
alexa: your order for tomato soup has been placed.

Это работает нормально, но если пользователь запускает HelloWorldIntent между PlaceOrderIntent, тогда он срабатывает, как этого избежать

user: open demo bot
alexa: welcome!
user: place order
alexa: you can order platter, soup and shake?
user : hello
alexa: hello world!

Без завершения PlaceOrderIntent срабатывает другое намерение вместо отображения сообщения с повторной подсказкой.

Это мой код

const HelloWorldIntentHandler = {
    canHandle(handlerInput) {
        return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
            && Alexa.getIntentName(handlerInput.requestEnvelope) === 'HelloWorldIntent';
    },
    handle(handlerInput) {
        const speakOutput = 'Hello World!';
        return handlerInput.responseBuilder
            .speak(speakOutput)
            .reprompt()
            .getResponse();
    }
};

const StartedInProgressOrderFoodIntentHandler = {
  canHandle(handlerInput) {
    return handlerInput.requestEnvelope.request.type === "IntentRequest"
      && handlerInput.requestEnvelope.request.intent.name === "PlaceOrderIntent"
      && handlerInput.requestEnvelope.request.dialogState !== 'COMPLETED'
      && !handlerInput.requestEnvelope.request.intent.slots.menu.value;
  },
  handle(handlerInput) {
  const speakOutput = `You can order Platters, Soups and, Shakes. What you want to order?`
  const prompt = `Please select any one from platter, soup or, drink.`
    return handlerInput.responseBuilder
      .speak(speakOutput)
      .reprompt(prompt)
      .addElicitSlotDirective('menu')
      .getResponse();
  }
};

const PlatterGivenOrderFoodIntentHandler = {
canHandle(handlerInput) {
    return handlerInput.requestEnvelope.request.type === "IntentRequest"
      && handlerInput.requestEnvelope.request.intent.name === "PlaceOrderIntent"
      && handlerInput.requestEnvelope.request.intent.slots.menu.value 
      && handlerInput.requestEnvelope.request.intent.slots.menu.value === 'platter'
      && !handlerInput.requestEnvelope.request.intent.slots.platType.value;
  },
  handle(handlerInput) {
    const speakOutput = `Which platter would you like Regular, Special, Rajasthani, Gujarati, or Punjabi?`
    const prompt = `Which platter would you like Regular, Special, Rajasthani, Gujarati, or Punjabi?`
      return handlerInput.responseBuilder
      .speak(speakOutput)
      .reprompt(prompt)
      .addElicitSlotDirective('platType')
      .getResponse();
  }
};

const SoupGivenOrderFoodIntentHandler = {
  canHandle(handlerInput) {
    return handlerInput.requestEnvelope.request.type === "IntentRequest"
      && handlerInput.requestEnvelope.request.intent.name === "PlaceOrderIntent"
      && handlerInput.requestEnvelope.request.intent.slots.menu.value
      && handlerInput.requestEnvelope.request.intent.slots.menu.value === 'soup'
      && !handlerInput.requestEnvelope.request.intent.slots.soupType.value;
  },
  handle(handlerInput) {
      return handlerInput.responseBuilder
      .speak("Which soup would you like tomato, manchow, onion, or corn soup?")
      .reprompt("Would you like a tomato, manchow, onion, or corn soup?")
      .addElicitSlotDirective('soupType')
      .getResponse();
  }
};

const ShakeGivenOrderFoodIntentHandler = {
  canHandle(handlerInput) {
    return handlerInput.requestEnvelope.request.type === "IntentRequest"
      && handlerInput.requestEnvelope.request.intent.name === "PlaceOrderIntent"
      && handlerInput.requestEnvelope.request.intent.slots.menu.value
      && handlerInput.requestEnvelope.request.intent.slots.menu.value === 'shake'
      && !handlerInput.requestEnvelope.request.intent.slots.shakeType.value;
      },
  handle(handlerInput) {
      return handlerInput.responseBuilder
      .speak("Which shake would you like chocolate, vanilla, milk, strawberry, or mango shake?")
      .reprompt("Would you like a chocolate, vanilla, milk, strawberry, or mango shake?")
      .addElicitSlotDirective('shakeType')
      .getResponse();
  }
};

const CompletedOrderFoodIntentHandler = {
  canHandle(handlerInput) {
    return handlerInput.requestEnvelope.request.type === "IntentRequest"
        && handlerInput.requestEnvelope.request.intent.name === "PlaceOrderIntent"
        && handlerInput.requestEnvelope.request.dialogState === "COMPLETED"
        && handlerInput.requestEnvelope.request.intent.slots.menu.value
        || handlerInput.requestEnvelope.request.intent.slots.platType.value || handlerInput.requestEnvelope.request.intent.slots.soupType.value || handlerInput.requestEnvelope.request.intent.slots.shakeType.value;
  },
  handle(handlerInput){

    const menuitems = handlerInput.requestEnvelope.request.intent.slots.menu.value;
    let type; 

    if (menuitems === 'platter') {
        type = handlerInput.requestEnvelope.request.intent.slots.platType.value;
    } else if (menuitems === 'soup') {
        type = handlerInput.requestEnvelope.request.intent.slots.soupType.value;
    } else if (menuitems === 'shake') {
        type = handlerInput.requestEnvelope.request.intent.slots.shakeType.value;
    } else {
        type = 'water'
    }

    const speechText = `Your order for ${type} ${menuitems} has been placed.`;
        return handlerInput.responseBuilder
        .speak(speechText)
        .reprompt()
        .getResponse();
  }
};
0
Vikas Patidar 13 Апр 2020 в 06:20

1 ответ

Похоже, вы хотите конечный автомат.

Вот например...

  • Установите state = started sessionVariable при входе на шаг, который вы хотите заблокировать. т. е. StartedInProgress
handlerInput.attributesManager.setSessionAttributes({state: "started"});
  • Теперь вы только "отключаете" state в своих намерениях OrderFood.
handlerInput.attributesManager.setSessionAttributes({state: ""});
  • Наконец, если вы сначала зарегистрируете StartedInProcess… (поищите addRequestHandlers в файле index.js) и настроите canHandle этого намерения так, чтобы оно включало "состояние начальное, а не одно из Намерения OrderFood», он всегда будет срабатывать, если вы находитесь в этом состоянии, но не пытаетесь сделать заказ.
const StartedInProgressOrderFoodIntentHandler = {
  canHandle(handlerInput) {
      const sessionAttributes = handlerInput.attributesManager.getSessionAttributes();
      hasStarted = sessionAttributes.state == "started"
      isOrdering = handlerInput.requestEnvelope.request.intent.name.includes('GivenOrder')
      return (hasStarted and !isOrdering) or (
        handlerInput.requestEnvelope.request.type === "IntentRequest"
        && handlerInput.requestEnvelope.request.intent.name === "PlaceOrderIntent"
        && handlerInput.requestEnvelope.request.dialogState !== 'COMPLETED'
        && !handlerInput.requestEnvelope.request.intent.slots.menu.value);
    }
  …

Поймите, что это означает, что ваши пользователи будут БЛОКИРОВАНЫ в процессе… если вы не зарегистрируете другое намерение (скажем, Выход?) до StartedInProcess, которое может очистить state — что я настоятельно рекомендую.

0
Timothy Aaron 15 Апр 2020 в 00:12
Спасибо, @Timothy Aaron за помощь, но я новичок, поэтому не могли бы вы показать мне, как должен выглядеть код, когда вы будете следовать вашим шагам.
 – 
Vikas Patidar
14 Апр 2020 в 07:12
Я старался. Я использую Python SDK, поэтому моих навыков работы с JS (не говоря уже о Alexa NodeJS SDK) не хватает... но, по крайней мере, это должно дать вам достаточно деталей, чтобы понять большую часть пути. Удачи.
 – 
Timothy Aaron
15 Апр 2020 в 00:13