Calling AWS Lambda Functions From Alexa (Part 1)
Learn how to create a simple Alexa skill, then a Lambda function to handle requests. Finally, get a look at how the SDK interacts with Alexa intents.
Join the DZone community and get the full member experience.
Join For FreeBy now, most of you are familiar with Alexa, the virtual assistant created by Amazon and popularized through their line of Echo smart speakers and devices. Alexa gives users the capability to execute actions from a pre-defined set of functionality (called “skills”) using a voice interface. Alexa performs language processing and converts the spoken words into programmatic action
In this two-part series, we’re going to take a look at leveraging this platform to drive execution of AWS Lambda functions. We’ll cover creating a custom Alexa skill, building intents to drive our skill, and finally modifying those intents to call an item in a list of arbitrary AWS Lambda functions hosted in a Backand application.
Before we get started, take a look at this short video I created:
This demonstrates how easily you can adapt this technique into a useful skill. The Alexa skill used to create the demo video below relies on three Lambda functions – one to run the skill, one to interface with Yelp, and one to interface with OpenTable.
We’ll start with a straightforward base of calling a Lambda function in response to a voice command, then expand this to allow for arbitrary execution of a Lambda function based on a dynamic list we obtain from a Backand application.
Architecture of an Alexa Skill
At a high level, the architecture of an Alexa skill is as follows:
- The custom Alexa skill: This is an object within AWS that manages the invocation of your custom Alexa skill from the Alexa service.
- The Alexa skill handler function: This is a Lambda function that provides the code driving the custom Alexa skill being developed. It handles obtaining the information that fulfills the user’s request.
- Third-party function: These functions, which could be anything from a database call to a third-party web request, are hosted outside of the Alexa skill and provide the concrete functionality for the intents to be performed.
So in this sense, the Alexa Lambda function is a service dispatcher, accepting a processed voice command from an Alexa-enabled device and routing that traffic to the appropriate handler.
Creating a Custom Alexa Skill
So now that we have a high-level view of the architecture, let’s look at constructing the skill itself. To get started, you’ll need to sign up for a developer account at developer.amazon.com. Once there, select “Alexa” from the top navigation bar:
On the Alexa screen, you’re presented with two options – “Alexa Skills Kit” and “Alexa Voice Service.” For custom skills, like the one we’ll be building, you’ll want to select “Alexa Skills Kit” and then press the “New skill” button in the upper-right-hand corner of the page. Once that’s done, you’re brought to the skill configuration page:
You’ll use this screen to configure the remainder of your skill’s functionality. This first page, “Skill Information,” contains two vital pieces of information – the name of your custom Alexa skill (which is what users will search for when looking for Alexa skills) and the invocation name. This invocation name plays a crucial role in your skill, as it provides the voice commands issued by the user when working with the skill on an Alexa-enabled device.
Alexa custom skills should usually be invoked via their name prior to requesting the functionality. This reduces confusion on Alexa’s side as well as the user’s. Also, if you are working on a skill that shares common utility, such as building a restaurant reservation skill, you’ll often find that Alexa already has variations on many of the activation phrases you are likely to rely upon. Take, for example, the command one might use to reserve a table at a restaurant:
“Alexa, get me a reservation for 6:00 PM at Per Se.”
Without the custom skill being specified, the above command translates into a request handled by an official skill put out by OpenTable.com. By specifying our custom skill name in the command, we can circumvent this behavior:
“Alexa, ask My Amazing Restaurants to get me a reservation for 6:00 PM at Per Se.”
There are a number of different techniques you can use to invoke a skill by name – which of those you rely upon will largely be driven by the grammar of your underlying commands. Read more in the Alexa developer documentation.
Controlling Alexa With AWS Lambda
As mentioned previously, Amazon Alexa needs to be controlled through a custom AWS Lambda function. Luckily, there are several blueprints provided for AWS Lambda that already cover some of this functionality. You can see them from the AWS Lambda creation screen (“alexa-skill-kit-sdk-factskill” in the list below):
Note: AWS Lambda functions for Alexa, per the Alexa developer documentation, can only be located in either the US East (N. Virginia) or EU (Ireland) regions.
Once you’ve selected your Alexa skill handler, you’ll next be taken to the “Choose a trigger” screen. From this screen, if you’re in the correct region, you should see “Alexa Skills Kit” as an option – select it:
Once this is complete, you’re brought to the Configure Function screen. On this screen, you can see the initial stub code for your Lambda handler functions. Copy this into a separate Node.JS project on your local machine and you’re ready to go.
Analyzing the Sample Code
The sample code provided uses the Alexa SDK from Amazon to implement processing of intent handlers. There are a few relevant blocks of code to examine that provide all of the critical Alexa-related functionality. The first is in the Lambda Function Handler:
exports.handler = function (event, context) {
const alexa = Alexa.handler(event, context);
alexa.APP_ID = APP_ID;
// To enable string internationalization (i18n) features, set a resources object.
alexa.resources = languageStrings;
alexa.registerHandlers(handlers);
alexa.execute();
};
This code accepts the event and context passed in by AWS Lambda and passes those to the Alexa SDK. It then registers a set of internationalized resources, to be used as response commands, and registers a set of handler functions using the registerHandlers() command. Finally, the function passes control to the Alexa SDK via the execute() method. The execute() method finds a handler for the current Alexa intent from the list of registered handlers. These are specified in the file as an associative array between intent names and functions. The code looks like this:
const handlers = {
'LaunchRequest': function () {
this.emit('GetFact');
},
'GetNewFactIntent': function () {
this.emit('GetFact');
},
'GetFact': function () {
// Get a random space fact from the space facts list
// Use this.t() to get corresponding language data
const factArr = this.t('FACTS');
const factIndex = Math.floor(Math.random() * factArr.length);
const randomFact = factArr[factIndex];
// Create speech output
const speechOutput = this.t('GET_FACT_MESSAGE') + randomFact;
this.emit(':tellWithCard', speechOutput, this.t('SKILL_NAME'), randomFact);
},
'AMAZON.HelpIntent': function () {
const speechOutput = this.t('HELP_MESSAGE');
const reprompt = this.t('HELP_MESSAGE');
this.emit(':ask', speechOutput, reprompt);
},
'AMAZON.CancelIntent': function () {
this.emit(':tell', this.t('STOP_MESSAGE'));
},
'AMAZON.StopIntent': function () {
this.emit(':tell', this.t('STOP_MESSAGE'));
},
};
While the code above is specific to the quiz skill template that is provided by the AWS Lambda function blueprint, we can identify a few pieces of useful information:
- Handlers are defined by adding a new entry to this array, with the intent name as the key and the functionality handling the intent as the value
- We can emit responses to Alexa using this.emit()
- We can emit different kinds of responses, resulting in variations in control flow. The code sample above uses ‘tell’, ‘ask’, and ‘tellWithCard’ to instruct Alexa in how to respond. There are a large number of response types that can be implemented through Amazon Alexa, including modifications to the speech pattern in the response. Review the SDK Readme and the developer documentation for more detail.
Using this simple skeleton, we can easily adapt the code to do whatever we please. Start by modifying the existing intents, to see how you can affect Alexa’s response data. Once you’ve exhausted this bit of functionality, you’ll want to look at creating intents – something we’ll handle in the next post in this series.
Conclusion
So far, we’ve started the basic configuration of our custom Alexa skill. We’ve created the skill, we’ve created a Lambda function to handle the skill request, and we’ve examined how we can use the SDK to interact with Amazon Alexa intents in our system. In the next post in this series, we’ll cover creating intents, then implementing those intents using the same handler mechanism as used in the blueprint AWS Lambda function above. We’ll then cover using this code to call out to a Backand API to fetch a list of Lambda functions, and finally, call an arbitrary member of that list using a dedicated Alexa skill.
Published at DZone with permission of Matt Billock, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments