> labs.luisguisado.cloud
Intermedio~60 min·por Luis Guisado·actualizado 16 de mayo de 2026

Cambiar el proveedor del modelo: OpenAI, Anthropic, Bedrock, Ollama

Corre el mismo crew con cuatro backends de modelo distintos cambiando solo una variable de entorno. Comparas costo, latencia, privacidad y fricción de setup. Confirmas que el agente es independiente del proveedor.

Bedrock

Costo estimado: free a poco según el proveedor

Aparece en: Agentic AI desde cero para Backend y Cloud Developers

Por qué este lab existe

Tu crew_setup.py del Lab 4 instancia el LLM así:

llm = LLM(
    model="groq/llama-3.3-70b-versatile",
    api_key=os.environ["GROQ_API_KEY"],
    temperature=0.3,
)

Funciona. Pero si mañana tu cliente exige que los datos no salgan de su VPC (Groq es cloud público) o si el bill crece y quieres probar un modelo más barato, tienes que tocar el archivo donde están los agentes para cambiar dónde corre el modelo. La identidad de los agentes (roles, goals, backstories) y la elección del proveedor viven mezcladas.

CrewAI usa por debajo litellm, una librería que abstrae más de 100 proveedores detrás de la misma interfaz. Cambiar de proveedor es cambiar el string del modelo y, a veces, las credenciales. El refactor de este lab te permite hacer ese cambio con una sola variable de entorno, sin tocar crew_setup.py ni tasks.py.

Duración: ~60 min · Nivel: Intermediate · Costo: gratis a poco según el proveedor.


Lo que vas a tener al terminar

  1. Un llm_factory.py que decide qué LLM instanciar leyendo la env var LLM_PROVIDER.
  2. Un crew_setup.py modificado que pide el LLM al factory en vez de hardcodearlo.
  3. Cuatro corridas validadas del mismo crew: Groq (default del Lab 4), OpenAI, Anthropic y Ollama local. Bedrock como opcional con AWS account.
  4. Una tabla comparativa real con costo por 1M tokens, dónde corre, fricción del setup y notas de calidad observada.

Qué vas a aprender

  • Aplicar Factory pattern para desacoplar el agente del proveedor del modelo.
  • Distinguir las tres categorías de cómo se accede a un LLM desde Python: dialecto OpenAI-compatible, SDK nativo, gateway agregador.
  • Configurar Amazon Bedrock con credenciales IAM y entender por qué su setup es distinto.
  • Comparar trade-offs reales de cuatro proveedores sobre el mismo caso de uso.

Conceptos clave

Tres categorías de cómo un cliente Python le habla a un LLM

Qué es: la diferencia entre las tres categorías es lo que determina cuánto código tienes que escribir por proveedor:

  1. Dialecto OpenAI-compatible. El proveedor expone el endpoint en el mismo formato JSON que OpenAI. Cliente único (el SDK openai), cambia solo el base_url y la key. Ejemplos: Groq, Cerebras, OpenRouter, Together. Visto en el Lab 1.
  2. SDK nativo. El proveedor tiene su propio SDK con su propio formato. Ejemplos: Anthropic (anthropic), Amazon Bedrock (boto3 con cliente bedrock-runtime). El payload, los nombres de los campos y la forma de las respuestas son distintos.
  3. Gateway agregador. Una librería que envuelve las dos categorías anteriores y expone una sola interfaz uniforme. El más usado es litellm. CrewAI lo trae como dependencia, por eso groq/llama-3.3-70b-versatile funciona sin que tú escribas el cliente.

Mini-ejemplo: tres caminos posibles para hablarle a Claude desde Python.

# 1. SDK nativo (formato propio de Anthropic)
from anthropic import Anthropic
client = Anthropic(api_key=...)
client.messages.create(model="claude-3-5-haiku-20241022", ...)

# 2. Dialecto OpenAI-compatible: no aplica a Anthropic.
# Anthropic no expone su API en formato OpenAI; necesitas un gateway.

# 3. Gateway (litellm directo, o vía CrewAI como en este lab)
from litellm import completion
completion(model="anthropic/claude-3-5-haiku-20241022", ...)

Factory pattern para el LLM

Qué es: un Factory (también fábrica en español) es una función que centraliza la decisión de qué objeto instanciar. En vez de que crew_setup.py decida directamente “uso Groq”, le pide al factory “dame el LLM configurado”. El factory lee LLM_PROVIDER del entorno y devuelve la instancia correcta. Cambiar de proveedor pasa a ser una variable de entorno, no un edit de código.

Mini-ejemplo:

# llm_factory.py
def get_llm():
    provider = os.environ.get("LLM_PROVIDER", "groq")
    if provider == "groq":
        return LLM(model="groq/llama-3.3-70b-versatile", ...)
    if provider == "openai":
        return LLM(model="gpt-4o-mini", ...)
    ...

