Inicio / Inteligencia Artificial / AI Engineering Pro / MLOps: CI/CD para Modelos de IA

MLOps: CI/CD para Modelos de IA

Pipelines CI/CD, quality gates, versionado de prompts y rollback.

Avanzado
🔒 Solo lectura
📖

Estás en modo lectura

Puedes leer toda la lección, pero para marcar progreso, hacer ejercicios y ganar XP necesitas una cuenta Pro.

Desbloquear por $9/mes

MLOps Fundamentals: CI/CD para Modelos de IA

¿Qué es MLOps / LLMOps?

MLOps aplica prácticas de DevOps al ciclo de vida de modelos de Machine Learning. LLMOps es su evolución para aplicaciones basadas en LLMs, donde el "modelo" no se entrena desde cero sino que se orquesta, se configura con prompts, y se conecta con herramientas.

DevOps:    Code ──► Build ──► Test ──► Deploy ──► Monitor
MLOps:     Data ──► Train ──► Eval ──► Deploy ──► Monitor
LLMOps:    Prompt ──► Chain ──► Eval ──► Deploy ──► Monitor

CI/CD Pipeline para Aplicaciones de IA

GitHub Actions: Pipeline Completo

# .github/workflows/ai-service-ci.yml
name: AI Service CI/CD

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]

env:
  AWS_REGION: us-east-1
  ECR_REPOSITORY: rag-api
  ECS_CLUSTER: ai-production

jobs:
  # ── 1. Lint y Tests Unitarios ──────────────────────────
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Setup Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.12"

      - name: Install dependencies
        run: |
          pip install -r requirements.txt
          pip install -r requirements-dev.txt

      - name: Lint
        run: |
          ruff check .
          mypy src/ --ignore-missing-imports

      - name: Unit tests
        run: pytest tests/unit/ -v --cov=src --cov-report=xml

      - name: Upload coverage
        uses: codecov/codecov-action@v4

  # ── 2. Tests de Integración ────────────────────────────
  integration:
    needs: test
    runs-on: ubuntu-latest
    services:
      qdrant:
        image: qdrant/qdrant:latest
        ports: ["6333:6333"]
      redis:
        image: redis:7
        ports: ["6379:6379"]

    steps:
      - uses: actions/checkout@v4
      - name: Setup Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.12"

      - name: Install dependencies
        run: pip install -r requirements.txt -r requirements-dev.txt

      - name: Integration tests
        env:
          QDRANT_HOST: localhost
          REDIS_HOST: localhost
        run: pytest tests/integration/ -v --timeout=60

  # ── 3. Evaluación de Calidad de IA ────────────────────
  evaluation:
    needs: integration
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Setup Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.12"

      - name: Install dependencies
        run: pip install -r requirements.txt -r requirements-dev.txt

      - name: Run AI evaluation suite
        env:
          OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
        run: |
          python -m pytest tests/evaluation/ -v \
            --tb=short \
            --junitxml=eval-results.xml

      - name: Check quality gates
        run: |
          python scripts/check_quality_gates.py eval-results.xml \
            --min-faithfulness 0.85 \
            --min-relevancy 0.80 \
            --max-hallucination 0.05

  # ── 4. Build y Push Docker ─────────────────────────────
  build:
    needs: [integration, evaluation]
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    outputs:
      image_tag: ${{ steps.meta.outputs.tags }}
    steps:
      - uses: actions/checkout@v4

      - name: Configure AWS
        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: ${{ env.AWS_REGION }}

      - name: Login to ECR
        uses: aws-actions/amazon-ecr-login@v2

      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          push: true
          tags: |
            ${{ env.ECR_REGISTRY }}/${{ env.ECR_REPOSITORY }}:${{ github.sha }}
            ${{ env.ECR_REGISTRY }}/${{ env.ECR_REPOSITORY }}:latest

  # ── 5. Deploy ──────────────────────────────────────────
  deploy:
    needs: build
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    environment: production
    steps:
      - name: Deploy to ECS
        uses: aws-actions/amazon-ecs-deploy-task-definition@v1
        with:
          task-definition: task-definition.json
          service: rag-api
          cluster: ${{ env.ECS_CLUSTER }}
          wait-for-service-stability: true

Quality Gates para IA

# scripts/check_quality_gates.py
import sys
import xml.etree.ElementTree as ET

def check_gates(results_file, thresholds):
    tree = ET.parse(results_file)
    root = tree.getroot()

    failures = []

    for testcase in root.iter("testcase"):
        name = testcase.get("name", "")
        # Extraer métricas de los test results
        properties = {p.get("name"): float(p.get("value", 0))
                      for p in testcase.findall(".//property")}

        if "faithfulness" in properties:
            if properties["faithfulness"] < thresholds["min_faithfulness"]:
                failures.append(
                    f"FAIL: faithfulness {properties['faithfulness']:.2f} "
                    f"< {thresholds['min_faithfulness']}"
                )

    if failures:
        print("❌ Quality gates FAILED:")
        for f in failures:
            print(f"  {f}")
        sys.exit(1)

    print("✅ All quality gates passed")

