/// <inheritdoc/> public Attachment CreateSuggestAnswerMessage(Question question, SuggestedAnswer suggestedAnswer) { var data = new { suggestedAnswer = new { id = suggestedAnswer.Id, message = suggestedAnswer.Answer, }, question = new { id = question.Id, }, text = new { helpful = this.localizer.GetString("helpful").Value, notHelpful = this.localizer.GetString("notHelpful").Value, confidence = this.localizer.GetString("confidence", suggestedAnswer.Score).Value, }, }; var template = this.GetCardTemplate(SuggestAnswerTemplatePath); var serializedJson = template.Expand(data); return(this.CreateAttachment(serializedJson)); }
/// <inheritdoc/> public async Task <Answer> PostSuggestedAnswerAsync(Answer answer, SuggestedAnswer suggestedAnswer) { if (!this.answerValidator.IsValid(answer)) { throw new QBotException(HttpStatusCode.BadRequest, ErrorCode.InvalidAnswer, "Invalid answer object"); } if (suggestedAnswer is null) { throw new ArgumentNullException(nameof(suggestedAnswer)); } // Fetch question. var question = await this.GetQuestionAsync(answer.CourseId, answer.ChannelId, answer.QuestionId); question.AnswerId = answer.Id; // Store answer and updated question. await this.questionRespository.AddAnswerAsync(answer); await this.questionRespository.UpdateQuestionAsync(question); var userIds = new HashSet <string> { answer.AcceptedById, question.AuthorId, }; var users = await this.userReaderService.GetUsersAsync(userIds, false /*fetchProfilePic*/); // Update existing answer. await this.teamsMessageService.PostCorrectAnswerAsync(question, answer, users); // Notify question author if the question is not accepted by the author. if (answer.AcceptedById != question.AuthorId) { var course = await this.courseReader.GetCourseAsync(answer.CourseId); var channel = await this.courseReader.GetChannelAsync(answer.CourseId, answer.ChannelId); await this.NotifyQuestionAuthorAsync(course, channel, question, answer); } try { // Update QnA Service. await this.qnAService.UpdateQnAPairAsync(question, suggestedAnswer); } catch (QBotException exception) { this.logger.LogWarning(exception, "Failed to update QnA Pair."); } return(answer); }
/// <inheritdoc/> public async Task UpdateQnAPairAsync(Question question, SuggestedAnswer suggestedAnswer) { if (question is null) { throw new ArgumentNullException(nameof(question)); } if (suggestedAnswer is null) { throw new ArgumentNullException(nameof(suggestedAnswer)); } var dto = new UpdateQnaDTO() { Id = suggestedAnswer.Id, Questions = new UpdateQnaDTOQuestions() { Add = new List <string>() { question.GetSanitizedMessage() }, }, }; var operation = new UpdateKbOperationDTO() { Update = new UpdateKbOperationDTOUpdate() { QnaList = new List <UpdateQnaDTO>() { dto }, }, }; try { var response = await this.qnAClient.Knowledgebase.UpdateAsync(this.settings.KnowledgeBaseId, operation); } catch (ErrorResponseException exception) { var message = $"Failed to update QnA Pair to QnA Service. Question Id: {question.Id}, QnAPair Id : {suggestedAnswer.Id}."; this.logger.LogWarning(exception, message); throw new QBotException(HttpStatusCode.InternalServerError, ErrorCode.Unknown, message, exception); } }
/// <inheritdoc/> public async Task <string> PostSuggestAnswerAsync(Question question, SuggestedAnswer suggestedAnswer) { if (question is null) { throw new ArgumentNullException(nameof(question)); } if (suggestedAnswer is null) { throw new ArgumentNullException(nameof(suggestedAnswer)); } var conversationId = this.GetConversationId(question.ChannelId, question.MessageId); var attachment = this.messageFactory.CreateSuggestAnswerMessage(question, suggestedAnswer); var messageActivity = MessageFactory.Attachment(attachment); messageActivity.Summary = suggestedAnswer.Answer; return(await this.PostMessageAsync(conversationId, messageActivity)); }
private async Task SuggestAnswerActionAsync(ITurnContext <IMessageActivity> turnContext) { var valueObject = JObject.Parse(turnContext.Activity.Value.ToString()); valueObject.TryGetValue("questionId", out var questionId); valueObject.TryGetValue("action", out var action); valueObject.TryGetValue("suggestedAnswerMessage", out var answerMessage); var courseId = turnContext.Activity.TeamsGetTeamInfo().Id; var channelId = turnContext.Activity.TeamsGetChannelId(); var messageId = turnContext.Activity.ReplyToId; // Fetch Question. if (BotConstants.HelpfulActionText.Equals(action?.ToString(), StringComparison.InvariantCultureIgnoreCase)) { valueObject.TryGetValue("suggestedAnswerId", out var suggestedAnswerId); // Post answer. var answer = new Answer { CourseId = courseId, ChannelId = channelId, AcceptedById = turnContext.Activity.From.AadObjectId, AuthorId = turnContext.Activity.Recipient.Id, MessageId = messageId, Id = messageId, QuestionId = questionId.ToString(), TimeStamp = turnContext.Activity.Timestamp.Value, Message = answerMessage.ToString(), }; // Suggested Answer var suggestedAnswer = new SuggestedAnswer() { Answer = answerMessage.ToString(), Id = int.Parse(suggestedAnswerId.ToString(), CultureInfo.InvariantCulture), }; await this.qBotService.PostSuggestedAnswerAsync(answer, suggestedAnswer); } else if (BotConstants.NotHelpfulActionText.Equals(action?.ToString(), StringComparison.InvariantCultureIgnoreCase)) { // Prepare suggested answer object. var answer = new Answer { CourseId = courseId, ChannelId = channelId, AcceptedById = turnContext.Activity.From.AadObjectId, AuthorId = turnContext.Activity.Recipient.Id, MessageId = messageId, Id = messageId, QuestionId = questionId.ToString(), TimeStamp = turnContext.Activity.Timestamp.Value, Message = answerMessage.ToString(), }; await this.qBotService.MarkSuggestedAnswerNotHelpfulAsync(answer, answer.AcceptedById); } else { this.logger.LogWarning($"Unexpected action type: {action?.ToString()}"); } }