예제 #1
0
        /// <summary>
        /// Initializes a new instance of the class.
        /// </summary>
        /// <param name="conversationState">The managed conversation state.</param>
        /// <param name="loggerFactory">A <see cref="ILoggerFactory"/> that is hooked to the Azure App Service provider.</param>
        /// <seealso cref="https://docs.microsoft.com/en-us/aspnet/core/fundamentals/logging/?view=aspnetcore-2.1#windows-eventlog-provider"/>

        // public dialogBotBot(ConversationState conversationState, ILoggerFactory loggerFactory)
        public dialogBotBot(dialogBotAccessors accessors, LuisRecognizer luis, QnAMaker qna)
        {
            Console.WriteLine("Bot constructor");
            // Set the _accessors
            _accessors = accessors ?? throw new ArgumentNullException(nameof(accessors));
            // The DialogSet needs a DialogState accessor, it will call it when it has a turn context.
            _dialogs = new DialogSet(accessors.ConversationDialogState);
            // This array defines how the Waterfall will execute.
            var waterfallSteps = new WaterfallStep[]
            {
                NameStepAsync,
                NameConfirmStepAsync,
            };

            // The incoming luis variable is the LUIS Recognizer we added above.
            this.Recognizer = luis ?? throw new System.ArgumentNullException(nameof(luis));

            // The incoming QnA variable is the QnAMaker we added above.
            this.QnA = qna ?? throw new System.ArgumentNullException(nameof(qna));

            // Add named dialogs to the DialogSet. These names are saved in the dialog state.
            _dialogs.Add(new WaterfallDialog("details", waterfallSteps));
            _dialogs.Add(new TextPrompt("name"));
        }
