question

janmajay avatar image
janmajay asked ·

How to Build Conversation with Alexa?

The requirement is stated below.


I have two Intents, OfferIntent and SelectedOfferIntent, the offers are presented to User on successful trigger of OfferIntent, after this voice message I'm using reprompt to ask the User which offer he/she wants to select. When the user says option1,option2 etc it should trigger SelectedOfferIntent. Option1, option2 etc are captured as slot value for SelectedOfferIntent.

This is not working, User input after reprompt doesn't gets mapped to SelectedOfferIntent.


User: Alexa, ask mySkill are there any available offers for me.

Alexa: The available offers are offer1, offer2, offer3.

Alexa (Reprompt): Are you interested in these offers? If Yes, mention the offers as option1, option2, option3 etc. (here option1, option2 etc are captured in slot which is used in SelectedOfferIntent)

User: I select option2

Alexa: Sorry, I don't understand the command.


I need to further build the conversation. Any suggestion/help please.



alexa skills kitalexa voice servicealexaalexa dev days
1 comment
10 |2000 characters needed characters left characters exceeded

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Sounds like an interaction model issue to me. Try re-building your model.

Also you can check what alexa matches when you press 'Evaluate model' button, which you can find when you are editing interaction model. Try entering 'option one' and see what it matches.

The important bit is to write numbers as words, even though console allows to write numeric values. On second thought, this might be your issue. Instead of testing with 'option 2', try entering 'option two' and see if that helps. It works the same way on the device, because alexa always parses user said numbers as words, not numerics.

0 Likes 0 ·
janmajay avatar image
janmajay answered ·

@RokasV - I was able to find the issue. After reprompt the correct intent handler was getting called.

As I described earlier I created a slot type as options with values option one, option two etc. When I checked in Evaluate Model for utterance 'I select option one' Alexa framework was giving the slot value as 'option 1' instead on 'option one'.

So I did the below change to by global variable index array.

var index = {"option 1":0, "option 2":1, "option 3":2, "option 4":3, "option 5":4};

thus I was able to parse the offers global variable properly.

      // we can also use getSlotValue(handlerInput.requestEnvelope, 'OfferOptions');
        const selectedOffer = handlerInput.requestEnvelope.request.intent.slots.OfferOptions.value;
  
        // In below step i'm trying to get the correct index of selected offer/slot value so that I can traverse the offers JSON array object
        var speakOutput = "You have selected Offer " + (index[selectedOffer] + 1) + "." + " Here are the offer benefits, " + offers[index[selectedOffer]].Benefits;


Thanks a lot for all the help.

I just have one question if the conversation gets too long, for every user input after reprompt we have to create a new Intent or is there a better way?

1 comment
10 |2000 characters needed characters left characters exceeded

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

I am happy you figured it out.

I am just not sure what you are asking in your new question. What do you mean by saying 'conversation getting too long'? Can you give me an example dialog how do you think it is going to look like?

0 Likes 0 ·
janmajay avatar image
janmajay answered ·

@RokasV - I tried 'Evaluate Model' button, it maps the Utterances to correct intent 'SelectedOfferIntent' on trying with both 'option1' and 'option one' as slot values. I have changed the slot values of my options slot type as 'option one', 'option two' etc. When I Test the utterance in Test console and in Alexa device, Alexa still says ' Sorry, I don't understand the command.' But I can see that the correct Intent is hit and slot value is captured in the request JSON.


In my scenario 'SelectedOfferIntent' is meant to output the Benefits of the offer selected by the User(after reprompt). In the SelectedOfferHandler I'm trying to use the same Global variable in which I captured Offers (from a REST API) in the 'OfferHandler' code. After reprompt when the Intent switch is happening I believe the offers info in the global variable is missing. Can this be the issue? If Yes, then how to persist the information captured in previous Intent. Any code sample will be helpful.

10 comments
10 |2000 characters needed characters left characters exceeded

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

