La interfaz de rerank no tiene un estándar unificado como Chat Completions, así que el mismo código puede devolver 404 o 422 al cambiar de proveedor. Al diagnosticar, conviene separar primero por código de estado HTTP y después ocuparse de los errores suaves, esos que devuelven 200 pero con un resultado incorrecto. Este artículo aborda cinco categorías —autenticación, conjunto de candidatos, limitación de tasa, tiempos de espera y resultados vacíos— y termina con un código de reintento reutilizable y una lista de registro. Los modelos y precios se rigen por la página de precios de modelos.
Nota: Cohere, Jina, Voyage y otros nombres son marcas de sus respectivos titulares; este artículo solo las menciona con fines técnicos. Las rutas de interfaz, los límites y los códigos de error pueden cambiar según la versión; consulta la documentación del proveedor correspondiente.
1. Distingue primero las cinco clases de problema
| Síntoma | Código de estado habitual | Causa típica | Orden de tratamiento |
|---|---|---|---|
| Fallo de autenticación | 401, 403 | Clave incorrecta, encabezado ausente, modelo no habilitado | Corregir primero credenciales y permisos |
| Solicitud rechazada | 400, 422 | Conjunto de candidatos demasiado grande, campos incompatibles, documento vacío | Revisar el cuerpo y los límites |
| Ruta incorrecta | 404 | Endpoint mal escrito, nombre de modelo antiguo, Base URL mal concatenada | Contrastar con la documentación del proveedor |
| Límite o cuota | 429 | Aumento súbito de concurrencia, clave compartida, tormenta de reintentos | Retroceso y reducción de concurrencia |
| Espera o error del upstream | 504, 5xx | Demasiados candidatos, documentos largos, upstream sobrecargado | Reducir la solicitud, reintentos limitados |
| Respuesta vacía | 200 | top_n inválido, campo mal leído, documentos filtrados | Añadir aserciones y alertas |
El registro debe incluir al menos: hora, endpoint, modelo, número de documentos, total de caracteres, top_n, código de estado, duración, número de reintentos y ID de solicitud. No registres la clave completa ni imprimas párrafos enteros del documento del usuario.
2. 401 y 403: primero autenticación, después permisos
El 401 indica que la identidad no se validó y normalmente no tiene relación con la capacidad del modelo ni con el saldo. Revisa en este orden:
- Si el encabezado usa Authorization: Bearer con la clave; algunas gateways exigen x-api-key.
- Si la clave tiene espacios, saltos de línea o comillas extra al principio o al final. Copiar desde una ventana de chat es la causa más común.
- Si una variable de entorno fue sobrescrita por la configuración local o por la plataforma de despliegue, y si producción y local usan claves distintas.
- Si la clave tiene habilitada la interfaz de rerank. Algunas cuentas solo tienen permiso de conversación y carecen de permiso para Rerank.
- Si el endpoint está mal escrito.
/v1/reranky/v2/rerankpueden tener formatos diferentes; concatenar directamente/reranka la Base URL del chat suele producir un 404 o un 401.
El 403 significa que la identidad es válida pero los permisos no alcanzan; revisa si el modelo está habilitado, si la IP está en la lista blanca, los permisos del proyecto y el estado de pago. No reintentes un 401: solo multiplica los registros de fallo y puede activar controles de riesgo. Primero valida con un curl mínimo y después vuelve al código de negocio.
3. 400 y 422: conjunto de candidatos grande y campos incompatibles
El conjunto de candidatos demasiado grande es la fuente más común de 400. Las interfaces gestionadas suelen tener límites para la cantidad de documentos por llamada, los tokens por documento y el tamaño del cuerpo. En el caso de Cohere, la recomendación es no superar los mil documentos por llamada y el truncado predeterminado es de 4096 tokens por documento; otros proveedores manejan cifras distintas que además cambian con la versión del modelo, así que hay que consultar su documentación antes de integrar. Cuando se supera el límite, la respuesta correcta no es reintentar a ciegas, sino:
- Dividir el conjunto de candidatos en fragmentos, reordenar cada uno por separado y combinar por puntaje.
- Controlar la cantidad de candidatos ya en la etapa de recuperación, por ejemplo entre cincuenta y doscientos.
- Dividir o truncar los documentos largos antes de enviarlos; no introduzcas un PDF completo en documents.
- Eliminar cadenas vacías, null, texto solo con espacios y documentos duplicados.
Los campos incompatibles también producen 400 o 422: escribir top_n donde va top_k o al revés; Jina y Cohere suelen usar top_n, mientras que Voyage usa top_k. Enviar documents como arreglo de objetos en lugar de arreglo de cadenas, o colocar id y text en el nivel equivocado. Cuando top_n supera la cantidad de documentos, algunas interfaces devuelven error y otras truncan automáticamente. Parámetros como return_documents, truncation y max_tokens_per_doc pueden no estar soportados por el proveedor actual. Los valores NaN o Infinity y los saltos de línea sin escapar en el JSON también provocan fallos de análisis.
Método de diagnóstico: conserva el cuerpo original de la solicitud con datos sensibles enmascarados y vuelve a añadir los parámetros uno a uno con un ejemplo mínimo, cambiando una sola variable cada vez.
4. 429: límites, cuotas y tormenta de reintentos
El 429 indica que la solicitud fue limitada o que la cuota se agotó. Las causas habituales son: solicitudes por segundo o concurrencia por encima del plan, cuota medida en tokens agotada en horas pico, varias aplicaciones compartiendo una misma clave, o reintentos del cliente sin retroceso. Revisa primero los encabezados Retry-After y los campos de cuota de la respuesta, y después decide si esperar o reducir la concurrencia.
Orden de tratamiento:
- Confirma si es un límite de una sola clave o una cuota a nivel de cuenta.
- Cambia los reintentos a retroceso exponencial con jitter aleatorio y respeta Retry-After.
- Limita la concurrencia y usa colas para suavizar los picos en lugar de reintentar sin fin.
- Mueve los trabajos por lotes a horas de baja demanda y separa la evaluación offline del tráfico en línea.
- Prepara una degradación para el negocio crítico: omitir el rerank y conservar el orden de recuperación.
No uses un reintento fijo cada segundo hasta saturar. Varias instancias reintentando a la vez forman una tormenta de reintentos que convierte un límite pequeño en una falla sostenida.
5. Tiempos de espera, 504 y 5xx
Los tiempos de espera deben separarse en tiempo de conexión y tiempo de lectura. El de conexión suele apuntar a problemas de red, DNS, proxy o TLS; el de lectura se relaciona más con un conjunto de candidatos demasiado grande, documentos largos, colas en el upstream o arranque en frío del modelo. Un 504 normalmente significa que la gateway no recibió respuesta del upstream, lo cual es distinto del tiempo de espera del cliente.
Orden de diagnóstico:
- Prueba con una solicitud mínima, una consulta y cinco documentos cortos, para confirmar que la red no está totalmente caída.
- Aumenta gradualmente la cantidad de documentos y localiza el punto donde el tiempo se dispara.
- Revisa la longitud por documento y el total de tokens, y trunca si es necesario.
- Comprueba si el tiempo de espera del cliente es menor que el tiempo de procesamiento del servidor.
- Haz reintentos limitados para 5xx y tiempos de espera; pasada la degradación, reduce la funcionalidad.
- Registra el ID de solicitud y el trace id que devuelve el upstream para poder conciliar con el proveedor.
El rerank normalmente no es una interfaz de streaming, así que no se puede ocultar una duración larga con salida progresiva. Para negocios sensibles a la latencia, conviene mover el rerank a una cadena asíncrona o reordenar solo las primeras decenas de candidatos.
6. Respuesta 200 con resultado vacío o incorrecto
Estos errores suaves son más difíciles de detectar: documents es un arreglo vacío y la interfaz devuelve un resultado vacío; top_n se estableció en 0 o en un número negativo; todos los documentos fueron excluidos por un filtro de negocio; se lee mal el campo de respuesta, porque algunas interfaces devuelven results y otras data; el index es la posición en el arreglo original de documentos, pero al dividir en fragmentos se olvidó sumar el desplazamiento; la semántica del puntaje cambia, con algunos modelos normalizando entre cero y uno y otros devolviendo logits, y la dirección del orden también puede diferir; la respuesta devuelve el cuerpo del documento en lugar del index y la deduplicación fusionó textos iguales.
Se recomienda añadir aserciones en el cliente: que la cantidad de resultados no supere top_n, que cada index esté dentro del rango válido y que los puntajes sean monótonos según la semántica del proveedor. Ante una anomalía, registra un resumen de la respuesta original; no devuelvas una lista vacía en silencio.
7. Un código de reintento reutilizable
El siguiente ejemplo divide los errores en tres clases: los de autenticación y parámetros no se reintentan, los 429 y 5xx se reintentan con retroceso, y los tiempos de espera tienen reintentos limitados; cuando se agotan, se degrada al orden de recuperación original.
import random
import time
import requests
def rerank(query, documents, top_n=10, model="<rerank-model>",
url="<base-url>/v1/rerank", api_key="<key>"):
payload = {"model": model, "query": query,
"documents": documents, "top_n": top_n}
headers = {"Authorization": f"Bearer {api_key}"}
last_error = None
for attempt in range(5):
try:
resp = requests.post(url, json=payload, headers=headers,
timeout=(3.05, 30))
except requests.Timeout as exc:
last_error = exc
time.sleep(min(2 ** attempt + random.random(), 20))
continue
if resp.status_code in (400, 401, 403, 404, 422):
raise RuntimeError(f"Sin reintento {resp.status_code}: {resp.text[:300]}")
if resp.status_code == 429 or resp.status_code >= 500:
retry_after = resp.headers.get("Retry-After")
wait = float(retry_after) if retry_after else min(
2 ** attempt + random.random(), 20)
time.sleep(wait)
last_error = RuntimeError(f"Reintentable {resp.status_code}")
continue
data = resp.json()
results = data.get("results") or data.get("data") or []
if not results:
return list(range(min(top_n, len(documents))))
return [item["index"] for item in results[:top_n]]
raise RuntimeError(f"Reintentos agotados: {last_error}")
# El llamador aún debe adaptar los campos según el proveedor; por ejemplo, Voyage usa data y top_k.
Si los documentos se reordenan por fragmentos, al combinar hay que sumar el desplazamiento a los índices de cada fragmento y después ordenar de forma unificada.
8. Lista de registro y monitoreo
En cada llamada registra al menos: hora, endpoint, modelo, número de documentos, total de caracteres o tokens estimados, top_n, código de estado, tipo de error, duración, número de reintentos e ID de solicitud. No registres la clave completa ni escribas párrafos enteros de los documentos del usuario en el log; cuando necesites diagnosticar, guarda un hash, la longitud y los primeros caracteres enmascarados.
Monitorea cuatro indicadores: proporción de 429, proporción de tiempos de espera y 5xx, proporción de resultados vacíos y latencia p95. Desglósalos además por línea de negocio, para que una tarea frecuente y de poco valor no consuma la cuota y oculte anomalías del negocio principal.
Preguntas frecuentes
¿Cuál es la diferencia entre 401 y 403?
El 401 indica que la identidad no se validó, normalmente porque la clave falta, está mal formada o caducó; el 403 indica que la identidad es válida pero los permisos no alcanzan, quizá porque el modelo no está habilitado, la IP no está en la lista blanca o el proyecto o el saldo tienen restricciones. Primero corrige la autenticación y después revisa los permisos.
¿Qué hacer si el conjunto de candidatos supera el límite de la interfaz?
Divide en el cliente, reordena cada fragmento por separado, combina por puntaje y suma el desplazamiento a los índices. La solución de fondo es controlar la cantidad en la etapa de recuperación; normalmente bastan decenas o cientos de candidatos, no envíes miles al rerank.
¿Cuántos reintentos conviene hacer ante un 429?
No hay una respuesta única. Se recomienda un número limitado, por ejemplo de tres a cinco, con retroceso exponencial y jitter aleatorio, respetando Retry-After, además de limitar la concurrencia. Cuando se agotan los reintentos se degrada la función, sin acumular solicitudes sin fin.
Si la interfaz de rerank agota el tiempo, ¿se puede usar streaming como en el chat?
Por lo general no. El rerank necesita ver todo el conjunto de candidatos para producir un orden estable y la mayoría de las interfaces responden de forma síncrona. Si la latencia es crítica, reduce los candidatos, trunca la longitud de los documentos o mueve el rerank a una tarea asíncrona.
¿Por qué devuelve 200 pero sin resultados?
Revisa primero si documents está vacío, si top_n es válido y si el filtro de negocio excluyó todos los documentos; después verifica si se lee mal el campo de respuesta y si al combinar fragmentos el índice queda fuera de rango. Añadir aserciones y alertas de resultado vacío es más eficaz que investigar después.
Siguiente paso
Cuando termines el diagnóstico, conviene fijar un conjunto mínimo de reproducción y un conjunto de casos de regresión, y luego crear una clave de prueba en ZSQH AI Gateway para validar la cadena de llamadas; la facturación y los límites se rigen por la página de precios de modelos.
Lecturas relacionadas:
