Exemplo n.º 1
0
        protected override async Task MessageReceived(IDialogContext context, IAwaitable <IMessageActivity> item)
        {
            var message     = await item;
            var messageText = await GetLuisQueryTextAsync(context, message);

            var tasks   = this.services.Select(s => s.QueryAsync(messageText, context.CancellationToken)).ToArray();
            var results = await Task.WhenAll(tasks);

            var winners = from result in results.Select((value, index) => new { value, index })
                          let resultWinner = this.BestIntentFrom(result.value)
                                             where resultWinner != null
                                             select new LuisServiceResult(result.value, resultWinner, this.services[result.index]);

            var winner = this.BestResultFrom(winners);

            if (winner == null)
            {
                throw new InvalidOperationException("No winning intent selected from Luis results.");
            }

            var intentName = default(string);
            var luisAction = this.actionResolver.ResolveActionFromLuisIntent(winner.Result, out intentName);

            if (luisAction != null)
            {
                var executionContextChain = new List <ActionExecutionContext> {
                    new ActionExecutionContext(intentName, luisAction)
                };
                while (LuisActionResolver.IsContextualAction(luisAction))
                {
                    var luisActionDefinition = default(LuisActionBindingAttribute);
                    if (!LuisActionResolver.CanStartWithNoContextAction(luisAction, out luisActionDefinition))
                    {
                        await context.PostAsync($"Cannot start contextual action '{luisActionDefinition.FriendlyName}' without a valid context.");

                        return;
                    }

                    luisAction = LuisActionResolver.BuildContextForContextualAction(luisAction, out intentName);
                    if (luisAction != null)
                    {
                        this.onContextCreation?.Invoke(luisAction, context);

                        executionContextChain.Insert(0, new ActionExecutionContext(intentName, luisAction));
                    }
                }

                var validationResults = default(ICollection <ValidationResult>); //check the validation result
                if (!luisAction.IsValid(out validationResults))
                {
                    var childDialog = new LuisActionMissingEntitiesDialog(winner.LuisService, executionContextChain);

                    context.Call(childDialog, this.LuisActionMissingDialogFinished);
                }
                else
                {
                    await this.DispatchToLuisActionActivityHandler(context, item, intentName, luisAction);
                }
            }
        }
Exemplo n.º 2
0
            private async Task AfterContextualActionFinished(IDialogContext context, IAwaitable <ActionExecutionContext> executionContext)
            {
                var executionContextResult = await executionContext;

                if (executionContextResult.ChangeRootSignaling)
                {
                    if (LuisActionResolver.IsContextualAction(this.luisAction))
                    {
                        context.Done(executionContextResult);

                        return;
                    }
                    else
                    {
                        this.intentName = executionContextResult.Intent;
                        this.luisAction = executionContextResult.Action;
                    }
                }
                else
                {
                    var result = await executionContextResult.Action.FulfillAsync();

                    if (result is string)
                    {
                        await context.PostAsync(result.ToString());
                    }
                }

                await this.MessageReceivedAsync(context, null);
            }
Exemplo n.º 3
0
        public async Task <ActionResult> Index(QueryViewModel model)
        {
            if (!model.HasIntent)
            {
                var luisService = new LuisService(new LuisModelAttribute(ConfigurationManager.AppSettings["LUIS_ModelId"], ConfigurationManager.AppSettings["LUIS_SubscriptionKey"]));
                var luisResult  = await luisService.QueryAsync(model.Query, CancellationToken.None);

                var resolver = new LuisActionResolver(typeof(GetTimeInPlaceAction).Assembly);
                var action   = resolver.ResolveActionFromLuisIntent(luisResult);

                // Triggering Contextual Action from scratch is not supported on this Web Sample
                if (action != null && !LuisActionResolver.IsContextualAction(action))
                {
                    model.LuisAction = action;

                    // TODO: this is dangerous. This should be stored somewhere else, not in the client, or at least encrypted
                    model.LuisActionType = action.GetType().AssemblyQualifiedName;
                }
                else
                {
                    // no action recnogized
                    return(this.View(new QueryViewModel()));
                }
            }

            ModelState.Clear();
            var isValid = TryValidateModel(model.LuisAction);

            if (isValid)
            {
                // fulfill
                var actionResult = await model.LuisAction.FulfillAsync();

                if (actionResult == null)
                {
                    actionResult = "Cannot resolve your query";
                }

                return(this.View("ActionFulfill", actionResult));
            }
            else
            {
                // not valid, continue to present form with missing/invalid parameters
                return(this.View(model));
            }
        }
