Exemple #1
0
        private static async Task <ActionExecutionContext> RunActions(ILuisService luisService, IList <ActionExecutionContext> actions)
        {
            if (actions == null || actions.Count == 0)
            {
                Console.WriteLine(">> ERROR: Action chain cannot be null or empty.");

                return(null);
            }

            var actionExecutionContext = actions.First();
            var intentAction           = actions.First().Action;

            actions.RemoveAt(0);
            if (actions.Count > 0)
            {
                await RunActions(luisService, actions);
            }

            var  validationResults = default(ICollection <ValidationResult>);
            bool isValid           = intentAction.IsValid(out validationResults);

            while (!isValid)
            {
                var fieldValidation = validationResults.FirstOrDefault();
                if (fieldValidation != null)
                {
                    var paramName = fieldValidation.MemberNames.First();
                    Console.Write("({0}) {1}: ", paramName, fieldValidation.ErrorMessage);
                    var input = Console.ReadLine();

                    var queryResult = await LuisActionResolver.QueryValueFromLuisAsync(luisService, intentAction, paramName, input, CancellationToken.None);

                    if (!queryResult.Succeed && !string.IsNullOrWhiteSpace(queryResult.NewIntent) && queryResult.NewAction != null)
                    {
                        var newActionDefinition     = LuisActionResolver.GetActionDefinition(queryResult.NewAction);
                        var currentActionDefinition = LuisActionResolver.GetActionDefinition(intentAction);

                        var isContextual = false;
                        if (LuisActionResolver.IsValidContextualAction(queryResult.NewAction, intentAction, out isContextual))
                        {
                            var executionContextChain = new List <ActionExecutionContext> {
                                new ActionExecutionContext(queryResult.NewIntent, queryResult.NewAction)
                            };

                            var executionContext = await RunActions(luisService, executionContextChain);

                            if (executionContext.ChangeRootSignaling)
                            {
                                if (LuisActionResolver.IsContextualAction(intentAction))
                                {
                                    return(executionContext);
                                }
                                else
                                {
                                    intentAction = executionContext.Action;
                                }
                            }
                        }
                        else if (isContextual && !LuisActionResolver.IsContextualAction(intentAction))
                        {
                            Console.WriteLine($"Cannot execute action '{newActionDefinition.FriendlyName}' in the context of '{currentActionDefinition.FriendlyName}' - continuing with current action");
                        }
                        else if (!intentAction.GetType().Equals(queryResult.NewAction.GetType()))
                        {
                            var valid = LuisActionResolver.UpdateIfValidContextualAction(queryResult.NewAction, intentAction, out isContextual);
                            if (!valid && isContextual)
                            {
                                Console.WriteLine($"Cannot switch to action '{newActionDefinition.FriendlyName}' from '{currentActionDefinition.FriendlyName}' due to invalid context - continuing with current action");
                            }
                            else if (currentActionDefinition.ConfirmOnSwitchingContext)
                            {
                                Console.Write($"You are about to discard the current action '{currentActionDefinition.FriendlyName}' and start executing '{newActionDefinition.FriendlyName}'\nContinue? ");
                                var response = Console.ReadLine();

                                if (response.ToUpperInvariant().StartsWith("Y"))
                                {
                                    if (LuisActionResolver.IsContextualAction(intentAction) && !LuisActionResolver.IsContextualAction(queryResult.NewAction))
                                    {
                                        return(new ActionExecutionContext(queryResult.NewIntent, queryResult.NewAction)
                                        {
                                            ChangeRootSignaling = true
                                        });
                                    }

                                    intentAction = queryResult.NewAction;
                                }
                            }
                            else
                            {
                                intentAction = queryResult.NewAction;
                            }
                        }
                    }

                    // re-evaluate
                    isValid = intentAction.IsValid(out validationResults);
                }
            }

            var result = await intentAction.FulfillAsync();

            // We just show the ToString() of the result - not care about the result type here
            Console.WriteLine(result != null ? result.ToString() : "Cannot resolve your query");

            return(actionExecutionContext);
        }
Exemple #2
0
            protected virtual async Task MessageReceivedAsync(IDialogContext context, IAwaitable <IMessageActivity> item)
            {
                var nextPromptIdx = 0;

                var validationResults = default(ICollection <ValidationResult>);

                this.luisAction.IsValid(out validationResults);

                if (item != null)
                {
                    var message = await item;

                    var paramName  = validationResults.First().MemberNames.First();
                    var paramValue = message.Text;

                    var result = await LuisActionResolver.QueryValueFromLuisAsync(this.luisService, this.luisAction, paramName, paramValue, context.CancellationToken);

                    if (result.Succeed)
                    {
                        nextPromptIdx++;
                    }
                    else if (!string.IsNullOrWhiteSpace(result.NewIntent) && result.NewAction != null)
                    {
                        var currentActionDefinition = LuisActionResolver.GetActionDefinition(this.luisAction);

                        var isContextual = false;
                        if (LuisActionResolver.IsValidContextualAction(result.NewAction, this.luisAction, out isContextual))
                        {
                            var executionContextChain = new List <ActionExecutionContext> {
                                new ActionExecutionContext(result.NewIntent, result.NewAction)
                            };

                            var childDialog = new LuisActionMissingEntitiesDialog(this.luisService, executionContextChain);

                            context.Call(childDialog, this.AfterContextualActionFinished);

                            return;
                        }
                        else if (isContextual & !LuisActionResolver.IsContextualAction(this.luisAction))
                        {
                            var newActionDefinition = LuisActionResolver.GetActionDefinition(result.NewAction);

                            await context.PostAsync($"Cannot execute action '{newActionDefinition.FriendlyName}' in the context of '{currentActionDefinition.FriendlyName}' - continuing with current action");
                        }
                        else if (!this.luisAction.GetType().Equals(result.NewAction.GetType()))
                        {
                            var newActionDefinition = LuisActionResolver.GetActionDefinition(result.NewAction);

                            var valid = LuisActionResolver.UpdateIfValidContextualAction(result.NewAction, this.luisAction, out isContextual);
                            if (!valid && isContextual)
                            {
                                await context.PostAsync($"Cannot switch to action '{newActionDefinition.FriendlyName}' from '{currentActionDefinition.FriendlyName}' due to invalid context - continuing with current action");
                            }
                            else if (currentActionDefinition.ConfirmOnSwitchingContext)
                            {
                                // serialize overrun info
                                this.overrunData = result;

                                PromptDialog.Confirm(
                                    context,
                                    this.AfterOverrunCurrentActionSelected,
                                    $"Do you want to discard the current action '{currentActionDefinition.FriendlyName}' and start executing '{newActionDefinition.FriendlyName}' action?");

                                return;
                            }
                            else
                            {
                                this.intentName = result.NewIntent;
                                this.luisAction = result.NewAction;

                                this.luisAction.IsValid(out validationResults);
                            }
                        }
                    }
                }

                if (validationResults.Count > nextPromptIdx)
                {
                    await context.PostAsync(validationResults.ElementAt(nextPromptIdx).ErrorMessage);

                    context.Wait(this.MessageReceivedAsync);
                }
                else
                {
                    context.Done(new ActionExecutionContext(this.intentName, this.luisAction));
                }
            }