Lab 4: Train Alexa Conversations to Collect Information

Welcome to lab 4 Train Alexa Conversations to collect information. In this lab, you'll learn how to build and link together all of the build-time components needed to build a skill with Alexa Conversations skill.

This includes:

  • dialogs
  • slots
  • API definitions
  • Utterance Sets
  • Response Templates

You will use these assets to annotate your dialogs. When you click build model, these annotations will allow Alexa Conversations to generate thousands of variations of your dialogs and then use them to train a machine learning model that will act as your dialog manager.

Time required: 60 minutes

What you'll learn:

  • How to add and annotate dialogs.
  • How to create input and output slots.
  • How to configure inform and request type responses.
  • How to add an API definition
  • How to create Utterance Sets
  • How to create your skill code

Introduction

In lab 3, you built an Alexa Conversations skill that can say several variations of, "Welcome to pet match. I can find the best dog for you. What are two things you're looking for in a dog?"

In this lab, you will teach the skill to collect values for our desired slots from your customer: size, temperament, and energy. You'll also train it to send those slots to your skill code via the getRecommendation API Definition. Finally, you'll teach your skill how to respond to your customer with the information our skill code provides back to Alexa conversations.

At the end of this lab your Pet Match skill will be set up to collect the energy, temperament, and size of dog and provide a recommendation. You'll create back-end code to handle these requests and then we'll test it all out!

Step 1: Add Dialogs

As discussed previously, Alexa Conversations builds a statistical model that will interpret inputs from your customer and predict the best response from your skill. To create this model you need to provide Alexa with a set of dialogs that demonstrate the functionalities we want in our skill. The build time systems behind Alexa Conversations will take the dialogs and create thousands of variations of these examples. You can teach your model how to behave by exposing it to these thousands of dialogs demonstrating how what you expect the model to interpret and predict in each of the cases. From that information, Alexa Conversations will be able to make a good guess of how to behave when your customer says something similar to the utterances in the dataset.

You want to specify a set of example dialogs that will form the core of your skill. On top of that, you'll add a set of notes that will allow the build-time tools to simplify specific sentences into into abstractions like utterance sets, slots, responses and other assets you've specified so it can properly generalize from your examples. In this section you'll add your examples, but we won't be able to add all of the notes until you've created the assets you'll need.

Start by adding the dialogs that you will work from.

  1. From the developer console click on the Dialogs page on the left navbar.
Dialogs

You're going to define your first dialog:

First Dialog

U: I want a large family dog.

A: Do you prefer low, medium, or high energy dogs?

U: Low

A: Okay! In that case I recommend a chihuahua.
  1. Click add dialog.

The dialog edit screen will appear. From here you can define and annotate your dialog.

  1. Name your dialog dialog0

In the center, there is a space for a user utterance and an Alexa response. This pairing is called a turn.

  1. Paste "I want a large family dog" into the User input field.

  2. Paste "Do you prefer low, medium, or high energy dogs?" into the Alexa input field.

Add Dialog
  1. Click on the User Says button to add "Low".

  2. Click on the Alexa Says button to add "Okay! In that case I recommend a chihuahua."

Add Dialog
  1. Paste the remaining turns into the appropriate boxes. When you're finished, the result should look like this:
Build Dialog
  1. Once you've made it this far, click on the save button to save your work.

Congratulations, you've created your first dialog! With your first dialog out of the way, you have four more left to create.

  1. Add the following dialogs into the skill.
Dialog1

U: I want a large dog with high energy.

A: Do you want a dog that is good with family or better at guarding

U: Family

A: Okay, in that case I recommend a chihuahua.
Build Dialog
Dialog2

U: I want a family dog with high energy.

A: Do you prefer tiny, small, medium, or large dogs?

U: Large

A: Okay, in that case I recommend a chihuahua.
Build Dialog
Dialog3

U: I want a large high energy guard dog.

A: Okay, in that case I recommend a chihuahua
Build Dialog
Dialog4

U: I want a large dog.

A: Do you prefer low, medium, or high energy dogs?

U: Low

A: Do you prefer a family dog or a guard dog?

U: Guard.

A: Okay, in that case I recommend a chihuahua.
Build Dialog

You've defined your sample dialogs that represent your happy path. Now you need to define slots, utterance sets, response templates and API Definitions so you can finish annotating your dialog to train Alexa Conversations. Doing so will enable Alexa Conversations to track conversational context and remember your customer's choices.

Step 2a: Import Slot Types

