/// <summary> /// Processess an incoming activity. /// </summary> /// <param name="context">The context object for this turn.</param> /// <param name="next">The delegate to call to continue the bot middleware pipeline.</param> public async Task OnTurn(ITurnContext context, MiddlewareSet.NextDelegate next) { if (context.Activity.Type == ActivityTypes.Message) { var messageActivity = context.Activity.AsMessageActivity(); if (!string.IsNullOrEmpty(messageActivity.Text)) { var results = await _qnaMaker.GetAnswers(messageActivity.Text.Trim()).ConfigureAwait(false); if (results == null) { throw new Exception("Call to QnAMaker failed."); } var traceInfo = new QnAMakerTraceInfo { Message = messageActivity, QueryResults = results, KnowledgeBaseId = _endpoint.KnowledgeBaseId, // leave out _endpoint.SubscriptionKey, it is not public ScoreThreshold = _options.ScoreThreshold, Top = _options.Top, StrictFilters = _options.StrictFilters, MetadataBoost = _options.MetadataBoost, }; var traceActivity = Activity.CreateTraceActivity(QnAMakerMiddlewareName, QnAMakerTraceType, traceInfo, QnAMakerTraceLabel); await context.SendActivity(traceActivity).ConfigureAwait(false); if (results.Any()) { if (!string.IsNullOrEmpty(_options.DefaultAnswerPrefixMessage)) { await context.SendActivity(_options.DefaultAnswerPrefixMessage); } await context.SendActivity(results.First().Answer); if (_options.EndActivityRoutingOnAnswer) { //Question is answered, don't keep routing return; } } } } await next().ConfigureAwait(false); }
/// <summary> /// Generates an answer from the knowledge base. /// </summary> /// <param name="context">The Turn Context that contains the user question to be queried against your knowledge base.</param> /// <returns>A list of answers for the user query, sorted in decreasing order of ranking score.</returns> public async Task <QueryResult[]> GetAnswersAsync(ITurnContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } if (context.Activity == null) { throw new ArgumentNullException(nameof(context.Activity)); } var messageActivity = context.Activity.AsMessageActivity(); if (messageActivity == null) { throw new ArgumentException("Activity type is not a message"); } if (string.IsNullOrEmpty(context.Activity.Text)) { throw new ArgumentException("Null or empty text"); } var requestUrl = $"{_endpoint.Host}/knowledgebases/{_endpoint.KnowledgeBaseId}/generateanswer"; var request = new HttpRequestMessage(HttpMethod.Post, requestUrl); var jsonRequest = JsonConvert.SerializeObject( new { messageActivity.Text, top = _options.Top, strictFilters = _options.StrictFilters, metadataBoost = _options.MetadataBoost, }, Formatting.None); request.Content = new StringContent(jsonRequest, System.Text.Encoding.UTF8, "application/json"); var isLegacyProtocol = _endpoint.Host.EndsWith("v2.0") || _endpoint.Host.EndsWith("v3.0"); if (isLegacyProtocol) { request.Headers.Add("Ocp-Apim-Subscription-Key", _endpoint.EndpointKey); } else { request.Headers.Add("Authorization", $"EndpointKey {_endpoint.EndpointKey}"); } var response = await _httpClient.SendAsync(request).ConfigureAwait(false); if (!response.IsSuccessStatusCode) { return(null); } var jsonResponse = await response.Content.ReadAsStringAsync().ConfigureAwait(false); var results = isLegacyProtocol ? ConvertLegacyResults(JsonConvert.DeserializeObject <InternalQueryResults>(jsonResponse)) : JsonConvert.DeserializeObject <QueryResults>(jsonResponse); foreach (var answer in results.Answers) { answer.Score = answer.Score / 100; } var result = results.Answers.Where(answer => answer.Score > _options.ScoreThreshold).ToArray(); var traceInfo = new QnAMakerTraceInfo { Message = (Activity)messageActivity, QueryResults = result, KnowledgeBaseId = _endpoint.KnowledgeBaseId, ScoreThreshold = _options.ScoreThreshold, Top = _options.Top, StrictFilters = _options.StrictFilters, MetadataBoost = _options.MetadataBoost, }; var traceActivity = Activity.CreateTraceActivity(QnAMakerMiddlewareName, QnAMakerTraceType, traceInfo, QnAMakerTraceLabel); await context.SendActivityAsync(traceActivity).ConfigureAwait(false); return(result); }