【问题标题】:Adding session attributes in Python for Alexa skills在 Python 中为 Alexa 技能添加会话属性
【发布时间】:2017-08-16 23:28:12
【问题描述】:

我的意图架构中有 3 个插槽(accountdollar_valuerecipient_first)用于 Alexa 技能,我想保存演讲者在会话属性中提供的所有插槽。

我正在使用以下方法来设置会话属性:

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}

但是,您可能猜到了,如果我想在sessionAttributes 中保存多个插槽作为数据,sessionAttributes 将被覆盖,如下所示:

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)

我的 lambda 函数对提供两个插槽(dollar_valuerecipient_first)的语音输入的 JSON 响应如下(我的猜测是第二个 if 语句中的 the create_dollar_value_attribute 方法覆盖了第一个):

{
  "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"
  }
}

sessionAttributes 的正确响应应该是:

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

如何创建此响应?有没有更好的方法在 JSON 响应中向 sessionAttributes 添加值?

【问题讨论】:

    标签: python json aws-lambda alexa alexa-skill


    【解决方案1】:

    在我看来,用 Python 添加sessionAttributes 的最简单方法似乎是使用字典。例如,如果您想在会话属性中存储一些插槽以供将来使用:

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

    接下来,您可以将其传递给构建响应方法:

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

    本例中的实现:

    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
        }
    

    这会在 Lambda 响应 JSON 中以推荐的方式创建 sessionAttributes。

    此外,如果最后一个不存在,只需添加一个新的 sessionAttribute 并不会覆盖它。它只会创建一个新的键值对。

    请注意,这可能在服务模拟器中运行良好,但在实际 Amazon Echo 上进行测试时可能会返回关键属性错误。根据这个post

    在服务模拟器上,会话以 Session:{ ... Attributes:{}, ... } 开始 当会话在 Echo 上启动时,Session 根本没有 Attributes 键。

    我解决此问题的方法是在创建新会话时在 lambda 处理程序中手动创建它:

     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'])
    

    【讨论】:

    • 我在event['session'] 中没有属性但是我不明白实例化这个event['session']['attributes'] = {} 将如何解决它? alexa/lambda 怎么知道? onSessionStarted 函数有什么作用?
    【解决方案2】:

    首先,您必须定义 session_attributes。

    session_attributes = {}
    

    然后代替使用

    session_attributes = create_recipient_first_attribute(recipient_first)
    

    你应该使用

    session_attributes.update(create_recipient_first_attribute(recipient_first)).

    您面临的问题是因为您正在重新分配 session_attributes。而不是这个,你应该只更新 session_attributes。

    所以你的最终代码会变成:

    session_attributes = {}
    if session.get('attributes', {}) and "recipient_first" not in session.get('attributes', {}):
        recipient_first = intent['slots']['recipient_first']['value']
        session_attributes.update(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.update(create_dollar_value_attribute(dollar_value))
    

    【讨论】:

      【解决方案3】:

      ASK SDK for Python 提供了一个attribute manager,用于管理技能中的请求/会话/持久性级别属性。您可以查看color picker sample,了解如何在技能开发中使用这些属性。

      【讨论】:

        【解决方案4】:

        请看下面:

        account = intent['slots']['account']['value'] 
        dollar_value = intent['slots']['dollar_value']['value'] 
        recipient_first = intent['slots']['recipient_first']['value']  
        
        # put your data in a dictionary
        attributes = { 
            'account':account, 
            'dollar_value':dollar_value, 
            'recipient_first':recipient_first
        }
        

        在您的回复中将 attributes 字典放入 'sessionAttributes' 中。一旦 Alexa 回复您,您应该在 'sessionAttributes' 中取回它。

        希望这会有所帮助。

        【讨论】:

          【解决方案5】:

          下面的代码 sn -p 也会防止覆盖会话属性:

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-03-04
            • 2017-12-18
            • 1970-01-01
            相关资源
            最近更新 更多