Kyle Rockman
Lead Infrastructure Engineer OpsLevel.com
Kyle Rockman
http://slides.com/rocktavious/django-alexa/live
Utterance
Intent
Amazon service that interacts with your service to provide extra functionality to the Amazon Echo
Amazon service that you can interact with to provide Amazon Echo capabilities to your device
A definintion of a specific command your skill can act on
A phrase that is mapped to an Intent which aids ASK in speech recognition for your skill
Ask <invocation name> to <do some action>
Ask recipes how do i make an omelet?
Tell <invocation name> that <some command>
Tell scorekeeper that Stephen has ten points.
Ask <invocation name> for <some information>
Ask daily horoscopes for Taurus
Play Jeopardy
Start Seven Minute Workout
Load BART Times
Full Intent
Partial Intent
No Intent
A spoken request in which the user expresses everything required in a single utterance
A spoken request where only a subset of the needed slots were expressed leaving it up to your skill to have extract more information from the user
An open ended request in which the user is expecting the skill to report back its capabilities
Demo
Why?
I just want to write my skill...man.
pip install django-alexa
INSTALLED_APPS = [
'django-alexa',
...
]
urlpatterns = [
url(r'^', include('django_alexa.urls')),
...
]
https://example.com/alexa/ask/
export ALEXA_APP_ID_my_app=amzn1.echo-sdk-ams.app.e18a3326-4775-45f2-83n0-5eeg03832401
export ALEXA_APP_ID_preso=amzn1.echo-sdk-ams.app.e17a3326-4885-44f3-85a0-5eef03832401
export ALEXA_REQUEST_VERIFICATON=True # Default = True
ALEXA_APP_IDS = dict(
[(str(os.environ[envvar]), envvar.replace("ALEXA_APP_ID_", "")) \
for envvar in os.environ.keys() \
if envvar.startswith('ALEXA_APP_ID_')]
)
...
def validate_app_ids(value):
"""
value - an alexa app id
"""
if value not in ALEXA_APP_IDS.keys():
msg = "{0} is not one of the valid " \
"alexa skills application ids for this service".format(value)
raise InternalError(msg)
.
├── __init__.py
├── core
│ ├── __init__.py
│ ├── alexa.py
│ ├── gunicorn.py
│ ├── models.py
│ ├── settings.py
│ ├── urls.py
│ ├── views.py
│ ├── wsgi.py
└── presentation
├── __init__.py
└── alexa.py
INSTALLED_APPS = (
...
'django_alexa',
'myproject.core',
'myproject.presentation',
)
from django_alexa.api import intent, ResponseBuilder
@intent
def LaunchRequest(session):
"""
Default Start Session Intent
"""
message = "Welcome."
reprompt = "What would you like to do next?"
return ResponseBuilder.create_response(message=message,
reprompt=reprompt,
end_session=False)
@intent
def HelpIntent(session):
"""
Default Help Intent
---
help
info
information
"""
message = "No help was configured!"
return ResponseBuilder.create_response(message=message)
from django_alexa.api import fields, intent, Slots, ResponseBuilder
HOUSES = ("gryffindor", "hufflepuff", "ravenclaw", "slytherin")
class PointsForHouseSlots(Slots):
house = fields.AmazonCustom(label="HOUSE_LIST", choices=HOUSES)
points = fields.AmazonNumber()
@intent(slots=PointsForHouseSlots)
def AddPointsToHouse(session, house, points):
"""
Direct response to add points to a house
---
{house}
{points}
{points} {house}
{points} points {house}
add {points} points to {house}
give {points} points to {house}
"""
kwargs = {}
kwargs['points'] = points or session.get('points')
kwargs['house'] = house or session.get('house')
if points is None:
kwargs['message'] = "How many points?".format(house)
kwargs["end_session"] = False
return ResponseBuilder.create_response(**kwargs)
if house is None:
kwargs['message'] = "Which house?".format(points)
kwargs["end_session"] = False
return ResponseBuilder.create_response(**kwargs)
else:
... do points adding work here ...
kwargs['message'] = "{0} points added to house {1}.".format(points,
house)
return ResponseBuilder.create_response(**kwargs)
class ResponseBuilder(object):
"""
Simple class to help users to build alexa response data
"""
@classmethod
def create_response(cls,
message=None, message_is_ssml=False,
reprompt=None, reprompt_is_ssml=False, reprompt_append=True,
title=None, content=None, card_type=None,
end_session=True, **kwargs):
"""
Shortcut to create the data structure for an alexa response
Output Speech:
message - text message to be spoken out by the Echo
message_is_ssml - If true the "message" is ssml formated and should be treated as such
Reprompt Speech:
reprompt - text message to be spoken out by the Echo
reprompt_is_ssml - If true the "reprompt" is ssml formated and should be treated as such
reprompt_append - If true the "reprompt" is append to the end of "message"
Card:
card_type - A string describing the type of card to render. ("Simple", "LinkAccount")
title - A string containing the title of the card. (n/a for cards of type LinkAccount).
content - A string containing the contents of the card (n/a for cards of type LinkAccount).
Note that you can include line breaks in the content for a card of type Simple.
end_session - flag to determine whether this interaction should end the session
kwargs - Anything added here will be persisted across requests if end_session is False
"""
>>> python manage.py alexa_intents
{
"intents": [
{
"intent": "HelpIntent",
"slots": []
},
{
"intent": "LaunchRequest",
"slots": []
},
{
"intent": "AddPointsToHouse",
"slots": [
{
"name": "house",
"type": "HOUSE_LIST"
},
{
"name": "points",
"type": "AMAZON.NUMBER"
}
]
}
]
}
>>> python manage.py alexa_custom_slots
HOUSE_LIST:
gryffindor
hufflepuff
ravenclaw
slytherin
>>> python manage.py alexa_utterances
HelpIntent help
HelpIntent info
HelpIntent information
AddPointsToHouse {points} {house}
AddPointsToHouse {points} points {house}
AddPointsToHouse add {points} points to {house}
AddPointsToHouse give {points} points to {house}
Define your skill, where it's hosted, intents, custom slot types and utterances in the amazon developer portal
Demo
@intent(slots=PointsForHouseSlots)
def AddPointsToHouse(session, house, points):
...
kwargs = {}
kwargs['launched'] = launched = session.get('launched')
kwargs['marauder'] = marauder = session.get('marauder')
kwargs['points'] = points = points or session.get('points')
kwargs['house'] = house = house or session.get('house')
if points is None:
kwargs['message'] = "How many points?".format(house)
kwargs["end_session"] = False
return ResponseBuilder.create_response(**kwargs)
if house is None:
kwargs['message'] = "Which house?".format(points)
kwargs["end_session"] = False
return ResponseBuilder.create_response(**kwargs)
if marauder:
kwargs['message'] = "messers can not give points to houses, we lose them in the name of mischief!"
kwargs['message'] += " {0} points removed from house {1}.".format(randint(1,10), house or HOUSES[randint(0, 3)])
kwargs['reprompt'] = "What mischief brings you here?"
kwargs['end_session'] = False
else:
if launched:
kwargs['reprompt'] = "What house would you like to give points to?"
kwargs['end_session'] = False
kwargs['message'] = "{0} points added to house {1}.".format(points, house)
kwargs.pop("house")
kwargs.pop("points")
return ResponseBuilder.create_response(**kwargs)
By Kyle Rockman
Amazon Alexa Skills Kit integration for Django