Ejemplo n.º 1
0
        //This PizzaOrderBot receives the PizzaOrderAccessors and dialog factories via Dependency Injection
        //By abstracting the creation of dialogs into a factory, we create something that is reusable and testable!
        public PizzaOrderBot(PizzaOrderAccessors accessors, MainMenuDialogFactory mainDialogFactory, PizzaOrderDialogFactory orderDialogFactory, ILogger <PizzaOrderBot> logger)
        {
            _accessors = accessors;
            _logger    = logger;

            //Step 1) Create a new DialogSet based on the PizzaOrderAccessors DialogState
            //A DialogSet is a grouping of dialogs that can transition between each other.
            _dialogs = new DialogSet(_accessors.DialogState);

            //Step 2) Add the Main and Order dialogs
            _dialogs.Add(mainDialogFactory.Build());
            _dialogs.Add(orderDialogFactory.Build());

            //STEP 3) Add the following built-in prompts to the dialog set:
            // - TextPrompt for the address
            // - ConfirmPrompt to confirm the address
            // - ConfirmPrompt to confirm the order
            _dialogs.Add(new TextPrompt(DialogNames.ADDRESS_PROMPT, AddressValidator.ValidateAddressAsync));
            _dialogs.Add(new ConfirmPrompt(DialogNames.ADDRESS_CONFIRM));
            _dialogs.Add(new ConfirmPrompt(DialogNames.CONFIRM_ORDER));

            //Step 4) Add prompts for size and toppings. These can be text prompts
            // or use the provided PizzaSizePrompt and PizzaToppingPrompt dialogs.
            // Custom prompt dialogs can be created to make a consistent user experience.
            _dialogs.Add(new PizzaSizePrompt(DialogNames.SIZE_PROMPT));
            _dialogs.Add(new PizzaToppingPrompt(DialogNames.TOPPINGS_PROMPT));
        }
 public MainMenuDialogFactory(PizzaOrderAccessors accessors, LuisRecognizer luisRecognizer)
 {
     _accessors      = accessors;
     _luisRecognizer = luisRecognizer;
 }
Ejemplo n.º 3
0
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            //The extension to add a bot to our services container
            //can be found in Microsoft.Bot.Builder.Integration.AspNet.Core
            //Whichever type is passed will be the bot that is created
            services.AddBot <PizzaOrderBot>(options =>
            {
                //Traffic coming through to your app is protected by the app ID and app secret
                //credentials applied to your Bot Registration on Azure.
                //If you are running locally, these can be blank.
                var secretKey   = Configuration.GetSection("botFileSecret")?.Value;
                var botFilePath = Configuration.GetSection("botFilePath")?.Value;

                var botConfig = BotConfiguration.Load(botFilePath ?? @".\BotConfiguration.bot", secretKey);
                if (botConfig == null)
                {
                    throw new InvalidOperationException($"The .bot config file could not be loaded from [{botFilePath}]");
                }

                //Add the bot configuration as something we can retrieve through DI
                services.AddSingleton(sp => botConfig);

                //The bot configuration can map different endpoints for different environments
                var serviceName = Environment.EnvironmentName.ToLowerInvariant();
                var service     = botConfig.FindServiceByNameOrId(serviceName) as EndpointService;
                if (service == null)
                {
                    throw new InvalidOperationException($"The .bot file does not contain an endpoint with name '{serviceName}'.");
                }

                options.CredentialProvider = new SimpleCredentialProvider(service.AppId, service.AppPassword);


                //Memory storage is only used for this example.
                //In a production application, you should always rely on
                //a more persistant storage mechanism, such as CosmosDB
                IStorage dataStore = new MemoryStorage();

                //Whichever datastore we're working with, we will need to use it
                //to actually store the conversation state.
                var conversationState = new ConversationState(dataStore);
                options.State.Add(conversationState);

                //Setup a call back to use in case any application or middleware exceptions were thrown
                ILogger logger = _loggerFactory.CreateLogger <EchoBot>();

                options.OnTurnError = async(context, e) =>
                {
                    //Ideally you do not want to get here - you want to handle business logic errors more gracefully.
                    //But if we're here, we can do any housekeeping such as logging and letting the know something went wrong.
                    logger.LogError(e, "Unhandled exception on bot turn - incoming input was {0}", context.Activity.Text);

                    //Since we have the context, we can send (helpful) messagse to the user
                    await context.SendActivityAsync($"Something went wrong. Please forgive me. Exception: {e.Message}");
                };
            });

            //Any state accessors need to be injected into the bot for each turn,
            //so add them to the services container
            services.AddSingleton <PizzaOrderAccessors>(sp =>
            {
                //Step 24) Retrieve the bot options from the IServiceCollection.
                //This is found via the type IOptions<BotFrameworkOptions>
                var options = sp.GetRequiredService <IOptions <BotFrameworkOptions> >().Value;
                if (options == null)
                {
                    throw new InvalidOperationException("BotFrameworkOptions must be configured prior to setting up the state accessors");
                }

                //Step 25) Retrieve the ConversationState from the options.
                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.");
                }

                //Step 26) Now our factory method needs to return a new instance of type PizzaOrderAccessors
                //based on this conversation state. We also need to register new properties for each
                //state we're tracking - the "PizzaOrderState" and the "DialogState".
                var accessors = new PizzaOrderAccessors(conversationState)
                {
                    PizzaOrderState = conversationState.CreateProperty <PizzaOrderState>("PizzaOrderState"),
                    DialogState     = conversationState.CreateProperty <DialogState>("DialogState")
                };

                return(accessors);
            });

            //Step 27 )Add a singleton of type LuisRecognizer to the services container.
            //This involves creating a new instance of LuisApplication and LuisPredictionOptions.
            services.AddSingleton(sp =>
            {
                var appId    = Configuration.GetSection("luisAppId")?.Value;
                var key      = Configuration.GetSection("luisKey")?.Value;
                var endpoint = Configuration.GetSection("luisEndpoint")?.Value;

                // Get LUIS information
                var luisApp = new LuisApplication(appId, key, endpoint);

                // Specify LUIS options. These may vary for your bot.
                var luisPredictionOptions = new LuisPredictionOptions
                {
                    IncludeAllIntents = true,
                };

                // Create the recognizer
                var recognizer = new LuisRecognizer(luisApp, luisPredictionOptions, true, null);
                return(recognizer);
            });

            //Step 28) The last setup step for this lab. Add singletons for "MainMenuDialogFactory"
            //and "PizzaOrderDialogFactory" to the services container.
            //This shows that they can be decoupled from the bot for reuse and testing.
            services.AddSingleton <MainMenuDialogFactory>();
            services.AddSingleton <PizzaOrderDialogFactory>();
        }