Exemple #1
0
        private async Task <QueryResult> GetGeneralResponseFromKB(ITurnContext turnContext, ShowQnAResultState qnaStatus, bool considerActiveLearning = false, CancellationToken cancellationToken = default(CancellationToken))
        {
            var qnaOptions = new QnAMakerOptions();

            if (considerActiveLearning)
            {
                qnaOptions.Top            = Constants.ActiveLearningTop;
                qnaOptions.ScoreThreshold = Constants.ActiveLearningThreshold;
            }
            else
            {
                qnaOptions.Top            = Constants.DefaultTop;
                qnaOptions.ScoreThreshold = Constants.DefaultThreshold;
            }

            var response = await _services.QnAServices[QnAMakerKey].GetAnswersAsync(turnContext, qnaOptions);

            if (response != null && response.GetLength(0) != 0 && response[0].Score >= Constants.DefaultThreshold)
            {
                if (response.GetLength(0) == 1 || !considerActiveLearning || response[0].Score > 0.95F)
                {
                    return(response[0]);
                }

                var activeLearningResponse = HandleActiveLearning(response, qnaStatus, turnContext.Activity.Text);
                TelemetryUtils.LogActiveLearningResponse(this._services.TelemetryClient, TelemetryConstants.ActiveLearningEvent, turnContext.Activity, activeLearningResponse);
                return(activeLearningResponse);
            }

            return(null);
        }
Exemple #2
0
        private async Task HandleFeedbackFlow(ShowQnAResultState qnastatus, ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken))
        {
            var isValidFeedback = await this.IsValidFeedback(turnContext);

            if (isValidFeedback)
            {
                TelemetryUtils.LogFeedbackResponse(this._services.TelemetryClient, TelemetryConstants.FeedbackEvent, turnContext.Activity, qnastatus);
                turnContext.Activity.Text = qnastatus.QnaAnswer.Requery ?? null;
            }

            qnastatus.ConsiderState = false;
            qnastatus.IsFeedback    = false;
            qnastatus.NeuroconCount = 0;
        }
Exemple #3
0
        private async Task <string> GetLuisIntent(ITurnContext turnContext, bool enableLuis, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (!enableLuis)
            {
                return("None");
            }

            try
            {
                var luisResult = await _services.LuisServices[LuisKey].RecognizeAsync(turnContext, cancellationToken);
                var topIntent  = luisResult?.GetTopScoringIntent();
                TelemetryUtils.LogLuisResponse(this._services.TelemetryClient, TelemetryConstants.LuisEvent, turnContext.Activity, topIntent.Value.intent + " score : " + topIntent.Value.score.ToString());
                return(topIntent.Value.intent);
            }
            catch (Exception e)
            {
                TelemetryUtils.LogException(this._services.TelemetryClient, turnContext.Activity, e, "luis", "expection while getting luis intent");
                return("None");
            }
        }
