You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Alexa对话流规范咨询:电影问答游戏代码优化方案

Standard Approach for Stateful Alexa Skill Dialog Flows

Hey there, I totally get the frustration with nested if-else spaghetti code when building Alexa skills—this is a super common pain point when you’re first figuring out how to manage conversation flows. The good news is that stateful intent handling is the standard/traditional way to solve this exact problem, and it’ll clean up your code dramatically while giving you full control over when intents can trigger.

Here’s a step-by-step breakdown of how to implement your movie trivia game flow properly:

Core Concept: Explicit Session States

First, define clear, discrete states for each stage of your conversation. For your game, these would be:

  • ASKING_RULES: Waiting for user to say yes/no to hearing rules
  • ASKING_CATEGORY: Waiting for user to pick a genre
  • QUIZZING: In the middle of answering questions

Store the current state in sessionAttributes (e.g., sessionAttributes.currentState = "ASKING_RULES"). Each intent handler will first check this state to decide if it should act, or redirect the user back to the current conversation stage.

Step-by-Step Implementation

1. Launch Request: Initialize State

When the user triggers Alexa, start Movie Trivia, your LaunchRequestHandler sets the initial state and sends the welcome message:

const LaunchRequestHandler = {
  canHandle(handlerInput) {
    return Alexa.getRequestType(handlerInput.requestEnvelope) === 'LaunchRequest';
  },
  handle(handlerInput) {
    const sessionAttributes = handlerInput.attributesManager.getSessionAttributes();
    sessionAttributes.currentState = 'ASKING_RULES';
    handlerInput.attributesManager.setSessionAttributes(sessionAttributes);

    const speechText = 'Welcome to Movie Trivia! Would you like to hear the rules first?';
    return handlerInput.responseBuilder
      .speak(speechText)
      .reprompt(speechText)
      .getResponse();
  }
};

2. Handle Rules Yes/No Response

Use Alexa’s built-in AMAZON.YesIntent and AMAZON.NoIntent to handle the user’s rule preference. The key here is checking the current state before acting:

const YesIntentHandler = {
  canHandle(handlerInput) {
    const sessionAttributes = handlerInput.attributesManager.getSessionAttributes();
    return (
      Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest' &&
      Alexa.getIntentName(handlerInput.requestEnvelope) === 'AMAZON.YesIntent' &&
      sessionAttributes.currentState === 'ASKING_RULES'
    );
  },
  handle(handlerInput) {
    const sessionAttributes = handlerInput.attributesManager.getSessionAttributes();
    sessionAttributes.currentState = 'ASKING_CATEGORY'; // Move to next state
    handlerInput.attributesManager.setSessionAttributes(sessionAttributes);

    const speechText = 'Great! Here are the rules: I’ll ask you a movie question, and you answer with the correct option. Ready? Pick a category: Comedy, Drama, or Animation.';
    return handlerInput.responseBuilder
      .speak(speechText)
      .reprompt('Did you say Comedy, Drama, or Animation?')
      .getResponse();
  }
};

const NoIntentHandler = {
  canHandle(handlerInput) {
    const sessionAttributes = handlerInput.attributesManager.getSessionAttributes();
    return (
      Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest' &&
      Alexa.getIntentName(handlerInput.requestEnvelope) === 'AMAZON.NoIntent' &&
      sessionAttributes.currentState === 'ASKING_RULES'
    );
  },
  handle(handlerInput) {
    const sessionAttributes = handlerInput.attributesManager.getSessionAttributes();
    sessionAttributes.currentState = 'ASKING_CATEGORY';
    handlerInput.attributesManager.setSessionAttributes(sessionAttributes);

    const speechText = 'Got it! Pick a category: Comedy, Drama, or Animation.';
    return handlerInput.responseBuilder
      .speak(speechText)
      .reprompt('Choose Comedy, Drama, or Animation to start playing!')
      .getResponse();
  }
};

3. Handle Category Selection

Create a custom SetCategoryIntent (with a slot for category that accepts your three options). Again, restrict this intent to only trigger when in the ASKING_CATEGORY state:

