public ScopeScorable(TryResolve tryResolve, IScorable <IResolver, InnerScore> inner)
     : base(inner)
 {
     SetField.NotNull(out this.tryResolve, nameof(tryResolve), tryResolve);
 }
 public Scope(TryResolve tryResolve, IResolver inner)
     : base(inner)
 {
     SetField.NotNull(out this.tryResolve, nameof(this.tryResolve), tryResolve);
 }
Example #3
0
        public static IScorable <IResolver, object> Make(Type type, Func <ILuisModel, ILuisService> make)
        {
            var methods          = type.GetMethods();
            var scorableByMethod = methods.ToDictionary(m => m, m => new MethodScorable(m));

            var luisSpec =
                from method in methods
                from model in AttributesFor <LuisModelAttribute>(method)
                from intent in AttributesFor <LuisIntentAttribute>(method)
                select new { method, intent, model };

            // for a given LUIS model and intent, fold the corresponding method scorables together to enable overload resolution
            var luisScorables =
                from spec in luisSpec
                group spec by new { spec.model, spec.intent } into modelIntents
            let method = modelIntents.Select(m => scorableByMethod[m.method]).ToArray().Fold(Binding.ResolutionComparer.Instance)
                         select new LuisIntentScorable <Binding, Binding>(modelIntents.Key.model, modelIntents.Key.intent, method);

            var regexSpec =
                from method in methods
                from pattern in AttributesFor <RegexPatternAttribute>(method)
                select new { method, pattern };

            // for a given regular expression pattern, fold the corresponding method scorables together to enable overload resolution
            var regexScorables =
                from spec in regexSpec
                group spec by spec.pattern into patterns
                let method                         = patterns.Select(m => scorableByMethod[m.method]).ToArray().Fold(Binding.ResolutionComparer.Instance)
                                         let regex = new Regex(patterns.Key.Pattern)
                                                     select new RegexMatchScorable <Binding, Binding>(regex, method);

            var methodScorables = scorableByMethod.Values;

            // fold all of the scorables together by score type, and select the best
            IScorable <IResolver, object> regexAll  = regexScorables.ToArray().Fold(MatchComparer.Instance);               //.Select((_, m) => 1.0);
            IScorable <IResolver, object> luisAll   = luisScorables.ToArray().Fold(IntentComparer.Instance);               //.Select((_, i) => i.Score.Value);
            IScorable <IResolver, object> methodAll = methodScorables.ToArray().Fold(Binding.ResolutionComparer.Instance); //.Select((_, b) => 1.0);

            // introduce a precedence order to prefer regex over luis over generic method matches
            var all = new[] { regexAll, luisAll, methodAll };

            // select the first scorable that matches
            var winner = all.First();

            // introduce a lifetime scope to the scoring process to memoize service calls to LUIS
            TryResolve tryResolve = (Type t, object tag, out object value) =>
            {
                var model = tag as ILuisModel;
                if (model != null)
                {
                    value = new MemoizingLuisService(make(model));
                    return(true);
                }

                value = null;
                return(false);
            };
            var scope = new ScopeScorable <object, object>(tryResolve, winner);

            return(scope);
        }