Build an AI Chatbot using Amazon Lex and Lambda

Aishwary GuptaAishwary Gupta
7 min read

Chatbot's

So, what are chatbots:
They are AI-powered conversational interfaces that can engage in natural language interactions with users. They are transforming how we interact with technology, enabling more intuitive and personalized experiences. I am sure as of now we all have heard of ChatGPT/gamma/Claude AI etc... they all are some kinds of chatbots performing tasks on the commands of the user (prompt), and in this blog, you will learn the basics of building one (at a smaller/no cost level).

Prerequisites

  • An AWS account

  • Some basic understanding of Node.js or Python is required.

  • A working computer with any operating system

  • Any code editor you’re comfortable using (VScode)

Amazon Lex

What is Lex and how can it help us build a chatbot:

  • Conversational AI

Amazon Lex is a service that enables the creation of advanced chatbots and voice-powered applications using deep learning technologies.

  • Flexible Integration

Lex bots can be easily integrated with other AWS services and external systems, allowing for powerful and customized solutions.

  • Natural Language Understanding

Lex provides robust natural language processing capabilities to understand user intents and extract relevant information.

How will Lambda and CloudWatch help you in building the chatbot:

Amazon Lambda

With Lambda, you can run code without provisioning or managing servers. This is perfect for building the backend of a chatbot, as you can write the business logic and integrations as Lambda functions that automatically scale based on usage.

Amazon CloudWatch

It's a monitoring and observability service that collects and tracks various metrics and logs from your AWS resources. For a chatbot, you can use CloudWatch to monitor key performance indicators like the number of user interactions, error rates, response times, and more. This allows you to identify and address any issues with your chatbot quickly.

Guide
Now let's hop onto building a chatbot

How to Build an AWS Lex Chatbot

  • Log on to your AWS account (Console Home)

  • Search for Lex and select to open the Amazon Lex dashboard πŸ‘‡πŸ»

  • use the latest version which is version 2 (if you are on v1 you can click on "Return to the V2 console")

  • Create a new bot

  • Select "Create a blank bot", and give your bot a name

  • Select "Create a role with basic Amazon Lex permissions." in the IAM permissions and "NO" for COPPA

  • Click on next, then you can choose any voice interaction (I am going with Danielle)

    Done.

Setup Intents, Utterances, and Slots

Excellent work! You have successfully created a custom chatbot. From here and onwards I will be using my own custom pizza ordering chatbot, so let's go over the key fundamental components of the Lex service, which are Intents, Utterances and Slots.

Remember you can make as many Intent/ utterances and slots as you want (they define what all your chatbot can perform).

Define Intents

Identify the key conversational intents that your chatbot needs to handle, such as product queries, order placement, or customer support.

Build Utterances

Provide sample user input phrases for each intent, allowing Lex to learn and understand the natural language patterns. Simply they are the words/phases that you will use for starting the conversation.

Configure Slots

Define the parameters or slots your bot needs to collect from users to fulfill their requests.

For my bot, I have made 3 slots "PizzaTypes", "PizzaSizes", PizzaPlaces. These slots consists of all the required questions that a person would have while ordering a pizza.

Amazon Lex includes a variety of built-in slot types, including numbers, dates, countries, and many more. We can also define what sets of values are acceptable by creating our custom slot types.

So now let us move on to using the lambda function.

Integrating Amazon Lex with AWS Lambda

We need a way to prompt the user for proper data and for running the code without the hassle of manually managing servers or clusters; that is where lambda comes in.

Serverless Functions

AWS Lambda allows you to run your chatbot's backend logic as serverless functions, eliminating the need for infrastructure management.

Before we make the lambda function make sure to select this option in your intent

and go to Fulfillment -> Advanced option and select this option also

Custom Logic

You can write custom code in your Lambda functions to fetch data, execute business logic, and provide a tailored conversational experience.

Making the lambda function

Go on to lambda -> Functions and create a new function, name it whatever you like. I have named my lambda: OrderPizzaBot

make sure to select python instead of nodejs

Then go back to you lex and you will find the Aliases option under development

