示例#1
0
        private async Task <RecognizerResult> RecognizeAsync(ITurnContext turnContext, string utterance, LuisV3.LuisPredictionOptions options, HttpClient httpClient, CancellationToken cancellationToken)
        {
            RecognizerResult recognizerResult;
            JObject          luisResponse = null;

            if (string.IsNullOrWhiteSpace(utterance))
            {
                recognizerResult = new RecognizerResult
                {
                    Text = utterance
                };
            }
            else
            {
                luisResponse = await GetLuisResponseAsync(utterance, options, httpClient, cancellationToken).ConfigureAwait(false);

                recognizerResult = BuildRecognizerResultFromLuisResponse(luisResponse, utterance);
            }

            var traceInfo = JObject.FromObject(
                new
            {
                recognizerResult,
                luisModel = new
                {
                    ModelID = Application.ApplicationId,
                },
                luisOptions = options,
                luisResult  = luisResponse,
            });

            await turnContext.TraceActivityAsync("LuisRecognizer", traceInfo, LuisTraceType, LuisTraceLabel, cancellationToken).ConfigureAwait(false);

            return(recognizerResult);
        }
        private async Task <RecognizerResult> RecognizeInternalAsync(ITurnContext turnContext, Dictionary <string, string> telemetryProperties, Dictionary <string, double> telemetryMetrics, CancellationToken cancellationToken)
        {
            BotAssert.ContextNotNull(turnContext);

            if (turnContext.Activity.Type != ActivityTypes.Message)
            {
                return(null);
            }

            var utterance = turnContext.Activity?.AsMessageActivity()?.Text;

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

            var luisResult = await _runtime.Prediction.ResolveAsync(
                _application.ApplicationId,
                utterance,
                timezoneOffset : _options.TimezoneOffset,
                verbose : _options.IncludeAllIntents,
                staging : _options.Staging,
                spellCheck : _options.SpellCheck,
                bingSpellCheckSubscriptionKey : _options.BingSpellCheckSubscriptionKey,
                log : _options.Log ?? true,
                cancellationToken : cancellationToken).ConfigureAwait(false);

            var recognizerResult = new RecognizerResult
            {
                Text        = utterance,
                AlteredText = luisResult.AlteredQuery,
                Intents     = LuisUtil.GetIntents(luisResult),
                Entities    = LuisUtil.ExtractEntitiesAndMetadata(luisResult.Entities, luisResult.CompositeEntities, _options.IncludeInstanceData ?? true),
            };

            LuisUtil.AddProperties(luisResult, recognizerResult);
            if (_includeApiResults)
            {
                recognizerResult.Properties.Add("luisResult", luisResult);
            }

            // Log telemetry
            await OnRecognizerResultAsync(recognizerResult, turnContext, telemetryProperties, telemetryMetrics, cancellationToken).ConfigureAwait(false);

            var traceInfo = JObject.FromObject(
                new
            {
                recognizerResult,
                luisModel = new
                {
                    ModelID = _application.ApplicationId,
                },
                luisOptions = _options,
                luisResult,
            });

            await turnContext.TraceActivityAsync("LuisRecognizer", traceInfo, LuisTraceType, LuisTraceLabel, cancellationToken).ConfigureAwait(false);

            return(recognizerResult);
        }
        private async Task SendErrorMessageAsync(ITurnContext turnContext, Exception exception)
        {
            try
            {
                // Send a message to the user.
                var errorMessageText = "The bot encountered an error or bug.";
                var errorMessage     = MessageFactory.Text(errorMessageText, errorMessageText, InputHints.IgnoringInput);
                errorMessage.Value = exception;
                await turnContext.SendActivityAsync(errorMessage);

                await turnContext.SendActivityAsync($"Exception: {exception.Message}");

                await turnContext.SendActivityAsync(exception.ToString());

                errorMessageText = "To continue to run this bot, please fix the bot source code.";
                errorMessage     = MessageFactory.Text(errorMessageText, errorMessageText, InputHints.ExpectingInput);
                await turnContext.SendActivityAsync(errorMessage);

                // Send a trace activity, which will be displayed in the Bot Framework Emulator.
                await turnContext.TraceActivityAsync("OnTurnError Trace", exception.ToString(), "https://www.botframework.com/schemas/error", "TurnError");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"Exception caught in SendErrorMessageAsync : {ex}");
            }
        }
        public async Task OnExceptionAsync(ITurnContext turnContext, Exception exception)
        {
            await turnContext.SendActivityAsync("Sorry, it looks like something went wrong.");

            if (environment.IsDevelopment())
            {
                await turnContext.TraceActivityAsync("Exception", exception);
            }
        }
