我该如何解决从Amazon lex获得的424(依赖失败)(python)?

时间:2019-02-07 08:04:25

标签: amazon-web-services aws-lambda amazon-lex

我已经编写了lambda函数,它可以完美运行,但是当我尝试从Lex与之通信时,我得到了依赖异常。我该如何调试或解决此问题?变量REST_END_POINT已定义。下面是我的代码,请仔细查看并告诉我我可能做错了什么?

我在Amazon Lex文档上研究了该问题。并提到了以下内容:

DependencyFailedException 1.其中一个依赖项(例如AWS Lambda或Amazon Polly)引发了异常。例如,

  • 如果Amazon Lex没有足够的权限来调用Lambda函数。

  • 如果Lambda函数执行时间超过30秒。

  • 如果实现Lambda函数返回了Delegate对话框动作而没有删除任何插槽值。

HTTP状态代码:424

这些是我采取的行动:

  • 我已检查过我的lambda函数执行时间不会超过30秒
  • Amazon Lex拥有调用我的lambda函数的正确权限

我不太理解的第三点,但是我认为我提供的代码也解决了它,如果有误,请纠正我。

def elicit_slot(session_attributes, intent_name, slots, slot_to_elicit, message, response_card):
    return {
        'sessionAttributes': session_attributes,
        'dialogAction': {
            'type': 'ElicitSlot',
            'intentName': intent_name,
            'slots': slots,
            'slotToElicit': slot_to_elicit,
            'message': message,
            'responseCard': response_card
        }
    }


def confirm_intent(session_attributes, intent_name, slots, message, response_card):
    return {
        'sessionAttributes': session_attributes,
        'dialogAction': {
            'type': 'ConfirmIntent',
            'intentName': intent_name,
            'slots': slots,
            'message': message,
            'responseCard': response_card
        }
    }


def close(session_attributes, fulfillment_state, message):
    response = {
        'sessionAttributes': session_attributes,
        'dialogAction': {
            'type': 'Close',
            'fulfillmentState': fulfillment_state,
            'message': message
        }
    }

    return response


def delegate(session_attributes, slots):
    return {
        'sessionAttributes': session_attributes,
        'dialogAction': {
            'type': 'Delegate',
            'slots': slots
        }
    }


def build_response_card(title, subtitle, options):
    """
    Build a responseCard with a title, subtitle, and an optional set of options which should be displayed as buttons.
    """
    buttons = None
    if options is not None:
        buttons = []
        for i in range(min(5, len(options))):
            buttons.append(options[i])

    return {
        'contentType': 'application/vnd.amazonaws.card.generic',
        'version': 1,
        'genericAttachments': [{
            'title': title,
            'subTitle': subtitle,
            'buttons': buttons
        }]
    }


""" --- Helper Functions --- """


def parse_int(n):
    try:
        return int(n)
    except ValueError:
        return float('nan')


def try_ex(func):
    """
    Call passed in function in try block. If KeyError is encountered return None.
    This function is intended to be used to safely access dictionary.

    Note that this function would have negative impact on performance.
    """

    try:
        return func()
    except KeyError:
        return None


def isvalid_date(date):
    try:
        dateutil.parser.parse(date)
        return True
    except ValueError:
        return False


def build_validation_result(is_valid, violated_slot, message_content):
    return {
        'isValid': is_valid,
        'violatedSlot': violated_slot,
        'message': {'contentType': 'PlainText', 'content': message_content}
    }


def validate_oms_count(oms_type, date):
    if oms_type:
        if len(oms_type) == 0 or (oms_type != 'transport' and oms_type != 'overtime'):
            return build_validation_result(False, 'OmsType', 'I did not recognize that, can I make an overtime request?')

    if date:
        if not isvalid_date(date):
            return build_validation_result(False, 'Date', 'I did not understand that, what date works best for you?')

    return build_validation_result(True, None, None)


def validate_menu_date(date):
    if date:
        if not isvalid_date(date):
            return build_validation_result(False, 'Date', 'I did not understand that, what date works best for you?')

    return build_validation_result(True, None, None)


def get_token(output_session_attributes):
    token = json.loads(try_ex(lambda: output_session_attributes['token']) or '{}')

    if not token:
        try:
            data = bytes(json.dumps({"username": "admin","password": "Oms2017@","rememberMe": "false"}), 'utf-8')
            f = urllib.request.urlopen(urllib.request.Request(REST_END_POINT+'/authenticate', data, {'Content-Type': 'application/json'}))
            result = json.loads(f.read().decode())
            output_session_attributes['token'] = result['id_token']

            logger.debug('Token {}'.format(result['id_token']))

            return result['id_token']
        except Exception as e:
            logger.debug('An error occurred at the backend1 {}'.format(e)) 
    else:
        return token