Exemple #4
0
        /// <summary>
        /// Every conversation turn for our QnA bot will call this method.
        /// There are no dialogs used, the sample only uses "single turn" processing,
        /// meaning a single request and response, with no stateful conversation.
        /// </summary>
        /// <param name="turnContext">A <see cref="ITurnContext"/> containing all the data needed
        /// for processing this conversation turn. </param>
        /// <param name="cancellationToken">(Optional) A <see cref="CancellationToken"/> that can be used by other objects
        /// or threads to receive notice of cancellation.</param>
        /// <returns>A <see cref="Task"/> that represents the work queued to execute.</returns>
        /// <seealso cref="BotStateSet"/>
        /// <seealso cref="ConversationState"/>
        /// <seealso cref="IMiddleware"/>
        public async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken))
        {
            // Handle Message activity type, which is the main activity type for shown within a conversational interface
            // Message activities may contain text, speech, interactive cards, and binary or unknown attachments.
            // see https://aka.ms/about-bot-activity-message to learn more about the message and other activity types
            if (turnContext.Activity.Type == ActivityTypes.Message)
            {
                var dialogContext = await dialogs.CreateContextAsync(turnContext, cancellationToken);

                var qnastatus = await _accessors.QnAResultState.GetAsync(turnContext, () => new ShowQnAResultState());

                if (qnastatus.IsFeedback)
                {
                    await HandleFeedbackFlow(qnastatus, turnContext, cancellationToken);
                }

                string requery = null;
                if (qnastatus.ConsiderState)
                {
                    // Call Active Learning Train API
                    if (qnastatus.ActiveLearningAnswer)
                    {
                        _services.QnAServices.TryGetValue(QnAMakerKey, out var qnaservice);
                        var activeLearningData = new ActiveLearningDTO()
                        {
                            hostName     = qnaservice.Endpoint.Host,
                            endpointKey  = qnaservice.Endpoint.EndpointKey,
                            kbid         = qnaservice.Endpoint.KnowledgeBaseId,
                            userId       = turnContext.Activity.From.Id,
                            userQuestion = qnastatus.ActiveLearningUserQuestion,
                        };

                        requery = Utils.GetRequery(qnastatus, turnContext.Activity.Text, activeLearningData);
                        if (requery != null)
                        {
                            TelemetryUtils.LogTrainApiResponse(this._services.TelemetryClient, TelemetryConstants.TrainApiEvent, turnContext.Activity, activeLearningData, requery);
                        }
                    }
                    else
                    {
                        requery = Utils.GetRequery(qnastatus, turnContext.Activity.Text);
                    }

                    if (requery != null)
                    {
                        turnContext.Activity.Text = requery;
                    }
                }

                QueryResult responseGeneral = null, responseLuis = null;

                // Get QnA Answer for multiturn
                var responseMultiturn = await GetMultiturnResponseFromKB(turnContext, qnastatus.QnaAnswer);

                if (responseMultiturn == null)
                {
                    // Get general response from KB
                    responseGeneral = await GetGeneralResponseFromKB(turnContext, qnastatus, true);

                    if (responseGeneral == null)
                    {
                        // Get LUIS intent
                        var luisIntent = await GetLuisIntent(turnContext, Constants.EnableLuis);

                        if (!luisIntent.Equals("None"))
                        {
                            // Get Luis response
                            responseLuis = await GetResponseWithLuisIntent(turnContext, luisIntent);
                        }
                    }
                }

                // choose response
                var qnaresponse = Utils.SelectResponse(responseMultiturn, responseGeneral, responseLuis, qnastatus.QnaAnswer);
                if (qnaresponse != null)
                {
                    if (qnaresponse.Options != null && qnaresponse.Options.Count != 0)
                    {
                        await ShowQnAResponseWithOptions(turnContext, qnaresponse, qnastatus);
                    }
                    else
                    {
                        await ShowQnAResponseWithText(turnContext, qnaresponse, qnastatus);
                    }

                    if (qnastatus.QnaAnswer.Name == Constants.MetadataValue.Redirection)
                    {
                        await ShowRedirection(Constants.RedirectionType.GuidedFlow, turnContext, cancellationToken);
                    }

                    if (qnastatus.NeuroconCount >= Constants.ConsecutiveNeuroconAnswersAllowed)
                    {
                        await ShowRedirection(Constants.RedirectionType.Neurocon, turnContext, cancellationToken);
                    }
                }
                else
                {
                    // get answer from Nurocon
                    var personalitychatanswer = await SendCognitiveServicesResponse(turnContext, cancellationToken, Constants.EnablePersonalityChat);

                    if (personalitychatanswer == string.Empty || personalitychatanswer.Equals(@"Sorry, I don't have a response for that.", StringComparison.OrdinalIgnoreCase))
                    {
                        var msg = @"I don't have an answer for that. Try typing MENU to go back to the main menu";
                        TelemetryUtils.LogNoAnswerEvent(this._services.TelemetryClient, turnContext.Activity);
                        qnastatus.NeuroconCount++;
                        await _accessors.QnAResultState.SetAsync(turnContext, qnastatus);

                        await _accessors.ConversationState.SaveChangesAsync(turnContext);

                        await turnContext.SendActivityAsync(msg, cancellationToken : cancellationToken);

                        if (qnastatus.NeuroconCount >= Constants.ConsecutiveNeuroconAnswersAllowed)
                        {
                            await ShowRedirection(Constants.RedirectionType.Neurocon, turnContext, cancellationToken);
                        }
                    }
                    else
                    {
                        personalitychatanswer   = personalitychatanswer + " [&#x1f6c8;](https://labs.cognitive.microsoft.com/en-us/project-personality-chat \"Auto generated answer using Personality chat. Click to know more\")";
                        qnastatus.ConsiderState = false;
                        qnastatus.QnaAnswer     = null;
                        qnastatus.NeuroconCount++;
                        TelemetryUtils.LogNeuroconResponse(this._services.TelemetryClient, TelemetryConstants.NeuroconEvent, turnContext.Activity, qnastatus, personalitychatanswer);
                        await _accessors.QnAResultState.SetAsync(turnContext, qnastatus);

                        await _accessors.ConversationState.SaveChangesAsync(turnContext);

                        await turnContext.SendActivityAsync(personalitychatanswer, cancellationToken : cancellationToken);

                        if (qnastatus.NeuroconCount >= Constants.ConsecutiveNeuroconAnswersAllowed)
                        {
                            await ShowRedirection(Constants.RedirectionType.Neurocon, turnContext, cancellationToken);
                        }
                    }
                }
            }
            else if (turnContext.Activity.Type == ActivityTypes.ConversationUpdate)
            {
                return;
            }
            else if (turnContext.Activity.Type == ActivityTypes.Event)
            {
                // Send a welcome message to the user.
                var eventActivity = turnContext.Activity.AsEventActivity();
                if (eventActivity.Name == Constants.EventWelcomeMessage)
                {
                    TelemetryUtils.LogWelcomeResponse(this._services.TelemetryClient, "Welcome Event Detected", turnContext.Activity);
                    var dialogContext = await dialogs.CreateContextAsync(turnContext, cancellationToken);

                    var qnastatus = await _accessors.QnAResultState.GetAsync(turnContext, () => new ShowQnAResultState());

                    qnastatus.ConsiderState  = false;
                    qnastatus.QnaAnswer.Text = Constants.WelcomeQuestion;
                    qnastatus.QnaAnswer.Name = Constants.MetadataValue.Welcome;
                    await _accessors.QnAResultState.SetAsync(turnContext, qnastatus);

                    await _accessors.ConversationState.SaveChangesAsync(turnContext);
                    await SendWelcomeMessageAsync(turnContext, cancellationToken);
                }
            }
            else
            {
                await turnContext.SendActivityAsync($"{turnContext.Activity.Type} event detected", cancellationToken : cancellationToken);
            }
        }