Having an issue with Lambda response that LexBot expect.

0

I have a lambda which query dynamo Db table for an available times once the the date is entered by the user and then the lambda will add those available time to the session attribute and will elicit to next slot. but once the user entered the date then the lex gives me an error message which I believe is about the response from the lambda. here is the lex error message

Invalid Lambda Response: Received invalid response from Lambda: Cannot construct instance of `java.util.LinkedHashMap` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('slots') at [Source: (String)"{"sessionState":{"sessionAttributes":{"availableTimes":"2:30 PM, 8:00 AM"},"intent":{"name":"Date","slots":"slots"}},"dialogAction":{"type":"ElicitSlot","fulfillmentState":"Fulfilled","slotToElicit":"Time","message":{"contentType":"PlainText","content":"What time would you like to schedule your appointment?"}}}"; line: 1, column: 108]

here is the lambda code

import { DynamoDBClient, QueryCommand } from "@aws-sdk/client-dynamodb";
import { unmarshall } from "@aws-sdk/util-dynamodb";

const REGION = "us-east-1";
const dynamodbClient = new DynamoDBClient({ region: REGION });

export const handler = async (event) => {
    console.log("EVENT: ", JSON.stringify(event, null, 2));

    try {
        const sessionState = event.sessionState || {};
        const intent = sessionState.intent || {};
        const slots = intent.slots || {};
        const dateSlot = slots.Dates || {};
        const appointmentDate = dateSlot.value ? dateSlot.value.interpretedValue : null;
        const params = {
            TableName: "Schedule",
            KeyConditionExpression: "availableDates = :date",
            ExpressionAttributeValues: {
                ":date": { S: appointmentDate }
            }
        };
        const command = new QueryCommand(params);
        const response = await dynamodbClient.send(command);

        const items = response.Items.map((item) => unmarshall(item));
        console.log('Data from Schedule: ', items);

        let availableTimesSet = new Set();
        items.forEach(item => {
            if (item.availableTimes) {
                availableTimesSet.add(item.availableTimes);
            }
        });
        const availableTimesArray = Array.from(availableTimesSet);
        const availableTimes = availableTimesArray.join(', ');

        sessionState.sessionAttributes = sessionState.sessionAttributes || {};
        sessionState.sessionAttributes.availableTimes = availableTimes;
        return {
            sessionState: {
                sessionAttributes: sessionState.sessionAttributes || {},
                intent: {
                    name: "Date"
                }
            },
            dialogAction: {
                type: "ElicitSlot",
                fulfillmentState: "Fulfilled",
                slotToElicit: "Time",
                message: {
                    contentType: "PlainText",
                    content: "What time would you like to schedule your appointment?"
                }
            }
        };
    }
    catch (error) {
        console.error('Error querying DynamoDB', error);
        return {
            sessionAttributes: event.sessionState ? event.sessionState.sessionAttributes : {},
            dialogAction: {
                type: "Close",
                fulfillmentState: "Failed",
                message: {
                    contentType: "PlainText",
                    content: `There was an error retrieving available times. Please try again later.`
                }
            }
        };
    }
};

I need help with processing the lambda response according to the lex requirement PS: I have read too many documents

2 Answers
0
Accepted Answer

Guys, I solved the issue, the problem was with my lambda code, once I fixed that, it worked fine. here is the corrected Lambda Code:

import { DynamoDBClient, QueryCommand } from "@aws-sdk/client-dynamodb";
import { unmarshall } from "@aws-sdk/util-dynamodb";

const REGION = "us-east-1";
const dynamodbClient = new DynamoDBClient({ region: REGION });

export const handler = async (event) => {
    console.log("EVENT: ", JSON.stringify(event, null, 2));

    try {
        const sessionState = event.sessionState || {};
        const intent = sessionState.intent || {};
        const slots = intent.slots || {};
        const dateSlot = slots.Dates || {};

       let appointmentDate = event.interpretations[0].intent.slots.NewAppointmentDate.value.interpretedValue;

        console.log("AppointmentDate: ", appointmentDate);
        const params = {
            TableName: "ACME_Healthcare_Demo_Schedule",
            KeyConditionExpression: "availableDates = :date",
            ExpressionAttributeValues: {
                ":date": { S: appointmentDate }
            }
        };

        const command = new QueryCommand(params);
        const response = await dynamodbClient.send(command);

        const items = response.Items.map((item) => unmarshall(item));
        console.log('Data from ACME_Healthcare_Demo_Schedule: ', items);

        // Extract unique available times for the given date
        let availableTimesSet = new Set();
        items.forEach(item => {
            if (item.availableTimes) {
                availableTimesSet.add(item.availableTimes);
            }
        });

        // Convert Set to a comma-separated string
        const availableTimesArray = Array.from(availableTimesSet);
        const availableTimes = availableTimesArray.join(', ');

        // Set available times as session attribute
        sessionState.sessionAttributes = sessionState.sessionAttributes || {};
        sessionState.sessionAttributes.availableTimes = availableTimes;

        console.log("Availeble time: ", availableTimes);
        return {
            sessionState: {
                sessionAttributes: sessionState.sessionAttributes || {},
                dialogAction: {
                    type: "ElicitSlot",
                    slotToElicit: "appointmentTime"
                },
                intent: {
                    name: intent.name,
                    slots: slots
                }
            }
        };

    }
    catch (error) {
        console.error('Error querying DynamoDB', error);
        return {
            sessionAttributes: event.sessionState ? event.sessionState.sessionAttributes : {},
            dialogAction: {
                type: "Close",
                fulfillmentState: "Failed",
                message: {
                    contentType: "PlainText",
                    content: `There was an error retrieving available times. Please try again later.`
                }
            }
        };
    }
};

After updating the code, I worked. thanks All,

answered 2 months ago
0

Hello,

Greetings! Hope you are doing good!

I understand that you are getting the below error from lambda while using Lex: Invalid Lambda Response: Received invalid response from Lambda: Cannot construct instance of java.util.LinkedHashMap (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('slots').

You also have a lambda function which query DynamoDb table for available time and as the user enters the date Lambda function will add that available time to the session attribute.

I would like to inform you that in order to fetch more information regarding this issue and dive deep further I would suggest you to please raise a case with the AWS premium support and provide the following information on the case:

  1. Please share your bot .zip export so that we can replicate this issue on our end. please follow the link below to know more about exporting your bot [ https://docs.aws.amazon.com/lex/latest/dg/export-to-lex.html#export-console ]
  2. Region where your resources are present.
AWS
answered 2 months ago

Relevant content