Creating An Alexa Skill (Synonyms Finder) - Part Two - AWS Lambda Function And Integration

In part two of this article series, we will learn how we can create an AWS Lambda function and integrate it with Alexa skills. We will also learn how we can call an external API within our AWS Lambda function and process each intent. Let's get started. 

Before you go through this article I recommend going through part one of this article here:

Log on to your AWS Console and click Services and search for "Lambda" function. 

Creating An Alexa Skill

Now, on your AWS Lambda Console, click "create a function" and select Blueprints. Search for Alexa Skills in the search bar and select sdk-factskill and click the link. We need to work on the basic Alexa Skill template and change the existing code. 

Creating An Alexa Skill

Give a name to your AWS Lambda function and in Role, select "create a custom role".
Creating An Alexa Skill 

In the new tab created, you will be creating a new role for your Lambda function. Give a name to your role and click Allow. 

Creating An Alexa Skill

Now, you will be able to see the role which you have created. So select the role you created and click Create Function. We will modify the Lambda Function code once the Lambda function is created.

Make sure you are in the Northern  Virginia zone when you are creating. Alexa Skills kit trigger, as AWS Lambda function is available there.

Before we deep dive into the code let's integrate our Alexa Skill to this AWS Lambda function. Integration is done by configuring two things. 

  1. Letting your AWS Lambda function exist from where this Lambda function is called. So we configure triggers in AWS Lambda function configuration.

    Creating An Alexa Skill
  2. Configuring Alexa Skill to which Lambda function we have to call. 

    Creating An Alexa Skill

So we have to use two ids for integration - Skill Id and AWS Lambda ARN

Skill Id can be found in Alexa Console,

  1. In Alexa Console get skill ID by clicking view Skill ID and add the skill ID in Trigger configuration and click ok.

  2. AWS Lambda ARN is found in Lambda Console on top of your Lambda function.  

Part 1 of Integration

Once Lambda function is created you have to add triggers to your AWS Lambda function. Select Alexa Skills Kit from the left menu, so now you are able to add a trigger to your AWS Lambda function.

Creating An Alexa Skill

Now click Configuration Required in the trigger and provide your Alexa Skill Id and click Add. 

Creating An Alexa Skill

Part 2 of Integration

In Alexa Console, click "View Alexa Skill" and click "Endpoint" in the Left Menu to configure the AWS Lambda function.

 Select AWS Lambda ARN and provide the AWS Lambda ARN of the lambda function you have created in the default region. 

Creating An Alexa Skill

Now that Integration of Alexa Skills with lambda function is done, let us look at the lambda function code and modify the code to process our Alexa Skill request.

I have used WORDSAPI to get synonyms for the words. Create an account in WordsAPI to use it in Lambda function. Once you signup they will provide an X-Mashape-Key which we use for authorization of words API. 

In Lambda function we use Alexa SDK and https node js modules. 

  1. constAlexa = require('alexa-sdk');    
  2. varhttp = require('https');    

We have to create handlers for Alexa using Alexa SDK. In the handlers object, we have to write logic for each intent which we have created in our Alexa Skill. By default, we have code execution for Amazon-defined Intents like AMAZON, HelpIntent, etc.

  1. consthandlers = {  
  2.     'LaunchRequest'function() {  
  3.         this.emit('GetNewFactIntent');  
  4.     },  
  5.     'AMAZON.HelpIntent'function() {  
  6.         const speechOutput = 'You can ask me a word, I can help you with synonyms of the word';  
  7.         const reprompt = 'What can I help you with?';  
  8.         this.response.speak(speechOutput).listen(reprompt);  
  9.         this.emit(':responseReady');  
  10.     },  
  11.     'AMAZON.CancelIntent'function() {  
  12.         this.response.speak(STOP_MESSAGE);  
  13.         this.emit(':responseReady');  
  14.     },  
  15.     'AMAZON.StopIntent'function() {  
  16.         this.response.speak(STOP_MESSAGE);  
  17.         this.emit(':responseReady');  
  18.     },  
  19. };  

We do have some logic that gets executed for each Intent. Let us look at the  logic for Help Intent. 

  1. this.response.speak(speechOutput).listen(reprompt);     

Here speaking the method within the response object will let Alexa Skills know that whatever is sent as a parameter has to be read to the end user. 

The Listen method within the response object will make Alexa Skills wait for a response from the user for some time and keep the session active until the user responds. 

We do also have a Launch Request Intent which gets invoked when the user says something like "Alexa, start Synonyms Finder", code within Launch the request intent gets executed. For LaunchRequest we have to maintain the session so we use the listen method.

  1. 'LaunchRequest'function() {    
  2.    this.response.speak('Welcome to Synonyms Finder. Know synonyms for the words you want').listen();    
  3.    this.emit(':responseReady');    
  4. }   

