Lab 3: Create a Skill by using ACDL in Alexa Conversations
Welcome to lab 3 of our introductory course on building an engaging Alexa Conversations skill by using ACDL. In this lab, we'll learn how to create a skill called "Flight Search" with step-by-step instructions.
Note: This skill is an example only and is not intended to refer to actual airlines or airline data.
Time required: 60 minutes
What you'll learn
ACDL artifacts
Changing invocation name
How to add audio response templates
How to add types
How to add APIs
How to add utterance sets
How to add dialogs
How to create your skill backend code
ACDL artifacts
There are four key ACDL artifacts: Types, Actions, Events and Dialogs. The first three (Types, Actions, Events) are dependencies for dialogs.
Types are equivalent to data type representations in any programming language. They serve a variety of functions for skill building and define the data structures for request and response payloads, slot values, etc.
Events are equivalent to utterance groups in the developer console. Each event is linked to a type which defines the slot inputs a user may provide within those utterances.
Actions are always triggered by events. Actions define which back-end APIs are invoked on a given turn and define how to respond events within the context of an ongoing dialog.
Dialogs pull together all the other ACDL assets to create templatized sample interactions that form the basis of your experience.
Step-by-Step: Build Flight Search Skill
Step 1: Changing invocation name
Let's change the skill invocation name. Skill invocation name is found under skill-package/interactionModels/custom/en-US.json. You will see the current invocation name is "change me", so let's change the skill invocation name to "flight search". This invocation name will be used when customers open your skill. They can say "Alexa, open flight search".
Step 2: How to add audio response templates
Audio responses are under "response/prompts" folder. By default, we will have AlexaConversationsBye, AlexaConversationsOutOfDomain, Alexa ConversationsRequestMore, AlexaConversationsWelcome and AlexaConversationsProvideHelp response prompts. We will start by updating the welcome prompt. Let's open the document.json under AlexaConversationsWelcome folder and replace the "content" with our "flight search" welcome message.
"content":"Welcome to the flight search. I can help you find cheap flights in the main cabin. What do you want to do?"
This is the welcome message that Alexa will prompt when the skill is invoked. Your AlexaConversationsWelcome prompt will look as indicated below:
Copied to clipboard.
Now, let's add a prompt for departure city when Alexa asks the user to provide the city name.
First, create a new folder under "response/prompts" folder, and name it "RequestDepartureCityPrompt"
Create a new "document.json" file under that "RequestDepartureCityPrompt"
We will create the content of the "document.json" as follows:
Copied to clipboard.
Okay, it's easy, right? This prompt might look a bit different from the previous one. The reason is that we have two prompts (see under "items") from which Alexa will randomly pick.
Let's create the remaining response templates for arrival, date, confirmation and final response prompts by following the same steps.
"RequestArrivalCityPrompt":
Copied to clipboard.
"RequestDatePrompt"
Copied to clipboard.
"FlightSearchConfirmPrompt"
Copied to clipboard.
Note: At runtime, Alexa Conversations will replace whatever appears between ${} with the value it represents.
"FlightSearchResponsePrompt"
Copied to clipboard.
Note: We will define flightResponse as a custom slot type with properties to represent the data that our API will return.
Your response folder should look as follows:
Once we created the response templates, now we are ready to create "types" in ACDL.
Step 3: How to add types
Types define data structures which are declared with the keyword “type”. In the Flight Search skill, we will need to collect departure city, arrival city, and the date from customers. Therefore, we will create a type to collect these three built-in slots. As a response, we will return date, time, airline, and the cost for the given cities. We will create a custom slot type for the airlines.
"FlightDetails" type, which we will create later, will contain arrivalCity, departureCity, date, time, airline, and cost. We will also create a "FlightDetailsPayload" type for the payload which will have a child referral to "FlightDetails".
Let's open the en-US.json file under skill-package/interactionModels/custom folder.
We will add a new custom type called "Airline" in "types" object as follows:
Copied to clipboard.
Your json file should look as noted below:
Copied to clipboard.
Now we are going to change the name of the ACDL file (skill-package/conversations/empty.acdl) to "flightSearch.acdl".
Let's open the "flightSearch.acdl" and change the namespace to "com.flightsearch".
We will import conversations, custom slot type and built-in types to the ACDL file:
Copied to clipboard.
Create an input type for the skill to collect departureCity, arrivalCity and date
Copied to clipboard.
We create a type "FlightSearchDetails" with three optional slots, so customers can provide any permutations of these three slots or they might provide none of them.
Create an output type for the skill to return the flight details
Copied to clipboard.
Create a payload for the output
Copied to clipboard.
Here is the ACDL file that we created so far:
Copied to clipboard.
Step 4: How to add APIs
We are still working on our "flightsearch.acdl" file, and now, we will create an action which will invoke a back-end API and return flight details to us. Our backend API will be named "FlightFinder". The below code is our API FlightFinder which requires date, arrival city and departure city. It will return the FlightDetails type object we created in step 3. Copy the below code under the FlightDetailsPayload type.
Copied to clipboard.
This is the declaration of our action which we will use in the dialog.
ReturnType → FlightDetails
action_name → FlightFinder
Type arg1 → Date date
Type arg2 → US_CITY arrivalCity
Type arg3 → US_CITY departureCity
"flightsearch.acdl" file should look as noted below:
Copied to clipboard.
Step 5: How to add utterance sets
The last piece you need before you can start working on 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 flight search that includes all three slots you need to call the API. Utterance sets that belong to a group must include the same slots. Since we created an input with 3 optional slots, we can create one utterance set for the following cases:
Customer requests a flight search
Customer requests a flight search and provides departure city, arrival city and date
Customer requests a flight search and provides departure city, arrival city
Customer requests a flight search and provides departure city, date
Customer requests a flight search and provides arrival city, date
Customer requests a flight search and provides departure city
Customer requests a flight search and provides arrival city
Customer requests a flight search and provides date
In ACDL, the given utterances represent variations of the utterances that trigger the event and returns an utterance event.
Let's create an utterance set in our "flightsearch.acdl" file which covers the cases we defined above, you will start adding the utterances to the under the action we created in previous step:
Copied to clipboard.
Note: Expressions without the @locale annotation are global. In other words, the expressions apply to all locales. You can learn more about locales here.
Let's also create "Affirm" utterance set for the customer:
Copied to clipboard.
We use the type "Nothing" for affirm utterance group, so we need to import it to the ACDL. Add the following code to import Nothing. You should add this code to the section where you previously created imports (top of your acdl code):
Copied to clipboard.
You are doing great, almost done! Here you can find a snapshot of your ACDL code to compare what you created so far:
Copied to clipboard.
Step 6: How to add dialogs
So far, we learned how to create responses, utterence sets, types, and APIs. We have all skill assets required for starting to write our dialog samples.
We will use response templates that we created earlier, but first we need to import them. We will add this import statement above the first type definition in our "flightsearch.acdl" file.
Copied to clipboard.
Let's change the dialog name to "FlightSearch" and add locale annotation.
Copied to clipboard.
Now, we can create our dialog sample. Our dialog will expect the invocation from customers which can contain any permutations of the three slots, or none of them.
We created a dialog path for the slot collection through invocation from customers. However, what if customers don't provide all three slots in the invocation? We require all three slots for our API call to find the cheapest flight. Therefore, we will use "ensure" action here, which will make sure that all three slots are collected from customers before moving forward in the dialog flow. "Ensure" action helps to create dialog variations by using request args for the missing slots.
Once customers provide all three slots, we would like to confirm that all slots are collected correctly. To do that, we will use "ConfirmAction".
In our dialog, we expect customers to either "affirm" or "deny" the collected slots. As a developer, you can define the deny paths along with the affirm paths in your dialog samples, however, Alexa Conversations will also create the deny paths for the simulation out-of-the-box if you don't create the deny paths. In this example, we will just create the affirm path and let Alexa Conversation handle the deny path.
Once the customer has confirmed all slots, we can call the "FlightFinder" API and assign results to the variable (flightResult) we just created.
Now, we can create the response prompt in Alexa based on the API response.
Here is the dialog we put together so far:
Copied to clipboard.
We finished making the changes in our ACDL file, so let's compile our changes.
You can compare your flightsearch.acdl file with the following snapshot:
Copied to clipboard.
To compile the skill artifacts, you need to open the terminal and navigate to your flight search skill main directory (we created a folder called "FlightSearch"). Then, enter the following command:
Copied to clipboard.
Step 7: How to create your skill backend code
We completed our skill artifacts and compiled our skill. Now let's work on our backend logic. We will create a lambda handler to handle our API call and we will create a simple database which contains the flight information for the search. Let's start!
Open the "lambda" folder in your flightsearch directory. We will start by creating the "package.json" file. Copy the below code to the created "package.json".
Copied to clipboard.
We will create a simple database in the lambda directory which has flight information for some cities. Create a file called "flight-data.json" and copy the below code. To keep it simple, we will only search for departure and arrival city without actual dates.
Copied to clipboard.
Let's create a flightSearch.js file in lambda folder for a simple search function to query our flight-data.json database.
Copied to clipboard.
Now, let's work on utility functions that we will use in our beckend; create a "util.js" file in lambda folder to keep common functions that we will use in the backend. Copy the below code to the "util.js":
Copied to clipboard.
We are ready to create our lambda handler now. In our lambda handler, we will have our API handler for flight search, session ended request handler and error handler. Let's create a file called "index.js" and copy the below code.
Copied to clipboard.
You are ready to deploy your skill now! You can run the following command in your skill directory to start the deployment process. It will take around 20-30 mins.
Copied to clipboard.
Note: If you created a new profile, you should run askx deploy -p tutorial ("tutorial" is an example profile, replace it with your profile name).
Note: Each time when you run askx deploy you will receive the following default ACDL message: "Skills with ACDL are not yet compatible with the https://developer.amazon.com, hence this skill will be disabled on the Developer Console. Would you like to proceed?". You should enter "y" (Yes) in order to continue on to deployment.
Step 8: Test your skill
Once the deployment is completed, you are ready to test your skill! You have two options to test:
You can use your echo devices that are linked to your account and invoke your skill by saying "Alexa, open flight search"
You can test your skill in developer console. If you prefer this option: