16/01/2021

Skill de Alexa I: crear una skill en unos pocos pasos

Desde que en 2014 Amazon lanzó al mercado sus dispositivos Echo con el ya famoso asistente de voz Alexa como anfitrión la empresa habilitó e incentivó la creación de skills para extender las capacidades de dicho asistente, que están al alcance de todo aquel que esté interesado en entrar en el mundo de los asistentes virtuales y para lo que no hacen falta demasiados conocimientos técnicos como iremos viendo a lo largo de este post.

¿Qué es una skill de ALexa?

Una skill es eso, una habilidad, una funcionalidad extra que se le puede añadir al asistente y que debe instalarse e invocarse como si fuera una aplicación de las que usamos a diario en otros dispositivos, pero obviamente con una capacidad de interacción entre el usuario el sistema mucho más limitada al estar basada en la voz.

Entendiendo el modelo

El sistema que plantea Amazon para su asistente de voz está basado en dos partes:

  • reconocimiento de voz: sería considerada la parte fontend del sistema llevada a cabo en local por el dispositivo receptor.
  • procesado de la petición: sería la parte backend ya que depende de un pocesamiento de la petición que se realizaría en remoto mediante las funciones lambda de los Amazon Web Services

Dentro de este sistema el dispositivo físico compatible con Alexa, tipo echo o del tipo que sea, es el dispositivo encargado de captar las instrucciones del usuario (1), aplicar el reconocimiento de voz para "entender" cuál es la intención del usuario y qué proceso debe lanzar (2), ponerse en contacto con la parte backend del sistema para procesar la petición y generar una respuesta (3) que finalmente devolverá al usuario para finalizar el flujo de comunicación.

Así pues el entorno estará formado por una parte hardware conformada por el dispositivo de comunicación y dos partes software (frontend y backend). Entender este punto es importante para poder identificar qué estamos haciendo y por qué cuando desarrollemos más adelante la skill

Entendiendo el flujo de comunicación

El flujo de comunicación por tanto constará de tres fases:

  1. El usuario invoca la skill a través del dispositivo de hardware usando un nombre de invocación que identifica la skill ("Alexa, abre mis tareas").
  2. Una vez invocada la skill Alexa nos pide más información si es necesario ("Soy tu lista de tareas ¿qué quieres hacer?")
  3. El usuario expresa una intención ("Dime qué tareas tengo programadas para hoy")
  4. Mediante la configuración de la parte "fontend" Alexa reconoce qué quiere el usuario (su lista de tareas) e identifica las variables necesarias (solo las tareas de hoy), a continuación envía la petición parametrizada al backend que la procesa (obtiene las tareas para hoy del usuario) y se la devuelve al dispositivo para que emita la respuesta ("Hoy tienes 3 tareas programadas: llamar a X, pedir presupuesto en Y y partido de fútbol en Z").

Dentro de este proceso podemos identificar:

  • Palabra para lanzar el proceso activando la escucha por parte del dispositivo: Alexa en este caso, a este término se le denomina wake word.
  • Nombre para identificar nuestra skill: mis tareas en nuestro ejemplo, a este término se le denomina invocation name.
  • Las distintas declaraciones de intención del usuario: dime qué tareas tengo, a estos elementos se les conoce como intents.
  • Las variables necesarias para procesar la ejecución: dime qué tareas tengo hoy, hoy sería una variable necesaria para filtrar la búsqueda de tareas. A estas variables se las denomina slots. A la hora de identificarlos, como veremos más adelante, será necesario "entrenar" al modelo de identificación de lenguaje aportándole una serie de ejemplos o posibles expresiones.

Teniendo claros estos sencillos conceptos podemos comenzar ya la creación de nuestra skill para Alexa, que como veremos a continuación va plasmando todo lo que hemos estado enumerando en distintos elementos dentro de la plataforma que Amazon nos facilita para el desarrollo de estas skills.

Creando nuestra primera skill para Alexa

0. Si no la tenemos creamos una cuenta de desarrollador

