Sentiment Analysis using Microsoft’s Cognitive Services

Now that we are making more conversational interfaces thanks to technology like botframework, interaction with the user is no longer limited to a tap on a link or a button.

Having written language as the primary form of interaction with our systems gives significant difficulties in terms of intent understanding, but also gives great opportunities for further understanding of the user.

Intent understanding has already been tackled by the likes of LUIS; what about the user’s sentiment?

In this article I’m going to introduce Microsoft’s Text Analysis API and show you how to easily get sentiment analysis for a message coming in to your bot.

Microsoft’s Text Analytics API

Microsoft's Text Analytics API

Another part of the Cognitive Services group, the Text Analysis API is a set of endpoints to which you can submit some text and receive scores on various aspects:

Key Phrases

The Key Phrases endpoint will return the key talking points in the input text as a string array. Clever stuff.

Detect Language

The Detect Languages endpoint takes an input string and returns the detected language with a score between 0 and 1. Scores close to 1 indicate 100% certainty that the identified language is true. A total of 120 languages are supported.

Not entirely sure how this would be useful in a bot (these Text Analytics services aren’t bot-specific), but if you think of a good use case let me know!

Detect Topics

This one is insane. The Detect Topics endpoint returns the top detected topics for a list of submitted text documents. A topic is identified with a key phrase, which can be one or more related words. At least 100 text documents must be submitted – but it’s designed to detect topics across hundreds to thousands of documents!

Ridiculous. Obviously, this won’t return a result immediately, so you need to call the Operation Status endpoint to check how processing is progressing.

Sentiment

The Sentiment endpoint will take a piece of text and give a score between 0 and 1, with 1 being totally happy and 0 being totally unhappy/angry.

I’ll focus on Sentiment; let’s take the input message and find out if the user is happy or not! Using this information you could decide to respond differently to the user; if they’re angry/unhappy, perhaps be apologetic and more polite (or tell them a joke!)

Set Up

In order to use the Text Analysis API, you’ll need to sign up for Azure and get a Cognitive Services key.

First sign up for Cognitive Services APIs and select “Text Analytics API (preview)”:

Text Analytics API (preview)

Once that’s created you’ll need to pick up the key as we’ll use that shortly to authenticate our API calls:

Sentiment Analysis Example

This is the structure of the data that the sentiment endpoint expects, which you can look up by checking the Text Analytics API reference for the Sentiment method:

{
  "documents": [
    {
      "language": "en",
      "id": "001",
      "text": "everything is awesome!"
    }
  ]
}

Now that we’ve got the prerequisites, here’s a quick example to call the API and read the result:

var text = "this is the best article ever!";

using (var client = new HttpClient())
{
    // Add your Cognitive Services key here
    client.DefaultRequestHeaders.Add(
        "Ocp-Apim-Subscription-Key", 
        "<your key here>");

    // This is the data we're posting.
    // Anonymous types are fun!
    var request = 
        new { 
            documents = new [] { 
                new { 
                    language = "en", 
                    id = "001", 
                    text 
                    } 
                } 
            };

    // Create form data, setting the content type
    HttpContent content = new StringContent(
        JsonConvert.SerializeObject(request), 
        Encoding.UTF8, 
        "application/json");

    // Send it to Sentiment endpoint
    var sentimentEndpoint = "https://westus.api.cognitive.microsoft.com/text/analytics/v2.0/sentiment";
    var response = await client.PostAsync(sentimentEndpoint, content);

    // Dynamic types are fun!
    // Deserialize json response to dynamic object
    dynamic dynamicResponse = 
        JsonConvert.DeserializeObject(
            await response.Content.ReadAsStringAsync()
        );

    // Get the score as a number
    float score = dynamicResponse.documents[0].score;

    // Arbitrary happiness threshold
    return score > 0.5 ? "Happy :)" : "SAD :(";
}

Fire that up and you’ll get a response like this from the sentiment endpoint:

{"documents":[{"score":0.8399854,"id":"001"}],"errors":[]}

And the method itself will return: “Happy :)”, since the score is greater than our arbitrary threshold of 0.5

Integrating into Botframework

One great way to integrate this could be to have your own dialog that always calls the api and exposes the score in much the same way as the LuisDialog exposes a LuisResult.

Or you could just have a play around by wrapping that code above as a method – maybe called GetSentiment– which takes the input message as the API parameter:

  public class SentimentDialog : IDialog<object>
  {
      public async Task StartAsync(IDialogContext context)
      {
          await context.PostAsync("Let's see how you're feeling...");
          context.Wait(MessageReceivedAsync);
      }

      public async Task MessageReceivedAsync(
          IDialogContext context, 
          IAwaitable<IMessageActivity> argument)
      {
          var message = (await argument).Text;
          var sentiment = await GetSentiment(message).ConfigureAwait(false);

          await context.PostAsync($"Score: {sentiment}");           
          context.Wait(MessageReceivedAsync);
      }
  }

Which gives a response like this:

sentiment response

Cool, huh? Let me know how you plan to use the sentiment analysis API – or even how you’d use the other Text Analysis endpoints!

Leave a Reply

Your email address will not be published. Required fields are marked *