How to Debug Your Alexa Skill Using DynamoDB with the New Alexa Skills Kit SDK Helpers in Python

Douglas De Araujo Jul 31, 2019
Share:
Python Tutorial
Blog_Header_Post_Img

In April, we announced new helpers in the Alexa Skills Kit SDK for Python that allow you to locally run, test, and debug your Alexa skill faster. They also make it easier for you to deploy your skill backend as a web service built with Django or Flask.

If you are (or are thinking of) using AWS Lambda, testing and debugging may not be straightforward outside of using CloudWatch Logs. By adding a few lines of code, you can run any of your Alexa skills in Python on a local server, and use your favorite code editor to do step-by-step debugging and track down possible issues. This tutorial shows you how to set up a local Flask Server with a local DynamoDB instance for persistent storage and connect a debugger.

 

Part 1: Install the Flask Service and Change Your Skill Code

1. Install the flask-ask-sdk package through the pip command.

Copied to clipboard
pip install the flask-ask-sdk

2. Import the SkillBuilder class from the ASK SDK core package. This class provides utility methods to construct the skill instance and create lambda integration handler.

Copied to clipboard
from ask_sdk_core.skill_builder import SkillBuilder

3. Import the required Flask packages.

Copied to clipboard
from flask import Flask
from flask_ask_sdk.skill_adapter import SkillAdapter

4. Then, create a Flask web server from the Flask module using the prompt below:

Copied to clipboard
app = Flask(__name__)

5. Next, create your skill builder object by defining an instance of the SkillBuilder class.

Copied to clipboard
sb = SkillBuilder()

6. If you want to test whether or not your Flask server is responding, you can also add the following lines to the code after creating the skill builder object. Once you start your server in Visual Studio Code, you can navigate to http://127.0.0.1:5000/ in your browser, where you should see the message “Hello, Flask!”

Copied to clipboard
@app.route("/")
def home():
    return "Hello, Flask!"

7. Note that you can keep your intent handlers (Python classes) defined as they are.

Copied to clipboard
sb.add_request_handler(LaunchRequestHandler())
sb.add_request_handler(HelpIntentHandler())
sb.add_request_handler(CancelOrStopIntentHandler())
sb.add_request_handler(SessionEndedRequestHandler())

sb.add_exception_handler(CatchAllExceptionHandler())

handler = sb.lambda_handler()

8. After the last line in the previous prompt, insert the code shown below. This will allow you to create a skill adapter to register your skill and dispatch the incoming requests. Then you can run your application.

Copied to clipboard
skill_adapter = SkillAdapter(
                    skill=sb.create(), 
                    skill_id=1, 
                    app=app)

skill_adapter.register(app=app, route="/")

if __name__ == '__main__':
    app.run()

 

Part 2: Install Ngrok and Run It Locally

Now that your skill is running as a local Flask server, we need to make it available as an endpoint to the Alexa cloud service.

First, download and install ngrok. To run ngrok, type the following command:

Copied to clipboard
ngrok http -host-header="localhost:5000" 5000

Port 5000 is the port where your Flask server is running on. You should get an output like this:

Alexa Blog

The underlined ngrok URL displayed in the prompt above is the public URL you will use for your web service. This public URL can change every time you run your ngrok server, so this an example URL. If you want to test whether or not your public URL (https://9cdaeb58.ngrok.io in this example) is working as expected, you can just type it in your browser and you should see the message “Hello, Flask!” again. You can also inspect HTTPS request and response details running over the ngrok tunnels by navigating to http://localhost:4040 in a web browser.

 

Part 3: Update the Endpoint in the Developer Console

Now that you have a public URL to connect to your skill backend, you can update the endpoint information.

1. In the developer console, click on the “Build” tab, then select “Endpoint.”

Alexa Blog
Alexa Blog

 

2. Select “HTTPS” under “Service Endpoint Type,” and then enter your public URL in the “Default Region” field. This will allow you to test your skill by running your backend on your local machine.

Alexa Blog

 

3. In the dropdown menu, select the SSL certificate option “My development endpoint is a subdomain of a domain that has a certificate from a trusted certificate authority”.

Alexa Blog

 

4. Now that your endpoint is defined, you can save it.

Alexa Blog

 

Part 4: Add DynamoDB Persistence to Your Local Environment

When you need to retain data during the skill session, you use session attributes. Session attributes exist while the session is open. Once the session ends, any attributes associated with that session are lost. If your skill needs to remember data across multiple sessions, you need to save that data in persistent storage such as DynamoDB or S3.

DynamoDB is a key-value and document database. You can download, install, and run a self-contained version of DynamoDB on your computer. This version will allow you to write and test applications without accessing the DynamoDB web service.

Once you’ve downloaded DynamoDB, navigate to the directory where you extracted DynamoDBLocal.jar, and type the following command:

Copied to clipboard
java -Djava.library.path=./DynamoDBLocal_lib -jar DynamoDBLocal.jar –sharedDb

The local DynamoDB uses port 8000 by default.

Next, take the following steps:

1. Import the boto3 module from the AWS SDK for Python. Boto is the Amazon Web Services (AWS) SDK for Python. It enables Python developers to create, configure, and manage AWS services such as DynamoDB.

Copied to clipboard
import boto3

2. Import the StandardSkillBuilder class from the Alexa Skills Kit (ASK) SDK standard. This provides Persistence and Service Client features. It also provides optional parameters for configuring the DynamoDB table options. Note that you no longer need to use the SkillBuilder class from the ASK SDK core package.

Copied to clipboard
from ask_sdk.standard import StandardSkillBuilder

3. Create a resource object representing the local DynamoDB by defining the resource to be used and the endpoint where the local DynamoDB server is running on.

Copied to clipboard
srvcResource = boto3.resource('dynamodb', endpoint_url='http://localhost:8000')

4. Create your skill builder object by using the constructor for the StandardSkillBuilder class. The constructor accepts three parameters: the name of the table you want to create; the flag indicating that the table will be created, if it does not exist; and the DynamoDB client, which is the resource object to be used.

Copied to clipboard
sb = StandardSkillBuilder(table_name="meuwebserv", 
                          auto_create_table=True, 
                          dynamodb_client=srvcResource)

Then you just use your attributes manager object to interact with your persistent attributes. The attributes manager object is defined inside the handler_input object, available in each request handler implemented in your skill. A request handler is the code responsible for taking action on one or more types of incoming requests.

You can retrieve and save your persistent attributes to DynamoDB with the following prompts:

Copied to clipboard
attr = handler_input.attributes_manager.persistent_attributes

#update your session attributes

handler_input.attributes_manager.save_persistent_attributes()

 

Part 5: Test and Debug

You are now ready to start testing and debugging your skill. You can use the Alexa simulator for testing the utterances. Visual Studio Code (or your favorite editor) can be used to set breakpoints in your code and do the step-by-step debugging.

Testing and debugging your Alexa skill with Lambda may not be a simple task if you are not using CloudWatch logs. With the new ASK SDK helpers, you can add a few lines of code and run any of your Alexa skills in Python on a local server. You can also use your favorite code editor to do step-by-step debugging and track down possible issues.

 

Related Content