How to create your first ALEXA skill using python ?

  • A great voice experience allows for the many ways people express meaning and intent. It is rich and flexible. Because of this, building for voice isn’t the same as building graphical user interfaces (GUIs) for the web or mobile.
  • The easier a skill is to use, the more speed and efficiency it offers.

Speed and efficiency

  • Alexa skills bring speed and efficiency to habitual tasks — which is why voice is poised to become ubiquitous.
  • Consider your room’s A/C. With Alexa, turning an A/C on is as easy as saying, “Alexa, turn on A/C.” Who would have guessed pushing a few buttons on the remote would become the less convenient option?
  • Alexa hears the wake word and listens.
  • The Alexa service uses the interaction model to figure where to route the request.
  • A JSON request is sent to the skill’s lambda function.
  • The lambda function inspects the JSON request.
  • The lambda function determines how to respond.
  • The lambda function sends a JSON response to the Alexa service.
  • The Alexa service receives the JSON response and converts the output text to an audio file.
  • The Alexa-enabled device receives and plays the audio.
  1. Create different Slots and Utterances as you needed.
  2. Write an appropriate code in the code section.
  3. Finally test your code and publish your skills.
  1. Kindly complete your procedure of signing up for AWS free tier account.
  2. You must have some basic knowledge of Programming languages like C,C++,Java,Python,Node.js,etc. whichever you are comfortable with.
  3. Optionally, you can have the Alexa devices like Amazon Echo, Echo Dot, etc. OR you can use the Alexa inbuilt simulator on Alexa Developer console to test your skills.
  1. In choose a model to add to your skill select ‘custom’.

Invocation name is the name that will enable alexa skill when you will say that word.

First, let’s setup the invocation name in our interaction model:

  • Enter “Sales Data” in the Skill Invocation Name:

Note: Built-in intents have built-in utterances. It is possible to extend the number of existing utterances by adding new utterances. When a skill is created, four built-in intents are added to the Interaction model by default. These are: AMAZON.HelpIntent, AMAZON.CancelIntent, AMAZON.FallbackIntent and AMAZON.StopIntent.

  • Here in this skill we will need StatusIntent, which will ask user some data from where it should fetch the data. So create a new intent names SttusIntent.
  • Under the statusIntent we will create different slots for ease of access and for the Alexa for fetching/storing the data.

Note: Slots are a very powerful accessory for building a custom Alexa skill. For example, the statement “Tell me about {player}” means that the user can ask our skill about any chess player from the slot player. Furthermore, multiple slots provide the possibility of using dialogs in which the Alexa skill prompts the user to fill all slot values in order to fulfill the intent.

  • Click on the intents tab and create a new intents and name it as “HelloWorldIntent” and then on going into the HelloWorldIntent you’ll see the Sample Utterances in which you have to add sample’s such that this intent would be called by alexa if alexa would find similar words.
  • Now, we want alexa to prompt something when this Intent has been invoked.
  • So, now we have to create a slot-name into the HelloWorldIntent, which is created by just writing a word in between { }(Eg. {greetings} in my case). Thus, the slot is being created.
  • You will find that word below the HelloWorldIntent.
  • Click on the slot types and then add slot type and create a custom slot and add the slot values in regarding greetings.
  • Similarly You have to create a statusIntent which will tell ask me about which data that you want to fetch, so you have to add the sample utterances such that it will invoke statusIntent if you will say similar to that statements.
  • Also you have to create different slot names like date, locationGujarat, etc. and thus you have to create slot-type respectively.

