// Handle message activity in 1:1 chat private async Task OnMessageActivityInPersonalChatAsync(IMessageActivity message, ITurnContext <IMessageActivity> turnContext, CancellationToken cancellationToken) { if (!string.IsNullOrEmpty(message.ReplyToId) && (message.Value != null) && ((JObject)message.Value).HasValues) { this.telemetryClient.TrackTrace("Card submit in 1:1 chat"); await this.OnAdaptiveCardSubmitInPersonalChatAsync(message, turnContext, cancellationToken); return; } string text = (message.Text ?? string.Empty).Trim().ToLower(); switch (text) { case AskAnExpert: this.telemetryClient.TrackTrace("Sending user ask an expert card"); await turnContext.SendActivityAsync(MessageFactory.Attachment(AskAnExpertCard.GetCard())); break; case ShareFeedback: this.telemetryClient.TrackTrace("Sending user feedback card"); await turnContext.SendActivityAsync(MessageFactory.Attachment(ShareFeedbackCard.GetCard())); break; case TakeATour: this.telemetryClient.TrackTrace("Sending user tour card"); var userTourCards = TourCarousel.GetUserTourCards(this.appBaseUri); await turnContext.SendActivityAsync(MessageFactory.Carousel(userTourCards)); break; default: this.telemetryClient.TrackTrace("Sending input to QnAMaker"); var queryResult = await this.GetAnswerFromQnAMakerAsync(text, turnContext, cancellationToken); if (queryResult != null) { string answer = this.ReplaceWildCard(message, turnContext, queryResult.Answer); await turnContext.SendActivityAsync(MessageFactory.Attachment(ResponseCard.GetCard(queryResult.Questions[0], answer, queryResult.Source, text))); } else { await turnContext.SendActivityAsync(MessageFactory.Attachment(UnrecognizedInputCard.GetCard(text))); } // Save conversation var saveConversations = await this.configurationProvider.GetSavedEntityDetailAsync(ConfigurationEntityTypes.SaveConversations); if (bool.Parse(saveConversations)) { var userDetails = await this.GetUserDetailsInPersonalChatAsync(turnContext, cancellationToken); ConversationEntity newConversation = await this.CreateConversationAsync(message, queryResult, userDetails); } break; } }
// Handle message activity in 1:1 chat private async Task OnMessageActivityInPersonalChatAsync(IMessageActivity message, ITurnContext <IMessageActivity> turnContext, CancellationToken cancellationToken) { if (!string.IsNullOrEmpty(message.ReplyToId) && (message.Value != null) && ((JObject)message.Value).HasValues) { this.telemetryClient.TrackTrace("Card submit in 1:1 chat"); await this.OnAdaptiveCardSubmitInPersonalChatAsync(message, turnContext, cancellationToken); return; } string text = (message.Text ?? string.Empty).Trim().ToLower(); if (text.Equals(Resource.ResourceManager.GetString("AskAnExpertDisplayText", CultureInfo.CurrentCulture), StringComparison.InvariantCultureIgnoreCase)) { this.telemetryClient.TrackTrace("Sending user ask an expert card"); await turnContext.SendActivityAsync(MessageFactory.Attachment(AskAnExpertCard.GetCard())); } else if (text.Equals(Resource.ResourceManager.GetString("ShareFeedbackDisplayText", CultureInfo.CurrentCulture), StringComparison.InvariantCultureIgnoreCase)) { this.telemetryClient.TrackTrace("Sending user feedback card"); await turnContext.SendActivityAsync(MessageFactory.Attachment(ShareFeedbackCard.GetCard())); } else if (text.Equals(Resource.ResourceManager.GetString("TakeATourButtonText", CultureInfo.CurrentCulture), StringComparison.InvariantCultureIgnoreCase)) { this.telemetryClient.TrackTrace("Sending user tour card"); var userTourCards = TourCarousel.GetUserTourCards(this.appBaseUri); await turnContext.SendActivityAsync(MessageFactory.Carousel(userTourCards)); } else { this.telemetryClient.TrackTrace("Sending input to QnAMaker"); var queryResult = await this.GetAnswerFromQnAMakerAsync(text, turnContext, cancellationToken); if (queryResult != null) { this.telemetryClient.TrackTrace("Sending user QnAMaker card"); await turnContext.SendActivityAsync(MessageFactory.Attachment(ResponseCard.GetCard(queryResult.Questions[0], queryResult.Answer, text))); } else { var tileList = await this.MatchTagsWithMessageAsync(text); if (tileList != null) { this.telemetryClient.TrackTrace("Sending user tags card"); await turnContext.SendActivityAsync(SuggestedLinkCard.GetTagsCarouselCards(text, tileList, Resource.CustomMessage)); } else { this.telemetryClient.TrackTrace("Sending user with no matched tags result"); await turnContext.SendActivityAsync(MessageFactory.Attachment(UnrecognizedInputCard.GetCard(text, Resource.NoMatchedTagsMessage))); } } } }
// Handle message activity in 1:1 chat private async Task OnMessageActivityInPersonalChatAsync(IMessageActivity message, ITurnContext <IMessageActivity> turnContext, CancellationToken cancellationToken) { if (!string.IsNullOrEmpty(message.ReplyToId) && (message.Value != null) && ((JObject)message.Value).HasValues) { this.telemetryClient.TrackTrace("Card submit in 1:1 chat"); await this.OnAdaptiveCardSubmitInPersonalChatAsync(message, turnContext, cancellationToken); return; } string text = (message.Text ?? string.Empty).Trim().ToLower(); this.telemetryClient.TrackTrace($"Se ha enviado esta solicitud: {text}"); switch (text) { case AskAnExpert: this.telemetryClient.TrackTrace("Sending user ask an expert card"); await turnContext.SendActivityAsync(MessageFactory.Attachment(AskAnExpertCard.GetCard())); break; case ShareFeedback: this.telemetryClient.TrackTrace("Sending user feedback card"); await turnContext.SendActivityAsync(MessageFactory.Attachment(ShareFeedbackCard.GetCard())); break; case TakeATour: this.telemetryClient.TrackTrace("Sending user tour card"); var userTourCards = TourCarousel.GetUserTourCards(this.appBaseUri); await turnContext.SendActivityAsync(MessageFactory.Carousel(userTourCards)); break; case WelcomeMsg: this.telemetryClient.TrackTrace("The user as required the Welcome screen"); var welcomeText = await this.configurationProvider.GetSavedEntityDetailAsync(ConfigurationEntityTypes.WelcomeMessageText); var userWelcomeCardAttachment = WelcomeCard.GetCard(welcomeText); var userWelcomeCardAttachment2 = WelcomeCardPreguntas.GetCard(Resource.WelcomeTeamCardContent); await turnContext.SendActivityAsync(MessageFactory.Attachment(userWelcomeCardAttachment)); await turnContext.SendActivityAsync(MessageFactory.Attachment(userWelcomeCardAttachment2)); break; default: this.telemetryClient.TrackTrace("Sending input to QnAMaker"); var queryResult = await this.GetAnswerFromQnAMakerAsync(text, turnContext, cancellationToken); if (queryResult != null) { this.telemetryClient.TrackTrace("Sending user QnAMaker card"); await turnContext.SendActivityAsync(MessageFactory.Attachment(ResponseCard.GetCard(queryResult.Questions[0], queryResult.Answer, text))); } else { var tileList = await this.MatchTagsWithMessageAsync(text); if (tileList != null) { this.telemetryClient.TrackTrace("Sending user tags card"); await turnContext.SendActivityAsync(SuggestedLinkCard.GetTagsCarouselCards(text, tileList, Resource.CustomMessage)); } else { this.telemetryClient.TrackTrace("Sending user with no matched tags result"); await turnContext.SendActivityAsync(MessageFactory.Attachment(UnrecognizedInputCard.GetCard(text, Resource.NoMatchedTagsMessage))); } } break; } }
/// <summary> /// Get the reply to a question asked by end user. /// </summary> /// <param name="turnContext">Context object containing information cached for a single turn of conversation with a user.</param> /// <param name="message">Text message.</param> /// <returns>A task that represents the work queued to execute.</returns> private async Task GetQuestionAnswerReplyAsync( ITurnContext turnContext, IMessageActivity message) { string text = message.Text?.ToLower()?.Trim() ?? string.Empty; try { var queryResult = new QnASearchResultList(); ResponseCardPayload payload = new ResponseCardPayload(); if (!string.IsNullOrEmpty(message.ReplyToId) && (message.Value != null)) { payload = ((JObject)message.Value).ToObject <ResponseCardPayload>(); } queryResult = await _qnaServiceProvider.GenerateAnswerAsync(question : text, isTestKnowledgeBase : false, payload.PreviousQuestions?.First().Id.ToString(), payload.PreviousQuestions?.First().Questions.First()).ConfigureAwait(false); if (queryResult.Answers.First().Id != -1) { var answerData = queryResult.Answers.First(); payload.QnaPairId = answerData.Id ?? -1; AnswerModel answerModel = new AnswerModel(); if (Validators.IsValidJSON(answerData.Answer)) { answerModel = JsonConvert.DeserializeObject <AnswerModel>(answerData.Answer); } if (!string.IsNullOrEmpty(answerModel?.Title) || !string.IsNullOrEmpty(answerModel?.Subtitle) || !string.IsNullOrEmpty(answerModel?.ImageUrl) || !string.IsNullOrEmpty(answerModel?.RedirectionUrl)) { await turnContext.SendActivityAsync(MessageFactory.Attachment(MessagingExtensionQnaCard.GetEndUserRichCard(text, answerData, payload.QnaPairId))).ConfigureAwait(false); } else { await turnContext.SendActivityAsync(MessageFactory.Attachment(ResponseCard.GetCard(answerData, text, _appBaseUri, payload))).ConfigureAwait(false); } _telemetryClient.TrackEvent( FaqPlusPlusBot.EVENT_ANSWERED_QUESTION_SINGLE, new Dictionary <string, string> { { "QuestionId", payload.QnaPairId.ToString() }, { "QuestionAnswered", queryResult.Answers[0].Questions[0] }, { "QuestionAsked", text }, { "UserName", turnContext.Activity.From.Name }, { "UserAadId", turnContext.Activity.From?.AadObjectId ?? "" }, { "Product", _options.ProductName }, }); } else { await turnContext.SendActivityAsync(MessageFactory.Attachment(UnrecognizedInputCard.GetCard(text))).ConfigureAwait(false); } } catch (Exception ex) { // Check if knowledge base is empty and has not published yet when end user is asking a question to bot. if (((Azure.CognitiveServices.Knowledge.QnAMaker.Models.ErrorResponseException)ex).Response.StatusCode == HttpStatusCode.BadRequest) { var knowledgeBaseId = await _configurationProvider.GetSavedEntityDetailAsync(Constants.KnowledgeBaseEntityId).ConfigureAwait(false); var hasPublished = await _qnaServiceProvider.GetInitialPublishedStatusAsync(knowledgeBaseId).ConfigureAwait(false); // Check if knowledge base has not published yet. if (!hasPublished) { this._telemetryClient.TrackException(ex, new Dictionary <string, string> { { "message", "Error while fetching the qna pair: knowledge base may be empty or it has not published yet." }, }); await turnContext.SendActivityAsync(MessageFactory.Attachment(UnrecognizedInputCard.GetCard(text))).ConfigureAwait(false); return; } } // Throw the error at calling place, if there is any generic exception which is not caught. throw; } }
/// <summary> /// Get the reply to a question asked by end user. /// </summary> /// <param name="turnContext">Context object containing information cached for a single turn of conversation with a user.</param> /// <param name="message">Text message.</param> /// <returns>A task that represents the work queued to execute.</returns> public async Task GetReplyToQnAAsync( ITurnContext<IMessageActivity> turnContext, IMessageActivity message) { string text = message.Text?.ToLower()?.Trim() ?? string.Empty; try { var queryResult = new QnASearchResultList(); ResponseCardPayload payload = new ResponseCardPayload(); if (!string.IsNullOrEmpty(message.ReplyToId) && (message.Value != null)) { payload = ((JObject)message.Value).ToObject<ResponseCardPayload>(); } queryResult = await this.qnaServiceProvider.GenerateAnswerAsync(question: text, isTestKnowledgeBase: false, payload.PreviousQuestions?.Last().Id.ToString(), payload.PreviousQuestions?.Last().Questions.First()).ConfigureAwait(false); bool answerFound = false; foreach (QnASearchResult answerData in queryResult.Answers) { bool isContextOnly = answerData.Context?.IsContextOnly ?? false; if (answerData.Id != -1 && ((!isContextOnly && payload.PreviousQuestions == null) || (isContextOnly && payload.PreviousQuestions != null))) { // This is the expected answer await turnContext.SendActivityAsync(MessageFactory.Attachment(ResponseCard.GetCard(answerData, text, this.appBaseUri, payload))).ConfigureAwait(false); answerFound = true; break; } } if (!answerFound) { await turnContext.SendActivityAsync(MessageFactory.Attachment(UnrecognizedInputCard.GetCard(text))).ConfigureAwait(false); } } catch (Exception ex) { // Check if knowledge base is empty and has not published yet when end user is asking a question to bot. if (((ErrorResponseException)ex).Response.StatusCode == System.Net.HttpStatusCode.BadRequest) { var knowledgeBaseId = await this.configurationProvider.GetSavedEntityDetailAsync(Constants.KnowledgeBaseEntityId).ConfigureAwait(false); var hasPublished = await this.qnaServiceProvider.GetInitialPublishedStatusAsync(knowledgeBaseId).ConfigureAwait(false); // Check if knowledge base has not published yet. if (!hasPublished) { this.logger.LogError(ex, "Error while fetching the qna pair: knowledge base may be empty or it has not published yet."); await turnContext.SendActivityAsync(MessageFactory.Attachment(UnrecognizedInputCard.GetCard(text))).ConfigureAwait(false); return; } } // Throw the error at calling place, if there is any generic exception which is not caught. throw; } }
// Handle message activity in 1:1 chat private async Task OnMessageActivityInPersonalChatAsync(IMessageActivity message, ITurnContext <IMessageActivity> turnContext, CancellationToken cancellationToken) { if (!string.IsNullOrEmpty(message.ReplyToId) && (message.Value != null) && ((JObject)message.Value).HasValues) { this.telemetryClient.TrackTrace("Card submit in 1:1 chat"); await this.OnAdaptiveCardSubmitInPersonalChatAsync(message, turnContext, cancellationToken); return; } string text = (message.Text ?? string.Empty).Trim().ToLower(); switch (text) { case AskAnExpert: this.telemetryClient.TrackTrace("Mandando tarjeta pregunta a un experto al usuario"); await turnContext.SendActivityAsync(MessageFactory.Attachment(AskAnExpertCard.GetCard())); break; case ShareFeedback: this.telemetryClient.TrackTrace("Sending user feedback card"); await turnContext.SendActivityAsync(MessageFactory.Attachment(ShareFeedbackCard.GetCard())); break; case TakeATour: this.telemetryClient.TrackTrace("Sending user tour card"); var userTourCards = TourCarousel.GetUserTourCards(this.appBaseUri); await turnContext.SendActivityAsync(MessageFactory.Carousel(userTourCards)); break; default: this.telemetryClient.TrackTrace("Sending input to QnAMaker"); var queryResult = await this.GetAnswerFromQnAMakerAsync(text, turnContext, cancellationToken); if (queryResult != null) { this.telemetryClient.TrackTrace("Sending user QnAMaker card"); await turnContext.SendActivityAsync(MessageFactory.Attachment(ResponseCard.GetCard(queryResult.Questions[0], queryResult.Answer, text))); } else { var tileList = await this.MatchTagsWithMessageAsync(text); if (tileList != null) { this.telemetryClient.TrackTrace("Sending user tags card"); await turnContext.SendActivityAsync(SuggestedLinkCard.GetTagsCarouselCards(text, tileList, Resource.CustomMessage)); } else { this.telemetryClient.TrackTrace("Sending user with no matched tags result"); await turnContext.SendActivityAsync(MessageFactory.Attachment(UnrecognizedInputCard.GetCard(text, Resource.NoMatchedTagsMessage))); } } break; } }
/// <summary> /// Get the reply to a question asked by end user. /// </summary> /// <param name="turnContext">Context object containing information cached for a single turn of conversation with a user.</param> /// <param name="message">Text message.</param> /// <returns>A task that represents the work queued to execute.</returns> private async Task GetQuestionAnswerReplyAsync( ITurnContext <IMessageActivity> turnContext, IMessageActivity message) { string text = message.Text?.ToLower()?.Trim() ?? string.Empty; try { var queryResult = new QnASearchResultList(); ResponseCardPayload payload = new ResponseCardPayload(); if (!string.IsNullOrEmpty(message.ReplyToId) && (message.Value != null)) { payload = ((JObject)message.Value).ToObject <ResponseCardPayload>(); } queryResult = await this.qnaServiceProvider.GenerateAnswerAsync(question : text, isTestKnowledgeBase : false, payload.PreviousQuestions?.First().Id.ToString(), payload.PreviousQuestions?.First().Questions.First()).ConfigureAwait(false); if (queryResult.Answers.First().Id != -1) { var answerData = queryResult.Answers.First(); AnswerModel answerModel = new AnswerModel(); if (Validators.IsValidJSON(answerData.Answer)) { answerModel = JsonConvert.DeserializeObject <AnswerModel>(answerData.Answer); } if (!string.IsNullOrEmpty(answerModel?.Title) || !string.IsNullOrEmpty(answerModel?.Subtitle) || !string.IsNullOrEmpty(answerModel?.ImageUrl) || !string.IsNullOrEmpty(answerModel?.RedirectionUrl)) { await turnContext.SendActivityAsync(MessageFactory.Attachment(MessagingExtensionQnaCard.GetEndUserRichCard(text, answerData))).ConfigureAwait(false); } else { await turnContext.SendActivityAsync(MessageFactory.Attachment(ResponseCard.GetCard(answerData, text, this.appBaseUri, payload))).ConfigureAwait(false); } } else { await turnContext.SendActivityAsync(MessageFactory.Attachment(UnrecognizedInputCard.GetCard(text))).ConfigureAwait(false); } } catch (Exception ex) { // Check if knowledge base is empty and has not published yet when end user is asking a question to bot. if (((ErrorResponseException)ex).Response.StatusCode == HttpStatusCode.BadRequest) { var knowledgeBaseId = await this.configurationProvider.GetSavedEntityDetailAsync(Constants.KnowledgeBaseEntityId).ConfigureAwait(false); var hasPublished = await this.qnaServiceProvider.GetInitialPublishedStatusAsync(knowledgeBaseId).ConfigureAwait(false); // Check if knowledge base has not published yet. if (!hasPublished) { this.logger.LogError(ex, "Error while fetching the qna pair: knowledge base may be empty or it has not published yet."); await turnContext.SendActivityAsync(MessageFactory.Attachment(UnrecognizedInputCard.GetCard(text))).ConfigureAwait(false); return; } } // Throw the error at calling place, if there is any generic exception which is not caught. throw; } }