/// <summary> /// Generate response with options. /// </summary> /// <param name="qnaresponse"QnAMaker answer.></param> /// <returns>message activity with hero card.</returns> public static IMessageActivity GenerateResponseOptions(QnAMakerAnswer qnaresponse) { var cardButtons = new List <CardAction>(); foreach (var promptoption in qnaresponse.Options) { var title = FormatOptionText(promptoption.Option); var card = new CardAction() { Value = title, Type = ActionTypes.ImBack, Title = title, }; cardButtons.Add(card); } var heroCard = new HeroCard { Title = Constants.HeroCardTitle, Text = qnaresponse.Text, Buttons = cardButtons, }; var cardActivity = Activity.CreateMessageActivity(); cardActivity.AttachmentLayout = AttachmentLayoutTypes.Carousel; var cardAttachment = heroCard.ToAttachment(); cardActivity.Attachments.Add(cardAttachment); return(cardActivity); }
private async Task ShowQnAResponseWithOptions(ITurnContext turnContext, QnAMakerAnswer qnaresponse, ShowQnAResultState qnastatus, CancellationToken cancellationToken = default(CancellationToken)) { var cardActivity = Utils.GenerateResponseOptions(qnaresponse); qnastatus.ConsiderState = true; qnastatus.QnaAnswer = qnaresponse; qnastatus.NeuroconCount = 0; if (qnaresponse.Flowtype == Constants.MetadataValue.Feedback) { qnastatus.IsFeedback = true; } else { qnastatus.IsFeedback = false; } await _accessors.QnAResultState.SetAsync(turnContext, qnastatus); await _accessors.ConversationState.SaveChangesAsync(turnContext); await turnContext.SendActivityAsync(cardActivity, cancellationToken); }
/// <summary> /// Get QnAAnswer from the query result. /// </summary> /// <param name="response">query result response.</param> /// <returns>QnAMaker answer.</returns> public static QnAMakerAnswer GetQnAAnswerFromResponse(Microsoft.Bot.Builder.AI.QnA.QueryResult response) { if (response == null) { return(null); } var promptOptionDictionary = new Dictionary <int, PromptOption>(); var selectedResponse = response; var qnaAnswer = new QnAMakerAnswer(); qnaAnswer.Text = selectedResponse.Answer ?? null; foreach (var metadata in selectedResponse.Metadata) { if (metadata.Name.Contains(Constants.MetadataName.OptionRequery)) { var index = metadata.Name.Substring(13); if (int.TryParse(index, out var result)) { if (promptOptionDictionary.ContainsKey(result)) { promptOptionDictionary[result].Requery = metadata.Value; } else { var optionPrompt = new PromptOption(); optionPrompt.Requery = metadata.Value; promptOptionDictionary.Add(result, optionPrompt); } } } else if (metadata.Name.Contains(Constants.MetadataName.Option)) { var index = metadata.Name.Substring(6); if (int.TryParse(index, out var result)) { if (promptOptionDictionary.ContainsKey(result)) { promptOptionDictionary[result].Option = metadata.Value; } else { var optionPrompt = new PromptOption(); optionPrompt.Option = metadata.Value; promptOptionDictionary.Add(result, optionPrompt); } } } else if (metadata.Name.Contains(Constants.MetadataName.QnAId)) { var index = metadata.Name.Substring(5); if (int.TryParse(index, out var result)) { int.TryParse(metadata.Value, out var id); if (promptOptionDictionary.ContainsKey(result)) { promptOptionDictionary[result].QnAId = id; } else { var optionPrompt = new PromptOption(); optionPrompt.QnAId = id; promptOptionDictionary.Add(result, optionPrompt); } } } else if (metadata.Name == Constants.MetadataName.Requery) { qnaAnswer.Requery = metadata.Value ?? null; } else if (metadata.Name.Contains(Constants.MetadataName.Name)) { qnaAnswer.Name = metadata.Value ?? null; } else if (metadata.Name.Contains(Constants.MetadataName.Parent)) { qnaAnswer.Parent = metadata.Value ?? null; } else if (metadata.Name.Contains(Constants.MetadataName.Isroot)) { qnaAnswer.IsRoot = metadata.Value ?? null; } else if (metadata.Name.Contains(Constants.MetadataName.Flowtype)) { qnaAnswer.Flowtype = metadata.Value ?? null; } } foreach (var promptOption in promptOptionDictionary) { qnaAnswer.Options.Add(promptOption.Value); } qnaAnswer.IsChitChat = IsResponseChitChat(response); return(qnaAnswer); }
/// <summary> /// Select final response. /// </summary> /// <param name="responseMultiturn">multiturn response.</param> /// <param name="responseGeneral">general response.</param> /// <param name="luisresponse">luis response.</param> /// <param name="previousAnswer">answer shoen previously.</param> /// <returns>selected QnAMaker answer.</returns> public static QnAMakerAnswer SelectResponse(QueryResult responseMultiturn, QueryResult responseGeneral, QueryResult luisresponse, QnAMakerAnswer previousAnswer) { if (responseMultiturn != null) { var qnaresponse = Utils.GetQnAAnswerFromResponse(responseMultiturn); if (previousAnswer == null || !qnaresponse.IsEqual(previousAnswer)) { return(qnaresponse); } } if (responseGeneral != null) { var qnaresponse = Utils.GetQnAAnswerFromResponse(responseGeneral); if (qnaresponse.IsRoot == null || !Constants.MetadataValue.ExcludeIsroot.Equals(qnaresponse.IsRoot)) { return(qnaresponse); } } if (luisresponse != null) { var qnaresponse = Utils.GetQnAAnswerFromResponse(luisresponse); if (previousAnswer == null || !qnaresponse.IsEqual(previousAnswer)) { return(qnaresponse); } } return(null); }
private async Task ShowQnAResponseWithText(ITurnContext turnContext, QnAMakerAnswer qnaresponse, ShowQnAResultState qnastatus, CancellationToken cancellationToken = default(CancellationToken)) { qnastatus.ConsiderState = true; if (!qnaresponse.IsChitChat) { qnastatus.NeuroconCount = 0; } else { qnastatus.NeuroconCount++; } qnastatus.QnaAnswer = qnaresponse; if (qnaresponse.Flowtype == Constants.MetadataValue.Feedback) { qnastatus.IsFeedback = true; } else { qnastatus.IsFeedback = false; } await _accessors.QnAResultState.SetAsync(turnContext, qnastatus); await _accessors.ConversationState.SaveChangesAsync(turnContext); await turnContext.SendActivityAsync(qnaresponse.Text); if (!string.IsNullOrEmpty(qnaresponse.Requery) && !qnastatus.IsFeedback) { var showNextResponseText = true; var counter = 0; while (showNextResponseText) { turnContext.Activity.Text = qnaresponse.Requery; qnastatus = await _accessors.QnAResultState.GetAsync(turnContext, () => new ShowQnAResultState()); var response = await GetMultiturnResponseFromKB(turnContext, qnastatus.QnaAnswer); if (response == null) { showNextResponseText = false; } else { qnaresponse = Utils.GetQnAAnswerFromResponse(response); if (qnaresponse == qnastatus.QnaAnswer) { break; } if (qnaresponse.Options != null && qnaresponse.Options.Count != 0) { qnastatus.ConsiderState = true; qnastatus.QnaAnswer = qnaresponse; qnastatus.NeuroconCount = 0; if (qnaresponse.Flowtype == Constants.MetadataValue.Feedback) { qnastatus.IsFeedback = true; } else { qnastatus.IsFeedback = false; } await _accessors.QnAResultState.SetAsync(turnContext, qnastatus); await _accessors.ConversationState.SaveChangesAsync(turnContext); var cardActivity = Utils.GenerateResponseOptions(qnaresponse); await turnContext.SendActivityAsync(cardActivity, cancellationToken); showNextResponseText = false; } else { qnastatus.ConsiderState = true; qnastatus.QnaAnswer = qnaresponse; if (!qnaresponse.IsChitChat) { qnastatus.NeuroconCount = 0; } else { qnastatus.NeuroconCount++; } if (qnaresponse.Flowtype == Constants.MetadataValue.Feedback) { qnastatus.IsFeedback = true; } else { qnastatus.IsFeedback = false; } await _accessors.QnAResultState.SetAsync(turnContext, qnastatus); await _accessors.ConversationState.SaveChangesAsync(turnContext); await turnContext.SendActivityAsync(qnaresponse.Text); } counter++; if (counter > Constants.MaxContinuousTextDialogs || qnastatus.IsFeedback || qnastatus.QnaAnswer.Requery == null || qnastatus.NeuroconCount > Constants.ConsecutiveNeuroconAnswersAllowed) { showNextResponseText = false; } } } } }
private async Task <QueryResult> GetMultiturnResponseFromKB(ITurnContext turnContext, QnAMakerAnswer previousAnswer, CancellationToken cancellationToken = default(CancellationToken)) { if (previousAnswer == null || string.IsNullOrEmpty(previousAnswer.Name)) { return(null); } var qnaOptions = new QnAMakerOptions(); var metadata = new Microsoft.Bot.Builder.AI.QnA.Metadata(); metadata.Name = Constants.MetadataName.Parent; metadata.Value = previousAnswer.Name; qnaOptions.StrictFilters = new Microsoft.Bot.Builder.AI.QnA.Metadata[] { metadata }; qnaOptions.Top = Constants.DefaultTop; qnaOptions.ScoreThreshold = Constants.MultiturnThreshold; var response = await _services.QnAServices[QnAMakerKey].GetAnswersAsync(turnContext, qnaOptions); if (response != null && response.GetLength(0) != 0 && response[0].Score >= Constants.MultiturnThreshold) { return(response[0]); } return(null); }