Exemple #1
0
        internal override async Task <RecognizerResult> RecognizeInternalAsync(DialogContext dialogContext, Activity activity, HttpClient httpClient, CancellationToken cancellationToken)
        {
            var options = PredictionOptions;

            if (ExternalEntityRecognizer != null)
            {
                // call external entity recognizer
                var matches = await ExternalEntityRecognizer.RecognizeAsync(dialogContext, activity, cancellationToken).ConfigureAwait(false);

                if (matches.Entities != null && matches.Entities.Count > 0)
                {
                    options = new LuisV3.LuisPredictionOptions(options);
                    options.ExternalEntities = new List <LuisV3.ExternalEntity>();
                    var entities = matches.Entities;
                    var instance = entities["$instance"].ToObject <JObject>();
                    if (instance != null)
                    {
                        foreach (var child in entities)
                        {
                            // TODO: Checking for "text" because we get an extra non-real entity from the text recognizers
                            if (child.Key != "text" && child.Key != "$instance")
                            {
                                var instances = instance[child.Key]?.ToObject <JArray>();
                                var values    = child.Value.ToObject <JArray>();
                                if (instances != null && values != null &&
                                    instances.Count == values.Count)
                                {
                                    for (var i = 0; i < values.Count; ++i)
                                    {
                                        var childInstance = instances[i].ToObject <JObject>();
                                        if (childInstance != null &&
                                            childInstance.ContainsKey("startIndex") &&
                                            childInstance.ContainsKey("endIndex"))
                                        {
                                            var start = childInstance["startIndex"].Value <int>();
                                            var end   = childInstance["endIndex"].Value <int>();
                                            options.ExternalEntities.Add(new LuisV3.ExternalEntity(child.Key, start, end - start, child.Value));
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            // call luis recognizer with options.ExternalEntities populated from externalEntityRecognizer.
            return(await RecognizeAsync(dialogContext.Context, activity?.Text, options, httpClient, cancellationToken).ConfigureAwait(false));
        }
        public override async Task <RecognizerResult> RecognizeAsync(DialogContext dialogContext, Activity activity, CancellationToken cancellationToken = default, Dictionary <string, string> telemetryProperties = null, Dictionary <string, double> telemetryMetrics = null)
        {
            if (this._engine == null)
            {
                if (this.Model == null)
                {
                    var resourceExplorer = dialogContext.Context.TurnState.Get <ResourceExplorer>() ?? throw new ArgumentException("No resource Explorer was found in dialog context");
                    resourceExplorer.AddResourceType("yaml");
                    var modelId       = ResourceId.GetValue(dialogContext.State);
                    var modelResource = resourceExplorer.GetResource(modelId) ?? throw new ArgumentException($"{modelId} not found");
                    var yamlOrJson    = await modelResource.ReadTextAsync();

                    this._engine = new LucyEngine(yamlOrJson);
                }
                else
                {
                    this._engine = new LucyEngine(this.Model);
                }
            }

            List <LucyEntity> externalEntities = new List <LucyEntity>();

            if (ExternalEntityRecognizer != null)
            {
                var results = await ExternalEntityRecognizer.RecognizeAsync(dialogContext, activity, cancellationToken, telemetryProperties, telemetryMetrics).ConfigureAwait(false);

                externalEntities = GetEntitiesFromObject(activity, results.Entities).ToList();
            }

            var recognizerResult = new RecognizerResult();
            var lucyEntities     = _engine.MatchEntities(activity.Text ?? string.Empty, externalEntities);

            recognizerResult.Entities = GetRecognizerEntities(lucyEntities);

            var intents = this.Intents.GetValue(dialogContext.State) ?? new List <string>();

            if (intents.Any())
            {
                foreach (var lucyEntity in lucyEntities.Where(entity => intents.Contains(entity.Type)))
                {
                    recognizerResult.Intents.Add(lucyEntity.Type, new IntentScore()
                    {
                        Score = lucyEntity.Score
                    });
                }
            }
            else if (recognizerResult.Entities.Count > externalEntities.Count + 1)
            {
                recognizerResult.Intents.Add(MatchedIntent, new IntentScore()
                {
                    Score = lucyEntities.Max(e => e.Score)
                });
            }

            if (!recognizerResult.Intents.Any())
            {
                recognizerResult.Intents.Add(NoneIntent, new IntentScore {
                    Score = 1.0f
                });
            }

            await dialogContext.Context.TraceActivityAsync(nameof(LucyRecognizer), JObject.FromObject(recognizerResult), "RecognizerResult", "Lucy RecognizerResult", cancellationToken).ConfigureAwait(false);

            this.TrackRecognizerResult(dialogContext, "LucyRecognizerResult", this.FillRecognizerResultTelemetryProperties(recognizerResult, telemetryProperties), telemetryMetrics);

            return(recognizerResult);
        }
Exemple #3
0
        /// <summary>
        /// Return recognition results.
        /// </summary>
        /// <param name="dc">Context object containing information for a single turn of conversation with a user.</param>
        /// <param name="activity">The incoming activity received from the user. The Text property value is used as the query text for QnA Maker.</param>
        /// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
        /// <param name="telemetryProperties">Additional properties to be logged to telemetry with the LuisResult event.</param>
        /// <param name="telemetryMetrics">Additional metrics to be logged to telemetry with the LuisResult event.</param>
        /// <returns>A <see cref="RecognizerResult"/> containing the QnA Maker result.</returns>
        public override async Task <RecognizerResult> RecognizeAsync(DialogContext dc, Schema.Activity activity, CancellationToken cancellationToken, Dictionary <string, string> telemetryProperties = null, Dictionary <string, double> telemetryMetrics = null)
        {
            var text            = activity.Text ?? string.Empty;
            var detectAmbiguity = DetectAmbiguousIntents.GetValue(dc.State);

            _modelFolder  = ModelFolder.GetValue(dc.State);
            _snapshotFile = SnapshotFile.GetValue(dc.State);

            InitializeModel();

            var recognizerResult = new RecognizerResult()
            {
                Text    = text,
                Intents = new Dictionary <string, IntentScore>(),
            };

            if (string.IsNullOrWhiteSpace(text))
            {
                // nothing to recognize, return empty recognizerResult
                return(recognizerResult);
            }

            if (ExternalEntityRecognizer != null)
            {
                // Run external recognition
                var externalResults = await ExternalEntityRecognizer.RecognizeAsync(dc, activity, cancellationToken, telemetryProperties, telemetryMetrics).ConfigureAwait(false);

                recognizerResult.Entities = externalResults.Entities;
            }

            // Score with orchestrator
            var results = _resolver.Score(text);

            // Add full recognition result as a 'result' property
            recognizerResult.Properties.Add(ResultProperty, results);

            if (results.Any())
            {
                var topScore = results[0].Score;

                // if top scoring intent is less than threshold, return None
                if (topScore < UnknownIntentFilterScore)
                {
                    recognizerResult.Intents.Add(NoneIntent, new IntentScore()
                    {
                        Score = 1.0
                    });
                }
                else
                {
                    // add top score
                    recognizerResult.Intents.Add(results[0].Label.Name, new IntentScore()
                    {
                        Score = results[0].Score
                    });

                    // Disambiguate if configured
                    if (detectAmbiguity)
                    {
                        var thresholdScore   = DisambiguationScoreThreshold.GetValue(dc.State);
                        var classifyingScore = Math.Round(topScore, 2) - Math.Round(thresholdScore, 2);
                        var ambiguousResults = results.Where(item => item.Score >= classifyingScore).ToList();

                        if (ambiguousResults.Count > 1)
                        {
                            // create a RecognizerResult for each ambiguous result.
                            var recognizerResults = ambiguousResults.Select(result => new RecognizerResult()
                            {
                                Text        = text,
                                AlteredText = result.ClosestText,
                                Entities    = recognizerResult.Entities,
                                Properties  = recognizerResult.Properties,
                                Intents     = new Dictionary <string, IntentScore>()
                                {
                                    { result.Label.Name, new IntentScore()
                                      {
                                          Score = result.Score
                                      } }
                                },
                            });

                            // replace RecognizerResult with ChooseIntent => Ambiguous recognizerResults as candidates.
                            recognizerResult = CreateChooseIntentResult(recognizerResults.ToDictionary(result => Guid.NewGuid().ToString(), result => result));
                        }
                    }
                }
            }
            else
            {
                // Return 'None' if no intent matched.
                recognizerResult.Intents.Add(NoneIntent, new IntentScore()
                {
                    Score = 1.0
                });
            }

            await dc.Context.TraceActivityAsync($"{nameof(OrchestratorAdaptiveRecognizer)}Result", JObject.FromObject(recognizerResult), nameof(OrchestratorAdaptiveRecognizer), "Orchestrator Recognition", cancellationToken).ConfigureAwait(false);

            TrackRecognizerResult(dc, $"{nameof(OrchestratorAdaptiveRecognizer)}Result", FillRecognizerResultTelemetryProperties(recognizerResult, telemetryProperties, dc), telemetryMetrics);

            return(recognizerResult);
        }