Exemplo n.º 1
0
        public async Task GetTokenAsync(WaterfallStepContext step, LuisRouterAccessor accessor, string encryptedRequest)
        {
            using (var handler = new HttpClientHandler())
            {
                handler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true;

                using (HttpClient client = new HttpClient(handler))
                {
                    byte[] byteData = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new { AppIdentity = encryptedRequest }));
                    using (var content = new ByteArrayContent(byteData))
                    {
                        content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
                        var response = await client.PostAsync($"{config.LuisRouterUrl}/identity", content);

                        if (response.IsSuccessStatusCode)
                        {
                            var json = await response.Content.ReadAsStringAsync();

                            var identityResponse = JsonConvert.DeserializeObject <IdentityResponse>(json);

                            await accessor.TokenPreference.SetAsync(step.Context, identityResponse.token);

                            await accessor.UserState.SaveChangesAsync(step.Context, false);
                        }
                    }
                }
            }
        }
        public async void AskForATopicTest()
        {
            var storage = new MemoryStorage();

            var userState         = new UserState(storage);
            var conversationState = new ConversationState(storage);

            var adapter = new TestAdapter()
                          .Use(new AutoSaveStateMiddleware(conversationState));

            // Adding LUIS Router accessor
            LuisRouterAccessor luisRouterAccessor = null;

            using (LuisRouterHelper luisRouterHelper = new LuisRouterHelper(Startup.EnvironmentName, Startup.ContentRootPath))
            {
                luisRouterAccessor = luisRouterHelper.BuildAccessor(userState, null);
            }

            // Adding QnAMaker Router accessor
            QnAMakerAccessor qnaMakerAccessor = null;

            using (QnAMakerHelper qnaMakerHelper = new QnAMakerHelper(Startup.EnvironmentName, Startup.ContentRootPath))
            {
                qnaMakerAccessor = qnaMakerHelper.BuildAccessor();
            }

            var accessors = new BotAccessors(new LoggerFactory(), conversationState, userState)
            {
                ConversationDialogState   = conversationState.CreateProperty <DialogState>("DialogState"),
                AskForExamplePreference   = conversationState.CreateProperty <bool>("AskForExamplePreference"),
                IsAuthenticatedPreference = userState.CreateProperty <bool>("IsAuthenticatedPreference")
            };

            await new TestFlow(adapter, async(turnContext, cancellationToken) =>
            {
                var state   = await accessors.ConversationDialogState.GetAsync(turnContext, () => new DialogState());
                var dialogs = new DialogSet(accessors.ConversationDialogState);
                dialogs.Add(new LuisQnADialog(accessors, luisRouterAccessor, qnaMakerAccessor));

                var dc = await dialogs.CreateContextAsync(turnContext, cancellationToken);

                var results = await dc.ContinueDialogAsync(cancellationToken);
                if (results.Status == DialogTurnStatus.Empty)
                {
                    await dc.BeginDialogAsync(LuisQnADialog.dialogId, null, cancellationToken);
                }
                else if (results.Status == DialogTurnStatus.Complete)
                {
                    //no additional send activities.
                }
            })
            .Send("")
            .AssertReply("What topic would you like to know more about?")
            .Send("what do i need to consider for an interview?")
            .AssertReply("In interviews, your job is to convince a recruiter that you have the skills, knowledge and experience for the job. Show motivation and convince a recruiter that you fit the organization's culture and job description, and you get that much closer to an offer.")
            .StartTestAsync();
        }
Exemplo n.º 3
0
        public BotAppBot(BotAccessors accessors, LuisRouterAccessor luisRouterAccessor, QnAMakerAccessor qnaMakerAccessor, ConversationState conversationState, UserState userState, ILogger <BotAppBot> logger)
        {
            this.accessors          = accessors;
            this.conversationState  = conversationState;
            this.userState          = userState;
            this.logger             = logger;
            this.luisRouterAccessor = luisRouterAccessor;
            this.qnaMakerAccessor   = qnaMakerAccessor;

            this.dialogs = new DialogSet(accessors.ConversationDialogState);
            this.dialogs.Add(new MainDialog(accessors, luisRouterAccessor, qnaMakerAccessor));
            this.dialogs.Add(new LuisQnADialog(accessors, luisRouterAccessor, qnaMakerAccessor));
        }