Para tener acceso a la consola de desarrollo de las skills de Alexa necesitaremos darnos de alta primero en el portal de developers de Amazon, que consiste en simplemente crearnos una cuenta de desarrollador para lo cual únicamente necesitaremos un correo electrónico y dar los típicos datos básicos para crear nuestro perfil.

No es necesario dar de alta una tarjeta de crédito para crear la cuenta de desarrollador.

1. Accedemos a nuestro panel de desarrolladores

Una vez hemos hecho login en el portal de developers de Amazon accedemos a nuestro dashboard de desarrollo mediante el link a la Developer Console y una vez ahí accediendo a la sección Alexa Skills Kit. Dentro tendremos acceso, mediante distintas pestañas, al listado de nuestras skills, a nuestros ingresos, información de pagos, hosting y configuración. Por el momento todo esto estará vacío.

2. Creamos una nueva skill

En la pestaña Skills veremos un botón Create Skill que nos dará acceso al asistente para crear nuestra primera skill para Alexa.

Para este ejemplo vamos a crear una skill sencilla que nos devuelva una cita célebre, en este primer post la cita será siempre la misma y en el proximo post de la serie veremos cómo conectar la skill con un servicio externo para obtener cada vez una cita aleatoria distinta. Usaremos tanto para el asistente de voz como para el resto de servicios externos futuros el inglés como idioma de desarrollo para facilitar la integración y conseguir un resultado coherente.

Antes de comenzar a configurar nuestra skill podemos elegir en qué region de la infraestructura de Amazon Web Services queremos que se ubique el procesado en backend de las peticiones de nuestra skill. Para este ejemplo usamos la región EU Ireland. Lo ideal sería usar la región más cercana a la ubicación de los potenciales usuario de la skill.

  • Damos un nombre a nuestra skill, que servirá para identificarla en nuestra lista de skills, solamente, más adelante ya veremos cómo definir el invocation name. En este caso nombramos nuestra skill como RandomQuote.
  • Como ya hemos mencionado usaremos el inglés como idioma por defecto.
  • Usaremos un modelo Custom que como vemos es de las opciones de modelo el que más se ajusta a lo que queremos implementar.
  • El method to host es básicamente el lenguaje de programación que se usará en los procesos AWS Lambda en la parte backend de nuestra skill. En este post usaremos la opción Node.js pero como vemos se puede usar también Python o incluso nuestros propios recursos backend.

Una vez completadas las opciones pulsamos el botón Create Skill que hay arriba a la derecha.

A continuación podemos elegir aplicar una template para partir de una base ya pre-configurada o podríamos también importar una skill que hubiéramos exportado previamente. En nuestro caso dejamos la opción por defecto start from scratch para crear nuestra skill con la base mínima requerida y poder añadir manualmente los elementos que necesitamos. Finalmente pulsamos el botón Continue with template.

El sistema nos pedirá que resolvamos un sencillo captcha y a continuación comenzará el proceso de creación de nuestra template. Pasados unos segundos si todo ha ido bien tendremos acceso a la consola de desarrollo de nuestra primera skill.

3. Identificando las partes

Como ya hemos mencionado una skill de Alexa está formada por una parte frontend encargada de la interacción con el usuario y el reconocimiento del lenguaje y una parte backend encargada del proceso lógico de la skill. En la pantalla podemos situar cada una de estas dos partes, siendo la pestaña Build y sus elementos de la izquierda (Invocation, Interaction Model y Assets) los que representan los recursos frontend, mientras que la pestaña Code es en la que definiremos los procesos backend, en nuestro caso mediante Javascript al haber elegido el method to host tipo Node.js.

4. Definir el Invocation Name

Lo primero que debemos hacer será definir un invocation name para que el dispositivo receptor de nuestra voz sepa identificar cuándo queremos acceder a nuestra skill. Como se trata de un elemento front necesitaremos situarnos en la pestaña Build que es la que engloba dichos recursos y concretamente iremos a la sección Invocation. Por defecto vemos que el Invocation Name está definido como "change me" en una clara invitación a que personalicemos este parámetro. Elegimos para este caso "famous quote", como veremos hay ciertos requisitos que nuestro Invocation Name deberá cumplir, como un rango de longitud y el estar formado por al menos dos palabras.

