AWS Machine Learning Blog

Smarter FAQ bots with Amazon Kendra

We often have questions when making a choice about a product or service. When was the last time you found yourself at the IT help desk at work? You probably had questions like “What time does the IT Help Desk open?” or “Can I get a temporary machine while you repair my laptop?”  Quick and accurate responses to such queries improve customer satisfaction. Support staff can easily answer these questions, but it may not be the best use of their time. Such repetitive work is well suited for automation. Customers get a response right away, and the support staff can focus on solving problems.

To enable such a conversation with a bot, you could model each question as a separate intent. Sample utterances are designed to capture the user’s questions in natural language form, and the bot responds to provide the answers. This works well for a few questions. But as the number of questions grows, so does the number of intents, which leads to an ever-changing bot definition. This can be a bit inefficient if most of the responses are just static text. An alternate approach is to ingest the list of questions into a database, and query the database to answer each question. This is similar to what the QnABot bot does. With this design, you don’t have to add an intent for every question. However, if the natural language input varies from the database entry, the search has to be smart enough to accommodate linguistic variations. For example, it should provide the same answer for “How long does it take to fix a screen” and “What’s the turnaround time to fix a screen?”

With the recent launch of Amazon Kendra, you can now use natural language questions to get the answers you’re looking for, whether that is an FAQ, an answer in a document, or as a link to an entire document. Amazon Kendra can extract specific answers from unstructured data. You simply point Amazon Kendra at your content, and Amazon Kendra indexes the content to provide the answers. You can use the Amazon Kendra console or APIs to index your FAQs and documents to create a search index. Amazon Kendra uses the index to find the closest match to a search query, and returns the corresponding answer.

This post shows how you can integrate an Amazon Lex chatbot with Amazon Kendra, so that end users can query Amazon Kendra from messaging platforms such as Slack.  The diagram below illustrates the idea:

Building an Amazon Lex chatbot

This post uses the following conversation to model a bot.

User: Where’s the IT Help Desk?

Agent: 2nd floor; room 221 (two rights after you get out of the elevators)

User: When does the Help Desk open?

Agent: 11am – 2pm.

User: Can I come in at noon?

Agent: Sure. What’s the nature of your problem?

User: I have a cracked laptop screen.

Agent: For verification purposes, can I get the last four digits of your employee ID?

User: 1234

Agent: Got it, we’ll see you then to take a look at your screen.

User: How long does it take to fix a screen?

Agent: Laptop screen repairs typically take 4 hours.

User: What do I need to bring with me for a screen repair?

Agent: For a laptop screen repair, please bring your employee badge, laptop, and VPN fob.

User: How do I access my documents while my laptop is being repaired?

Agent: You can use Amazon Workdocs to access your documents.

User: Can I access Amazon WorkDocs from my tablet?

Agent:  Here is an excerpt from a document that might help: (displays relevant text from the document)

User: How do I use WorkDocs again?

Agent: Here are some documents I found… (displays list of relevant support documents)

User: Is there a coffee shop nearby?

Agent: There is on the 3rd floor and it’s open from 8 AM to 4 PM daily.

The first step is to build an Amazon Lex bot with intents to book an appointment and check appointment status. The MakeAppointment intent elicits the information required to make an appointment, such as the date, time, employee ID, and the nature of the issue. The CheckAppointmentStatus intent provides status of the appointment.  When a user asks a question that the Lex bot can’t answer with these intents, you will use the built-in Fallback intent to connect to Amazon Kendra to search for an appropriate answer.

Deploying the sample Amazon Lex bot

To create the sample bot, perform the following steps.  This creates an Amazon Lex bot called help_desk_bot, and an AWS Lambda function called help_desk_bot_handler.

  1. Download the Amazon Lex code here, and the Lambda code here.
  2. In the AWS Lambda console, choose Create function.
  3. Enter the function name help_desk_bot_handler.
  4. Choose the latest Python runtime (for example, Python 3.8).
  5. For Permissions, choose Create a new role with basic Lambda permissions. We will update this role later to allow your Lambda function to access Amazon Kendra.
  6. Choose Create function.
  7. Once your new Lambda function is available, in the Function code section, choose Upload a .zip file, and for the Function package, select the help_desk_bot_lambda_handler.zip file that you downloaded.
  8. Choose Save.
  9. In the Amazon Lex console, choose Actions, Import.
  10. Choose the file help_desk_bot.zip that you downloaded, and choose Import.
  11. Choose the Lex bot help_desk_bot in the Amazon Lex console.
  12. For each of the intents, including the fallback intent [help_desk_fallback], choose AWS Lambda function in the Fulfillment section, and select the help_desk_bot_handler function in the dropdown list.
  13. For each intent, you will be prompted to Add permission to Lambda function. Choose OK.
  14. Once all of the intents have been updated, choose Build.