If you've made an intent-based Alexa custom skill before, you should be familiar with slots and slot types. A slot type backs a slot and aids the Automatic Speech Recognition (ASR) system to figure out what the customer has said. You can think of them as a list of values attached to slots. Slots are parts of an utterance that your skill needs in order to function. For example, "I want a large high energy guard dog" contains three slot values that Pet Match needs in order to function large, high and guard. Once you've defined your slot types, you can mark up the dialog with its corresponding slot. Upon doing so, your dialog will like:

Dialog with Slots

I want a {size} {energy} energy {temperament} dog.

As you can see, you can now represent all possible slot value permutations with just one sentence. While there are built-in slots, throughout this course, you'll be using custom slots.

Alexa Conversations has access to the slot types you've defined for an intent-based custom skill. We've prepared a custom interaction model that includes the energy, size and temperament slot types. Once you've imported that model, you'll be able to start marking up your dialog with slots.

  1. From the left navigation pane, you'll see a section labeled Interaction Model scroll down the page until you see JSON Editor.

  2. Click JSON Editor.

  3. A text area will appear.

  4. Copy the contents of JSON and paste it into the text area.

  1. Click Save. After importing the interaction model, you should see the size, temperament, and energy slot types appear underneath the Slot Types header on the left navigation pane.
Define Slot Types

Now that you've imported the model that includes the basic slot types known as custom with values (vcs), you need to use these to define some custom slots with properties.

Step 2b: Define Slot Types

Alexa Conversations introduces a new property based custom slot type. It is a collection of slots used to pass structured data between your build-time components such as API Definitions and response templates. You will define a "custom slot type with properties" to represent the data that your API will return.

  1. Click on Slot types on the left nav bar.

You will return to the slot type page. You now have three value-based custom slots size, energy, and temperament. These will be passed to an API that you'll define later and it will return the recommended dog breed along with the three value-based slots it received as input. To do this you'll define a custom slot type with properties.

  1. Click on add slot type.

  2. Select Create a custom slot type with values and enter, name into the text field.

  3. Add a value "dummy" since this slot will not collect inputs from the user.

  4. Click next.

  5. Click save and return to the slot types page.

Add Slot Name
  1. Next, click add slot type to create another slot.

Since custom slot types with properties are hierarchical you can use them to represent a data structure. In the previous step, you created the name slot type to hold the recommendation that your skill code will provide. Now you will define the container that will include the name, size, energy, and temperament slots. This will then be passed from your skill code to Alexa Conversations. Alexa Conversations will pass that data to a response template to speak the response.

Later on you'll create an API called getRecommendation. Since this custom slot types with properties will represent what that API returns, name it getRecommendationResult.

  1. Leave Create a custom slot type with properties selected and enter, getRecommendationResult into the text field.

Now that you've created a container, you need to add stuff to it. Start with the name.

  1. Click Add a New Property
Add new property
  1. In the name field that appears type "name" into the name field.

  2. From the type drop-down, select name.

  3. You'll repeat this process for the remaining value-based slots:

  • size
  • energy
  • temperament

These properties are value-based (VCS). In each case your customer is filling the slot with a spoken value and there is a constrained set of possible values. When you've finished, it should look like this:

Get recommendation result
  1. Click save

You've added all the slots you'll need for our skill! Now you need to define an API definition so can provide a recommendation based upon the inputs.

Step 3: Add API definitions

In order to train Alexa Conversations to call your skill code, you need to provide an API definition. The definition contains a name, a set of input slots (arguments), an output slot (return), and a set of response templates. Input slots can either be required or optional

At runtime, Alexa Conversations will try to predict which API definition to use based upon the conversation. If all of the required slots have been collected, Alexa Conversations will send a JSON request to your skill code. The JSON payload will include the API definition name and the slots (arguments). Your skill code will return a JSON response that contains the custom slot type with properties you defined.

For Pet Match, you want to make an API definition that will call your back end after your customer provides the size, temperament, and energy slots and return the recommendation.

In Step 2, you created the getRecommendationResult to store the information that your skill will return. In this section, you'll create the getRecommendation API definition.

  1. Click API definitions on the left navbar.

  2. Click on Add API Definition.

  3. Enter getRecommendation into the API Name field at the top of the page.

Create API

Find the arguments section. This section allows you to specify the slots to pass the API as arguments. You can specify whether or not each slot value is required. By default all arguments are required.

  1. Click add argument.

  2. Enter size into the name field.

  3. Next, select size from the Type dropdown.

Repeat these steps to add temperament and energy as required arguments for your API. You can check your work against the screenshot below!

