0

I Have a lex workflow with multiple bots chained together with fallback intents . Reason is to separate content by type into their individual bots. All my other bots returns just and fulfil except for my primary bot which has intents to do some custom questioner .

Currently i am trying to chain a new bot which has intent that has custom questioner when i try to elicit slot from the fallback lambda for a different bot it throws An error has occurred: The server encountered an error processing the Lambda response on the lex, i am sending the proper format.

Following this example https://aws-ml-blog.s3.amazonaws.com/artifacts/lex-fallback-intent/lambda_function.py but modified it for chaining different bots.

To Summarize: what i am trying to achieve, I have Bot_A which is my primary bot which has different types of questioner(s) my other bots BOT_B and BOT_C have just lex fulfilments (on sentence answers and close the session) now i am trying to create a separate intent which can be any bots (i am okay to create a new bot for this if needed) its roles is when a user input is not found in these 3 Bots it should be triggered it's again a lambda questioner in which there will be a different conversation.

My python fallback lambda code (a re-construct of above shared link) .

import logging
import boto3

logger = logging.getLogger()
logger.setLevel(logging.DEBUG)

lex_runtime = boto3.client('lex-runtime')

# --- Helpers that build all of the responses to Lex ---

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

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

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
        }
    }
    
# --- Helper Functions ---

def get_session_attributes(intent_request):
    print(intent_request)
    """
    Get session attributes from intent request
    """
    return intent_request['sessionAttributes'] if 'sessionAttributes' in intent_request and intent_request['sessionAttributes'] is not None else {}
    
def get_user_id(intent_request):
    """
    Get user id from intent request
    """
    return intent_request.get('userId')
    
def get_input_transcript(intent_request):
    """
    Get input transcript from intent request
    """
    return intent_request['inputTranscript']
    
# --- Intent handler ---


def handle_other_chatbot(intent_request, bot_name, bot_alias):
    
    userId = get_user_id(intent_request)
    session_attributes = get_session_attributes(intent_request)
    input_text = get_input_transcript(intent_request)
    
    
    response = lex_runtime.post_text(
        botName = bot_name,
        botAlias = bot_alias,
        userId = userId,
        sessionAttributes = session_attributes,
        inputText = input_text
    )
    
    session_attributes = response['sessionAttributes']
    message = {
        "contentType": response['messageFormat'],
        "content": response['message']
    }
    
    return close(session_attributes, response['dialogState'], message)

# --- Intents ---

def dispatch(intent_request):
    """
    Called when the user specifies an intent for this bot.
    """
    logger.debug('dispatch userId={}, botName={}'.format(intent_request.get('userId', ""), intent_request['bot']['name']))
    
    if intent_request['bot']['name'] == "BOT_A":
        return handle_other_chatbot(intent_request, "BOT_B", "AliasA")
    elif intent_request['bot']['name'] == "BOT_B":
        return handle_other_chatbot(intent_request, "BOT_C", "AliasA")
    else:
        return close(get_session_attributes(intent_request), 
            'Fulfilled', { 
                'contentType': 'PlainText', 
                'content': "No action found, please retry"
            })
  


def lambda_handler(event, context):
    print("EVENT: ",event)
    """
    Route the incoming request based on intent.
    The JSON body of the request is provided in the event slot.
    """
    logger.debug('event.bot.name={}'.format(event['bot']['name']))

    return dispatch(event)

Thanks in advance.

charithreddyv
  • 135
  • 4
  • 12

1 Answers1

0

Personally I would dispatch to different intents instead of bots, and then you can finish your fulfillment/closing of session within those intents instead.

To answer the question:

now i am trying to create a separate intent which can be any bots (i am okay to create a new bot for this if needed) its roles is when a user input is not found in these 3 Bots it should be triggered

You could try passing a session attribute to each bot, such as "triggeredAllBots" and find some condition to set it to True once it has reached all of the prior 3 bots and so you could trigger the dispatch to that 4th intent based on the value of that session attribute.

Hope that helps.