예제 #2
0
        /// <summary>
        /// This method gets called by the runtime. Use this method to add services to the container.
        /// </summary>
        /// <param name="services">The <see cref="IServiceCollection"/> specifies the contract for a collection of service descriptors.</param>
        /// <seealso cref="IStatePropertyAccessor{T}"/>
        /// <seealso cref="https://docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/dependency-injection"/>
        /// <seealso cref="https://docs.microsoft.com/en-us/azure/bot-service/bot-service-manage-channels?view=azure-bot-service-4.0"/>
        public void ConfigureServices(IServiceCollection services)
        {
            var secretKey   = Configuration.GetSection("botFileSecret")?.Value;
            var botFilePath = Configuration.GetSection("botFilePath")?.Value;

            if (!File.Exists(botFilePath))
            {
                throw new FileNotFoundException($"The .bot configuration file was not found. botFilePath: {botFilePath}");
            }

            // Loads .bot configuration file and adds a singleton that your Bot can access through dependency injection.
            BotConfiguration botConfig = null;

            try
            {
                botConfig = BotConfiguration.Load(botFilePath, secretKey);
            }
            catch
            {
                var msg = @"Error reading bot file. Please ensure you have valid botFilePath and botFileSecret set for your environment.
        - You can find the botFilePath and botFileSecret in the Azure App Service application settings.
        - If you are running this bot locally, consider adding a appsettings.json file with botFilePath and botFileSecret.
        - See https://aka.ms/about-bot-file to learn more about .bot file its use and bot configuration.
        ";
                throw new InvalidOperationException(msg);
            }

            services.AddSingleton(sp => botConfig ?? throw new InvalidOperationException($"The .bot configuration file could not be loaded. botFilePath: {botFilePath}"));

            // Retrieve current endpoint.
            var environment = _isProduction ? "production" : "development";
            var service     = botConfig.Services.FirstOrDefault(s => s.Type == "endpoint" && s.Name == environment);

            if (service == null && _isProduction)
            {
                // Attempt to load development environment
                service = botConfig.Services.Where(s => s.Type == "endpoint" && s.Name == "development").FirstOrDefault();
            }

            if (!(service is EndpointService endpointService))
            {
                throw new InvalidOperationException($"The .bot file does not contain an endpoint with name '{environment}'.");
            }

            // Memory Storage is for local bot debugging only. When the bot is restarted, everything stored in memory will be gone.
            IStorage dataStore = new MemoryStorage();

            // For production bots use the Azure Blob or
            // Azure CosmosDB storage providers. For the Azure
            // based storage providers, add the Microsoft.Bot.Builder.Azure
            // Nuget package to your solution. That package is found at:
            // https://www.nuget.org/packages/Microsoft.Bot.Builder.Azure/
            // Un-comment the following lines to use Azure Blob Storage
            // // Storage configuration name or ID from the .bot file.
            // const string StorageConfigurationId = "<STORAGE-NAME-OR-ID-FROM-BOT-FILE>";
            // var blobConfig = botConfig.FindServiceByNameOrId(StorageConfigurationId);
            // if (!(blobConfig is BlobStorageService blobStorageConfig))
            // {
            //    throw new InvalidOperationException($"The .bot file does not contain an blob storage with name '{StorageConfigurationId}'.");
            // }
            // // Default container name.
            // const string DefaultBotContainer = "<DEFAULT-CONTAINER>";
            // var storageContainer = string.IsNullOrWhiteSpace(blobStorageConfig.Container) ? DefaultBotContainer : blobStorageConfig.Container;
            // IStorage dataStore = new Microsoft.Bot.Builder.Azure.AzureBlobStorage(blobStorageConfig.ConnectionString, storageContainer);

            services.AddBot <dialogBotBot>(options =>
            {
                options.CredentialProvider = new ConfigurationCredentialProvider(Configuration);
                //options.CredentialProvider = new SimpleCredentialProvider(endpointService.AppId, endpointService.AppPassword);

                // Catches any errors that occur during a conversation turn and logs them to currently
                // configured ILogger.
                ILogger logger = _loggerFactory.CreateLogger <dialogBotBot>();

                options.OnTurnError = async(context, exception) =>
                {
                    logger.LogError($"Exception caught : {exception}");
                    await context.SendActivityAsync("Sorry, it looks like something went wrong.");
                };

                //Add middleware
                options.Middleware.Add(new Middleware());

                // Create and add conversation state.
                var conversationState = new ConversationState(dataStore);
                options.State.Add(conversationState);

                // Create and add user state.
                var userState = new UserState(dataStore);
                options.State.Add(userState);
            });

            services.AddSingleton <dialogBotAccessors>(sp =>
            {
                var options = sp.GetRequiredService <IOptions <BotFrameworkOptions> >().Value;
                // Create the custom state accessor.
                // State accessors enable other components to read and write individual properties of state.
                //var userState = options.State.OfType<UserState>().FirstOrDefault();
                var conversationState = options.State.OfType <ConversationState>().FirstOrDefault();
                if (conversationState == null)
                {
                    throw new InvalidOperationException("ConversationState must be defined and added before adding conversation-scoped state accessors.");
                }

                var userState = options.State.OfType <UserState>().FirstOrDefault();
                if (userState == null)
                {
                    throw new InvalidOperationException("UserState must be defined and added before adding user-scoped state accessors.");
                }

                var accessors = new dialogBotAccessors(conversationState, userState)
                {
                    CounterState            = conversationState.CreateProperty <CounterState>(dialogBotAccessors.CounterStateName),
                    ConversationDialogState = conversationState.CreateProperty <DialogState>("DialogState"),
                    UserProfile             = userState.CreateProperty <UserProfile>("UserProfile"),
                };

                return(accessors);
            });

            // Create and register a LUIS recognizer.
            services.AddSingleton(sp =>
            {
                // Set up Luis
                var luisApp = new LuisApplication(
                    applicationId: "8d5bf38e-108c-47f3-a03f-84c4da0aa8c9",
                    endpointKey: "7f267a067ce249639d74e9c23c9b3f7e",
                    endpoint: "https://westus.api.cognitive.microsoft.com/luis/v2.0/apps/8d5bf38e-108c-47f3-a03f-84c4da0aa8c9?verbose=true&timezoneOffset=-360&subscription-key=7f267a067ce249639d74e9c23c9b3f7e&q=");
                // Specify LUIS options. These may vary for your bot.
                var luisPredictionOptions = new LuisPredictionOptions
                {
                    IncludeAllIntents = true,
                };
                return(new LuisRecognizer(
                           application: luisApp,
                           predictionOptions: luisPredictionOptions,
                           includeApiResults: true));
            });

            // Create and register a QnA service and knowledgebase
            services.AddSingleton(sp =>
            {
                var hostPath        = "https://pedroqna.azurewebsites.net/qnamaker";
                var endpointKey     = "647d6f22-f64f-4732-a87f-ee7c48a2b1f7";
                var knowledgebaseId = "7e7af984-c985-4211-8ed2-923fed042f9f";
                var qnaOptions      = float.TryParse("0.4F", out float scoreThreshold)
                    ? new QnAMakerOptions
                {
                    ScoreThreshold = scoreThreshold,
                    Top            = 1
                } : null;
                return(new QnAMaker(
                           new QnAMakerEndpoint
                {
                    EndpointKey = endpointKey,
                    Host = hostPath,
                    KnowledgeBaseId = knowledgebaseId,
                },
                           qnaOptions));
            });
        }