Once you've defined your arguments, you need to specify what the API (your skill code) will return.

  1. Under the Return slot type section, Select getRecommendationResult from the drop-down.
Build API Definition
  1. Click Save.

Step 4: Add responses

In order to make your skill speak, you need to define a response. Your skill greets, provides help, asks questions, makes recommendations and says goodbye. In the previous lab, you created the greeting response. You now need to create responses to ask questions and give a recommendation.

Start by creating responses that request information from your customer. Since the getRecommedation API definition needs three slots in order to make a recommendation, we will need to create three responses, one for each slot:

  • temperament
  • size
  • energy

4.1 Define 'Request' Responses

  1. Click on responses on the left nav bar to get to the response template builder.

  2. Click on Add Response.

At the top of the page you will see: "responses / __"

The part that comes after the / is where you'll enter the name of the response template.

  1. Name your template request_temperament.
Create request response

The input section allows you to identify slots whose value(s) you want to be able to use in your response. Skip over it for now and continue down to the Output section. You'll come back to this in a bit.

  1. In the audio response section click on the dropdown and select create a new prompt.

This will let you specify the text you want Alexa to speak to the customer.

  1. Enter the name "request_temperament" into the Audio Response name field.

  2. Click on Add Prompt.

  3. Enter "Would you like a family dog or a guard dog?" in the Alexa Prompts box.

  4. Click on save once finished.

Save

Just as you did in the previous lab, you will add some additional variations to the template. Code samples are provided for expediency, but feel free to experiment adding your own!

  1. Click Save Model and open APL for Audio editor for for advanced updates to request_temperament. Update the APLA block to match the code segment below to add "I can filter for a family dog or a guard dog. Which do you prefer?" as a variation.
{
    "type": "APLA",
    "version": "0.8",
    "mainTemplate": {
        "parameters": [
            "payload"
        ],
        "item": {
            "type": "Selector",
            "strategy": "randomItem",
            "description": "Change 'type' above to try different Selector Component Types like Sequencer",
            "items": [
                {
                    "type": "Speech",
                    "contentType": "text",
                    "content": "Would you like a family dog or a guard dog?",
                    "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' <amazon:effect name=\"whispered\">like that</amazon:effect>"
                },
                {
                    "type": "Speech",
                    "contentType": "text",
                    "content": "I can filter for a family dog or a guard dog. Which do you prefer?",
                    "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' <amazon:effect name=\"whispered\">like that</amazon:effect>"
                }                
            ]
        }
    }
}
Request Temperament
  1. Click on the floppy disk icon to save.
Apl Save
  1. Switch tabs back to the Alexa Developer Console.

You've now finished this response!

  1. Click save in the top navbar to save your work. Then, click on responses on the left nav bar to return to the responses page.
Save
  1. Repeat these steps to create a request_energy and request_size template.

For the request_energy response have Alexa choose randomly from:

  • "Would you prefer a high energy dog or a low energy dog?"
  • "Do your friends describe you as high energy or low energy?"
Request energy response template

For the request_size response have Alexa choose randomly from:

  • "Do you prefer tiny, small, medium, or large dogs?"
  • "Would you like a tiny, small, medium, or large dog?"
  • "Are you interested in tiny, small, medium, or large dogs?"
Request size response template

4.2 Define Notify Success Response

As previously mentioned, Alexa Conversations sends a JSON request of type Dialog.API.Invoked to your skill's endpoint. Your skill code inspects it, does some work, and returns a JSON response. Alexa Conversations receives the response and determines which response to use. How does it know? We need to tell it. Since the request was successful, Alexa Conversations will look for a template that can provide the user with the results of a successful API request.

To define your notify_success response that will share info from your API return object you'll follow the following steps.

  1. Click on add response.

  2. Name this template notifySuccess_getRecommendation and scroll to the agruments section.

Because this template provides the recommendation to your customer, it needs to know the result of getRecommendation. To do that, you need to have Alexa Conversations pass the getRecommendationResult slot to your template.

  1. click Add Argument and name it getRecommendationResult.

  2. From the slot type dropdown, select getRecommendationResult.

Define success response

With the argument out of the way now you need to define the Audio Response.

  1. Create a new prompt using the Audio Response drop-down

  2. Enter "notifySuccess_getRecommendation" into the Prompt Name field and paste the text below into the Alexa Prompts field:

I recommend a ${getRecommendationResult.name}.

Create sucess audio response

Take a moment to understand the string you pasted into the textfield.

There's definitely something interesting going on here. Instead of hardcoding the name of the dog breed into the string, you used a special syntax to create a template.At run-time Alexa Conversations will replace whatever appears between ${} with the value it represents.