def build_options(slot, oms_type):
    """
    Build a list of potential options for a given slot, to be used in responseCard generation.
    """

    if slot == 'OmsType':
        return [
            {'text': 'Transport', 'value': 'transport'},
            {'text': 'Overtime', 'value': 'overtime'}
        ]


""" --- Functions that control the bot's behavior --- """


def get_menu_of_day(intent_request):
    """
    Performs dialog management and fulfillment for getting the menu of the day.

    Beyond fulfillment, the implementation for this intent demonstrates the following:
    1) Use of elicitSlot in slot validation and re-prompting
    2) Use of confirmIntent to support the confirmation of inferred slot values, when confirmation is required
    on the bot model and the inferred slot values fully specify the intent.
    """
    date = intent_request['currentIntent']['slots']['Date']
    source = intent_request['invocationSource']
    output_session_attributes = intent_request['sessionAttributes'] if intent_request['sessionAttributes'] is not None else {}
    data_map = json.loads(try_ex(lambda: output_session_attributes['dataMap']) or '{}')

    if source == 'DialogCodeHook':
        # Perform basic validation on the supplied input slots.
        slots = intent_request['currentIntent']['slots']
        validation_result = validate_menu_date(date)
        if not validation_result['isValid']:
            slots[validation_result['violatedSlot']] = None
            return elicit_slot(
                output_session_attributes,
                intent_request['currentIntent']['name'],
                slots,
                validation_result['violatedSlot'],
                validation_result['message'],
                build_response_card(
                    'Specify {}'.format(validation_result['violatedSlot']),
                    validation_result['message']['content'],
                    build_options(validation_result['violatedSlot'], None)
                )
            )

        if not date:
            slots['Date'] = None
            return elicit_slot(
                output_session_attributes,
                intent_request['currentIntent']['name'],
                intent_request['currentIntent']['slots'],
                'Date',
                {'contentType': 'PlainText', 'content': 'What date works for you?'},
                build_response_card(
                    'Specify Date', 'What date works for you?',
                    build_options('Date', None)
                )
            )

        if date:
            get_token(output_session_attributes)
            data_map['date'] = date
            output_session_attributes['dataMap'] = json.dumps(data_map)

        return delegate(output_session_attributes, slots)

    # Send request to the backend service to perform user action.
    token = get_token(output_session_attributes)
    extractedMenu = []
    try:
        data_map['date'] = date
        output_session_attributes['dataMap'] = json.dumps(data_map)
        params = urllib.parse.urlencode({'day':date})
        response = urllib.request.urlopen(urllib.request.Request(REST_END_POINT+'/menuOfdays?'+ params, headers={'Authorization': 'Bearer '+token}))
        convertedResponse = json.loads(response.read().decode())
        extractedMenu = [item['menu']['name'] for item in convertedResponse]
        logger.debug(extractedMenu)
    except Exception as e:
        logger.debug('An error occurred at the backend2 {}'.format(e))

    return close(
        output_session_attributes,
        'Fulfilled',
        {
            'contentType': 'PlainText',
            'content': 'Menu of the day include: {} '.format(extractedMenu)
        }
    )


""" --- Intents --- """


def dispatch(intent_request):
    """
    Called when the user specifies an intent for this bot.
    """

    logger.debug('dispatch userId={}, intentName={}'.format(intent_request['userId'], intent_request['currentIntent']['name']))

    intent_name = intent_request['currentIntent']['name']

    # Dispatch to your bot's intent handlers

    if intent_name == 'GetMenuOfDay':
        return get_menu_of_day(intent_request)

    raise Exception('Intent with name ' + intent_name + ' not supported')


""" --- Main handler --- """


def lambda_handler(event, context):
    """
    Route the incoming request based on intent.
    The JSON body of the request is provided in the event slot.
    """
    # By default, treat the user request as coming from the America/New_York time zone.
    os.environ['TZ'] = 'America/New_York'
    time.tzset()
    logger.debug('event.bot.name={}'.format(event['bot']['name']))

    return dispatch(event)

如果一切正常,则当询问问题{日期}的菜单是什么时,响应为:每日菜单包括a list of menu items

0 个答案:

没有答案