Batch API для LLM: 50 000 запросов со скидкой до 50% и три класса ошибок
Когда сервису нужно прогнать через LLM 50 000 договоров, синхронный API упирается в TPM, RPM и бюджет. OpenAI, Anthropic и Google предлагают Batch API: вы грузите один JSONL-файл, платите со скидкой и получаете результат в течение 24 часов. Батчи живут в отдельном пуле лимитов, но у него есть свой потолок по enqueued-токенам. А ошибки приходят не сразу, а внутри готового файла.
AI-обработка оригинала Habr AI; редакция Hamidun News
Пока запросов к LLM десяток или сотня, синхронный API ведёт себя прилично: отправил запрос, получил ответ. Но когда нужно обработать 50 000 договоров или карточек товаров, вы быстро упираетесь в лимиты TPM и RPM, а длинные контекстные запросы начинают отваливаться ещё до генерации. Для таких задач у OpenAI, Anthropic и Google есть пакетный режим, Batch API. Вы собираете все задачи в один файл, отправляете провайдеру и ждёте до 24 часов, зато платите меньше.
Как устроена очередь
За простым словом «батч» стоят три уровня ограничений.
Первый уровень — сам пакет. Это JSONL-файл, где каждая строка содержит custom_id, method, url и body с моделью и сообщениями. По сути, это обычный запрос к Chat Completions, упакованный в одну строку. Файл загружается через Files API с purpose «batch», после чего создаётся задача. Результаты возвращаются не в том порядке, в котором вы их отправляли, поэтому custom_id фактически работает как первичный ключ: по нему вы сопоставляете ответ с исходной записью.
Второй уровень — пул enqueued-токенов. Лимит считается не по файлам, а по суммарному объёму токенов во всех незавершённых пакетах. Если новый пакет выводит организацию за потолок, API возвращает token_limit_exceeded и отказывается создавать джобу. У OpenAI потолок зависит от tier: чем он выше, тем больше токенов можно держать в очереди.
Третий уровень — окно завершения. Сутки — это SLA, а не прогноз. На практике пакеты чаще всего завершаются за несколько часов, а Anthropic пишет, что большинство батчей готово меньше чем за час. Но рассчитывать нужно на худший случай. Параметр completion_window сейчас принимает только значение «24h».
Где ломается пайплайн
Автор исходной статьи делит ошибки на четыре класса, и ловушки тут нетривиальные.
До создания пакета. Лишняя запятая в JSONL, дубль или пропуск custom_id, неверный endpoint. По словам автора, Anthropic проверяет параметры запросов только после завершения всего пакета: можно отправить 100 тысяч строк, прождать час и узнать, что в трёх из них кривой max_tokens. Поэтому валидируйте файл локально до загрузки: распарсите каждую строку, проверьте уникальность custom_id и наличие model и messages. Для этого подойдут и Pydantic-модели.
На уровне очереди. Здесь главная ошибка — token_limit_exceeded. Лечится подсчётом токенов до отправки и собственной очередью на стороне приложения. Если бюджет не влезает, ждите завершения предыдущих пакетов или повторяйте попытку с экспоненциальным backoff: 30, 60, 120 секунд и так далее.
Внутри пакета. Самая коварная категория. Пакет completed, но в выгрузке часть строк succeeded, часть errored, часть expired. Если код просто читает content и пишет в базу, проблемные строки молча теряются. У Anthropic счётчики errored, canceled и expired в request_counts остаются нулевыми, пока не завершится весь пакет, так что заранее оценить масштаб провала не получится. Разумная схема — три корзины: invalid_request чинится и переотправляется, серверные ошибки повторяются с задержкой, expired идёт в новый пакет, потому что окно уже закрыто.
При опросе статуса. Если дёргать статус каждые пять секунд, можно поймать 429 на сам polling. Наивный цикл прочтёт это как «пакет не готов», хотя вы упёрлись в rate limit на чтение. Для пакетов до тысячи строк опрашивайте раз в 30 секунд, для крупных — раз в 2–5 минут. Если пакет висит дольше нескольких часов, проверьте, не застрял ли он на этапе validating.
Сколько это стоит на самом деле
Скидка в 50% — это потолок, а не гарантия. Итоговая цифра зависит от того, сколько запросов ушло в expired, сколько пришлось переотправить и использовался ли кеш системного промпта. В удачном сценарии экономия даже выше, потому что cached-input тоже дешевле. В неудачном вы платите дважды за одни и те же строки. Ещё важный нюанс: у OpenAI при отмене пакета незавершённые запросы отменяются, а за уже выполненные деньги списываются.
Отдельно стоит упомянуть, что оригинал частично написан в рекламном ключе: автор предлагает OpenAI-совместимый шлюз Bothub с оплатой российской картой и заявленной экономией 45%. Идея совместимого эндпоинта рабочая, но условия и надёжность любого посредника стоит проверять самостоятельно, а не по рефералке.
Что делать на практике
Батч — это другой контракт: вы получаете скидку и отдельный пул лимитов, но берёте на себя разбор результатов. Если вы строите массовую обработку документов, классификацию или разметку, закладывайте в пайплайн несколько вещей:
- локальную валидацию JSONL до отправки;
- подсчёт токенов и семафор на enqueued-лимит;
- разбор выгрузки по типам результата и повторную отправку только упавших строк;
- polling с backoff и логирование created_at.
И главное правило: не переотправляйте целый пакет из-за трёх упавших строк, потому что за успешные вы уже заплатили.
- 12 нояб. 2026 г.Дженсен Хуанг ушёл с поста CEO Nvidia: компания потеряла $1,4 трлн за две недели
- 12 нояб. 2026 г.Профсоюз Окленда добился переобучения вместо увольнений из-за ИИ: за забастовку 94,1%
- 12 нояб. 2026 г.Восемь стран и OpenAI с Anthropic обещают «рубильник» для ИИ-моделей, но без сроков и штрафов
- 12 нояб. 2026 г.OpenAI и ModRetro выпустили консоль за $200 для игр, написанных в Codex
Вопросы и ответы по материалу
Что известно по теме: как устроена очередь?
За простым словом «батч» стоят три уровня ограничений. Первый уровень — сам пакет. Это JSONL-файл, где каждая строка содержит custom_id, method, url и body с моделью и сообщениями. По сути, это обычный запрос к Chat Completions, упакованный в одну строку. Файл загружается через Files API с purpose «batch», после чего создаётся задача. Результаты возвращаются не в том порядке, в котором вы их отправляли, поэтому custom_id фактически работает как первичный ключ: по нему вы сопоставляете ответ с исходной записью.
Что известно по теме: где ломается пайплайн?
Автор исходной статьи делит ошибки на четыре класса, и ловушки тут нетривиальные. До создания пакета. Лишняя запятая в JSONL, дубль или пропуск custom_id, неверный endpoint. По словам автора, Anthropic проверяет параметры запросов только после завершения всего пакета: можно отправить 100 тысяч строк, прождать час и узнать, что в трёх из них кривой max_tokens. Поэтому валидируйте файл локально до загрузки: распарсите каждую строку, проверьте уникальность custom_id и наличие model и messages.
Что известно по теме: сколько это стоит на самом деле?
Скидка в 50% — это потолок, а не гарантия. Итоговая цифра зависит от того, сколько запросов ушло в expired, сколько пришлось переотправить и использовался ли кеш системного промпта. В удачном сценарии экономия даже выше, потому что cached-input тоже дешевле. В неудачном вы платите дважды за одни и те же строки. Ещё важный нюанс: у OpenAI при отмене пакета незавершённые запросы отменяются, а за уже выполненные деньги списываются.
Протестируйте новые LLM и мультимодальные модели в одном окне
Платформа Nomad AI (nomadnet.ai) даёт прямой доступ к Claude Opus 5.5, GPT-6, Gemini 3.1, DeepSeek и автономным агентам без VPN, зарубежных карт и зоопарка подписок.
Главное из мира ИИ — раз в неделю
7 ключевых событий недели, отобранных вручную. Без шума, репостов и пресс-релизов.
Готово! Проверьте почту — мы отправили подтверждение.