diff --git a/.dockerignore b/.dockerignore index 0ecb00b..38f1110 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,8 +1,9 @@ # .dockerignore # Цель: контекст сборки должен быть маленьким. Образ собирается из src, -# requirements.txt и run.sh (см. Dockerfile); чекпоинт в образ не копируется, а -# монтируется в /app/models при запуске. Данные, тесты и служебные файлы -# исключаются — DICOM-датасет не должен попадать в образ с медицинскими данными. +# requirements.txt, run.sh и чекпоинта models/dxa_model.pth — он закоммичен в +# репозиторий и копируется внутрь образа (см. Dockerfile), поэтому модели не +# нужно монтировать при запуске. Данные, тесты и служебные файлы исключаются — +# DICOM-датасет не должен попадать в образ с медицинскими данными. __pycache__ **/__pycache__ *.pyc diff --git a/Dockerfile b/Dockerfile index c3daaa5..6776d9a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,12 +1,13 @@ # DXA Quality Assessment — контейнер для инференса (CPU) # -# Сборка: docker build -t rell.ru:5000/rell-bone-2026:latest . -# Запуск: docker run -v /data/bone_2026/models:/app/models:ro -p 8000:8000 dxa-quality +# Сборка: docker build -t dxa-quality . +# Запуск: docker run -p 8000:8000 dxa-quality +# или: docker compose up -d (сервис dxa-cpu) # -# Веса в образ НЕ копируются: swarm монтирует каталог с чекпоинтом в -# /app/models только для чтения, а models/ не попадает в git (см. .gitignore), -# поэтому COPY models ломал бы сборку в CI. Путь к чекпоинту берётся из -# DXA_MODEL_PATH и по умолчанию указывает на смонтированный каталог. +# Чекпоинт лежит ВНУТРИ образа: models/dxa_model.pth отслеживается git (каталог +# models/ не исключён в .gitignore) и копируется на этапе сборки. Монтировать +# пути не нужно — условие приёмки в том, что модели уже в образе. Если всё-таки +# смонтировать каталог в /app/models, он перекроет встроенный чекпоинт. # # Требования методики: зафиксированные версии зависимостей и работа без # внешних сервисов. Inference не скачивает веса из сети — они внутри @@ -40,8 +41,7 @@ COPY run.sh ./run.sh RUN chmod +x ./run.sh # Smoke-проверка импорта: падает на сборке, если расходятся зависимости или -# модуль не найден, вместо тихой 500-й на каждом запросе в рантайме. Модель -# здесь не загружается — чекпоинта в контексте сборки нет. +# модуль не найден, вместо тихой 500-й на каждом запросе в рантайме. RUN python -c "import src.main; print('app import ok')" # --- Проверка статики для офлайн-работы --- @@ -54,6 +54,21 @@ RUN python -c "import os; \ assert not missing, f'missing frontend assets: {missing}'; \ print('frontend assets ok')" +# --- Чекпоинт внутри образа --- +# Условие приёмки: модель уже в образе, чтобы проверяющему не приходилось +# указывать путь к каталогу с весами. models/dxa_model.pth отслеживается git, +# поэтому копирование работает и в CI. +COPY models/dxa_model.pth /app/models/dxa_model.pth + +# Проверка, что чекпоинт читается и содержит всё нужное для инференса: без этого +# битый или забытый файл проявился бы только в рантайме как model_loaded: false +# и HTTP 500 на каждый запрос анализа. +RUN python -c "import torch; \ + ckpt=torch.load('/app/models/dxa_model.pth', map_location='cpu', weights_only=False); \ + missing=[k for k in ('model_state_dict','backbone','head','threshold') if k not in ckpt]; \ + assert not missing, f'checkpoint missing keys: {missing}'; \ + print('checkpoint ok:', ckpt['backbone'], ckpt['head'], 'threshold', ckpt['threshold'])" + # Каталоги монтирований swarm: создаём заранее, чтобы образ вёл себя одинаково # и при обычном `docker run` без volume. RUN mkdir -p /app/data /app/logs diff --git a/Dockerfile_cuda b/Dockerfile_cuda index a1fdcc0..29c53e0 100644 --- a/Dockerfile_cuda +++ b/Dockerfile_cuda @@ -1,71 +1,106 @@ -# DXA Quality Assessment - Docker Container (GPU / CUDA) -# Build: docker build -f Dockerfile_cuda -t dxa-quality-cuda . -# Run: docker run --gpus all -v /path/to/data:/data -v /path/to/models:/app/models \ -# -p 8000:8000 dxa-quality-cuda +# DXA Quality Assessment — контейнер для инференса (GPU / CUDA) +# +# Сборка: docker build -f Dockerfile_cuda -t dxa-quality:cuda . +# Запуск: docker run --gpus all -p 8000:8000 dxa-quality:cuda +# или: docker compose --profile cuda up -d dxa-cuda +# +# База — тот же python:3.11-slim, что и у CPU-варианта, а CUDA и cuDNN приходят +# внутри колёс torch с индексом cu126. Отдельный nvidia/cuda-образ не нужен: +# контейнеру достаточно драйвера хоста, который подставляет +# nvidia-container-toolkit по флагу --gpus all (или секции deploy в compose). +# Требуется драйвер NVIDIA >= 525; для H200 (sm_90) в кластере он заведомо новее. +# +# Индекс cu118 в прежней версии файла не работал: torch 2.8.0 под CUDA 11.8 не +# публикуется (последняя версия там — 2.7.1), поэтому сборка падала на pip. +# Для 2.8.0 доступны только cu126 и cu128; выбран cu126 как наиболее +# распространённый. Под H200 нужен torch>=2.5, sm_90 поддерживается. +# +# Чекпоинт лежит ВНУТРИ образа (см. Dockerfile): монтировать пути не нужно. +FROM python:3.11-slim -# Base image with GPU support -FROM nvidia/cuda:11.8.0-cudnn8-runtime-ubuntu22.04 - -# Неинтерактивный режим для apt -ENV DEBIAN_FRONTEND=noninteractive - -RUN apt-get update && apt-get install -y \ - python3.10 \ - python3-pip \ - python3.10-dev \ - python3.10-venv \ - build-essential \ - ninja-build \ - libgl1-mesa-glx \ +# libgl1/libglib2.0-0 нужны opencv (импортируется через зависимости проекта), +# libgomp1 — для параллельных циклов torch. Список совпадает с CPU-образом. +RUN apt-get update && apt-get install -y --no-install-recommends \ + libgl1 \ libglib2.0-0 \ - libsm6 \ - libxext6 \ - libxrender1 \ libgomp1 \ && rm -rf /var/lib/apt/lists/* -# Обновляем pip и ставим свежий meson (0.64.0+) — ДО всех Python-пакетов -RUN pip3 install --no-cache-dir --upgrade pip "meson>=0.64.0" - WORKDIR /app -# --- PyTorch под CUDA 11.8 (ставим отдельно, чтобы не тянулся CUDA 12.6) --- -RUN pip3 install --no-cache-dir \ - torch==2.8.0 torchvision==0.23.0 \ - --index-url https://download.pytorch.org/whl/cu118 +# --- PyTorch под CUDA 12.6 --- +# CUDA-колёса ставим первыми и с явным индексом: иначе pip взял бы с PyPI сборку +# под CUDA 12.6/12.8 произвольной ревизии. torchvision 0.23.0 — парная к torch +# 2.8.0 версия (другие комбинации несовместимы). +RUN pip install --no-cache-dir --upgrade pip \ + && pip install --no-cache-dir \ + --index-url https://download.pytorch.org/whl/cu126 \ + torch==2.8.0 torchvision==0.23.0 # --- Остальные зависимости --- -# Список версий один на оба образа: requirements.txt. Уже установленный torch -# pip не переустановит — версия из cu118 удовлетворяет требованию. +# Отдельным слоем и после torch: список версий один на оба образа +# (requirements.txt), а уже установленный torch==2.8.0+cu126 pip повторно не +# поставит — требование torch==2.8.0 считается выполненным, потому что локальная +# метка сборки при сравнении версий не учитывается. COPY requirements.txt ./ -RUN pip3 install --no-cache-dir -r requirements.txt +RUN pip install --no-cache-dir -r requirements.txt -# --- Код приложения --- +# --- Код --- COPY src ./src + +# Скрипт пакетной обработки (оценка берёт его из корня образа). COPY run.sh ./run.sh RUN chmod +x ./run.sh -RUN mkdir -p models -# Smoke-проверка импорта: падает на сборке, если зависимость недоступна или -# модуль не найден, вместо тихой 500-й в рантайме. Чекпоинт здесь не читается. -RUN python3 -c "import src.main; print('app import ok')" +# Smoke-проверка импорта: падает на сборке, если расходятся зависимости или +# модуль не найден, вместо тихой 500-й на каждом запросе в рантайме. +RUN python -c "import src.main; print('app import ok')" # --- Проверка статики для офлайн-работы --- -# Tailwind и FontAwesome лежат в src/api/static, обращений к CDN быть не должно. -RUN python3 -c "import os; \ +# Веб-интерфейс не должен зависеть от CDN: Tailwind и FontAwesome лежат в +# src/api/static/vendor и src/api/static/webfonts (см. index.html). +RUN python -c "import os; \ files=['src/api/static/vendor/tailwind.js','src/api/static/vendor/fontawesome.css', \ 'src/api/static/webfonts/fa-solid-900.woff2']; \ missing=[f for f in files if not os.path.exists(f)]; \ assert not missing, f'missing frontend assets: {missing}'; \ print('frontend assets ok')" -# Expose API port -EXPOSE 8000 +# --- Чекпоинт внутри образа --- +# Условие приёмки: модель уже в образе, чтобы проверяющему не приходилось +# указывать путь к каталогу с весами. models/dxa_model.pth отслеживается git, +# поэтому копирование работает и в CI. +COPY models/dxa_model.pth /app/models/dxa_model.pth -# Environment variables +# Проверка, что чекпоинт читается и содержит всё нужное для инференса, а также +# что сборка torch видит CUDA: без этого проблемы всплыли бы только в рантайме. +RUN python -c "import torch; \ + ckpt=torch.load('/app/models/dxa_model.pth', map_location='cpu', weights_only=False); \ + missing=[k for k in ('model_state_dict','backbone','head','threshold') if k not in ckpt]; \ + assert not missing, f'checkpoint missing keys: {missing}'; \ + print('checkpoint ok:', ckpt['backbone'], ckpt['head'], 'threshold', ckpt['threshold']); \ + print('torch', torch.__version__, 'cuda built:', torch.version.cuda)" + +# --- Переменные окружения --- +# Читается кодом только DXA_MODEL_PATH (src/main.py). MODEL_PATH, DATA_PATH, +# ANNOTATION_DIR swarm передаёт по инерции от прежней версии — код их не +# использует, и они ни на что не влияют. ENV PYTHONUNBUFFERED=1 \ PYTHONPATH=/app \ - DXA_MODEL_PATH=/app/models/dxa_model.pth + DXA_MODEL_PATH=/app/models/dxa_model.pth \ + MODEL_PATH=/app/models \ + DATA_PATH=/app/data \ + ANNOTATION_DIR=/app/data/annotations -# Default command -CMD ["python3", "-m", "uvicorn", "src.main:app", "--host", "0.0.0.0", "--port", "8000"] +RUN mkdir -p /app/data /app/logs + +EXPOSE 8000 + +# HEALTHCHECK опирается на /api/v1/health, который отдаёт model_loaded. +# На GPU-устройстве старт дольше: даём запас по start-period. +HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \ + CMD python -c "import urllib.request,sys; \ + r=urllib.request.urlopen('http://127.0.0.1:8000/api/v1/health', timeout=5); \ + sys.exit(0 if r.status==200 else 1)" + +CMD ["python", "-m", "uvicorn", "src.main:app", "--host", "0.0.0.0", "--port", "8000"] diff --git a/QWEN.md b/QWEN.md index 3a70f20..e1c2ce3 100644 --- a/QWEN.md +++ b/QWEN.md @@ -297,14 +297,19 @@ position_validator,universal_scorer,medical_quality}.py`) удалены 2026-09 ## Docker ```bash -docker build -t dxa-quality . -docker run -v /path/to/data:/data -p 8000:8000 dxa-quality +docker compose up -d # CPU, http://localhost:8000 +docker compose --profile cuda up -d dxa-cuda # GPU (нужен nvidia-container-toolkit) ``` -Dockerfile ставит зафиксированные версии, копирует только `src/` и `run.sh`, -проверяет импорт приложения и наличие офлайн-ассетов фронтенда на этапе сборки и -имеет HEALTHCHECK. Чекпоинт в образ не копируется — он монтируется в `/app/models` -при запуске (`DXA_MODEL_PATH`). Данные, тесты и `labels/` в образ не попадают +Образы: `Dockerfile` (python:3.11-slim, torch из CPU-индекса) и `Dockerfile_cuda` +(та же база, torch и torchvision из индекса `cu126` — под CUDA 11.8 колёс torch +2.8.0 нет, индекс заканчивается на 2.7.1). Оба собираются из `src/`, +`requirements.txt`, `run.sh` и **чекпоинта**: `models/dxa_model.pth` отслеживается +git и копируется в `/app/models` на этапе сборки, поэтому монтировать пути при +запуске не нужно (условие приёмки — модели уже внутри образа). Сборка проверяет +импорт приложения, наличие офлайн-ассетов фронтенда и читаемость чекпоинта, +образ имеет HEALTHCHECK. Данные, тесты и `labels/` в образ не попадают (`.dockerignore`), поэтому `./run.sh train` внутри контейнера возьмёт метки из имён файлов (с предупреждением); для обучения в контейнере смонтируйте `labels/` -или передайте свой `--labels-csv`. +или передайте свой `--labels-csv`. Если внешний `docker-swarm.yml` монтирует +каталог с моделями в `/app/models`, монтирование перекроет встроенный чекпоинт. diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..0fec134 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,52 @@ +# DXA Quality Assessment — запуск сервиса в контейнере. +# +# Чекпоинт лежит внутри образа (models/dxa_model.pth копируется на этапе сборки), +# поэтому монтировать пути не нужно: ни каталог с моделями, ни данные. +# Данные для анализа загружаются через веб-интерфейс (http://localhost:8000). +# +# CPU — работает на любой машине, ничего кроме docker не требуется: +# docker compose up -d # сервис dxa-cpu, порт 8000 +# +# GPU — H200 и другие ускорители; нужен драйвер NVIDIA и nvidia-container-toolkit: +# docker compose --profile cuda up -d dxa-cuda +# имя сервиса указано явно: без него поднялись бы оба и разошлись по одному порту +# +# Пересобрать после правок кода: docker compose build [dxa-cpu|dxa-cuda] +# Логи: docker compose logs -f dxa-cpu +# Состояние: curl -s localhost:8000/api/v1/health +# Остановить: docker compose down + +name: dxa-quality + +services: + # Обычный инференс на CPU: torch ставится из CPU-индекса, GPU не используется. + dxa-cpu: + image: dxa-quality:cpu + build: + context: . + dockerfile: Dockerfile + ports: + - "8000:8000" + restart: unless-stopped + + # Инференс на GPU: базовый образ тот же, но torch собран под CUDA 12.6. + # Профиль cuda — чтобы на машинах без NVIDIA сервис не мешал запуску по умолчанию. + dxa-cuda: + profiles: ["cuda"] + image: dxa-quality:cuda + build: + context: . + dockerfile: Dockerfile_cuda + ports: + - "8000:8000" + restart: unless-stopped + environment: + NVIDIA_VISIBLE_DEVICES: all + NVIDIA_DRIVER_CAPABILITIES: compute,utility + deploy: + resources: + reservations: + devices: + - driver: nvidia + count: all + capabilities: [gpu] diff --git a/docs/technical-description.html b/docs/technical-description.html index b123fb4..72e9c16 100644 --- a/docs/technical-description.html +++ b/docs/technical-description.html @@ -158,10 +158,10 @@ FastAPI: восемь маршрутов, включая /api/v1/batch и /api/v1/export Разд. 10 Обязательная контейнеризация, скрипт сборки и запуска в Linux - Dockerfile (python:3.11-slim), Dockerfile_cuda для GPU, run.sh - Разд. 14; сборка проверена, см. 14 + Dockerfile (python:3.11-slim, чекпоинт внутри образа), Dockerfile_cuda для GPU, docker-compose.yml на оба случая, run.sh + Разд. 14; сборка и запуск проверены, см. 14 Фиксация зависимостей, включая базовый контейнер - requirements.txt с точными версиями, базовый образ по тегу, torch с CPU-индексом + requirements.txt с точными версиями, базовый образ по тегу, torch с CPU-индексом (CPU-вариант) и cu126 (GPU-вариант) Разд. 14 Работа без обращения к внешним сервисам Офлайн-ассеты фронтенда, отсутствие сетевых вызовов в коде предсказания @@ -185,7 +185,7 @@ Загрузка файлов, таблица результатов, панель деталей, панель «О модели»; все подписи и метрики получает с сервера Эвристики качестваsrc/quality/ Числовые измерения снимка (резкость, плотные включения, полнота и поворот области) для панели деталей - Инфраструктураrun.sh, Dockerfile, Dockerfile_cuda, Jenkinsfile + Инфраструктураrun.sh, docker-compose.yml, Dockerfile, Dockerfile_cuda, Jenkinsfile Единая точка входа для сборки, обучения, инференса и тестов; сборка образа и выкладка @@ -729,16 +729,20 @@ seed'ах. Принято правило «только экспертная т РесурсМинимальная конфигурацияРекомендуемая Процессор2 ядра x86-64 или ARM644 ядра и более; инференс векторизован и масштабируется по кадрам Оперативная память1.5 ГБ (измеренный пик ≈ 640 МБ + запас на ОС и веб-слой)4 ГБ - Графический ускорительНе требуется: torch устанавливается из CPU-индекса, инференс на CPU укладывается в требование по времениЛюбой GPU с поддержкой CUDA 11.8 — вариант сборки Dockerfile_cuda - Дисковое пространствобазовый образ python:3.11-slim (150 МБ) + зависимости и код; чекпоинт 43 МБ монтируется отдельноплюс место под входные архивы DICOM и результаты + Графический ускорительНе требуется: torch устанавливается из CPU-индекса, инференс на CPU укладывается в требование по времениЛюбой GPU с поддержкой CUDA 12.6, включая H200 (compute capability 9.0) — вариант сборки Dockerfile_cuda + Дисковое пространствобазовый образ python:3.11-slim (150 МБ) + зависимости, код и чекпоинт (43 МБ) — всё внутри образаплюс место под входные архивы DICOM и результаты СетьНе требуется при работе: образ и веса фиксированы, обращений во внешние сервисы нетНужна только для сборки образа и загрузки базовых зависимостей -

