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);
        }
Beispiel #2
0
        public static async Task <QueryValueResult> QueryValueFromLuisAsync(
            ILuisService service,
            ILuisAction action,
            string paramName,
            object paramValue,
            CancellationToken token,
            Func <PropertyInfo, IEnumerable <EntityRecommendation>, EntityRecommendation> entityExtractor = null)
        {
            var originalValue = paramValue;

            service.ThrowIfNull(nameof(service));
            action.ThrowIfNull(nameof(action));
            service.ThrowIfNull(nameof(service));
            paramValue.ThrowIfNull(nameof(paramValue));

            if (string.IsNullOrWhiteSpace(paramName))
            {
                throw new ArgumentNullException(nameof(paramName));
            }

            var result = await service.QueryAsync(paramValue.ToString(), token);

            var queryIntent = result.Intents.FirstOrDefault();

            if (!Intents.None.Equals(queryIntent.Intent, StringComparison.InvariantCultureIgnoreCase))
            {
                var newAction = new LuisActionResolver(action.GetType().Assembly).ResolveActionFromLuisIntent(result, out string newIntentName);
                if (newAction != null && !newAction.GetType().Equals(action.GetType()))
                {
                    return(new QueryValueResult(false)
                    {
                        NewAction = newAction,
                        NewIntent = newIntentName
                    });
                }
            }

            var properties = new List <PropertyInfo>
            {
                action.GetType().GetProperty(paramName, BindingFlags.Public | BindingFlags.Instance)
            };

            if (!AssignEntitiesToMembers(action, properties, result.Entities, entityExtractor))
            {
                return(new QueryValueResult(AssignValue(action, properties.First(), originalValue)));
            }

            return(new QueryValueResult(true));
        }
        public virtual bool IsValid(out ICollection <ValidationResult> validationResults)
        {
            var context = new ValidationContext(this, null, null);

            validationResults = new List <ValidationResult>();
            var result = Validator.TryValidateObject(this, context, validationResults, true);

            // do order properties
            validationResults = validationResults
                                .OrderBy(r =>
            {
                var paramAttrib = LuisActionResolver.GetParameterDefinition(this, r.MemberNames.First());
                return(paramAttrib != null ? paramAttrib.Order : int.MaxValue);
            })
                                .ThenBy(r => r.MemberNames.First())
                                .ToList();

            return(result);
        }
Beispiel #4
0
        public static ILuisAction BuildContextForContextualAction(ILuisAction action, out string intentName)
        {
            action.ThrowIfNull(nameof(action));

            if (!IsContextualAction(action))
            {
                intentName = null;
                return(null);
            }

            var contextType = GetActionInterface(action)
                              .First(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(ILuisContextualAction <>))
                              .GetGenericArguments()[0];

            var result = Activator.CreateInstance(contextType) as ILuisAction;

            intentName = LuisActionResolver.GetActionDefinition(result).IntentName;

            var isContextual = false;

            LuisActionResolver.IsValidContextualAction(action, result, out isContextual);

            return(result);
        }
        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);
        }
        protected virtual async Task MessageReceivedAsync(IDialogContext context, IAwaitable <IMessageActivity> item)
        {
            var nextPromptIdx = 0;

            this.luisAction.IsValid(out ICollection <ValidationResult> 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));
            }
        }