0_tFeGkwrnE2Y_QPpp

Build a Chat App with Sentiment Analysis Using AWS Machine Learning Services

Technology companies cannot get through 2018 without somehow incorporating chat into their platform. Whether it be a medium for sales outreach, tech support, in-game chat, or your core product — there is a need for reliable, scalable chat, now.

After seven years of PubNub’s realtime data APIs, our customers have made it clear that chat doesn’t work without PubNub. To give developers a head start and get off the ground in a fraction of the time, we created ChatEngine. An opinionated framework built on top of PubNub, ChatEngine is the secure wrapper that does the heavy lifting for chat integration.

The ChatEngine JavaScript SDK is available on NPM and also CDN. Integrating it into an existing web application is straightforward.

<script src="https://cdn.jsdelivr.net/npm/chat-engine@0.9.5/dist/chat-engine.min.js"></script>
<script>
    // WARNING! - Get PubNub API keys and run the ChatEngine setup:
    // https://www.pubnub.com/docs/tutorials/chatengine#step-one-pubnub-keys
    // Make sure to import ChatEngine first!
    const ChatEngine = ChatEngineCore.create({
        publishKey: '__your_PubNub_Publish_key__',
        subscribeKey: '__your_PubNub_Subscribe_key__'
    }, {
        globalChannel: 'chat-engine-demo'
    });
</script>

 

In a matter of minutes, an app with features like chat rooms, presence, message history, and more can be programed and enabled. Plugins like typing indicators, markdown and emojis are all available via NPM. The door for accessing even more power is opened by PubNub Functions.

PubNub Functions make a ChatEngine backend instantly able to support AI based features. Our catalog currently has more than 80 open source blocks with pre-built integrations for APIs like Amazon Comprehend.

In this post, we will take an in-depth dive into a demo application that shows how a Function can be dropped into an app to integrate sentiment analysis rapidly. Similar functionality can be enabled just as simply for each of the AWS machine learning services thanks to serverless, open source, PubNub Functions:

  • Amazon Translate: Natural and fluent language translation
  • Amazon Polly: Turn text into lifelike speech using deep learning
  • Amazon Comprehend: Discover insights and relationships in text
  • Amazon Lex: Conversational interfaces for your applications (Coming to PubNub Functions soon!)

Think of PubNub Functions as an in-transit message enricher by way of small node.js script.

// PubNub Functions event handler
// Deploy globally in minutes at https://admin.pubnub.com/

// Specify one channel or all with '*' in the editor

// Use `xhr.fetch(url).then()` to do an HTTP request
const xhr = require("xhr");

export default (request) => {
    
    // Replaces all instances of "bad" with "good" while a message is in transit
    request.message.text.replace(/bad/g, "good");
    
    return request.ok(); // Return a promise when you're done
};

Imagine a chat message submitted from a ChatEngine application passing through the PubNub ecosystem. A developer can decide to include the above event handler on one or many channels in which PubNub messages travel. From within this event handler, we can provide some sort of message enrichment with plain JavaScript, or by making an HTTP request to an external API.

For instance, a text message can be translated into another language by way of an HTTP request to the Amazon Translate API. When the request returns, we can overwrite the text message payload with the translated text. This code can be implemented as a On Before, On After, or After Presence event handler.

In addition to being an in-transit message mutator, PubNub Functions can also be used as a REST API endpoint. This is what was changed from the default code of the Amazon Cognitive block in this tutorial. The chat app will hit this REST endpoint for every ChatEngine message that is published. The sentiment will be gathered from Amazon, and the text bubble will change to the corresponding color of the sentiment analysis result.

  • Green: Positive
  • Red: Negative
  • Grey: Neutral
sentiment analysis chat

Program a Chat App with Amazon APIs in Record Time

Follow this guide to build a ChatEngine demo app with sentiment analysis for all chat messages, powered by Amazon Comprehend and PubNub. The referenced code is available on GitHub.

By using the existing demo (javascript/desktop.html) from the PubNub ChatEngine Examples Repository, you can get started with a functional chat UI that is browser and mobile compatible. Importing ChatEngine to the web browser via CDN is painless.

<script src="https://cdn.jsdelivr.net/npm/chat-engine@0.9.5/dist/chat-engine.min.js"></script>
<script>
    // WARNING! - Get PubNub API keys and run the ChatEngine setup:
    // https://www.pubnub.com/docs/tutorials/chatengine#step-one-pubnub-keys
    // Make sure to import ChatEngine first!
    const ChatEngine = ChatEngineCore.create({
        publishKey: '__your_PubNub_Publish_key__',
        subscribeKey: '__your_PubNub_Subscribe_key__'
    }, {
        globalChannel: 'chat-engine-demo'
    });
</script>

Once you have signed up for PubNub, run the ChatEngine Setup to automatically deploy the serverless backend of PubNub Functions event handlers. Think of these as little, RESTful Node.js servers that run in the cloud. They are used for ChatEngine user authentication policies, channel provisioning, and presence state storage (kvstore).

