Inquir Compute · ML-инференс

Инференс ONNX-моделей в функциях на Python

Запускайте обученную модель за HTTP-маршрутом без отдельного model server. Среда выполнения — Python 3.12 на glibc (Debian slim), поэтому manylinux-колёса ставятся чисто: объявите onnxruntime, onnx или scikit-learn в inquir.yaml, и деплой их установит. Положите файл модели внутрь функции — он лежит рядом с обработчиком в /var/task, — загрузите его один раз на холодном старте и переиспользуйте в тёплых вызовах. Это инференс на CPU: GPU нет.

Обновлено: 2026-06-28

  • Python 3.12 на glibc (Debian slim): manylinux-колёса работают, без ограничений edge-изолятов
  • Пакеты в build.dependencies в inquir.yaml: onnxruntime, onnx, scikit-learn
  • Модель в /var/task рядом с обработчиком — загрузка один раз на холодном старте, переиспользование в тёплых
  • Память 256 МБ по умолчанию (до 2 ГБ); таймаут 5 с по умолчанию, настраивается до 24 ч

Суть ответа

Инференс ONNX-моделей в функциях на Python. Inquir запускает Python 3.12 в контейнерах на glibc (Debian slim), поэтому manylinux-колёса ставятся так же, как на обычной Linux-машине. Перечислите onnxruntime, onnx или scikit-learn в build.dependencies в inquir.yaml функции: деплой поставит опубликованные колёса, и класть колесо в исходники не нужно.

Когда подходит

  • Инференс по запросу для небольшой или средней модели, экспортированной в ONNX (классификатор, ранкер, голова эмбеддингов)
  • Модели scikit-learn или другие CPU-модели, которые нужно выставить за HTTP-маршрутом с авторизацией без model server
  • Всплесковый или малообъёмный скоринг, где платить за всегда включённый GPU или контейнер расточительно

На что обратить внимание

  • Edge и V8-изоляты вообще не запускают нативные ML-колёса — onnxruntime поставляет скомпилированный бинарник, и изоляты не могут его загрузить. Так что инференс, которому нужен настоящий процесс CPython, в таких средах выполнения недоступен, какой бы маленькой ни была модель.
  • Даже там, где Python есть, образ на musl (Alpine) ломает готовые manylinux-колёса, которые публикуют onnxruntime и scikit-learn: приходится собирать из исходников или фиксировать старые версии. База на glibc — то, что позволяет колёсам ставиться как опубликовано.

Во что обходится одна обученная модель в продакшене

У вас есть обученная модель — классификатор scikit-learn, экспортированный в ONNX, небольшой градиентный ранкер, голова эмбеддингов. Обычно её обслуживание — это контейнер или model server, работающий круглосуточно, рассчитанный на пик и оплачивающий простой между запросами. Для инференса по запросу, в основном всплескового, это слишком много постоянной инфраструктуры ради функции, которая грузит файл и вызывает session.run().

Сама модель небольшая, а код инференса короткий. Не хватает места, где запускать её по требованию: поставить среду выполнения, держать модель в памяти между вызовами, выставить за HTTP-маршрутом с авторизацией и не платить, когда вызовов нет.

Почему edge и минимальные среды выполнения мешают инференсу

Edge и V8-изоляты вообще не запускают нативные ML-колёса — onnxruntime поставляет скомпилированный бинарник, и изоляты не могут его загрузить. Так что инференс, которому нужен настоящий процесс CPython, в таких средах выполнения недоступен, какой бы маленькой ни была модель.

Даже там, где Python есть, образ на musl (Alpine) ломает готовые manylinux-колёса, которые публикуют onnxruntime и scikit-learn: приходится собирать из исходников или фиксировать старые версии. База на glibc — то, что позволяет колёсам ставиться как опубликовано.

Python на glibc, где ML-колёса ставятся как опубликованы

Inquir запускает Python 3.12 в контейнерах на glibc (Debian slim), поэтому manylinux-колёса ставятся так же, как на обычной Linux-машине. Перечислите onnxruntime, onnx или scikit-learn в build.dependencies в inquir.yaml функции: деплой поставит опубликованные колёса, и класть колесо в исходники не нужно.

Файл модели едет внутри бандла функции и лежит рядом с обработчиком в /var/task. Загрузите его один раз на уровне модуля — на холодном старте — и тёплый пул контейнеров (от 1 до 8 на функцию) переиспользует загруженную сессию между вызовами, так что при стабильном трафике модель не перечитывается на каждый вызов. Инференс идёт на CPU: GPU на платформе нет, поэтому это подходит для небольших и средних моделей, а не для крупных сетей под GPU.

Что покрывает инференс ONNX в функциях

Объявите ONNX Runtime в inquir.yaml

Добавьте onnxruntime (и onnx или scikit-learn при необходимости) в build.dependencies в inquir.yaml — деплой его установит. База на glibc означает, что опубликованное manylinux-колесо грузится как есть.

Модель грузится один раз на холодном старте

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

Инференс за маршрутом с авторизацией