Versionado de Prompts

# Prompts versionados junto al código
"""
prompts/
├── v1/
│   ├── rag_system.txt
│   └── agent_system.txt
├── v2/
│   ├── rag_system.txt      # Mejorado tras eval
│   └── agent_system.txt
└── current -> v2/           # Symlink a versión activa
"""

class PromptManager:
    def __init__(self, prompts_dir: str = "prompts/current"):
        self.dir = prompts_dir
        self._cache = {}

    def get(self, name: str) -> str:
        if name not in self._cache:
            path = f"{self.dir}/{name}.txt"
            with open(path) as f:
                self._cache[name] = f.read()
        return self._cache[name]

    def render(self, name: str, **kwargs) -> str:
        template = self.get(name)
        return template.format(**kwargs)

Rollback Strategy

# Canary deployment para IA
# 1. Desplegar la nueva versión al 10% del tráfico
# 2. Monitorear métricas de calidad durante 30 min
# 3. Si calidad OK → progresivamente subir a 100%
# 4. Si calidad cae → rollback automático

# ECS con CodeDeploy traffic shifting
deploy:
  type: CodeDeployDefault.ECSCanary10Percent5Minutes
  alarm:
    - AIQualityAlarm      # faithfulness < 85%
    - HighLatencyAlarm    # p99 > 30s
    - HighErrorRateAlarm  # error rate > 5%

Resumen

MLOps/LLMOps para IA en producción:

  1. CI/CD pipeline — lint, unit tests, integration tests, eval, build, deploy
  2. Quality gates — métricas mínimas de calidad antes de deploy
  3. Versionado de prompts — tratar prompts como código
  4. Canary deploys — despliegue gradual con rollback automático
  5. Monitoreo post-deploy — alertas de calidad, latencia y costo

🧠 Preguntas de Repaso

1. ¿Cuál es la diferencia fundamental entre MLOps tradicional y LLMOps?

  • A) LLMOps es más barato que MLOps
  • B) En MLOps se entrena el modelo (Data → Train → Eval → Deploy); en LLMOps el modelo no se entrena, se orquesta con prompts y herramientas (Prompt → Chain → Eval → Deploy)
  • C) MLOps solo funciona con Python, LLMOps con cualquier lenguaje
  • D) No hay diferencia, LLMOps es otro nombre para MLOps

Respuesta: B) — MLOps se centra en el ciclo de vida de entrenamiento de modelos. LLMOps es la evolución para apps con LLMs donde el modelo (GPT-4, Claude) ya viene pre-entrenado y lo que se gestiona son prompts, chains, herramientas y evaluaciones.

2. En un pipeline CI/CD para IA, ¿qué son los "Quality Gates" y qué pasa si no se cumplen?

  • A) Son tests de velocidad de la aplicación
  • B) Son umbrales mínimos de calidad (ej: faithfulness ≥0.85, hallucination ≤5%) que se verifican automáticamente, y si no se cumplen el pipeline falla y no se despliega
  • C) Son aprobaciones manuales del equipo de QA
  • D) Son indicadores de uso de memoria

Respuesta: B) — Los quality gates son umbrales automáticos: --min-faithfulness 0.85, --min-relevancy 0.80, --max-hallucination 0.05. Si alguna métrica no pasa, el script retorna sys.exit(1) y el pipeline falla, evitando deployment de versiones de baja calidad.

3. ¿Qué significa el canary deployment CodeDeployDefault.ECSCanary10Percent5Minutes?

  • A) Se despliega al 10% de los usuarios durante 5 minutos, y si no hay alarmas se completa el deployment al 100%
  • B) Se reinicia el 10% de los containers cada 5 minutos
  • C) Se reduce la capacidad al 10% durante 5 minutos de mantenimiento
  • D) Se prueban 10 endpoints diferentes en 5 minutos

Respuesta: A) — Canary deployment envía 10% del tráfico a la nueva versión durante 5 minutos. Si las alarmas (faithfulness <85%, latencia p99 >30s, error rate >5%) no se activan, se completa el deployment. Si alguna alarma se activa, se hace rollback automático.

4. ¿Por qué se recomienda tratar los prompts como código con versionado en directorio?

  • A) Porque los prompts cambian con más frecuencia que el código y necesitan rollback rápido
  • B) Para que el editor los resalte con syntax highlighting
  • C) Porque Git no puede versionar strings en código Python
  • D) Solo por convención, no hay beneficio real

Respuesta: A) — Los prompts son el componente que más cambia en sistemas LLM. Versionarlos en directorio (prompts/v1/, prompts/v2/, prompts/current → symlink) permite rollback instantáneo, auditoría de cambios, y desvincula los cambios de prompts del deployment de código.

¿Te gustó esta lección?

Con Pro puedes marcar progreso, hacer ejercicios, tomar quizzes, ganar XP y obtener tu constancia.

Ver planes desde $9/mes