Note: While creating the slot type you can also use the inbuilt intent like AMAZON.DATE in date slot name.

  • Also you have to set slot type in the particular slot name like in the data slot you have to choose the AMAZON.DATE in the slot type under the different inents.
  • When you will turn on the slot filling at that time you’ll find two things Alexa speech prompts and User utterances. In Alexa speech prompts you have to write some sample utterances that Alexa will prompt if the respective intent is called. And in User utterances you have to write the sample utterances that the user may ask you.
  • Now you will also find the JSON editor tab in which you have created the Virtual interface above is converted to the JSON form. It will be like below mentioned:
{
"interactionModel": {
"languageModel": {
"invocationName": "sales data",
"modelConfiguration": {
"fallbackIntentSensitivity": {
"level": "LOW"
}
},
"intents": [
{
"name": "AMAZON.CancelIntent",
"samples": []
},
{
"name": "AMAZON.HelpIntent",
"samples": [
"how to use you",
"how to use ",
"kindly help",
"please help",
"please help me",
"help "
]
},
{
"name": "AMAZON.StopIntent",
"samples": [
"can you please keep quite",
"keep quite",
"can please stop",
"can please shut up",
"kindly stop",
"please stop ",
"stop "
]
},
{
"name": "HelloWorldIntent",
"slots": [
{
"name": "greeting",
"type": "Greetings",
"samples": [
"sad",
"good",
"Fine "
]
}
],
"samples": [
"{greeting}",
"hello",
"how are you",
"say hi world",
"say hi",
"hi",
"say hello world",
"say hello"
]
},
{
"name": "AMAZON.NavigateHomeIntent",
"samples": [
"HelloWorldIntent",
"StatusIntent",
"please navigate me to statusIntent"
]
},
{
"name": "AMAZON.FallbackIntent",
"samples": []
},
{
"name": "StatusIntent",
"slots": [
{
"name": "date",
"type": "AMAZON.DATE",
"samples": [
"data on {date} of {locationGujarat}",
"please provide me the data of {locationGujarat} on {date}",
"can you provide me the data of {locationGujarat} on {date}",
"day after tomorrow",
"may eleven ",
"october twenty five",
"november twenty five",
"this friday",
"this monday"
]
},
{
"name": "locationGujarat",
"type": "StoreLocationInGujarat",
"samples": [
"vadodara",
"baroda",
"gandhinagar",
"rajkot",
"surat",
"ahmedabad"
]
}
],
"samples": [
"data of {locationGujarat} on {date}",
"provide me all data of {locationGujarat} on {date}",
"tell me all data of {locationGujarat} on {date}",
"data on {date} of {locationGujarat}",
"can you please provide me the data on {date} of {locationGujarat}",
"please provide me the data of the {locationGujarat} on {date}",
"what is {date} status",
"what about {date}",
"what about work load",
"what about todays order",
"what is {date} work load",
"what work load {date}",
"what work load on {date}",
"what about work",
"what work load at {locationGujarat}"
]
}
],
"types": [
{
"name": "StoreLocationInGujarat",
"values": [
{
"name": {
"value": "Ahmedabad",
"synonyms": [
"amdavad"
]
}
},
{
"name": {
"value": "Vadodara",
"synonyms": [
"baroda"
]
}
},
{
"name": {
"value": "Surat",
"synonyms": [
"hurat"
]
}
},
{
"name": {
"value": "Rajkot",
"synonyms": [
"rojkot"
]
}
},
{
"name": {
"value": "Gandhinagar",
"synonyms": [
"gondhinagar"
]
}
}
]
},
{
"name": "Greetings",
"values": [
{
"name": {
"value": "hii"
}
},
{
"name": {
"value": "hello"
}
},
{
"name": {
"value": "alexa"
}
},
{
"name": {
"value": "good morning"
}
},
{
"name": {
"value": "good evening"
}
},
{
"name": {
"value": "good night"
}
},
{
"name": {
"value": "hey alexa"
}
}
]
}
]
},
"dialog": {
"intents": [
{
"name": "StatusIntent",
"confirmationRequired": false,
"prompts": {},
"slots": [
{
"name": "date",
"type": "AMAZON.DATE",
"confirmationRequired": false,
"elicitationRequired": true,
"prompts": {
"elicitation": "Elicit.Slot.867268475988.1435074133862"
}
},
{
"name": "locationGujarat",
"type": "StoreLocationInGujarat",
"confirmationRequired": false,
"elicitationRequired": true,
"prompts": {
"elicitation": "Elicit.Slot.867268475988.397803401305"
}
}
]
},
{
"name": "HelloWorldIntent",
"confirmationRequired": false,
"prompts": {},
"slots": [
{
"name": "greeting",
"type": "Greetings",
"confirmationRequired": false,
"elicitationRequired": true,
"prompts": {
"elicitation": "Elicit.Slot.353512166593.1518986883486"
}
}
]
}
],
"delegationStrategy": "ALWAYS"
},
"prompts": [
{
"id": "Elicit.Slot.867268475988.1544387796744",
"variations": [
{
"type": "PlainText",
"value": "can you provide me the {day} ?"
},
{
"type": "PlainText",
"value": "can you provide me the {date} ?"
},
{
"type": "PlainText",
"value": "can you provide me the location ?"
},
{
"type": "PlainText",
"value": "ya sure at which {locationGujarat} ?"
}
]
},
{
"id": "Confirm.Slot.867268475988.1544387796744",
"variations": [
{
"type": "PlainText",
"value": "ohk will provide you the details on {date} , {day} at {locationGujarat} ."
}
]
},
{
"id": "Elicit.Slot.867268475988.1435074133862",
"variations": [
{
"type": "PlainText",
"value": "ohk sure on which date ?"
},
{
"type": "PlainText",
"value": "on which date ?"
}
]
},
{
"id": "Confirm.Slot.867268475988.1435074133862",
"variations": [
{
"type": "PlainText",
"value": "ok sure will provide you the data of {locationGujarat} on {date}"
},
{
"type": "PlainText",
"value": "are you sure you want to see work at that date {date}"
}
]
},
{
"id": "Elicit.Slot.867268475988.1119428064907",
"variations": [
{
"type": "PlainText",
"value": "can you provide me the day at which you want to see work load ?"
},
{
"type": "PlainText",
"value": "please provide the day"
},
{
"type": "PlainText",
"value": "can you provide me the day ?"
}
]
},
{
"id": "Confirm.Slot.867268475988.1119428064907",
"variations": [
{
"type": "PlainText",
"value": "ohk will tell you the load on {day}"
}
]
},
{
"id": "Elicit.Slot.353512166593.1518986883486",
"variations": [
{
"type": "PlainText",
"value": "Hi, What can I help you ?"
},
{
"type": "PlainText",
"value": "Hello, How are you ?"
}
]
},
{
"id": "Elicit.Slot.867268475988.397803401305",
"variations": [
{
"type": "PlainText",
"value": "At which location ?"
},
{
"type": "PlainText",
"value": "please provide me the location ?"
},
{
"type": "PlainText",
"value": "pls give me the location ?"
},
{
"type": "PlainText",
"value": "Can you provide me the loction ?"
}
]
},
{
"id": "Confirm.Slot.867268475988.397803401305",
"variations": [
{
"type": "PlainText",
"value": "ohk sure will provide you the data on {date} at {locationGujarat} ."
}
]
},
{
"id": "Confirm.Intent.698543170008",
"variations": [
{
"type": "PlainText",
"value": "ok"
},
{
"type": "PlainText",
"value": "ohk sure will provide you the data on {date} of {locationGujarat} ."
}
]
}
]
}
}
# -*- coding: utf-8 -*-# This sample demonstrates handling intents from an Alexa skill using the Alexa Skills Kit SDK for Python.
# Please visit https://alexa.design/cookbook for additional examples on implementing slots, dialog management,
# session persistence, api calls, and more.
# This sample is built using the handler classes approach in skill builder.
import logging
import boto3
import ask_sdk_core.utils as ask_utils
from ask_sdk_core.skill_builder import SkillBuilder
from ask_sdk_core.dispatch_components import AbstractRequestHandler
from ask_sdk_core.dispatch_components import AbstractExceptionHandler
from ask_sdk_core.handler_input import HandlerInput
from ask_sdk_model import Responselogger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
class LaunchRequestHandler(AbstractRequestHandler):
"""Handler for Skill Launch."""
def can_handle(self, handler_input):
# type: (HandlerInput) -> bool
return ask_utils.is_request_type("LaunchRequest")(handler_input)def handle(self, handler_input):
# type: (HandlerInput) -> Response
print('LaunchRequest')
speak_output = "Welcome, you can say Hello or Help. Which would you like to try?"
return (
handler_input.response_builder
.speak(speak_output)
.ask(speak_output)
.response
)
class StatusHandler(AbstractRequestHandler):
"""Handler for Skill Launch."""
def can_handle(self, handler_input):
# type: (HandlerInput) -> bool

