How to develop a Serverless Chatbot with AWS Amplify, Amazon Lex & React

How to develop a Serverless Chatbot with AWS Amplify, Amazon Lex & React

Create your chatbot, step-by-step. Code & Architecture inclusive.

This blog post gives you an introduction and step-by-step guide on how to create a chatbot application with AWS Amplify & AWS Lex. The great part about using this tech-stack is, that no Data Science or NLP knowledge is required because it is purely created with managed services by AWS. The same technology is used within Alexa so it is a bulletproof stack.

In this post, we will create a chatbot for booking a car. You can find the code here.

Let's go!

The Architecture

Let's start with the architecture.

image.png

The architecture contains four different components:

Web Interface - Chatbot Component

The web interface is a Single Page Application (SPA), built with React & TypeScript. This gives us the opportunity to host the application in a cheap way and serve it very fast to users all over the world. We can also use already existing libraries (such as the chatbot implementation from Amplify) and we don't have to reinvent the wheel.

AWS Amplify

In this application, Amplify is used for two different use cases.

  1. Amplify-CLI for bootstrapping the cloud environment and building the infrastructure as code
  2. Amplify JS libraries for accessing AWS components and building the chatbot interface.

The web application is hosted via Amplify which uses S3 and CloudFront in the background. The chatbot and lambda function is created with Amplify.

Amazon Lex

Amazon Lex is the chatbot interaction service by AWS. It is the same service that uses Amazon Alexa and is built to serve many customers.

AWS Lambda

Lambda is the serverless function service by AWS. For this use case it is optional. But normally it will be used to extend the functionality of chatbots by adding more business logic to them. For example for really booking an Uber.

You can see the architecture is really simple and just consist of 4 different parts.

Let's Code!

Now let's create the actual chatbot application. If you don't have already, please install the Amplify CLI, see this guide.

Prerequisites for this project are:

  • Amplify-CLI
  • yarn or npm
  • npx
  • AWS Account

Project Setup

React App

First of all, let's start with the initial project setup and folder structure. Go into the folder where your project should reside and type in the console:

npx create-react-app chatbot-with-amplify --template typescript

This bootstraps the initial folder structure with TypeScript as the main language.

Amplify App

Now, we will do the same thing for Amplify. Just run amplify init within your newly created project folder and follow the CLI commands.

cd chatbot-with-amplify
amplify init

CLI Workflow: You can use the default values almost everywhere.

? Enter a name for the project chatbotwithamplify
The following configuration will be applied:

Project information
| Name: chatbotwithamplify
| Environment: dev
| Default editor: Visual Studio Code
| App type: javascript
| Javascript framework: react
| Source Directory Path: src
| Distribution Directory Path: build
| Build Command: npm run-script build
| Start Command: npm run-script start

? Initialize the project with the above configuration? (Y/n) Y

Using default provider  awscloudformation
? Select the authentication method you want to use: (Use arrow keys)
❯ AWS profile
  AWS access keys

Here, you must choose your authentication method (either profile or access keys) and hit enter. I always suggest using AWS Profiles for your different accounts. Here is a short explanation of how to create them. After choosing it your Amplify project was created within the directory amplify.

Sample Chatbot

Now we will build the actual chatbot component. Amplify has its own category for chatbot called interactions. We start by using a pre-defined chatbot template for booking different trips.

First, we start by adding an interaction component.

amplify add interactions

We have to configure a bunch of different stuff, just follow along the output here.

? Provide a friendly resource name that will be used to label this category in the project: (lex282f4c21) lex282f4c21
? Would you like to start with a sample chatbot or start from scratch? (Use arrow keys)
❯ Start with a sample
  Start from scratch
? Choose a sample chatbot: (Use arrow keys)
❯ BookTrip
  OrderFlowers
  ScheduleAppointment
? Please indicate if your use of this bot is subject to the Children's Online Privacy Protection Act (COPPA). No
Successfully added resource

We will start with the sample chatbot BookTrip. After adding this resource we will push it to AWS. The push command shows us a quick overview of all components to add.

amplify push

Output:

✔ Successfully pulled backend environment dev from the cloud.

    Current Environment: dev

┌──────────────┬─────────────────┬───────────┬───────────────────┐
│ Category     │ Resource name   │ Operation │ Provider plugin   │
├──────────────┼─────────────────┼───────────┼───────────────────┤
│ Auth         │ cognito8550b67d │ Create    │ awscloudformation │
├──────────────┼─────────────────┼───────────┼───────────────────┤
│ Interactions │ lex282f4c21     │ Create    │ awscloudformation │
└──────────────┴─────────────────┴───────────┴───────────────────┘
? Are you sure you want to continue? (Y/n) Y

In the overview we see that Amplify added one new Interaction component lex282f4c21 and one Auth component which acts as the authentication method for the bot. After hitting enter the CloudFormation templates will be executed and deployed on your AWS account.

