Automatiza MLOps con GitHub Actions: CI/CD para ML
En la ingeniería de software moderna, las tuberías de CI/CD son la base de la entrega de software eficiente y fiable. Sin embargo, cuando el activo que se está entregando es un modelo de aprendizaje automático, el paradigma tradicional de CI/CD resulta insuficiente. El ciclo de vida único de los modelos de aprendizaje automático – que abarca la validación de datos, el entrenamiento y la supervisión del rendimiento – requiere un enfoque especializado conocido como MLOps.
Este artículo proporciona una guía completa y práctica para directores de ingeniería (CTOs) y ingenieros senior, que abarca la arquitectura e implementación de un robusto pipeline CI/CD para modelos de aprendizaje automático utilizando GitHub Actions. Pasaremos de la teoría a ejemplos de código y patrones arquitectónicos concretos que pueden implementar directamente. El enfoque estará en automatizar todo el proceso, desde el commit de código hasta un endpoint de modelo contenedorizado y listo para producción.
Visión general arquitectónica: La línea de flujo de CI/CD de MLOps
El principal desafío en MLOps es gestionar el conjunto de código, datos y modelo como una sola y coherente unidad. Nuestra plataforma debe automatizar procesos que a menudo son manuales y propensos a errores, garantizando la reproducibilidad y el cumplimiento.
Servicios de Ingeniería de LLM y IA
Ofrecemos un conjunto completo de soluciones impulsadas por IA, incluyendo IA generativa, visión artificial, aprendizaje automático, procesamiento del lenguaje natural y automatización con IA.
La arquitectura que construiremos se activa mediante un git push a la rama principal y consta de dos etapas principales orquestadas por GitHub Actions:
- Integración Continua (CI) y Formación Continua (CT): Esta fase es responsable de validar todo el sistema de aprendizaje automático. Incluye:
- Validación del código: Revisión y ejecución de pruebas unitarias en el código fuente del modelo (p. ej., preprocesamiento de datos, ingeniería de características).
- Validación de datos: Asegurar que los datos de entrenamiento cumplen con un esquema y distribución esperados.
- Entrenamiento y evaluación del modelo: Entrenar el modelo en un conjunto de datos versionado y evaluar su rendimiento en función de métricas predefinidas (p. ej., precisión, F1-score). Si el rendimiento cumple con el umbral, el modelo entrenado se versiona y se guarda.
- Generación de artefactos: El modelo serializado, las métricas de rendimiento y cualquier otro activo necesario se empaquetan como artefactos de construcción.
- Entrega Continua (CD): Esta fase se centra en empaquetar y desplegar el modelo validado.
- Contenedorización: Crear una imagen de Docker que contenga el modelo y una capa de servicio (p. ej., una aplicación FastAPI).
- Publicación de la imagen: Subir la imagen de Docker versionada a un registro de contenedores (p. ej., GitHub Container Registry, Docker Hub, AWS ECR).
- Despliegue: Desplegar automáticamente el contenedor en un entorno de destino, como un clúster de Kubernetes o un servicio de contenedor en la nube.
Esta separación garantiza que solo los modelos que pasan por rigurosas pruebas automatizadas se consideren para su implementación, minimizando el riesgo de introducir errores en el entorno de producción.
Implementación paso a paso
Vamos a proceder con una implementación práctica. Utilizaremos un modelo simple de Scikit-learn, pero los principios son directamente aplicables a modelos más complejos construidos con TensorFlow, PyTorch u otros frameworks.
Estructura del repositorio
Un repositorio bien organizado es fundamental para un proyecto de MLOps de gestión.
/
├── .github/
│ └── workflows/
│ └── ci-cd.yml # GitHub Actions workflow definition
├── data/ # Raw data (managed by DVC)
├── models/ # Output for serialized models
├── src/
│ ├── __init__.py
│ ├── train.py # Model training and evaluation script
│ └── serve.py # API server for model inference
├── tests/
│ └── test_model.py # Unit tests for our code
├── requirements.txt # Python dependencies
└── Dockerfile # Docker definition for the serving image
Control de versiones de datos y modelos con DVC
Gestionar grandes conjuntos de datos y archivos de modelos directamente en Git es poco práctico. Utilizaremos Control de Versiones de Datos (DVC) para ello. DVC almacena punteros a los datos/modelos en Git, mientras que los archivos reales se almacenan en el almacenamiento de objetos remoto (como S3, GCS o incluso una unidad de red compartida).
Para inicializar DVC y realizar un seguimiento de nuestros datos:
# Install DVC
pip install dvc dvc-s3
# Initialize DVC in your Git repository
dvc init
# Configure remote storage
dvc remote add -d my-remote s3://your-bucket-name/dvc-store
# Add and track data
dvc add data/my_dataset.csv
git add data/my_dataset.csv.dvc .dvc/config
git commit -m "feat: Add initial dataset with DVC"
dvc push
Este proceso garantiza que cada commit de Git tenga una versión de los datos sobre los que se entrenó, que es permanente e inmutable.
El flujo de trabajo de CI/CD: ci-cd.yml
Este archivo es el núcleo de nuestra automatización. Define las tareas, los pasos y los disparadores para nuestro flujo de trabajo. Colócalo en github.com/tu_usuario/ci-cd.yml.
name: MLOps CI/CD Pipeline
on:
push:
branches:
- main
jobs:
build-and-test:
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.9'
- name: Install Dependencies
run: |
pip install -r requirements.txt
pip install dvc[s3] # Install DVC with S3 support
- name: Authenticate with AWS for DVC
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: us-east-1
- name: Pull Data with DVC
run: dvc pull
- name: Run Unit Tests
run: pytest tests/
- name: Train and Evaluate Model
id: train
run: python src/train.py
- name: Upload Model Artifact
uses: actions/upload-artifact@v4
with:
name: model
path: |
models/classifier.joblib
metrics.json
deploy:
needs: build-and-test
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Download Model Artifact
uses: actions/download-artifact@v4
with:
name: model
path: ./
# We assume the model is downloaded to a directory matching its name
# Move files to their correct locations for the Docker build context
- name: Prepare Docker Build Context
run: |
mkdir -p models
mv model/classifier.joblib models/
mv model/metrics.json ./
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and Push Docker Image
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ghcr.io/${{ github.repository }}:${{ github.sha }}
# Deployment step would go here. Example for a generic script execution.
# - name: Deploy to Production
# run: ./scripts/deploy.sh ghcr.io/${{ github.repository }}:${{ github.sha }}
Puntos clave en el flujo de trabajo:
- Información confidencial: Utilizamos
secrets.AWS_ACCESS_KEY_IDysecrets.GITHUB_TOKENpara la autenticación segura. Estos deben configurarse en la sección "Settings > Secrets y variables > Actions" de su repositorio. - Dependencias: La
tarea de construcción y pruebasdepende del éxito de latarea de despliegue(needs: build-and-test), lo que garantiza que solo se desplieguen modelos validados. - Artefactos:
actions/upload-artifactyactions/download-artifactson cruciales para pasar el modelo entrenado entre tareas, ya que cada tarea se ejecuta en un entorno limpio e aislado. - Etiquetado de imágenes: Etiquetamos la imagen de Docker con el SHA del commit de Git (
${{ github.sha }}). Esto proporciona un seguimiento explícito desde una imagen de contenedor desplegada hasta la versión exacta de código y datos que la produjeron.
Servicios de Ingeniería de LLM y IA
Ofrecemos una completa gama de soluciones impulsadas por la IA, que incluyen IA generativa, visión artificial, aprendizaje automático, procesamiento del lenguaje natural y automatización basada en IA.
Código de la aplicación principal
Guía de entrenamiento del modelo (src/train.py)
Este script gestiona el entrenamiento, la evaluación y la serialización.
# src/train.py
import pandas as pd
import joblib
import json
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score
# 1. Load Data
df = pd.read_csv('data/my_dataset.csv')
# Dummy preprocessing
X = df.drop('target', axis=1)
y = df['target']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 2. Train Model
model = RandomForestClassifier(n_estimators=100, random_state=42)
model.fit(X_train, y_train)
# 3. Evaluate Model
y_pred = model.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
print(f"Model Accuracy: {accuracy}")
# 4. Save Metrics
with open('metrics.json', 'w') as f:
json.dump({'accuracy': accuracy}, f)
# Performance Gate: Fail the build if accuracy is below a threshold
MINIMUM_ACCURACY = 0.85
if accuracy < MINIMUM_ACCURACY:
raise Exception(f"Model accuracy {accuracy} is below the threshold of {MINIMUM_ACCURACY}")
# 5. Serialize Model
joblib.dump(model, 'models/classifier.joblib')
print("Training complete. Model and metrics saved.")
Dockerfile para el servicio de modelos
Este Dockerfile crea una imagen de contenedor con nuestra aplicación FastAPI y el modelo entrenado.
# Dockerfile
FROM python:3.9-slim
WORKDIR /app
# Copy dependencies and install them
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Copy the application and model
COPY ./src /app/src
COPY ./models /app/models
# Expose port and define command
EXPOSE 8000
CMD ["uvicorn", "src.serve:app", "--host", "0.0.0.0", "--port", "8000"]
Servidor de API (src/serve.py)
Una sencilla aplicación FastAPI para cargar el modelo y realizar predicciones.
# src/serve.py
import joblib
from fastapi import FastAPI
from pydantic import BaseModel
from typing import List
app = FastAPI(title="ML Model Server")
# Define the input data schema
class ModelInput(BaseModel):
features: List[float]
# Load the trained model from the file system
model = joblib.load("models/classifier.joblib")
@app.post("/predict")
def predict(data: ModelInput):
"""Makes a prediction based on the input features."""
prediction = model.predict([data.features])
return {"prediction": int(prediction[0])}
@app.get("/")
def read_root():
return {"status": "ML model server is running."}
Consideraciones Avanzadas y Próximos Pasos
Esta plataforma proporciona una base sólida, pero un sistema de MLOps de nivel de producción implica más componentes.
- Registro de modelos: Para una gobernanza de modelos más robusta, integre un registro de modelos como MLflow o Weights & Biases. El pipeline de CI publicaría el modelo en el registro, que a su vez gestionaría el versionado, la etapa (por ejemplo, "staging", "producción") y el almacenamiento de metadatos. El pipeline de CD, a continuación, recuperaría una versión específica del modelo del registro para su implementación.
- Almacenes de características: En entornos complejos, un almacén de características centralizado Almacén de características (por ejemplo, Feast, Tecton) garantiza la consistencia en la ingeniería de características entre el entrenamiento y la inferencia, mitigando las diferencias entre el entorno online y offline.
- Monitoreo continuo: La implementación no es el paso final. Implemente el monitoreo tanto para métricas operativas (latencia, tasa de error) como para métricas de rendimiento del modelo (drift de concepto, drift de datos). Si el rendimiento disminuye, esto debería generar una alerta o iniciar una pipeline de reentrenamiento.
- Estrategias de implementación sofisticadas: En lugar de una implementación directa, considere versiones en "canario" o pruebas A/B. El pipeline de CD puede extenderse para implementar el nuevo modelo en un pequeño subconjunto del tráfico, comparar su rendimiento con el modelo existente y promover o revertir automáticamente según los resultados.
Conclusión
Al automatizar el ciclo de vida del aprendizaje automático con una plataforma CI/CD, transformamos el desarrollo de modelos de una actividad artesanal en un proceso de ingeniería disciplinado y repetible. Utilizando GitHub Actions, hemos demostrado una forma práctica, potente y accesible para implementar esta capacidad.
Este enfoque reduce significativamente el tiempo de lanzamiento de nuevos modelos, mejora la colaboración entre los equipos de ciencia de datos e ingeniería, y proporciona la gobernanza y la reproducibilidad necesarias para sistemas de ML de nivel empresarial. El marco presentado aquí no es simplemente un ejercicio teórico, sino un plan directo para construir una práctica de MLOps más madura dentro de su organización.
Preguntas frecuentes
¿Qué es MLOps y cómo se diferencia de los procesos CI/CD tradicionales?
MLOps es un enfoque especializado para las tuberías CI/CD adaptado a la vida útil única de los modelos de aprendizaje automático. A diferencia de los procesos CI/CD tradicionales, que se centran principalmente en el código, MLOps gestiona el conjunto de código, datos y modelos como una unidad coherente. Automatiza procesos únicos para el aprendizaje automático, como la validación de datos, el entrenamiento de modelos y la evaluación del rendimiento.
¿Cómo automatizan las acciones de GitHub una tubería de aprendizaje automático?
Las acciones de GitHub automatizan la tubería de ML utilizando un archivo YAML de flujo de trabajo, que se activa por eventos de Git (como un push). Este flujo de trabajo define una serie de tareas. Una tarea de Integración Continua/Entrenamiento Continuo (CI/CT) valida el código, prueba los datos y entrena el modelo. Si es exitoso, una tarea de Entrega Continua (CD) toma el control para construir una imagen de Docker del modelo, subirla a un registro y desplegarla como un punto final listo para la producción.
¿Por qué es importante el versionado de datos y modelos en MLOps?
El versionado de datos y modelos es crucial para la reproducibilidad y el control. Dado que los archivos de datos y los modelos grandes no pueden almacenarse directamente en Git, se utilizan herramientas como Data Version Control (DVC). DVC almacena archivos de puntero pequeños en Git que hacen referencia a archivos de datos grandes en el almacenamiento remoto (como S3). Esto garantiza que cada commit de Git tenga una versión inmutable de los datos en los que se entrenó, lo que hace que cada experimento sea rastreable y reproducible.