chatengine setup
The maximum number of event handlers for a PubNub app is 3. We are going to add the third to our ChatEngine backend as the connector between the Amazon ML APIs and the chat app. I have made some changes to the open source code in the BLOCKS catalog, so our Comprehend block will be an On Request handler instead of a Before Publish handler. This makes it more like a REST endpoint instead of an in transit message enricher. Code is here, in comprehend-pfunc.js.

Go to the PubNub Admin Dashboard, click on your ChatEngine App, then the FUNCTIONS tab on the left. You should see the ChatEngine module, click it, and then click create to declare a new Function event handler.

function setupNext, we’ll copy the edited source code for the Comprehend integration, found in comprehend-function.js, from the aforementioned GitHub repository. Paste the code into the editor.

If you have not already, make an AWS account and get a Comprehend access key and secret key (find out how here).

Add those keys in the editor by clicking MY SECRETS. This is a safe place to store keys and environment variables which are referenced in Functions event handler code. Be sure to use the key AWS_access_key and AWS_secret_key so the Vault reference in the event handler file is correct. Click SAVE.

functions keys

Now that we have imported all of the necessary back end code, start the module by clicking the button at the top right of the Functions editor. This button deploys the new code globally in just a few seconds. Our ChatEngine front-end will now be able to groove.

Before closing the Functions editor, click the COPY URL button. This copies the REST endpoint URL for the service. Open the app.js file in the project and paste this URL in comprehendFunctionURI (line 5).

// Be sure to replace strings with your own App's Publish & Subscribe keys
// Also replace the REST endpoint with your own On Request handler
var userPubKey = '__PUBNUB_PUBLISH_KEY__';
var userSubKey = '__PUBNUB_SUBSCRIBE_KEY__';
var comprehendFunctionURI = 'https://pubsub.pubnub.com/v1/blocks/sub-key/__SUB_KEY__/__URI__';

Visit the Key Info page for the app in the admin portal. Copy the Publish and Subscribe keys from the portal and paste them near the top of app.js.

chatengine keyset configThat’s it! All of the coding and configuring for the fullstack of this chat app is done. To run the app, boot a local server from the root directory of the project.

If you have never done this before, I recommend installing http-server from NPM. This runs a dev server on your machine by simply entering http-server on the command line, in your app directory. Once this is running, go to the localhost address in a web browser to see the UI (by default http://localhost:8080).

Every other client who boots this UI will see the same chat log as you. This instance is organized by your PubNub app’s Publish and Subscribe keys, and the chat channel. This UI can also be accessed from a mobile web browser, as is.

Comprehend UI Functionality

The method in which the Comprehend feature is architected is through a HTTP request made to the PubNub Function whenever a ChatEngine message renders. The render event writes the message to the DOM immediately and colors it grey. Next it asynchronously begins the Comprehend API request.

sentimentAnalysis: function (text, id) {
    var deferred = $.Deferred();

    $.ajax({
        method: "POST",
        url: comprehendFunctionURI,
        data: JSON.stringify({
            "data": {
                "text": text,
                "comprehend": {
                    "language": "en",
                    "location": "text"
                }
            }
        }),
    })
    .done(function(res) {
        var sentiment = res.sentiment;

        if (res.error) {
            console.error(res);
        }

        deferred.resolve(id, sentiment);
    });

    return deferred.promise();
}

Once the request returns, jQuery is used to select the elements in the DOM that are to be changed. A CSS class with a transition is used for the message bubble background, to change the color. Sentiment analysis percentages are added in a span above the message bubble.

this.sentimentAnalysis(plainText, message.timetoken)
.then(function(id, sentiment) {
    var messageInfoSpan = $('span[data-identifier="' + id + '"]');
    var messageDiv = $('div[data-identifier="' + id + '"]');

    if (sentiment.Sentiment &&
        sentiment.SentimentScore &&
        sentiment.SentimentScore.Negative &&
        sentiment.SentimentScore.Positive
    ) {
        messageDiv.removeClass('neutral');
        messageDiv.addClass(sentiment.Sentiment);

        var neg = (sentiment.SentimentScore.Negative * 100).toFixed(2);
        var pos = (sentiment.SentimentScore.Positive * 100).toFixed(2);

        messageInfoSpan.text('+' + pos + '%   -' + neg + '%');
    }
});

Type a message and enter it into the chat. Watch as the colors and sentiment analysis scores mutate the chat log!

ChatEngine Features and Plugins

chatengine markdown

See the extended features of ChatEngine plugins by uncommenting the lines in app.js that are noted with UNCOMMENT. This is how you would implement chat log history fetch, typing indicator, and the markdown plugin. ChatEngine and all of its plugins are open source on PubNub’s GitHub and available for import through NPM.

Language:

Try PubNub Today