feat(photo-ai): официальный CodeFormer вендорен, веса на этапе сборки
CodeFormer был написан по API сторонней обёртки с PyPI (rohitkhatri): CodeFormer(..., device=..., fp16=False) и net.device официальный класс не принимает — вызов падал бы с TypeError. В photo-ai/vendor/codeformer вендорен официальный sczhou/CodeFormer (codeformer_arch.py + vqgan_arch.py, b33cc7d, лицензия S-Lab 1.0), устройство передаётся через net.to(device), чекпоинт читается из params_ema. Веса больше не качаются лениво при первом запросе: fetch-weights.py на сборке образа кладёт их в /opt/photo-ai-seed (build-arg PHOTO_AI_PREFETCH, дефолт codeformer), при старте seed_weights() переносит их в том photo-ai-models:/models/weights. Том переживает пересборку образа, BuildKit-кэш не даёт качать повторно, недоступная сеть на сборке не роняет образ.
This commit is contained in:
@@ -132,7 +132,7 @@ REDIS_PASSWORD=случайная-длинная-строка
|
||||
| `PHOTO_AI_MAX_PIXELS` | `4000000` | Максимум пикселей входного изображения, вход большего размера уменьшается |
|
||||
| `PHOTO_AI_DEVICE` | `auto` | Устройство инференса: `auto` (CUDA, если контейнеру выдан GPU, иначе CPU), `cuda`, `cpu`. Явный `cuda` без CUDA не роняет сервис: WARN в лог и работа на CPU |
|
||||
| `PHOTO_AI_TILE` | `256` | Размер тайла инференса (`0` — без тайлов): меньше тайл — меньше памяти, но медленнее |
|
||||
| `PHOTO_AI_FACE_MODEL` | `gfpgan` | Модель восстановления лиц: `gfpgan`; `codeformer` доступен только при вендоринге модуля в `photo-ai/vendor` |
|
||||
| `PHOTO_AI_FACE_MODEL` | `gfpgan` | Модель восстановления лиц: `gfpgan` или `codeformer` (официальный модуль вендорен в `photo-ai/vendor/codeformer`, доступен сразу) |
|
||||
| `PHOTO_AI_LOAD_ALL` | `0` | Загружать все модели при старте (`1`) или лениво по требованию (`0`) |
|
||||
| `PHOTO_AI_JPEG_QUALITY` | `92` | Качество JPEG результата, 70..100 |
|
||||
| `PHOTO_AI_FACE_TIMEOUT_MS` | `600000` | Таймаут заданий с восстановлением лиц (мс) |
|
||||
@@ -140,6 +140,32 @@ REDIS_PASSWORD=случайная-длинная-строка
|
||||
| `PHOTO_AI_SOFT_BACKOFF_MS` | `10000` | Первая пауза перед мягким повтором |
|
||||
| `PHOTO_AI_SOFT_BACKOFF_MAX_MS` | `300000` | Потолок паузы (задержка растёт вдвое) |
|
||||
|
||||
### Модели лиц и где лежат веса
|
||||
|
||||
Face-модели доступны обе: `gfpgan` (дефолт) и `codeformer`. Модуль `codeformer` — официальный
|
||||
`sczhou/CodeFormer` (`b33cc7d`), вендорен в `photo-ai/vendor/codeformer/` (`codeformer_arch.py`
|
||||
+ `vqgan_arch.py`, лицензия S-Lab 1.0 лежит рядом). Отдельный пакет с PyPI не используется: там лежит
|
||||
сторонняя обёртка `rohitkhatri`, которая тянет свой `facelib` и `lpips`. Модуль попадает в образ
|
||||
через `COPY vendor/` и подхватывается `sys.path` в `app.py` — правки Dockerfile не требуется.
|
||||
|
||||
Веса **не** лежат в репозитории и **не** скачиваются при первом запросе: на сборке образа
|
||||
`fetch-weights.py` кладёт их в `/opt/photo-ai-seed`, а при старте сервис переносит их в том
|
||||
`photo-ai-models:/models/weights` (`seed_weights()`). Дальше модель живёт в томе и переживает
|
||||
пересборку образа; если её нет ни в томе, ни в образе, работает старый ленивый заозагрузчик.
|
||||
Сам файл качается в BuildKit-кэш `/var/cache/photo-ai-weights`, поэтому повторная сборка
|
||||
(и сборка с другим `PHOTO_AI_PREFETCH`) берёт его оттуда и заново не качает.
|
||||
|
||||
| Сборка | Что скачает |
|
||||
|---|---|
|
||||
| `docker compose build photo-ai` | `codeformer` (дефолт `PHOTO_AI_PREFETCH=codeformer`) |
|
||||
| `PHOTO_AI_PREFETCH=face docker compose build photo-ai` | `codeformer` + `gfpgan` |
|
||||
| `PHOTO_AI_PREFETCH=all docker compose build photo-ai` | всё: апскейлы, face-модели, веса facexlib |
|
||||
| `PHOTO_AI_PREFETCH=none docker compose build photo-ai` | ничего, веса качаются лениво в том |
|
||||
|
||||
Переменная `PHOTO_AI_PREFETCH` — именно build-arg, он читается при сборке образа, а не контейнера
|
||||
(в `.env.example` она есть, чтобы задать значение один раз). Скачивание при сборке не роняет образ:
|
||||
при недоступной сети шаг пишет предупреждение, сервис докачает веса при первом использовании.
|
||||
|
||||
### Запуск на NVIDIA GPU
|
||||
|
||||
GPU не обязателен: без него сервис работает на CPU. Чтобы включить GPU-вариант, нужен драйвер NVIDIA
|
||||
@@ -168,9 +194,7 @@ GPU выдаётся контейнеру ключом `gpus: all`, поэтом
|
||||
генерации, поэтому после переподключения видеокарты или смены порта она начинает ссылаться на
|
||||
несуществующий узел, и контейнер не стартует с `CDI device injection failed: failed to stat CDI host
|
||||
device /dev/dri/cardN`. Перегенерация спеки требует sudo и теряется при каждой перегенерации;
|
||||
`gpus: all` от этого свободен. Если nvidia-runtime уже зарегистрирован в
|
||||
демоне (`nvidia-ctk runtime configure --runtime=docker`), в оверрайде можно вместо этого указать
|
||||
`deploy.resources.reservations.devices` с `driver: nvidia, count: 1` — результат тот же.
|
||||
`gpus: all` от этого свободен.
|
||||
|
||||
Проверка результата: в `/health` должны быть `device: cuda:0`, `half: true`, непустые
|
||||
`vram_total_mb`/`vram_free_mb`. На 4 ГБ (например, RTX 3050 Laptop) реально держатся одновременно
|
||||
|
||||
Reference in New Issue
Block a user