Размер образа (измерено): 1.41 ГБ (1 412 385 143 байт) для сборки под -linux/arm64. Базовый образ python:3.11-slim занимает 150 МБ, остальное — -зависимости из requirements.txt, включая torch и torchvision из CPU-индекса; CUDA-колёса -в образ не попадают. Данные, тесты, labels/ и assets/ в образ не входят, -чекпоинт (43 МБ) монтируется отдельно.

+

Размер образа (измерено). CPU-вариант: 1.46 ГБ под linux/arm64 и 1.8 ГБ под +linux/amd64. GPU-вариант: 7.0 ГБ под linux/amd64 — почти всё сверх базы +занимают CUDA-библиотеки внутри колёс torch (nvidia-cublas-cu12, +nvidia-cudnn-cu12, nvidia-nccl-cu12 и другие). Базовый образ +python:3.11-slim — 150 МБ; torch и torchvision берутся из CPU-индекса в CPU-варианте и из +индекса cu126 в GPU-варианте, поэтому CUDA-колёса в CPU-образ не попадают (там +torch 2.8.0+cpu и ноль nvidia-пакетов). Данные, тесты, labels/, +assets/ и docs/ в образ не входят; чекпоинт (43 МБ), наоборот, лежит внутри — +монтировать каталог с моделями при запуске не нужно.

