/// <summary> /// Validates the response from the choice prompt /// </summary> /// <param name="promptContext">The context of the prompt</param> /// <param name="cancellationToken">The cancellation token</param> /// <returns></returns> private async Task <bool> ChoiceValidation(PromptValidatorContext <FoundChoice> promptContext, CancellationToken cancellationToken) { Companies value; if (recognizer != null && recognizer.IsConfigured) { await SendTypingAsync(promptContext.Context, cancellationToken); CareerAdvise luisResult = await recognizer.RecognizeAsync <CareerAdvise>(promptContext.Context, cancellationToken); value = luisResult.Organization; } else { var val = promptContext.Context.Activity.Text; if (!Enum.TryParse(val, true, out value)) { value = Companies.NotSupported; } } switch (value) { case Companies.KPMG: case Companies.Deloitte: case Companies.EY: case Companies.PWC: promptContext.Recognized.Value = CreateChoice(value.ToString()); return(await Task.FromResult(true)); default: return(await Task.FromResult(false)); } }
/// <summary> /// Validates the response from the choice prompt /// </summary> /// <param name="promptContext">The context of the prompt</param> /// <param name="cancellationToken">The cancellation token</param> /// <returns></returns> private async Task <bool> ChoiceValidation(PromptValidatorContext <FoundChoice> promptContext, CancellationToken cancellationToken) { bool result = false; string value = null; if (recognizer != null && recognizer.IsConfigured) { CareerAdvise luisResult = await recognizer.RecognizeAsync <CareerAdvise>(promptContext.Context, cancellationToken); value = luisResult.QuestionType; switch (value?.ToLowerInvariant()) { case "general": case "application": case "assessment": case "interviews": case "offer": case "starting": result = true; break; } } else { // Without LUIS, we need to list all the acceptable answers from user value = promptContext.Context.Activity.Text; switch (value.ToLowerInvariant()) { case "general questions": value = "general"; result = true; break; case "applying": value = "application"; result = true; break; case "assessment test": value = "assessment"; result = true; break; case "interviews": value = "interviews"; result = true; break; case "the offer stage": value = "offer"; result = true; break; case "starting new job": value = "starting"; result = true; break; } } promptContext.Recognized.Value = CreateChoice(value); return(await Task.FromResult(result)); }
/// <summary> /// Start the child dialog. This will create the main menu adaptive card attachment. /// </summary> /// <param name="stepContext">The context of the waterfall dialog</param> /// <param name="cancellationToken">The cancellation token</param> /// <returns>The <see cref="System.Threading.Tasks.Task{TResult}"/> from prompting user.</returns> private async Task <DialogTurnResult> MenuPromptAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken) { if (stepContext == null) { throw new ArgumentNullException(nameof(stepContext)); } var userStateAccessor = userState.CreateProperty <ConversationMember>(nameof(ConversationMember)); var user = await userStateAccessor.GetAsync(stepContext.Context, () => null); if (recognizer == null || !recognizer.IsConfigured) { if (!user.WasGreeted) { var response = String.Format(stringResource.ResponseGreeting, stepContext.Context.Activity.From.Name); await stepContext.Context.SendActivityAsync(MessageFactory.Text(response), cancellationToken); } // If the LUIS model is not configured, we start the menu prompt return(await RunPromptAsync(stepContext, cancellationToken)); } // The step is called to re-prompt user if (stepContext.Options != null) { Companies value = Companies.NotSupported; if (!Enum.TryParse(stepContext.Options?.ToString(), true, out value)) { value = Companies.NotSupported; } switch (value) { case Companies.KPMG: case Companies.Deloitte: case Companies.EY: case Companies.PWC: return(await stepContext.NextAsync(CreateChoice(value.ToString()), cancellationToken)); default: return(await RunPromptAsync(stepContext, cancellationToken)); } } else { await SendTypingAsync(stepContext.Context, cancellationToken); CareerAdvise luisResult = await recognizer.RecognizeAsync <CareerAdvise>(stepContext.Context, cancellationToken); switch (luisResult.TopIntent().Intent) { case CareerAdvise.Intent.Greeting: string response = !user.WasGreeted ? String.Format(stringResource.ResponseGreeting, stepContext.Context.Activity.From.Name) : stringResource.ResponseWelcome; await stepContext.Context.SendActivityAsync(MessageFactory.Text(response), cancellationToken); return(await RunPromptAsync(stepContext, cancellationToken)); case CareerAdvise.Intent.CareerQuestionType: stepContext.Values[Organization] = luisResult.Organization; stepContext.Values[QuestionType] = luisResult.QuestionType; if (luisResult.Organization == Companies.NotSupported) { return(await RunPromptAsync(stepContext, cancellationToken)); } else { return(await stepContext.NextAsync(CreateChoice(luisResult.Organization.ToString()), cancellationToken)); } default: // Sends a message to user to indicate the bot is unable to help and end the dialog await stepContext.Context.SendActivityAsync(MessageFactory.Text(stringResource.ErrorHelpNotFound), cancellationToken); await stepContext.Context.SendActivityAsync(MessageFactory.Text(stringResource.ResponseEnd), cancellationToken); return(await stepContext.EndDialogAsync()); } } }
/// <summary> /// Process result from question prompt /// </summary> /// <param name="stepContext">The context of the waterfall dialog</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>The <see cref="Task"/> from processing the result</returns> private async Task <DialogTurnResult> QuestionPromptResultAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken) { // Sends activity indicator await SendTypingAsync(stepContext.Context, cancellationToken); if (recognizer != null && recognizer.IsConfigured) { await SendTypingAsync(stepContext.Context, cancellationToken); CareerAdvise luisResult = await recognizer.RecognizeAsync <CareerAdvise>(stepContext.Context, cancellationToken); switch (luisResult.TopIntent(0.8).Intent) { case CareerAdvise.Intent.Finish: // Ends the current dialog return(await stepContext.EndDialogAsync()); case CareerAdvise.Intent.CareerQuestionType: switch (luisResult.Organization) { case Companies.Deloitte: case Companies.EY: case Companies.PWC: // User is asking question for another organization, we end the dialog return(await stepContext.EndDialogAsync(luisResult.Organization.ToString())); } if (luisResult.QuestionType == null) { stepContext.Values.Remove(QuestionType); } else { stepContext.Values[QuestionType] = luisResult.QuestionType; } break; } } string answer = null; if (qnaMaker != null) { QnAMakerOptions options = new QnAMakerOptions() { Top = 3, ScoreThreshold = 0.5F, }; if (stepContext.Values.ContainsKey(QuestionType)) { options.MetadataBoost = new Metadata[] { new Metadata() { Name = "type", Value = stepContext.Values[QuestionType]?.ToString(), } }; } var response = await qnaMaker.GetAnswersAsync(stepContext.Context, options); if (response != null && response.Length > 0) { answer = response[0].Answer; } } if (answer != null) { await stepContext.Context.SendActivityAsync(MessageFactory.Text(answer), cancellationToken); } else { await stepContext.Context.SendActivityAsync(MessageFactory.Text(stringResource.ErrorHelpNotFound), cancellationToken); } var opts = stepContext.Values.ContainsKey(QuestionType) ? stepContext.Values[QuestionType]?.ToString() : null; return(await stepContext.ReplaceDialogAsync(InitialDialogId, opts, cancellationToken)); }