示例#5
0
        public override async Task EndDialogAsync(ITurnContext turnContext, DialogInstance instance, DialogReason reason, CancellationToken cancellationToken = default)
        {
            if (reason == DialogReason.CancelCalled || reason == DialogReason.ReplaceCalled)
            {
                await turnContext.TraceActivityAsync($"{GetType().Name}.EndDialogAsync()", label : $"ActivityType: {turnContext.Activity.Type}", cancellationToken : cancellationToken).ConfigureAwait(false);

                var activity = (Activity)Activity.CreateEndOfConversationActivity();
                ApplyParentActivityProperties(turnContext, activity, null);

                await SendToSkillAsync(null, (Activity)activity, cancellationToken).ConfigureAwait(false);
            }

            await base.EndDialogAsync(turnContext, instance, reason, cancellationToken).ConfigureAwait(false);
        }
    private async Task ProcessTurnError(ITurnContext turnContext, Exception ex)
    {
        if (logger != null)
        {
            logger.LogError(ex, $"[OnTurnError] Error : {ex.Message}");
        }

        await turnContext.SendActivityAsync("The bot encountered an error");

        await turnContext.TraceActivityAsync("OnTurnError Trace", ex.Message, "https://www.botframework.com/schemas/error", "TurnError");

        if (conversationState != null)
        {
            await conversationState.DeleteAsync(turnContext);
        }
    }
        private async Task SendErrorMessageAsync(ITurnContext turnContext, Exception exception)
        {
            try
            {
                _telemetryClient.TrackException(exception);

                // Send a message to the user.
                await turnContext.SendActivityAsync(_templateEngine.GenerateActivityForLocale(RestaurantBookingSharedResponses.ErrorMessage));

                // Send a trace activity, which will be displayed in the Bot Framework Emulator.
                // Note: we return the entire exception in the value property to help the developer;
                // this should not be done in production.
                await turnContext.TraceActivityAsync("OnTurnError Trace", exception.ToString(), "https://www.botframework.com/schemas/error", "TurnError");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"Exception caught in SendErrorMessageAsync : {ex}");
            }
        }
        public override async Task EndDialogAsync(ITurnContext turnContext, DialogInstance instance, DialogReason reason, CancellationToken cancellationToken = default)
        {
            // Send of of conversation to the skill if the dialog has been cancelled.
            if (reason == DialogReason.CancelCalled || reason == DialogReason.ReplaceCalled)
            {
                await turnContext.TraceActivityAsync($"{GetType().Name}.EndDialogAsync()", label : $"ActivityType: {turnContext.Activity.Type}", cancellationToken : cancellationToken).ConfigureAwait(false);

                var activity = (Activity)Activity.CreateEndOfConversationActivity();

                // Apply conversation reference and common properties from incoming activity before sending.
                activity.ApplyConversationReference(turnContext.Activity.GetConversationReference(), true);
                activity.ChannelData = turnContext.Activity.ChannelData;
                activity.Properties  = turnContext.Activity.Properties;

                await SendToSkillAsync(turnContext, activity, cancellationToken).ConfigureAwait(false);
            }

            await base.EndDialogAsync(turnContext, instance, reason, cancellationToken).ConfigureAwait(false);
        }
示例#9
0
        internal override async Task <RecognizerResult> RecognizeInternalAsync(ITurnContext turnContext, HttpClient httpClient, CancellationToken cancellationToken)
        {
            BotAssert.ContextNotNull(turnContext);

            if (turnContext.Activity == null || turnContext.Activity.Type != ActivityTypes.Message)
            {
                return(null);
            }

            var utterance = turnContext.Activity.AsMessageActivity()?.Text;
            RecognizerResult recognizerResult;
            LuisResult       luisResult = null;

            if (string.IsNullOrWhiteSpace(utterance))
            {
                recognizerResult = new RecognizerResult {
                    Text = utterance
                };
            }
            else
            {
                luisResult = await GetLuisResultAsync(utterance, httpClient, cancellationToken).ConfigureAwait(false);

                recognizerResult = BuildRecognizerResultFromLuisResult(luisResult, utterance);
            }

            var traceInfo = JObject.FromObject(
                new
            {
                recognizerResult,
                luisModel = new
                {
                    ModelID = Application.ApplicationId,
                },
                luisOptions = PredictionOptions,
                luisResult,
            });

            await turnContext.TraceActivityAsync("LuisRecognizer", traceInfo, LuisTraceType, LuisTraceLabel, cancellationToken).ConfigureAwait(false);

            return(recognizerResult);
        }
        private async Task SendErrorMessageAsync(ITurnContext turnContext, Exception exception)
        {
            try
            {
                // Send a message to the user.
                CultureInfo.CurrentUICulture = new CultureInfo(turnContext.Activity.Locale ?? "en-us");
                await turnContext.SendActivityAsync(_templateManager.GenerateActivity(PhoneSharedResponses.ErrorMessage));

                await turnContext.SendActivityAsync(new Activity(type : ActivityTypes.Trace, text : $"Phone Skill Error: {exception.Message} | {exception.StackTrace}"));

                _telemetryClient.TrackException(exception);

                // Send a trace activity, which will be displayed in the Bot Framework Emulator.
                // Note: we return the entire exception in the value property to help the developer;
                // this should not be done in production.
                await turnContext.TraceActivityAsync("OnTurnError Trace", exception.ToString(), "https://www.botframework.com/schemas/error", "TurnError");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"Exception caught in SendErrorMessageAsync : {ex}");
            }
        }