Exemplo n.º 4
0
        public MainDialog(BotAccessors accessors, LuisRouterAccessor luisRouterAccessor, QnAMakerAccessor qnaMakerAccessor) : base(dialogId)
        {
            this.accessors          = accessors ?? throw new ArgumentNullException(nameof(accessors));
            this.luisRouterAccessor = luisRouterAccessor ?? throw new ArgumentNullException(nameof(luisRouterAccessor));
            this.qnaMakerAccessor   = qnaMakerAccessor ?? throw new ArgumentNullException(nameof(qnaMakerAccessor));

            AddDialog(new WaterfallDialog(dialogId, new WaterfallStep[]
            {
                LaunchLuisQnADialog,
                EndMainDialog
            }));

            AddDialog(new LuisQnADialog(accessors, luisRouterAccessor, qnaMakerAccessor));
        }
Exemplo n.º 5
0
        public LuisQnADialog(BotAccessors accessors, LuisRouterAccessor luisRouterAccessor, QnAMakerAccessor qnaMakerAccessor) : base(dialogId)
        {
            this.accessors          = accessors ?? throw new ArgumentNullException(nameof(accessors));
            this.luisRouterAccessor = luisRouterAccessor ?? throw new ArgumentNullException(nameof(luisRouterAccessor));
            this.qnaMakerAccessor   = qnaMakerAccessor ?? throw new ArgumentNullException(nameof(qnaMakerAccessor));

            AddDialog(new WaterfallDialog(dialogId, new WaterfallStep[]
            {
                AskQuestionDialog,
                ProcessQuestionDialog,
                ProcessIfExampleIsRequiredDialog,
                EndDialog
            }));

            AddDialog(new TextPrompt("QuestionValidator", QuestionValidator));
            AddDialog(new ChoicePrompt("AskForExampleValidator", AskForExampleValidator)
            {
                Style = ListStyle.List
            });
        }
Exemplo n.º 6
0
        public async Task <List <LuisAppDetail> > LuisDiscoveryAsync(WaterfallStepContext step, LuisRouterAccessor accessor, string text, string applicationCode, string encryptionKey)
        {
            List <LuisAppDetail> result = new List <LuisAppDetail>();

            int IterationsToRetry   = 3;
            int TimeToSleepForRetry = 100;

            for (int i = 0; i <= IterationsToRetry; i++)
            {
                using (var handler = new HttpClientHandler())
                {
                    handler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true;

                    using (HttpClient client = new HttpClient(handler))
                    {
                        try
                        {
                            byte[] byteData = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new { Text = text, BingSpellCheckSubscriptionKey = config.BingSpellCheckSubscriptionKey, EnableLuisTelemetry = config.EnableLuisTelemetry }));
                            using (var content = new ByteArrayContent(byteData))
                            {
                                string token = await accessor.TokenPreference.GetAsync(step.Context, () => { return(string.Empty); });

                                content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
                                client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", $"{token}");
                                var response = await client.PostAsync($"{config.LuisRouterUrl}/luisdiscovery", content);

                                if (response.IsSuccessStatusCode)
                                {
                                    var json = await response.Content.ReadAsStringAsync();

                                    var res = JsonConvert.DeserializeObject <LuisDiscoveryResponseResult>(json);
                                    result = res.Result.LuisAppDetails;
                                    break;
                                }
                                else if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized)
                                {
                                    IdentityRequest request = new IdentityRequest()
                                    {
                                        appcode   = applicationCode,
                                        timestamp = DateTime.UtcNow
                                    };

                                    string json             = JsonConvert.SerializeObject(request);
                                    var    encryptedRequest = NETCore.Encrypt.EncryptProvider.AESEncrypt(json, encryptionKey);
                                    await GetTokenAsync(step, accessor, encryptedRequest);

                                    continue;
                                }
                            }
                        }
                        catch
                        {
                            Thread.Sleep(TimeToSleepForRetry);
                            continue;
                        }
                    }
                }
            }

            return(result);
        }
        public async void AskForATopicSampleTest()
        {
            var storage = new MemoryStorage();

            var userState         = new UserState(storage);
            var conversationState = new ConversationState(storage);

            var adapter = new TestAdapter()
                          .Use(new AutoSaveStateMiddleware(conversationState));

            // Adding LUIS Router accessor
            LuisRouterAccessor luisRouterAccessor = null;

            using (LuisRouterHelper luisRouterHelper = new LuisRouterHelper(Startup.EnvironmentName, Startup.ContentRootPath))
            {
                luisRouterAccessor = luisRouterHelper.BuildAccessor(userState, null);
            }

            // Adding QnAMaker Router accessor
            QnAMakerAccessor qnaMakerAccessor = null;

            using (QnAMakerHelper qnaMakerHelper = new QnAMakerHelper(Startup.EnvironmentName, Startup.ContentRootPath))
            {
                qnaMakerAccessor = qnaMakerHelper.BuildAccessor();
            }

            var accessors = new BotAccessors(new LoggerFactory(), conversationState, userState)
            {
                ConversationDialogState   = conversationState.CreateProperty <DialogState>("DialogState"),
                AskForExamplePreference   = conversationState.CreateProperty <bool>("AskForExamplePreference"),
                IsAuthenticatedPreference = userState.CreateProperty <bool>("IsAuthenticatedPreference")
            };

            List <MediaUrl> mediaList = new List <MediaUrl>();

            mediaList.Add(new MediaUrl("https://www.youtube.com/watch?v=CmTSY9oO3dw"));

            VideoCard videoCard = new VideoCard
            {
                Title     = "Interview Sample",
                Text      = "Each interview takes on a life of its own, but there are certain standard questions that arise. By reviewing them in advance, you can arrive confident and ready to articulate your skills and qualifications. Take a look at the sample questions here, and then bolster them with those specific to your goals and the organization. Both your answers to the interviewer's questions and those you post to them can provide a mechanism by which to communicate your qualifications.",
                Autostart = false,
                Media     = mediaList
            };

            Activity activity = new Activity
            {
                Type        = ActivityTypes.Message,
                Attachments = new List <Attachment> {
                    videoCard.ToAttachment()
                }
            };

            await new TestFlow(adapter, async(turnContext, cancellationToken) =>
            {
                var state   = await accessors.ConversationDialogState.GetAsync(turnContext, () => new DialogState());
                var dialogs = new DialogSet(accessors.ConversationDialogState);
                dialogs.Add(new LuisQnADialog(accessors, luisRouterAccessor, qnaMakerAccessor));

                var dc = await dialogs.CreateContextAsync(turnContext, cancellationToken);

                var results = await dc.ContinueDialogAsync(cancellationToken);
                if (results.Status == DialogTurnStatus.Empty)
                {
                    await dc.BeginDialogAsync(LuisQnADialog.dialogId, null, cancellationToken);
                }
                else if (results.Status == DialogTurnStatus.Complete)
                {
                    //no additional send activities.
                }
            })
            .Send("")
            .AssertReply("What topic would you like to know more about?")
            .Send("i would like to see a sample about the considerations for a human resources interview")
            .AssertReply((ac) =>
            {
                if (ac.AsMessageActivity().Attachments != null)
                {
                    var contentType = ac.AsMessageActivity().Attachments[0].ContentType;
                    Assert.Equal("application/vnd.microsoft.card.video", contentType);
                }
                else
                {
                    Assert.NotNull(ac.AsMessageActivity().Attachments);
                }
            })
            .StartTestAsync();
        }