return ask_utils.is_intent_name("StatusIntent")(handler_input)
def handle(self, handler_input):
# type: (HandlerInput) -> Response
print('StatusHandler')
speak_output = "What you want to know from me?"
return (
handler_input.response_builder
.speak(speak_output)
.ask(speak_output)
.response
)
class HelloWorldIntentHandler(AbstractRequestHandler):
"""Handler for Hello World Intent."""
def can_handle(self, handler_input):
# type: (HandlerInput) -> bool
return ask_utils.is_intent_name("HelloWorldIntent")(handler_input)
def handle(self, handler_input):
# type: (HandlerInput) -> Response
dynamodb_client = boto3.client('dynamodb')
existing_tables = dynamodb_client.list_tables()['TableNames']
print(existing_tables, end="\n\n")
print('HelloWorldIntentHandler')
speak_output = "HelloWorldIntentHandler"
return (
handler_input.response_builder
.speak(speak_output)
# .ask("add a reprompt if you want to keep the session open for the user to respond")
.response
)
class HelpIntentHandler(AbstractRequestHandler):
"""Handler for Help Intent."""
def can_handle(self, handler_input):
# type: (HandlerInput) -> bool
return ask_utils.is_intent_name("AMAZON.HelpIntent")(handler_input)
def handle(self, handler_input):
# type: (HandlerInput) -> Response
print('HelpIntentHandler')
speak_output = "You can say hello to me! How can I help?"
return (
handler_input.response_builder
.speak(speak_output)
.ask(speak_output)
.response
)
class CancelOrStopIntentHandler(AbstractRequestHandler):
"""Single handler for Cancel and Stop Intent."""
def can_handle(self, handler_input):
# type: (HandlerInput) -> bool
return (ask_utils.is_intent_name("AMAZON.CancelIntent")(handler_input) or
ask_utils.is_intent_name("AMAZON.StopIntent")(handler_input))
def handle(self, handler_input):
# type: (HandlerInput) -> Response

