ВойтиКонтактыНачать бесплатно
Reliability and Routing30 июля 2026 г.Flatkey Team

Пояснение лимитов запросов LLM: RPM, TPM и повторные попытки

Разберитесь в RPM, TPM, ошибках 429, планировании мощности, очередях, экспоненциальной задержке, лимитах повторных попыток и fallback-маршрутизации для production API LLM.

Пояснение лимитов запросов LLM: RPM, TPM и повторные попытки

Лимиты запросов LLM определяют, какой объём трафика ваше приложение может отправить модели за заданный промежуток времени. Два лимита, с которыми инженеры сталкиваются чаще всего, — это RPM (requests per minute, запросы в минуту) и TPM (tokens per minute, токены в минуту). Нагрузка может укладываться в один лимит и при этом превышать другой.

Это различие важно. Если вы воспринимаете любую ошибку 429 как общую проблему с количеством запросов, вы можете добавить повторные попытки, которые увеличат давление по токенам, повысят задержку и усугубят сбой. Безопасная для продакшена схема сначала определяет ограниченный ресурс, а затем выбирает между регулированием темпа, очередями, повторными попытками, снижением числа токенов или маршрутизацией в другое место.

В этом руководстве объясняется механика, приводятся формулы планирования ёмкости и включён ограниченный шаблон повторных попыток на TypeScript для API, совместимых с OpenAI.

RPM vs. TPM: краткий ответ

Лимит Что измеряет Какие нагрузки достигают его первыми Лучшее первое действие
RPM Запросы, принятые в течение временного окна, заданного провайдером Много мелких вызовов, циклы инструментов агента, проверки с высоким fan-out Сгладить темп запросов, пакетировать работу или поставить всплески в очередь
TPM Входные и/или выходные токены, принятые в течение временного окна Длинный контекст, большие ответы, запросы с большим объёмом retrieval, параллельные проверки Сократить объём токенов, ограничить длину ответа или перенаправить на доступную ёмкость
RPD Запросы в день Плановые краулеры, широкие офлайн-проверки, нагрузки бесплатного тарифа Перепланировать или повысить уровень сервиса
Concurrent requests Запросы, выполняющиеся одновременно Медленные генерации и потоковые нагрузки Ограничить число воркеров и применять backpressure
429 Лимит или политика ёмкости отклонили запрос Любая нагрузка, превышающая активный bucket Классифицировать ошибку перед повторной попыткой

RPM управляет частотой. TPM управляет пропускной способностью. Конкурентность управляет одновременной работой. Они взаимодействуют, но не взаимозаменяемы.

Почему запрос может не пройти ниже заявленного лимита

Опубликованный лимит, например 600 RPM, не обязательно означает, что клиент может отправить 600 запросов в первую секунду каждой минуты. Провайдеры обычно применяют скользящие окна или механизмы, похожие на token bucket. Короткий всплеск может исчерпать доступную немедленно ёмкость, даже если арифметика для всей минуты выглядит безопасной.

Другие причины, по которым 429 может появиться раньше:

  • Лимит применяется к проекту, организации, аккаунту, семейству моделей или уровню сервиса, а не к одному API-ключу.
  • Входные и выходные токены используют отдельные buckets.
  • Несколько воркеров, сервисов или пользователей разделяют один и тот же пул квоты.
  • Повторные попытки после предыдущих сбоев расходуют тот же лимит.
  • Провайдер применяет лимит ускорения или burst-лимит, пока трафик резко нарастает.
  • Пул, специфичный для модели, заполнен, хотя у другой модели ещё есть ёмкость.

Именно поэтому приложение не должно делать вывод о причине только на основе собственного счётчика запросов. Читайте тело ответа и заголовки, сохраняйте идентификаторы запросов провайдера и логируйте модель, аккаунт, оценки токенов, номер попытки и задержку в очереди.

Практическая формула расчёта ёмкости

Начните с двух независимых потолков.

request_ceiling = RPM × safety_factor

token_ceiling = (TPM × safety_factor) ÷ average_tokens_per_request

safe_requests_per_minute = min(request_ceiling, token_ceiling)

Используйте коэффициент запаса ниже 1.0 — например, 0.70.9 — чтобы учесть вариативность токенов, повторные попытки, общих потребителей и неравномерные паттерны поступления запросов.

Пример

