Alexa-news-stentiment-evalu.../f-ask/docs/requests.rst

266 lines
8.9 KiB
ReStructuredText

Handling Requests
=================
With the Alexa Skills Kit, spoken phrases are mapped to actions executed on a server. Alexa converts
speech into JSON and delivers the JSON to your application.
For example, the phrase:
"Alexa, Tell HelloApp to say hi to John"
produces JSON like the following:
.. code-block:: javascript
"request": {
"intent": {
"name": "HelloIntent",
"slots": {
"firstname": {
"name": "firstname",
"value": "John"
}
}
}
...
}
Parameters called 'slots' are defined and parsed out of speech at runtime.
For example, the spoken word 'John' above is parsed into the slot named ``firstname`` with the ``AMAZON.US_FIRST_NAME``
data type.
For detailed information, see
`Handling Requests Sent by Alexa <https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/handling-requests-sent-by-alexa>`_
on the Amazon developer website.
This section shows how to process Alexa requests with Flask-Ask. It contains the following subsections:
.. contents::
:local:
:backlinks: none
Mapping Alexa Requests to View Functions
----------------------------------------
📼 Here is a video demo on `Handling Requests with Flask-Ask video <https://youtu.be/6RoSi3G1chk>`_.
Flask-Ask has decorators to map Alexa requests to view functions.
The ``launch`` decorator handles launch requests::
@ask.launch
def launched():
return question('Welcome to Foo')
The ``intent`` decorator handles intent requests::
@ask.intent('HelloWorldIntent')
def hello():
return statement('Hello, world')
The ``session_ended`` decorator is for the session ended request::
@ask.session_ended
def session_ended():
return "{}", 200
Launch and intent requests can both start sessions. Avoid duplicate code with the ``on_session_started`` callback::
@ask.on_session_started
def new_session():
log.info('new session started')
Mapping Intent Slots to View Function Parameters
------------------------------------------------
📼 Here is a video demo on `Intent Slots with Flask-Ask video <https://youtu.be/AnyZG2AJE4o>`_.
When Parameter and Slot Names Differ
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Tell Flask-Ask when slot and view function parameter names differ with ``mapping``::
@ask.intent('WeatherIntent', mapping={'city': 'City'})
def weather(city):
return statement('I predict great weather for {}'.format(city))
Above, the parameter ``city`` is mapped to the slot ``City``.
Assigning Default Values when Slots are Empty
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Parameters are assigned a value of ``None`` if the Alexa service:
* Does not return a corresponding slot in the request
* Includes a corresponding slot without its ``value`` attribute
* Includes a corresponding slot with an empty ``value`` attribute (e.g. ``""``)
Use the ``default`` parameter for default values instead of ``None``. The default itself should be a
literal or a callable that resolves to a value. The next example shows the literal ``'World'``::
@ask.intent('HelloIntent', default={'name': 'World'})
def hello(name):
return statement('Hello, {}'.format(name))
Converting Slots Values to Python Data Types
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
📼 Here is a video demo on `Slot Conversions with Flask-Ask video <https://youtu.be/gP86uugBico>`_.
When slot values are available, they're always assigned to parameters as strings. Convert to other Python
data types with ``convert``. ``convert`` is a ``dict`` that maps parameter names to callables::
@ask.intent('AddIntent', convert={'x': int, 'y': int})
def add(x, y):
z = x + y
return statement('{} plus {} equals {}'.format(x, y, z))
Above, ``x`` and ``y`` will both be passed to ``int()`` and thus converted to ``int`` instances.
Flask-Ask provides convenient API constants for Amazon ``AMAZON.DATE``, ``AMAZON.TIME``, and ``AMAZON.DURATION``
types exist since those are harder to build callables against. Instead of trying to define functions that work with
inputs like those in Amazon's
`documentation <https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/alexa-skills-kit-interaction-model-reference#Slot%20Types>`_,
just pass the strings in the second column below:
📼 Here is a video demo on `Slot Conversion Helpers with Flask-Ask video <https://youtu.be/2RoRoABK_VE>`_.
=================== =============== ======================
Amazon Data Type String Python Data Type
=================== =============== ======================
``AMAZON.DATE`` ``'date'`` ``datetime.date``
``AMAZON.TIME`` ``'time'`` ``datetime.time``
``AMAZON.DURATION`` ``'timedelta'`` ``datetime.timedelta``
=================== =============== ======================
**Examples**
.. code-block:: python
convert={'the_date': 'date'}
converts ``'2015-11-24'``, ``'2015-W48-WE'``, or ``'201X'`` into a ``datetime.date``
.. code-block:: python
convert={'appointment_time': 'time'}
converts ``'06:00'``, ``'14:15'``, or ``'23:59'`` into a ``datetime.time``.
.. code-block:: python
convert={'ago': 'timedelta'}
converts ``'PT10M'``, ``'PT45S'``, or ``'P2YT3H10M'`` into a ``datetime.timedelta``.
Handling Conversion Errors
^^^^^^^^^^^^^^^^^^^^^^^^^^
Sometimes Alexa doesn't understand what's said, and slots come in with question marks:
.. code-block:: javascript
"slots": {
"age": {
"name": "age",
"value": "?"
}
}
Recover gracefully with the ``convert_errors`` context local. Import it to use it:
.. code-block:: python
...
from flask_ask import statement, question, convert_errors
@ask.intent('AgeIntent', convert={'age': int})
def say_age(age):
if 'age' in convert_errors:
# since age failed to convert, it keeps its string
# value (e.g. "?") for later interrogation.
return question("Can you please repeat your age?")
# conversion guaranteed to have succeeded
# age is an int
return statement("Your age is {}".format(age))
``convert_errors`` is a ``dict`` that maps parameter names to the ``Exceptions`` raised during
conversion. When writing your own converters, raise ``Exceptions`` on failure, so
they work with ``convert_errors``::
def to_direction_const(s):
if s.lower() not in ['left', 'right']
raise Exception("must be left or right")
return LEFT if s == 'left' else RIGHT
@ask.intent('TurnIntent', convert={'direction': to_direction_const})
def turn(direction):
# do something with direction
...
That ``convert_errors`` is a ``dict`` allows for granular error recovery::
if 'something' in convert_errors:
# Did something fail?
or::
if convert_errors:
# Did anything fail?
``session``, ``context``, ``request`` and ``version`` Context Locals
---------------------------------------------------------------------
An Alexa
`request payload <https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/alexa-skills-kit-interface-reference#Request%20Format>`_
has four top-level elements: ``session``, ``context``, ``request`` and ``version``. Like Flask, Flask-Ask provides `context
locals <http://werkzeug.pocoo.org/docs/0.11/local/>`_ that spare you from having to add these as extra parameters to
your functions. However, the ``request`` and ``session`` objects are distinct from Flask's ``request`` and ``session``.
Flask-Ask's ``request``, ``context`` and ``session`` correspond to the Alexa request payload components while Flask's correspond
to lower-level HTTP constructs.
To use Flask-Ask's context locals, just import them::
from flask import App
from flask_ask import Ask, request, context, session, version
app = Flask(__name__)
ask = Ask(app)
log = logging.getLogger()
@ask.intent('ExampleIntent')
def example():
log.info("Request ID: {}".format(request.requestId))
log.info("Request Type: {}".format(request.type))
log.info("Request Timestamp: {}".format(request.timestamp))
log.info("Session New?: {}".format(session.new))
log.info("User ID: {}".format(session.user.userId))
log.info("Alexa Version: {}".format(version))
log.info("Device ID: {}".format(context.System.device.deviceId))
log.info("Consent Token: {}".format(context.System.user.permissions.consentToken))
...
If you want to use both Flask and Flask-Ask context locals in the same module, use ``import as``::
from flask import App, request, session
from flask_ask import (
Ask,
request as ask_request,
session as ask_session,
version
)
For a complete reference on ``request``, ``context`` and ``session`` fields, see the
`JSON Interface Reference for Custom Skills <https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/alexa-skills-kit-interface-reference>`_
in the Alexa Skills Kit documentation.