Beispiel #1
0
        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));
                }
            }
        }
Beispiel #3
0
        // 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;
            }
            }
        }
Beispiel #6
0
        // 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);
        }
Beispiel #7
0
        // 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);
        }