Remember that custom slot types with properties are hierarchical, you can use dot-notation to trace through the structured data to access the value of a specific field. Take a look at the object below:

"getRecommendationResult": {
    "name": "American Eskimo"
}

To access the value of name (American Eskimo), you can connect getRecommendationResult to name using a '.' to arrive at the following notation: getRecommendationResult.name

You haven't created an utterance set yet so skip adding variations for now.

  1. Click save.
Save

In a later step you will link the API response you just created to the getRecommendation API. Next you will need to create utterance sets.

Step 5: Add Utterance sets

The last piece you need before you can annotate your dialogs are utterance sets. They are a collection of unique utterance variations your customer might say that deviate from your happy path. Although Alexa Conversations automatically predicts how your customer may deviate from your happy path, utterance sets allow you to directly influence what Alexa Conversations adds to your model.

For example, one utterance set will represent a set of utterances the Customer might say to request a dog recommendation that includes all three slots you need to call the API. Utterance sets that belong to a group must include the same slots. Therefore, you need to define utterance sets for the following cases:

  • Customer requests a dog and provides a size, temperament, and energy.
  • Customer requests a dog and provides size only.
  • Customer requests a dog and provides energy only.
  • Customer requests a dog and provides temperament only.
  • Customer requests a dog and provides size and energy only.
  • Customer requests a dog and provides size and temperament only.
  • Customer requests a dog and provides energy and temperament only.

This type of utterance set where a customer is starting an interaction where the goal is to invoke a certain API (AKA perform a certain action supported by our skill) is an invoke utterance set.

If the customer doesn't provide all the necessary slots in one turn (underfilling), Alexa Conversations will ask follow-up questions until all the necessary slots have been collected. If the customer gives more information (overfilling) Alexa Conversations will skip asking for slots that have already been provided. These utterance sets inform Alexa Conversations about the arguments that need to be passed to an API. This will be the following:

1) User informs Alexa of size 2) User informs Alexa of temperament 3) User informs Alexa of energy

The final type of Utterance Set are affirm and deny Utterance Sets. These groups capture ways your customer might say yes or no when Alexa asks confirmation before calling an API. Pet Match won't be asking for confirmation, so you don't need to include these, but we encourage you to try it out after you' completed this lab.

Now it's time to define these utterance sets.

  1. Click on the Utterance Sets tab in the left navbar.

  2. Click on Add Utterance Set.

  3. Enter invoke_getRecommendation_temperament as the name.

This utterance group will cover utterances to request a dog recommendation where the customer fills just the temperament slot.

Create utterance set
  1. Under slots, click add slots.

  2. Use temperament as the name.

  3. Select temperament from the type dropdown.

You've added the temperament slot to this Utterance Set. All sample utterances in this set need to contain the temperament slot as a variable.

Keep going to see what that looks like.

  1. Click on the Add Utterance button.

  2. In the Sample Utterances field, enter I want a {temperament} dog

Just like the response template you're using a string template again. In this case, you are identifying the slot values that our customer will speak and where they belong in the utterance.

Next, you need to specify what kind of response this is. Remember the three groups of responses? They correspond with four dialog acts: invoke, inform, affirm, and deny.

  1. Under Dialog Act, select the Invoke APIs from the dropdown menu.

This will mark our template as an invoke template.

Invoke Get Recommendation Temperament
  1. When you've finished, click the save button.
Save

Next, let's add an inform set.

  1. Click on the Utterance Sets tab in the left navbar.

  2. Click on Add Utterance Set.

  3. Use inform_getRecommendation_size as the name.

  4. Under slots, add a slot named size with type size.

  5. In the Sample Utterances field, enter {size} and click on the + icon.

Now we need to tell Alexa Conversations what to do when the customer speaks these words. For example, when our customer tells us that they'd like a large dog, they are providing one of three slots that our skill code needs in order to make a recommendation. Therefore, they are informing slot (or slots) to an API. In this case they are informing the size slot.

  1. In the Dialog Act dropdown, select Inform Args.
Inform GR size
  1. Click the save button.

That's all there is to creating Utterance Sets! Now that you understand how to manually create them, go ahead and create the following utterance sets using the same steps on your own:

invoke_getRecommendation_temperament(You already did this one)

Slots: "temperament": "temperament"

Utterance(s): "I want a ${temperament} dog."

Dialog Act: "invoke"
invoke_getRecommendation_energy

Slots: "energy": "energy"

Utterance(s): "I want a ${energy} dog."

