Blog de Amazon Web Services (AWS)

Cómo desplegar el modelo recomendador de anime en una API REST.

Por Elizabeth Fuentes Leone, AWS Developer Advocate

Recomendaciones personalizadas de anime, es una serie donde construirás una aplicación web capaz de entregar una experiencia personalizada de recomendaciones de animes nuevos de acuerdo a la preferencia del usuario y a medida que se utiliza con mayor frecuencia, puede ir entregando recomendaciones cada vez más relevantes.

Esta serie consistirá en los siguientes episodios:

En el primer episodio te mostramos como crear un modelo de recomendaciones de anime utilizando la data histórica de Anime Recommendation Database 2020 de kaggle. Utilizamos el servicio de Amazon Personalize para entrenar el modelo y hacer inferencia a través de una API utilizando un jupyter notebook, obteniendo recomendaciones de acuerdo a los gustos del usuario y/o anime consultado, filtrar los resultados por géneros y además podemos alimentar el modelo recomendador con las nuevas interacciones de los usuarios.

En este segundo episodio, crearás una API REST (Fig. 1) para consumir de forma segura y escalable la API de Amazon Personalize creada en el episodio anterior.

Fig. 1 Diagrama de api-rest para un recomendador utilizando Amazon Personalize.

El servicio Amazon API Gateway se utiliza para invocar funciones de AWS Lambda donde se ejecuta el  código para consultar la API de Amazon Personalize para cada tipo de inferencia (Event Tracker, anime-sims, anime-rerank y user-personalization), la respuesta recibida es enriquecida con información adicional de los animes almacenados en Amazon DynamoDB, obteniendo como resultado un JSON con la información completa de los animes recomendados.

El proyecto 👷🏻: Cómo desplegar el modelo recomendador de anime en una API REST.

Pre-requisitos:

Manos a la obra 🚀 👩🏻🚀

Paso 1: Crear el modelo de recomendación personalizado.

Sigue los pasos del episodio Cómo crear un modelo de recomendación personalizado e ignora el paso 12 donde se borran los recursos.

Paso 2: Crear el archivo de datos para la tabla Anime.  

El modelo de recomendaciones esta entrenado con los IDs del anime, nombrado como ITEM_ID, por lo cual, las consultas y respuestas al modelo están relacionadas al ITEM_ID.

Para la futura aplicación web es necesario que la API REST entregue el ID del anime (ITEM_ID), el nombre del anime y su información general.

Para esto cargarás una tabla de DynamoDB con el contenido del archivo anime_with_synopsis.csv de Anime Recommendation Database 2020 de kaggle descargado en el paso anterior.

La tabla tendrá dos usos:

  1. Retornar Nombre del Anime cuando se consulte por
  2. Retornar un listado de ITEM_ID cuando se realice una búsqueda por Nombre de Anime, no necesariamente exacto.

Ahora, explorando el notebook anime-table.ipynb de Amazon SageMaker, creado en el Paso 1, verás que el archivo anime_with_synopsis.csv consta de 5 columnas (Fig. 2):

  • MAL_ID: ID del anime.
  • Name: Nombre del anime.
  • Score: Promedio de puntación obtenida por el anime.
  • Genres: Géneros del anime.
  • Sypnosis: Descripción del anime.

Fig.2 Muestra de anime_with_synopsis.csv

Agrega una nueva columna llamada Name_Lower a anime_with_synopsisName normalizados a minúsculas. Esto facilita las consultas por nombre.

anime_with_synopsis[‘Name_Lower’] = anime_with_synopsis[‘Name’].str.lower()

Continuando los pasos en anime-table.ipynb, crea el archivo new_anime_with_synopsis.csv y guárdalo en el bucket creado en el Paso 1.

Fig.2 Muestra de anime_with_synopsis.csv

Fig.3 Muestra de anime_with_synopsis.csv con Name_lower.

