Example #1
0
        private static async Task EvaluateAndRespondToSentimentAsync(ITurnContext <IMessageActivity> context, SentimentBatchResultItem sentiment, string languageCode, CancellationToken cancellationToken)
        {
            // If there's no Sentiment object or score value, quit now.
            if (sentiment?.Score == null)
            {
                return;
            }

            var sentimentResponse = string.Empty;

            try
            {
                // Score ranges from 0.0 to 1, with 4 decimals of precision
                if (sentiment.Score <= 0.1)
                {
                    // If the sentiment is lower than 3%, respond with apologies and recommend to reach out to support
                    sentimentResponse = "I'm sorry you're having problems. If you'd like to talk to a person, please email [email protected] and they will be able to assist further.";
                }
                else if (sentiment.Score >= 0.95)
                {
                    // if the sentiment is in the top 97%, respond with a reminder to leave a review for the app.
                    sentimentResponse = "I'm happy to see you're enjoying our services. Please consider leaving an app review after you're done today!";
                }

                // If there's no response needed, quit now.
                if (string.IsNullOrEmpty(sentimentResponse))
                {
                    return;
                }

                // Check to see if we need to translate the response.
                if (languageCode != "en")
                {
                    using (var translationClient = new TextTranslationServiceClient(SubscriptionKeys.TextTranslationServiceKey))
                    {
                        if (!string.IsNullOrEmpty(sentimentResponse))
                        {
                            var translationResult = await translationClient.TranslateAsync(sentimentResponse, languageCode);

                            var translatedSentimentResponse = translationResult.Translations.FirstOrDefault()?.Text;

                            if (!string.IsNullOrEmpty(translatedSentimentResponse))
                            {
                                // If we were able to translate the message, update the message we're sending.
                                sentimentResponse = translatedSentimentResponse;
                            }
                        }
                    }
                }

                // Reply with the sentiment response.
                await context.SendActivityAsync(MessageFactory.Text(sentimentResponse, sentimentResponse), cancellationToken);
            }
            catch (Exception ex)
            {
                var replyText = $"EvaluateAndRespondToSentimentAsync Exception: {ex.Message}";
                await context.SendActivityAsync(MessageFactory.Text(replyText, replyText), cancellationToken);
            }
        }
Example #2
0
        private static async Task <bool> RespondWithEnglishAsync(ITurnContext <IMessageActivity> context, string intent, string languageCode, CancellationToken cancellationToken)
        {
            var responseText = string.Empty;

            // Intents are capitalized and match the intent's name in the LUIS portal, it's still safer is you use a static
            if (intent == LuisIntents.Greeting)
            {
                responseText = "Hello! Welcome, how can I be of assistance today? You can ask about employees, customers, products, orders or shipping.";
            }
            else if (intent == LuisIntents.Employee)
            {
                responseText = "To locate the employee data, select 'Employees' from the navigation menu. In there you can see a list of employees, selecting one will let you explore employee details and statistics.";
            }
            else if (intent == LuisIntents.Customer)
            {
                responseText = "Choose 'Customers' from the navigation menu. Once there, selecting a customer will open their detailed information, including order history.";
            }
            else if (intent == LuisIntents.Product)
            {
                responseText = "To browse the products list, select 'Products' from the navigation menu. The products page will show all the available art in the gallery.";
            }
            else if (intent == LuisIntents.Order)
            {
                responseText = "Select 'Orders' from the navigation menu. You'll find a DataGrid where you can sort, filter and group orders. Order details will provide you with customer and employee data as well.";
            }
            else if (intent == LuisIntents.Shipping)
            {
                responseText = "Find all scheduled packages to be delivered on the Shipping page. You'll see the order and the carrier that is delivering it.";
            }
            else if (intent == LuisIntents.Help)
            {
                responseText = "Sure, let me try to help. You can ask about the employees, the products, customers, orders and shipping information. If you're still stuck, call us at 1-800-123-4567.";
            }
            else if (intent == LuisIntents.None)
            {
                responseText = "I'm not sure what I can to help with this. You might need a human, contact us at [email protected]";
            }
            else if (intent == LuisIntents.Cancel)
            {
                responseText = "If you would like to cancel and end this conversation, just navigate to another page in the application.";
            }
            else if (intent == LuisIntents.Joke)
            {
                var joke = "";

                string url = "http://api.icndb.com/jokes/random?exclude=[explicit]&limitTo=[nerdy]";

                using (var client = new HttpClient())
                {
                    var json = await client.GetStringAsync(url);

                    dynamic jokeResult = JObject.Parse(json);

                    if (jokeResult?.type == "success")
                    {
                        joke = jokeResult.value.joke;
                    }
                }

                responseText = string.IsNullOrEmpty(joke)
                    ? "My funny bone doesn't appear to be working right now. Try again later :D"
                    : joke;
            }

            // If the user is using another language, reply in their language
            if (languageCode != "en")
            {
                using (var translationClient = new TextTranslationServiceClient(SubscriptionKeys.TextTranslationServiceKey))
                {
                    var translationResult = await translationClient.TranslateAsync(responseText, languageCode);

                    if (translationResult != null)
                    {
                        var translatedReply = translationResult?.Translations?.FirstOrDefault()?.Text;

                        if (!string.IsNullOrEmpty(translatedReply))
                        {
                            responseText = translatedReply;
                        }
                    }
                }
            }

            if (!string.IsNullOrEmpty(responseText))
            {
                await context.SendActivityAsync(MessageFactory.Text(responseText, responseText), cancellationToken);

                return(true);
            }

            var replyText = $"I'm sorry, I wasn't able to understand or locate what you're looking for. Try again with specific questions about employees, customers, products or orders.";
            await context.SendActivityAsync(MessageFactory.Text(replyText, replyText), cancellationToken);

            return(false);
        }
Example #3
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);
                }
            }
        }
        public async Task MessageReceivedAsync(IDialogContext context, IAwaitable <IMessageActivity> argument)
        {
            var message = await argument;

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

                await context.PostAsync($"Art Gallery Support Assistant v{version.Major}.{version.Minor}.{version.Build}.{version.Revision}");

                return;
            }


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

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

            // Detect what language is being used
            var langResult = await textAnalyticsClient.DetectLanguageAsync(new BatchInput(new List <Input>
            {
                new Input("1", message.Text)
            }));

            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();
                }
            }

            // If we couldn't detect language
            if (string.IsNullOrEmpty(languageCode))
            {
                await context.PostAsync("We could not determine what language you're using. Please try again.");

                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)
                {
                    await context.PostAsync($"RespondWithTranslatedReply Exception: {ex.Message}");
                }
            }
            else
            {
                query = message.Text;
            }


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

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

                // Create prediction client
                var prediction = new Prediction(luisClient);

                // get prediction from LUIS using spell correction and Sentiment enabled (Sentiment is enabled in the LUIS portal Manage -> PublishSettings)
                var luisResult = await prediction.ResolveAsync(
                    appId : SubscriptionKeys.LuisAppId,
                    query : query,
                    timezoneOffset : null,
                    verbose : true,
                    staging : false,
                    spellCheck : true,
                    bingSpellCheckSubscriptionKey : SubscriptionKeys.BingSpellCheckKey,
                    log : false,
                    cancellationToken : CancellationToken.None);

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

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


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

                // You can get the user's sentiment by:
                // 1. Make a separate call to Cognitive Services using "await textAnalyticsClient.SentimentAsync()"
                // or
                // 2. Enable Sentiment in the LUIS portal (Manage -> PublishSettings -> 'Use sentiment analysis')

                // The 2nd option saves you a round trip because sentiment will already be in the LuisResult object!

                // Only evaluate sentiment if we've given a meaningful reply (and not connection or service error messages).
                if (respondedToQuery)
                {
                    // Use the sentiment score, the range is 0 (angriest) to 1 (happiest)
                    await EvaluateAndRespondToSentimentAsync(context, luisResult?.SentimentAnalysis, languageCode);
                }
            }

            context.Wait(MessageReceivedAsync);
        }