El pasado mes de octubre publiqué mis primeros Skills para Amazon Alexa. Al igual que ocurre en otros markets de apps como AppStore, Amazon se preocupa de certificar manualmente cada uno de los nuevos Skills antes de aprobarlos.

Durante este proceso de certificación he aprendido muchas cosas que quiero compartir con otros desarrolladores. Espero que sirvan de ayuda para que vuestros Skills de Amazon Alexa lleguen rápido a los usuarios 🙂

Los primeros skills que he publicado han sido aplicaciones lo más sencillas posibles. Poco a poco he ido aumentando la complejidad, conforme iban aprobando skills. Para la parte backend de los skills, he usado Amazon Lambda y Node. Listado completo de skills aquí.

1. Actualmente los skills tardan en ser certificados mucho más de los 5 días laborales que anuncia Amazon. Hace semanas sí que tardaban menos de 5 días. Parece que hay un poco de saturación en el proceso de certificación porque hace pocos días (25/10/2018) se lanzó Alexa en castellano, los nuevos altavoces, etc… y hay más desarrolladores enviando sus Skills.

2. Además de probar tus Skills en el simulador web, es muy recomendable probarlos también en un dispositivo real. El el dispositivo real Alexa te responderá muchas más veces con un «lo siento, no te he entendido» o la frase por defecto que hayáis definido para el caso «else».

3. Entrena los intents «AMAZON.StopIntent» y «AMAZON.HelpIntent» del modelo. Aunque estos intents son creados por defecto, no están entrenados y deberás escribir frases de ejemplo para que Alexa sepa cuándo lanzarlos. Por ejemplo:

AMAZON.StopIntent: salir, sal, apaga, terminar, exit, finaliza, finalizar, apaga esto...
AMAZON.HelpIntent: ayuda, ayúdame, necesito ayuda, no me aclaro, help, help me, cómo se juega...

Actualización (7/12/2018): parece que por defecto sí que están un poco entrenados dichos intents, pero les faltan expresiones obvias. Recomendamos extenderlos con las expresiones escritas arriba.

4. Cuidado con las diferencias entre singular y plural. Me ha llamado la atención que el modelo interactivo (el que escucha tu voz y la convierte en acciones que entiende tu aplicación), se hace un lío cuando el usuario cambia el singular por el plural o viceversa. Pensaba que esto sería transparente al usuario. Por ejemplo, si entrenas al modelo para entender una frase con un slot, donde el slot tiene un nº reducido de valores posibles, el sistema no comprende los plurales:

  • «Dime el color de {slot}»

donde {slot} solo puede tomar los valores «la manzana», «el coche», «el cielo».
Falla cuando el usuario dice «Dime el color de las manzanas» (plural).

Como solución al problema anterior, a la hora de crear los valores posibles del slot, puedes crear «sinónimos» para cada valor, en dicho sinónimo poner el valor en plural.

5. Cuidado con las tildes. Mismo problema que en el punto anterior. En algunas Skills lo he resuelto creando sinónimos (como en el punto anterior) y en otras normalizando el parámetro de entrada en la función lambda:

itemName = itemSlot.value.toLowerCase();
itemName = itemName.normalize('NFD').replace(/[\u0300-\u036f]/g, "");

6. Si tu skill está relacionado con salud, no olvides poner un texto «disclamer» en la descripción de la tienda, para que los usuarios tengan claro que tu skill no sustituye nunca a un médico, ni a un diagnóstico ni a un tratamiento, etc. Concretamente, Amazon recomienda poner esto (en el idioma/s de tu skill): «This tool does not provide medical advice, and is for informational and educational purposes only, and is not a substitute for professional medical advice, treatment or diagnosis. Call your doctor to receive medical advice. If you think you may have a medical emergency, please dial your local emergency response phone number.».

7. Cuidado con la sesión de usuario. Asegúrate de cerrarla cuando el usuario salga del skill.

8. Cuidado con los skills multiidioma. Pruébalos en dispositivos que estén configurados con diferentes idiomas. Comprueba también que el idioma por defecto carga correctamente.

9. Si utilizas Amazon Lambda como backend de tu skill, configúralo de forma segura para que solo pueda ser invocado por tu skill. Añade «Alexa Skills Kit» en la lista de triggers de tu función Lambda y configúralo con tu Skill Id.

10. Cuando envíes tu Skill para publicar, te pedirán la frase de ejemplo para invocar tu Skill. Recuerda poner «Alexa abre» al comienzo de la frase de ejemplo y ningún signo o falta de ortografía. Por ejemplo, si la frase de invocación de tu skill es «recomendador de libros», la frase de ejemplo será:

«Alexa abre Recomendador de libros» –> Correcto.

«Alexa, abre recomendador de libros» –> Error de certificación (¿por la minúscula?).

«Recomendador de libros» –> Error de certificación (falta el «Alexa, abre» inicial).

Actualización (17/12/2018): el poner o no la coma «,» después de la palabra «Alexa» causa muchas veces problemas. Me han rechazado algunas skills por poner la «,» y otras me las han rechazado por no poner la «,» 🙁