14. Сборка, запуск и развёртывание

@@ -746,30 +750,40 @@ seed'ах. Принято правило «только экспертная т - - - - - - + + + + + + +
ЭлементЗначение
Базовый образpython:3.11-slim (фиксированный тег)
Зависимостиrequirements.txt с точными версиями; torch и torchvision — из CPU-индекса PyTorch, чтобы в образ не попали CUDA-колёса
Что копируется в образтолько src/, requirements.txt и run.sh
Что не копируетсяданные, тесты, labels/, assets/, docs/ (см. .dockerignore), а также чекпоинт
Чекпоинтмонтируется при запуске в /app/models; путь задаётся переменной DXA_MODEL_PATH (по умолчанию /app/models/dxa_model.pth)
Проверки на этапе сборкиимпорт приложения (import src.main) и наличие офлайн-ассетов фронтенда; сборка падает при их отсутствии
Базовый образpython:3.11-slim (фиксированный тег); у GPU-варианта он тот же — CUDA и cuDNN приходят внутри колёс torch, отдельный nvidia/cuda-образ не нужен
Зависимостиrequirements.txt с точными версиями; CPU-вариант берёт torch и torchvision из CPU-индекса PyTorch, GPU-вариант — из индекса cu126
Что копируется в образsrc/, requirements.txt, run.sh и чекпоинт models/dxa_model.pth
Что не копируетсяданные, тесты, labels/, assets/, docs/ (см. .dockerignore)
Чекпоинткопируется на этапе сборки и лежит в образе как /app/models/dxa_model.pth; путь задаётся переменной DXA_MODEL_PATH. Монтировать каталог с моделями не нужно
Проверки на этапе сборкиимпорт приложения (import src.main), наличие офлайн-ассетов фронтенда и читаемость чекпоинта (ключи backbone, head, threshold); сборка падает при их отсутствии
Контроль состоянияHEALTHCHECK обращается к /api/v1/health каждые 30 с
Запускdocker-compose.yml: сервис dxa-cpu поднимается по умолчанию, GPU-сервис dxa-cuda — под профилем cuda
Точка входаuvicorn src.main:app на порту 8000
-

