Introduction
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
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.
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.
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
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.
The sample HTTP request is shown, the request to be sent is in a JSON format.
{“question”:””}
We can create a consumer application by creating an ASP.NET MVC application. In the HomeController.cs file, Create a method “Chat
”
[ValidateInput(false)]
public string Chat(string query)
{
string responseString = string.Empty;
var knowledgebaseId = "";
var qnamakerSubscriptionKey = "";
Uri qnamakerUriBase = new Uri("https://westus.api.cognitive.microsoft.com/qnamaker/v1.0");
var builder = new UriBuilder(@"https://westus.api.cognitive.microsoft.com/qnamaker/v1.0/knowledgebases/" + knowledgebaseId + "/generateAnswer");
var postBody = "{\"question\": \"" + query + "\"}";
using (WebClient client = new WebClient())
{
client.Encoding = System.Text.Encoding.UTF8;
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;
}
else
{
return "Sorry, I don't have an answer. Please mail admin@application.com";
}
}
}
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) {
addPerson();
}
}
self.addPerson = function () {
addPerson();
};
function addPerson()
{
var q = $("#btn-input").val();
if (q != "")
{
$("#btn-input").val("");
self.people.push({ Name: "You - ", Query: q });
$.ajax({
type: "GET",
url: '@Url.Action("Chat", "Home")',
data: { query: q },
success: function (data) {
console.log(data.replace(/\ /g, ''));
data = data.replace(/\</g, '<').replace(/\>/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>
</button>
</span>
</div>
</div>
<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>
<div style="padding-left:2px" data-bind="bindHTML:Query">
</div>
</div>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
In case if the knowledge has some a tag and HTML text then create a custom binding
ko.bindingHandlers.bindHTML = {
init: function () {
return { 'controlsDescendantBindings': true };
},
update: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
ko.utils.setHtml(element, valueAccessor());
var elementsToAdd = element.children;
for (var i = 0; i < elementsToAdd.length; i++) {
ko.cleanNode(elementsToAdd[i]);
ko.applyBindings(bindingContext, elementsToAdd[i]);
}
}
};