Skip to content

Instantly share code, notes, and snippets.

@AbhiOnGithub
Created August 23, 2018 07:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AbhiOnGithub/8098dd9bc03120d1379f2079eb239ba0 to your computer and use it in GitHub Desktop.
Save AbhiOnGithub/8098dd9bc03120d1379f2079eb239ba0 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
// NOTE: Install the Newtonsoft.Json NuGet package.
using Newtonsoft.Json;
namespace QnAMaker
{
class Program
{
// Represents the various elements used to create HTTP request URIs
// for QnA Maker operations.
static string host = "https://westus.api.cognitive.microsoft.com";
static string service = "/qnamaker/v4.0";
static string method = "/knowledgebases/create";
// NOTE: Replace this value with a valid QnA Maker subscription key.
static string key = "YOUR SUBSCRIPTION KEY HERE";
/// <summary>
/// Defines the data source used to create the knowledge base.
/// The data source includes a QnA pair, with metadata,
/// the URL for the QnA Maker FAQ article, and
/// the URL for the Azure Bot Service FAQ article.
/// </summary>
static string kb = @"
{
'name': 'QnA Maker FAQ',
'qnaList': [
{
'id': 0,
'answer': 'You can use our REST APIs to manage your knowledge base. See here for details: https://westus.dev.cognitive.microsoft.com/docs/services/58994a073d9e04097c7ba6fe/operations/58994a073d9e041ad42d9baa',
'source': 'Custom Editorial',
'questions': [
'How do I programmatically update my knowledge base?'
],
'metadata': [
{
'name': 'category',
'value': 'api'
}
]
}
],
'urls': [
'https://docs.microsoft.com/en-in/azure/cognitive-services/qnamaker/faqs',
'https://docs.microsoft.com/en-us/bot-framework/resources-bot-framework-faq'
],
'files': []
}
";
/// <summary>
/// Represents the HTTP response returned by an HTTP request.
/// </summary>
public struct Response
{
public HttpResponseHeaders headers;
public string response;
public Response(HttpResponseHeaders headers, string response)
{
this.headers = headers;
this.response = response;
}
}
/// <summary>
/// Formats and indents JSON for display.
/// </summary>
/// <param name="s">The JSON to format and indent.</param>
/// <returns>A string containing formatted and indented JSON.</returns>
static string PrettyPrint(string s)
{
return JsonConvert.SerializeObject(JsonConvert.DeserializeObject(s), Formatting.Indented);
}
/// <summary>
/// Asynchronously sends a POST HTTP request.
/// </summary>
/// <param name="uri">The URI of the HTTP request.</param>
/// <param name="body">The body of the HTTP request.</param>
/// <returns>A <see cref="System.Threading.Tasks.Task{TResult}(QnAMaker.Program.Response)"/>
/// object that represents the HTTP response."</returns>
async static Task<Response> Post(string uri, string body)
{
using (var client = new HttpClient())
using (var request = new HttpRequestMessage())
{
request.Method = HttpMethod.Post;
request.RequestUri = new Uri(uri);
request.Content = new StringContent(body, Encoding.UTF8, "application/json");
request.Headers.Add("Ocp-Apim-Subscription-Key", key);
var response = await client.SendAsync(request);
var responseBody = await response.Content.ReadAsStringAsync();
return new Response(response.Headers, responseBody);
}
}
/// <summary>
/// Asynchronously sends a GET HTTP request.
/// </summary>
/// <param name="uri">The URI of the HTTP request.</param>
/// <returns>A <see cref="System.Threading.Tasks.Task{TResult}(QnAMaker.Program.Response)"/>
/// object that represents the HTTP response."</returns>
async static Task<Response> Get(string uri)
{
using (var client = new HttpClient())
using (var request = new HttpRequestMessage())
{
request.Method = HttpMethod.Get;
request.RequestUri = new Uri(uri);
request.Headers.Add("Ocp-Apim-Subscription-Key", key);
var response = await client.SendAsync(request);
var responseBody = await response.Content.ReadAsStringAsync();
return new Response(response.Headers, responseBody);
}
}
/// <summary>
/// Creates a knowledge base.
/// </summary>
/// <param name="kb">The data source for the knowledge base.</param>
/// <returns>A <see cref="System.Threading.Tasks.Task{TResult}(QnAMaker.Program.Response)"/>
/// object that represents the HTTP response."</returns>
/// <remarks>The method constructs the URI to create a knowledge base in QnA Maker, and then
/// asynchronously invokes the <see cref="QnAMaker.Program.Post(string, string)"/> method
/// to send the HTTP request.</remarks>
async static Task<Response> PostCreateKB(string kb)
{
// Builds the HTTP request URI.
string uri = host + service + method;
// Writes the HTTP request URI to the console, for display purposes.
Console.WriteLine("Calling " + uri + ".");
// Asynchronously invokes the Post(string, string) method, using the
// HTTP request URI and the specified data source.
return await Post(uri, kb);
}
/// <summary>
/// Gets the status of the specified QnA Maker operation.
/// </summary>
/// <param name="operation">The QnA Maker operation to check.</param>
/// <returns>A <see cref="System.Threading.Tasks.Task{TResult}(QnAMaker.Program.Response)"/>
/// object that represents the HTTP response."</returns>
/// <remarks>The method constructs the URI to get the status of a QnA Maker operation, and
/// then asynchronously invokes the <see cref="QnAMaker.Program.Get(string)"/> method
/// to send the HTTP request.</remarks>
async static Task<Response> GetStatus(string operation)
{
// Builds the HTTP request URI.
string uri = host + service + operation;
// Writes the HTTP request URI to the console, for display purposes.
Console.WriteLine("Calling " + uri + ".");
// Asynchronously invokes the Get(string) method, using the
// HTTP request URI.
return await Get(uri);
}
/// <summary>
/// Creates a knowledge base, periodically checking status
/// until the knowledge base is created.
/// </summary>
async static void CreateKB()
{
try
{
// Starts the QnA Maker operation to create the knowledge base.
var response = await PostCreateKB(kb);
// Retrieves the operation ID, so the operation's status can be
// checked periodically.
var operation = response.headers.GetValues("Location").First();
// Displays the JSON in the HTTP response returned by the
// PostCreateKB(string) method.
Console.WriteLine(PrettyPrint(response.response));
// Iteratively gets the state of the operation creating the
// knowledge base. Once the operation state is set to something other
// than "Running" or "NotStarted", the loop ends.
var done = false;
while (true != done)
{
// Gets the status of the operation.
response = await GetStatus(operation);
// Displays the JSON in the HTTP response returned by the
// GetStatus(string) method.
Console.WriteLine(PrettyPrint(response.response));
// Deserialize the JSON into key-value pairs, to retrieve the
// state of the operation.
var fields = JsonConvert.DeserializeObject<Dictionary<string, string>>(response.response);
// Gets and checks the state of the operation.
String state = fields["operationState"];
if (state.CompareTo("Running") == 0 || state.CompareTo("NotStarted") == 0)
{
// QnA Maker is still creating the knowledge base. The thread is
// paused for a number of seconds equal to the Retry-After header value,
// and then the loop continues.
var wait = response.headers.GetValues("Retry-After").First();
Console.WriteLine("Waiting " + wait + " seconds...");
Thread.Sleep(Int32.Parse(wait) * 1000);
}
else
{
// QnA Maker has completed creating the knowledge base.
done = true;
}
}
}
catch
{
// An error occurred while creating the knowledge base. Ensure that
// you included your QnA Maker subscription key where directed in the sample.
Console.WriteLine("An error occurred while creating the knowledge base.");
}
finally
{
Console.WriteLine("Press any key to continue.");
}
}
static void Main(string[] args)
{
// Invoke the CreateKB() method to create a knowledge base, periodically
// checking the status of the QnA Maker operation until the
// knowledge base is created.
CreateKB();
// The console waits for a key to be pressed before closing.
Console.ReadLine();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment