У интерфейса Rerank нет единого стандарта, как у Chat Completions, поэтому один и тот же код у разных поставщиков может вернуть 404 или 422. При диагностике сначала разделяйте ошибки по HTTP-статусу, затем разбирайте «мягкие» случаи, когда приходит 200, но результат неверен. Ниже пять категорий: аутентификация, набор кандидатов, ограничение скорости, тайм-ауты и пустой результат; в конце — готовый код повторов и чек-лист журналов. Модели и цены — на странице тарифов.
Примечание: Cohere, Jina, Voyage и другие названия — товарные знаки их правообладателей; статья носит технический характер. Пути интерфейсов, лимиты и коды ошибок могут меняться от версии к версии — сверяйтесь с документацией соответствующего поставщика.
1. Сначала различите пять категорий
| Симптом | Частый статус | Типичная причина | Порядок действий |
|---|---|---|---|
| Ошибка аутентификации | 401, 403 | Неверный ключ, нет заголовка, модель не активирована | Сначала учётные данные и права |
| Запрос отклонён | 400, 422 | Слишком большой набор, несовпадение полей, пустой документ | Проверить тело запроса и лимиты |
| Неверный путь | 404 | Ошибка в endpoint, старое имя модели, неверная сборка Base URL | Сверить с официальной документацией |
| Лимит или квота | 429 | Резкий рост параллелизма, общий ключ, шторм повторов | Backoff, снижение параллелизма |
| Тайм-аут или ошибка upstream | 504, 5xx | Много кандидатов, длинные документы, перегрузка upstream | Уменьшить запрос, ограниченные повторы |
| Пустой результат | 200 | Некорректный top_n, неверное поле, документы отфильтрованы | Добавить проверки и оповещения |
В журнале фиксируйте как минимум время, endpoint, модель, число документов, общее число символов, top_n, статус, длительность, число повторов и request ID. Не записывайте полный ключ и не печатайте целиком пользовательские документы.
2. 401 и 403: сначала аутентификация, затем права
401 означает, что личность не прошла проверку; это обычно не связано с возможностями модели или балансом. Проверяйте по порядку:
- Используется ли в заголовке
Authorization: Bearerс ключом; некоторые шлюзы требуютx-api-key. - Нет ли вокруг ключа пробелов, переводов строк или лишних кавычек. При копировании из чата они появляются чаще всего.
- Не переопределены ли переменные окружения локальной конфигурацией или платформой развёртывания; совпадают ли ключи в локальной и онлайн-среде.
- Открыт ли ключу именно интерфейс реранкинга. У некоторых аккаунтов есть только права на чат, без Rerank.
- Правильно ли указан endpoint. Форматы
/v1/rerankи/v2/rerankмогут различаться; если просто добавить/rerankк Base URL чат-интерфейса, легко получить 404 или 401.
403 — личность валидна, но прав недостаточно. Смотрите, активирована ли модель, входит ли IP в белый список, есть ли права проекта и нет ли задолженности. 401 не повторяйте: повторы только раздуют журнал ошибок и могут запустить защиту от злоупотреблений. Сначала выполните минимальный curl, затем возвращайтесь к бизнес-коду.
3. 400 и 422: слишком большой набор и несовпадение полей
Слишком большой набор кандидатов — самая частая причина 400. У хостинговых интерфейсов обычно есть лимиты на число документов за вызов, токены одного документа и размер тела запроса. У Cohere, например, официально рекомендуется не более тысячи документов за вызов, а один документ по умолчанию усекается до 4096 токенов; у других поставщиков значения иные и меняются с версией модели, поэтому перед подключением проверяйте документацию. При превышении лимита правильная реакция — не слепой повтор, а:
- разбить набор на части, переранжировать каждую отдельно и объединить по оценкам;
- ограничить число кандидатов уже на этапе поиска, например пятьюдесятью–двумястами;
- длинные документы сначала нарезать или усечь, не отправляя целый PDF в
documents; - удалить пустые строки,
null, пробельные и повторяющиеся документы.
Несовпадение полей тоже даёт 400 или 422: top_n записан как top_k или наоборот; Jina и Cohere чаще используют top_n, Voyage — top_k. В documents передан массив объектов вместо массива строк, либо id и text лежат на неверном уровне. Если top_n больше числа документов, одни интерфейсы возвращают ошибку, другие автоматически усекают. Параметры return_documents, truncation, max_tokens_per_doc могут не поддерживаться текущим поставщиком. NaN, Infinity и неэкранированные переводы строк в JSON также ломают разбор.
Метод диагностики: сохраните обезличенное исходное тело запроса и добавляйте параметры обратно по одному на минимальном примере, меняя только одну переменную за раз.
4. 429: лимиты, квоты и шторм повторов
429 означает, что запрос ограничен по скорости или квота исчерпана. Частые причины: превышение запросов в секунду или параллелизма тарифа, исчерпание токеновой квоты в пик, использование одного ключа несколькими сервисами, повторы без задержки. Сначала посмотрите Retry-After и поля квоты в заголовках ответа, затем решайте, ждать или снижать параллелизм.
Порядок обработки:
- Определите, это лимит одного ключа или квота всего аккаунта.
- Переведите повторы на экспоненциальную задержку со случайным разбросом и учитывайте
Retry-After. - Ограничьте параллелизм и сглаживайте пики очередью, а не бесконечными повторами.
- Перенесите пакетные задачи на часы низкой нагрузки, разделите офлайн-оценку и онлайн-трафик.
- Для критичных сервисов предусмотрите деградацию: пропуск реранкинга с сохранением порядка поиска.
Не повторяйте с фиксированной секундой до отказа. Несколько экземпляров, повторяющих одновременно, создают шторм повторов и превращают небольшой лимит в длительный сбой.
5. Тайм-ауты, 504 и 5xx
Тайм-аут делится на соединение и чтение. Тайм-аут соединения обычно связан с сетью, DNS, прокси или TLS; тайм-аут чтения — с большим набором кандидатов, длинными документами, очередью upstream или холодным стартом модели. 504 обычно означает, что шлюз не дождался upstream; это не то же самое, что тайм-аут клиента.
Порядок диагностики:
- Проверьте минимальный запрос: один query и пять коротких документов, чтобы исключить полную недоступность сети.
- Постепенно увеличивайте число документов и найдите точку роста времени.
- Проверьте длину одного документа и общее число токенов, при необходимости усеките.
- Убедитесь, что клиентский тайм-аут не короче времени обработки на сервере.
- Для 5xx и тайм-аутов делайте ограниченное число повторов, после порога — деградация.
- Записывайте request ID и trace id upstream для сверки с поставщиком.
Rerank обычно не потоковый интерфейс, поэтому скрыть долгую обработку потоковым выводом нельзя. Для чувствительных к задержке сервисов реранкинг стоит вынести в асинхронную цепочку или применять только к первым десяткам кандидатов.
6. Приходит 200, но результат пустой или неверный
Такие мягкие ошибки коварнее: documents — пустой массив, и интерфейс возвращает пустой результат; top_n равен нулю или отрицательному числу; все документы исключены бизнес-фильтрами; прочитано неверное поле ответа — где-то results, где-то data; index — позиция в исходном массиве, но после разбиения на части забыли добавить смещение; семантика оценок различается — одни нормализуют к нулю–единице, другие отдают logits, направление сортировки тоже может отличаться; возвращается текст документа вместо index, и при дедупликации одинаковые тексты склеиваются.
Добавьте на клиенте проверки: число результатов не больше top_n, каждый index в допустимом диапазоне, оценки монотонны в соответствии с семантикой поставщика. При аномалии сохраняйте краткую сводку исходного ответа, а не молча возвращайте пустой список.
7. Готовый код повторов
Пример делит ошибки на три класса: аутентификация и параметры не повторяются, 429 и 5xx повторяются с задержкой, тайм-ауты — ограниченно; после исчерпания повторов происходит деградация к исходному порядку поиска.
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"Без повтора {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"Повтор {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"Повторы исчерпаны: {last_error}")
# Вызывающая сторона всё равно адаптирует поля под поставщика:
# например, Voyage использует data и top_k.
Если документы переранжируются частями, при объединении прибавляйте к index смещение части, затем сортируйте единый список.
8. Чек-лист журналов и мониторинга
На каждый вызов записывайте: время, endpoint, модель, число документов, общее число символов или оценку токенов, top_n, статус, тип ошибки, длительность, число повторов, request ID. Не записывайте полный ключ и не сохраняйте пользовательские документы целиком; для диагностики достаточно хеша, длины и обезличенных первых символов.
Мониторинг должен покрывать четыре показателя: долю 429, долю тайм-аутов и 5xx, долю пустых результатов и задержку p95. Разбивайте их по бизнес-линиям, чтобы высокочастотная низкоценная задача не съедала квоту и не маскировала сбой основного сервиса.
Частые вопросы
Чем 401 отличается от 403?
401 — личность не прошла проверку, обычно из-за отсутствующего, неверно оформленного или просроченного ключа. 403 — личность валидна, но прав недостаточно: модель не активирована, IP не в белом списке, ограничен проект или баланс. Сначала исправляйте аутентификацию, затем права.
Что делать, если набор кандидатов превышает лимит интерфейса?
Разбейте его на клиенте, переранжируйте части отдельно и объедините по оценкам, добавив смещение к index. Более правильное решение — ограничивать число уже на этапе поиска: обычно достаточно десятков или сотен документов, не отправляйте тысячи в реранкинг.
Сколько раз повторять 429?
Единого ответа нет. Рекомендуется ограниченное число повторов, например три–пять, с экспоненциальной задержкой и случайным разбросом, с учётом Retry-After; параллелизм тоже нужно ограничить. После исчерпания — деградация, а не бесконечное накопление запросов.
Можно ли использовать потоковый режим при тайм-ауте Rerank, как в чате?
Обычно нет. Для устойчивой сортировки нужно обработать весь набор кандидатов, и большинство интерфейсов отвечает синхронно. При чувствительности к задержке сокращайте число кандидатов, усекайте документы или выносите реранкинг в асинхронную задачу.
Приходит 200, но результатов нет — почему?
Проверьте, не пуст ли documents, корректен ли top_n, не исключили ли документы бизнес-фильтры; затем проверьте, не перепутано ли поле ответа и не выходит ли index за границы при объединении частей. Проверки и оповещение о пустом результате эффективнее разбора постфактум.
Что дальше
После диагностики зафиксируйте минимальный воспроизводимый пример и набор регрессионных случаев, затем создайте тестовый ключ в ZSQH AI Gateway и проверьте всю цепочку вызова; тарификация и лимиты — на странице тарифов.
Связанные статьи:
