public override async Task <DialogTurnResult> ContinueDialogAsync(DialogContext dialogContext, CancellationToken cancellationToken = default(CancellationToken)) { var inputActivity = dialogContext.Context.Activity; IActivity outputActivity = new Activity(); var query = inputActivity.Text; var qnaResult = await _qnaMaker.GetAnswersAsync(dialogContext.Context); if (qnaResult.Any()) { var qnaAnswer = qnaResult[0].Answer; var prompts = qnaResult[0].Context?.Prompts; if (prompts == null || prompts.Length < 1) { outputActivity = MessageFactory.Text(qnaAnswer); } else { outputActivity = MessageFactory.SuggestedActions(text: qnaAnswer, actions: prompts.Select(p => p.DisplayText)); } await dialogContext.Context.SendActivityAsync(outputActivity); return(EndOfTurn); } dialogContext.SuppressCompletionMessage(true); await dialogContext.EndDialogAsync(); return(await dialogContext.ContinueDialogAsync()); }
// Runs when the dialog stack is empty, and a new message activity comes in. protected override async Task OnMessageActivityAsync(DialogContext innerDc, CancellationToken cancellationToken = default) { var activity = innerDc.Context.Activity.AsMessageActivity(); var userProfile = await _userProfileState.GetAsync(innerDc.Context, () => new UserProfileState()); if (!string.IsNullOrEmpty(activity.Text)) { // Get current cognitive models for the current locale. CognitiveModelSet localizedServices = _services.GetCognitiveModels(); // Get dispatch result from turn state. var dispatchResult = innerDc.Context.TurnState.Get <DispatchLuis>(StateProperties.DispatchResult); (var dispatchIntent, var dispatchScore) = dispatchResult.TopIntent(); // Check if the dispatch intent maps to a skill. var identifiedSkill = SkillRouter.IsSkill(_settings.Skills, dispatchIntent.ToString()); if (identifiedSkill != null) { // Start the skill dialog. await innerDc.BeginDialogAsync(identifiedSkill.Id); } else if (dispatchIntent == DispatchLuis.Intent.q_Faq) { await innerDc.BeginDialogAsync("Faq"); } else if (dispatchIntent == DispatchLuis.Intent.q_Chitchat) { innerDc.SuppressCompletionMessage(true); await innerDc.BeginDialogAsync("Chitchat"); } else if (dispatchIntent == DispatchLuis.Intent.q_HRBenefits) { innerDc.SuppressCompletionMessage(true); await innerDc.BeginDialogAsync("HRBenefits"); } else { innerDc.SuppressCompletionMessage(true); await innerDc.Context.SendActivityAsync(_templateEngine.GenerateActivityForLocale("UnsupportedMessage", userProfile)); } } }
// Runs when the dialog stack completes. protected override async Task OnDialogCompleteAsync(DialogContext outerDc, object result, CancellationToken cancellationToken = default) { var userProfile = await _userProfileState.GetAsync(outerDc.Context, () => new UserProfileState()); // Only send a completion message if the user sent a message activity. if (outerDc.Context.Activity.Type == ActivityTypes.Message && !outerDc.SuppressCompletionMessage()) { await outerDc.Context.SendActivityAsync(_templateEngine.GenerateActivityForLocale("CompletedMessage", userProfile)); } }
// Runs when the dialog stack completes. protected override async Task OnDialogCompleteAsync(DialogContext dc, object result = null, CancellationToken cancellationToken = default(CancellationToken)) { // workaround. if connect skill directly to teams, the following response does not work. if (!dc.SuppressCompletionMessage() && (dc.Context.Adapter is IRemoteUserTokenProvider remoteInvocationAdapter || Channel.GetChannelId(dc.Context) != Channels.Msteams)) { var response = dc.Context.Activity.CreateReply(); response.Type = ActivityTypes.Handoff; await dc.Context.SendActivityAsync(response); } // End active dialog await dc.EndDialogAsync(result); }
// Runs when a new event activity comes in. protected override async Task OnEventActivityAsync(DialogContext dc, CancellationToken cancellationToken = default(CancellationToken)) { var ev = dc.Context.Activity.AsEventActivity(); var value = ev.Value?.ToString(); var state = await _stateAccessor.GetAsync(dc.Context, () => new PointOfInterestSkillState()); switch (ev.Name) { case Events.Location: { dc.SuppressCompletionMessage(true); // Test trigger with // /event:{ "Name": "Location", "Value": "34.05222222222222,-118.2427777777777" } if (!string.IsNullOrEmpty(value)) { var coords = value.Split(','); if (coords.Length == 2) { if (double.TryParse(coords[0], out var lat) && double.TryParse(coords[1], out var lng)) { var coordinates = new LatLng { Latitude = lat, Longitude = lng, }; state.CurrentCoordinates = coordinates; } } } break; } case TokenEvents.TokenResponseEventName: { // Forward the token response activity to the dialog waiting on the stack. await dc.ContinueDialogAsync(); break; } default: { await dc.Context.SendActivityAsync(new Activity(type : ActivityTypes.Trace, text : $"Unknown Event '{ev.Name ?? "undefined"}' was received but not processed.")); break; } } }
// Runs when the dialog stack is empty, and a new member is added to the conversation. Can be used to send an introduction activity. protected override async Task OnMembersAddedAsync(DialogContext innerDc, CancellationToken cancellationToken = default) { var userProfile = await _userProfileState.GetAsync(innerDc.Context, () => new UserProfileState()); if (string.IsNullOrEmpty(userProfile.Name)) { // Send new user intro card. await innerDc.Context.SendActivityAsync(_templateEngine.GenerateActivityForLocale("NewUserIntroCard", userProfile)); // Start onboarding dialog. await innerDc.BeginDialogAsync(nameof(OnboardingDialog)); } else { // Send returning user intro card. await innerDc.Context.SendActivityAsync(_templateEngine.GenerateActivityForLocale("ReturningUserIntroCard", userProfile)); } // Suppress completion message. innerDc.SuppressCompletionMessage(true); }
// Runs on every turn of the conversation to check if the conversation should be interrupted. protected override async Task <InterruptionAction> OnInterruptDialogAsync(DialogContext dc, CancellationToken cancellationToken) { var activity = dc.Context.Activity; var userProfile = await _userProfileState.GetAsync(dc.Context, () => new UserProfileState()); var dialog = dc.ActiveDialog?.Id != null?dc.FindDialog(dc.ActiveDialog?.Id) : null; if (activity.Type == ActivityTypes.Message && !string.IsNullOrEmpty(activity.Text)) { // Check if the active dialog is a skill for conditional interruption. var isSkill = dialog is SkillDialog; // Get Dispatch LUIS result from turn state. var dispatchResult = dc.Context.TurnState.Get <DispatchLuis>(StateProperties.DispatchResult); (var dispatchIntent, var dispatchScore) = dispatchResult.TopIntent(); // Check if we need to switch skills. if (isSkill) { if (dispatchIntent.ToString() != dialog.Id && dispatchScore > 0.9) { var identifiedSkill = SkillRouter.IsSkill(_settings.Skills, dispatchResult.TopIntent().intent.ToString()); if (identifiedSkill != null) { var prompt = _templateEngine.GenerateActivityForLocale("SkillSwitchPrompt", new { Skill = identifiedSkill.Name }); await dc.BeginDialogAsync(_switchSkillDialog.Id, new SwitchSkillDialogOptions(prompt, identifiedSkill)); return(InterruptionAction.Waiting); } } } if (dispatchIntent == DispatchLuis.Intent.l_General) { // Get connected LUIS result from turn state. var generalResult = dc.Context.TurnState.Get <GeneralLuis>(StateProperties.GeneralResult); (var generalIntent, var generalScore) = generalResult.TopIntent(); if (generalScore > 0.5) { switch (generalIntent) { case GeneralLuis.Intent.Cancel: { // Suppress completion message for utility functions. dc.SuppressCompletionMessage(true); await dc.Context.SendActivityAsync(_templateEngine.GenerateActivityForLocale("CancelledMessage", userProfile)); await dc.CancelAllDialogsAsync(); return(InterruptionAction.End); } case GeneralLuis.Intent.Escalate: { await dc.Context.SendActivityAsync(_templateEngine.GenerateActivityForLocale("EscalateMessage", userProfile)); return(InterruptionAction.Resume); } case GeneralLuis.Intent.Help: { // Suppress completion message for utility functions. dc.SuppressCompletionMessage(true); if (isSkill) { // If current dialog is a skill, allow it to handle its own help intent. await dc.ContinueDialogAsync(cancellationToken); break; } else { await dc.Context.SendActivityAsync(_templateEngine.GenerateActivityForLocale("HelpCard", userProfile)); return(InterruptionAction.Resume); } } case GeneralLuis.Intent.Logout: { // Suppress completion message for utility functions. dc.SuppressCompletionMessage(true); // Log user out of all accounts. await LogUserOut(dc); await dc.Context.SendActivityAsync(_templateEngine.GenerateActivityForLocale("LogoutMessage", userProfile)); return(InterruptionAction.End); } case GeneralLuis.Intent.Repeat: { // No need to send the usual dialog completion message for utility capabilities such as these. dc.SuppressCompletionMessage(true); // Sends the activities since the last user message again. var previousResponse = await _previousResponseAccessor.GetAsync(dc.Context, () => new List <Activity>()); foreach (var response in previousResponse) { // Reset id of original activity so it can be processed by the channel. response.Id = string.Empty; await dc.Context.SendActivityAsync(response); } return(InterruptionAction.Waiting); } case GeneralLuis.Intent.StartOver: { // Suppresss completion message for utility functions. dc.SuppressCompletionMessage(true); await dc.Context.SendActivityAsync(_templateEngine.GenerateActivityForLocale("StartOverMessage", userProfile)); // Cancel all dialogs on the stack. await dc.CancelAllDialogsAsync(); return(InterruptionAction.End); } case GeneralLuis.Intent.Stop: { // Use this intent to send an event to your device that can turn off the microphone in speech scenarios. break; } } } } } return(InterruptionAction.NoAction); }