Los Invocation Name solo es necesario en los casos de custom skill como el nuestro y no son identificadores únicos de una skill, por lo que podremos elegir cualquier valor que cumpla con los requisitos. Los Invocation Name pueden cambiarse en cualquier momento del desarrollo hasta que la skill pasa por el proceso final de certificación y publicación.

Una vez configurado el invocation name lanzamos el proceso Build Model para que los cambios en la skill tengan efecto.

5. Testear el Invocation Name

Antes de continuar vamos a comprobar que el invocation name se ha configurado correctamente. Vamos a la pestaña Test y elegimos Development como opción en el desplegable Skill testing is enabled in.

Si hemos dado permisos al navegador para usar nuestro micro podremos dirigirnos directamente a la versión test de Alexa mediante nuestra voz, si no podemos usar el cuadro de diálog para solicitar que abra nuestra skill escribiendo y enviando el mensaje "open famous quote". Si el invocation name está bien configurado nuestra skill se lanzará y Alexa nos devolverá una respuesta por defecto, en cualquier otro caso nos responderá con una respuesta de error.

6,. Cambiar la respuesta por defecto

Ahora que ya hemos visto el primer elemento frontend de la Developer Console vamos a entrar en contacto con el backend para cambiar esa respuesta por defecto y sustituirla por una personalizada para nuestra skill. En la pestaña Code podremos ver los distintos bloques de código contenidos en el fichero index.js. Debemos centrarnos en el primero de ellos, el que define una constante llamada LaunchRequestHandler, ese bloque de código son las instrucciones que sigue la función Lambda remota de AWS, que se ejecuta una vez invocada la skill mediante el invocation name, en algún servidor de Irlanda en nuestro caso.

const LaunchRequestHandler = {
    canHandle(handlerInput) {
        return Alexa.getRequestType(handlerInput.requestEnvelope) === 'LaunchRequest';
    },
    handle(handlerInput) {
        const speakOutput = 'Welcome, you can say Hello or Help. Which would you like to try?';

        return handlerInput.responseBuilder
            .speak(speakOutput)
            .reprompt(speakOutput)
            .getResponse();
    }
};

Como podemos ver el mensaje speakOutput, insertado tanto en la función de respuesta speak (para que Alexa lo pronuncie), como en la reprompt (para que Alexa quede a la espera de interacción sin abandonar la el contexto de la skill), corresponde a la respuesta que hemos recibido en el test rápido realizado en el punto anterior.

Simplemente cambiamos el mensaje a algo tipo Welcome to famous quote skill. What do you want me to do?

Y finalmente guardamos cambios y desplegamos el nuevo backend mediante los botones Save y Deploy.

Como podemos ver el frontend y el backend de la skill tienen procesos distintos y separados para el Deployment. En la parte front podemos construir el modelo para aplicar los cambios mientras que en el caso del back debemos accionar el despliegue.

Bajo el botón Deploy tendremos siempre la referencia de cuándo se ha desplegado la última vez.

Si ahora repetimos el test que hemos hecho antes deberemos recibir como respuesta el nuevo mensaje personalizado en lugar del mensaje por defecto.

7. Configurar un nuevo Intent

A continuación vamos a cubrir el último elemento de este post de introducción a la creación de skills para Alexa. Se trata de los Intent que como ya hemos mencionado son elementos que sirven para que Alexa entienda qué intención tiene el usuario, qué es lo que quiere hacer. En el caso de nuestra skill, aunque un tanto obvio, el usuario tras invocar la skill querrá que esta le diga la cita célebre o famosa, por lo que expresará esa intención mediante algún mensaje tipo "quiero que me digas una cita célebre" o "dime una cita famosa". Para capturar, y que Alexa "entienda" dicha petición necesitamos definir un Intent específico.

Para crear un nuevo Intent, al tratarse de un elemento de la parte frontend debemos volver a la pestaña Build y seleccionar el apartado Interaction Model > Intents en el panel de la izquierda. Veremos el listado de los intents que trae por defecto una skill con template del tipo start from scratch como es la nuestra y tendremos un botón Add Intent para crear nuevos intents personalizados.

