Skip to content
Архитектура системы

Архитектура системы

Архитектура системы

Архитектурный стиль

Проект организован по принципам слоистой и частично hexagonal architecture. В каждом сервисе можно выделить:

  • core - доменные интерфейсы, перечисления, use cases или сервисы бизнес-логики.
  • infrastructure - реализации хранилищ, брокеров, облачного storage, детекторов, тренеров и DI.
  • presentation - HTTP-роутеры и Pydantic-схемы в API-сервисе.
  • tests - модульные тесты сервисов, репозиториев, фабрик и use cases.

Зависимости в основном направлены внутрь: доменный слой описывает интерфейсы, инфраструктура их реализует, а presentation-слой вызывает сервисы через DI.

Компоненты

schemion-api

FastAPI-приложение. Основные функции:

  • регистрация, вход и обновление JWT-токенов;
  • создание и чтение датасетов, моделей и задач;
  • загрузка файлов в MinIO;
  • публикация сообщений в Bobber;
  • выдача presigned URL для скачивания файлов;
  • SSE-подписка на обновления задачи;
  • административная панель на базе sqladmin;
  • in-memory кэширование списков и отдельных объектов.

Маршруты подключаются в schemion-api/app/main.py:

  • /auth
  • /datasets
  • /models
  • /tasks
  • /admin

schemion-training

Фоновый Python-процесс, который запускается как python -m app.main. Он подписывается на training_queue через BobberClient. При получении сообщения воркер:

  1. открывает сессию PostgreSQL;
  2. создает репозитории задач, моделей и датасетов;
  3. загружает базовые веса модели из MinIO;
  4. загружает ZIP-датасет из MinIO и извлекает YAML-конфигурацию;
  5. создает тренер через DetectorTrainerFactory;
  6. запускает обучение;
  7. сохраняет обученную модель и метрики в MinIO;
  8. обновляет задачу в PostgreSQL;
  9. создает новую пользовательскую модель, связанную с базовой моделью и датасетом.

schemion-inference

Фоновый Python-процесс, который запускается как python -m app.infrastructure.main. Он подписывается на inference_queue. При получении сообщения воркер:

  1. загружает входное изображение из MinIO;
  2. загружает веса модели;
  3. создает детектор через DetectorFactory;
  4. разбивает изображение на тайлы;
  5. выполняет предсказание на каждом тайле;
  6. сдвигает координаты bounding boxes обратно в систему координат исходного изображения;
  7. сохраняет JSON-результат в MinIO;
  8. обновляет задачу в PostgreSQL.

Bobber

Bobber используется как брокер сообщений. API публикует JSON-сообщения в очереди:

  • inference_queue
  • training_queue

Воркеры подписываются на соответствующие очереди и обрабатывают сообщения синхронно внутри callback.

PostgreSQL

PostgreSQL хранит метаданные: пользователей, роли, разрешения, датасеты, модели и задачи. Файлы в базе не хранятся; вместо этого сохраняются объектные пути MinIO.

MinIO

MinIO хранит:

  • ZIP-архивы датасетов;
  • входные изображения или PDF для инференса;
  • веса моделей;
  • JSON-метрики обучения;
  • JSON-результаты инференса.

Поток создания задачи инференса

  1. Клиент вызывает POST /tasks/create/inference с model_id и файлом.
  2. API проверяет существование модели.
  3. API валидирует MIME-тип файла: image/jpeg, image/png или application/pdf.
  4. Файл сохраняется в бакет schemas-images.
  5. В таблице tasks создается задача со статусом queued.
  6. API публикует сообщение в inference_queue.
  7. Inference-воркер меняет статус на running.
  8. Воркер выполняет предсказание и сохраняет результат в бакет inference-results.
  9. Воркер записывает output_path и переводит задачу в succeeded.
  10. При ошибке воркер записывает error_msg и статус failed.

Поток создания задачи обучения

  1. Клиент вызывает POST /tasks/create/training с model_id, dataset_id, image_size, num_epochs и name.
  2. API проверяет существование датасета.
  3. В таблице tasks создается задача со статусом queued.
  4. API публикует сообщение в training_queue.
  5. Training-воркер загружает базовую модель и датасет.
  6. Воркер проверяет, что базовая модель является системной (is_system=True).
  7. Создается тренер: YOLO или Faster R-CNN.
  8. Выполняется обучение.
  9. Новые веса сохраняются в бакет models.
  10. Метрики сохраняются в бакет metrics.
  11. Создается новая запись в models с is_system=False, base_model_id и dataset_id.
  12. Задача переводится в succeeded или failed.

Статусы задач

Задача может находиться в одном из состояний:

  • queued - задача создана и ожидает обработки воркером.
  • running - воркер начал обработку.
  • succeeded - обработка завершена успешно.
  • failed - обработка завершилась ошибкой, причина хранится в error_msg.

Синхронизация результата с клиентом

Клиент может получать состояние задачи двумя способами:

  • периодический REST-запрос GET /tasks/{task_id};
  • SSE-подписка GET /tasks/subscribe/{task_id}.

SSE-эндпоинт раз в секунду читает задачу и отправляет событие task_update, пока статус не станет succeeded или failed.