Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Inference Service для sergeyzh/rubert-mini-frida

Небольшой HTTP-сервис для получения эмбеддингов из модели sergeyzh/rubert-mini-frida.


Что умеет сервис

Сервис:

  • принимает текст через POST /embed и возвращает эмбеддинг;
  • загружает модель один раз при старте приложения;
  • имеет служебный эндпоинт GET /health;
  • запускается через Docker;
  • сопровождается тестами и отдельным скриптом для бенчмарка.

Почему был выбран FastAPI

Для реализации сервиса был выбран FastAPI.

Почему именно он:

  • для небольшого inference service это один из самых удобных вариантов по соотношению простоты и возможностей;
  • он позволяет сразу описать понятные схемы запросов и ответов через Pydantic;
  • из коробки даёт валидацию входных данных, что особенно удобно для API;
  • хорошо сочетается с uvicorn и без лишних сложностей запускается в Docker;
  • для сервиса с одним основным эндпоинтом требует совсем немного шаблонного кода.

Структура проекта

  • app/main.py — точка входа в приложение, создание API и загрузка модели при старте;
  • app/service.py — логика подготовки текста, токенизации, mean pooling и нормализации эмбеддинга;
  • benchmarks/runner.py — запуск нагрузочного сценария и сохранение результатов;
  • tests/ — базовые API-тесты.

Эмбеддинги получаются через transformers.


API

GET /health

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

Пример ответа:

{
  "status": "ok",
  "model": "sergeyzh/rubert-mini-frida",
  "dimensions": 312,
  "device": "cpu"
}

POST /embed

Принимает JSON:

{
  "text": "Текст для эмбеддинга",
  "prefix": "categorize: "
}

Поле prefix необязательное. Если его не передать, используется categorize: .

Пример ответа:

{
  "embedding": [0.123, 0.456, 0.789],
  "dimensions": 312,
  "model": "sergeyzh/rubert-mini-frida",
  "prefix_used": "categorize: "
}

Дополнительно сервис пишет время инференса в заголовок X-Inference-Time-Ms.


Запуск через Docker

docker compose up --build -d

После старта сервис будет доступен на http://127.0.0.1:8000.


Запуск тестов

pytest

Тесты покрывают базовую работоспособность эндпоинтов /health и /embed.


Какие метрики были выбраны

Для сервиса были выбраны четыре основные группы метрик:

  1. Latency P50 / P95 / P99
  2. Throughput (RPS)
  3. Model inference time
  4. Memory usage

1. Latency P50 / P95 / P99

Что показывает:
Это полное время ответа HTTP-сервиса.
P50 отражает типичную задержку, а P95 и P99 позволяют увидеть, как сервис ведёт себя в более тяжёлых случаях и насколько сильно растут хвосты распределения под нагрузкой.

Целевые пороги:

  • P95 <= 200 ms
  • P99 <= 250 ms

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

Что делать при нарушении порога:

  • уменьшать лишние накладные расходы в обработчике;
  • проверять сериализацию ответа;
  • выносить тяжёлые операции из request-path;
  • рассматривать ONNX Runtime, квантизацию или запуск нескольких worker-процессов.

2. Throughput (RPS)

Что показывает:
Сколько запросов в секунду сервис может обработать на выбранном железе при фиксированном уровне конкуренции.

Целевой порог:

  • >= 8 RPS

Почему именно такой:
Это умеренное требование для CPU-only окружения и компактной BERT-подобной модели.

Что делать при нарушении порога:

  • увеличивать число процессов;
  • использовать более быстрый runtime;

3. Model inference time

Что показывает:
Время работы самой модели внутри сервиса, без учёта сетевой части и клиентских накладных расходов.

Целевой порог:

  • P95 <= 150 ms

Почему именно такой:
Если большая часть задержки приходится на модель, оптимизация только HTTP-слоя уже почти ничего не даст.

Что делать при нарушении порога:

  • оптимизировать runtime модели;
  • пробовать ONNX Runtime;
  • использовать dynamic quantization;
  • ограничивать длину входного текста.

4. Memory usage

Что показывает:
Базовое и пиковое потребление памяти процессом сервиса после загрузки модели и во время нагрузки.

Целевой порог:

  • peak RSS <= 900 MB

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

Что делать при нарушении порога:

  • проверять, не дублируется ли модель;
  • ограничивать число worker-процессов;
  • уменьшать лишние буферы;
  • переходить на более компактный runtime.

Как устроен бенчмарк

Сценарий в benchmarks/runner.py:

  1. использует уже запущенный Docker-контейнер сервиса
  2. ждёт, пока начнёт отвечать GET /health
  3. выполняет прогрев
  4. отправляет серию POST-запросов на /embed
  5. считает latency p50/p95/p99, throughput, inference time, peak memory
  6. сохраняет результаты в JSON и Markdown

Запуск:

python -m benchmarks.runner

По умолчанию бенчмарк ожидает контейнер rubert-inference-service на http://127.0.0.1:8000.

Если имя контейнера или адрес отличаются, можно переопределить их так:

python -m benchmarks.runner --base-url http://127.0.0.1:8000 --container-name rubert-inference-service

Результаты замеров

Актуальные результаты Docker-прогона сохраняются в:

  • benchmarks/results/docker_cpu.json
  • benchmarks/results/docker_cpu.md

Ниже приведены значения последнего замера, выполненного в этом репозитории.

Стенд замера

  • macOS 14.4 arm64
  • Python 3.11.9
  • CPU: 8 vCPU
  • RAM: 8 GB
  • контейнер: rubert-inference-service
  • сценарий: 120 запросов, concurrency=6, warmup=12
Метрика Значение
Latency mean, ms 149.774
Latency p50, ms 147.895
Latency p95, ms 174.195
Latency p99, ms 181.042
Throughput, RPS 39.007
Inference time mean, ms 25.460
Inference time p95, ms 29.208
Peak RSS, MB 278.500
Delta RSS, MB 8.100

Краткий анализ результатов

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

Что видно по результатам:

  • задержка остаётся в комфортных пределах;
  • P95 и P99 не выходят за заданные ограничения;
  • throughput заметно выше минимального целевого значения;
  • время самого инференса существенно меньше полного HTTP latency;
  • память после загрузки модели ведёт себя стабильно, а рост под нагрузкой остаётся небольшим.

Что было проверено

В рамках задания было реализовано и проверено следующее:

  • API-тесты для /health и /embed;
  • отдельный сценарий нагрузочного теста;
  • реальный запуск сервиса и фактический замер метрик;
  • запуск сервиса через Docker.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages