Beispiel #1
0
        protected virtual async Task <object> PerformActionFulfillment(IDialogContext context, IAwaitable <IMessageActivity> item, ILuisAction luisAction)
        {
            var message = await item;

            return(await luisAction.FulfillAsync(context, message.Text));
        }
Beispiel #2
0
        protected virtual async Task DispatchToLuisActionActivityHandler(IDialogContext context, IAwaitable <IMessageActivity> item, string intentName, ILuisAction luisAction)
        {
            var actionHandlerByIntent = new Dictionary <string, LuisActionActivityHandler>(this.GetActionHandlersByIntent());

            var handler = default(LuisActionActivityHandler);

            if (!actionHandlerByIntent.TryGetValue(intentName, out handler))
            {
                handler = actionHandlerByIntent[string.Empty];
            }

            if (handler != null)
            {
                await handler(context, item, await this.PerformActionFulfillment(context, item, luisAction));
            }
            else
            {
                throw new Exception($"No default intent handler found.");
            }
        }
            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));
                }
            }
Beispiel #4
0
        private static bool AssignEntitiesToMembers(
            ILuisAction action,
            IEnumerable <PropertyInfo> properties,
            IEnumerable <EntityRecommendation> entities,
            Func <PropertyInfo, IEnumerable <EntityRecommendation>, EntityRecommendation> entityExtractor = null)
        {
            var result = true;

            if (action == null)
            {
                throw new ArgumentNullException(nameof(action));
            }

            if (properties == null)
            {
                throw new ArgumentNullException(nameof(properties));
            }

            if (entities == null)
            {
                throw new ArgumentNullException(nameof(entities));
            }

            if (!entities.Any())
            {
                return(!result);
            }

            // Cross match entities to copy resolution values for custom entities from pairs
            foreach (var group in entities.GroupBy(e => e.Entity))
            {
                if (group.Count() > 1)
                {
                    var entityToUpdate  = group.FirstOrDefault(e => !BuiltInTypes.IsBuiltInType(e.Type));
                    var entityWithValue = group.FirstOrDefault(e => e.Resolution != null);
                    if (entityToUpdate != null && entityWithValue != null)
                    {
                        entityToUpdate.Resolution = entityWithValue.Resolution;
                    }
                }
            }

            foreach (var property in properties)
            {
                var matchingEntity   = default(EntityRecommendation);
                var matchingEntities = default(IEnumerable <EntityRecommendation>);

                // Find using custom type from attrib if available
                var paramAttrib = property.GetCustomAttributes <LuisActionBindingParamAttribute>(true).FirstOrDefault();
                if (paramAttrib != null)
                {
                    matchingEntities = entities.Where(e => e.Type == paramAttrib.CustomType);
                }

                // Find using property name
                if (matchingEntities == null || !matchingEntities.Any())
                {
                    matchingEntities = entities.Where(e => e.Type == property.Name);
                }

                // Find using builtin type from attrib if available
                if ((matchingEntities == null || !matchingEntities.Any()) && paramAttrib != null)
                {
                    matchingEntities = entities.Where(e => e.Type == paramAttrib.BuiltinType);
                }

                // If callback available then use it
                if (matchingEntities.Count() > 1)
                {
                    if (entityExtractor != null)
                    {
                        matchingEntity = entityExtractor(property, matchingEntities);
                    }
                }
                else
                {
                    matchingEntity = matchingEntities.FirstOrDefault();
                }

                // Prioritize resolution
                if (matchingEntity != null)
                {
                    object paramValue = null;
                    if (matchingEntity.Resolution != null && matchingEntity.Resolution.Count > 0)
                    {
                        var resolutionValue = matchingEntity.Resolution.First().Value;
                        if (resolutionValue is IList <object> )
                        {
                            // multiple resolution values - datetimev2
                            var dateTimeResolutionValues = GetDateTimeValues(matchingEntity);
                            paramValue = dateTimeResolutionValues["value"];
                        }

                        if (paramValue == null)
                        {
                            // other built-in with single resolution value
                            paramValue = resolutionValue;
                        }
                    }
                    else
                    {
                        paramValue = matchingEntity.Entity;
                    }

                    result &= AssignValue(action, property, paramValue);
                }
                else if (matchingEntities.Count() > 0 &&
                         matchingEntities.Count(e => e.Resolution != null && e.Resolution.First().Value is JArray) == matchingEntities.Count())
                {
                    var paramValues = new JArray();

                    foreach (var currentMatchingEntity in matchingEntities)
                    {
                        var values = currentMatchingEntity.Resolution.First().Value as JArray;
                        foreach (var value in values)
                        {
                            paramValues.Add(value);
                        }
                    }

                    result &= AssignValue(action, property, paramValues);
                }
                else
                {
                    result = false;
                }
            }

            return(result);
        }
