Batch API
Batch API позволяет отправить много inference-запросов одним пакетом и забрать результаты асинхронно. Это удобно, когда ответ не нужен сразу: overnight-прогоны, оценка датасетов, массовая генерация эмбеддингов и похожие задачи.
Окно выполнения — 24 часа. После завершения batch результаты приходят в том же ответе при опросе статуса (отдельный download URL не нужен).
Скидка на токены
Для поддерживаемых моделей токены ввода/вывода в Batch тарифицируются примерно на 50% дешевле стандартной цены. Точные batch-цены смотрите на странице модели (блок Batch API) и в поле batch публичного каталога.
Нетокеновые услуги
Не все компоненты тарифа одинаково скидываются. Например, вызовы web search обычно идут по стандартной цене; ставки prompt caching зависят от модели. Источник истины — карточка модели и фактический usage.cost_rub после completed.
Поддерживаемые модели
В Batch указывайте обычное имя модели из каталога (gpt-5.4, claude-sonnet-5, text-embedding-3-small, …). Модель поддерживает Batch, если в каталоге есть поле batch:
curl https://api.aitunnel.ru/public/aitunnel/models/chat
curl https://api.aitunnel.ru/public/aitunnel/models/embeddingsПример фрагмента:
{
"prompt_cost": 500,
"completion_cost": 3000,
"batch": {
"discount": 0.5,
"window": "24h"
}
}Список моделей с Batch также отмечен на страницах моделей на сайте (блок возможностей и цены).
Эндпоинты
| Метод | Путь | Описание |
|---|---|---|
POST | /v1/batches | Создать batch (202 Accepted) |
GET | /v1/batches/{id} | Статус и результаты |
Базовый URL: https://api.aitunnel.ru/v1. Авторизация — как обычно: Authorization: Bearer sk-aitunnel-….
Форма запроса
| Поле | Описание |
|---|---|
endpoint | Форма API для всех элементов batch: /v1/chat/completions, /v1/responses, /v1/messages или /v1/embeddings |
model | Id модели AITUNNEL (без префикса провайдера) |
requests | Непустой массив { custom_id, body }. custom_id уникален внутри batch; body — тело запроса выбранного endpoint |
Порядок полей
В JSON сначала должны идти endpoint и model, затем requests. API stream-парсит тело и вернёт 400, если requests окажется раньше.
Batch-level model применяется ко всем запросам. В body поле model можно не указывать. Если указать — оно должно совпадать с batch-level значением.
Тарификация
- При
POST /v1/batchesAITUNNEL резервирует на балансе оценочную стоимость (worst-case по составу batch). - Когда статус становится терминальным, списывается фактическая стоимость; разница возвращается на баланс.
- При
failed/expired/cancelledзарезервированная сумма возвращается целиком. - Итоговая сумма в рублях — в
usage.cost_rubответаGET /v1/batches/{id}послеcompleted(и успешной сверки).
Отправка batch
import os
import time
import requests
API_KEY = os.environ["AITUNNEL_API_KEY"]
BASE = "https://api.aitunnel.ru/v1"
headers = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
}
resp = requests.post(
f"{BASE}/batches",
headers=headers,
json={
"endpoint": "/v1/chat/completions",
"model": "gpt-5.4",
"requests": [
{
"custom_id": "req-0001",
"body": {
"messages": [
{
"role": "user",
"content": "Суммируй AITUNNEL одним предложением.",
}
]
},
}
],
},
)
resp.raise_for_status()
batch = resp.json()
print("Batch ID:", batch["id"], "status:", batch["status"])
# Опрос до терминального статуса
while batch["status"] not in ("completed", "failed", "expired", "cancelled"):
time.sleep(5)
batch = requests.get(
f"{BASE}/batches/{batch['id']}",
headers=headers,
).json()
print("Status:", batch["status"], batch.get("request_counts"))
if batch["status"] != "completed":
raise RuntimeError(batch.get("error") or batch["status"])
for item in batch.get("results") or []:
print(item["custom_id"], item.get("response") or item.get("error"))
print("cost_rub:", (batch.get("usage") or {}).get("cost_rub"))const API_KEY = process.env.AITUNNEL_API_KEY!;
const BASE = 'https://api.aitunnel.ru/v1';
const headers = {
Authorization: `Bearer ${API_KEY}`,
'Content-Type': 'application/json',
};
let res = await fetch(`${BASE}/batches`, {
method: 'POST',
headers,
body: JSON.stringify({
endpoint: '/v1/chat/completions',
model: 'gpt-5.4',
requests: [
{
custom_id: 'req-0001',
body: {
messages: [
{ role: 'user', content: 'Суммируй AITUNNEL одним предложением.' },
],
},
},
],
}),
});
let batch = await res.json();
console.log('Batch ID:', batch.id, batch.status);
while (!['completed', 'failed', 'expired', 'cancelled'].includes(batch.status)) {
await new Promise((r) => setTimeout(r, 5000));
res = await fetch(`${BASE}/batches/${batch.id}`, { headers });
batch = await res.json();
console.log('Status:', batch.status, batch.request_counts);
}
if (batch.status !== 'completed') {
throw new Error(batch.error || batch.status);
}
for (const item of batch.results ?? []) {
console.log(item.custom_id, item.response ?? item.error);
}
console.log('cost_rub:', batch.usage?.cost_rub);curl https://api.aitunnel.ru/v1/batches \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $AITUNNEL_API_KEY" \
-d '{
"endpoint": "/v1/chat/completions",
"model": "gpt-5.4",
"requests": [
{
"custom_id": "req-0001",
"body": {
"messages": [
{
"role": "user",
"content": "Суммируй AITUNNEL одним предложением."
}
]
}
}
]
}'Успешный submit возвращает 202 и объект batch со статусом validating:
{
"id": "batch_123",
"object": "batch",
"endpoint": "/v1/chat/completions",
"model": "gpt-5.4",
"completion_window": "24h",
"status": "validating",
"created_at": 1782097200,
"finalized_at": null,
"request_counts": {
"total": 1,
"completed": 0,
"failed": 0
},
"usage": null,
"results": null,
"error": null
}Опрос статуса
curl https://api.aitunnel.ru/v1/batches/batch_123 \
-H "Authorization: Bearer $AITUNNEL_API_KEY"Типичная цепочка статусов:
validating → in_progress → finalizing → completedТакже возможны failed, expired, cancelling, cancelled. Терминальные: completed, failed, expired, cancelled.
request_counts показывает прогресс:
{
"total": 100,
"completed": 98,
"failed": 2
}Пока batch не завершён (или завершён с ошибкой без результатов), results равен null. После completed результаты приходят inline в массиве results.
Каждый элемент сопоставляется с входом по custom_id. Заполняется ровно одно из полей — response или error:
{
"id": "batch_req_123",
"custom_id": "req-0001",
"response": {
"status_code": 200,
"request_id": "request_123",
"body": {
"id": "gen-…",
"object": "chat.completion",
"model": "gpt-5.4",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "AITUNNEL — единый API к сотням моделей ИИ с оплатой в рублях."
},
"finish_reason": "stop"
}
]
}
},
"error": null
}Другие формы API
Все элементы одного batch используют один и тот же endpoint. Чтобы смешать формы — отправьте несколько batch.
Anthropic Messages
{
"endpoint": "/v1/messages",
"model": "claude-sonnet-5",
"requests": [
{
"custom_id": "req-1",
"body": {
"max_tokens": 32,
"messages": [
{ "role": "user", "content": "Скажи привет." }
]
}
}
]
}Embeddings
{
"endpoint": "/v1/embeddings",
"model": "text-embedding-3-small",
"requests": [
{
"custom_id": "emb-0001",
"body": {
"input": [
"The quick brown fox jumped over the lazy dog.",
"Pack my box with five dozen liquor jugs."
]
}
}
]
}Поддержка Batch у конкретной embeddings-модели — поле batch в каталоге:
curl https://api.aitunnel.ru/public/aitunnel/models/embeddingsМультимодальный input и часть дополнительных параметров могут быть недоступны в Batch — для них используйте синхронный /v1/embeddings.
Хранение результатов
Входные данные и результаты batch хранятся ограниченное время (порядка 30 дней). Скачайте и сохраните нужные результаты до истечения окна хранения.
FAQ
Когда списываются деньги?
Сначала резерв при создании, затем сверка по факту на первом терминальном опросе. Смотрите usage.cost_rub.
Можно ли смешивать модели в одном batch?
Нет. Один batch — одна модель и один endpoint.