Предположим, пул моделей допускает:

  • 1,000 RPM
  • 2,000,000 TPM
  • 4,000 средних общих токенов на запрос
  • 80% операционный коэффициент запаса
request_ceiling = 1,000 × 0.8 = 800 requests/minute

token_ceiling = (2,000,000 × 0.8) ÷ 4,000
              = 400 requests/minute

safe_requests_per_minute = min(800, 400) = 400

TPM — это ограничивающий фактор. Добавление большего числа воркеров не увеличит устойчивую пропускную способность; это лишь создаст большую очередь или больше ответов 429.

Для онлайн-систем переведите пропускную способность в начальное значение конкурентности с помощью закона Литтла:

target_concurrency ≈ requests_per_second × average_request_seconds

Если безопасная скорость составляет 400 запросов в минуту (6.67 в секунду), а средняя задержка модели — 3 секунды, начальная конкурентность составляет около 20. Аккуратно добавляйте запас, затем настраивайте по реальной p95 задержке и распределению токенов.

Ограничения токенов часто являются скрытым узким местом

Команды часто отслеживают количество запросов, но упускают из виду объем токенов. Давление на TPM растет, когда вы:

  • Добавляете в каждый промпт больше извлеченных документов.
  • Сохраняете длинную историю разговоров.
  • Запускаете несколько вариантов completion для одной задачи.
  • Увеличиваете лимиты на выход.
  • Повторно отправляете один и тот же большой системный промпт.
  • Запускаете параллельные наборы оценок в рамках одной проектной квоты.

Измеряйте как минимум четыре значения токенов для каждого успешно выполненного запроса:

  1. Входные токены.
  2. Выходные токены.
  3. Общее количество токенов.
  4. Скользящие p50, p95 и максимум по рабочей нагрузке и модели.

Планирование емкости только по среднему значению — это оптимистичный подход. Более безопасный планировщик резервирует ресурсы по высокому процентилю или оценке, специфичной для нагрузки, а затем сверяет резерв с фактическим использованием после завершения.

Что означает 429 — и что не означает

HTTP 429 Too Many Requests сообщает, что сервер отклонил запрос в рамках действующего лимита или политики емкости. Это не означает автоматически «подождите одну секунду и попробуйте снова».

Классифицируйте 429 в операционную категорию:

Класс 429 Признаки Правильное действие
Кратковременный всплеск Недавний пик; заголовок повторной попытки короткий; очередь в остальном здорова Подождите указание сервера, затем повторите попытку с джиттером
Устойчивое исчерпание RPM Скорость запросов держится около верхнего предела Уменьшите темп или поставьте в очередь; одни только повторы не исправят ситуацию
Устойчивое исчерпание TPM Скорость токенов высокая; доминируют длинные промпты или ответы Сократите число токенов, отложите работу или направьте в другой допустимый пул
Дневной лимит или лимит уровня Ошибка указывает на дневную квоту, биллинг или ограничение уровня Прекратите повторы; перенесите выполнение или измените доступную емкость аккаунта
Лимит ускорения Трафик быстро вырос от низкой базовой нагрузки Плавно наращивайте нагрузку и сглаживайте всплески
Событие нехватки емкости у провайдера Обычная скорость клиента, но повторяющиеся временные отклонения Используйте небольшой бюджет повторов, затем безопасный с точки зрения контракта запасной вариант

Тело ответа и заголовки различаются у разных провайдеров. Если доступен явный сигнал Retry-After или сброса лимита, отдавайте ему предпочтение. В противном случае используйте экспоненциальную задержку с случайным джиттером.

Экспоненциальная задержка с джиттером

Экспоненциальная задержка увеличивает паузу после каждой неудачной попытки. Джиттер случайным образом варьирует эту паузу, чтобы сотни воркеров не повторяли запрос в один и тот же момент.

Одна из распространенных формул полного джиттера:

delay_ms = random(0, min(cap_ms, base_ms × 2^attempt))

Политике повторных попыток в продакшене также нужны ограничения:

  • Максимум попыток: обычно небольшое число, а не бесконечный цикл.
  • Максимальное время выполнения: остановитесь, когда исчерпан бюджет задержки для вызывающей стороны.
  • Список повторяемых статусов: обычно 429, выбранные ответы 5xx и безопасные сетевые сбои.
  • Подсказки сервера: соблюдайте Retry-After, когда он корректен.
  • Отмена: немедленно прекращайте попытки, если исходный запрос был прерван.
  • Наблюдаемость: записывайте число попыток, время ожидания, финальный статус и идентификатор запроса провайдера.

