Как я могу решить 424 (Failed Dependency) (python), полученный от Amazon lex? - PullRequest
0 голосов
/ 07 февраля 2019

Я написал свою лямбда-функцию, и она отлично работает, но когда я пытаюсь связаться с ней из Lex, я получаю исключение зависимости. Как я могу отладить это или решить эту проблему?Переменная REST_END_POINT была определена.Ниже мой код, пожалуйста, просмотрите его и скажите, что я могу делать не так?

Я исследовал проблему на Amazon Lex doc.И упоминается следующее:

DependencyFailedException 1. Одна из зависимостей, такая как AWS Lambda или Amazon Polly, вызвала исключение.Например,

  • Если у Amazon Lex недостаточно прав для вызова функции Lambda.

  • Если функция Lambda занимает больше 30 секундвыполнить.

  • Если лямбда-функция выполнения возвращает диалоговое действие «Делегат» без удаления значений слотов.

Код состояния HTTP: 424

Вот действия, которые я предпринял:

  • Я проверил, что для выполнения моей лямбда-функции не требуется более 30 секунд
  • И у Amazon Lex есть необходимые разрешениячтобы вызвать мою лямбда-функцию

Третий момент, который я не совсем понимаю, но я думаю, что он также решен из кода, который я предоставил, пожалуйста, исправьте меня, если я не прав.

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)

Если все работает, когда задается вопрос «Что такое меню для {Date}», ответ будет таким: «Меню дня включает a list of menu items

»
...