Dialog Act: "invoke"
invoke_getRecommendation_size

Slots: "size": "size"

Utterance(s): "I want a ${size} dog."

Dialog Act: "invoke"
invoke_getRecommendation_size_energy

Slots: "size": "size", "energy": "energy"

Utterances: "I want a ${size} ${energy} dog.", "I want a ${energy} ${size} dog."

Dialog Act: "invoke"
invoke_getRecommendation_size_temperament

Slots: "size": "size", "temperament": "temperament"

Utterances: "I want a ${size} ${temperament} dog.", "I want a ${temperament} ${size} dog."

Dialog Act: "invoke"
invoke_getRecommendation_energy_temperament

Slots: "energy": "energy", "temperament": "temperament"

Utterances: "I want a ${energy} ${temperament} dog.", "I want a ${temperament} ${energy} dog."

Dialog Act: "invoke"
invoke_getRecommendation_size_temperament_energy

Slots: "energy": "energy", "temperament": "temperament", "size":"size"

Utterances:
"I want a ${size} ${temperament} ${energy} dog.",
"I want a ${size} ${energy} ${temperament} dog.",
"I want a ${energy} ${temperament} ${size} dog.",
"I want a ${energy} ${size} ${temperament} dog.",
"I want a ${temperament} ${size} ${energy} dog.",
"I want a ${energy} ${size} ${temperament} dog."

Dialog Act: "invoke"
inform_getRecommendation_size(You already did this one)

Slots: "size": "size"

Utterances: "${size}."

Dialog Act: "inform"
inform_getRecommendation_temperament

Slots: "temperament": "temperament"

Utterances: "${temperament}."

Dialog Act: "inform"
inform_getRecommendation_energy

Slots: "energy": "energy"

Utterances: "${energy}."

Dialog Act: "inform"
  1. Once you've finished, click save.

You've now created all the Utterance Sets you will need for your skill! We now have utterance groups for annotating all variations of user input into your skill, requesting any information you might be missing to call your API, and handling yes/no confirmation from your user before we call the API. Equipped with these inputs, you can now return to annotating your sample dialogs.

Step 6a: Annotate

It's time to tie everything together! You defined the assets you need to return to your example dialogs and annotate them. These annotated dialogs will be converted into a large dataset for training a conversational model just for your skill.

  1. Click on Dialogs to return to the dialog editor.

  2. Click on the edit button near dialog0 to begin editing.

Take a look at the first line of the dialog: "I want a large family dog."

Ask yourself, "Are there any slots in this line?"

YES! large (size) and family (temperament)

This means you need mark them.

  1. Highlight the word "large".

A popup will appear allowing you choose a slot type.

Since "large" describes the size of the dog. You need to choose size.

  1. Under the slot type drop-down, choose size.

The variable name "size0" will automatically into the adjacent box. This will allow you to refer to the collected value throughout the rest of the dialog.

  1. Click away to make the popup disappear. At the top of the page you can see that size has been annotated as a slot type.
Annotate Slot
  1. Repeat the same steps for the word "family" and select temperament as the slot type.

When you're finished, it should look like this:

Step6a-e

You have annotated all the slots in the initial turn, but you're not finished yet. This is indicated by the red ! displayed at the end of the line.

Error Icon
  1. Click on the first USER: line.

The User Input panel will appear to the right. Since this a user utterance, you need to associate it with a dialog act and utterance set.

This line of dialog is an attempt at invoking the getRecommendation API, but the customer only provided two out of three slots. So the dialog act is Invoke APIs.

  1. Select Invoke APIs from the Dialog Acts drop-down

  2. Select invoke_getRecommendation_size_temperament from the utterance set drop-down.

This tells Alexa conversations that this user utterance is asking Alexa to invoke the getRecommendation API and that the line of dialog includes the size and temperament slots.

The slots in this utterance set, represent the values our customer provided. Alexa Conversations enables you to map the slot to a variable so you can refer to it later. Defining a variable enables you to flag a specific value for use at specific time. In this case, you're going to flag the size, energy, and template values and tell Alexa Conversations to pass them to your getRecommendation API.

  1. Under Slot → Variable, select size0 from the drop-down for size.

  2. Select temperament0 from the drop-down for temperament.

Upon doing so, the ! will turn into a green checkmark.

Select Dialog Act

Now that you've completed annotating what your customer said, it's now time to annotate how Alexa responds.

  1. Click on the first ALEXA: utterance, "Do you prefer low, medium, or high energy dogs?"

The Alexa Response panel will appear on the right-hand side of the screen.