Exemplo n.º 4
0
        protected override async Task MessageReceived(IDialogContext context, IAwaitable <IMessageActivity> item)
        {
            LuisServiceResult winner = await GetWinner(context, item);

            if (winner == null)
            {
                throw new InvalidOperationException("No winning intent selected from Luis results.");
            }

            ILuisAction luisAction = this.actionResolver.ResolveActionFromLuisIntent(winner.Result, out string intentName);

            if (luisAction != null)
            {
                var executionContextChain = new ActionExecutionContext(intentName, luisAction).ToSingleList();
                while (LuisActionResolver.IsContextualAction(luisAction))
                {
                    if (!LuisActionResolver.CanStartWithNoContextAction(luisAction, out LuisActionBindingAttribute luisActionDefinition))
                    {
                        await context.PostAsync($"Cannot start contextual action '{luisActionDefinition.FriendlyName}' without a valid context.");

                        return;
                    }

                    luisAction = LuisActionResolver.BuildContextForContextualAction(luisAction, out intentName);
                    if (luisAction != null)
                    {
                        this.onContextCreation?.Invoke(luisAction, context);
                        executionContextChain.Insert(0, new ActionExecutionContext(intentName, luisAction));
                    }
                }

                if (!luisAction.IsValid(out ICollection <ValidationResult> validationResults))
                {
                    var childDialog = new LuisActionMissingEntitiesDialog(winner.LuisService, executionContextChain);
                    context.Call(childDialog, this.LuisActionMissingDialogFinished);
                }
                else
                {
                    await this.DispatchToLuisActionActivityHandler(context, item, intentName, luisAction);
                }
            }
        }
Exemplo n.º 5
0
        private static async Task RunQuery(string query)
        {
            // Process message
            var luisService = new LuisService(new LuisModelAttribute(ConfigurationManager.AppSettings["LUIS_ModelId"], ConfigurationManager.AppSettings["LUIS_SubscriptionKey"]));
            var luisResult  = await luisService.QueryAsync(query, CancellationToken.None);

            // Try to resolve intent to action
            var intentName     = default(string);
            var intentEntities = default(IList <EntityRecommendation>);
            var intentAction   = new LuisActionResolver(typeof(GetTimeInPlaceAction).Assembly)
                                 .ResolveActionFromLuisIntent(luisResult, out intentName, out intentEntities);

            if (intentAction != null)
            {
                var executionContextChain = new List <ActionExecutionContext> {
                    new ActionExecutionContext(intentName, intentAction)
                };
                while (LuisActionResolver.IsContextualAction(intentAction))
                {
                    var luisActionDefinition = default(LuisActionBindingAttribute);
                    if (!LuisActionResolver.CanStartWithNoContextAction(intentAction, out luisActionDefinition))
                    {
                        Console.WriteLine($"Cannot start contextual action '{luisActionDefinition.FriendlyName}' without a valid context.");

                        return;
                    }

                    intentAction = LuisActionResolver.BuildContextForContextualAction(intentAction, out intentName);
                    if (intentAction != null)
                    {
                        executionContextChain.Insert(0, new ActionExecutionContext(intentName, intentAction));
                    }
                }

                await RunActions(luisService, executionContextChain);
            }
            else
            {
                Console.WriteLine("Could not understand the input.");
            }
        }
Exemplo n.º 6
0
            private async Task AfterOverrunCurrentActionSelected(IDialogContext context, IAwaitable <bool> result)
            {
                if (await result == true)
                {
                    // if switching from contextual to other root
                    if (LuisActionResolver.IsContextualAction(this.luisAction) && !LuisActionResolver.IsContextualAction(this.overrunData.NewAction))
                    {
                        context.Done(new ActionExecutionContext(this.overrunData.NewIntent, this.overrunData.NewAction)
                        {
                            ChangeRootSignaling = true
                        });

                        return;
                    }

                    this.intentName = this.overrunData.NewIntent;
                    this.luisAction = this.overrunData.NewAction;
                }

                // clean overrunData - avoid serialization payload
                this.overrunData = null;

                await this.MessageReceivedAsync(context, null);
            }
Exemplo n.º 7
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);
        }
Exemplo n.º 8
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));
                }
            }