print('CancelOrStopIntentHandler')
speak_output = "Goodbye!"
return (
handler_input.response_builder
.speak(speak_output)
.response
)
class SessionEndedRequestHandler(AbstractRequestHandler):
"""Handler for Session End."""
def can_handle(self, handler_input):
# type: (HandlerInput) -> bool
return ask_utils.is_request_type("SessionEndedRequest")(handler_input)
def handle(self, handler_input):
# type: (HandlerInput) -> Response
# Any cleanup logic goes here.
print('SessionEndedRequest')
return handler_input.response_builder.responseclass IntentReflectorHandler(AbstractRequestHandler):
"""The intent reflector is used for interaction model testing and debugging.
It will simply repeat the intent the user said. You can create custom handlers
for your intents by defining them above, then also adding them to the request
handler chain below.
"""
def can_handle(self, handler_input):
# type: (HandlerInput) -> bool
return ask_utils.is_request_type("IntentRequest")(handler_input)
def handle(self, handler_input):
# type: (HandlerInput) -> Response
intent_name = ask_utils.get_intent_name(handler_input)
speak_output = "You just triggered " + intent_name + "."
return (
handler_input.response_builder
.speak(speak_output)
# .ask("add a reprompt if you want to keep the session open for the user to respond")
.response
)
class CatchAllExceptionHandler(AbstractExceptionHandler):
"""Generic error handling to capture any syntax or routing errors. If you receive an error
stating the request handler chain is not found, you have not implemented a handler for
the intent being invoked or included it in the skill builder below.
"""
def can_handle(self, handler_input, exception):
# type: (HandlerInput, Exception) -> bool
return True
def handle(self, handler_input, exception):
# type: (HandlerInput, Exception) -> Response
logger.error(exception, exc_info=True)
speak_output = "Sorry, I had trouble doing what you asked. Please try again."return (
handler_input.response_builder
.speak(speak_output)
.ask(speak_output)
.response
)
# The SkillBuilder object acts as the entry point for your skill, routing all request and response
# payloads to the handlers above. Make sure any new handlers or interceptors you've
# defined are included below. The order matters - they're processed top to bottom.
sb = SkillBuilder()sb.add_request_handler(LaunchRequestHandler())
sb.add_request_handler(StatusHandler())
sb.add_request_handler(HelloWorldIntentHandler())
sb.add_request_handler(HelpIntentHandler())
sb.add_request_handler(CancelOrStopIntentHandler())
sb.add_request_handler(SessionEndedRequestHandler())
sb.add_request_handler(IntentReflectorHandler()) # make sure IntentReflectorHandler is last so it doesn't override your custom intent handlers
sb.add_exception_handler(CatchAllExceptionHandler())lambda_handler = sb.lambda_handler()
  • Select the “AWS Lambda ARN”.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store