Actualización (27/1/2019): ver también el punto 20.

11. Los límites del humor. Al compartir un contenido con Alexa, ten en cuenta que casi siempre alguien puede darse por ofendido. Por ejemplo, Amazon me ha rechazado un Skill de chistes por estos 2 chistes. No por ser malos sino por contenido ofensivo 😀

- Papá, ¿qué significa patriota? . ¿Has visto todos esos catalanes que piden la independencia? . Sí . Po tráeme una birra. Y pa-ti-otra"
- ¿Por qué los de Lepe tiran a los niños al pozo? Porque en el fondo son buenos.

12. El nombre de tu skill debe comenzar con mayúscula.

13. No pongas emoticonos en la descripción de tu skill. No están permitidos.

14. Si tu skill es un juego tripo trivial en el que hay que contestar con «A», «B», «C» o «D», no olvides entrenar al modelo para que entienda como inputs válidos:

  • Mayúsculas y minúsculas: A, a, B, b, C, c, D, d.
  • «be», «ce», «de» o «dé».
  • ¡Ojo! Pronunciaciones con «s»: «se» (c).

15. La ayuda debe terminar con una pregunta explícita al usuario. Cuando el usuario pide ayuda a tu skill, ésta debe responder y terminar siempre haciendo una pregunta al usuario.

16. Random issues. En algunos casos, el revisor de tu skill puede pedirte cambiar una frase sin que quede muy claro el motivo. Un ejemplo:

Please modify the description as follows:

Actual: Agradecemos a xxx su trabajo para extraer las preguntas de dicha web.
Expected: Agradecemos a xxx por su trabajo en extraer las preguntas de dicha web.

17. El tipo de slot predefinido (Built-In Slot) llamado «AMAZON.NUMBER» tiene pegas. Si reconoce lo que dice el usuario como la palabra que representa un número (ejemplo: «cinco», «seis», …) entonces enviará a tu función Lambda el número en cifras («5», «6»). Hasta aquí OK. Pero si reconoce directamente lo que dice el usuario como una cifra («5»), entonces el valor no llegará a la función Lambda. Al final esto lo estoy resolviendo con un slot custom que entiende tanto nombres de números como cifras de números.

18. Después de cada punto y aparte, deja un espacio antes de comenzar la siguiente frase. Si no, Alexa puede pronunciar «punto» en lugar de hacer la correspondiente pausa.

19. APL (Alexa Presentation Language) y el cierre de sesión. Si tu skill soporte APL es posible que no estés cerrando bien la sesión del usuario. Según la documentación y el proceso de certificación, hay que cerrar la sesión si no se espera una contestación del usuario. En skills sin APL, bastaba con no poner «reprompt» en el «responseBuilder» para que la sesión se cerrara automáticamente. Ejemplo de responseBuilder sin reprompt:

return handlerInput.responseBuilder
.speak("texto...")
.getResponse();

Pero en skills con APL, el código anterior deja erróneamente abierta la sesión. Lo correcto es usar en todas las skills (con y sin APL), el método .withShouldEndSession(true) cuando queramos cerrar la sesión:

return handlerInput.responseBuilder
.speak("texto...")
.withShouldEndSession(true)
.getResponse();

20. En las frases de ejemplo que hay que facilitar en la ficha de tu skill, copia y pega desde tus «Sample Utterances» de tus intents y tus «slots», ya que las expresiones que uses en las frases de ejemplo tienen que estar exactamente igual en tu modelo. Por ejemplo, si has creado la siguiente skill con este Intent y Slot:

Invocation Name: Información medicamentos

MedicamentoIntent: Quiero información del medicamento {medicamentoSlot}, Quiero info del medicamento {medicamentoSlot}

MedicamentoSlot: [paracetamol, dormidina, ibuprofeno]

entonces no todas las frases de ejemplo valdrían. Ejemplos:

Alexa, abre información medicamentos –> Correcto

Alexa, abre información medicamentos y quiero información de paracetamol –> Error de certificación. No coincide 100% con un sample utterance del intent.

Alexa, abre información medicamentos y quiero información del medicamento dormidina valeriana –> Error de certificación. No coincide 100% con un valor del slot.

Alexa, abre información medicamentos y quiero información del medicamento dormidina –> Correcto

21. Recuerda que en package.json, el «name» no puede tener espacios. Si los pones, tu skill dará error tras el deploy y verás este error en los logs:

Unable to import module 'index': Error
at Function.Module._resolveFilename (module.js:547:15)
at Function.Module._load (module.js:474:25)
at Module.require (module.js:596:17)
at require (internal/module.js:11:18)
at Object.<anonymous> (/var/task/index.js:4:15)
at Module._compile (module.js:652:30)
at Object.Module._extensions..js (module.js:663:10)
at Module.load (module.js:565:32)
at tryModuleLoad (module.js:505:12)
at Function.Module._load (module.js:497:3)

22. Define un «tiempo de espera» (timeout) para tu función Lambda. Si tu función llama a otras APIs es posible que tengas que ampliar el valor por defecto. Cuando la ejecución de tu función Lambda supera este límite, la ejecución termina y no muestra un error concreto.