/// <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);
        }
Beispiel #2
0
        /// <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);
        }