Usando "Progressive Response" en nuestra Alexa skill
En un post anterior pudimos ver cómo usar una API externa desde el backend de nuestra Alexa skill. Este tipo de interacciones con third-parties puede ser a veces demasiado lenta y crea una experiencia de usuario extraña.
Imaginemos una conversación con otra persona, cara a cara o por teléfono, donde le preguntamos algo y, hasta que lo encuentra, se produce un silencio. Un silencio que puede durar segundos. Sería un poco extraño en una conversación ¿no? Normalmente la persona que está buscando la información suele dar algún tipo de respuesta intermedia como: "dame un segundo", "vale, lo miro", etc.
Ese tipo de experiencia es la que tenemos que buscar también con un asistente conversacional. Si la respuesta a una petición puede tardar demasiado y producir ese silencio incómodo con le usuario, debemos cubrirlo con alguna respuesta intermedia. Es para esto que existe la posibilidad de mandar un "progressive response" a nuestro skill.
Usos de una Progressive Response
Una respuesta de este tipo en Alexa nos permite enviar algo al usuario, texto o audio, mientras nuestro backend está creando la respuesta final. Esto deriva en una experiencia más natural ya que no dejamos un silencio prolongado entre la petición del usuario y la respuesta.
Se me ocurre que podríamos usar una progressive response para:
- Decir al usuario que hemos recibido su petición y vamos a procesarla. Es el uso que hago yo en mi skill y que enseñaré luego.
- Poner algún tipo de audio, ya sea relacionado con nuestra skill, marca o, simplemente, que haga la espera más agradable.
- Ofrecer algún tipo de contenido adicional mientras el usuario espera para la respuesta final.
Al final lo importante es simular con el usuario el ejemplo de interacción real con otra persona mientras que recopila la info que necesita.
Añadiendo Progressive Response a nuestro backend
Para hacer uso de esta respuesta intermedia en nuestro skill solo tenemos que modificar el backend. No hay nada que afecte al modelo de interacción.
La implementación concreta varia según el SDK pero los conceptos son los mismos. En mi caso voy a mostrar el código usado en mi skill Estrenos de Cine que tiene el backend en Kotlin. Para ejemplos en Javascript podéis ver documentación oficial de Amazon o el curso de German en KeepCoding.
En el SDK de Java tenemos algunas clases que nos van a facilitar la vida bastante a la hora de crear esta progressive response. Lo único que necesitamos para crearla será el requestId
de la petición del usuario, ya venga del LaunchRequest
o de un IntentRequest
, y el mensaje/audio que queremos responder.
Mi skill de Estrenos de cine tiene dos escenarios donde quería meter una progressive response:
- Cuando el usuario pide los estrenos para una fecha determinada, antes de pedir esa info a la API, creo una progressive response informando de que voy a realizar esa consulta.
- Cuando el usuario quiere conocer la cartelera actual, antes de pedir esa info a la API, al igual que antes, creo una progressive response para informarle.
Quiero ofrecer un mensaje distinto para cada caso y por eso veréis en mi código que le paso un texto distinto dependiendo del intent desde el cual genero la progressive response.
Lo que hice fue crear una clase donde iba a manejar todo el comportamiento relacionado con la progressive response. Lo único que hago es recibir el inputRequest
, desde donde saco el requestId
y ofrecer dos métodos públicos que me identificarán el contexto de los dos escenarios que os indicaba antes.
Uso el concepto de "encolar" el mensaje porque es como en realidad se realiza esta respuesta al final. El SDK puede ir encolando respuestas, ya sean de texto o audio, que puede procesar antes de tener la respuesta final del intentHandler
que recibió la petición del usuario.
En términos del SDK:
- Creamos una directiva
SpeakDirective
con el mensaje que vamos a encolar. - Creamos un
header
que será quien contenga la información de la petición, elrequestId
, para poder responder al usuario concreto. - Creamos una
SendDirectiveRequest
con la directiva y el header. Esta directiva es la que tenemos que encolar con unas clases que ya nos proporciona el propio SDK enHandlerInput
.
Esta clase es la que uso en los IntentHandler
de los dos escenarios que ponía antes:
En el código podemos ver dos handlers para el intent de pedir los estrenos para una fecha determinada y para el intent que pide la cartelera actual (es un AMAZON.YesIntent
porque se lanza en un momento concreto de la skill donde el usuario puede responder si o no).
El encolado del mensaje de la progressive response lo hago antes de ir contra la API que me dará la información final. De esta forma el usuario recibirá una respuesta intermedia mientras se realiza la llamada a la API y luego se construye la respuesta final.
En el caso de mi skill la API responde bastante rápido y no era necesario el uso de progressive response, pero quería usarlo para aprender. Además así lo tengo para poder enseñar su uso con Kotlin, que apenas había ejemplos actuales de su uso fuera de Javascript.
Si usáis mi skill de Estrenos de Cine podréis comprobar que Alexa primero os dará el mensaje de la progressive response y seguidamente la respuesta final de la API.