Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Alexa (Amazon Echo) conversation skill - Using Session Attributes (JavaScript - AWS Lambda)

this might be an easy one but I couldn't figure it out in days.

I want to make Alexa have a conversation, like;

>> Alexa, start testSkill.

A: Test Skill started. Tell me a number.

>> One.

A: Okay, tell me a color now.

>> Blue.

A: And finally, tell me an animal name.

>> Chicken.

A: You told me one, blue and chicken.

I found out that I have to handle the Session Attributes of the skill, which is a JSON holds and transfers the information between intents.

I use functions like this ;

    function testConversation(intent, session, callback) {

    var cardTitle = intent.name;
    var repromptText = "";
    var sessionAttributes = { // I don't know how to handle this
        nameOfPairOne: "",
        nameOfPairTwo: "",
    };
    var shouldEndSession = false;
    var speechOutput = "";

    var color= convertToASCII(intent.slots.color.value);
    sessionAttributes.nameOfPairOne = color;

    speechOutput = "You said "+sessionAttributes.nameOfPairOne+". Please say another thing. ";
    callback(sessionAttributes, buildSpeechletResponse(cardTitle, speechOutput, repromptText, shouldEndSession));
}

 function testConversation2(intent, session, callback) {

    var cardTitle = intent.name;
    var repromptText = "";
    var sessionAttributes = session.attributes;
    var shouldEndSession = false;
    var speechOutput = "";

    var number = convertToASCII(intent.slots.number.value);
    sessionAttributes.nameOfPairTwo = number;

    speechOutput = "You first said "+sessionAttributes.nameOfPairOne+", and now said "+sessionAttributes.nameOfPairTwo;
    callback(sessionAttributes, buildSpeechletResponse(cardTitle, speechOutput, repromptText, shouldEndSession));
}

//------Helpers that build all of the responses ---------//
function buildSpeechletResponse(title, output, repromptText, shouldEndSession) {
    return {
        outputSpeech: {type: "PlainText", text: output},
        card: {type: "Simple", title: "SessionSpeechlet - " + title, content: "SessionSpeechlet - " + output},
        reprompt: {outputSpeech: {type: "PlainText", text: repromptText}},
        shouldEndSession: shouldEndSession
    };
}


function buildResponse(sessionAttributes, speechletResponse) {
    return {version: "1.0", sessionAttributes: sessionAttributes, response: speechletResponse};
} 

A piece of code from onIntent() function where I call the above functions. (I know it's wrong but couldn't figure out the right way)

 else if ("getColorNum" == intentName) {
    if (session.attributes.nameOfPairOne === "") {
        testConversation(intent, session, callback);
    } else {
        testConversation2(intent, session, callback);
    }
}

And the Intent Schema JSON is like that;

 "intents": [
{
  "intent": "getColorNum",
  "slots": [
    {
      "name": "Color",
      "type": "ColorSlot"
    },
    {
      "name": "Number",
      "type": "NumberSlot"
    }
  ]
}

] }

So, am I doing all of the things wrong ? Where is the mistake ? And, how can I build a conversation like I mentioned ? Thanks from now.

like image 972
Batuhan GUNDOGDU Avatar asked Jan 03 '17 09:01

Batuhan GUNDOGDU


People also ask

Is Alexa supported by AWS Lambda?

You can use Lambda functions to build services that give new skills to Alexa, the Voice assistant on Amazon Echo. The Alexa Skills Kit provides the APIs, tools, and documentation to create these new skills, powered by your own services running as Lambda functions.

What is session attributes in Alexa?

Session attributes are key-value pairs of data we want to persist for the current session.


2 Answers

Since no one gave you any answer yet I thought I'd give you my two cents. My language of choice is Python but I can give you some high-level ideas.

  • Use a session object to keep track of everything related to the conversation. After you compute the "response", serialize your session object into the session json and deserialize it in the next intent request.
  • Maintain a conversation state and use a finite-state-machine approach to know where you are and what callback to execute given an intent and a specific conversation state.
  • Decouple your conversation logic from the ASK interface as much as you can. Try to write tests you can run locally.

If you want to see how I implemented these, check out:

  • https://www.hackster.io/josep-valls/alexa-message-board-now-with-slack-324b84
  • https://github.com/josepvalls/ask.py
like image 86
Josep Valls Avatar answered Oct 20 '22 09:10

Josep Valls


There are several ways to approach this, depending on the complexity of what you are trying to store.

First, using slots. If One, blue, chicken and such are in classified categories, you can store them in slots and access them the JSON way, getting the value and store in a variable in your JavaScript code. Example (sudo):

var something1 = event.request.intent.slots.assetName.value;
var something2 = event.request.intent.slots.assetName.value;
buildSpeechletResponse(`my ${something1} likes ${something2} and blah blah blah`)

Second, using attributes to store something and use it late on runtime, Alexa won't remember this after skill ended. Example:

'BreakfastIntent': function () {
    var restaurant = randomArrayElement(getRestaurantsByMeal('breakfast'));
    this.attributes['restaurant'] = restaurant.name;

    var say = 'For breakfast, try this, ' + restaurant.name + '. Would you like to hear more?';
    this.response.speak(say).listen(say);
    this.emit(':responseReady');
},

Last, storing them in a database, highly recommended one is DynamoDB and there are plenty of tutorial for storing and access Dynamo from Alexa Skill Kit. Checkout: https://github.com/alexa/alexa-cookbook/tree/master/aws/Amazon-DynamoDB/read

I hope this helps.

like image 33
Huy Le Avatar answered Oct 20 '22 10:10

Huy Le