We are using https module to fetch data from Words API. Let us create a httpGet method within Lambda function where we will call the WordsAPI. 

  1. functionhttpGet(query, callback) {  
  2.     var options = {  
  3.         //    
  4.         host: '',  
  5.         path: '/words/' + encodeURIComponent(query) + '/synonyms',  
  6.         method: 'GET',  
  7.         headers: {  
  8.             "X-Mashape-Key""Your MaSH api kEY"  
  9.         }  
  10.     };  
  11.     var req = http.request(options, res => {  
  12.         setEncoding('utf8');  
  13.         var responseString = "";  
  14.         //accept incoming data asynchronously  
  15.         on('data', chunk => {  
  16.             responseString = responseString + chunk;  
  17.         });  
  18.         //return the data when streaming is complete  
  19.         on('end', () => {  
  20.             if (responseString != '') {  
  21.                 // to handle null response from API  
  22.                 if (!responseString.includes("word not found")) callback(JSON.parse(responseString));  
  23.                 else callback(null);  
  24.             } else {  
  25.                 callback(null);  
  26.             }  
  27.         });  
  28.     });  
  29.     end();  

We will use the above httpGet during SynonymsIntent invocation. So let's create a Synonyms Intent function within our Handlers object. 

Let us first see what we will be coding within Synonyms Intent when a user asks "Synonyms of {word}"  where word is a slot which we have created in part 1 of the article. So in Synonyms Intent function, we have to access the word slot, call the words API, get the response from Words API and format the response and use this.response.speak to return the message back to the user.

To access the slot within synonyms intent, we use event.request object. 

  1. var word=this.event.request.intent.slots.word.value;    

We can have validation checks like null  and multiple words in slots for words and different responses based on the validation failure. So for invalid slot words we should maintain an active session, so we have to reprompt the user using listen method in the response object.

  1. 'Synonyms'function() {  
  2.     var word = this.event.request.intent.slots.word.value;  
  3.     if (word == undefined || word == null) {  
  4.         this.response.speak('You havent spoken the word you want synonyms for.').listen('Can you say it again');  
  5.         this.emit(':responseReady');  
  6.         return;  
  7.     }  
  8.     console.log(word);  
  9.     if (word.split(' ').length > 1) {  
  10.         this.response.speak('Problem with word you have asked. Ask a single word').listen('Can you say it again');  
  11.         this.emit(':responseReady');  
  12.         return;  
  13.     } 

Now we call httpGet method by passing word slot and then process the response by splitting the json array of synonyms as a string message such as,  Synonyms of word are ...... Here we have restricted the number of synonyms to five.

  1. httpGet(word, (theResult) => {  
  2.     if (theResult === null) {  
  3.         speech = 'Sorry! No Synonyms Found, Please try again';  
  4.         this.response.speak(speech).listen('Sorry I Didnt Get you.');  
  5.         this.emit(':responseReady');  
  6.     } else {  
  7.         var theFact = theResult.synonyms;  
  8.         console.log(theFact);  
  9.         if (theFact.length == 0) {  
  10.             speech = 'Sorry! No Synonyms Found, Please try again';  
  11.             this.response.speak(speech).listen('Sorry I Didnt Get you.');  
  12.             this.emit(':responseReady');  
  13.             return;  
  14.         }  
  15.         var speech = "The Synonyms for the word " + word + " are ";  
  16.         for (vari = 0; i < theFact.length && i < 5; i++) {  
  17.             speech = speech + theFact[i] + ", ";  
  18.         }  
  19.     }  
  20.     this.response.speak(speech);  
  21.     this.emit(':responseReady');  
  22. });  

So far we have just created handler objects which we use to process the intents and we haven't used the alexa-sdk which we imported yet.  

We create an Alexa handler and register handler objects which we created and then execute it. 

  1. handler = function(event, context, callback) {    
  2.    const alexa = Alexa.handler(event, context, callback);    
  3.    alexa.APP_ID = APP_ID;    
  4.    alexa.registerHandlers(handlers);    
  5.    alexa.execute();    
  6. };   

Now that we are done with the code part of AWS Lambda function click save. We have already integrated our Alexa skill with AWS Lambda function. Now let us test the skill in Alexa simulator in Alexa Console.

Click Test in Skills console and test the skill in Alexa simulator. And it works fine.

Creating An Alexa Skill

You can even test the skill by providing a sample request as json using Manual JSON.  

Creating An Alexa Skill

That's it for this article.  You can create Alexa skills of your own by using different APIs based on the skill. Comment with your questions, if any, I am happy to help.