Paso 3: Crear tabla anime-table en Amazon DynamoDB. 

  1. Accede a la consola de Amazon DynamoDB en la misma región donde creaste el proyecto del Paso 1.
  2. En la parte derecha del panel de Amazon DynamoDB, selecciona Importaciones de S3 y luego el botón Importación de S3.
  3. En opciones de importación
    1. En Explorar S3, elige el archivo que creamos anteriormente (Fig. 4).
    2. En Importar formato de archivo selecciona CSV.
    3. Selecciona

Fig.4 Explorar S3 > Elige archivo new_anime_with_synopsis.csv.

  1. En Tabla destino:
    1. En el campo Nombre de la tabla, introduce anime-table.
    2. En el campo Clave de partición (Primary key), escribe MAL_ID. El tipo de datos en Cadena (String).
  2. Selecciona

Las consultas de a las tablas de DynamoDB se hacen a través de la clave de partición (Primary key), en este caso MAL_ID.

Ahora, para poder consultar a través de Name_Lower, crea un Global Secondary Index (GSI):

  1. Accede a la tabla dando click sobre el nombre de la tabla.
  2. En el menú Índices, selecciona Crear Índicey luego:
    1. En el campo Clave de partición (Particion Key), escribe Name_Lower y tipo de datos en Cadena (String).
    2. Al final en Proyecciones de atributos, selecciona Only keys. 
    3. Finaliza con Crear Índice.

Paso 4: Crear los permisos para las Funciones Lambda. 

Separando las funciones Lambda de la Arquitectura en la Fig. 5, crearás 6 Funciones Lambda, 4 con permisos para Personalize, con el código para consultar la API creada en el episodio anterior, y 5 con permiso de lectura a DynamoDB para complementar la información entregada por Personalize.

Fig. 5 Funciones Lambda de la Arquitectura.

Para otorgar los permisos a las funciones Lambda se crean los AWS Identity and Access Management Roles (IAM Roles) de ejecución (rol de ejecución) con políticas de acceso para cada servicio, especificado en la Tabla 1 y separado en 3 tipos.

Nombre Función Lambda Amazon Personalize Amazon DynamoDB Amazon Lambda
PutEvents GetRecommendations GetPersonalizedRanking read_data AWSLambdaBasicExecutionRole
Descripción rol de ejecución Permite ingresar nuevos eventos. Devuelve una lista de elementos recomendados. Devuelve una lista de artículos recomendados para el usuario dado. Permite leer en DynamoDB Otorga permisos para cargar registros en Amazon CloudWatch.
lambda_tracker X X
lambda_sims X X X X
lambda_rerank X X X X
lambda_personalization X X X X
lambda_get_anime X X
lambda_search X X

Tabla 1. Tipos de IAM Roles para Funciones Lambda.

Para la creación de cada política de IAM sigue los pasos en este link, en el paso 5 pega el JSON a continuación correspondiente a cada tipo de IAM Role, ingresando tu región e ID de cuenta donde corresponde y escribe el Nombre respectivo para cada una en el paso 8 del link.

a. Política IAM Role verde – Nombre: politicaverde:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "xray:PutTraceSegments",
                "xray:PutTelemetryRecords"
            ],
            "Resource": "*",
            "Effect": "Allow"
        },
        {
            "Action": "personalize:PutEvents",
            "Resource": "*",
            "Effect": "Allow"
        }
    ]
}

b. Política IAM Role azul – Nombre: politicaazul:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "xray:PutTraceSegments",
                "xray:PutTelemetryRecords"
            ],
            "Resource": "*",
            "Effect": "Allow"
        },
        {
            "Action": [
                "dynamodb:GetItem"
            ],
            "Resource": [
                "arn:aws:dynamodb:TU-REGION:TU-ID-CUENTA:table/anime_table",
                "arn:aws:dynamodb:TU-REGION:TU-ID-CUENTA:table/anime_table/index/"
            ],
            "Effect": "Allow"
        },
        {
            "Action": [
                "personalize:GetPersonalizedRanking",
                "personalize:GetRecommendations"
            ],
            "Resource": [
                "arn:aws:personalize:TU-REGION:TU-ID-CUENTA:campaign/*",
                "arn:aws:personalize:TU-REGION:TU-ID-CUENTA:filter/*"
            ],
            "Effect": "Allow"
        }
    ]
 }