Если чекпоинт не смонтирован, сервис всё равно поднимается: /api/v1/health сообщает +

Модель встроена в образ, поэтому штатно чекпоинт всегда на месте. Если файл всё же недоступен +(например, образ повреждён), сервис всё равно поднимается: /api/v1/health сообщает model_loaded: false, а запросы анализа возвращают ошибку вместо тихой неверной оценки. Это сознательный выбор: отсутствие модели должно быть заметно сразу, а не проявляться как «странные» результаты.

-

Что проверено на самом образе. Сборка прошла обе внутренние проверки -(app import ok, frontend assets ok). Образ запущен и проверен в двух режимах: -без смонтированного чекпоинта /api/v1/health отдаёт model_loaded: false и -exists: false, а запрос анализа — HTTP 500 с телом {"error": "Model not loaded"}; -с примонтированным каталогом моделей /api/v1/health сообщает model_loaded: true, -device: cpu, эпоху 39 и файл разметки labels/labels_images.csv, запрос анализа -отвечает корректной строкой результата, а /api/v1/export возвращает XLSX с ожидаемым -набором столбцов. Сквозная проверка выполнялась в контейнере на той же машине, где снимались -измерения производительности.

+

Что проверено на самом образе. Сборка проходит три внутренние проверки: +app import ok, frontend assets ok и +checkpoint ok: resnet18 linear threshold -0.4930129051208496. Контейнер запущен без единого +монтирования (docker run -d -p 8000:8000 dxa-quality:cpu): чекпоинт присутствует внутри +образа (/app/models/dxa_model.pth), /api/v1/health сообщает +model_loaded: true, device: cpu, эпоху 39 и файл разметки +labels/labels_images.csv, запрос /api/v1/analyze отвечает корректной строкой +результата, а /api/v1/export возвращает XLSX с ожидаемым набором столбцов. Сквозная +проверка выполнена в контейнере на той же машине, где снимались измерения производительности. Оба +варианта дополнительно собраны под целевой linux/amd64 (эмуляция на той же машине): +CPU-образ содержит torch 2.8.0+cpu и ни одного nvidia-пакета, GPU-образ — +torch 2.8.0+cu126 с cuDNN 9.10.2 и библиотекой libtorch_cuda.so; в обоих +сервис стартует, и /api/v1/health, /api/v1/analyze и +/api/v1/export отвечают корректно (device: cpu, поскольку ускорителя в машине +нет). Работа на самом GPU не проверялась: для неё нужна машина с драйвером NVIDIA, где критерий +приёмки — torch.cuda.is_available() == True и device: cuda в +/api/v1/health.

