How to create a simple Quiz bot using Amazon LEX and AWS lambda (python)

Amazon LEX is a great service to create chatbots. A quiz bot is something that can be more engaging to customers. Nowadays we can find many companies using quizzes in order to educate their customers to understand our product. In this blog, I am going to show how to create a simple blog.

Amazon LEX and Amazon Alexa have many similar features as far as development is concerned. If you want to know more about the difference between these services take a look at this blog.

Create a lambda function

The first step before creating a LEX bot is to create a lambda function. To do so, go to the AWS console and search for “lambda”.

  • Click on create function and name your lambda appropriately as shown below.
  • Once you create the lambda function replace the source code as shown below.
import boto3
import random
import json
import logging
import os
import sys
from datetime import datetime,timedelta,date
import calendar
from dateutil.relativedelta import relativedelta

# get the logger
logger = logging.getLogger()
logger.setLevel(logging.INFO)

intent = None
message = None
response = None
slotName = None
slots = None

questions_with_options = [
    {
        "question" : "which of the following is a programming language?",
        "options" : [
            {
                "text": "python",
                "value": "python"
            },
            {
                "text": "English",
                "value": "english"
            }
        ],
        "answer" : "python"
    },
    {
    "question" : "what is the captical of India?",
    "options" : [
        {
            "text": "Delhi",
            "value": "Delhi"
        },
        {
            "text": "Chennai",
            "value": "Chennai"
        }
    ],
    "answer" : "Delhi"
    }
]

def lambda_handler(event, context):
    logger.info("Event: {0}, Context: {1}".format(event, context))
    
    global intent  
    intent = event['currentIntent']['name']
    
    global slots 
    slots = event['currentIntent']['slots']
    
    if intent == "QuestionIntent":
        response = QuestionIntentHandler(event)
    elif intent == "AnswerIntent":
        response = AnswerIntentHandler(event)
    elif intent == "NextQuestionOrExitIntent":
        response = NextQuestionOrExitIntentHandler(event)
        
    return response

def QuestionIntentHandler(event):
    index = random.randint(0, len(questions_with_options)-1)
    print(index)
    session = {}
    session["answer"] = questions_with_options[index]["answer"]
    output = {
        "dialogAction": {
            "slotToElicit": "answer",
            "intentName": "AnswerIntent",
            "responseCard": {
                "genericAttachments": [
                    {
                        "buttons": questions_with_options[index]["options"],
                        "subTitle": questions_with_options[index]["question"],
                        "title": "Question"
                    }
                ],
                "version": 1,
                "contentType": "application/vnd.amazonaws.card.generic"
            },
            "slots": {
                "answer": None
            },
            "type": "ElicitSlot",
            "message": {
                "content": questions_with_options[index]["question"],
                "contentType": "PlainText"
            }
        },
        "sessionAttributes": session
    }
    return output
    
def AnswerIntentHandler(event):
    input_transcript = event["inputTranscript"]
    session = event["sessionAttributes"]
    if session["answer"] == input_transcript:
        message = f"{input_transcript} is correct answer"
    else:
        message = f"{input_transcript} is wrong answer"
    
    output = {
        "dialogAction": {
            "slotToElicit": "NextQuestionOrExitType",
            "intentName": "NextQuestionOrExitIntent",
            "responseCard": {
                "genericAttachments": [
                    {
                        "buttons": [
                            {
                                "text": "Next Question",
                                "value": "next"
                            },
                            {
                                "text": "Exit",
                                "value": "exit"
                            }
                        ],
                        "subTitle": "Next question or exit?",
                        "title": "Question"
                    }
                ],
                "version": 1,
                "contentType": "application/vnd.amazonaws.card.generic"
            },
            "slots": {
                "NextQuestionOrExitType": None
            },
            "type": "ElicitSlot",
            "message": {
                "content": message,
                "contentType": "PlainText"
            }
        },
        "sessionAttributes": session
    }
    return output
    
    
def NextQuestionOrExitIntentHandler(event):
    input_transcript = event["inputTranscript"]
    session = event["sessionAttributes"]
    slot = event['currentIntent']['slots']["NextQuestionOrExitType"]
    if slot == "exit":
        message = "Thank you"
        return {
            "sessionAttributes": session,
            "dialogAction": {
                "type": "Close",
                "fulfillmentState": "Fulfilled",
                "message": {
                  "contentType": "PlainText",
                  "content": message
                },
            }
        }
    else:
        return QuestionIntentHandler(event)
    
    
  • Replace the question and answers in the “questions_with_options” variable.