c. Política IAM Role Rojo – Nombre: politicarojo:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "xray:PutTraceSegments",
                "xray:PutTelemetryRecords"
            ],
            "Resource": "*",
            "Effect": "Allow"
        },
        {
            "Action": [
                "dynamodb:GetItem",
                "dynamodb:Scan"
            ],
            "Resource": [
                "arn:aws:dynamodb:TU-REGION:TU-ID-CUENTA:table/anime_table",
                "arn:aws:dynamodb:TU-REGION:TU-ID-CUENTA:table/anime_table/index/"
            ],
            "Effect": "Allow"
        }
        
    ]
}

Una vez, creadas las políticas, puedes crear los IAM Roles:

  1. En la consola de Amazon IAMselecciona Roles.
  2. Selecciona Crear Roles.
  3. En Seleccionar entidad de confianza:

a. Tipo de entidad de confianza: Servicio de AWS. 

b. Caso de uso: Lambda

c. Siguiente.

4. En Agregar permisos, realiza lo siguiente para cada IAM Role:

Por ejemplo, para el IAM Role verde:

    • Buscar y seleccionar: AWSLambdaBasicExecutionRole
    • Quita el filtro.
    • Buscar y seleccionar: politicaverde
    • Selecciona Siguiente.
    • Nombre del rol: role-verde.
    • Selecciona Crear rol.

Al finalizar debes visualizar en la consola algo similar a la Fig. 6 para cada IAM Role.

Fig. 6 IAM Role creado con éxito.

Paso 5: Crear las variables de entorno para las Funciones Lambda. 

Nombre Función Lambda IAM Role código Función Lambda Variables de entorno
TABLE_NAME Región INDEX_NAME FILTERS CAMPAIGN_ARN TRACKING_ID
lambda_tracker role-verde codigo-tracker X X X
lambda_sims role-azul codigo-simis X X X X
lambda_rerank role-azul codigo-rerank X X X X
lambda_personalization role-azul codigo-personalization X X X X
lambda_get_anime role-rojo codigo-get-anime X
lambda_search role-rojo codigo-search X X

Tabla 2. Configuración Funciones Lambda.

Los valores para variables de entorno de acuerdo a la Tabla 2 son los siguientes:

TABLE_NAME: anime-table.

Región: TU-REGIÓN, donde tienes creados los proyectos. Lo ves en la parte derecha de la consola, en mi caso es us-east-1.

INDEX_NAME: El valor en menú Índices de la tabla creada en el Paso 2 (Fig. 7) igual a Name_Lower-index.

Fig.7 Nombre de Índice secundario global.

FILTERS: Los filtros fueron creados en el Paso 1, y están accediendo a la consola de Amazon Personalize, en el menú selecciona Manage dataset groups e ingresa a tu dataset, luego selecciona Filters, y veremos lo siguiente (Fig. 8)

Fig.8 Filtros en Amazon Personalize.

Copia cada uno de los Filter ARN del recuadro naranja de la Fig. 8, luego completa la información en el nombre que corresponda a cada filtro en el siguiente JSON:

[{"name": "Drama","Filter ARN"}, 
{"name": "Music", "Filter ARN"}, 
{"name": "Sci-Fi", "Filter ARN"}, 
{"name": "Shounen", "Filter ARN"}, 
{"name": "Fantasy", "Filter ARN"}, 
{"name": "Action", "Filter ARN"}, 
{"name": "Comedy", "Filter ARN"}, 
{"name": "Adventure", "Filter ARN"}, 
{"name": "Kids", "Filter ARN"}]

El JSON final corresponde al valor de la variable de entorno FILTERS.

CAMPAIGN_ARN: siguiendo los mismos pasos que para obtener FILTERS, en el menú selecciona Custom resources > Campaigns, como en la Fig. 10, debe haber tres tipos de campañas, creadas en el Paso 1.

Fig.9 Campañas en Amazon Personalize.

Ingresa a cada campaña, copia y pega el valor de ARN, este será el CAMPAIGN_ARN. Por ejemplo, el CAMPAIGN_ARN para la Función Lambda con nombre lambda_sims corresponde al de la Fig. 10.

