/// <summary> /// Initializes a new instance of the <see cref="PublishFunction"/> class. /// </summary> /// <param name="qnaServiceProvider">Qna service provider.</param> /// <param name="configurationProvider">Configuration service provider.</param> /// <param name="searchServiceDataProvider">Search service data provider.</param> /// <param name="knowledgeBaseSearchService">Knowledgebase search service.</param> public PublishFunction(IQnaServiceProvider qnaServiceProvider, IConfigurationDataProvider configurationProvider, ISearchServiceDataProvider searchServiceDataProvider, IKnowledgeBaseSearchService knowledgeBaseSearchService) { this.qnaServiceProvider = qnaServiceProvider; this.configurationProvider = configurationProvider; this.searchServiceDataProvider = searchServiceDataProvider; this.knowledgeBaseSearchService = knowledgeBaseSearchService; }
/// <summary> /// Initializes a new instance of the <see cref="CrowdSourcerBot"/> class. /// </summary> /// <param name="telemetryClient">telemetry client.</param> /// <param name="qnaServiceProvider">qnA maker service provider.</param> /// <param name="microsoftAppCredentials">app credentials.</param> /// <param name="configuration">configuration settings.</param> /// <param name="messagingExtensionQueryHandler">messaging extension.</param> /// <param name="storageProvider">storage provider.</param> public CrowdSourcerBot(TelemetryClient telemetryClient, IQnaServiceProvider qnaServiceProvider, IConfiguration configuration, IStorageProvider storageProvider) { this.telemetryClient = telemetryClient; this.qnaServiceProvider = qnaServiceProvider; this.configuration = configuration; this.storageProvider = storageProvider; }
/// <summary> /// Initializes a new instance of the <see cref="PublishFunction"/> class. /// </summary> /// <param name="searchServiceDataProvider">search service data provider.</param> /// <param name="qnaServiceProvider">qna service provider.</param> /// <param name="configurationStorageProvider">configuration storage provider.</param> /// <param name="searchService">search service.</param> public PublishFunction(IConfigurationStorageProvider configurationStorageProvider, IQnaServiceProvider qnaServiceProvider, ISearchServiceDataProvider searchServiceDataProvider, ISearchService searchService) { this.configurationStorageProvider = configurationStorageProvider; this.qnaServiceProvider = qnaServiceProvider; this.searchServiceDataProvider = searchServiceDataProvider; this.searchService = searchService; }
/// <summary> /// Initializes a new instance of the <see cref="QuestionController"/> class. /// </summary> /// <param name="configurationProvider"></param> /// <param name="qnaServiceProvider"></param> /// <param name="imageStorageProvider"></param> /// <param name="optionsAccessor"></param> public QuestionController(IConfigurationDataProvider configurationProvider, IQnaServiceProvider qnaServiceProvider, IImageStorageProvider imageStorageProvider, IOptionsMonitor <BotSettings> optionsAccessor) { this.configurationProvider = configurationProvider; this.qnaServiceProvider = qnaServiceProvider; this.imageStorageProvider = imageStorageProvider; this.options = optionsAccessor.CurrentValue; this.appId = this.options.MicrosoftAppId; }
/// <summary> /// Initializes a new instance of the <see cref="CrowdSourcerBot"/> class. /// </summary> /// <param name="telemetryClient">telemetry client.</param> /// <param name="qnaServiceProvider">qnA maker service provider.</param> /// <param name="configuration">configuration settings.</param> /// <param name="configurationStorageProvider">Knowledge base configuration storage provider.</param> /// <param name="nameMappingStorageProvider">name mapping storage provider.</param> /// <param name="searchService">serach service.</param> /// <param name="cards">all cards.</param> public CrowdSourcerBot(TelemetryClient telemetryClient, IQnaServiceProvider qnaServiceProvider, IConfiguration configuration, IConfigurationStorageProvider configurationStorageProvider, IObjectIdToNameMapper nameMappingStorageProvider, ISearchService searchService, CrowdSourcerCards cards) { this.telemetryClient = telemetryClient; this.qnaServiceProvider = qnaServiceProvider; this.configuration = configuration; this.configurationStorageProvider = configurationStorageProvider; this.nameMappingStorageProvider = nameMappingStorageProvider; this.searchService = searchService; this.cards = cards; }
/// <summary> /// Initializes a new instance of the <see cref="TaskModuleActivity"/> class. /// </summary> /// <param name="configurationProvider">Configuration Provider.</param> /// <param name="qnaServiceProvider">QnA service provider.</param> /// <param name="logger">Instance to send logs to the Application Insights service.</param> /// <param name="qnaPairServiceFacade">Instance of QnA pair service class to call add/update/get QnA pair.</param> public TaskModuleActivity( Common.Providers.IConfigurationDataProvider configurationProvider, IQnaServiceProvider qnaServiceProvider, ILogger <TaskModuleActivity> logger, IQnAPairServiceFacade qnaPairServiceFacade) { this.configurationProvider = configurationProvider ?? throw new ArgumentNullException(nameof(configurationProvider)); this.qnaServiceProvider = qnaServiceProvider ?? throw new ArgumentNullException(nameof(qnaServiceProvider)); this.logger = logger ?? throw new ArgumentNullException(nameof(logger)); this.qnaPairServiceFacade = qnaPairServiceFacade ?? throw new ArgumentNullException(nameof(qnaPairServiceFacade)); }
/// <summary> /// Checks whether question exist in production/test knowledgebase. /// </summary> /// <param name="provider">Qna service provider.</param> /// <param name="question">Question.</param> /// <returns>A <see cref="Task"/> of type bool where true represents question is already exist in knowledgebase while false indicates the question does not exist in knowledgebase.</returns> public static async Task <bool> QuestionExistsInKbAsync(this IQnaServiceProvider provider, string question) { var prodHasQuestion = await provider.HasQuestionAsync(question, isTestKnowledgeBase : false).ConfigureAwait(false); if (prodHasQuestion) { return(true); } return(await provider.HasQuestionAsync(question, isTestKnowledgeBase : true).ConfigureAwait(false)); }
public async Task <ActionResult> SaveLanguageKbConfigurationDetails(LanguageKbConfigurationViewModel item) { string teamIdAfterParse = ParseTeamIdFromDeepLink(item.TeamId ?? string.Empty); if (string.IsNullOrWhiteSpace(teamIdAfterParse)) { return(new HttpStatusCodeResult(HttpStatusCode.BadRequest, "The provided team id is not valid.")); } else { // Get bot supported languages from web.config. var languageQnAMakerSubscriptionKeyJson = ConfigurationManager.AppSettings["LanguageQnAMakerSubscriptionKeyJson"]; var languageQnAMakerKeyCombinations = JsonConvert.DeserializeObject <List <LanguageQnAMakerKeyCombination> >(languageQnAMakerSubscriptionKeyJson); var supportedLanguages = from languageQnAMakerKeyCombination in languageQnAMakerKeyCombinations select new BotLanguageDetail { Code = languageQnAMakerKeyCombination.LanguageCode, Default = languageQnAMakerKeyCombination.Default, Name = languageQnAMakerKeyCombination.LanguageName }; // Save the bot supported language details to table storage. await this.configurationProvider.UpsertEntityAsync(JsonConvert.SerializeObject(supportedLanguages), ConfigurationEntityTypes.SupportedLanguagesKey).ConfigureAwait(false); LanguageQnAMakerKeyCombination langQnaDetails = languageQnAMakerKeyCombinations.FirstOrDefault(x => x.LanguageCode == item.LanguageCode); IQnaServiceProvider applicableQnaServiceProvider = this.qnaServiceProviders.FirstOrDefault(qsp => qsp.GetApplicableLanguageCode().Equals(item.LanguageCode)); bool isValidKnowledgeBaseId = await applicableQnaServiceProvider.IsKnowledgeBaseIdValid(item.KnowledgeBaseId).ConfigureAwait(false); if (isValidKnowledgeBaseId) { LanguageKBConfigurationEntity langKBConfigEntity = new LanguageKBConfigurationEntity(); langKBConfigEntity.TeamId = teamIdAfterParse; langKBConfigEntity.KnowledgeBaseId = item.KnowledgeBaseId; langKBConfigEntity.ChangeLanguageMessageText = item.WelcomeMessage; langKBConfigEntity.HelpTabText = item.HelpTabText; langKBConfigEntity.PartitionKey = "LanguageKBConfiguration"; langKBConfigEntity.QnaMakerEndpointKey = langQnaDetails.QnAMakerSubscriptionKey; langKBConfigEntity.RowKey = item.LanguageCode; bool isSaved = await this.configurationProvider.UpsertLanguageKBConfigurationEntityAsync(item.LanguageCode, langKBConfigEntity); if (isSaved) { return(new HttpStatusCodeResult(HttpStatusCode.OK)); } else { return(new HttpStatusCodeResult(HttpStatusCode.InternalServerError, "Sorry, unable to save the team id due to an internal error. Try again.")); } } else { return(new HttpStatusCodeResult(HttpStatusCode.BadRequest, "The provided knowledgebase id is not valid.")); } } }
/// <summary> /// Initializes a new instance of the <see cref="FaqPlusPlusBot"/> class. /// </summary> /// <param name="configurationProvider">Configuration Provider.</param> /// <param name="microsoftAppCredentials">Microsoft app credentials to use.</param> /// <param name="ticketsProvider">Tickets Provider.</param> /// <param name="qnaServiceProvider">Question and answer maker service provider.</param> /// <param name="optionsAccessor">A set of key/value application configuration properties for FaqPlusPlus bot.</param> /// <param name="logger">Instance to send logs to the Application Insights service.</param> /// <param name="smeBot">Instance of SME bot to handle actions on old cards sent with old bot version.</param> public UserActivityHandler( IConfigurationDataProvider configurationProvider, MicrosoftAppCredentials microsoftAppCredentials, ITicketsProvider ticketsProvider, IQnaServiceProvider qnaServiceProvider, IOptionsMonitor <BotSettings> optionsAccessor, ILogger <UserActivityHandler> logger, SmeActivityHandler smeBot) : base(configurationProvider, microsoftAppCredentials, ticketsProvider, qnaServiceProvider, optionsAccessor.CurrentValue, logger) { this.smeBot = smeBot; this.expertTeamNameCache = new MemoryCacheWithPolicy <string>(); }
/// <summary> /// Checks whether question exist in knowledgebase. /// </summary> /// <param name="provider">Qna service provider.</param> /// <param name="question">Question.</param> /// <param name="isTestKnowledgeBase">Knowledgebase.</param> /// <returns>A <see cref="Task"/> of type bool where true represents question is already exist in knowledgebase while false indicates the question does not exist in knowledgebase.</returns> private static async Task <bool> HasQuestionAsync(this IQnaServiceProvider provider, string question, bool isTestKnowledgeBase) { var qnaPreviewAnswerResponse = await provider.GenerateAnswerAsync(question, isTestKnowledgeBase).ConfigureAwait(false); var questionAnswerResponse = qnaPreviewAnswerResponse.Answers.FirstOrDefault(); if (questionAnswerResponse == null || questionAnswerResponse.Questions.Count == 0) { return(false); } // Check if question asked and result returned from the knowledgebase are same. return(questionAnswerResponse.Questions.First().ToUpperInvariant() == question?.ToUpperInvariant().Trim()); }
/// <summary> /// Initializes a new instance of the <see cref="CommonTeamsActivityHandler"/> class. /// </summary> /// <param name="configurationProvider">Configuration Provider.</param> /// <param name="microsoftAppCredentials">Microsoft app credentials to use.</param> /// <param name="ticketsProvider">Tickets Provider.</param> /// <param name="qnaServiceProvider">Question and answer maker service provider.</param> /// <param name="options">A set of key/value application configuration properties for FaqPlusPlus bot.</param> /// <param name="logger">Instance to send logs to the Application Insights service.</param> public CommonTeamsActivityHandler( IConfigurationDataProvider configurationProvider, MicrosoftAppCredentials microsoftAppCredentials, ITicketsProvider ticketsProvider, IQnaServiceProvider qnaServiceProvider, BotSettings options, ILogger logger) { this.logger = logger; this.options = options; this.configurationProvider = configurationProvider; this.microsoftAppCredentials = microsoftAppCredentials; this.ticketsProvider = ticketsProvider; this.qnaServiceProvider = qnaServiceProvider; this.appBaseUri = this.options.AppBaseUri; }
/// <summary> /// Initializes a new instance of the <see cref="QnAPairServiceFacade"/> class. /// </summary> /// <param name="configurationProvider">Configuration Provider.</param> /// <param name="activityStorageProvider">Activity storage provider.</param> /// <param name="qnaServiceProvider">QnA service provider.</param> /// <param name="botSettings">Represents a set of key/value application configuration properties for FaqPlusPlus bot.</param>ram> /// <param name="logger">Instance to send logs to the Application Insights service.</param> public QnAPairServiceFacade( Common.Providers.IConfigurationDataProvider configurationProvider, IQnaServiceProvider qnaServiceProvider, IActivityStorageProvider activityStorageProvider, IOptionsMonitor<BotSettings> botSettings, ILogger<QnAPairServiceFacade> logger) { this.configurationProvider = configurationProvider ?? throw new ArgumentNullException(nameof(configurationProvider)); this.qnaServiceProvider = qnaServiceProvider ?? throw new ArgumentNullException(nameof(qnaServiceProvider)); this.logger = logger ?? throw new ArgumentNullException(nameof(logger)); this.activityStorageProvider = activityStorageProvider ?? throw new ArgumentNullException(nameof(activityStorageProvider)); if (botSettings == null) { throw new ArgumentNullException(nameof(botSettings)); } this.options = botSettings.CurrentValue; this.appBaseUri = this.options.AppBaseUri; }
public PersonalChatMainDialog(ChangeLanguageDialog changeLangDialog, UserState userState, IQnaServiceProvider qnaServiceProvider, IOptionsMonitor <BotSettings> optionsAccessor, TelemetryClient telemetryClient, IConfigurationDataProvider configurationProvider) : base("root") { _telemetryClient = telemetryClient; _configurationProvider = configurationProvider; _changeLangDialog = changeLangDialog; _qnaServiceProvider = qnaServiceProvider; _options = optionsAccessor.CurrentValue; _appBaseUri = _options.AppBaseUri; AddDialog(changeLangDialog); AddDialog(new WaterfallDialog("personalRoot", new WaterfallStep[] { StartDialogAsync })); InitialDialogId = "personalRoot"; }
/// <summary> /// Initializes a new instance of the <see cref="MessagingExtensionActivity"/> class. /// </summary> /// <param name="configurationProvider">Configuration Provider.</param> /// <param name="activityStorageProvider">Activity storage provider.</param> /// <param name="qnaServiceProvider">Question and answer maker service provider.</param> /// <param name="searchService">SearchService dependency injection.</param> /// <param name="botAdapter">Bot adapter dependency injection.</param> /// <param name="memoryCache">IMemoryCache dependency injection.</param> /// <param name="knowledgeBaseSearchService">KnowledgeBaseSearchService dependency injection.</param> /// <param name="optionsAccessor">A set of key/value application configuration properties for FaqPlusPlus bot.</param> /// <param name="logger">Instance to send logs to the Application Insights service.</param> /// <param name="ticketsProvider">Instance of Ticket provider helps in fetching and storing information in storage table.</param> /// <param name="notificationService">Notifies in expert's Team chat.</param> public MessagingExtensionActivity( Common.Providers.IConfigurationDataProvider configurationProvider, IQnaServiceProvider qnaServiceProvider, IActivityStorageProvider activityStorageProvider, ISearchService searchService, BotFrameworkAdapter botAdapter, IMemoryCache memoryCache, IKnowledgeBaseSearchService knowledgeBaseSearchService, IOptionsMonitor <BotSettings> optionsAccessor, ILogger <MessagingExtensionActivity> logger, ITicketsProvider ticketsProvider, INotificationService notificationService) { this.configurationProvider = configurationProvider ?? throw new ArgumentNullException(nameof(configurationProvider)); this.qnaServiceProvider = qnaServiceProvider ?? throw new ArgumentNullException(nameof(qnaServiceProvider)); this.activityStorageProvider = activityStorageProvider ?? throw new ArgumentNullException(nameof(activityStorageProvider)); this.searchService = searchService ?? throw new ArgumentNullException(nameof(searchService)); this.botAdapter = botAdapter ?? throw new ArgumentNullException(nameof(botAdapter)); this.accessCache = memoryCache ?? throw new ArgumentNullException(nameof(memoryCache)); this.logger = logger ?? throw new ArgumentNullException(nameof(logger)); this.knowledgeBaseSearchService = knowledgeBaseSearchService ?? throw new ArgumentNullException(nameof(knowledgeBaseSearchService)); this.ticketsProvider = ticketsProvider ?? throw new ArgumentNullException(nameof(ticketsProvider)); this.notificationService = notificationService ?? throw new ArgumentNullException(nameof(notificationService)); if (optionsAccessor == null) { throw new ArgumentNullException(nameof(optionsAccessor)); } this.options = optionsAccessor.CurrentValue; this.appId = this.options.ExpertAppId; this.appBaseUri = this.options.AppBaseUri; this.accessCacheExpiryInDays = this.options.AccessCacheExpiryInDays; if (this.accessCacheExpiryInDays <= 0) { this.accessCacheExpiryInDays = DefaultAccessCacheExpiryInDays; this.logger.LogInformation($"Configuration option is not present or out of range for AccessCacheExpiryInDays and the default value is set to: {this.accessCacheExpiryInDays}", SeverityLevel.Information); } }
/// <summary> /// Initializes a new instance of the <see cref="BotCommandResolver"/> class. /// </summary> /// <param name="configurationProvider">Configuration Provider.</param> /// <param name="activityStorageProvider">Activity storage provider.</param> /// <param name="qnaServiceProvider">QnA service provider.</param> /// <param name="logger">Instance to send logs to the Application Insights service.</param> /// <param name="qnaPairService">Instance of QnA pair service class to call add/update/get QnA pair.</param> /// <param name="botSettings">Represents a set of key/value application configuration properties for FaqPlusPlus bot.</param> /// <param name="conversationService">Conversation service to send adaptive card in personal and teams chat.</param> public BotCommandResolver( Common.Providers.IConfigurationDataProvider configurationProvider, IQnaServiceProvider qnaServiceProvider, IActivityStorageProvider activityStorageProvider, IQnAPairServiceFacade qnaPairService, IOptionsMonitor <BotSettings> botSettings, ILogger <BotCommandResolver> logger, IConversationService conversationService) { this.configurationProvider = configurationProvider ?? throw new ArgumentNullException(nameof(configurationProvider)); this.qnaServiceProvider = qnaServiceProvider ?? throw new ArgumentNullException(nameof(qnaServiceProvider)); this.activityStorageProvider = activityStorageProvider ?? throw new ArgumentNullException(nameof(activityStorageProvider)); this.logger = logger ?? throw new ArgumentNullException(nameof(logger)); this.qnaPairService = qnaPairService ?? throw new ArgumentNullException(nameof(qnaPairService)); this.conversationService = conversationService ?? throw new ArgumentNullException(nameof(conversationService)); if (botSettings == null) { throw new ArgumentNullException(nameof(botSettings)); } var options = botSettings.CurrentValue; this.appBaseUri = options.AppBaseUri; }
/// <summary> /// Initializes a new instance of the <see cref="SearchServiceDataProvider"/> class. /// </summary> /// <param name="qnaServiceProvider">qna ServiceProvider.</param> public SearchServiceDataProvider(IQnaServiceProvider qnaServiceProvider) { this.qnaServiceProvider = qnaServiceProvider; }
/// <summary> /// Delete qna pair. /// </summary> /// <param name="turnContext">Turn context.</param> /// <param name="qnaServiceProvider">Qna Service provider.</param> /// <param name="activityStorageProvider">Activity Storage Provider.</param> /// <param name="logger">Logger.</param> /// <param name="cancellationToken">Cancellation Token.</param> /// <returns>A task that represents the work queued to execute.</returns> public static async Task DeleteQnaPair( ITurnContext <IMessageActivity> turnContext, IQnaServiceProvider qnaServiceProvider, IActivityStorageProvider activityStorageProvider, ILogger logger, CancellationToken cancellationToken) { QnASearchResult searchResult; Attachment attachment; var activity = (Activity)turnContext.Activity; var activityValue = ((JObject)activity.Value).ToObject <AdaptiveSubmitActionData>(); QnASearchResultList qnaAnswerResponse = await qnaServiceProvider.GenerateAnswerAsync(activityValue?.OriginalQuestion, isTestKnowledgeBase : false).ConfigureAwait(false); bool isSameQuestion = false; searchResult = qnaAnswerResponse.Answers.First(); // Check if question exist in the knowledgebase. if (searchResult != null && searchResult.Questions.Count > 0) { // Check if the deleted question & result returned from the knowledgebase are same. isSameQuestion = searchResult.Questions.First().ToUpperInvariant() == activityValue?.OriginalQuestion.ToUpperInvariant().Trim(); } // Delete the QnA pair if question exist in the knowledgebase & exactly the same question user wants to delete. if (searchResult.Id != -1 && isSameQuestion) { await qnaServiceProvider.DeleteQnaAsync(searchResult.Id.Value).ConfigureAwait(false); logger.LogInformation($"Question deleted by: {activity.Conversation.AadObjectId}"); attachment = MessagingExtensionQnaCard.DeletedEntry(activityValue?.OriginalQuestion, searchResult.Answer, activity.From.Name, activityValue?.UpdateHistoryData); ActivityEntity activityEntity = new ActivityEntity { ActivityReferenceId = searchResult.Metadata.FirstOrDefault(x => x.Name == Constants.MetadataActivityReferenceId)?.Value }; bool operationStatus = await activityStorageProvider.DeleteActivityEntityAsync(activityEntity).ConfigureAwait(false); if (!operationStatus) { logger.LogInformation($"Unable to delete the activity data from table storage."); } var updateCardActivity = new Activity(ActivityTypes.Message) { Id = turnContext.Activity.ReplyToId, Conversation = turnContext.Activity.Conversation, Attachments = new List <Attachment> { attachment }, }; // Send deleted question and answer card as response. await turnContext.UpdateActivityAsync(updateCardActivity, cancellationToken).ConfigureAwait(false); } else { // check if question and answer is present in unpublished version. qnaAnswerResponse = await qnaServiceProvider.GenerateAnswerAsync(activityValue?.OriginalQuestion, isTestKnowledgeBase : true).ConfigureAwait(false); if (qnaAnswerResponse?.Answers?.First().Id != -1) { await turnContext.SendActivityAsync(MessageFactory.Text(string.Format(CultureInfo.InvariantCulture, Strings.WaitMessage, activityValue?.OriginalQuestion))).ConfigureAwait(false); } } return; }
/// <summary> /// Initializes a new instance of the <see cref="SearchServiceDataProvider"/> class. /// </summary> /// <param name="qnaServiceProvider">question and answer ServiceProvider.</param> /// <param name="storageConnectionString">Azure web job storage.</param> public SearchServiceDataProvider(IQnaServiceProvider qnaServiceProvider, string storageConnectionString) { this.qnaServiceProvider = qnaServiceProvider; this.storageConnectionString = storageConnectionString; }