At this point, you should have a working Amazon Lex bot that is not yet connected to Amazon Kendra.

Creating an Amazon Kendra index

You are now ready to create a Kendra index for your documents and your FAQ. To create a Kendra index, complete the following steps:

  1. On the Amazon Kendra console, choose Launch Amazon Kendra.
  2. If you have existing Kendra indexes, choose Create index.
  3. Enter an Index name, such as “it-helpdesk,” and an optional Description, such as “IT Help Desk documents and FAQs”.
  4. For IAM role, choose “Create a new role” to create a role to allow Amazon Kendra to access CloudWatch Logs.
  5. For Role name, enter a name, such as “cloudwatch-logs”.
  6. Choose Create.

While Amazon Kendra creates your new index, upload your content to an S3 bucket.

  1. On the Amazon S3 console, create a new bucket, such as “kendra-it-helpdesk-docs-<account#>”
  2. Keep the default settings and choose Create bucket.
  3. Download the following sample files, and upload them to your S3 bucket:

Once your new Kendra index has been created, you can add your content.

  1. On the Amazon Kendra console, choose FAQs, and Add FAQ.
  2. For FAQ name, enter a name, such as “it-helpdesk-faq”
  3. For Description, enter an optional description, such as “FAQ for the IT Help Desk Lex bot”
  4. For S3, browse S3 to find your bucket, and select the “help-desk-faq.csv” file.
  5. For IAM role, choose “Create a new role” to allow Amazon Kendra to access your S3 bucket.
  6. For Role name, enter a name such as “s3-access” and choose Add.
  7. Stay on the page while Amazon Kendra creates your FAQ.
  8. On the Amazon Kendra console, choose Data sources, and under the S3 option, Add connector.
  9. For Data source name, enter a name, such as “it-helpdesk-documents”.
  10. For Description, enter a value, such as “IT Help Desk documents to be indexed by Kendra”.
  11. Choose Next.
  12. For Enter the data source location, choose Browse S3, and select your S3 bucket.
  13. For IAM role, choose “Create a new role” to allow Amazon Kendra to access your S3 bucket.
  14. For Role name, enter a name, such as “access-data-source”.
  15. For Set sync run schedule, select an option such as “Run on demand”.
  16. Choose Next, and then choose Create.
  17. Stay on the page while Kendra creates your data source.
  18. Once your data source has been created, you need to synchronize it. Choose Sync now.  You can run this on demand whenever you add new documents, or on a specific schedule.

Once your data source is synchronized, you can try some searches on the Kendra Search console.  For example:

  • When is the help desk open?
  • When does the help desk close?
  • Where is the help desk?
  • Can I access WorkDocs from my phone?

Now that you have a working Kendra index, you need to update the Amazon Lex bot code with the Kendra index ID.

  1. On the Amazon Kendra console, navigate to your new index.
  2. Copy the Index ID
  3. On the AWS Lambda console, choose the help_desk_bot_handler function.
  4. In Environment variables, choose Edit, and Add environment variable.
  5. For Key, enter “KENDRA_INDEX”.
  6. For Value, paste the Kendra Index ID that you copied.
  7. Choose Save.

The last step is to allow your Lambda function to query Amazon Kendra.

  1. On the AWS Lambda console for your help_desk_bot_handler function, choose the Permissions tab.
  2. Choose the IAM role listed under Role name.
  3. Choose Add inline policy.
  4. Under Service, choose “Kendra”.
  5. Under Read, choose “Query”.
  6. Under Resources, choose Add ARN.
  7. For Region, choose Any.
  8. For Index Id, paste in your Kendra index Id.
  9. Choose Add.
  10. Choose Review policy.
  11. Enter a Name, such as “queryKendra”.
  12. Choose Create policy.

Now your Amazon Lex bot is able to execute Amazon Kendra queries.  You can test this on the Amazon Lex console.

Deploying on a Slack channel

The final step is to connect your bot to a Slack channel.

To create a Slack channel association with your bot, complete the following steps:

  1. On the Amazon Lex console, choose Settings. You will need to publish a version of your bot to integrate it with Slack.
  2. Choose Publish, and in the Create an alias field, enter an alias name such as “test”. Choose Publish.
  3. Once your alias is published, choose the Channels
  4. Under Channels, choose Slack.
  5. Enter a Channel Name, such as “slack_HelpDeskBot”.
  6. Choose “aws/lex” from the KMS Key drop-down.
  7. Select your “test” Alias
  8. Provide the Client Id, Client Secret, and Verification Token for your Slack application.
  9. Choose Activate to generate the OAuth URL and Postback URL.

