diff --git a/module-1/README.md b/module-1/README.md index 067635e..8052945 100644 --- a/module-1/README.md +++ b/module-1/README.md @@ -14,7 +14,7 @@ Once you’ve completed this course; you’ll have built a skill that is useful, ### About this module If this is your first time building an Alexa skill, we recommend completing this module and the next three, which walk you through all the necessary steps. Don’t worry if you get stuck along the way or if your code breaks. At the end of each module, the complete working code solution is provided for you under the **Code** heading. -If you’re already up to speed on the fundamentals of Alexa skill building and want to make your skill more conversational, please take a look at the [conversational design course](http://alexa.design/cdw) . +If you’re already up to speed on the fundamentals of Alexa skill building and want to make your skill more conversational, please take a look at the [conversational design course](http://alexa.design/cdw). ### Features covered * Utterances @@ -49,7 +49,11 @@ To get started, log into the [Alexa developer console](https://developer.amazon ![](http://alexa-github.s3.amazonaws.com/alexa-hosted-python.png) -**f.** At the top of the page, click **Create skill**. +**f.** Choose the **Hello World Skill** template. + +![](./hello_world_template.PNG) + +**g.** At the top of the page, click **Create skill**. ![](http://alexa-github.s3.amazonaws.com/create-skill-button.png) @@ -62,11 +66,18 @@ To get started, log into the [Alexa developer console](https://developer.amazon > ![](https://d3ogm7ac91k97u.cloudfront.net/content/dam/alexa/alexa-skills-kit/courses/cake-walk/3/building-a-skill-2f-3.png) ## Step 3: Greet the user -The first thing a user will want to do with the skill is open it. The intent of opening the skill is built into the experience, so you don’t need to define this intent in your front end. +The first thing a user will want to do with the skill is open it. On the front end, we will need to update the intent phrase that will be used to open this skill. You will also need to respond to the intent in your backend. In this step, you will update the invocation name and your backend code to greet the user when they open the skill. + +**a.** Open the Cake Walk skill in the Alexa developer console. The Build tab should automatically be opened. This is where the front end user interaction is configured. Click the Invocation tab in the ribbon on the left. Under **Skill Invocation Name**, change the existing text to "cake walk". + + +![](./cake_walk_invocation.PNG) + +**b.** Click **Save Model**. -However, you need to respond to the intent in your backend. In this step, you will update your backend code to greet the user when they open the skill. +**c.** Click **Build Model**. -**a.** Open the Cake Walk skill in the Alexa developer console. Click the Code tab. The code editor opens the lambda_function.py file. +**d.** Click the Code tab. The code editor opens the lambda_function.py file. ![](http://alexa-github.s3.amazonaws.com/python-code-tab.png) @@ -86,7 +97,7 @@ Within the **LaunchRequestHandler** object, find the **handle()** function. This Within the **handle()** function, find the line that begins **speak_output =**. This variable contains the string of words the skill should say back to the user when they launch the skill. Let’s change what it says to make sense for this skill. -**b.** Within the **LaunchRequestHandler** object, find the **handle()** function, and the line that begins **speak_output =**. Replace that line with the following: +**e.** Within the **LaunchRequestHandler** object, find the **handle()** function, and the line that begins **speak_output =**. Replace that line with the following: ```python speak_output = "Hello! Welcome to cake walk. That was a piece of cake! Bye!" @@ -96,7 +107,7 @@ speak_output = "Hello! Welcome to cake walk. That was a piece of cake! Bye!" > > **When you replace existing text or add new text to the code, blank lines may be introduced just before or after the text. Blank lines will not impact the code, but you may remove them.** > -> **You may also notice your lines of code are not indented the same as code snippets in this course. This will also not impact the code, but you can use the TAB key to indent code if you would like.** +> **You may also notice your lines of code are not indented the same as code snippets in this course. However, tabbing is important in Python so be careful when using tabs in your code.** Within the **LaunchRequestHandler**, on the line under the speech text you just replaced, look for **handlerInput.responseBuilder**. This piece of the SDK will help build the response to the user. @@ -105,9 +116,9 @@ On the next line, look for **.speak(speak_output)**. Note the **speak_output** v Next, look for the **.ask()** function within **responseBuilder**. (Be sure you are looking in the **LaunchRequestHandler**, within the **handle()** function.) If the skill was supposed to listen for the user’s response, you would use this. In this case, you want the skill to speak and then exit. Therefore, let’s omit this line of code for now. -**c.** Within the **LaunchRequestHandler**, in the **handle()** function, find the line that begins **.ask()**. Add a **#** at the beginning of the line. This turns the line into a comment, meaning the line is ignored when the code runs. +**f.** Within the **LaunchRequestHandler**, in the **handle()** function, find the line that begins **.ask()**. Add a **#** at the beginning of the line. This turns the line into a comment, meaning the line is ignored when the code runs. -**d.** Next, look for the **.response()** function just below the line you commented out in the **LaunchRequestHandler**. This converts the **responseBuilder’s** work into the response that the skill will return. Remember the line that started with return? Think of it like hitting the Send button—it sends the response. +**g.** Next, look for the **.response()** function just below the line you commented out in the **LaunchRequestHandler**. This converts the **responseBuilder’s** work into the response that the skill will return. Remember the line that started with return? Think of it like hitting the Send button—it sends the response. Your **LaunchRequestHandler** should now look like: @@ -132,11 +143,11 @@ class LaunchRequestHandler(AbstractRequestHandler): ``` You have built the code that will handle a LaunchRequest for this skill. Before doing anything else, save your changes and deploy the code. -**e.** Click **Save**. +**h.** Click **Save**. ![](https://d3ogm7ac91k97u.cloudfront.net/content/dam/alexa/alexa-skills-kit/courses/cake-walk/3/building-a-skill-3-save.png) -**f.** Click **Deploy**. +**i.** Click **Deploy**. ![](https://d3ogm7ac91k97u.cloudfront.net/content/dam/alexa/alexa-skills-kit/courses/cake-walk/3/building-a-skill-3-deploy.png) @@ -160,7 +171,7 @@ There are two ways to test your skill in the console. With the first method, typ So far, the skill has one intent: **LaunchRequest**. This function responds to the user when they ask Alexa to open or launch the skill. The user will say, “Alexa, open Cake Walk.” Cake Walk is the name of your skill and was automatically set as the invocation name for the skill. You can change the invocation name, but let’s leave it as is for this exercise. -**c.** Test the skill. Type **open Cake Walk** (not case sensitive) into the box at the top left and press **ENTER**, or click and hold the microphone icon and say, “**Open Cake Walk**.” +**a.** Test the skill. Type **open Cake Walk** (not case sensitive) into the box at the top left and press **ENTER**, or click and hold the microphone icon and say, “**Open Cake Walk**.” > **When testing your skill in the Alexa developer console, you don’t need to provide the wake word (usually “Alexa”). Typing or saying, “Open Cake Walk” is fine. When testing on an Alexa-enabled device, you need the wake word: “Alexa, open Cake Walk.”** diff --git a/module-1/cake_walk_invocation.PNG b/module-1/cake_walk_invocation.PNG new file mode 100644 index 0000000..0308df0 Binary files /dev/null and b/module-1/cake_walk_invocation.PNG differ diff --git a/module-1/hello_world_template.PNG b/module-1/hello_world_template.PNG new file mode 100644 index 0000000..4f0b054 Binary files /dev/null and b/module-1/hello_world_template.PNG differ diff --git a/module-2/README.md b/module-2/README.md index 7be81a2..1b1ef08 100644 --- a/module-2/README.md +++ b/module-2/README.md @@ -140,19 +140,13 @@ Notice that the text does not include punctuation. > **When finished, the Cake Walk skill will be able to capture any birthday.** From this utterance, there are three key pieces of information to collect: month, day, and year. These are called slots. You need to let Alexa know which words are slots and what kind of slots they are. -Start with the month slot. In the utterance, you will replace the word representing the month (November) with the word **month** in curly brackets ({ }). This creates a slot called month. The utterance will then look like this: **I was born on {month} seventh nineteen eighty three** -There are two ways to create a slot. The first way is to select the word in the sample utterance where the slot should go and type the name of the slot in curly brackets (for example, **{month}**). -The second way is to select the word in the sample utterance and use the **Select an Existing Slot** dialog box when it appears. In the dialog box, click the field under **Create a new slot**, type the name of the slot without curly brackets (for example, **month**), and click **Add**. +Start with the month slot. In the utterance, you will replace the word representing the month (November) with the word **month** in curly brackets ({ }). This creates a slot called month. The utterance will then look like this: **I was born on {month} seventh nineteen eighty three**. The slot is automatically created when the closing curly brace is typed. Once this utterance is added, a list of slots appears below the list of utterances. -![](https://d3ogm7ac91k97u.cloudfront.net/content/dam/alexa/alexa-skills-kit/courses/cake-walk/4/chapter4-2e2.png) - -**f.** In the utterance, use either method of creating a slot to create a slot called **month** over the word **November**. - -**g.** Repeat this process for the other variable pieces of information (day and year). +**f.** Repeat this process for the other variable pieces of information (day and year). Your utterance should now look like this: **I was born on {month} {day} {year}** -What if the user omits the words _I was born on_? Account for this by adding a second utterance with only the slots. +What if the user omits the words _I was born on_? Account for this by adding a second utterance with only the slots: **{month} {day} {year}** -**h.** In the **Sample Utterances** field, type the following, and then press **ENTER** or click the + icon: **{month} {day} {year}** +**g.** In the **Sample Utterances** field, type the following, and then press **ENTER** or click the + icon: **{month} {day} {year}** ![](https://d3ogm7ac91k97u.cloudfront.net/content/dam/alexa/alexa-skills-kit/courses/cake-walk/4/chapter4-2h.png) @@ -160,13 +154,13 @@ What if the user omits the words _I was born on_? Account for this by adding a s Now, you should account for a few other potential slot combinations. -**i.** Enter each of the examples below as sample utterances. When you are finished, you should have six utterances. -{month} {day} -{month} {day} {year} -{month} {year} -I was born on {month} {day} -I was born on {month} {day} {year} -I was born in {month} {year} +**h.** Enter each of the examples below as sample utterances. When you are finished, you should have six utterances. +> {month} {day} +> {month} {day} {year} +> {month} {year} +> I was born on {month} {day} +> I was born on {month} {day} {year} +> I was born in {month} {year} You have let Alexa know what slots need to be collected (and covered some of the different patterns users might provide that information in). Now you need to define exactly what those slots are by assigning a slot type to each slot. @@ -182,18 +176,18 @@ If an applicable built-in slot does not exist, create a custom slot and define t ![](https://d3ogm7ac91k97u.cloudfront.net/content/dam/alexa/alexa-skills-kit/courses/cake-walk/4/chapter4-2i2.png) -**j.** To the right of the **month** slot, select **AMAZON.Month** from the **Slot Type** drop-down menu. +**i.** To the right of the **month** slot, select **AMAZON.Month** from the **Slot Type** drop-down menu. -**k.** For the **day** slot, select **AMAZON.Ordinal** as the slot type. +**j.** For the **day** slot, select **AMAZON.Ordinal** as the slot type. -**l.** For the **year** slot, select **AMAZON.FOUR_DIGIT_NUMBER** as the slot type. +**k.** For the **year** slot, select **AMAZON.FOUR_DIGIT_NUMBER** as the slot type. ![](https://d3ogm7ac91k97u.cloudfront.net/content/dam/alexa/alexa-skills-kit/courses/cake-walk/4/chapter4-2j.png) You have created an intent to collect the user's birthday. But what about a user who doesn't respond with all three slot values? For example, a user who responds, "In July." Let's take a look at solving that problem. -**m.** At the top of the page, click **Save Model**. +**l.** At the top of the page, click **Save Model**. ![](https://d3ogm7ac91k97u.cloudfront.net/content/dam/alexa/alexa-skills-kit/courses/cake-walk/4/chapter4-2m.png) @@ -259,7 +253,7 @@ If you look at the code, you will notice the **HelloWorldIntentHandler**. But yo **c.** Within the **CaptureBirthdayIntentHandler**, on the line that begins **return ask_utils.is_intent_name("HelloWorldIntent")(handler_input)**, change '**HelloWorldIntent**' to '**CaptureBirthdayIntent**' -This change ensures that the **canHandle()** function will be invoked when a **CaptureBirthdayIntent** request comes through. +This change ensures that the **canHandle()** function will be invoked when a **CaptureBirthdayIntent** request comes through. Your `CaptureBirthdayIntentHandler ` should now look like: @@ -286,9 +280,7 @@ Now you need to update the logic within the handler so Alexa will confirm to the Start by creating three variables in the handler to save the slots the skill is collecting. -**d.** Within the **CaptureBirthdayIntentHandler**, find the line that begins **def handle(self, handler_input):**. Create a new line _below_it. - -**e.** Copy and paste the following code on the new line: +**d.** Within the **CaptureBirthdayIntentHandler**, find the line that begins **def handle(self, handler_input):**. Create a new line below it. Copy and paste the following code at the beginning of the handle function. ```py slots = handler_input.request_envelope.request.intent.slots @@ -297,7 +289,7 @@ Start by creating three variables in the handler to save the slots the skill is day = slots["day"].value ``` -Next, update the **speak_output**. To do this, we use string interpolation to substitute values of our variables into placeholders in our string. While Python supports multiple ways to do this, we will use .format() function to replace placeholder values inside braces {} with the values of our variables. +**e.** Next, update the **speak_output**. To do this, we use string interpolation to substitute values of our variables into placeholders in our string. While Python supports multiple ways to do this, we will use .format() function to replace placeholder values inside braces {} with the values of our variables. This allows you to drop the new variables into a text string. @@ -395,6 +387,6 @@ However, while your skill can ask for a user’s birthday, your skill doesn’t ## Code If your skill isn’t working or you’re getting some kind of syntax error, download the code sample in Python from the link below. Then, go to the Code tab in the Alexa developer console and copy and paste the code into the **lambda_function.py** file. Be sure to save and deploy the code before testing it. - [Python Github Code Sample, Module 2: Collecting Slots Turn by Turn](https://github.com/alexa/skill-sample-python-first-skill/tree/master/module-2) + [Python Github Code Sample, Module 2: Collecting Slots Turn by Turn](https://github.com/alexa/skill-sample-python-first-skill/tree/master/module-2) [Continue to module 3](https://github.com/alexa/skill-sample-python-first-skill/tree/master/module-3) diff --git a/module-3/README.md b/module-3/README.md index c13340c..d111d8e 100644 --- a/module-3/README.md +++ b/module-3/README.md @@ -28,7 +28,7 @@ Start by using the AttributesManager to save the user’s birthday in Cake Walk. ask-sdk-s3-persistence-adapter ``` -Your requirements.text file should now look like: +Your requirements.txt file should now look like: ``` boto3==1.9.216 @@ -50,10 +50,20 @@ The new dependency allows you to use the AttributesManager to save and read user ```py import os from ask_sdk_s3.adapter import S3Adapter -s3_adapter = S3Adapter(bucket_name=os.environ["S3_PERSISTENCE_BUCKET"]) +s3_adapter = S3Adapter(bucket_name="NAME_OF_YOUR_BUCKET_HERE") ``` -**h.** In the **lambda_function.py** file, find the line that begins **from ask_sdk_core.skill_builder import SkillBuilder**. Replace this line with the following code: +**h.** We need to update the name of the bucket we are using. To view available buckets provided by Amazon S3, click **Media Storage: S3 [0.0/5GB]** at the bottom left corner of the screen. + +![](./media_storage.PNG) + +**i.** Expand the menu on the left by clicking the small arrow at the top left of the screen, and click **Buckets**. We will be using the first bucket as shown below. + +![](./s3_buckets.PNG) + +**j.** In the code from step g, replace **NAME_OF_YOUR_BUCKET_HERE** with the name of the bucket found in step **i**. + +**k.** In the **lambda_function.py** file, find the line that begins **from ask_sdk_core.skill_builder import SkillBuilder**. Replace this line with the following code: ```py from ask_sdk_core.skill_builder import CustomSkillBuilder @@ -66,7 +76,7 @@ import logging import ask_sdk_core.utils as ask_utils import os from ask_sdk_s3.adapter import S3Adapter -s3_adapter = S3Adapter(bucket_name=os.environ["S3_PERSISTENCE_BUCKET"]) +s3_adapter = S3Adapter(bucket_name="NAME_OF_YOUR_BUCKET_HERE") from ask_sdk_core.skill_builder import CustomSkillBuilder from ask_sdk_core.dispatch_components import AbstractRequestHandler @@ -79,13 +89,13 @@ logger = logging.getLogger(__name__) logger.setLevel(logging.INFO) ``` -**i.** In the **lambda_function.py** file, scroll all the way down to find the line that begins **sb = SkillBuilder()**. Replace this line with the following code: +**l.** In the **lambda_function.py** file, scroll all the way down to find the line that begins **sb = SkillBuilder()**. Replace this line with the following code: ```py sb = CustomSkillBuilder(persistence_adapter=s3_adapter) ``` -**j.** Click **Save**. +**m.** Click **Save**. ![](https://d3ogm7ac91k97u.cloudfront.net/content/dam/alexa/alexa-skills-kit/courses/cake-walk/5/chapter5-1e.png) @@ -295,4 +305,4 @@ If your skill isn’t working or you’re getting some kind of syntax error, dow [Python Github Code Sample, Module 3: Add Memory to Your Skill](https://github.com/alexa/skill-sample-python-first-skill/tree/master/module-3) -[Continue to module 4](https://github.com/alexa/skill-sample-python-first-skill/tree/master/module-4) \ No newline at end of file +[Continue to module 4](https://github.com/alexa/skill-sample-python-first-skill/tree/master/module-4) diff --git a/module-3/lambda_function.py b/module-3/lambda_function.py index 6350c9d..7a434bd 100644 --- a/module-3/lambda_function.py +++ b/module-3/lambda_function.py @@ -8,7 +8,7 @@ import ask_sdk_core.utils as ask_utils import os from ask_sdk_s3.adapter import S3Adapter -s3_adapter = S3Adapter(bucket_name=os.environ["S3_PERSISTENCE_BUCKET"]) +s3_adapter = S3Adapter(bucket_name="NAME_OF_YOUR_BUCKET_HERE") from ask_sdk_core.skill_builder import CustomSkillBuilder from ask_sdk_core.dispatch_components import AbstractRequestHandler @@ -210,4 +210,4 @@ def handle(self, handler_input, exception): sb.add_exception_handler(CatchAllExceptionHandler()) -lambda_handler = sb.lambda_handler() \ No newline at end of file +lambda_handler = sb.lambda_handler() diff --git a/module-3/media_storage.PNG b/module-3/media_storage.PNG new file mode 100644 index 0000000..0d0c6c7 Binary files /dev/null and b/module-3/media_storage.PNG differ diff --git a/module-3/s3_buckets.PNG b/module-3/s3_buckets.PNG new file mode 100644 index 0000000..8d049fa Binary files /dev/null and b/module-3/s3_buckets.PNG differ diff --git a/module-4/README.md b/module-4/README.md index 297c980..bd0c5f0 100644 --- a/module-4/README.md +++ b/module-4/README.md @@ -24,7 +24,7 @@ handlerInput.requestEnvelope.context.System.device.deviceId > > **device_id = ask_sdk_core.utils.request_util.get_device_id(handler_input)** > -> *For additional information, refer to [ASK SDK Python Utilities. ](https://alexa-skills-kit-python-sdk.readthedocs.io/en/latest/api/core.html#module-ask_sdk_core.utils.predicate)* +> *For additional information, refer to [ASK SDK Python Utilities]. (https://alexa-skills-kit-python-sdk.readthedocs.io/en/latest/api/core.html#module-ask_sdk_core.utils.predicate)* **a.** In the developer console, click the **Code** tab, then click on the file **requirements.txt** @@ -98,7 +98,7 @@ class HasBirthdayLaunchRequestHandler(AbstractRequestHandler): Now that we have the Device ID, API endpoint, and the access token, we are ready to call the Alexa Settings API to get the user time zone. ## Step 2: Using the Alexa Settings API to retrieve the user time zone -There’s a chance that an error can happen when the code makes a call to the Alexa Settings API. For example, if the API takes too long to respond, the code could time out. Therefore, you need to wrap the code in a **try_catch_**_ block. A _**_try_catch** block is a way to ensure the skill code doesn’t crash if it encounters an error. You will wrap the code that _could_ crash in a **try** block. If the code within that block crashes, the **catch** block will run to handle errors. +There’s a chance that an error can happen when the code makes a call to the Alexa Settings API. For example, if the API takes too long to respond, the code could time out. Therefore, you need to wrap the code in a **try/catch block**. A try/catch block is a way to ensure the skill code doesn’t crash if it encounters an error. You will wrap the code that _could_ crash in a **try** block. If the code within that block crashes, the **catch** block will run to handle errors. You want to know the time zone for the user’s Alexa-enabled device. In the **try** block, use **serviceClientFactory** to get the settings service client—upsServiceClient—and pass the device ID to the **getSystemTimeZone** function to get the time zone. The **catch** block will log an error message using **console.log** and return an error message response that Alexa will say to the user. @@ -354,12 +354,7 @@ If it is the user’s birthday, you want the skill to wish them happy birthday. speak_output = “Happy {}th birthday!”.format(str(current_year - year)) if now_date != next_birthday: diff_days = abs((now_date - next_birthday).days) - speak_output = “Welcome back. It looks like there are \ - {days} days until your {birthday_num}th\ - birthday”.format( - days=diff_days, - birthday_num=(current_year-year) - ) + speak_output = “Welcome back. It looks like there are {days} days until your {birthday_num}th birthday”.format(days=diff_days,birthday_num=(current_year-year)) ``` **b.** Within the **HasBirthdayLaunchRequestHandler**, remove the comment that begins with **# TODO:: Say happy birthday on the user’s birthday**. We’ve just added this functionality. @@ -430,12 +425,7 @@ class HasBirthdayLaunchRequestHandler(AbstractRequestHandler): speak_output = "Happy {}th birthday!".format(str(current_year - year)) if now_date != next_birthday: diff_days = abs((now_date - next_birthday).days) - speak_output = "Welcome back. It looks like there are \ - {days} days until your {birthday_num}th\ - birthday".format( - days=diff_days, - birthday_num=(current_year-year) - ) + speak_output = speak_output = "Welcome back. It looks like there are {days} days until your {birthday_num}th birthday".format(days=diff_days,birthday_num=(current_year-year)) handler_input.response_builder.speak(speak_output) @@ -455,4 +445,4 @@ class HasBirthdayLaunchRequestHandler(AbstractRequestHandler): ## Code If your skill isn’t working or you’re getting some kind of syntax error, download the code sample in Python from the link below. Then, go to the Code tab in the Alexa developer console and copy and paste the code into the **lambda_function.py** file. Be sure to save and deploy the code before testing it. - [Python Github Code Sample, Module 4: Using the Alexa Setting API](https://github.com/alexa/skill-sample-python-first-skill/tree/master/module-4) \ No newline at end of file + [Python Github Code Sample, Module 4: Using the Alexa Setting API](https://github.com/alexa/skill-sample-python-first-skill/tree/master/module-4) diff --git a/module-4/lambda_function.py b/module-4/lambda_function.py index e5af985..155f030 100644 --- a/module-4/lambda_function.py +++ b/module-4/lambda_function.py @@ -12,7 +12,7 @@ from datetime import datetime from pytz import timezone from ask_sdk_s3.adapter import S3Adapter -s3_adapter = S3Adapter(bucket_name=os.environ["S3_PERSISTENCE_BUCKET"]) +s3_adapter = S3Adapter(bucket_name=os.environ["INSERT_YOUR_BUCKET_NAME_HERE"]) from ask_sdk_core.skill_builder import CustomSkillBuilder from ask_sdk_core.dispatch_components import AbstractRequestHandler @@ -107,12 +107,7 @@ def handle(self, handler_input): speak_output = "Happy {}th birthday!".format(str(current_year - year)) if now_date != next_birthday: diff_days = abs((now_date - next_birthday).days) - speak_output = "Welcome back. It looks like there are \ - {days} days until your {birthday_num}th\ - birthday".format( - days=diff_days, - birthday_num=(current_year-year) - ) + speak_output = "Welcome back. It looks like there are {days} days until your {birthday_num}th birthday".format(days=diff_days,birthday_num=(current_year-year)) handler_input.response_builder.speak(speak_output) @@ -264,4 +259,4 @@ def handle(self, handler_input, exception): sb.add_exception_handler(CatchAllExceptionHandler()) -lambda_handler = sb.lambda_handler() \ No newline at end of file +lambda_handler = sb.lambda_handler()