Fig.10 Campaign ARN de campaña Sims en Amazon Personalize.

TRACKING_ID: al igual que para FILTERS y CAMPAIGN_ARN, en el menú de la consola de Amazon Personalize selecciona Event trackers, ingresa al creado en el Paso 1 y copia el Tracking ID (Fig.11), el valor correspondiente a esta variable de entorno.

Fig.11 Tracking ID en Amazon Personalize.

Paso 6: Crea las Funciones Lambda. 

En la consola de AWS Lambda, en la misma región donde crearte el proyecto del Paso 1.

  1. Selecciona Crear una función, en esta página:

a. Selecciona Crear desde cero.

b. Nombre de la Función: El que corresponde en la tabla 2, por ejemplo, lambda_tracker.

c. Tiempo de ejecución: Python 3.8.

d. Cambiar el rol de ejecución predeterminado

      • Selecciona Uso de un rol existente.
      • En Role existente selecciona el rol que corresponde al color de la Función Lambda, por ejemplo, role-verde.

2. Deberías ver algo como la Fig. 12 para cada Función Lambda:

Fig.12 Crear Función Lambda.

  1. Selecciona Crear una función.

A continuación, agregamos el código fuente y las variables de entorno.

Para agregar el código fuente:

  1. En la consola de Amazon Lambdaselecciona el Nombre de la función a editar, por ejemplo, lambda_tracker.
  2. En el menú de la Función Lambda selecciona Código fuente, sobre-escribe el código en el cuadrado naranja de la Fig. 13 y pega el que corresponda, por ejemplo, para  lambda_tracker sería el codigo-tracker.

Fig.13 Código fuente de Función Lambda.

  1. Selecciona el botón Deploy.

Para agregar las variables de entorno:

  1. En el menú de la Función Lambda selecciona Configuración. 
  2. Selecciona Variables de entorno -> Editar.
  3. Agrega las variables de entorno de la Tabla 2 para cada Función Lambda. Por ejemplo, para lambda_tracker:

a. Clave: REGION – Valor: TU-REGIÓN

b. Clave: TRACKING_ID – Valor: Tracking ID en Amazon Personalize, obtenido en paso anterior.

4. Selecciona Guardar, deberías ver algo similar a la Fig. 14.

Fig.14 Variables de entorno de Función Lambda lambda_tracker.

Repite este paso para todas las Funciones Lambda de la Tabla 2.

Paso 7: Crea una API REST en Amazon API Gateway.

  1. Ingresa a la consola de API Gateway
  2. Selecciona Crear API.
  3. En API REST (publica), selecciona
  4. En protocolo selecciona REST, en Crear API nueva selecciona API nueva y en Configuración Nombra tu API, en nuestro caso como Recomendador-anime, por último, en Tipo de enlace selecciona Optimizado para límites (Fig. 15).

Fig. 15 Configuración API Gateway.

  1. SeleccionaCrear API.

Paso 8: Creamos los métodos en Amazon API Gateway.

Necesitamos crear seis APIs (Fig. 16), una para cada Función Lambda y que sea capaz de invocarlas de acuerdo a los métodos y recursos de la Tabla 3.

Fig.16 APIs a crear en Amazon API Gateway.

API Lambda Nombre del recurso Ruta de recurso Método
Event tracker lambda_tracker tracker {userId} POST
sims lambda_sims sims {itemId} GET
rerank lambda_rerank rerank {userId} GET
personalization lambda_personalization personalization {userId} GET
get_anime lambda_get_anime get_anime {MAL_ID} GET
search lambda_search search search GET

Tabla 3. Descripción configuración APIs.

Las APIs con método GET son para invocar las funciones Lambdas que obtienen información del modelo de recomendación y de la tabla anime_table de DynamoDB, y con el método POST se le informa al modelo de recomendaciones con nuevas interacciones de los usuarios.

Crea los recursos:

  1. Dentro de la API creada en el paso anterior, selecciona Acciones y luego Crear recurso.

a. En nuevo recurso secundario, usa el Nombre del recurso de la Tabla 3, por ejemplo, para tracker (Fig. 17):

