Bots

FAQ Bots with Microsoft QnA service

TL;DR

Luis may be overkill for the the bot you want to create. If you only need your bot to answer questions (especially ones already on a FAQ site) try QnA bots from Microsoft Cognitive Services. QnAMaker automatically trains your service based on existing FAQ pages to save a bunch of time. In this post, I walk you through creating one and the code needed for your bot to link to the service. QnAMaker is currently in Preview as of January 2016; more information can be found at qnamaker.ai.

QnA Service vs. LUIS Service

First what is Microsoft QnA Maker. Well “Microsoft QnA Maker is a free, easy-to-use, REST API and web-based service that trains AI to respond to user’s questions in a more natural, conversational way.” It streamlines production of a REST API that your bot or other application can ping. So why use LUIS? If you want automation of a service that requires multiple response from your user (i.e. phone automation systems, ordering a sandwich, modifying settings on a services), LUIS’s interface and pipeline manages that development process better.

Getting started with the QnA bots

First, go to QnAmaker.ai and sign in with your live ID.

qnasitesignin

Once you’ve signed in create a new service

createnewservices

Type in the name of the service and the FAQ link you want to use, I’m linking to Unity’s FAQ page in this example. What’s great is that you can add more than one URL for your QnA bot to pull from. So if the site you are using has a FAQ that redirects to different pages to answer questions you can add those other pages too. You don’t need to use a url, uploading your own questions and answers works too.

createnewservices2

Hit “Create” at the bottom of the page.

createnewservices3

After you hit create the page will take you a new page with the questions and answers that the service was able to identify from the source (url or file) you provided. The questions and answers that the service identifies is called your Knowledge Base (KB).

qnaknowledgebase

 

Natural Language Testing

To train your service you can start plugging natural language questions and the service return the FAQ answers that would best match. If the service can’t get a high enough probability percentage for an answer it will return multiple answers, that you can choose from.

testquestionschoice

You also have the ability to provide alternate phrasing for question you just asked in the right hand side of the tool, so that they can map to the same answer.

testquestionschoice2

Any time you make an adjustment to what the service returned for an answer, be sure to save what you’ve done by clicking Save and Retrain button.

testsaveretrain

Once you’ve finished training the service you can hit publish. You’ll be taken to a page with a summary of the numbers of changes that you had, before the service will be published.

publish

** Note: The service won’t be published until you hit the publish button on this summary page. **

publish2

Once your service is published the site will provide an sample HTTP request that you can test with any rest client.

publish3

Code – Connecting it to Microsoft Bot Framework

If this your first time working with the Microsoft Bot Framework you might want to check out my post about it here: Microsoft Bot Framework, or read up about it on the Microsoft’s site: https://docs.botframework.com/en-us/.

For this example I’m using:

The MessagesController class and create a QnAMakerResult class hold the most important parts of code. Depending on the complexity of your bot you may want to look into dialogs and chains, instead of putting your handler in the MessageController class.

QNAMAKER RESULT

    public class QnAMakerResult
    {
        ///

<summary>
        /// The top answer found in the QnA Service.
        /// </summary>


        [JsonProperty(PropertyName = "answer")]
        public string Answer { get; set; }

        ///

<summary>
        /// The score in range [0, 100] corresponding to the top answer found in the QnA    Service.
        /// </summary>


        [JsonProperty(PropertyName = "score")]
        public double Score { get; set; }
    }

Be sure to add the Newtonsoft Library to the class.

using Newtonsoft.Json;

Message Controller

Inside the MessageController Post task, in the if(activity.Type == Message) block add the following:

ConnectorClient connector = new ConnectorClient(new Uri(activity.ServiceUrl));
                var responseString = String.Empty;
                var responseMsg = "";

                //De-serialize the response
                QnAMakerResult QnAresponse;

                // Send question to API QnA bot
                if (activity.Text.Length > 0)
                {
                    var knowledgebaseId = "YOUR KB ID"; // Use knowledge base id created.
                    var qnamakerSubscriptionKey = "YOUR SUB KEY"; //Use subscription key assigned to you.

                    //Build the URI
                    Uri qnamakerUriBase = new Uri("https://westus.api.cognitive.microsoft.com/qnamaker/v1.0");
                    var builder = new UriBuilder($"{qnamakerUriBase}/knowledgebases/{knowledgebaseId}/generateAnswer");

                    //Add the question as part of the body
                    var postBody = $"{{\"question\": \"{activity.Text}\"}}";

                    //Send the POST request
                    using (WebClient client = new WebClient())
                    {
                        //Set the encoding to UTF8
                        client.Encoding = System.Text.Encoding.UTF8;

                        //Add the subscription key header
                        client.Headers.Add("Ocp-Apim-Subscription-Key", qnamakerSubscriptionKey);
                        client.Headers.Add("Content-Type", "application/json");
                        responseString = client.UploadString(builder.Uri, postBody);
                    }

                    try
                    {
                        QnAresponse = JsonConvert.DeserializeObject<QnAMakerResult>(responseString);
                        responseMsg = QnAresponse.Answer.ToString();
                    }
                    catch
                    {
                        throw new Exception("Unable to deserialize QnA Maker response string.");
                    }
                }

                // return our reply to the user
                Activity reply = activity.CreateReply(responseMsg);
                await connector.Conversations.ReplyToActivityAsync(reply);

You can now test your code by running it and opening up the emulator. Be sure to pass in the correct localhost port in the emulator to connect to your project. The default ID and password is blank so you won’t have to add anything when testing locally.

emulator

Your Bot

Okay so far we create a REST service that will answer questions based on a Knowledge Base built on specific FAQs. That service can be accessed by any type of application, including the Microsoft Bot Framework. With the code snippets we can use the bot framework to manage users input before pinging the QnA REST service. However we still need to build and host the bot.

We need to create Register a Bot on the Microsoft Bot Framework site. You can host the code on on a Web App within Azure then connect that to the Registered Bot. I use continuous GitHub deployment to update my code. The Microsoft Bot Framework enables the Web and Skype channels by default but there are others that you can easily add to your bot like Slack and Facebook Messenger. If you follow my previous post I have instruction on how to do this or you can look on the Microsoft Bot Framework documentation.

That’s it. You should have your FAQ bot up and working within a couple hours =)

Happy Hacking!

– TheNappingKat

Leave a Comment

Your email address will not be published. Required fields are marked *