Beispiel #5
0
 private static Type[] GetActionInterface(ILuisAction action)
 {
     return(action.GetType().GetInterfaces());
 }
Beispiel #6
0
 public static bool IsContextualAction(ILuisAction action)
 {
     action.ThrowIfNull(nameof(action));
     return(GetActionInterface(action).Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(ILuisContextualAction <>)));
 }
Beispiel #7
0
        private static bool FindEntity(ILuisAction action, IEnumerable <PropertyInfo> properties, IEnumerable <EntityRecommendation> entities, Func <PropertyInfo, IEnumerable <EntityRecommendation>, EntityRecommendation> entityExtractor)
        {
            bool result = true;

            foreach (var property in properties)
            {
                var matchingEntity   = default(EntityRecommendation);
                var matchingEntities = default(IEnumerable <EntityRecommendation>);
                var paramAttrib      = property.GetCustomAttributes <LuisActionBindingParamAttribute>(true).FirstOrDefault();

                // Find using custom type from attrib if available
                if (paramAttrib != null)
                {
                    matchingEntities = entities.Where(e => e.Type == paramAttrib.CustomType);
                }

                // Find using property name
                if (matchingEntities != null || !matchingEntities.Any())
                {
                    matchingEntities = entities.Where(e => e.Type == property.Name);
                }

                // Find using builtin type from attrib if available
                if ((matchingEntities != null || !matchingEntities.Any()) && paramAttrib != null)
                {
                    matchingEntities = entities.Where(e => e.Type == paramAttrib.BuiltinType);
                }

                // If callback available then use it
                if (matchingEntities.Count() > 1)
                {
                    matchingEntity = entityExtractor?.Invoke(property, matchingEntities);
                }
                else
                {
                    matchingEntity = matchingEntities.FirstOrDefault();
                }

                // Prioritize resolution
                if (matchingEntity != null)
                {
                    var paramValue = matchingEntity.Resolution != null && matchingEntity.Resolution.Count > 0
                        ? matchingEntity.Resolution.First().Value
                        : matchingEntity.Entity;

                    result &= AssignValue(action, property, paramValue);
                }
                else if (matchingEntities.Count() > 0
                         &&
                         matchingEntities.Count(e => e.Resolution != null && e.Resolution.First().Value is JArray) == matchingEntities.Count())
                {
                    var paramValues = new JArray();
                    foreach (var currentMatchingEntity in matchingEntities)
                    {
                        var values = currentMatchingEntity.Resolution.First().Value as JArray;
                        foreach (var value in values)
                        {
                            paramValues.Add(value);
                        }
                    }

                    result &= AssignValue(action, property, paramValues);
                }
                else
                {
                    result = false;
                }
            }

            return(result);
        }
Beispiel #8
0
 protected virtual async Task <object> PerformActionFulfillment(IDialogContext context, IMessageActivity item, ILuisAction luisAction)
 {
     return(await luisAction.FulfillAsync());
 }
Beispiel #9
0
 /// <summary>
 /// Construct the Action Context.
 /// </summary>
 /// <param name="intent">The LUIS Intent name that triggered the action.</param>
 /// <param name="action">The LUIS Action Binding model that was triggered.</param>
 public ActionExecutionContext(string intent, ILuisAction action)
 {
     this.Intent = intent;
     this.Action = action;
 }