Rohan Venkatram
Rohan Venkatram

Reputation: 31

How to program a decision tree with Alexa?

I am currently trying to program an alexa skill. I am very stuck... trying to see if I can get Alexa to ask the user 'How they are feeling' and then use this to ask further questions. Not sure if I should make a variable or attribute... any help please. For example, once the user says "SAD" for the emotion - I want to be able to ask further questions, like "Is it from your past or present?"

(AWS code)

const GREETING = [
'What emotion are you feeling today?',
'Hello, what emotion are you feeling right now?'
];
const SKILL_NAME = 'March Test';
const GET_FEEL = "That is unfortunate to hear?";
const HELP_MESSAGE = 'I can give you more information if you tell me 
how you are feeling';
const HELP_REPROMPT = 'How are you feeling currently?';
const STOP_MESSAGE = 'Goodbye!';


const FeelingsList = [
{
    Emotion: "SAD",
    suggestion: "My suggestion for sad is dry your tears and find a 
distraction" 
},
{
    Emotion: "HAPPY",
    suggestion: "My suggestion for happy is keep smiling and keep shining"
},
{
    Emotion: "ANGRY",
    suggestion: "My suggestion for angry is count to ten and cool down"
}

];

const handlers = {
'LaunchRequest': function () {
    const greetingArr = GREETING;
    const greetingIndex = Math.floor(Math.random() * 
greetingArr.length);
    this.emit(':ask',greetingArr[greetingIndex]); //first action that 
will be fired
},
'EmotionalState': function () {
  var stateSlot = this.event.request.intent.slots.Emotion.value;
  this.emit(':ask', EmotionalResponse(FeelingsList, 'Emotion', 
stateSlot.toUpperCase()).suggestion);
},


'AMAZON.HelpIntent': function () {
    const speechOutput = HELP_MESSAGE;
    const reprompt = HELP_REPROMPT;

    this.response.speak(speechOutput).listen(reprompt);
    this.emit(':responseReady');
},
'AMAZON.CancelIntent': function () {
    this.response.speak(STOP_MESSAGE);
    this.emit(':responseReady');
},
'AMAZON.StopIntent': function () {
    this.response.speak(STOP_MESSAGE);
    this.emit(':responseReady');
},

Upvotes: 3

Views: 558

Answers (2)

Jay A. Little
Jay A. Little

Reputation: 3287

Okay, thanks for answering my questions in comments, the EmotionalResponse function looks good. The way you have it set up currently should work well for a single response. If that is all you want Alexa to do here then just change ':ask' to ':tell' (which will respond and not expect the user to reply) so the line would become:

this.emit(':tell', EmotionalResponse(FeelingsList, 'Emotion', stateSlot.toUpperCase()).suggestion );

However, you want to be able to continue the conversation with multiple questions and response handlings. You might already have this but it's not in your code above, and you need it to use the Alexa SDK, so make sure you have this line at the very beginning:

const Alexa = require('alexa-sdk');

You also need this, preferably at the end:

exports.handler = function(event, context, callback) {
    const alexa = Alexa.handler(event, context, callback);
    alexa.registerHandlers(handlers);
    alexa.execute();
};

Next, some things to know about continuing a conversation using Alexa SDK:

':ask'
will respond with the speechOutput sentence and expect a reply from the user, but if the user does not reply, then Alexa will "reprompt" the user with the repromptSpeech sentence.

':delegate'
will tell Alexa to determine which required slot to ask the user for, and use the prompt (set up in the Alexa developer console) to elicit the slot information from the user.

':elicitSlot'
will give Alexa the specific instructions of which slot to elicit and the exact prompt to use.


There are many ways to continue an Alexa conversation and build your logic of handling the user's input and build an appropriate response. But to use your example of requesting more information from the user such as "Is it from your past or present?", here is one way I would suggest:

First, create another slot for this intent (anytime you want to hold user input information you'll need another slot). Let's call it Timeframe.

The simplest way is to "delegate" to Alexa to elicit this slot, so in the console make the slot required and add a prompt message such as, "Are you feeling this way because of something in your past or present?" You can even get fancy and use the emotion slot in that message like this: "Are you feeling {Emotion} because of something in your past or present?" Alexa will auto fill that and it will sound more intelligent and conversational.

Next you'll want to improve the logic of this intent inside const handlers:

const handlers = {
   ...
   'EmotionalState': function () {
      var emotion = this.event.request.intent.slots.Emotion.value;
      var timeframe = this.event.request.intent.slots.Timeframe.value;
      if (!timeframe){
        this.emit(':delegate');
      } else {
        var response = responseBuilder(emotion, timeframe);
        this.emit(':tell', response);
      }
    },
    ...
} //<<--------------your code seems to be missing this to close handlers

function responseBuilder(emotion, timeframe) {
    // compare emotion with timeframe to build the appropriate response
    // just for example
    if (emotion=="sad" && timeframe=="past") { 
        return "My suggestion for feeling sadness about the past is, dry your tears and find a distraction.";
    }
}      

That's just a rough idea, but should certainly get you progressing again. Good luck!

Upvotes: 1

gd vigneshwar
gd vigneshwar

Reputation: 887

Create a global object emotions and have all the emotions as properties and the corresponding suggestions as the value for them. Something like this,

const emotions = {"Happy" : "Keep smiling and shining", "Angry" : "count to 10 and cool down"}

Then, access the global object with the varibale to which you got the slot value from the user utterance and add it along with your response. For instance,

var stateSlot = this.event.request.intent.slots.Emotion.value;

var suggestion = emotions[stateSlot];

Use the square bracket to get the property in the emotions object that matches for the value in the variable stateSlot.

Upvotes: 0

Related Questions