you will see TestBotAlias click on it and then click on English (US) then select your source which means the lambda function that you just created

Now let's write some lambda_function (don't worry, I have written it for you, but you need to make some changes based on you chatbot slots)

Just copy the below code πŸ‘‡πŸ» onto your lambda function ☝🏻

import json

def validate(slots):

    if not slots['Pizza_Type']:
        print("Inside Empty Pizza_Type")
        return {
        'isValid': False,
        'violatedSlot': 'Pizza_Type'
        }        


    if not slots['Pizza_Place']:

        return {
        'isValid': False,
        'violatedSlot': 'Pizza_Place',
    }

    if not slots['Pizza_Size']:
        return {
        'isValid': False,
        'violatedSlot': 'Pizza_Size'
    }

    return {'isValid': True}

def lambda_handler(event, context):
    slots = event['sessionState']['intent']['slots']
    intent = event['sessionState']['intent']['name']
    print(event['invocationSource'])
    print(slots)
    print(intent)

    validation_result = validate(slots)
    print(validation_result)

    if event['invocationSource'] == 'DialogCodeHook':

        if not validation_result['isValid']:

            response = {
                "sessionState": {
                    "dialogAction": {
                        'slotToElicit': validation_result['violatedSlot'],
                        "type": "ElicitSlot"
                    },
                    "intent": {
                        'name':intent,
                        'slots': slots

                        }
                }
               } 

        else:
            response = {
            "sessionState": {
                "dialogAction": {
                    "type": "Delegate"
                },
                "intent": {
                    'name':intent,
                    'slots': slots

                    }

            }
        }

    if event['invocationSource'] == 'FulfillmentCodeHook':


        response = {
        "sessionState": {
            "dialogAction": {
                "type": "Close"
            },
            "intent": {
                'name':intent,
                'slots': slots,
                'state':'Fulfilled'

                }

        },
        "messages": [
            {
                "contentType": "PlainText",
                "content": "Thanks, I have placed your order"
            }
        ]
    }

    return response

Let me walk you through the code

  • Make sure to change the slots that you have made and add the if not conditions if you have more than 3 slots

Defines two functions: validate and lambda_handler. The code validates user input, manages dialog flow, and ultimately confirms the order.

Breakdown

validate function

  • Purpose: Validate the pizza order slots (type, place, and size).

  • Logic:

    • Check if each required slot (Pizza_Type, Pizza_Place, Pizza_Size) is present.

    • Returns a dictionary indicating whether the validation is successful and, if not, the violated slot.

lambda_handler function

  • Purpose: The main entry point for the Lambda function. Handles different invocation sources and processes the pizza order intent.

  • Logic:

    • Extracts slots and intent information from the event.

    • Calls the validate function to check for missing slots.

    • Handles different invocation sources:

      • DialogCodeHook: If the function is called during the dialog phase, it either elicits the missing slot or delegates to the next intent if all slots are valid.

      • FulfillmentCodeHook: If the function is called after all slots are filled, it confirms the order and closes the dialog.

Key Points

  • Intent-Based Dialog: The code uses an intent-based approach to manage the conversation.

  • Slot Validation: The validate function ensures that all required slots are filled.

  • Dialog Management: The lambda_handler function handles different stages of the dialog, either asking for missing information or confirming the order.

  • Invocation Source: The code differentiates between DialogCodeHook and FulfillmentCodeHook to determine the appropriate response.

  • Response Formatting: The response dictionary is formatted according to the Alexa Skills Kit (ASK) or similar dialog system requirements.

We are all done with the lambda function now let's test the bot. (Go back to lex)

Pizza Ordering Chatbot

All done.

You can go onto CloudWatch from your lambda function to check the logs (how your chatbot works in the background)

Find Monitor in the navigation bar and click on View CloudWatch logs

You can see all your logs in Log Stream.

Good job! Our bot is now working properly

If you liked this blog, you could read more tech-related blogs here

1
Subscribe to my newsletter

Read articles from Aishwary Gupta directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Aishwary Gupta
Aishwary Gupta