You can now open the service Lex and see your newly created chatbot named: BookTrip_dev.

image.png

This is how the chatbot overview looks like. We will go through the different parts you can see here:

Intents

On the far left side you can see the different intends. We have two:

  1. BookCar_dev
  2. BookHotel_dev

One chatbot can have different intents it can serve. We will just look at BookCar_dev.

Sample Utterances

Utterances are sentences or words on how to trigger a specific intent. In the case of the BookCar chatbot these utterances are:

  • Book a car
  • Reserver a car
  • Make a car reservation

Slots

Slots are data points that have to be collected by the user. In the example of booking a car, we need different information like the time, date and type of the car. The slot has different attributes like:

  • Priority: The order of the slot
  • Required: Do we need this slot or not?
  • Slot type: What type is the slot. There are pre-defined types like AMAZON.DATE or AMAZON.TIME which can parse text into date or time. And there are self-defined types like for example the type CarTypeValues. These were defined in the template and can be seen on the left side under SlotTypes.
  • Prompt: What is the question to show the user for receiving the slot as an answer?

Confirmation Prompt

This is the final confirmation of the chatbot conversation. In this example, it is a summary of the whole car reservation.

Testing the chatbot

You can test your chatbot by clicking on TestChatbot on the right side of the window. A chatbot window pops up.

image.png

This is really helpful because while you enter your messages and receive responses you see the filled Slots. The great thing about the pre-defined slot types is that AWS parses for example dates that are hidden in text into proper date formats. If I answer the question What day do you want to start your rental?, with Tomorrow it parses it to the correct date.

Chatbot information in Amplify

All this was created by the sample defined in Amplify. Since we are using Amplify as Infrastructure as Code (IaC), this can be defined as code. If you take a look at your project in the file amplify/backend/interactions/lex282f4c21/lex-params.json you will see all parameters in one JSON file.

{
    "resourceName": "lex282f4c21",
    "intents": [
        {
            "cancelMessage": "Okay, I have cancelled your reservation in progress.",
            "confirmationQuestion": "Okay, I have you down for a {CarType} rental in {PickUpCity} from {PickUpDate} to {ReturnDate}. Should I book the reservation?",
            "slots": [
                {
                    "name": "PickUpCity",
                    "type": "AMAZON.US_CITY",
                    "prompt": "In what city do you need to rent a car?",
                    "required": true,
                    "customType": false
                },
              ...
            ],
            "utterances": [
                "Make a car reservation",
                "Reserve a car",
                "Book a car"
            ],
            "intentName": "BookCar",
            "newSlotTypes": [
                {
                    "slotType": "CarTypeValues",
                    "slotTypeDescription": "Enumeration representing possible types of cars available for rental",
                    "slotValues": [
                        "standard",
                        "full size",
                       ...
                    ]
                }
            ]
        }
    ],
    "outputVoice": "Matthew",
    "botName": "BookTrip",
    "coppa": false
}

With these parameters, your can adjust and customize your chatbot in any way you want 😉

Interaction Component

The next step is to have a Chatbot component in our own web application. For that, we open the react project in our favorite IDE (probably VSCode) and add a new folder components and chatbot and install @aws-amplify/ui-react for using the pre-defined UI libraries. After that, we just start the development server.

cd chatbot-with-amplify
code .
mkdir src/components
mkdir src/components/Chatbot
touch src/components/Chatbot/Chatbot.tsx
yarn add aws-amplify @aws-amplify/ui-react 
yarn start

In the Chatbot.tsx file we return the AmplifyChatbot component and connect it to our chatbot. The whole file can be seen here. .

<AmplifyChatbot
    botName="BookTrip_dev"
    botTitle="This is a chatbot made with Amplify"
    welcomeMessage="Hi! I was made with Amplify. How can I help you?"
/>

This renders the whole component of the chatbot and we can already speak to it like in the Lex interface. Just go to your src/App.tsx and add the Chatbot and you should be able to see it. See App.tsx here :

App.tsx

function App() {
  return <Chatbot />;
}

If you open your browser and head to http://localhost:3000/ you can see your chatbot app and interact with it.

image.png

After finishing your conversation you can check the console in the browser and find the filled slots:

{
  "slots": {
    "CarType": "luxuery",
    "DriverAge": "21",
    "PickUpCity": "Munich",
    "PickUpDate": "2021-09-01",
    "ReturnDate": "2021-09-02"
  }
}

Finished 🥳

That's it! That is the whole workflow for building a chatbot. In this use case, we've used the easy approach of building a sample chatbot. The workflow is almost the same for building one from scratch. In one of the next posts, I will show you how to do exactly that.

If you want to know more about AWS, serverless, and bootstrapping your product on AWS follow my Twitter.

Did you find this article valuable?

Support Sandro Volpicella by becoming a sponsor. Any amount is appreciated!