Skip to content
Advertisement

Adding session attributes in Python for Alexa skills

I have 3 slots (account, dollar_value, recipient_first) within my intent schema for an Alexa skill and I want to save whatever slots are provided by the speaker in the session Attributes.

I am using the following methods to set session attributes:

def create_dollar_value_attribute(dollar_value):
    return {"dollar_value": dollar_value}

def create_account_attribute(account):
    return {"account": account}

def create_recipient_first_attribute(recipient_first):
    return {"recipient_first": recipient_first}

However, as you may guess, if I want to save more than one slot as data in sessionAttributes, the sessionAttributes is overwritten as in the following case:

session_attributes = {}
if session.get('attributes', {}) and "recipient_first" not in session.get('attributes', {}):
        recipient_first = intent['slots']['recipient_first']['value']
        session_attributes = create_recipient_first_attribute(recipient_first)


if session.get('attributes', {}) and "dollar_value" not in session.get('attributes', {}):
        dollar_value = intent['slots']['dollar_value']['value']
        session_attributes = create_dollar_value_attribute(dollar_value)

The JSON response from my lambda function for a speech input in which two slots (dollar_value and recipient_first) were provided is as follows (my guess is that the create_dollar_value_attribute method in the second if statement is overwriting the first):

{
  "version": "1.0",
  "response": {
    "outputSpeech": {
      "type": "PlainText",
      "text": "Some text output"
    },
    "card": {
      "content": "SessionSpeechlet - Some text output",
      "title": "SessionSpeechlet - Send Money",
      "type": "Simple"
    },
    "reprompt": {
      "outputSpeech": {
        "type": "PlainText"
      }
    },
    "shouldEndSession": false
  },
  "sessionAttributes": {
    "dollar_value": "30"
  }
}

The correct response for sessionAttributes should be:

"sessionAttributes": {
    "dollar_value": "30",
    "recipient_first": "Some Name"
  },

How do I create this response? Is there a better way to add values to sessionAttributes in the JSON response?

Advertisement

Answer

The easiest way to add sessionAttributes with Python in my opinion seems to be by using a dictionary. For example, if you want to store some of the slots for future in the session attributes:

session['attributes']['slotKey'] = intent['slots']['slotKey']['value']

Next, you can just pass it on to the build response method:

buildResponse(session['attributes'], buildSpeechletResponse(title, output, reprompt, should_end_session))

The implementation in this case:

def buildSpeechletResponse(title, output, reprompt_text, should_end_session):
return {
    'outputSpeech': {
        'type': 'PlainText',
        'text': output
    },
    'card': {
        'type': 'Simple',
        'title': "SessionSpeechlet - " + title,
        'content': "SessionSpeechlet - " + output
    },
    'reprompt': {
        'outputSpeech': {
            'type': 'PlainText',
            'text': reprompt_text
        }
    },
    'shouldEndSession': should_end_session
    }


def buildResponse(session_attributes, speechlet_response):
    return {
        'version': '1.0',
        'sessionAttributes': session_attributes,
        'response': speechlet_response
    }

This creates the sessionAttributes in the recommended way in the Lambda response JSON.

Also just adding a new sessionAttribute doesn’t overwrite the last one if it doesn’t exist. It will just create a new key-value pair.

Do note, that this may work well in the service simulator but may return a key attribute error when testing on an actual Amazon Echo. According to this post,

On Service Simulator, sessions starts with Session:{ … Attributes:{}, … } When sessions start on the Echo, Session does not have an Attributes key at all.

The way I worked around this was to just manually create it in the lambda handler whenever a new session is created:

 if event['session']['new']:
    event['session']['attributes'] = {}
    onSessionStarted( {'requestId': event['request']['requestId'] }, event['session'])
if event['request']['type'] == 'IntentRequest':
    return onIntent(event['request'], event['session'])
User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement