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