Response Building
Standard response
If you are using AWS lambda as your skill endpoint, you are only responsible for providing the response body in order for Alexa to respond to a customer request. The documentation on the JSON structure of the response body can be found here.
A response body may contain the following properties:
- version
- sessionAttributes
- response
ASK SDK for Python helps filling the version and sessionAttributes so you can focus on building the response instead of writing boilerplate code.
Similar to standard requests, the SDK creates response objects as deserialized model objects (ask-sdk-model
package) and internally handles serializing them to response JSON before sending to the Alexa service.
Response Factory
The SDK includes a ResponseFactory
class that contains helper functions for constructing responses. A Response
may contain multiple elements, and the helper functions aid in generating responses, reducing the need to initialize and set the elements of each response.
Interface
class ResponseFactory(object):
def __init__(self):
self.response = .... # Response object
def speak(self, speech, play_behavior=None):
# type: (str, ask_sdk_model.ui.play_behavior.PlayBehavior) -> 'ResponseFactory'
....
def ask(self, speech, play_behavior=None):
# type: (str, ask_sdk_model.ui.play_behavior.PlayBehavior) -> 'ResponseFactory'
....
def set_card(self, card):
# type: (ask_sdk_model.ui.card.Card) -> 'ResponseFactory'
....
def add_directive(self, directive):
# type: (ask_sdk_model.directive.Directive) -> 'ResponseFactory'
....
def add_directive_to_reprompt(self, directive):
# type: (Directive) -> 'ResponseFactory'
def set_should_end_session(self, end_session):
# type: (bool) -> 'ResponseFactory'
....
def set_can_fulfill_intent(self, can_fulfill_intent):
# type: (ask_sdk_model.canfulfill.can_fulfill_intent.CanFulfillIntent) -> 'ResponseFactory'
....
response_builder
, an instance of the ResponseFactory
class, is provided to the skill developers through the HandlerInput object, which is the standard argument passed to the skill components.
For using and adding different directives, look at the Directive model definition.
For using and setting a card, look at the Card model definition.
Code example
The following example shows how to construct a response containing a StandardCard
and a BodyTemplate2
display object through handler_input.response_builder
.
from ask_sdk_core.dispatch_components import AbstractRequestHandler
from ask_sdk_core.handler_input import HandlerInput
from ask_sdk_core.utils import is_intent_name
from ask_sdk_core.response_helper import get_plain_text_content
from ask_sdk_model.response import Response
from ask_sdk_model.interfaces.display import (
ImageInstance, Image, RenderTemplateDirective,
BackButtonBehavior, BodyTemplate2)
from ask_sdk_model import ui
class HelloIntentHandler(AbstractRequestHandler):
def can_handle(self, handler_input):
# type: (HandlerInput) -> bool
return is_intent_name("HelloIntent")(handler_input)
def handle(self, handler_input):
# type: (HandlerInput) -> Response
response_builder = handler_input.response_builder
speech = "This is a sample response"
response_builder.set_card(
ui.StandardCard(
title="Card Title",
text="Hey this is a sample card",
image=ui.Image(
small_image_url="<Small Image URL>",
large_image_url="<Large Image URL>"
)
)
)
if supports_display(handler_input):
img = Image(
sources=[ImageInstance(url="<Large Image URL>")])
title = "Template Title"
primary_text = get_plain_text_content(
primary_text="some text")
response_builder.add_directive(
RenderTemplateDirective(
BodyTemplate2(
back_button=BackButtonBehavior.VISIBLE,
image=img, title=title,
text_content=primary_text)))
return response_builder.speak(speech).response
Text helpers
The following helper functions are provided to skill developers, to help with text content generation:
get_plain_text_content
def get_plain_text_content(primary_text, secondary_text, tertiary_text):
# type: (str, str, str) -> TextContent
# Create a text content object with text as PlainText type
....
get_rich_text_content
def get_rich_text_content(primary_text, secondary_text, tertiary_text):
# type: (str, str, str) -> TextContent
# Create a text content object with text as RichText type
....
get_text_content
def get_text_content(
primary_text, primary_text_type,
secondary_text, secondary_text_type,
tertiary_text, tertiary_text_type):
# type: (str, str, str, str, str, str) -> TextContent
# Create a text content object with text as corresponding passed-type
# Passed-in type is defaulted to PlainText
....
Construct a response using a template
The SDK allows you to use a template to construct a skill response. A template is similar to a view in the model–view–controller (MVC) pattern commonly used to build dynamic web pages.
Using a template can help you:
- Generate a
Response
by separating the presentation logic from the request-handling logic. - More easily generate a
Response
with a complex and nested structure, for example when using Alexa Presentation Language. - Reduce duplicate code by reusing common templates across skills.
You can include multiple response components in a single template, for example outputSpeech
, card
, shouldEndSession
, directives
, and more. A component can contain static data and placeholders for dynamic data, and is built into a full skill response.
To generate a Response
using a template, configure the template factory when building the skill.
Template factory
The template factory interface processes a response template by injecting dynamic data to generate the skill response. In a RequestHandler
, the code that builds the skill response calls the template factory interface. You can implement your own unique template factory or use the TemplateFactory
provided in the SDK, which consists of a list of Template Loader
and Template Renderer
objects.
Template loader
The template loader interface loads template content from data storage. The SDK provides the FileSystemTemplateLoader
to load a template file from the local file system. You can implement your own loader to load a template from a different data storage location.
To use FileSystemTemplateLoader
, provide the directory path, encoding scheme, and file name extension for the template files. If you host your skill on AWS Lambda, include the template files as resources in the skill project.
Template enumerator
You can generate different responses for different locales. To use different template files for different locales, the SDK provides the AbstractTemplateEnumerator
interface and a LocaleTemplateEnumerator
implementation to enumerate possible template locations and names based on the locale property in the skill request. For example, en-US
is the locale property for a template file located at template/en/US
or named template_en_US
.
The LocaleTemplateEnumerator
first tries to find the most specific template file, for example base_response_template/en/US
, then falls back to a less specific file, for example base_response_template/en
, and then finally a global file, for example base_response_template
.
The following list shows the order of locale property combinations from most specific to least specific, assuming "/" as file separator.
- base_response_template/en/US
- base_response_template/en_US
- base_response_template/en
- base_response_template_en_US
- base_response_template_en
- base_response_template
You can implement your own template enumerator to enumerate templates according to your preference.
Template cache
To facilitate the template loading process, the SDK provides the AbstractTemplateCache
interface, and provides a LRUCache
to cache loaded templates for future use. The LRUCache
supports concurrent caching, has a capacity of 5 MB, and a time-to-live of 24 hours by default. You can modify the values according to your needs, or implement your own template cache.
Template renderer
The template renderer interface renders a full template including dynamic data, and converts it into a skill Response
. The SDK provides the JinjaTemplateRenderer
implementation to render a Jinja template. You can also implement your own template renderer to support other template engines.
To use the JinjaTemplateRenderer
, you need to install the package ask-sdk-jinja-renderer
from PyPi. For example:
pip install ask-sdk-jinja-renderer
Example usage of template factory
The following example shows the basic setup and usage of template factory. You provide the root path of the templates, and the SDK generates a default implementation of template factory.
from ask_sdk_core.skill_builder import SkillBuilder
from ask_sdk_core.handler_input import HandlerInput
from ask_sdk_core.dispatch_components import AbstractRequestHandler
from ask_sdk_core.utils import is_request_type
from ask_sdk_core.view_resolvers import FileSystemTemplateLoader
from ask_sdk_jinja_renderer import JinjaTemplateRenderer
from ask_sdk_model import Response
sb = SkillBuilder()
class LaunchRequestHandler(AbstractRequestHandler):
"""Handler for skill launch."""
def can_handle(self, handler_input):
# type: (HandlerInput) -> bool
return is_request_type("LaunchRequest")(handler_input)
def handle(self, handler_input):
# type: (HandlerInput) -> Response
speech_text = "Hello!!"
template_name = "responses"
data_map = {
'speech_text': speech_text,
'card': {
'type': 'Simple',
'title': 'Jinja2 Template',
'content': speech_text
},
'should_end_session': 'false'
}
return handler_input.generate_template_response(template_name, data_map, file_ext='jinja')
# Other skill components here ....
# Register all handlers, loaders, renderers, interceptors etc.
sb.add_request_handler(LaunchRequestHandler())
# Add default file system loader on skill builder
sb.add_loader(FileSystemTemplateLoader(dir_path="templates", encoding='utf-8'))
# Add default jinja renderer on skill builder
sb.add_renderer(JinjaTemplateRenderer())
skill = sb.create()
Using the preceding example code, the following example Jinja template has a full resource path of lambda/templates/responses.jinja
, with the directory path templates
and file extension jinja
passed into the TemplateFactory
, and the locale property of en-US
from the Request
passed into the LocaleTemplateEnumerator
.
Example Jinja template
The following example shows a Jinja template for the OutputSpeech component in a skill response.
{
"outputSpeech": {
"type": "SSML",
"ssml": "<speak></speak>"
},
"card": {
"type": "",
"title": "",
"content": ""
},
"shouldEndSession": ""
}
Last updated: Nov 28, 2023