marzo 16, 2022
~ 5 MIN
DLOps - Despliegue
< Blog RSSDLOps - Despliegue
En este post vamos a aprender como desplegar nuestros modelos en producción. Para ello usaremos FastAPI, un framework de Python para el desarrollo de APIs, Docker para paquetizar la API y Heroku para desplegar la API en producción.
FastAPI
Si bien existen diferente frameworks para crear APIs en Python, como Flask por ejemplo, aquí vamos a usar FastAPI ya que nos ofrece un montón de funcionalidad que usaremos a lo largo de esta serie de posts. Si no conoces este proyecto, te recomiendo que navegues por su documentación.
Pudes instalar FastAPI con el comando
pip install fastapi[all].
Una vez instalado, crea un script llamado app.py con el siguiente contenido:
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def root():
return {"message": "Hello World"}
Ahora, puedes arrancar tu API en local con el comando uvicorn app:app --reload. Si todo va bien, deberías ver un mensaje similar a

Si ahora abres tu navegador y escribes http://localhost:8000/, deberás ver el mensaje devuelto por la API.
{
"message": "Hello World"
}
Sencillo, ¿verdad? Ahora simplemente tenemos que hacer que esta API (que como puedes ver no es más que un script de Python) carge nuestro modelo, reciba entradas (en nuestro caso imágenes) y devuelva las predicciones. Esto lo conseguiremos con el siguiente código:
from fastapi import FastAPI, File, UploadFile
from PIL import Image
import onnxruntime as ort
import numpy as np
import io
import math
app = FastAPI()
ort_session = ort.InferenceSession('models/binary_classifier_3.onnx')
TRHESHOLD = 0.5
@app.get("/")
async def root():
return {"message": "Hello World"}
def sigmoid(x):
return 1 / (1 + math.exp(-x))
@app.post("/predict")
async def predict(file: UploadFile = File(...)):
request_object_content = await file.read()
img = Image.open(io.BytesIO(request_object_content))
input = np.expand_dims(np.array(img, dtype=np.uint8), axis=0)
ort_inputs = {
"input": input
}
ort_output = ort_session.run(['output'], ort_inputs)[0]
output = sigmoid(ort_output)
return {
"proba": output,
"label": "3" if output > TRHESHOLD else "no 3"
}
Una de las ventajas que FastAPI ofrece es la de generación automática de documentación interactiva. Si visitas http://localhost:8000/docs, podrás probar tu nuevo endpoint al cual enviarle imágenes y recibir las predicciones del modelo. Siéntete libre de personalizar tu API a tu gusto 😁.
Docker
Una vez implementada la lógica de nuestra API es momento de desplegarla en la nube para que todo el mundo tenga acceso. Sin embargo, para facilitar este proceso, primero crearemos una imágen de Docker que contendrá el código de nuestra API y todas sus dependencias. Esto nos evitará dolores de cabeza a la hora de crear el entorno de producción adecuado (versión de sistema operativo, versión de dependencias, ...). Simplemente, si nuestro servidor tiene Docker instalado, será capaz de ejecutar nuestra API.
Puedes instalar
Dockersiguiendo las instrucciones.
Crea un archivo llamado Dockerfile con el siguiente contenido:
FROM continuumio/miniconda3
RUN conda install -y -c conda-forge \
pillow \
onnxruntime \
fastapi \
uvicorn \
python-multipart
COPY ./models /models
COPY ./app.py /app.py
CMD uvicorn app:app --host=0.0.0.0 --port=$PORT
Y, para crear la imagen de Docker, ejecuta el comando docker build -t dlops ., donde dlops es el nombre que le quieras dar a tu imagen. Ahora podrás ejectuar la imágen de Docker con el comando docker run -p 8000:8000 -e PORT=8000 dlops para arrancar la API.
Durante el desarrollo con
Dockerno es recomendable copiar directamente tu código fuente en el paso debuild, ya que si haces cambios estos no se reflejarán hasta que hagas un nuevobuild. Para ello te dejo como ejemplo el archivoDockerfile.devydocker-compose-yml, que "montan" el código como un volumen dentro de la imagenDockery por lo tanto estos cambios si se verán reflejados.
Heroku
El último paso es el de subir nuestra imagen de Docker a Heroku y ejectuarla para obtener ana url pública con la que tener acceso a nuestra API.
Puedes instalar la
CLIde Horeku siguiendo las instrucciones.
Lo primero que necesitaremos será logearnos en Heroku usando la CLI.
heroku login
Una vez logeados deberemos generar las credenciales necesarias para guardar nuestra imagen de Docker en el registro de Heroku
heroku container:login
Con el comando hrekou create podemos crear una nueva aplicación, de la cual obtendremos una url pública. Para desplegar nuestra apliación deberemos ejecutar el siguiente comando:
heroku container:push web -a <nombre>
donde <nombre> es el subdominio de la url generada en el paso anterior. La imagen de Docker se subirá al registro y ya podemos desplegarla con el comando
heroku container:release web -a <nombre>
¡Voilà! Nuestra API está desplegada y tenemos acceso a través de la url generada. Puedes probar a navegar a la documentación (recuerda el endpoint /docs que hemos visto antes) y probar tu modelo.
Resumen
En este post hemos visto como podemos crear una API en Python para servir nuestro modelo. Para ello hemos usado FastAPI, un framewrok con buen rendimiento y multitud de funcionalidad incluida. Hemos usado Docker para paquetizar nuestro modelo, código de la API y todas sus dependencias de manera que sea facilmente desplegable. Por último, hemos usado Heroku para subir nuestra API a la nube y obtener una url pública. Con esta url cualquier persona o aplicación puede acceder a nuestro modelo, enviando imágenes y recibiendo las predicciones.