Неудачные запросы все равно могут расходовать емкость лимита запросов. Поэтому агрессивные повторы могут продлить период троттлинга.

TypeScript: ограниченный помощник для повторных попыток

В следующем примере используется совместимый с OpenAI базовый URL Flatkey. Он повторяет запрос только до того, как будет потреблено тело успешного ответа, и останавливается, когда исчерпан либо лимит попыток, либо общий временной бюджет.

type ChatRequest = {
  model: string;
  messages: Array<{ role: "system" | "user" | "assistant"; content: string }>;
  max_tokens?: number;
};

const sleep = (milliseconds: number) =>
  new Promise((resolve) => setTimeout(resolve, milliseconds));

function retryAfterMilliseconds(response: Response): number | null {
  const value = response.headers.get("retry-after");
  if (!value) return null;

  const seconds = Number(value);
  if (Number.isFinite(seconds)) return Math.max(0, seconds * 1_000);

  const date = Date.parse(value);
  return Number.isNaN(date) ? null : Math.max(0, date - Date.now());
}

export async function createChatCompletion(
  apiKey: string,
  request: ChatRequest,
  options: { maxAttempts?: number; maxElapsedMs?: number } = {},
) {
  const maxAttempts = options.maxAttempts ?? 4;
  const maxElapsedMs = options.maxElapsedMs ?? 30_000;
  const startedAt = Date.now();

  for (let attempt = 0; attempt < maxAttempts; attempt += 1) {
    const response = await fetch(
      "https://router.flatkey.ai/v1/chat/completions",
      {
        method: "POST",
        headers: {
          Authorization: `Bearer ${apiKey}`,
          "Content-Type": "application/json",
        },
        body: JSON.stringify(request),
      },
    );

    if (response.ok) return response.json();

    const retryable = response.status === 429 || response.status >= 500;
    const finalAttempt = attempt === maxAttempts - 1;
    if (!retryable || finalAttempt) {
      throw new Error(`LLM request failed with ${response.status}: ${await response.text()}`);
    }

    const hintedDelay = retryAfterMilliseconds(response);
    const exponentialCap = Math.min(8_000, 500 * 2 ** attempt);
    const jitteredDelay = Math.random() * exponentialCap;
    const delayMs = hintedDelay ?? jitteredDelay;

    if (Date.now() + delayMs - startedAt >= maxElapsedMs) {
      throw new Error("Лимит бюджета повторных попыток LLM исчерпан");
    }

    await sleep(delayMs);
  }

  throw new Error("Недостижимое состояние повторной попытки");
}

Для использования в production добавьте тайм-ауты запросов, структурированные типы ошибок, метрики и сигнал отмены вашего приложения. Если операция может создавать внешние побочные эффекты — например, отправлять письмо или выполнять инструмент — сделайте бизнес-операцию идемпотентной до ее повторной попытки.

Повторять, ставить в очередь, уменьшать или перенаправлять?

Используйте причину, а не только код состояния, чтобы выбрать способ управления.

Ситуация Повторная попытка Очередь Сократить токены Маршрутизировать в другое место
Один изолированный временный 429 Да, с ограничением Опционально Нет Обычно нет
Повторное исчерпание RPM Ограниченно Да Нет Иногда
Повторное исчерпание TPM Ограниченно Да Да Часто полезно
Исчерпана дневная квота Нет На потом Опционально Да, если политика позволяет
Инцидент у провайдера 5xx Да, с ограничением Да Нет Да после лимита на повторные попытки
Частичный потоковый ответ Нет автоматического повторного воспроизведения Зависит от приложения Нет Только с явной семантикой восстановления

Повторная попытка

Используйте повторную попытку, когда сбой временный и у вызывающей стороны еще есть время. Устанавливайте бюджет повторных попыток на уровне запроса и на уровне сервиса, чтобы инцидент у провайдера не мог многократно увеличить общий трафик.

Очередь

Используйте очередь, когда скорость поступления временно превышает устойчивую скорость обслуживания. Полезная очередь предоставляет:

  • Возраст самого старого элемента.
  • Оценочное время начала обработки.
  • Справедливость между арендаторами.
  • Отмену устаревших задач.
  • Максимальную глубину с явным поведением при сбросе.