Since this is one of Alexa's lines you don't need to mark slot values. You only need to configure the dialog act, API and response.

At this point you don't have all the information needed to give a recommendation so you can't select one yet. You need the energy slot so you'll need to have Pet Match ask for it. To do that have Alexa Conversations use the request_energy template.

  1. Under Dialog Act, click on the drop-down and select Request Args.

A new dropdown API to Request appears.

  1. Select getRecommendation from the new dropdown.

The API Arguments to Request and Response fields will appear. The UI has automatically populated the API Arguments to Request will all three arguments but on the previous line, the customer provided the size and temperament, so you only need to request the energy.

  1. Click the 'X" to delete size and temperament from the API Arguments to Request.

Now you need to choose the response.

  1. Select the request_energy response from the response drop-down.

Keep moving to the next turn of the conversation, starting with the response "Low."

Since "Low." is a user utterance, you need to check for slots and assign an utterance set.

  1. Highlight "Low" and mark it as energy slot in the popup just like you did before.

    substep 1. User Input > dialog Act - Purpose of user input > select "Inform Args"

  1. Using the Utterance set drop-down, assign this utterance the inform_getRecommendation_energy utterance set.

You want to use the inform utterance because this is a case where the customer is providing Alexa Conversations with additional information in order to complete the action invoked in the previous turn: calling the getRecommendation API.

  1. Click on the final utterance in the dialog.

This utterance is an example of the notifySuccess_getRecommendation response, and it builds its response the getRecommendationResult.

This template response is informing the customer of a successful API call. Therefore, you need to select the API Success dialog act.

  1. From the Alexa Response panel, choose API Success from the Dialog Act drop-down.

Next, you'll tell Alexa Conversations what API to invoke.

  1. Click on the + next to API to Invoke.

The Select an API Definition drop-down appears.

  1. Select getRecommendation from the API drop-down.

Now you need to map the variables to the API arguments. Remember how you specified the slot value for size to a variable called size0. You're now going to tell Alexa Conversations to pass that variable as an argument to the getRecommendation API.

  1. Click on > to the left of drop-down menu.

The Variable → Arguments UI will appear.

Step6a-w
  1. For each of the drop-downs that appear, map the argument to its corresponding variable.
    • size0 → size
    • temperament0 → temperament
    • energy0 → energy

You don't need to modify the return type → variable drop-down, since it is correctly set to getRecommendationResult0.

Last, you'll tell Alexa Conversations which response to use.

  1. Click on the response drop-down, choose notifySuccess_getRecommendation, and select your return value getRecommendationResult0 from the Variable → Arguments drop-down.
Annotate  Dialog
  1. Click Save.
Save Model

Step 6b: Finish annotating dialog 1-4

You've fully annotated your first dialog! Now it's your turn to practice annotating dialogs. For dialogs one through four, use what you've learned to annotate them. You can use our screenshots for reference below if you get stuck or to check your work! Remember to save after annotating each one!

Dialog 0

Annotate Dialog

Dialog 1

Annotate Dialog

Dialog 2

Annotate Dialog

Dialog 3

Annotate Dialog

Dialog 4

Annotate Dialog
  1. When you've finished, click save.

Your model is now fully annotated! The last step is now to build your model.

  1. Click build model.
Build Model

This can take up to fifteen minutes. In order to handle requests from Alexa Conversations, you need a back-end. When you created the skill and chose Alexa Hosted, a back-end was created for you. All you have to do is define the code to handle the request for a dog recommendation.

Step 7: Fulfill getRecommendation API requests with your back-end

At run-time when Alexa Conversations has collected the size, energy and temperament slots, it will bundle them up into a JSON request and send it to your skill code. It will inspect the request and perform the business logic to fulfill the request.

If you've built an intent and utterance based Alexa skill, you should be familiar with IntentRequests. They are invoked when your customer speaks an utterance that's mapped to the intent. Let's say you had an intent called PetMatchIntent. When your customer says, "I want a large dog." your skill will receive an IntentRequest for PetMatchIntent. To fulfill the request using the ASK SDK, you define a handler function that handles intent requests called PetMatchIntent.

Alexa Conversations introduces a new type of request. API.Dialog.Invoked. It contains an apiRequest property that includes the name of the API definition and the arguments you defined in your model. You named your API getRecommendation, so you handler will need to handle API.DialogInvoked requests for getRecommendation.

Your handler will receive the size, energy and temperament slot, look up what kind of dog to recommend and return a JSON response that corresponds to the return slot you defined in your model. Your getRecommendation API returns a getRecommendationResult slot.