So maybe the problem is that after first intent skill session closes. Check your response JSON, does it have reprompt in it? Maybe 'shouldEndSession' is set to 'true'? Can you share some of your code? It might be easier to spot the issue.

0 Likes 0 ·

@RokasV - Please find the response below. The response has reprompt and shouldEndSession is false.


{
    "body": {
        "version": "1.0",
        "response": {
            "outputSpeech": {
                "type": "SSML",
                "ssml": "<speak>The available offers are, 1 UpSell, 2 Upgrade, 3 DigitalInvoice, 4 CrossSell, 5 Referral</speak>"
            },
            "reprompt": {
                "outputSpeech": {
                    "type": "SSML",
                    "ssml": "<speak>Are you interested in these offers? If Yes, mention the offers as option1, option2, option3 etc.</speak>"
                }
            },
            "shouldEndSession": false,
            "type": "_DEFAULT_RESPONSE"
        },
        "sessionAttributes": {},
        "userAgent": "ask-node/2.7.0 Node/v10.19.0"
    }
}


0 Likes 0 ·

@RokasV - Below is the code I'm using inside OfferHandler.


const res = await fetch(config.InstanceUrl,{
            method: 'POST',
            body: JSON.stringify(post_body),
            headers: {'Content-Type': 'application/json'}
        });
        const json = await res.json();
        // parse the response JSON
        offers = json.ContainerList[0].RankedResults;
        console.log("The Offers are : " + JSON.stringify(offers));
        
        var speakOutput = "";
        var repromptText = "";
        var offerNumber = 0;

        
        // Loop the offers to create a unified text for speech output
        if(offers.length>0){
            for(var i=0; i<offers.length; i++){
              offerNumber = i + 1
                speakOutput += ", " + offerNumber + " " + offers[i].Name;
            }
            // prepare the speakOutput variable
            speakOutput = "The available offers are" + speakOutput;
            repromptText = "Are you interested in these offers? If Yes, mention the offers as option1, option2, option3 etc. ";
            
        }else{
          speakOutput = "No offers are available for you at the moment. Please try again later";
        }
        
        // prepare the JSON response that skill returns
        return handlerInput.responseBuilder
            .speak(speakOutput)
            .reprompt(repromptText)
            .getResponse();
0 Likes 0 ·

@RokasV - Below code is used for SelectedOfferHandler.

Note : offers and index are global variable declared at the top of code.

const Alexa = require('ask-sdk-core');
const fetch = require('node-fetch');
const config = require('config');
// making offers a global variable, to be able to use it in more that one handlers
var offers = "";
// map the offer options to indexes
var index = {"option one":0, "option two":1, "option three":2, "option four":3, "option five":4};

const SelectedOfferHandler = {

    canHandle(handlerInput){
        return handlerInput.requestEnvelope.request.type === 'IntentRequest'
        && handlerInput.requestEnvelope.request.intent.name === 'SelectedOfferIntent';
    },handle(handlerInput){
      // we can also use getSlotValue(handlerInput.requestEnvelope, 'OfferOptions');
        const selectedOffer = handlerInput.requestEnvelope.request.intent.slots.OfferOptions.value;
       
        // In below step i'm trying to get the correct index of selected offer/slot value so that I can traverse the offers JSON array object
        var speakOutput = "You have selected Offer " + (index[selectedOffer] + 1) + "." + "Here are the offer benefits " + offers[index[selectedOffer]].Benefits;
        
        var repromptText = "Would you like to know more?";
        
        // prepare the JSON response that skill returns
        return handlerInput.responseBuilder
            .speak(speakOutput)
            .reprompt(repromptText)
            .getResponse();
    },
};
0 Likes 0 ·

Hmm, looks correct. I am running out of ideas what could be wrong. One more thing to check would be is that are you sure that you're invoking the right skill? If you have any other dev skills with similar or same invocation name, make sure to disable them.

Other than that share your skill id, so that someone from amazon could take a look what's wrong with your skill, because I have nothing else to suggest.

0 Likes 0 ·
Show more comments