Fig.17 Crear recurso tracker en Amazon API Gateway.

b. Selecciona Crear Recurso.

  1. Dentro de los recursos creados anteriormente, crea un recurso nuevo anidado, que será un dato con el que se invocará la función Lambda. Este sub-recurso corresponde a los valores de la columna Ruta Recurso, por ejemplo, para tracker (Fig. 18).

Fig.18 Crear recurso dentro de tracker en Amazon API Gateway.

  1. Repite lo anterior para cada recurso de la Tabla 3.
  2. Hasta el momento debes ver algo similar a la Fig. 19.

Fig. 19 Recursos de API Recomendador-anime

Para crear el método:

  1. Selecciona el recurso al cual vamos a agregar el método, por ejemplo, para rerank seria {userId}. Luego ingresamos a Acciones> Crear método (Fig. 20).

Fig. 20 API Acciones > Crear método.

  1. En el nuevo menú (Fig. 21) selecciona GET o POST, de acuerdo a la Tabla 3, y luego selecciona el símbolo ✅ para aceptar.

Fig. 21 Crear método.

  1. Selecciona el método creado e iniciamos su configuración:
    • a. En Tipo de integración, seleccionamos Función Lambda.
    • b. Marca la opción Usar la integración de proxy Lambda, que permite invocar una función Lambda en el backend utilizando el request tal cual.
    • c. En Región Lambda, selecciona la región donde creaste las funciones.
    • d. En Función Lambda pon el nombre de la función, por ejemplo,
    • e. Deja el resto tal cual.
    • f. Selecciona Guardar.
    • g. Aparecerá una ventana “Agregar permiso a la función Lambda”, selecciona Aceptar. Esto otorgará los permisos necesarios para que Amazon API Gateway pueda invocar a la función Lambda.
  2. De igual forma, debes agregar el método OPTIONS, el cual configuramos con el Tipo de integración Simulación (Mock).
  3. Repetir lo anterior para cada recurso de la Tabla 3.
  4. Verifica que esté como en la Fig. 22.

Fig. 22 Recursos con métodos de API Recomendador-anime

Paso 9: Publica la API para que sea invocada desde una URL.

  1. Sobre la raíz de la API /.
  2. Selecciona Acciones > Implementar la API.
    • a. En Etapa de implementación selecciona [Nueva etapa].
    • b. Nombre de la fase escribe prod.
    • c. Selecciona Implementación.
  3. Cuando finalice, selecciona
  4. Despliega el contenido de prod.
  5. Seleccionando cada método GET/POST, vas a ver el link con el cual invocar la API: Invocar URL.

Paso 10: Probar la API.

Ahora, solo nos queda jugar con la API en cualquier navegador, para eso debes tener el valor de Invocar URL para cada método obtenido en el paso anterior (Fig. 23).

Fig. 23 API Recomendador-anime – Invocar URL

Tracker:

Para actualizar las preferencias por usuario.

POST https://<event-tracker-api>/{userId}
body 
{
    "itemId": (ITEM_ID con que se interactúa),
    "eventType": (tipo de evento, ej: click, compra, view),
    "eventValue": (valor del evento, de existir por ejemplo calificación),
    "sessionId": (identificador de la sesión)
}

sessionId: puedes generar un numero random, acá te muestro como. En producción corresponde a la sesión de usuario.

Ejemplo: Usuario userId = 20000 califica con nota = 9 una serie itemId = 199.

Request:

POST https://API-ID.execute-api.TU-REGION.amazonaws.com/20000
body : 
{
    "itemId": "199",
    "eventType": "RATING",
    "eventValue": 9,
    "sessionId": "96e5a75b-8c71-42ea-a0ad-d9c474c44422"
}

Respuesta:

{
    "data": {
        "ResponseMetadata": {
            "RequestId": "96e5a75b-8c71-42ea-a0ad-d9c474c44422",
            "HTTPStatusCode": 200,
            "HTTPHeaders": {
                ...
            },
            "RetryAttempts": 0
        }
    }
}

Consultas GET:

En la Tabla 4 puedes ver como utilizarlas.

Nombre Invocar URL Request Request con filtro Resultado
sims https://API-ID.execute-api.TU-REGION.amazonaws.com/prod/sims/{itemId} https://API-ID.execute-api.TU-REGION.amazonaws.com/prod/sims/1000 https://API-ID.execute-api.TU-REGION.amazonaws.com/prod/sims/1000?filter=Shounen entrega un listado de 25 elementos similares al consultado
rerank https://API-ID.execute-api.TU-REGION.amazonaws.com/prod/-rerank/{userId} https://API-ID.execute-api.TU-REGION.amazonaws.com/prod/-rerank/300?inputList=3000,3001,2500 https://API-ID.execute-api.TU-REGION.amazonaws.com/prod/-rerank/300?inputList=3000,3001,2500&filter=Drama&numResults=10 Reordena items para usuario según orden de recomendación.
personalization https://API-ID.execute-api.TU-REGION.amazonaws.com/prod/personalization/{userId} https://API-ID.execute-api.TU-REGION.amazonaws.com/prod/personalization/300 https://API-ID.execute-api.TU-REGION.amazonaws.com/prod/personalization/300?filter=Shounen Recomienda 25 items del filtro para el usuario = userId
get_anime https://API-ID.execute-api.TU-REGION.amazonaws.com/prod/get_anime/{MAL_ID} https://API-ID.execute-api.TU-REGION.amazonaws.com/prod/get_anime/1000 Entrega la información del anime MAL_ID consultado.
search https://API-ID.execute-api.TU-REGION.amazonaws.com/prod/search/search https://API-ID.execute-api.TU-REGION.amazonaws.com/prod/search/search?nombre=narut Entrega un listado de la data de animes que contengan la palabra buscada en su nombre.

Tabla 4. Ejemplos de Invocar URL y posibles inputs.

 

Paso 11: Borrar los recursos de la cuenta de AWS.

Estos pasos son opcionales, si tu intención es continuar con la construcción de la aplicación web, puedes mantener los recursos ya que los vamos a utilizar en el próximo episodio de esta serie.

De lo contrario, sigue los siguientes pasos:

  1. Borrar recursos en API Gateway: En la consola de API Gateway, selecciona la API y en Acciones seleccionar Delete.
  2. Borrar funciones Lambda: En la consola de AWS Lambda, selecciona las funciones Lambda a borrar y en Acciones selecciona Eliminar.
  3. Borrar Tabla de DynamoDB: En la consola de Amazon DynamoDBselecciona Tabla a borrar y luego selecciona Eliminar.
  4. Borrar AWS IAM Role: en la consola de AWS IAM en el menú de la izquierda selecciona Roles, y pega en el buscador el nombre del role que copiaste en el paso anterior, presiona la tecla Enter, selecciónalo y luego Eliminar.

Conclusiones:

En este nuevo episodio desbloqueaste una nueva habilidad: Creación de API REST para consultar de forma segura y escalable el recomendador de anime creado en el episodio anterior.

Usaste el servicio Amazon API Gateway para crear recursos y métodos que invocan las funciones de AWS Lambda con el código para consultar a Amazon Personalize, y las respuesta recibidas las fueron complementadas con la información general de los animes que almacenados en Amazon DynamoDB, como resultado obtuviste un JSON con la información completa de los animes recomendados.

Además, creaste una API para el Event Tracker, que te permite alimentar al modelo de recomendaciones con nuevas interacciones, y así entregue recomendaciones actualizadas considerando la actividad de los usuarios.

Te invito a continuar experimentando con estos servicios, creando aplicaciones para que sigas desbloqueando nuevas habilidades. En Amazon API Gateway tutorials and workshops puedes conseguir nuevos proyectos.

Pronto una nueva entrega de Recomendaciones personalizadas de Anime para que terminemos nuestra aplicación web de recomendaciones de anime.


Acerca de la autora

Elizabeth Fuentes Leone es Developer Advocate en AWS con experiencia en Data Analytics y Machine Learning. Le encanta ayudar a los desarrolladores a aprender mientras meten las manos construyendo.