14.2. Воспроизводимость

@@ -788,7 +802,10 @@ seed'ах. Принято правило «только экспертная т

Jenkinsfile выполняет три шага: сборка образа, публикация в реестр и выкладка в кластер. Скрипт run.sh — единая точка входа для разработки и эксплуатации: обучение, разметка, приведение имён файлов, инференс, сервис, сравнение вариантов разметки и тесты -(перечень команд — приложение Б).

+(перечень команд — приложение Б). Для запуска образа есть docker-compose.yml с двумя +сервисами (14.1). Файл выкладки swarm (/data/deploy/rell-bone-2026/docker-swarm.yml) лежит +вне репозитория: если он монтирует каталог с моделями в /app/models, монтирование +перекроет встроенный чекпоинт, поэтому его нужно убрать при обновлении выкладки.

15. Тесты и проверки

@@ -968,7 +985,7 @@ seed'ах. Принято правило «только экспертная т ├── models/dxa_model.pth рабочий чекпоинт и отчёт обучения ├── tests/ pytest + браузерные проверки интерфейса ├── docs/ настоящий документ (HTML и PDF) -├── run.sh, Dockerfile, Dockerfile_cuda, Jenkinsfile, requirements.txt +├── run.sh, docker-compose.yml, Dockerfile, Dockerfile_cuda, Jenkinsfile, requirements.txt

Приложение Б. Команды

@@ -987,9 +1004,11 @@ python -m src.dxa.discriminator проверка вклада содер ./run.sh test pytest (209 тестов) node tests/browser/ui_check.js проверки интерфейса (нужен сервер на 127.0.0.1:8123) -# контейнер -docker build -t dxa-quality . -docker run -v /path/to/data:/data -v /path/to/models:/app/models -p 8000:8000 dxa-quality +# контейнер (чекпоинт лежит внутри образа, монтировать пути не нужно) +docker compose up -d CPU-сервис в фоне, http://localhost:8000 +docker compose --profile cuda up -d dxa-cuda GPU-сервис (нужен nvidia-container-toolkit) +docker build -t dxa-quality . сборка CPU-образа напрямую +docker run -p 8000:8000 dxa-quality запуск без compose

Документ подготовлен по фактическому состоянию репозитория; машинные отчёты обучения — models/train_report.json, обоснование разметки — assets/labeling.md.

diff --git a/docs/technical-description.pdf b/docs/technical-description.pdf index 280bee3..730116f 100644 Binary files a/docs/technical-description.pdf and b/docs/technical-description.pdf differ