forked from Azure-Samples/cognitive-services-qnamaker-csharp
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcreate-knowledge-base.cs
228 lines (202 loc) · 9.09 KB
/
create-knowledge-base.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
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 QnaMakerQuickstart
{
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 = "ADD 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 from quickstart for update - take 2',
'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>
/// 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.
using (var client = new HttpClient())
using (var request = new HttpRequestMessage())
{
request.Method = HttpMethod.Post;
request.RequestUri = new Uri(uri);
request.Content = new StringContent(kb, 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>
/// 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 operationID)
{
// Builds the HTTP request URI.
string uri = host + service + operationID;
// 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.
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, 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();
}
}
}