Click here to Skip to main content
15,346,368 members
Articles / Hosted Services / Azure
Posted 9 May 2017


8 bookmarked

Turn your FAQ pages into an interesting Chat Bot using QnA Maker

Rate me:
Please Sign up or sign in to vote.
5.00/5 (5 votes)
10 May 2017CPOL2 min read
Microsoft QnA Maker helps turn your FAQ pages into interesting Chat Bot. It is very simple to configure and integrate with.


Every website that we create be it an external marketing website or an internal back office application always will have a page which will contain the Frequently Asked Questions(FAQ). These FAQs are usually designed in a single page with the list of questions and answers with internal links and a search box. How to make this interesting?

Let us Begin

Microsoft came up with a product QnA Maker which can turn any FAQs into a chat bot. Converting FAQs into chat bot is very simple. Just follow these simple instructions.

Login to QnA Maker

Create an account, if you don’t have one and follow the usual registration process

Once you log in, the user is taken to this page

Image 1

Click on the “Create New Service” button. Provide the name for the service, if you have an internet based website, you can provide the URL of the FAQ page, the QnAMaker will extract the Questions and Answers out of it.

You can also provide the Questions and Answers in a word document, in the following format

Else, you can provide the Questions and Answers manually in the next step.

Image 2

Click “Create Service” to continue. The service is created. The Knowledge Base screen will list all the questions and answers extracted out of the previous step. If it hasn’t extracted some, you can manually add those by clicking on the “Add new QnA Pair” on the top right hand corner.

Image 3

Once you are done adding all the Questions and Answers you can test your bot by clicking on the “Test” Menu on the right hand side

Image 4

Type in the chat text box and you could see how the bot answers to your questions. If the bot identifies more than one alternatives to the question. You can select the appropriate ones from the left hand side options. Click “Save and Retrain” to train you bot.

Once the training is done, Click on Publish to complete the process.

Image 5

The sample HTTP request is shown, the request to be sent is in a JSON format.


We can create a consumer application by creating an ASP.NET MVC application. In the HomeController.cs file, Create a method “Chat

public string Chat(string query)
    string responseString = string.Empty;
    var knowledgebaseId = ""; // Use knowledge base id created.
    var qnamakerSubscriptionKey = ""; //Use subscription key assigned to you.
    //Build the URI
    Uri qnamakerUriBase = new Uri("");
    var builder = new UriBuilder(@"" + knowledgebaseId + "/generateAnswer");

    //Add the question as part of the body
    var postBody = "{\"question\": \"" + query + "\"}";

    //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);
        var response = JsonConvert.DeserializeObject<QnAMakerResult>(responseString);
        if (response.Score > 10.0)
            return response.Answer;
            return "Sorry, I don't have an answer. Please mail";


In the client side, we can create a simple knockout.js script to invoke the controller endpoint and tie it to a HTML. 

   function AppViewModel() {
    var self = this;
    self.people = ko.observableArray([]);
    self.searchKeyUp = function (d, e) {
        if (e.keyCode == 13) {
    self.addPerson = function () {
    function addPerson()
        var q = $("#btn-input").val();
        if (q != "")
            self.people.push({ Name: "You - ", Query: q });
                type: "GET",
                url: '@Url.Action("Chat", "Home")',
                //contentType: "application/json; charset=utf-8",
                data: { query: q },
                //  dataType: "json",
                success: function (data) {
                    console.log(data.replace(/\&#160;/g, ''));
                    data = data.replace(/\&lt;/g, '<').replace(/\&gt;/g, '>');

                    self.people.push({ Name: "Smarty - ", Query: data });
                error: function () { alert('Error'); }



ko.applyBindings(new AppViewModel());

The HTML view can be expressed 

<div class="row">
    <div class="col-md-offset-7 col-md-5">
        <div class="panel panel-default">
            <div class="panel-heading" id="accordion">
                <div class="input-group">
                    <input id="btn-input" type="text" data-bind="event: { keyup: searchKeyUp }" 
                           class="form-control input-sm" placeholder="Type your message here..." 
                           vk_18c1e="subscribed" style="direction: ltr;" />
                    <span class="input-group-btn">
                        <button class="btn btn-default btn-sm" id="btn-chat" data-bind="click: addPerson">
                            <i class="fa fa-paper-plane" aria-hidden="true"></i>
            <div class="panel-collapse collapse in" id="collapseOne">
                <div class="panel-body">
                    <ul class="chat" style="font-size:11px">
                        <li class="left clearfix" data-bind="foreach:people">
                            <div class="chat-body clearfix" style="padding:10px">
                                <div class="header">

                                    <strong class="pull-left primary-font" style="margin-right:8px" data-bind="text:Name"></strong>
                                <div style="padding-left:2px" data-bind="bindHTML:Query">


In case if the knowledge has some a tag and HTML text then create a custom binding 

ko.bindingHandlers.bindHTML = {
           init: function () {
               // Prevent binding on the dynamically-injected HTML (as developers are unlikely to expect that, and it has security implications)
               return { 'controlsDescendantBindings': true };
           update: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
               // setHtml will unwrap the value if needed
               ko.utils.setHtml(element, valueAccessor());
               var elementsToAdd = element.children;
               for (var i = 0; i < elementsToAdd.length; i++) {
                   ko.cleanNode(elementsToAdd[i]); //Clean node from Knockout bindings
                   ko.applyBindings(bindingContext, elementsToAdd[i]);


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Antony Gino
United States United States
No Biography provided

Comments and Discussions

QuestionSource code Pin
Jim Mathew21-May-17 23:41
MemberJim Mathew21-May-17 23:41 
Questionall images are missing Pin
Tridip Bhattacharjee10-May-17 0:04
professionalTridip Bhattacharjee10-May-17 0:04 
QuestionUpdated the images back to code Pin
Antony Gino9-May-17 14:54
MemberAntony Gino9-May-17 14:54 
SuggestionImages, still Pin
Afzaal Ahmad Zeeshan9-May-17 11:55
mveAfzaal Ahmad Zeeshan9-May-17 11:55 
QuestionImages... Pin
OriginalGriff9-May-17 8:28
mveOriginalGriff9-May-17 8:28 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.