Привяжите обработчик к маршруту шлюза с авторизацией по API-ключу или bearer-токену. Вызывающие шлют признаки JSON-ом по POST; обработчик возвращает предсказания. Память по умолчанию 256 МБ и поднимается до 2 ГБ под крупные модели или батчи.

Батч- или async-инференс

Для одного предсказания отвечайте синхронно в пределах таймаута 5 с по умолчанию. Для объёмного скоринга, который идёт дольше, примите запрос, верните 202 и запускайте инференс в шаге пайплайна (таймаут шага настраивается до 24 часов).

Как обслужить ONNX-модель как функцию

Экспортируйте модель в ONNX, отправьте её с обработчиком, объявите ONNX Runtime в inquir.yaml и выставьте за маршрутом.

1

Экспортируйте и отправьте модель

Экспортируйте обученную модель в ONNX (например, через skl2onnx для оценщика scikit-learn). Положите файл .onnx в бандл функции, чтобы он попал в /var/task рядом с обработчиком.

2

Объявите ONNX Runtime и загрузите модель один раз

Объявите onnxruntime в build.dependencies в inquir.yaml. Создайте InferenceSession на уровне модуля, указав путь к модели в /var/task, чтобы она грузилась на холодном старте и оставалась в тёплых контейнерах.

3

Выставьте и наблюдайте

Привяжите обработчик к маршруту шлюза с авторизацией по API-ключу. Каждый вызов даёт запись прогона — длительность, статус, логи, — чтобы видеть задержку холодного и тёплого пути в истории выполнения.

Обработчик инференса ONNX: загрузка один раз, запуск на каждый запрос

Модель грузится во время импорта (холодный старт) и переиспользуется каждым тёплым вызовом. Обработчик читает признаки из тела запроса и возвращает предсказания. Файл модели лежит рядом с этим обработчиком в /var/task.

inquir.yaml (рядом с обработчиком)
# Python 3.12 on glibc (Debian slim) — manylinux wheels install as published.
build:
  dependencies:
    - onnxruntime>=1.20
    - numpy>=1.26
infer.py (обработчик на Python 3.12)
import os
import json
import numpy as np
import onnxruntime as ort

# Loaded ONCE on cold start, at module scope.
# The model ships inside the function and lives next to this handler in /var/task.
MODEL_PATH = os.path.join(os.path.dirname(__file__), "model.onnx")
_session = ort.InferenceSession(MODEL_PATH, providers=["CPUExecutionProvider"])  # CPU only — no GPU
_input_name = _session.get_inputs()[0].name


def handler(event, context):
    body = json.loads(event.get("body") or "{}")
    features = body.get("features")
    if not features:
        return {"statusCode": 400, "body": json.dumps({"error": "features required"})}

    x = np.asarray(features, dtype=np.float32)
    if x.ndim == 1:
        x = x.reshape(1, -1)  # single row -> batch of 1

    # Warm containers reuse _session — no per-request model load.
    outputs = _session.run(None, {_input_name: x})
    predictions = outputs[0].tolist()
    return {"statusCode": 200, "body": json.dumps({"predictions": predictions})}

Когда уместен инференс ONNX в функциях

Когда это уместно

  • Инференс по запросу для небольшой или средней модели, экспортированной в ONNX (классификатор, ранкер, голова эмбеддингов)
  • Модели scikit-learn или другие CPU-модели, которые нужно выставить за HTTP-маршрутом с авторизацией без model server
  • Всплесковый или малообъёмный скоринг, где платить за всегда включённый GPU или контейнер расточительно

Когда лучше выбрать другое

  • Крупные модели под GPU или низколатентное высоконагруженное обслуживание — GPU нет, а холодные старты на CPU реальны

Частые вопросы

Какая версия Python и базовый образ запускают модель?

Python 3.12 на glibc (Debian slim). Поскольку база — glibc, manylinux-колёса, которые публикуют onnxruntime, onnx и scikit-learn, ставятся и грузятся как есть — без сборки из исходников и без поломок колёс на Alpine/musl.

Как затащить onnxruntime в функцию?

Объявите его в inquir.yaml функции: build.dependencies: ["onnxruntime>=1.20"], плюс onnx или scikit-learn, если нужны. Деплой ставит список через pip; упаковывать ничего вручную не нужно.

Где лежит файл модели и когда он грузится?

Отправьте файл .onnx внутри бандла функции — он попадает рядом с обработчиком в /var/task. Создавайте InferenceSession на уровне модуля, чтобы он грузился один раз на холодном старте; тёплые контейнеры в пуле переиспользуют загруженную сессию между вызовами.

Есть ли GPU?

Нет. Инференс идёт на CPU (CPUExecutionProvider). Это подходит для небольших и средних моделей и оценщиков уровня scikit-learn. Крупные сети под GPU и обучение для этой платформы не подходят.

Какие лимиты памяти и таймаута?

Память по умолчанию 256 МБ и поднимается до 2 ГБ под крупные модели или батчи. Таймаут функции по умолчанию 5 с и настраивается до 24 часов. Для объёмного скоринга дольше этого верните 202 и запускайте инференс в шаге пайплайна.