4
votes

I'm trying to use a lambda function to send lex to a new intent based on the value of an incoming slot:

Like this

 public override LexResponse Process(LexEvent lexEvent, ILambdaContext context)
    {
        var slots = lexEvent.CurrentIntent.Slots;
        var sessionAttributes = lexEvent.SessionAttributes ?? new Dictionary<string, string>();
        DesiredVehicleYesNo type;
        if (slots.ContainsKey("DesiredVehicleYesNo"))
        {
            Enum.TryParse(slots["DesiredVehicleYesNo"], out type);
        }
        else
        {
            type = DesiredVehicleYesNo.Null;
        }

        switch (type)
        {
            case DesiredVehicleYesNo.YES:
                Dictionary<string, string> s = new Dictionary<string, string>();
                s.Add("DesiredVehicle", null);
                //return ConfirmIntent(sessionAttributes, "DesiredVehicleYes", s, new LexResponse.LexMessage() { Content = "That's great! Let's get started.", ContentType = MESSAGE_CONTENT_TYPE });
                //return ElicitSlot(sessionAttributes,"DesiredVehicleYes",null,"DesiredVehicle", new LexResponse.LexMessage() { Content = "That's great! Let's get started.", ContentType = MESSAGE_CONTENT_TYPE });

            case DesiredVehicleYesNo.NO:
                return ConfirmIntent(sessionAttributes, "DesiredVehicleNo", new Dictionary<string,string>(), new LexResponse.LexMessage() { Content = "Well, that's ok, I can help you choose", ContentType = MESSAGE_CONTENT_TYPE });

        }

I'm just not sure what return type I should be using for this? ConfirmIntent, ElicitSlot, ElicitIntent? Also I do need to be passing slots back, I want the new intent to use it's own prompts to fill the slots related to that intent.

Thanks

2

2 Answers

2
votes

You should use ConfirmIntent and supply the intentName and slots of the intent you want to switch to.

Lex Response Format Docs

ConfirmIntent — Informs Amazon Lex that the user is expected to give a yes or no answer to confirm or deny the current intent.
You must include the intentName and slots fields. The slots field must contain an entry for each of the slots configured for the specified intent. If the value of a slot is unknown, you must set it to null. You must include the message field if the intent's confirmationPrompt field is null. If you specify both the message field and the confirmationPrompt field, the response includes the contents of the confirmationPrompt field. The responseCard field is optional.

So you can supply your own message, but make sure it is written as a Yes/No question. Because ConfirmIntent will expect a Yes/No response from the user.

This approach will always trigger the intent that you supplied in intentName. So you will have to handle the user's response there.
If the user says "yes" then the confirmationStatus will hold the value Confirmed.
If the user says "no" then the confirmationStatus will hold the value Denied.

Make sure that the slots you pass back are correct for that new intent. You can pass them pre-filled to use what the user already gave you; or set to null to allow the new intent to ask the user to fill those slots again.

0
votes

You can use ConfirmIntent as Jay suggested, however if you do not want to prompt anything to user there is a hacky way to achieve this:

  • give access to invoke lambda functions to your calling lambda function i.e lambda function of intent-A
  • get the name of backend lambda function of intent-B
  • call that lambda function with all the inputs using boto3
  • response will be in 'Payload' key of response object
  • get the response using read() method
  • get actual output in ['dialogAction']['message']['content']
  • return using default close() method

Here is sample code for same:

import boto3

client = boto3.client('lambda')
data = {'messageVersion': '1.0', 'invocationSource': 'FulfillmentCodeHook', 'userId': '###', 
        'sessionAttributes': {}, 'requestAttributes': None, 
        'bot': {'name': '###', 'alias': '$LATEST', 'version': '$LATEST'}, 
        'outputDialogMode': 'Text', 
        'currentIntent': {'name': '###', 'slots': {'###': '###'}, 
        'slotDetails': {'###': {'resolutions': [], 'originalValue': '###'}}, 
        'confirmationStatus': 'None'}, 
        'inputTranscript': '###'}
response = client.invoke(
    FunctionName='{intent-B lambda function}',
    InvocationType='RequestResponse',
    Payload=json.dumps(data)
)
output = json.loads(response['Payload'].read())['dialogAction']['message']['content']

Hope it helps.