Para profundizar: el Factory pattern viene de Design Patterns (Gamma, Helm, Johnson y Vlissides, 1994). En su forma original es una clase abstracta con métodos para crear familias de objetos. Acá usamos la versión simplificada (una función con if/elif), que es suficiente cuando el set de proveedores es chico y conocido. Si crece, conviene mover a un dict PROVIDERS = \{"groq": _make_groq, ...\} o a una clase con polimorfismo.


Mapa visual

   LLM_PROVIDER=groq        ┐
   LLM_PROVIDER=openai      │
   LLM_PROVIDER=anthropic   │── env var ─▶ llm_factory.get_llm() ─▶ LLM(...)
   LLM_PROVIDER=bedrock     │                       │
   LLM_PROVIDER=ollama      ┘                       ▼
                                          crew_setup.py
                                          (researcher, writer, reviewer)


                                          main.py: crew.kickoff()

crew_setup.py no sabe qué proveedor está activo. Tampoco lo saben tasks.py ni main.py. El “swap point” es una sola env var. Esa es la propiedad que demuestra que el agente es independiente del proveedor del modelo.


Punto de partida

Antes de refactorizar, verifica que el Lab 4 esté funcionando.

cd agentic-ai-lab
source .venv/bin/activate
python main.py

Respuesta esperada: el crew corre los tres agentes con Groq y produce un post final.

Si falla, regresa al Lab 4.


Sobre las versiones y los modelos

Validado al updatedAt: 2026-05-16:

  • crewai: mismo de Lab 4. litellm viene como dependencia transitiva.
  • boto3: requerido solo si vas a probar Bedrock. Última en pypi.org/project/boto3.
  • Modelos (verifica la lista vigente antes de correr; los proveedores cambian la oferta cada pocos meses):

Si un modelo fue deprecado al momento que corres el lab, los proveedores suelen indicar el reemplazo en su página de modelos.


Paso 1. Refactor a llm_factory.py

Archivo: llm_factory.py (NUEVO)

import os
from dotenv import load_dotenv
from crewai import LLM

load_dotenv()


def get_llm():
    """Instancia el LLM según LLM_PROVIDER. Default: groq."""
    provider = os.environ.get("LLM_PROVIDER", "groq").lower()

    if provider == "groq":
        return LLM(
            model="groq/llama-3.3-70b-versatile",
            api_key=os.environ["GROQ_API_KEY"],
            temperature=0.3,
        )

    if provider == "openai":
        return LLM(
            model="gpt-4o-mini",
            api_key=os.environ["OPENAI_API_KEY"],
            temperature=0.3,
        )

    if provider == "anthropic":
        return LLM(
            model="anthropic/claude-3-5-haiku-20241022",
            api_key=os.environ["ANTHROPIC_API_KEY"],
            temperature=0.3,
        )

    if provider == "bedrock":
        return LLM(
            model="bedrock/anthropic.claude-3-5-haiku-20241022-v1:0",
            aws_region_name=os.environ.get("AWS_REGION", "us-east-1"),
            temperature=0.3,
        )

    if provider == "ollama":
        return LLM(
            model="ollama/llama3.2",
            base_url=os.environ.get("OLLAMA_BASE_URL", "http://localhost:11434"),
            temperature=0.3,
        )

    raise ValueError(f"LLM_PROVIDER={provider!r} no soportado")

Notas:

  1. Default = groq, para que la corrida del Lab 4 siga funcionando sin tocar nada más.
  2. Bedrock no recibe api_key como string: usa las credenciales AWS configuradas en el shell (env vars o ~/.aws/credentials).
  3. Ollama lee OLLAMA_BASE_URL con fallback a localhost. Útil si en algún momento corres Ollama en otra máquina.
  4. Si pasas un valor no soportado en LLM_PROVIDER, falla con ValueError en vez de intentar invocar y recibir un error confuso del proveedor.

Archivo: crew_setup.py (MODIFICADO, solo el bloque del llm)

Reemplaza:

llm = LLM(
    model="groq/llama-3.3-70b-versatile",
    api_key=os.environ["GROQ_API_KEY"],
    temperature=0.3,
)

Por:

from llm_factory import get_llm

llm = get_llm()

El resto del archivo (los tres agentes) queda igual.

Probar:

python main.py

Respuesta esperada: el crew sigue corriendo con Groq (default), produce el mismo post final que en el Lab 4. Si así es, el refactor no rompió nada.


Paso 2. Swap a OpenAI

  1. Crea cuenta en platform.openai.com y genera una API key (requiere agregar crédito; no hay free tier).
  2. Agrega al .env:
OPENAI_API_KEY=sk-tu-valor-aqui
LLM_PROVIDER=openai
  1. Corre:
python main.py

Respuesta esperada: misma estructura de output, modelo distinto. En los logs de litellm ves ahora api.openai.com en vez de api.groq.com. El post final viene de gpt-4o-mini.

Coste: a la fecha de validación, gpt-4o-mini está en ~$0.15 / 1M input + ~$0.60 / 1M output. Una corrida del crew (~5k tokens) cuesta fracciones de centavo.


Paso 3. Swap a Anthropic

  1. Crea cuenta en console.anthropic.com y genera una API key. Anthropic requiere agregar crédito; los $5 iniciales alcanzan para muchas corridas.
  2. Agrega al .env:
ANTHROPIC_API_KEY=sk-ant-tu-valor-aqui
LLM_PROVIDER=anthropic
  1. Corre:
python main.py

Respuesta esperada: mismo crew, mismo flujo, ahora con Claude 3.5 Haiku. La calidad del post tiende a ser distinta: Claude suele ser más verboso en revisión. Si te molesta, ajusta el expected_output de review_task (vuelve al Lab 4 para editarlo).


Paso 4. Swap a Amazon Bedrock

Bedrock es un servicio AWS. Tienes tres requisitos previos: pedir acceso al modelo, tener credenciales AWS válidas y tener boto3 instalado (litellm lo usa por debajo).

  1. Habilita acceso al modelo Claude en Bedrock:

    • Consola AWS → Amazon BedrockModel access.
    • Solicita acceso a Claude 3.5 Haiku en la región que vas a usar. La aprobación para Anthropic en Bedrock suele ser inmediata o de minutos.
  2. Configura credenciales AWS (si todavía no las tienes):

aws configure
aws sts get-caller-identity   # confirma que las credenciales funcionan
  1. Instala boto3:
pip install boto3
  1. Agrega al .env:
AWS_REGION=us-east-1
LLM_PROVIDER=bedrock
  1. Corre:
python main.py

Respuesta esperada: el crew corre con Claude 3.5 Haiku, pero servido por Bedrock. La primera corrida tarda un poco más (cold start del modelo en Bedrock). Fíjate que en el .env no aparece BEDROCK_API_KEY: la autenticación va por las credenciales AWS estándar.

Si te sale AccessDeniedException: no aprobaron el acceso al modelo, o tu identidad IAM no tiene bedrock:InvokeModel. La política mínima del IAM es:

{
  "Effect": "Allow",
  "Action": "bedrock:InvokeModel",
  "Resource": "arn:aws:bedrock:us-east-1::foundation-model/anthropic.claude-3-5-haiku-20241022-v1:0"
}

Paso 5. Swap a Ollama local

Ollama corre modelos en tu máquina, sin proveedor en la nube. Los datos no salen de tu laptop. Costo cero. Latencia depende de tu hardware.

  1. Instala Ollama desde ollama.com/download.
  2. Descarga el modelo y arranca el daemon:
ollama pull llama3.2
ollama serve     # corre en background, escucha en :11434
  1. Agrega al .env:
LLM_PROVIDER=ollama
  1. Corre:
python main.py

Respuesta esperada: el crew corre 100% local. La calidad de llama3.2 (3B parámetros) es notablemente más baja que los modelos cloud anteriores: el post tiende a ser más genérico y a veces no respeta el formato pedido. Es el trade-off por correr sin nube en hardware modesto.

Para acercarte a la calidad de los modelos cloud, prueba ollama pull llama3.1:70b o ollama pull qwen2.5:32b. Necesitas hardware adecuado (~40 GB de RAM o una GPU con buena VRAM).


Paso 6. Tabla comparativa de los cinco proveedores

Después de correr el crew con cada proveedor vas a tener datos propios. Esta es la lectura validada al updatedAt: 2026-05-16:

Proveedor Modelo de la corrida Coste 1M tokens (in / out) Dónde corre Setup Notas
Groq Llama 3.3 70B $0 (free tier) Cloud (LPU propio) Email + key El más rápido. Free tier holgado pero no apto para producción.
OpenAI gpt-4o-mini $0.15 / $0.60 Cloud público Cuenta + crédito El más barato de los SaaS comparables. Calidad decente.
Anthropic Claude 3.5 Haiku $1.00 / $5.00 Cloud público Cuenta + crédito Mejor calidad subjetiva en revisión. Más caro por token.
Bedrock Claude 3.5 Haiku igual a Anthropic AWS (tu región) IAM + acceso al modelo Datos no salen de tu cuenta AWS. Setup con más fricción.
Ollama Llama 3.2 (3B) $0 Local (tu máquina) Instalar + pull Datos no salen de tu red. Calidad limitada por el hardware.

Cómo leerla:

  • Para prototipos sin restricciones: Groq (gratis y rápido).
  • Para producción con presupuesto ajustado: OpenAI gpt-4o-mini.
  • Para calidad alta en revisión y escritura: Anthropic (o Bedrock con el mismo modelo).
  • Para datos sensibles que no pueden salir de AWS: Bedrock.
  • Para datos que no pueden salir de tu red local: Ollama.

Errores comunes

Error 1. KeyError: 'OPENAI_API_KEY' al hacer swap

Síntoma: cambias LLM_PROVIDER=openai pero olvidas agregar la key del nuevo proveedor en .env. Python explota al instanciar el LLM.

Causa raíz: el factory hace os.environ["X"] sin fallback. Es a propósito: si falta la credencial, mejor fallar rápido (en el constructor) que enviar la request y recibir un 401 confuso.

Corrección: cada vez que cambies LLM_PROVIDER, asegúrate de que la key correspondiente esté presente en .env.

Error 2. litellm.exceptions.AuthenticationError con Bedrock

Síntoma: corres con LLM_PROVIDER=bedrock y litellm responde AuthenticationError: Could not connect to AWS Bedrock.

Causa raíz: no tienes credenciales AWS válidas en el shell, o aws configure no se ha corrido.

Corrección: verifica primero que el CLI tiene credenciales activas:

aws sts get-caller-identity

Si esto falla, configura las credenciales antes de seguir.

Error 3. Ollama responde “connection refused”

Síntoma: con LLM_PROVIDER=ollama la corrida falla con httpcore.ConnectError: All connection attempts failed.

Causa raíz: el daemon de Ollama no está corriendo (ollama serve no fue ejecutado, o se detuvo).

Corrección:

ollama serve     # déjalo corriendo en una terminal aparte
# en macOS también sirve abrir la app de Ollama desde el dock

Buenas prácticas

  • Configuración por entorno, no por código. El factory lee LLM_PROVIDER del entorno. Esto te permite tener el mismo binario corriendo en dev contra Groq y en producción contra Bedrock sin un solo if en el dominio. Ref: 12-Factor App · Config, aplicado desde el Lab 1.
  • Mismo expected_output para todos los proveedores. Distintos modelos tienen sesgos distintos: Claude tiende a ser verboso, Llama-3.2-3B improvisa formato, gpt-4o-mini se queda corto. Si quieres comparar calidad de forma justa, no cambies las tasks entre proveedores: el control va siempre en expected_output.
  • Mide costo por corrida, no solo por token. Una corrida del crew gasta tokens en 3 agentes y en la coordinación interna que CrewAI hace por debajo. El número que importa para tu negocio es costo total de una kickoff completa, no costo por 1M tokens del modelo. Loggea ambos. Ref: el patrón last_usage del Lab 2 escalado al resultado.token_usage del Crew (Lab 4).

Estado del proyecto al finalizar

agentic-ai-lab/
├── .venv/
├── .env                  ← MODIFICADO (LLM_PROVIDER + keys de los proveedores que probaste)
├── .gitignore
├── call_llm.py           ← sin cambios
├── tools.py              ← sin cambios
├── agent.py              ← sin cambios
├── llm_factory.py        ← NUEVO
├── crew_setup.py         ← MODIFICADO (usa get_llm() del factory)
├── tasks.py              ← sin cambios
├── main.py               ← sin cambios
└── summary.md            ← sin cambios

Checklist:

  • Cambiar LLM_PROVIDER en .env corre el crew contra un backend distinto sin tocar crew_setup.py.
  • Probaste al menos dos proveedores y comparaste sus outputs.
  • Bedrock funciona con credenciales AWS estándar (sin api_key en .env).
  • Ollama corre el crew con datos que no salen de tu máquina.

¿Qué viene en el Lab 6?

Hasta acá todo corre en tu laptop. Si quieres que el crew sirva tráfico real, persista logs, se autentique con IAM y escale sin que mantengas tu propia infra, necesitas llevarlo a la nube. En el Lab 6 vas a desplegar el sistema a Amazon Bedrock + AgentCore Runtime, el entorno serverless oficial de AWS para correr agentes. Vas a empaquetar la app, crear el IAM role del agente, exponer un endpoint y leer los logs de cada agent step en CloudWatch.


Referencias

Documentación oficial

Libros canónicos

  • Gamma, E., Helm, R., Johnson, R. & Vlissides, J. Design Patterns: Elements of Reusable Object-Oriented Software (1994): origen del Factory pattern aplicado en este lab.

Specs y estándares

Repositorios y librerías

  • BerriAI/litellm: el gateway que CrewAI usa por debajo. Su catálogo model_prices_and_context_window.json es referencia útil para coste por token.
  • boto3: SDK oficial de AWS para Python; litellm lo usa para hablar con Bedrock.