Create LEX bot

The next step is to go ahead and create the bot. Go to the AWS console and search for Amazon LEX.

  • Switch over to the V1 console as shown above
  • Copy the following JSON data and store it in a file name “QnALexBot_Export.json”.
{
  "metadata": {
    "schemaVersion": "1.0",
    "importType": "LEX",
    "importFormat": "JSON"
  },
  "resource": {
    "name": "QnALexBot",
    "version": "1",
    "intents": [
      {
        "name": "QuestionIntent",
        "version": "2",
        "fulfillmentActivity": {
          "type": "ReturnIntent"
        },
        "sampleUtterances": [
          "ask me a question",
          "question me",
          "question",
          "hi",
          "hello"
        ],
        "slots": [],
        "followUpPrompt": {
          "prompt": {
            "messages": [
              {
                "groupNumber": 1,
                "contentType": "PlainText",
                "content": "Here is your question"
              }
            ],
            "maxAttempts": 3
          },
          "rejectionStatement": {
            "messages": [
              {
                "groupNumber": 1,
                "contentType": "PlainText",
                "content": "Thank you"
              }
            ]
          }
        }
      },
      {
        "name": "NextQuestionOrExitIntent",
        "version": "1",
        "fulfillmentActivity": {
          "type": "ReturnIntent"
        },
        "sampleUtterances": [
          "{NextQuestionOrExitType}"
        ],
        "slots": [
          {
            "sampleUtterances": [],
            "slotType": "NextQuestionOrExitType",
            "slotTypeVersion": "1",
            "obfuscationSetting": "NONE",
            "slotConstraint": "Optional",
            "valueElicitationPrompt": {
              "messages": [
                {
                  "contentType": "PlainText",
                  "content": "next question or exit"
                }
              ],
              "maxAttempts": 2
            },
            "priority": 1,
            "name": "NextQuestionOrExitType"
          }
        ]
      },
      {
        "name": "AnswerIntent",
        "version": "3",
        "fulfillmentActivity": {
          "type": "ReturnIntent"
        },
        "sampleUtterances": [
          "{answer}"
        ],
        "slots": [
          {
            "sampleUtterances": [],
            "slotType": "answer_type",
            "slotTypeVersion": "1",
            "obfuscationSetting": "NONE",
            "slotConstraint": "Optional",
            "valueElicitationPrompt": {
              "messages": [
                {
                  "contentType": "PlainText",
                  "content": "what is your answer"
                }
              ],
              "maxAttempts": 2
            },
            "priority": 1,
            "name": "answer"
          }
        ]
      }
    ],
    "slotTypes": [
      {
        "name": "answer_type",
        "version": "1",
        "enumerationValues": [
          {
            "value": "answer"
          }
        ],
        "valueSelectionStrategy": "ORIGINAL_VALUE"
      },
      {
        "name": "NextQuestionOrExitType",
        "version": "1",
        "enumerationValues": [
          {
            "value": "next"
          },
          {
            "value": "exit"
          }
        ],
        "valueSelectionStrategy": "ORIGINAL_VALUE"
      }
    ],
    "voiceId": "Matthew",
    "childDirected": false,
    "locale": "en-US",
    "idleSessionTTLInSeconds": 300,
    "clarificationPrompt": {
      "messages": [
        {
          "contentType": "PlainText",
          "content": "Sorry, can you please repeat that?"
        }
      ],
      "maxAttempts": 5
    },
    "abortStatement": {
      "messages": [
        {
          "contentType": "PlainText",
          "content": "Sorry, I could not understand. Goodbye."
        }
      ]
    },
    "detectSentiment": false,
    "nluIntentConfidenceThreshold": 0.4,
    "enableModelImprovements": true
  }
}
  • Next zip the file and import it into LEX as shown below.
  • Once you imported click on the bot name.

Integrate lambda with LEX

This is the final step where we need to attach the lambda which we created above with every intent as shown below.

  • Go Fulfillment section and click on AWS Lambda function
  • Select the lambda which you created and click ok if you are prompted to give permission to that lambda as shown below.
  • By doing the above step you can notice that 3 permission has been added to your lambda under the permissions tab.

  • Save all the intents and click on build.

Let’s test it out

We are done with the setup and it’s time to test it out. click on Test Chatbot as shown below.

  • Start the testing by typing “hi” and continue with the response with LEX.

BOOM!!! You have successfully built your first Quiz bot using Amazon LEX.

Feel free to leave a comment down here. I would love to hear from you. Happy programming!!

Leave a Comment