Now that you understand what to do at a high-level, it's time to start building.

You'll need to access the Code tab.

  1. Click on Code
Code Tab

Looking at the left hand side of the screen, You can see that there are three files under a folder called 'lambda', including a file called index.js. This is the file you'll use to write your code. You will also need another file to serve as a database of dog types. Create that file first.

  1. Click on the new file button in the top left to create a new file.

  2. Name the file PetMatch.json.

  3. Copy the text from this file.

  4. Click Save to save your changes.

PetMatch.json will act as your database. It contains various attributes about dog breeds mapped to a key. The key is based up the slot values you defined in your model, energy, size and temperament. So if your customer asked for a large, high energy, family dog, the key would be high-large-family.

Your skill code will need to construct that key and look up the recommendation that was mapped to it. Take a look below to see what was mapped to high-large-family.

"high-large-family": {
    "size": "Large",
    "energy": "High",
    "SSET": "high-large-family",
    "temperament": "Family",
    "description": "...",
    "breed": "Weimaraner"
},

In this case, the recommended dog breed would be a Weimaraner.

The key is based on a unique combination of values for energy, size, and temperament. The values you defined for each slot are:

  • energy: Low, Medium, High
  • size: Small, Medium, Large
  • temperament: Guard, Family

There are three slots, two of them have three possible values and one has two. Therefore, there are eighteen permutations. There are eighteen key-value pairs in the PetMatch.json file. What if someone asks for a giant dog? Alexa Conversations supports Entity Resolution, so you can map synonyms to slot values. When you build your size slot you did just that. When a customer says giant you'll get both the spoken value and the resolved value so you can use that to build your lookup key. Below you'll create a function called resolveEntity to that.

Now that you understand your data, it's time to write the code that will use it to provide a recommendation.

  1. Double click on index.js to open the file.

The index.js file contains all of your business logic.

The first thing you'll need to do is import your data stored in PetMatch.json into your skill code.

  1. Locate the line that says const Alexa = require('ask-sdk-core'); and on the next line add:
const data = require('./PetMatch.json');

As-is the index.js contains some basic building blocks but no business logic to support your getRecommendation API. You need to create a function to handle the request. Since you're using the ASK SDK, you'll create a handler. There are two parts to a handler:

  • canHandle() function
  • handle() function

The canHandle() function is where you define what requests the handler responds to. The handle() function contains the logic of the action you wish to preform to fulfill the request.

Since your handler will handle getRecommendation API requests, name the it, GetRecommendationAPIHandler.

  1. Below the line you just added, copy and paste the following block code:
const GetRecommendationAPIHandler = {
    canHandle(handlerInput) {
    },
    handle(handlerInput) {
    }
};

Your code will now look like:

const Alexa = require('ask-sdk-core');
const data = require('./PetMatch.json');

const GetRecommendationAPIHandler = {
    canHandle(handlerInput) {
    },
    handle(handlerInput) {
    }
};

Now that you have a framework to start from, you need to indicate when this handler will execute, so start with the canHandle function.

GetRecommendationAPIHandler will handle Dialog.API.Invoked requests for the getRecommendation, so the canHandle function will return true when request.type is Dialog.API.Invoked and .request.apiRequest.name is getRecommendation

  1. Update your canHandle function with the following:
return Alexa.getRequestType(handlerInput.requestEnvelope) === 'Dialog.API.Invoked'
    && handlerInput.requestEnvelope.request.apiRequest.name === 'getRecommendation';

Now that your handler can indicate which incoming requests it can handle, you need define how it should handle the request. Given the set of slots size, energy and temperament it needs to return the recommendation as a JSON response.

  1. To do this, update your handle function with the following:
const apiRequest = handlerInput.requestEnvelope.request.apiRequest;

let energy = resolveEntity(apiRequest.slots, "energy");
let size = resolveEntity(apiRequest.slots, "size");
let temperament = resolveEntity(apiRequest.slots, "temperament");

const recommendationEntity = {};
if (energy !== null && size !== null && temperament !== null) {
    const key = `${energy}-${size}-${temperament}`;
    const databaseResponse = data[key];

    console.log("Response from mock database ", databaseResponse);

    recommendationEntity.name = databaseResponse.breed;
    recommendationEntity.size = size
    recommendationEntity.energy = energy
    recommendationEntity.temperament = temperament;
}

const response = buildSuccessApiResponse(recommendationEntity);
return response;