const SetCategoryIntentHandler = {
  canHandle(handlerInput) {
    const sessionAttributes = handlerInput.attributesManager.getSessionAttributes();
    return (
      Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest' &&
      Alexa.getIntentName(handlerInput.requestEnvelope) === 'SetCategoryIntent' &&
      sessionAttributes.currentState === 'ASKING_CATEGORY'
    );
  },
  handle(handlerInput) {
    const sessionAttributes = handlerInput.attributesManager.getSessionAttributes();
    const category = Alexa.getSlotValue(handlerInput.requestEnvelope, 'category');
    
    // Validate the category (you can add more checks here)
    if (['comedy', 'drama', 'animation'].includes(category.toLowerCase())) {
      sessionAttributes.category = category.toLowerCase();
      sessionAttributes.currentState = 'QUIZZING';
      handlerInput.attributesManager.setSessionAttributes(sessionAttributes);

      // Fetch first question for the category
      const firstQuestion = getFirstQuestion(sessionAttributes.category);
      return handlerInput.responseBuilder
        .speak(firstQuestion)
        .reprompt(firstQuestion)
        .getResponse();
    } else {
      // Invalid category, prompt again
      const speechText = "Sorry, I didn't recognize that category. Please choose Comedy, Drama, or Animation.";
      return handlerInput.responseBuilder
        .speak(speechText)
        .reprompt(speechText)
        .getResponse();
    }
  }
};

4. Restrict Unintended Intent Triggers

For any other intents (like answer intents or help), add state checks to make sure they only fire when appropriate. For example, if a user tries to answer a question before picking a category, redirect them:

const AnswerIntentHandler = {
  canHandle(handlerInput) {
    const sessionAttributes = handlerInput.attributesManager.getSessionAttributes();
    return (
      Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest' &&
      Alexa.getIntentName(handlerInput.requestEnvelope) === 'AnswerIntent' &&
      sessionAttributes.currentState === 'QUIZZING'
    );
  },
  // ... handle answer logic here
};

// Fallback for invalid intent triggers
const UnhandledIntentHandler = {
  canHandle(handlerInput) {
    return true; // Catch all unhandled requests
  },
  handle(handlerInput) {
    const sessionAttributes = handlerInput.attributesManager.getSessionAttributes();
    let speechText = '';

    switch(sessionAttributes.currentState) {
      case 'ASKING_RULES':
        speechText = "I didn't catch that. Would you like to hear the rules?";
        break;
      case 'ASKING_CATEGORY':
        speechText = "Let's pick a category first! Choose Comedy, Drama, or Animation.";
        break;
      case 'QUIZZING':
        speechText = "Sorry, I didn't get that. Please answer with the correct option.";
        break;
      default:
        speechText = "Welcome to Movie Trivia! Would you like to hear the rules first?";
    }

    return handlerInput.responseBuilder
      .speak(speechText)
      .reprompt(speechText)
      .getResponse();
  }
};

Why This Works Better Than Nested If-Else

  • Cleaner code: Each intent handler is responsible for one specific action in one specific state, so you don’t have a giant block of nested conditions.
  • Full control: You explicitly define when each intent can trigger, so no accidental repeats or out-of-order actions.
  • Scalable: Adding new states (like a score summary at the end) is easy—just define a new state and corresponding handler.

Avoiding ElicitSlot Confusion

You mentioned elicitSlot causing repeated intent triggers. That’s because elicitSlot is designed for filling missing slots within a single intent (e.g., if you have an intent that needs both a category and difficulty). For navigating between different conversation stages (like moving from rules to category selection), state transitions are the right tool, not elicitSlot.

Additional Best Practices

  • Use built-in intents: Leverage AMAZON.YesIntent, AMAZON.NoIntent, AMAZON.HelpIntent, etc., instead of creating custom ones—Alexa handles natural language understanding for you.
  • Validate slots: Always check that slot values match your expected options before proceeding.
  • Clean up session attributes: When the skill ends (via AMAZON.StopIntent or AMAZON.CancelIntent), clear session attributes to reset the state for next time.

内容的提问来源于stack exchange,提问作者GreenTriangle

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 06:55:37