Mi viaje hacia una tubería de transformadores sin servidor en Google Cloud
'Mi experiencia con una tubería de transformadores sin servidor en Google Cloud'
Una publicación de blog de invitado por el miembro de la comunidad Maxence Dominici
En este artículo se discutirá mi experiencia al implementar el pipeline de análisis de sentimientos de transformers
en Google Cloud. Comenzaremos con una breve introducción a transformers
y luego pasaremos a la parte técnica de la implementación. Finalmente, resumiremos esta implementación y revisaremos lo que hemos logrado.
La meta
Quería crear un microservicio que detectara automáticamente si una reseña de un cliente dejada en Discord era positiva o negativa. Esto me permitiría tratar el comentario de acuerdo a eso y mejorar la experiencia del cliente. Por ejemplo, si la reseña era negativa, podría crear una función que contacte al cliente, se disculpe por la mala calidad del servicio e informe que nuestro equipo de soporte lo contactará lo antes posible para ayudarlo y, con suerte, solucionar el problema. Dado que no planeo recibir más de 2,000 solicitudes al mes, no impuse ninguna restricción de rendimiento en cuanto al tiempo y la escalabilidad.
La biblioteca Transformers
Al principio estaba un poco confundido cuando descargué el archivo .h5. Pensé que sería compatible con tensorflow.keras.models.load_model
, pero no fue el caso. Después de unos minutos de investigación, descubrí que el archivo era una verificación de pesos en lugar de un modelo de Keras. Después de eso, probé la API que ofrece Hugging Face y leí un poco más sobre la característica del pipeline que ofrecen. Como los resultados de la API y el pipeline fueron excelentes, decidí que podía servir el modelo a través del pipeline en mi propio servidor.
A continuación se muestra el ejemplo oficial de la página de GitHub de Transformers.
from transformers import pipeline
# Asignar un pipeline para el análisis de sentimientos
clasificador = pipeline('sentiment-analysis')
clasificador('Estamos muy contentos de incluir el pipeline en el repositorio de transformers.')
[{'label': 'POSITIVO', 'score': 0.9978193640708923}]
Implementar Transformers en Google Cloud
Elegí GCP porque es el entorno en la nube que utilizo en mi organización personal.
Paso 1 – Investigación
Ya sabía que podía usar un servicio de API como flask
para servir un modelo de transformers
. Busqué en la documentación de Google Cloud AI y encontré un servicio para alojar modelos de Tensorflow llamado AI-Platform Prediction. También encontré App Engine y Cloud Run allí, pero me preocupaba el uso de memoria en App Engine y no estaba muy familiarizado con Docker.
Paso 2 – Prueba en AI-Platform Prediction
Como el modelo no es un modelo guardado de TensorFlow “puro” sino una verificación, y no pude convertirlo en un modelo de TensorFlow “puro”, descubrí que el ejemplo en esta página no funcionaría. A partir de ahí, vi que podía escribir un código personalizado que me permitiera cargar el pipeline
en lugar de tener que manejar el modelo, lo cual parecía más fácil. También aprendí que podía definir una acción de pre-predicción y post-predicción, que podría ser útil en el futuro para el pre o post-procesamiento de los datos según las necesidades de los clientes. Seguí la guía de Google pero encontré un problema ya que el servicio aún está en beta y no todo es estable. Este problema se detalla aquí.
Paso 3 – Prueba en App Engine
Me mudé a App Engine de Google ya que es un servicio con el que estoy familiarizado, pero encontré un problema de instalación con TensorFlow debido a un archivo de dependencia del sistema que faltaba. Luego intenté con PyTorch, que funcionó con una instancia F4_1G, pero no pudo manejar más de 2 solicitudes en la misma instancia, lo cual no es realmente óptimo en cuanto al rendimiento.
Paso 4 – Prueba en Cloud Run
Finalmente, me mudé a Cloud Run con una imagen de Docker. Seguí esta guía para tener una idea de cómo funciona. En Cloud Run, pude configurar una mayor memoria y más vCPUs para realizar la predicción con PyTorch. Dejé de lado Tensorflow ya que PyTorch parece cargar el modelo más rápido.
Implementación del pipeline sin servidor
La solución final consta de cuatro componentes diferentes:
main.py
que maneja la solicitud al pipelineDockerfile
utilizado para crear la imagen que se implementará en Cloud Run.- Carpeta Modelo que tiene
pytorch_model.bin
,config.json
yvocab.txt
.- Modelo: DistilBERT base uncased finetuned SST-2
- Para descargar la carpeta del modelo, siga las instrucciones en el botón.
- No es necesario mantener el archivo
rust_model.ot
ni el archivotf_model.h5
, ya que utilizaremos PyTorch.
requirement.txt
para instalar las dependencias
El contenido en main.py
es muy simple. La idea es recibir una solicitud GET
que contiene dos campos. Primero, la reseña que se debe analizar, segundo, la clave de API para “proteger” el servicio. El segundo parámetro es opcional, lo utilicé para evitar configurar oAuth2 de Cloud Run. Después de proporcionar estos argumentos, cargamos el pipeline que se construye en función del modelo distilbert-base-uncased-finetuned-sst-2-english
(proporcionado anteriormente). Al final, se devuelve la mejor coincidencia al cliente.
import os
from flask import Flask, jsonify, request
from transformers import pipeline
app = Flask(__name__)
model_path = "./model"
@app.route('/')
def classify_review():
review = request.args.get('review')
api_key = request.args.get('api_key')
if review is None or api_key != "MyCustomerApiKey":
return jsonify(code=403, message="solicitud incorrecta")
classify = pipeline("sentiment-analysis", model=model_path, tokenizer=model_path)
return classify("eso fue genial")[0]
if __name__ == '__main__':
# Esto se utiliza solo al ejecutar localmente. Al implementar en Google Cloud
# Run, un proceso de servidor web como Gunicorn servirá la aplicación.
app.run(debug=False, host="0.0.0.0", port=int(os.environ.get("PORT", 8080)))
Luego, el DockerFile
que se utilizará para crear una imagen de Docker del servicio. Especificamos que nuestro servicio se ejecuta con python:3.7, y que también necesitamos instalar nuestros requisitos. Luego usamos gunicorn
para manejar nuestro proceso en el puerto 5000
.
# Use Python37
FROM python:3.7
# Permitir que las declaraciones y mensajes de registro aparezcan de inmediato en los registros de Knative
ENV PYTHONUNBUFFERED True
# Copiar requirements.txt a la imagen de Docker e instalar paquetes
COPY requirements.txt /
RUN pip install -r requirements.txt
# Establecer el WORKDIR en la carpeta
COPY . /app
# Exponer el puerto 5000
EXPOSE 5000
ENV PORT 5000
WORKDIR /app
# Usar gunicorn como punto de entrada
CMD exec gunicorn --bind :$PORT main:app --workers 1 --threads 1 --timeout 0
Es importante tener en cuenta los argumentos --workers 1 --threads 1
, lo que significa que quiero ejecutar mi aplicación en solo un trabajador (= 1 proceso) con un solo hilo. Esto se debe a que no quiero tener 2 instancias activas a la vez porque podría aumentar la facturación. Una de las desventajas es que llevará más tiempo procesar si el servicio recibe dos solicitudes al mismo tiempo. Después de eso, limito a un solo hilo debido al uso de memoria necesario para cargar el modelo en el pipeline. Si estuviera usando 4 hilos, podría tener 4 Gb / 4 = 1 Gb solo para realizar el proceso completo, lo cual no es suficiente y daría lugar a un error de memoria.
Por último, el archivo requirement.txt
Flask==1.1.2
torch===1.7.1
transformers~=4.2.0
gunicorn>=20.0.0
Instrucciones de implementación
Primero, necesitarás cumplir algunos requisitos como tener un proyecto en Google Cloud, habilitar la facturación e instalar el cli gcloud
. Puedes encontrar más detalles al respecto en la guía de Google – Antes de comenzar.
Segundo, necesitamos construir la imagen de Docker y desplegarla en Cloud Run seleccionando el proyecto correcto (reemplaza ID-DEL-PROYECTO
) y establecer el nombre de la instancia, como ai-customer-review
. Puedes encontrar más información sobre el despliegue en la guía de Google – Desplegando en.
gcloud builds submit --tag gcr.io/ID-DEL-PROYECTO/ai-customer-review
gcloud run deploy --image gcr.io/ID-DEL-PROYECTO/ai-customer-review --platform managed
Después de unos minutos, también necesitarás aumentar la memoria asignada a tu instancia de Cloud Run de 256 MB a 4 GB. Para hacerlo, dirígete a la Consola de Cloud Run de tu proyecto.
Allí deberías encontrar tu instancia, haz clic en ella.
Después de eso, tendrás un botón azul etiquetado como “editar y desplegar nueva revisión” en la parte superior de la pantalla, haz clic en él y se te pedirán muchas configuraciones. En la parte inferior deberías encontrar una sección de “Capacidad” donde puedes especificar la memoria.
Rendimiento
El manejo de una solicitud toma menos de cinco segundos desde el momento en que envías la solicitud, incluyendo la carga del modelo en el pipeline y la predicción. El inicio en frío puede tomar unos 10 segundos adicionales más o menos.
Podemos mejorar el rendimiento del manejo de solicitudes calentando el modelo, es decir, cargándolo al inicio en lugar de en cada solicitud (por ejemplo, variable global), al hacerlo, ganamos tiempo y uso de memoria.
Costos
Simulé el costo basado en la configuración de la instancia de Cloud Run con el simulador de precios de Google
Para mi micro-servicio, planeo cerca de 1,000 solicitudes por mes, de manera optimista. 500 es más probable para mi uso. Es por eso que consideré 2,000 solicitudes como un límite superior al diseñar mi microservicio. Debido a ese bajo número de solicitudes, no me preocupé tanto por la escalabilidad, pero podría volver a ello si mis facturas aumentan.
No obstante, es importante destacar que pagarás el almacenamiento por cada gigabyte de tu imagen de construcción. Es aproximadamente €0.10 por Gb por mes, lo cual está bien si no mantienes todas tus versiones en la nube, ya que mi versión es ligeramente superior a 1 Gb (Pytorch para 700 Mb y el modelo para 250 Mb).
Conclusión
Al utilizar el pipeline de análisis de sentimientos de Transformers, ahorré una cantidad no despreciable de tiempo. En lugar de entrenar/ajustar un modelo, pude encontrar uno listo para ser utilizado en producción y comenzar el despliegue en mi sistema. Tal vez lo ajuste en el futuro, pero como se muestra en mi prueba, ¡la precisión ya es increíble! Me hubiera gustado tener un modelo “puro de TensorFlow” o al menos una forma de cargarlo en TensorFlow sin dependencias de Transformers para usar la plataforma de IA. También sería genial tener una versión ligera.