Limitación de Tasa en APIs de IA: Cómo Funciona y Cómo Manejarla
Cada API de IA tiene límites de tasa. Alcanzarlos durante el desarrollo es molesto. Alcanzarlos en producción hace que tus usuarios vean errores. Entender cómo funcionan los límites de tasa según el proveedor y construir una lógica adecuada de reintentos es la diferencia entre una demo y una aplicación en producción.
Cómo Te Limita Cada Proveedor
OpenAI
OpenAI utiliza límites de tasa escalonados basados en el historial de uso y nivel de pago de tu cuenta.
| Nivel | RPM (Solicitudes/Min) | TPM (Tokens/Min) | Cómo Alcanzarlo |
|---|---|---|---|
| Gratis | 3 | 40,000 | Cuenta nueva |
| Nivel 1 | 500 | 200,000 | $5 pagados |
| Nivel 2 | 5,000 | 2,000,000 | $50 pagados |
| Nivel 3 | 5,000 | 10,000,000 | $100 pagados |
| Nivel 4 | 10,000 | 50,000,000 | $250 pagados |
| Nivel 5 | 10,000 | 300,000,000 | $1,000 pagados |
Los límites son por modelo. Usar GPT-4.1 no consume tu cuota de GPT-4.1-mini.
Anthropic
Anthropic usa un sistema de niveles similar con límites tanto de RPM como de TPM. También aplica un límite diario de tokens en los niveles inferiores.
Google (Gemini)
Google AI Studio tiene límites por modelo. El nivel gratuito es generoso en solicitudes diarias pero estricto en la tasa por minuto (15 RPM para Gemini 2.5 en nivel gratuito).
Plataformas Agregadoras
Agregadores como LemonData y OpenRouter añaden su propia capa de limitación de tasa encima de los límites de los proveedores. LemonData usa límites basados en roles:
| Rol | RPM |
|---|---|
| Usuario | 1,000 |
| Socio | 3,000 |
| VIP | 10,000 |
La ventaja: los límites de los agregadores suelen ser más altos que los niveles gratuitos de proveedores individuales, y el enrutamiento multicanal significa que si un canal upstream está limitado, la solicitud se redirige a otro.
Lectura de Encabezados de Límite de Tasa
Todos los proveedores principales devuelven información de límite de tasa en los encabezados de respuesta:
x-ratelimit-limit-requests: 500
x-ratelimit-remaining-requests: 499
x-ratelimit-reset-requests: 60s
x-ratelimit-limit-tokens: 200000
x-ratelimit-remaining-tokens: 199500
Usa estos encabezados de forma proactiva. No esperes a un error 429 para reducir la velocidad.
Construyendo Lógica de Reintentos
La Forma Incorrecta
# No hagas esto
import time
def call_api(messages):
while True:
try:
return client.chat.completions.create(
model="gpt-4.1",
messages=messages
)
except Exception:
time.sleep(1) # Retardo fijo, sin backoff, captura todo
Problemas: no hay backoff exponencial, captura errores no reintentables, no hay límite máximo de reintentos, no hay jitter.
La Forma Correcta
import time
import random
from openai import RateLimitError, APIError, APIConnectionError
def call_with_retry(messages, model="gpt-4.1", max_retries=3):
"""Reintenta con backoff exponencial y jitter."""
for attempt in range(max_retries + 1):
try:
return client.chat.completions.create(
model=model,
messages=messages
)
except RateLimitError as e:
if attempt == max_retries:
raise
# Usa retry_after de la respuesta si está disponible
wait = getattr(e, 'retry_after', None)
if wait is None:
wait = (2 ** attempt) + random.uniform(0, 1)
print(f"Limitado por tasa. Esperando {wait:.1f}s (intento {attempt + 1})")
time.sleep(wait)
except APIConnectionError:
if attempt == max_retries:
raise
wait = (2 ** attempt) + random.uniform(0, 1)
time.sleep(wait)
except APIError as e:
# No reintentar errores de cliente (400, 401, 403)
if e.status_code and 400 <= e.status_code < 500:
raise
if attempt == max_retries:
raise
time.sleep((2 ** attempt) + random.uniform(0, 1))
Principios clave:
- Backoff exponencial: 1s, 2s, 4s, 8s
- Jitter: 0-1s aleatorio añadido para evitar el efecto avalancha
- Respetar el encabezado
retry_aftercuando se proporciona - No reintentar errores de cliente (solicitud incorrecta, fallo de autenticación)
- Establecer un conteo máximo de reintentos
Versión Asíncrona
import asyncio
import random
from openai import AsyncOpenAI, RateLimitError
async_client = AsyncOpenAI(
api_key="sk-lemon-xxx",
base_url="https://api.lemondata.cc/v1"
)
async def call_with_retry_async(messages, model="gpt-4.1", max_retries=3):
for attempt in range(max_retries + 1):
try:
return await async_client.chat.completions.create(
model=model,
messages=messages
)
except RateLimitError:
if attempt == max_retries:
raise
wait = (2 ** attempt) + random.uniform(0, 1)
await asyncio.sleep(wait)
Avanzado: Limitador de Tasa Token Bucket
Para aplicaciones de alto rendimiento, implementa limitación de tasa del lado cliente para evitar alcanzar los límites del servidor:
import time
import asyncio
class TokenBucket:
def __init__(self, rate: float, capacity: int):
self.rate = rate # tokens por segundo
self.capacity = capacity # tamaño máximo de ráfaga
self.tokens = capacity
self.last_refill = time.monotonic()
async def acquire(self, tokens: int = 1):
while True:
now = time.monotonic()
elapsed = now - self.last_refill
self.tokens = min(
self.capacity,
self.tokens + elapsed * self.rate
)
self.last_refill = now
if self.tokens >= tokens:
self.tokens -= tokens
return
# Esperar a tener suficientes tokens
wait = (tokens - self.tokens) / self.rate
await asyncio.sleep(wait)
# 500 solicitudes por minuto = ~8.3 por segundo
limiter = TokenBucket(rate=8.0, capacity=20)
async def rate_limited_call(messages, model="gpt-4.1"):
await limiter.acquire()
return await async_client.chat.completions.create(
model=model,
messages=messages
)
Fallback de Modelo ante Límites de Tasa
Cuando tu modelo principal está limitado, usa un modelo alternativo:
FALLBACK_CHAIN = [
"claude-sonnet-4-6",
"gpt-4.1",
"gpt-4.1-mini",
]
async def call_with_fallback(messages):
for model in FALLBACK_CHAIN:
try:
return await async_client.chat.completions.create(
model=model,
messages=messages
)
except RateLimitError:
continue
raise Exception("Todos los modelos están limitados por tasa")
Aquí es donde los agregadores de API brillan. Con más de 300 modelos detrás de un solo endpoint, siempre tienes un fallback disponible.
Monitoreo del Uso de Límites de Tasa
Controla tu consumo de límites de tasa para detectar problemas antes de que afecten a los usuarios:
import logging
def log_rate_limits(response):
headers = response.headers
remaining = headers.get("x-ratelimit-remaining-requests")
limit = headers.get("x-ratelimit-limit-requests")
if remaining and int(remaining) < int(limit) * 0.1:
logging.warning(
f"Advertencia de límite de tasa: quedan {remaining}/{limit} solicitudes"
)
Configura alertas cuando la capacidad restante caiga por debajo del 10%. Esto te da tiempo para implementar throttling antes de que los usuarios vean errores 429.
Resumen
| Estrategia | Cuándo Usarla |
|---|---|
| Backoff exponencial | Siempre (base) |
| Limitador de tasa del lado cliente | Apps de alto rendimiento (>100 RPM) |
| Fallback de modelo | Apps en producción con requisitos SLA |
| Monitoreo proactivo | Cualquier despliegue en producción |
| API por lotes | Trabajos no en tiempo real |
El objetivo no es evitar los límites de tasa por completo. Es manejarlos con gracia para que tus usuarios nunca los noten.
Construye aplicaciones de IA resilientes: lemondata.cc ofrece enrutamiento multicanal que maneja automáticamente los límites upstream. Una clave API, más de 300 modelos.