A continuación veremos que podemos elegir entre una lista de intents predeterminados o crear uno personalizado. Elegimos Create custom intent y le damos un nombre, QuoteIntent por ejemplo, para definir que la petición del usuario está relacionada con la obtención de una nueva cita. Finalmente presionamos Create custom intent.

Ahora habremos sido redirigidos a la página de configuración del nuevo intent en la que lo primero que tendremos que hacer será "entrenar" a nuestra skill para que sepa ante qué tipo de mensajes del usuario queremos que lance el proceso relacionado con este nuevo intent. Para ello tendremos que añadir una serie de entradas en la sección Sample Utterances (muestra de declaraciones) que servirán para "mapear" los posibles mensajes del usuario. En nuestro caso, y en inglés, añadiremos las distintas variantes esperables para la obtención de una cita célebre:

  • "give me a famous quote"
  • "tell me a famous quote"
  • "say a quote"
  • "tell me a quote"
  • "give me a random quote"

Y así sucesivamente, cuantas más utterances aportemos más "inteligente" será Alexa a la hora de "comprender" al usuario.

Finalmente, y como siempre tras un cambio en la parte "frontend" de la skill lanzaremos la construcción del nuevo modelo mediante el botón Build Model.

8. Configurar una respuesta para el nuevo Intent

Finalmente como último paso necesitamos que Alexa tenga una respuesta asociada a este nuevo intent y que se ejecutará en el backend de la skill por lo que necesitamos volver a la pestaña Code.

Una vez allí necesitaremos crear un nuevo bloque de código para generar la función que se ejecutará cuando Alexa envíe la invocación del intent. A continuación del LaunchRequestHandler añadiremos el siguiente bloque de código:

const QuoteIntentHandler = {
    canHandle(handlerInput) {
        return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
            && Alexa.getIntentName(handlerInput.requestEnvelope) === 'QuoteIntent';
    },
    handle(handlerInput) {
        const speakOutput = 'Knowledge is of no value unless you put it into practice.';

        return handlerInput.responseBuilder
            .speak(speakOutput)
            //.reprompt('add a reprompt if you want to keep the session open for the user to respond')
            .getResponse();
    }
};

Mediante este código estamos creando una función lambda que en caso de que el request proveniente de la skill sea identificado como el QuoteIntent lanzará la lógica del handler, que en este caso devuelve simplemente una cita cualquiera y estática, siempre va a devolver la misma. Como vemos al función reprompt en el responseBuilder está comentada por lo que con esta ejecución, una vez devuelta la respuesta al usuario, se dará por cerrada la "sesión" de nuestra skill y en caso de querer volver a obtener la cita tendremos que volver a invocar la skill mediante su invocation name.

Antes de desplegar el nuevo backend tenemos que registrar el nuevo intent handler en la lista de exports al final del fichero index.js

Finalmente guardamos y desplegamos la nueva funcionalidad del backend como hemos hecho antes mediante los botones Save y Deploy.

Si ahora volvemos a testear nuestra skill veremos como, una vez invocada, podemos hacer uso del nuevo intent para que Alexa nos devuelva la cita célebre que le hemos definido.

Destacar como el mensaje que le hemos enviado no coincide exactamente con ninguna de las utterances que definimos para el intent pero el proceso de "Build Model" se encarga de procesar las "pistas" que le hemos dado para "entrenar" al modelo basado en eso pero dotándolo de mayor flexibilidad.

Conclusión

En este post hemos visto una sencilla introducción a la creación de skills para Alexa, hemos visto el modelo básico de funcionamiento, las fases del flujo de comunicación y hemos repasado los distintos elementos implicados en el funcionamiento de una skill básica.

En el siguiente post de la serie veremos cómo conectar la skill que hemos creado para que en lugar de devolver siempre la misa cita sea capaz de conectarse a una API externa, obtener citas aleatorias y hacérselas llegar al usuario.

Recursos utilizados: