Ошибка 429 означает, что вы превысили лимит. Неочевидно то, что лимитов несколько и упереться можно в любой из них.
Три вида лимитов
Запросы в минуту. Сколько раз вы можете дёрнуть API. Упираются сюда обычно те, кто параллелит мелкие задачи.
Входные токены в минуту. Сколько текста вы отправляете. Упираются те, кто гоняет большой контекст: агенты, работа с репозиторием.
Выходные токены в минуту. Сколько модель генерирует. Упираются те, кто просит длинные ответы или запускает много генераций сразу.
Первый лимит обычно не главный. На агентных сценариях вы упрётесь во второй задолго до первого.
Как правильно повторять запрос
Наивный повтор сразу же делает только хуже: вы добавляете нагрузку в момент, когда её и так много. Нужна выдержка с ростом и случайной добавкой.
import random, time
def call_with_retry(fn, attempts=5, base=1.0):
for i in range(attempts):
try:
return fn()
except RateLimitError:
if i == attempts - 1:
raise
delay = base * (2 ** i) + random.uniform(0, 0.5)
time.sleep(delay)
Случайная добавка нужна, чтобы десять ваших воркеров не пошли на повтор одновременно. Без неё вы получите волны отказов вместо ровной работы.
Читайте заголовки ответа
API возвращает, сколько осталось до сброса. Это лучше, чем угадывать: если сервер говорит подождать двадцать секунд, ждать надо двадцать, а не тридцать две по формуле.
Как не упираться вовсе
Не шлите весь файл, если нужен метод. Входной лимит расходуется контекстом, а он на агентных сценариях накапливается.
Используйте именованные ключи для учёта. Отдельные ключи показывают расход фона и живой работы отдельно, но не создают независимые квоты. Очередь и ограничитель частоты в клиенте управляют нагрузкой.
Ставьте очередь и ограничивайте частоту. Последовательные запросы тоже могут превысить квоту провайдера. Используйте ограниченную очередь, клиентский ограничитель частоты и указания о повторах, если провайдер их вернул.
Кэшируйте повторяющийся контекст. Если каждый запрос тащит одну и ту же большую инструкцию, её стоит закэшировать на стороне провайдера.
Про отдельные ключи
Давайте ключам названия для продакшена, фоновой работы и экспериментов, чтобы разделять учёт расхода. Ключи не изолируют квоты; очередь и ограничитель частоты в клиенте управляют каждой нагрузкой.
Claudexia показывает статистику расхода по каждому ключу. Давайте ключам названия по нагрузке, выбирайте Premium или Cheap, при необходимости срок действия и резервный Premium для Cheap. API ключей личного кабинета не позволяет задавать RPM, TPM, параллелизм или бюджет для ключа.
Коротко
На нагрузку могут влиять число запросов, токены и параллелизм. Ограничивайте повторы, добавляйте джиттер и учитывайте заголовки о повторах, если они есть. Очередь и ограничитель частоты в клиенте управляют фоном и живыми запросами. Именованные ключи разделяют учёт расхода, а не квоты.