Vue.js Chatbot with AWS Lex
Building A Chatbot with Vue.js, ChatEngine, and Amazon Lex
Vue.js continues to grow in popularity and is guaranteed to be one of the most popular front-end frameworks of 2018. In looking at the graphs about download rates, it’s conclusive to say the Vue.js developer following is growing rapidly.Following up PubNub’s recent announcement of our Vue.js ChatEngine plugin, in this tutorial, we’ll walk you through building a fully-featured Vue.js chat app using Vuex, the state management pattern and library for Vue (comparable to React with Redux). During development, we were inspired to build a Vue.js plugin for ChatEngine, so ChatEngine can be integrated using the same patterns as the Vue-Socket.io plugin.Try the live version!Tutorial AssetsYou can try out the finished version of the application here. Create private chat rooms, try out the chat bot, or chat in the main global feed.And all the code you need is available in our GitHub repo. Just a heads up, to run it, you need to register for PubNub (it’s free), and add your API keys to the app.Amazon Lex OverviewIn early 2018, PubNub announced the arrival of new, open source BLOCKS for each of the AWS Machine Learning APIs in the PubNub BLOCKS Catalog. This allows developers to fuse together their realtime applications with the powerful AI resources offered by AWS. Amazon Lex is a service that enables developers to build conversational interfaces with intelligent text and also voice audio.The Vue.js demo that we built has the code to easily integrate a chatbot powered by Lex. The live demo features a chat interface with a digital version of PubNub founder Stephen Blum, which took just a few minutes to configure and deploy, thanks to AWS.Building the UIIf you haven’t already, check out the live demo of this app hosted on GitHub Pages. First, we’ll walk through the steps taken to develop this app from scratch while learning how to use Vue.js and Lex at the same time.Vue is a JavaScript framework, so naturally, it can be installed using NPM, the package manager for Node.js. To develop something as feature-full as thist tutorial, you will also need ChatEngine and some ChatEngine plugins.First, we’ll install the Vue CLI so we can create a new project using a template on the command line. We’re using Webpack, which allows all of the bundling to take place so when ready to deploy the app to production, all of our JS, CSS, and assets are as small and optimized as can be.The CLI has neat on-screen options that you can select using the return and arrow keys (our GitHub repo uses the Google lint standard).Once the Webpack starter template is ready, move into the project directory using the “cd” command. Next, install the NPM packages that will make our project code elegant and small.vuex — Global state management pattern and library for Vue.js apps.vue-chat-engine — A Vue.js plugin that allows Vuex to listen to ChatEngine events.chat-engine — An opinionated JavaScript framework for rapid development of chat applications with PubNub.chat-engine-typing-indicator — A plugin for ChatEngine that enables typing indicator functionality on a chat by chat basis.There are a lot of default files and folders waiting in the chat-app directory. There’s no need to feel intimidated by all of that content. It isn’t important that you understand every line in each of the files. The most important stuff for a Vue.js app is located in the src folder../srcHere we have JavaScript, images, and Vue files. The Vue files (*.vue) will contain JavaScript, CSS, and HTML. Modern web frameworks like Vue break the front-end up into components in order to encapsulate event handling, encourage code reuse, and more.Here is a diagram that will represent the components in the chat demo:In the ./src/components/ directory, make new .vue files that will make up the components in my app../srcThis is what an empty .vue file will look like after you clear our the default contents from the template copy.If you’ve done some front-end web development before, this should look a bit familiar. There are spots in the file for HTML, CSS, and JS. You can begin filling these tags in with your own markup, styling, and code to fill the shape of your newest hack. As you can see in the diagram above, there are components within components. This means that in the app, some components will be parents, siblings, or children of others in the DOM.The ChatContainer component is the highest parent node of the UI. The markup will include custom HTML tags for other components and also some Vue specific markup to reactively render data.There are two instances of non-standard HTML in this markup. First is the curly braces within the h1. This binds some JavaScript variables that are part of the data exported in the code portion of the Vue file, reactively evaluates the expression, and displays the text output as the text content in the tag.The friend-list, chat-log, and message-input tags are also different. These tags represent the components that are children of the ChatContainer. In order for these to render properly, they need to be imported in the script portion of the Vue file.This is the ES6 method of importing files. You can also see the @ used in the file path. To Vue, this means that the path is prepended with the src folder path.As you continue to fill in the file with more JavaScript from the project GitHub repo, you can begin to see there is some more required code that allows the component to work.The component must have a name property that will coincide with the kebab-case HTML tag name. The data function returns some of the static string data that is rendered in the h1 tag. It’s also necessary to tell Vue which components are being referenced in the markup with the components property in the exports.The computed properties are variables that need an entire function to generate their return value. In this component, there is a reference to the Vuex store, specifically a getter called getMyUuid.src/store.jsThe store file contains a global state object along with a collection of getter, action, and mutation functions. This gives the Vue application the ability to access these methods from anywhere. The getMyUuid method referenced in the ChatContainer is a global getter for the client’s current UUID for ChatEngine. Think of this as a globally unique ID for a user within ChatEngine.The SDK references this property as ‘uuid’ however it doesn’t need to be a to-spec, 128-bit number. It can be a plain old string. In the case of this example app, it is a randomly generated 4 character string. Let’s see where that gets set for ChatEngine.src/main.jsThis is the main file for a Vue app. It is where the Vue instance is made and also the ChatEngine instance. At the top, grab the global chat settings and other default chat settings from my default-chats.js file which is just some static JSON.This tells Vue to use the VueChatEngine plugin so ChatEngine’s events are automatically handled by Vuex handlers that are prepended with CHATENGINE_.The created event handler fires when a new Vue instance is made. This is where we configured the ChatEngine logic.Disconnect PubNub when the browser’s “beforeunload” event fires.Set the Me object in the Vuex store when ChatEngine is readyConfigure a listener for ChatEngine invite events, when a 1:1 chat is made in another client.Make a global chat and get the message history, on init, using ChatEngine searchCreate the Chatbot’s own ChatEngine client (in ./src/bot.js)Make any other chats that are listed in the default-chats.js fileIf you want to make your own clone of this app you must register for PubNub (it’s free), press the ChatEngine Setup button, and grab the API keys from the setup.Click here to globally deploy your ChatEngine back-end in 10 secondsThe ChatEngine setup button globally deploys your ChatEngine backend in a few seconds, and then shows you the API keys for the app. To make the Chatbot connect to AWS Lex, you need to add an On Request event handler in the ChatEngine backend in PubNub Functions.Connecting LexTo make the connection between your own clone of the chat app and your own AWS Lex bot, start by going to the PubNub Admin Dashboard.Click on your ChatEngine App, the Functions tab, the ChatEngine Function, and then the Create button, to make a new On Request event handler.This will add a REST endpoint to your ChatEngine backend, which will be used to request a Chatbot reply from AWS Lex. You will need to create an AWS Account and also access keys for Lex, which we will explain later.Next, grab the code from ./pubnub-functions/lex-text-on-request.js in my GitHub repo. Copy and paste this code, replacing the default On Request code in the PubNub Function Editor.Configure the Path input on the left to chat-bot or something like that. Before we deploy this, we should input some AWS access keys with the Lex Chatbot.Creating the ChatbotTo make a Lex Chatbot, you need to make an AWS account.After you have made an account or logged into an existing one, type Amazon Lex into the AWS Services search bar. Click the Create button on the top left and select Custom bot. Choose the onscreen bot settings however you wish, and click Create.You should now be in the Lex Chatbot editor, where you can create Intents, or use existing Intents to teach your Chatbot how to interact. Once you have configured the bot inputs and outputs to your liking, hit Build then Publish on the top right.Next, we’ll get API keys. Click the AWS logo on the top left to navigate back to the AWS Services search bar. Type IAM to navigate to the Identity and Access Management panel. Click Users on the left and create a user. Next you need to add permissions for this user by clicking its name, and then the Add Permissions button. Create a group if need be, or click Attach existing policies directly and add AmazonLexFullAccess using the filter input.Then click the User on the left and create an access key. You will need to copy the Access key ID and the Secret access key.Now go back to the PubNub Functions event handler editor for your ChatEngine App. Click the MY SECRETS button on the left and input the AWS keys as AWS_access_key and AWS_secret_key.Click SAVE and then the Restart Module button in the top right corner of the panel to deploy the REST endpoint.The final step is adding the PubNub API keys and the On Request endpoint URL to the Vue project. The endpoint URL can be copied by clicking the COPY URL button on the left side of the Function editor. Go into the ./src/main.js file and put this URL in the chatBotURL variable. Fill in your unique pub/sub keys using the ChatEngine App’s keys from the PubNub Admin Dashboard.Also, you need to configure the request payload for the Chatbot in ./src/bot.js.Add your Bot Alias and Bot Name as you put it in the AWS console. The user ID can be whatever you’d like.To test your Vue app on your local machine, run npm run dev in your Vue app directory. This creates a local server for you to test your app in the browser at localhost.You can see your user ID in the top menu bar, and you can see everyone else’s ID above their text messages in the global chat. Using the text box and plus button on the right, you can invite another user to a private, 1 to 1 chat. They will automatically see the new private chat in their friend’s list on the left when you add their ID by clicking on the + button.The private chats are complete with a typing indicator that is made with pure CSS. The events are handled by ChatEngine using the typing indicator plugin. Try chatting with the Stephen Chatbot! Try asking him how he’s doing, what PubNub is, or what ChatEngine is. He’s very excited to answer you.