Use the OAuth URL and Postback URL on the Slack application portal to complete the integration. For more information about setting up a Slack application and integrating with Amazon Lex, see Integrating an Amazon Lex Bot with Slack.

Using a Lambda function to get answers from Amazon Kendra

When the user asks a question, the Lex bot’s fallback intent is triggered if the user’s input does not match any of the configured Lex intents. The fulfillment code in the Fallback intent can be used to query the Kendra index, and Amazon Kendra will surface a specific answer, which can be (1) a direct answer from an FAQ; (2) a relevant excerpt from an indexed document, along with a link to the document; or (3) a list of relevant documents for the user to choose from.

Here is the Lambda integration Python code for this blog post, which can be used for any Lex/Kendra integration:

def get_kendra_answer(question):
    try:
        KENDRA_INDEX = os.environ['KENDRA_INDEX']
    except KeyError:
        return 'Configuration error - please set the Kendra index ID in the environment variable KENDRA_INDEX.'
    
    try:
        response = kendra_client.query(IndexId=KENDRA_INDEX, QueryText=question)
    except:
        return None

    logger.debug('<<help_desk_bot>> get_kendra_answer() - response = ' + json.dumps(response)) 
    
    #
    # determine which is the top result from Amazon Kendra, based on the Type attribue
    #  - QUESTION_ANSWER = a result from a FAQ: just return the FAQ answer
    #  - ANSWER = text found in a document: return the text passage found in the document plus a link to the document
    #  - DOCUMENT = link(s) to document(s): check for several documents and return the links
    #
    
    first_result_type = ''
    try:
        first_result_type = response['ResultItems'][0]['Type']
    except KeyError:
        return None

    if first_result_type == 'QUESTION_ANSWER':
        try:
            faq_answer_text = response['ResultItems'][0]['DocumentExcerpt']['Text']
        except KeyError:
            faq_answer_text = "Sorry, I could not find an answer in our FAQs."

        return faq_answer_text

    elif first_result_type == 'ANSWER':
        # return the text answer from the document, plus the URL link to the document
        try:
            document_title = response['ResultItems'][0]['DocumentTitle']['Text']
            document_excerpt_text = response['ResultItems'][0]['DocumentExcerpt']['Text']
            document_url = response['ResultItems'][0]['DocumentURI']
            answer_text = "I couldn't find a specific answer, but here's an excerpt from a document ("
            answer_text += "<" + document_url + "|" + document_title + ">"
            answer_text += ") that might help:\n\n" + document_excerpt_text + "...\n"            
        except KeyError:
            answer_text = "Sorry, I could not find the answer in our documents."

        return answer_text

    elif first_result_type == 'DOCUMENT':
        # assemble the list of document links
        document_list = "Here are some documents you could review:\n"
        for item in response['ResultItems']:
            document_title = None
            document_url = None
            if item['Type'] == 'DOCUMENT':
                if item.get('DocumentTitle', None):
                    if item['DocumentTitle'].get('Text', None):
                        document_title = item['DocumentTitle']['Text']
                if item.get('DocumentId', None):
                    document_url = item['DocumentURI']
            
            if document_title is not None:
                document_list += '-  <' + document_url + '|' + document_title + '>\n'

        return document_list

    else:
        return None 

Amazon Lex allows you to create a convenient, natural language chat experience that your users can interact with using a familiar interface, such as Slack.  Amazon Lex allows you to curate specific types of interactions through intents, including transactional capabilities (such as scheduling an appointment with the Help Desk). By integrating Amazon Lex with Amazon Kendra, you can extend this experience with an additional natural language capability, enabling users to get answers to questions based on existing content in FAQs and documents.  Amazon Kendra can surface direct answers from FAQs, relevant document excerpts, and links to relevant documents.

Conclusion

This post demonstrates how to integrate Amazon Lex and Amazon Kendra to answer queries received via messaging platforms such as Slack. Amazon Kendra provides an intuitive way to search using natural language, and returns accurate answers, so your users can discover information stored within vast amounts of content. Integrating with Amazon Kendra simplifies your bot design, and delivers natural language answers that can fit seamlessly into your automated conversations. For more information about incorporating these techniques into your bots, please see the Amazon Kendra documentation.


About the Authors

Brian Yost is a Senior Consultant with AWS Professional Services. In his spare time, he enjoys mountain biking, home brewing, and tinkering with technology.

 

 

 

harshal_pimpalkhute_100As a Product Manager on the Amazon Lex team, Harshal Pimpalkhute spends his time trying to get machines to engage (nicely) with humans.

 

 

 

As a Solutions Architect, Niranjan Hira is often found near a white board helping our customers assemble the right building blocks to address their business challenges. In his spare time, he breaks things to see if he can put them back together.