예제 #1
0
        private async Task <OnTurnProperty> DetectIntentAndEntitiesAsync(ITurnContext turnContext)
        {
            // Handle card input (if any), update state and return.
            if (turnContext.Activity.Value != null)
            {
                if (turnContext.Activity.Value is JObject)
                {
                    return(OnTurnProperty.FromCardInput((JObject)turnContext.Activity.Value));
                }
            }

            // Acknowledge attachments from user.
            if (turnContext.Activity.Attachments != null && turnContext.Activity.Attachments.Count > 0)
            {
                await turnContext.SendActivityAsync("Thanks for sending me that attachment. I'm still learning to process attachments.");

                return(null);
            }

            // Nothing to do for this turn if there is no text specified.
            if (string.IsNullOrWhiteSpace(turnContext.Activity.Text) || string.IsNullOrWhiteSpace(turnContext.Activity.Text.Trim()))
            {
                return(null);
            }

            // Call to LUIS recognizer to get intent + entities.
            var luisResults = await _services.LuisServices[LuisConfiguration].RecognizeAsync(turnContext, default(CancellationToken));

            // Return new instance of on turn property from LUIS results.
            // Leverages static fromLUISResults method.
            return(OnTurnProperty.FromLuisResults(luisResults));
        }
예제 #2
0
        public async override Task <DialogTurnResult> ContinueDialogAsync(DialogContext dc, CancellationToken cancellationToken = default(CancellationToken))
        {
            var turnContext = dc.Context;
            var step        = dc.ActiveDialog.State;

            // Get reservation property.
            var newReservation = await _reservationsAccessor.GetAsync(turnContext, () => new ReservationProperty());

            // Get on turn property. This has any entities that mainDispatcher,
            // or Bot might have captured in its LUIS model.
            var onTurnProperties = await _onTurnAccessor.GetAsync(turnContext, () => new OnTurnProperty("None", new List <EntityProperty>()));

            // If on turn property has entities..
            ReservationResult updateResult = null;

            if (onTurnProperties.Entities.Count > 0)
            {
                // ...update reservation property with on turn property results.
                updateResult = newReservation.UpdateProperties(onTurnProperties);
            }

            // See if updates to reservation resulted in errors, if so, report them to user.
            if (updateResult != null &&
                updateResult.Status == ReservationStatus.Incomplete &&
                updateResult.Outcome != null &&
                updateResult.Outcome.Count > 0)
            {
                await _reservationsAccessor.SetAsync(turnContext, updateResult.NewReservation);

                // Return and do not continue if there is an error.
                await turnContext.SendActivityAsync(updateResult.Outcome[0].Message);

                return(await base.ContinueDialogAsync(dc));
            }

            // Call LUIS and get results.
            var luisResults   = await _botServices.LuisServices[LuisConfiguration].RecognizeAsync(turnContext, cancellationToken);
            var topLuisIntent = luisResults.GetTopScoringIntent();
            var topIntent     = topLuisIntent.intent;

            // If we don't have an intent match from LUIS, go with the intent available via
            // the on turn property (parent's LUIS model).
            if (luisResults.Intents.Count <= 0)
            {
                // Go with intent in onTurnProperty.
                topIntent = string.IsNullOrWhiteSpace(onTurnProperties.Intent) ? "None" : onTurnProperties.Intent;
            }

            // Update object with LUIS result.
            updateResult = newReservation.UpdateProperties(OnTurnProperty.FromLuisResults(luisResults));

            // See if update reservation resulted in errors, if so, report them to user.
            if (updateResult != null &&
                updateResult.Status == ReservationStatus.Incomplete &&
                updateResult.Outcome != null &&
                updateResult.Outcome.Count > 0)
            {
                // Set reservation property.
                await _reservationsAccessor.SetAsync(turnContext, updateResult.NewReservation);

                // Return and do not continue if there is an error.
                await turnContext.SendActivityAsync(updateResult.Outcome[0].Message);

                return(await base.ContinueDialogAsync(dc));
            }

            // Did user ask for help or said cancel or continuing the conversation?
            switch (topIntent)
            {
            case ContinuePromptIntent:
                // User does not want to make any change.
                updateResult.NewReservation.NeedsChange = false;
                break;

            case NoChangeIntent:
                // User does not want to make any change.
                updateResult.NewReservation.NeedsChange = false;
                break;

            case HelpIntent:
                // Come back with contextual help.
                var helpReadOut = updateResult.NewReservation.HelpReadOut();
                await turnContext.SendActivityAsync(helpReadOut);

                break;

            case CancelIntent:
                // Start confirmation prompt.
                var opts = new PromptOptions
                {
                    Prompt = new Activity
                    {
                        Type = ActivityTypes.Message,
                        Text = "Are you sure you want to cancel?",
                    },
                };

                return(await dc.PromptAsync(ConfirmCancelPrompt, opts));

            case InterruptionsIntent:
            default:
                // If we picked up new entity values, do not treat this as an interruption.
                if (onTurnProperties.Entities.Count != 0 || luisResults.Entities.Count > 1)
                {
                    break;
                }

                // Handle interruption.
                var onTurnProperty = await _onTurnAccessor.GetAsync(dc.Context);

                return(await dc.BeginDialogAsync(InterruptionDispatcher, onTurnProperty));
            }

            // Set reservation property based on OnTurn properties.
            await _reservationsAccessor.SetAsync(turnContext, updateResult.NewReservation);

            return(await base.ContinueDialogAsync(dc));
        }