Exemplo n.º 8
0
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            // Reading settings
            Settings.MicrosoftAppId       = Configuration.GetSection("ApplicationSettings:MicrosoftAppId")?.Value;
            Settings.MicrosoftAppPassword = Configuration.GetSection("ApplicationSettings:MicrosoftAppPassword")?.Value;
            Settings.BotConversationStorageConnectionString = Configuration.GetSection("ApplicationSettings:BotConversationStorageConnectionString")?.Value;
            Settings.BotConversationStorageKey                    = Configuration.GetSection("ApplicationSettings:BotConversationStorageKey")?.Value;
            Settings.BotConversationStorageDatabaseId             = Configuration.GetSection("ApplicationSettings:BotConversationStorageDatabaseId")?.Value;
            Settings.BotConversationStorageUserCollection         = Configuration.GetSection("ApplicationSettings:BotConversationStorageUserCollection")?.Value;
            Settings.BotConversationStorageConversationCollection = Configuration.GetSection("ApplicationSettings:BotConversationStorageConversationCollection")?.Value;

            // Adding EncryptionKey and ApplicationCode
            using (KeyVaultHelper keyVaultHelper = new KeyVaultHelper(EnvironmentName, ContentRootPath))
            {
                Settings.KeyVaultEncryptionKey = Configuration.GetSection("ApplicationSettings:KeyVaultEncryptionKey")?.Value;
                EncryptionKey = keyVaultHelper.GetVaultKeyAsync(Settings.KeyVaultEncryptionKey).Result;

                Settings.KeyVaultApplicationCode = Configuration.GetSection("ApplicationSettings:KeyVaultApplicationCode")?.Value;
                ApplicationCode = keyVaultHelper.GetVaultKeyAsync(Settings.KeyVaultApplicationCode).Result;
            }

            // Adding CosmosDB user storage
            CosmosDbStorage userstorage = new CosmosDbStorage(new CosmosDbStorageOptions
            {
                AuthKey          = Settings.BotConversationStorageKey,
                CollectionId     = Settings.BotConversationStorageUserCollection,
                CosmosDBEndpoint = new Uri(Settings.BotConversationStorageConnectionString),
                DatabaseId       = Settings.BotConversationStorageDatabaseId,
            });

            var userState = new UserState(userstorage);

            services.AddSingleton(userState);

            // Adding CosmosDB conversation storage
            CosmosDbStorage conversationstorage = new CosmosDbStorage(new CosmosDbStorageOptions
            {
                AuthKey          = Settings.BotConversationStorageKey,
                CollectionId     = Settings.BotConversationStorageConversationCollection,
                CosmosDBEndpoint = new Uri(Settings.BotConversationStorageConnectionString),
                DatabaseId       = Settings.BotConversationStorageDatabaseId,
            });

            var conversationState = new ConversationState(conversationstorage);

            services.AddSingleton(conversationState);

            // Adding Consul hosted service
            using (ConsulHelper consulHelper = new ConsulHelper(EnvironmentName, ContentRootPath))
            {
                consulHelper.Initialize(services, Configuration);
            }

            // Adding MVC compatibility
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

            // Adding the credential provider to be used with the Bot Framework Adapter
            services.AddSingleton <ICredentialProvider, ConfigurationCredentialProvider>();

            // Adding the channel provider to be used with the Bot Framework Adapter
            services.AddSingleton <IChannelProvider, ConfigurationChannelProvider>();

            // Adding the Bot Framework Adapter with error handling enabled
            services.AddSingleton <IBotFrameworkHttpAdapter, AdapterWithErrorHandler>();

            // Adding middlewares
            services.AddSingleton(new AutoSaveStateMiddleware(userState, conversationState));
            services.AddSingleton(new ShowTypingMiddleware());

            // Add Application Insights services into service collection
            services.AddApplicationInsightsTelemetry();

            // Add the standard telemetry client
            services.AddSingleton <IBotTelemetryClient, BotTelemetryClient>();

            // Add ASP middleware to store the HTTP body, mapped with bot activity key, in the httpcontext.items
            // This will be picked by the TelemetryBotIdInitializer
            services.AddTransient <TelemetrySaveBodyASPMiddleware>();

            // Add telemetry initializer that will set the correlation context for all telemetry items
            services.AddSingleton <ITelemetryInitializer, OperationCorrelationTelemetryInitializer>();

            // Add telemetry initializer that sets the user ID and session ID (in addition to other
            // bot-specific properties, such as activity ID)
            services.AddSingleton <ITelemetryInitializer, TelemetryBotIdInitializer>();

            // Create the telemetry middleware to track conversation events
            services.AddSingleton <IMiddleware, TelemetryLoggerMiddleware>();

            // Adding LUIS Router accessor
            services.AddSingleton(sp =>
            {
                LuisRouterAccessor accessor = null;
                using (LuisRouterHelper luisRouterHelper = new LuisRouterHelper(EnvironmentName, ContentRootPath))
                {
                    accessor = luisRouterHelper.BuildAccessor(userState, sp.GetRequiredService <IBotTelemetryClient>());
                }
                return(accessor);
            });

            // Adding QnAMaker Router accessor
            services.AddSingleton(sp =>
            {
                QnAMakerAccessor accessor = null;
                using (QnAMakerHelper qnaMakerHelper = new QnAMakerHelper(EnvironmentName, ContentRootPath))
                {
                    accessor = qnaMakerHelper.BuildAccessor();
                }
                return(accessor);
            });

            // Adding accessors
            services.AddSingleton(sp =>
            {
                // We need to grab the conversationState we added on the options in the previous step
                var options = sp.GetRequiredService <IOptions <BotFrameworkOptions> >().Value;
                if (options == null)
                {
                    throw new InvalidOperationException("BotFrameworkOptions must be configured prior to setting up the State Accessors");
                }

                // Create the custom state accessor.
                // State accessors enable other components to read and write individual properties of state.
                var accessors = new BotAccessors(loggerFactory, conversationState, userState)
                {
                    ConversationDialogState   = conversationState.CreateProperty <DialogState>("DialogState"),
                    AskForExamplePreference   = conversationState.CreateProperty <bool>("AskForExamplePreference"),
                    IsAuthenticatedPreference = userState.CreateProperty <bool>("IsAuthenticatedPreference")
                };

                return(accessors);
            });

            // Adding the bot as a transient. In this case the ASP Controller is expecting an IBot
            services.AddTransient <IBot, BotAppBot>();
        }