示例#11
0
        private async Task SendErrorMessageAsync(ITurnContext turnContext, Exception exception)
        {
            try
            {
                // Send a message to the user.
                var errorMessageText = "The skill encountered an error or bug.";
                var errorMessage     = MessageFactory.Text(errorMessageText + Environment.NewLine + exception, errorMessageText, InputHints.IgnoringInput);
                await turnContext.SendActivityAsync(errorMessage);

                errorMessageText = "To continue to run this bot, please fix the bot source code.";
                errorMessage     = MessageFactory.Text(errorMessageText, errorMessageText, InputHints.ExpectingInput);
                await turnContext.SendActivityAsync(errorMessage);

                // Send a trace activity, which will be displayed in the Bot Framework Emulator.
                // Note: we return the entire exception in the value property to help the developer;
                // this should not be done in production.
                await turnContext.TraceActivityAsync("OnTurnError Trace", exception.ToString(), "https://www.botframework.com/schemas/error", "TurnError");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"Exception caught in SendErrorMessageAsync : {ex}");
            }
        }
示例#12
0
        protected override async Task OnMessageActivityAsync(ITurnContext <IMessageActivity> context, CancellationToken cancellationToken)
        {
            var message = context.Activity;

            // To quickly test the bot after deploy to ensure the version we want is available.
            if (message.Text.ToLower().Equals("bot version"))
            {
                var version = typeof(SupportBot).Assembly.GetName().Version;

                var replyText = $"Art Gallery Support Assistant v{version?.Major}.{version?.Minor}.{version?.Build}.{version?.Revision}";
                await context.SendActivityAsync(MessageFactory.Text(replyText, replyText), cancellationToken);

                return;
            }

            // ******************************* Cognitive Services - Text Analysis API ******************************* //

            using var textAnalyticsClient = new TextAnalyticsClient(new TextAnalysisServiceClientCredentials(SubscriptionKeys.TextAnalysisServiceKey))
                  {
                      Endpoint = "https://eastus.api.cognitive.microsoft.com/"
                  };

            var langResult = await textAnalyticsClient.DetectLanguageAsync(false, new LanguageBatchInput(new List <LanguageInput>
            {
                new LanguageInput(id: "1", text: message.Text)
            }), cancellationToken : cancellationToken);

            await context.TraceActivityAsync("OnMessageActivity Trace", langResult, "LanguageResult", cancellationToken : cancellationToken);

            var languageCode = string.Empty;

            foreach (var document in langResult.Documents)
            {
                // Pick the language with the highest score
                var bestLanguage = document.DetectedLanguages?.OrderByDescending(l => l.Score).FirstOrDefault();

                if (string.IsNullOrEmpty(languageCode) && bestLanguage != null)
                {
                    languageCode = bestLanguage.Iso6391Name.ToLower();
                    await context.TraceActivityAsync("OnMessageActivity Trace", languageCode, "string", cancellationToken : cancellationToken);
                }
            }

            // If we couldn't detect language
            if (string.IsNullOrEmpty(languageCode))
            {
                var replyText = "We could not determine what language you're using. Please try again.";
                await context.SendActivityAsync(MessageFactory.Text(replyText, replyText), cancellationToken);

                return;
            }


            // ******************************* Cognitive Services - Text Translation API ******************************* //

            var query = string.Empty;

            // If the detected language was not English, translate it before sending to LUIS
            if (languageCode != "en")
            {
                try
                {
                    using var translationClient = new TextTranslationServiceClient(SubscriptionKeys.TextTranslationServiceKey);

                    var result = await translationClient.TranslateAsync(message.Text, "en");

                    var translatedQuery = result?.Translations?.FirstOrDefault()?.Text;

                    if (!string.IsNullOrEmpty(translatedQuery))
                    {
                        query = translatedQuery;
                    }
                }
                catch (Exception ex)
                {
                    var replyText = $"RespondWithTranslatedReply Exception: {ex.Message}";
                    await context.SendActivityAsync(MessageFactory.Text(replyText, replyText), cancellationToken);
                }
            }
            else
            {
                query = message.Text;
            }


            // ******************************* Cognitive Services - LUIS (Natural Language Understanding) API ******************************* //

            using var luisClient = new LUISRuntimeClient(new ApiKeyServiceClientCredentials(SubscriptionKeys.LuisPredictionKey));

            luisClient.Endpoint = SubscriptionKeys.LuisEndpoint;

            // Prepare a prediction request
            var predictionRequest = new PredictionRequest
            {
                Query = query
            };

            // Request a prediction, returns a PredictionResponse
            var predictionResponse = await luisClient.Prediction.GetSlotPredictionAsync(
                Guid.Parse(SubscriptionKeys.LuisAppId),
                "production",
                predictionRequest,
                verbose : true,
                showAllIntents : true,
                log : true,
                cancellationToken : cancellationToken);

            // You will get a full list of intents. For the purposes of this demo, we'll just use the highest scoring intent.
            var topScoringIntent = predictionResponse.Prediction.TopIntent;

            // Respond to the user depending on the detected intent of their query
            var respondedToQuery = await RespondWithEnglishAsync(context, topScoringIntent, languageCode, cancellationToken);


            // ******************************* Cognitive Services - Sentiment Analysis  ******************************* //

            // Only evaluate sentiment if we've given a meaningful reply (and not connection or service error messages).
            if (respondedToQuery)
            {
                // Use Text Analytics Sentiment analysis
                var sentimentResult = await textAnalyticsClient.SentimentAsync(
                    multiLanguageBatchInput : new MultiLanguageBatchInput(new List <MultiLanguageInput>
                {
                    new MultiLanguageInput(id: "1", text: query, language: languageCode)
                }),
                    cancellationToken : cancellationToken);


                if (sentimentResult?.Documents?.Count > 0)
                {
                    await context.TraceActivityAsync("SentimentAsync Trace", sentimentResult.Documents[0], "SentimentBatchResultItem", cancellationToken : cancellationToken);

                    SentimentBatchResultItem sentimentItem = sentimentResult.Documents[0];

                    // Use the sentiment score to determine if we need to react, the range is 0 (angriest) to 1 (happiest)
                    await EvaluateAndRespondToSentimentAsync(context, sentimentItem, languageCode, cancellationToken);
                }
            }
        }
        /// <summary>
        /// Creates a dialog stack and starts a dialog, pushing it onto the stack.
        /// </summary>
        /// <param name="dialog">The dialog to start.</param>
        /// <param name="turnContext">The context for the current turn of the conversation.</param>
        /// <param name="accessor">The <see cref="IStatePropertyAccessor{DialogState}"/> accessor
        /// with which to manage the state of the dialog stack.</param>
        /// <param name="cancellationToken">A cancellation token that can be used by other objects
        /// or threads to receive notice of cancellation.</param>
        /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
        public static async Task RunAsync(this Dialog dialog, ITurnContext turnContext, IStatePropertyAccessor <DialogState> accessor, CancellationToken cancellationToken)
        {
            var dialogSet = new DialogSet(accessor)
            {
                TelemetryClient = dialog.TelemetryClient
            };

            dialogSet.Add(dialog);

            var dialogContext = await dialogSet.CreateContextAsync(turnContext, cancellationToken).ConfigureAwait(false);

            if (turnContext.TurnState.Get <IIdentity>(BotAdapter.BotIdentityKey) is ClaimsIdentity claimIdentity && SkillValidation.IsSkillClaim(claimIdentity.Claims))
            {
                // The bot is running as a skill.
                if (turnContext.Activity.Type == ActivityTypes.EndOfConversation && dialogContext.Stack.Any())
                {
                    // Handle remote cancellation request if we have something in the stack.
                    var activeDialogContext = GetActiveDialogContext(dialogContext);

                    var remoteCancelText = "Skill was canceled by a request from the host.";
                    await turnContext.TraceActivityAsync($"{typeof(Dialog).Name}.RunAsync()", label : $"{remoteCancelText}", cancellationToken : cancellationToken).ConfigureAwait(false);

                    // Send cancellation message to the top dialog in the stack to ensure all the parents are canceled in the right order.
                    await activeDialogContext.CancelAllDialogsAsync(true, cancellationToken : cancellationToken).ConfigureAwait(false);
                }
                else
                {
                    // Process a reprompt event sent from the parent.
                    if (turnContext.Activity.Type == ActivityTypes.Event && turnContext.Activity.Name == DialogEvents.RepromptDialog && dialogContext.Stack.Any())
                    {
                        await dialogContext.RepromptDialogAsync(cancellationToken).ConfigureAwait(false);

                        return;
                    }

                    // Run the Dialog with the new message Activity and capture the results so we can send end of conversation if needed.
                    var result = await dialogContext.ContinueDialogAsync(cancellationToken).ConfigureAwait(false);

                    if (result.Status == DialogTurnStatus.Empty)
                    {
                        var startMessageText = $"Starting {dialog.Id}.";
                        await turnContext.TraceActivityAsync($"{typeof(Dialog).Name}.RunAsync()", label : $"{startMessageText}", cancellationToken : cancellationToken).ConfigureAwait(false);

                        result = await dialogContext.BeginDialogAsync(dialog.Id, null, cancellationToken).ConfigureAwait(false);
                    }

                    // Send end of conversation if it is completed or cancelled.
                    if (result.Status == DialogTurnStatus.Complete || result.Status == DialogTurnStatus.Cancelled)
                    {
                        var endMessageText = $"Dialog {dialog.Id} has **completed**. Sending EndOfConversation.";
                        await turnContext.TraceActivityAsync($"{typeof(Dialog).Name}.RunAsync()", label : $"{endMessageText}", value : result.Result, cancellationToken : cancellationToken).ConfigureAwait(false);

                        // Send End of conversation at the end.
                        var activity = new Activity(ActivityTypes.EndOfConversation)
                        {
                            Value = result.Result
                        };
                        await turnContext.SendActivityAsync(activity, cancellationToken).ConfigureAwait(false);
                    }
                }
            }
示例#14
0
 // Log Custom Trace
 public static async Task <Microsoft.Bot.Schema.ResourceResponse> LogCustomTrace(object trace, ITurnContext turnContext, string type, string service)
 {
     return(await turnContext.TraceActivityAsync(service, trace, type, type).ConfigureAwait(false));
 }
        /// <summary>
        /// Creates a dialog stack and starts a dialog, pushing it onto the stack.
        /// </summary>
        /// <param name="dialog">The dialog to start.</param>
        /// <param name="otherDialogs">Other dialogs to add to the stack other than starting dialog.</param>
        /// <param name="turnContext">The context for the current turn of the conversation.</param>
        /// <param name="accessor">The <see cref="IStatePropertyAccessor{DialogState}"/> accessor
        /// with which to manage the state of the dialog stack.</param>
        /// <param name="cancellationToken">A cancellation token that can be used by other objects
        /// or threads to receive notice of cancellation.</param>
        /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
        public static async Task RunAsync(this Dialog dialog, IEnumerable <Dialog> otherDialogs, ITurnContext turnContext, IStatePropertyAccessor <DialogState> accessor, CancellationToken cancellationToken)
        {
            var dialogSet = new DialogSet(accessor)
            {
                TelemetryClient = dialog.TelemetryClient
            };

            dialogSet.Add(dialog);
            if (otherDialogs != null)
            {
                foreach (var d in otherDialogs)
                {
                    dialogSet.Add(d);
                }
            }
            var dialogContext = await dialogSet.CreateContextAsync(turnContext, cancellationToken).ConfigureAwait(false);

            // Handle EoC and Reprompt event from a parent bot (can be root bot to skill or skill to skill)
            if (IsFromParentToSkill(turnContext))
            {
                // Handle remote cancellation request from parent.
                if (turnContext.Activity.Type == ActivityTypes.EndOfConversation)
                {
                    if (!dialogContext.Stack.Any())
                    {
                        // No dialogs to cancel, just return.
                        return;
                    }

                    var activeDialogContext = GetActiveDialogContext(dialogContext);

                    var remoteCancelText = "Skill was canceled through an EndOfConversation activity from the parent.";
                    await turnContext.TraceActivityAsync($"{typeof(Dialog).Name}.RunAsync()", label : $"{remoteCancelText}", cancellationToken : cancellationToken).ConfigureAwait(false);

                    // Send cancellation message to the top dialog in the stack to ensure all the parents are canceled in the right order.
                    await activeDialogContext.CancelAllDialogsAsync(true, cancellationToken : cancellationToken).ConfigureAwait(false);

                    return;
                }

                // Handle a reprompt event sent from the parent.
                if (turnContext.Activity.Type == ActivityTypes.Event && turnContext.Activity.Name == DialogEvents.RepromptDialog)
                {
                    if (!dialogContext.Stack.Any())
                    {
                        // No dialogs to reprompt, just return.
                        return;
                    }

                    await dialogContext.RepromptDialogAsync(cancellationToken).ConfigureAwait(false);

                    return;
                }
            }

            // Continue or start the dialog.
            var result = await dialogContext.ContinueDialogAsync(cancellationToken).ConfigureAwait(false);

            if (result.Status == DialogTurnStatus.Empty)
            {
                result = await dialogContext.BeginDialogAsync(dialog.Id, null, cancellationToken).ConfigureAwait(false);
            }

            // Skills should send EoC when the dialog completes.
            if (result.Status == DialogTurnStatus.Complete || result.Status == DialogTurnStatus.Cancelled)
            {
                if (SendEoCToParent(turnContext))
                {
                    var endMessageText = $"Dialog {dialog.Id} has **completed**. Sending EndOfConversation.";
                    await turnContext.TraceActivityAsync($"{typeof(Dialog).Name}.RunAsync()", label : $"{endMessageText}", value : result.Result, cancellationToken : cancellationToken).ConfigureAwait(false);

                    // Send End of conversation at the end.
                    var code     = result.Status == DialogTurnStatus.Complete ? EndOfConversationCodes.CompletedSuccessfully : EndOfConversationCodes.UserCancelled;
                    var activity = new Activity(ActivityTypes.EndOfConversation)
                    {
                        Value = result.Result, Locale = turnContext.Activity.Locale, Code = code
                    };
                    await turnContext.SendActivityAsync(activity, cancellationToken).ConfigureAwait(false);
                }
            }
        }
示例#16
0
        internal override async Task <RecognizerResult> RecognizeInternalAsync(ITurnContext turnContext, HttpClient httpClient, CancellationToken cancellationToken)
        {
            BotAssert.ContextNotNull(turnContext);

            if (turnContext.Activity == null || turnContext.Activity.Type != ActivityTypes.Message)
            {
                return(null);
            }

            var utterance = turnContext.Activity?.AsMessageActivity()?.Text;
            RecognizerResult recognizerResult;
            LuisResult       luisResult = null;

            if (string.IsNullOrWhiteSpace(utterance))
            {
                recognizerResult = new RecognizerResult
                {
                    Text = utterance
                };
            }
            else
            {
                var credentials = new ApiKeyServiceClientCredentials(Application.EndpointKey);
                var runtime     = new LUISRuntimeClient(credentials, httpClient, false)
                {
                    Endpoint = Application.Endpoint,
                };
                luisResult = await runtime.Prediction.ResolveAsync(
                    Application.ApplicationId,
                    utterance,
                    timezoneOffset : PredictionOptions.TimezoneOffset,
                    verbose : PredictionOptions.IncludeAllIntents,
                    staging : PredictionOptions.Staging,
                    spellCheck : PredictionOptions.SpellCheck,
                    bingSpellCheckSubscriptionKey : PredictionOptions.BingSpellCheckSubscriptionKey,
                    log : PredictionOptions.Log ?? true,
                    cancellationToken : cancellationToken).ConfigureAwait(false);

                recognizerResult = new RecognizerResult
                {
                    Text        = utterance,
                    AlteredText = luisResult.AlteredQuery,
                    Intents     = LuisUtil.GetIntents(luisResult),
                    Entities    = LuisUtil.ExtractEntitiesAndMetadata(luisResult.Entities, luisResult.CompositeEntities, PredictionOptions.IncludeInstanceData ?? true, utterance),
                };
                LuisUtil.AddProperties(luisResult, recognizerResult);
                if (IncludeAPIResults)
                {
                    recognizerResult.Properties.Add("luisResult", luisResult);
                }
            }

            var traceInfo = JObject.FromObject(
                new
            {
                recognizerResult,
                luisModel = new
                {
                    ModelID = Application.ApplicationId,
                },
                luisOptions = PredictionOptions,
                luisResult,
            });

            await turnContext.TraceActivityAsync("LuisRecognizer", traceInfo, LuisTraceType, LuisTraceLabel, cancellationToken).ConfigureAwait(false);

            return(recognizerResult);
        }
        private async Task <RecognizerResult> RecognizeInternalAsync(ITurnContext turnContext, LuisPredictionOptions predictionOptions, Dictionary <string, string> telemetryProperties, Dictionary <string, double> telemetryMetrics, CancellationToken cancellationToken)
        {
            BotAssert.ContextNotNull(turnContext);
            if (turnContext.Activity.Type != ActivityTypes.Message)
            {
                return(null);
            }

            var options   = predictionOptions ?? _predictionOptions;
            var utterance = turnContext.Activity?.AsMessageActivity()?.Text;
            RecognizerResult recognizerResult;
            JObject          luisResponse = null;

            if (string.IsNullOrWhiteSpace(utterance))
            {
                recognizerResult = new RecognizerResult
                {
                    Text    = utterance,
                    Intents = new Dictionary <string, IntentScore>()
                    {
                        { string.Empty, new IntentScore()
                          {
                              Score = 1.0
                          } }
                    },
                    Entities = new JObject(),
                };
            }
            else
            {
                var uri = new UriBuilder(_application.Endpoint);

                // TODO: When the endpoint GAs, we will need to change this.  I could make it an option, but other code is likely to need to change.
                uri.Path += $"luis/v3.0-preview/apps/{_application.ApplicationId}";

                var query = AddParam(null, "verbose", options.IncludeInstanceData);
                query     = AddParam(query, "log", options.Log);
                query     = AddParam(query, "show-all-intents", options.IncludeAllIntents);
                uri.Query = query;

                var content = new JObject
                {
                    { "query", utterance },
                };
                var queryOptions = new JObject
                {
                    { "overridePredictions", options.PreferExternalEntities },
                };
                content.Add("options", queryOptions);

                var settings = new JsonSerializerSettings {
                    NullValueHandling = NullValueHandling.Ignore
                };
                if (options.DynamicLists != null)
                {
                    foreach (var list in options.DynamicLists)
                    {
                        list.Validate();
                    }

                    content.Add("dynamicLists", (JArray)JsonConvert.DeserializeObject(JsonConvert.SerializeObject(options.DynamicLists, settings)));
                }

                if (options.ExternalEntities != null)
                {
                    foreach (var entity in options.ExternalEntities)
                    {
                        entity.Validate();
                    }

                    content.Add("externalEntities", (JArray)JsonConvert.DeserializeObject(JsonConvert.SerializeObject(options.ExternalEntities, settings)));
                }

                if (options.Version == null)
                {
                    uri.Path += $"/slots/{options.Slot}/predict";
                }
                else
                {
                    uri.Path += $"/versions/{options.Version}/predict";
                }

                var response = await DefaultHttpClient.PostAsync(uri.Uri, new StringContent(content.ToString(), System.Text.Encoding.UTF8, "application/json")).ConfigureAwait(false);

                response.EnsureSuccessStatusCode();
                luisResponse = (JObject)JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync().ConfigureAwait(false));
                var prediction = (JObject)luisResponse["prediction"];
                recognizerResult = new RecognizerResult
                {
                    Text        = utterance,
                    AlteredText = prediction["alteredQuery"]?.Value <string>(),
                    Intents     = LuisUtil.GetIntents(prediction),
                    Entities    = LuisUtil.ExtractEntitiesAndMetadata(prediction),
                };
                LuisUtil.AddProperties(prediction, recognizerResult);
                if (options.IncludeAPIResults)
                {
                    recognizerResult.Properties.Add("luisResult", luisResponse);
                }
            }

            // Log telemetry
            OnRecognizerResult(recognizerResult, turnContext, telemetryProperties, telemetryMetrics);

            var traceInfo = JObject.FromObject(
                new
            {
                recognizerResult,
                luisModel = new
                {
                    ModelID = _application.ApplicationId,
                },
                luisOptions = options,
                luisResult  = luisResponse,
            });

            await turnContext.TraceActivityAsync("LuisRecognizer", traceInfo, LuisTraceType, LuisTraceLabel, cancellationToken).ConfigureAwait(false);

            return(recognizerResult);
        }
        private async Task <RecognizerResult> RecognizeAsync(ITurnContext turnContext, string utterance, LuisV3.LuisPredictionOptions options, HttpClient httpClient, CancellationToken cancellationToken)
        {
            RecognizerResult recognizerResult;
            JObject          luisResponse = null;

            if (string.IsNullOrWhiteSpace(utterance))
            {
                recognizerResult = new RecognizerResult
                {
                    Text = utterance
                };
            }
            else
            {
                var uri     = BuildUri(options);
                var content = BuildRequestBody(utterance, options);
                httpClient.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", Application.EndpointKey);
                var response = await httpClient.PostAsync(uri.Uri, new StringContent(content.ToString(), System.Text.Encoding.UTF8, "application/json")).ConfigureAwait(false);

                response.EnsureSuccessStatusCode();
                httpClient.DefaultRequestHeaders.Remove("Ocp-Apim-Subscription-Key");
                luisResponse = (JObject)JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync().ConfigureAwait(false));
                var prediction = (JObject)luisResponse["prediction"];
                recognizerResult = new RecognizerResult();

                recognizerResult.Text        = utterance;
                recognizerResult.AlteredText = prediction["alteredQuery"]?.Value <string>();
                recognizerResult.Intents     = LuisV3.LuisUtil.GetIntents(prediction);
                recognizerResult.Entities    = LuisV3.LuisUtil.ExtractEntitiesAndMetadata(prediction);

                LuisV3.LuisUtil.AddProperties(prediction, recognizerResult);
                if (IncludeAPIResults)
                {
                    recognizerResult.Properties.Add("luisResult", luisResponse);
                }

                if (PredictionOptions.IncludeInstanceData)
                {
                    var instanceObject = recognizerResult.Entities["$instance"];
                    if (instanceObject == null)
                    {
                        recognizerResult.Entities.Add("$instance", new JObject());
                    }
                }
            }

            var traceInfo = JObject.FromObject(
                new
            {
                recognizerResult,
                luisModel = new
                {
                    ModelID = Application.ApplicationId,
                },
                luisOptions = options,
                luisResult  = luisResponse,
            });

            await turnContext.TraceActivityAsync("LuisRecognizer", traceInfo, LuisTraceType, LuisTraceLabel, cancellationToken).ConfigureAwait(false);

            return(recognizerResult);
        }
示例#19
0
        private async Task <RecognizerResult> RecognizeInternalAsync(ITurnContext turnContext, LuisPredictionOptions predictionOptions, Dictionary <string, string> telemetryProperties, Dictionary <string, double> telemetryMetrics, CancellationToken cancellationToken)
        {
            var luisPredictionOptions = predictionOptions == null ? _options : MergeDefaultOptionsWithProvidedOptions(_options, predictionOptions);

            BotAssert.ContextNotNull(turnContext);

            if (turnContext.Activity.Type != ActivityTypes.Message)
            {
                return(null);
            }

            var utterance = turnContext.Activity?.AsMessageActivity()?.Text;
            RecognizerResult recognizerResult;
            LuisResult       luisResult = null;

            if (string.IsNullOrWhiteSpace(utterance))
            {
                recognizerResult = new RecognizerResult
                {
                    Text    = utterance,
                    Intents = new Dictionary <string, IntentScore>()
                    {
                        { string.Empty, new IntentScore()
                          {
                              Score = 1.0
                          } }
                    },
                    Entities = new JObject(),
                };
            }
            else
            {
                luisResult = await _runtime.Prediction.ResolveAsync(
                    _application.ApplicationId,
                    utterance,
                    timezoneOffset: luisPredictionOptions.TimezoneOffset,
                    verbose: luisPredictionOptions.IncludeAllIntents,
                    staging: luisPredictionOptions.Staging,
                    spellCheck: luisPredictionOptions.SpellCheck,
                    bingSpellCheckSubscriptionKey : luisPredictionOptions.BingSpellCheckSubscriptionKey,
                    log : luisPredictionOptions.Log ?? true,
                    cancellationToken : cancellationToken).ConfigureAwait(false);

                recognizerResult = new RecognizerResult
                {
                    Text        = utterance,
                    AlteredText = luisResult.AlteredQuery,
                    Intents     = LuisUtil.GetIntents(luisResult),
                    Entities    = LuisUtil.ExtractEntitiesAndMetadata(luisResult.Entities, luisResult.CompositeEntities, luisPredictionOptions.IncludeInstanceData ?? true, utterance),
                };
                LuisUtil.AddProperties(luisResult, recognizerResult);
                if (_includeApiResults)
                {
                    recognizerResult.Properties.Add("luisResult", luisResult);
                }
            }

            // Log telemetry
            await OnRecognizerResultAsync(recognizerResult, turnContext, telemetryProperties, telemetryMetrics, cancellationToken).ConfigureAwait(false);

            var traceInfo = JObject.FromObject(
                new
            {
                recognizerResult,
                luisModel = new
                {
                    ModelID = _application.ApplicationId,
                },
                luisOptions = luisPredictionOptions,
                luisResult,
            });

            await turnContext.TraceActivityAsync("LuisRecognizer", traceInfo, LuisTraceType, LuisTraceLabel, cancellationToken).ConfigureAwait(false);

            return(recognizerResult);
        }