Сократить токены

Когда ограничивает TPM, удаляйте нерелевантный контекст, суммируйте историю, уменьшайте число кандидатов, снижайте лимиты на длину вывода, кэшируйте повторно используемые префиксы промптов там, где это поддерживается, и разделяйте короткий интерактивный трафик и длинные пакетные задания.

Маршрутизировать в другое место

Маршрутизация уместна, когда другая модель или другой провайдер удовлетворяет тому же контракту и имеет достаточную емкость. Запасной вариант должен сохранять необходимые возможности, такие как структурированный вывод, вызов инструментов, длина контекста, политика безопасности и целевая задержка. Для более глубокой практической схемы реализации используйте руководство по маршрутизации отказоустойчивого резерва для LLM API.

Ограничения скорости в оценках моделей

Плохое управление ограничением скорости может сделать оценку недействительной.

Предположим, что модель A тестируется с 10 воркерами, а модель B — со 100. Если модель B проводит больше времени под ограничением, ее измеренная задержка включает ожидание в очереди и задержки повторных попыток, с которыми модель A не сталкивалась. В результате может быть описана конфигурация вашего стенда, а не производительность модели.

Для обоснованных сравнений:

  1. Разделяйте задержку модели, задержку в очереди и задержку повторной попытки.
  2. Применяйте одинаковый процесс поступления запросов или нормализованный уровень загрузки к каждому провайдеру.
  3. Плавно разогревайте трафик, когда провайдеры используют механизмы ускорения.
  4. Записывайте число токенов и число попыток на каждую завершенную задачу.
  5. Публикуйте как долю успеха с первой попытки, так и итоговую долю успеха.
  6. Сравнивайте стоимость за принятую задачу, а не только стоимость за токен.
  7. Проводите тесты перегрузки отдельно от бенчмарков качества и задержки.

Если вы оцениваете провайдеров одновременно по надежности и стоимости, сочетайте этот процесс с сравнением цен на AI API.

Архитектура лимитов запросов для продакшена

Надежный путь обработки запросов обычно включает пять уровней управления:

  1. Контроль допуска отклоняет или откладывает работу, которая не успеет уложиться в свой дедлайн.
  2. Резервирование токенов оценивает вероятную стоимость запроса в квоте.
  3. Ограничитель частоты распределяет нагрузку по каждому провайдеру, пулу моделей, тенанту и классу приоритета.
  4. Контроллер повторных попыток расходует ограниченный бюджет повторов с jitter.
  5. Маршрутизатор выбирает совместимую с контрактом альтернативу после того, как бюджет повторных попыток или политика емкости говорит переключиться.
client
  → admission control
  → priority queue
  → RPM + token reservation limiter
  → provider/model route
  → bounded retry
  → contract-safe fallback
  → usage and latency logs

Не размещайте бесконечный цикл повторных попыток в каждом рабочем процессе приложения. Централизуйте политику, чтобы все вызывающие стороны разделяли одинаковое понимание доступной емкости.

Метрики, за которыми стоит следить с алертами

Отслеживайте их по провайдеру, модели, проекту, маршруту, тенанту и типу нагрузки:

  • Запросы в минуту и токены в минуту.
  • Оцененные зарезервированные токены versus фактически использованные токены.
  • Процент успешных запросов с первой попытки.
  • Число повторных попыток на один успешный запрос.
  • Частота 429 по классифицированной причине.
  • Глубина очереди и возраст самого старого элемента.
  • Время ожидания доступной частоты запросов.
  • Сквозная задержка p50, p95 и p99.
  • Частота fallback и результат fallback.
  • Стоимость одного успешного или принятого задания.

Алерт только по общему числу 429 создает шум. Лучший сигнал сочетает уровень throttling с возрастом очереди, усилением из-за повторных попыток и итоговой частотой сбоев.

Распространенные ошибки

Рассматривать RPM как лимит на параллелизм

RPM измеряет количество допусков во времени; параллелизм измеряет объем выполняемой работы. Медленные запросы могут создавать высокий параллелизм при умеренном RPM.

Сразу повторять каждый 429

Немедленные повторы синхронизируют рабочие процессы и потребляют больше емкости. По возможности соблюдайте серверное время ожидания и добавляйте jitter.

Использовать один ограничитель для каждой модели

Провайдеры могут использовать отдельные или общие пулы. Политика для конкретной модели должна соответствовать документированной области квоты провайдера и наблюдаемым заголовкам.

Игнорировать общих потребителей

Панель мониторинга, batch job и production API могут использовать одну и ту же квоту проекта. Резервируйте емкость по типам нагрузки и, где возможно, изолируйте критичный трафик.

Повторять частичный stream

Как только токены достигли пользователя, повторный запуск запроса может дублировать контент или действия инструментов. Определяйте явную семантику продолжения или перезапуска вместо молчаливого повторного запроса.

Как Flatkey меняет операционную модель

Flatkey предоставляет один API key и совместимый с OpenAI base URL для доступа к поддерживаемым провайдерам моделей. Это дает приложению одну точку интеграции, при этом политика маршрутизации по-прежнему может учитывать соответствие модели, емкость, надежность и стоимость.

Шлюз не снимает ограничения upstream-сервисов. Он упрощает внедрение согласованных контролей вокруг них: одна клиентская интеграция, централизованные журналы запросов и возможность перенаправлять подходящий трафик, когда маршрут перегружен. Ознакомьтесь с руководством по архитектуре AI API gateway, чтобы лучше понять общий дизайн маршрутизации, или посмотрите актуальные цены Flatkey перед выбором production-маршрутов.

FAQ

В чем разница между RPM и TPM?

RPM ограничивает, сколько запросов допускается за определенный промежуток времени. TPM ограничивает, сколько входных и/или выходных токенов допускается. Небольшие промпты обычно в первую очередь упираются в RPM; задачи с большим контекстом или высоким объемом генерации часто в первую очередь упираются в TPM.

Почему я получаю ошибки 429 ниже своего лимита RPM?

Провайдер может применять более короткие скользящие окна, token buckets, общие квоты проекта, отдельные лимиты по токенам, лимиты ускорения или пулы, специфичные для модели. Ваш локальный счетчик запросов может не отражать полный охват квоты.

Стоит ли повторять каждый ответ 429?

Нет. Повторяйте только кратковременное ограничение пропускной способности с небольшим бюджетом и jitter. Не выполняйте многократные повторные попытки при исчерпании дневной квоты, ограничениях по биллингу или устойчивой перегрузке, которая не имеет времени на восстановление.

Гарантирует ли exponential backoff успех?

Нет. Backoff снижает вероятность столкновений и дает временной емкости время на восстановление. Он не может создать квоту. При устойчивом исчерпании нужно снизить спрос, увеличить емкость, отложить работу или использовать другой подходящий маршрут.

Сколько повторных попыток должна использовать LLM-запрос?

Универсального числа нет. Задавайте число попыток, исходя из бюджета задержки, видимой пользователю, и типа сбоя. Многие интерактивные приложения должны разрешать лишь несколько коротких попыток перед ошибкой или перенаправлением; офлайн-задачи могут терпеть более длинные очереди.

Учитываются ли повторные попытки в rate limits?

Да, могут. Провайдеры могут учитывать неудачные попытки в активных лимитах, поэтому усиление нагрузки из-за повторов нужно отслеживать и ограничивать.

Финальный чек-лист

  • Отдельно моделируйте RPM, TPM, дневные лимиты и concurrency.
  • Рассчитывайте пропускную способность по минимуму из ограничений по запросам и токенам.
  • Работайте ниже опубликованного максимума, используя коэффициент безопасности.
  • Используйте очереди и pacing для устойчивой нагрузки.
  • Учитывайте Retry-After и используйте exponential backoff с jitter.
  • Ограничивайте число попыток и общее время повторов.
  • Не воспроизводите автоматически частично завершенные потоки или побочные эффекты.
  • Перенаправляйте только на модели, которые сохраняют требуемый контракт.
  • Разделяйте задержку очереди и повторов от задержки модели в оценках.
  • Настраивайте оповещения на усиление нагрузки из-за повторов и возраст очереди, а не только на сырые счета 429.

Лимиты запросов — это прежде всего задача планирования емкости, и только потом — задача повторных попыток. Как только вы отдельно измеряете частоту запросов, пропускную способность токенов, concurrency и усиление нагрузки из-за повторов, ошибки 429 становятся actionable-сигналами, а не непредсказуемым шумом в production.