The first line of code captures the apiRequest. The next three lines of code use resolveEntity to map the spoken value into the resolved value that way if your customer said giant your skill will use large to make the lookup key, since high-giant-family won't return a result. Once the key has been contructed the code looks up the recommendation and builds an object called responseEntity. Its properties correspond to the recommendationResult you defined in your model. It contains the recommended breed and size, energy and temperament.

When Alexa conversations receives the response, it will figure out what template to use and insert the data your skill code returned to say, "So a large high energy family dog sounds good for you. Consider a Weimaraner."

The last two lines of code builds and returns the response to Alexa Conversations.

const GetRecommendationAPIHandler = {

    canHandle(handlerInput) {
        return Alexa.getRequestType(handlerInput.requestEnvelope) === 'Dialog.API.Invoked'
            && handlerInput.requestEnvelope.request.apiRequest.name === 'getRecommendation';
    },
    handle(handlerInput) {
        const apiRequest = handlerInput.requestEnvelope.request.apiRequest;

        let energy = resolveEntity(apiRequest.slots, "energy");
        let size = resolveEntity(apiRequest.slots, "size");
        let temperament = resolveEntity(apiRequest.slots, "temperament");

        const recommendationEntity = {};
        if (energy !== null && size !== null && temperament !== null) {
            const key = `${energy}-${size}-${temperament}`;
            const databaseResponse = data[key];

            console.log("Response from mock database ", databaseResponse);

            recommendationEntity.name = databaseResponse.breed;
            recommendationEntity.size = apiRequest.arguments.size
            recommendationEntity.energy = apiRequest.arguments.energy
            recommendationEntity.temperament = apiRequest.arguments.temperament;
        }

        const response = buildSuccessApiResponse(recommendationEntity);
        console.log('GetRecommendationAPIHandler', JSON.stringify(response));

        return response;
    }
};

With the handler out of the way, you still need to define:

resolveEntity - resolves the slot value using Entity Resolution. For example, giant will map to large.

buildSuccessApiResponse - builds a the response in the format Alexa Conversations understands.

  1. Paste the following code below GetRecommendationAPIHandler
// *****************************************************************************
// Resolves slot value using Entity Resolution
const resolveEntity = function(resolvedEntity, slot) {

    //This is built in functionality with SDK Using Alexa's ER
    let erAuthorityResolution = resolvedEntity[slot].resolutions
        .resolutionsPerAuthority[0];
    let value = null;

    if (erAuthorityResolution.status.code === 'ER_SUCCESS_MATCH') {
        value = erAuthorityResolution.values[0].value.name;
    }

    return value;
};

const buildSuccessApiResponse = (returnEntity) => {
    return { apiResponse: returnEntity };
};

Great! You now have added all of the functions you need to support your first API definition. There is still one final change you need to make. You need to register GetRecommendationAPIHandler with the SDK otherwise your handler will never execute even if the income request is a Dialog.API.Invoked request for the getRecommendation API.

  1. Scroll the bottom of the file and look for .addRequestHandlers

  2. Add a new line and paste GetRecommendationAPIHandler, onto the new line.

exports.handler = skillBuilder
    .addRequestInterceptors(RequestInterceptor)
    .addRequestHandlers(
        GetRecommendationAPIHandler,
        SessionEndedRequestHandler
    )
    .addResponseInterceptors(ResponseInterceptor)
    .addErrorHandlers(ErrorHandler)
    .lambda();

This will ensure our GetRecommendationAPIHandler has a chance to handle the inbound request.

With that you're done! You can now head back and test your skill to see if everything is working. Remember to "Save" and "Deploy" before testing.

Step 8: Test Your Skill

The moment you've been waiting for has finally come! It's time to test your skill.

  1. Click the Test tab.

The test simulator will open.

  1. From the drop-down menu on the left of the page, select Development.

Testing Console

Test Tab

It's time to invoke the skill.

  1. Type open pet match into the box at the top left and press ENTER.

The skill should respond with your welcome template.

Now that the skill is open, try out the sample dialogs for example:

Sample Dialogs

U: I want a large family dog.

A: Do you want a high-energy or low-energy dog?

U: Low.

Did Pet Match recommend a great pyrenees? If so, it's working!

Spend some time experimenting with the skill. Choose different parameters and test out other dialogs.

Wrap-up

You have built out the core of the skill, but there's lots more to do. To continue adding more functionality, move on to the next lab

Code

If your skill isn't working or you're getting some kind of syntax error, download the code sample in Node.js from the link below. Then, go to the Code tab in the Alexa developer console and copy and paste the code into the index.js file.

Be sure to save and deploy the code before testing it.

Node.js Github Code Sample


Was this page helpful?