Асинхронный inference

Отправка inference-запросов асинхронно с последующим получением результата по job_id.

Обзор

Асинхронный inference реализует паттерн fire-and-forget на уровне шлюза: вы отправляете обычный inference-запрос на async-эндпоинт, получаете job_id сразу же, а позже опрашиваете шлюз и забираете итоговый результат.

Это функция уровня шлюза — она требует настроенного Logs Store.

Как это работает

ПровайдерAsync-воркерШлюз MeridianКлиентПровайдерAsync-воркерШлюз MeridianКлиентalt[Job в pending или processing][Job завершён или упал]POST /v1/async/chat/completions202 Accepted + {id, status: "pending"}Постановка job в очередьВыполнение inference-запросаОтвет или ошибкаGET /v1/async/chat/completions/{job_id}202 Accepted + статус200 OK + результат/ошибка

Поддерживаемые эндпоинты

Streaming на async-эндпоинтах не поддерживается.

Тип запросаОтправка (POST)Опрос (GET)
Text completions/v1/async/completions/v1/async/completions/{job_id}
Chat completions/v1/async/chat/completions/v1/async/chat/completions/{job_id}
Responses API/v1/async/responses/v1/async/responses/{job_id}
Embeddings/v1/async/embeddings/v1/async/embeddings/{job_id}
Speech/v1/async/audio/speech/v1/async/audio/speech/{job_id}
Transcriptions/v1/async/audio/transcriptions/v1/async/audio/transcriptions/{job_id}
Image generations/v1/async/images/generations/v1/async/images/generations/{job_id}
Image edits/v1/async/images/edits/v1/async/images/edits/{job_id}
Image variations/v1/async/images/variations/v1/async/images/variations/{job_id}
Rerank/v1/async/rerank/v1/async/rerank/{job_id}

Отправка запроса

Используйте то же тело JSON, что и для синхронного эндпоинта, заменив путь на /v1/async/.

curl -X POST http://localhost:8080/v1/async/chat/completions \
  -H "Content-Type: application/json" \
  -H "x-bf-vk: sk-bf-your-virtual-key" \
  -H "x-bf-async-job-result-ttl: 3600" \
  -d '{
    "model": "openai/gpt-4o-mini",
    "messages": [
      {
        "role": "user",
        "content": "Summarize the latest release notes in 3 bullets"
      }
    ]
  }'

Ответ (202 Accepted):

{
  "id": "1e89b165-d4fe-49e8-beb2-3e157f2df02f",
  "status": "pending",
  "created_at": "2026-02-19T08:10:17.831Z"
}

Опрос результата

Делайте GET на соответствующий эндпоинт, передавая полученный job_id.

curl -X GET http://localhost:8080/v1/async/chat/completions/1e89b165-d4fe-49e8-beb2-3e157f2df02f \
  -H "x-bf-vk: sk-bf-your-virtual-key"

Коды ответа:

  • 202 Accepted — job в статусе pending или processing.
  • 200 OK — job в статусе completed или failed.

Пример pending (202):

{
  "id": "1e89b165-d4fe-49e8-beb2-3e157f2df02f",
  "status": "pending",
  "created_at": "2026-02-19T08:10:17.831Z"
}

Пример completed (200):

{
  "id": "1e89b165-d4fe-49e8-beb2-3e157f2df02f",
  "status": "completed",
  "created_at": "2026-02-19T08:10:17.831Z",
  "completed_at": "2026-02-19T08:10:19.412Z",
  "expires_at": "2026-02-19T09:10:19.412Z",
  "status_code": 200,
  "result": {
    "id": "chatcmpl-123",
    "object": "chat.completion"
  }
}

Пример failed (200):

{
  "id": "1e89b165-d4fe-49e8-beb2-3e157f2df02f",
  "status": "failed",
  "created_at": "2026-02-19T08:10:17.831Z",
  "completed_at": "2026-02-19T08:10:19.412Z",
  "expires_at": "2026-02-19T09:10:19.412Z",
  "status_code": 429,
  "error": {
    "error": {
      "message": "rate limit exceeded",
      "type": "rate_limit_error"
    }
  }
}

Жизненный цикл job

СтатусЗначениеТриггер перехода
pendingЗапись о job создана и поставлена в очередьСразу при отправке
processingФоновый воркер взял job в работуВоркер начал исполнение
completedОперация успешна, результат сохранёнВызов провайдера завершился успешно
failedОперация упала, ошибка сохраненаВызов провайдера вернул Meridian-ошибку

TTL и истечение результата

  • TTL по умолчанию — 3600 секунд (1 час).
  • TTL отсчитывается от момента завершения, а не от момента отправки.
  • Серверное значение по умолчанию задаётся в client.async_job_result_ttl.
  • Переопределение на уровне запроса — заголовком x-bf-async-job-result-ttl.
  • Если значение заголовка некорректно или <= 0, Meridian использует дефолтный TTL.
  • Истёкшие jobs возвращают 404 Job not found or expired.
  • Очистка истёкших async-jobs выполняется раз в минуту.

Авторизация по виртуальному ключу

  • Если job создан с виртуальным ключом, его привязка сохраняется вместе с job.
  • Опрос должен выполняться с тем же значением виртуального ключа.
  • Отсутствие или несовпадение виртуального ключа приведут к 404 Job not found or expired.
  • Jobs, созданные без виртуального ключа, не привязаны к VK — их может опросить любой клиент, прошедший аутентификацию/middleware шлюза.

Observability

  • Async-запуски логируются так же, как и синхронные запросы.
  • В метаданных логов выставляется isAsyncRequest: true, что отображается значком Async в UI логов.
  • Фоновое исполнение использует те же request-API Meridian, поэтому LLM-хуки плагинов (governance, логирование, учёт стоимости и т. д.) выполняются на момент реального inference-запуска.

Ограничения

  • Функция доступна только на уровне шлюза.
  • Streaming на async-эндпоинтах не поддерживается.
  • Для регистрации async-роутов требуется Logs Store.
  • Jobs, застрявшие в статусе processing, не очищаются по TTL автоматически. Очистка удаляет только jobs с заданным expires_at (completed/failed).

Содержание