Code-style guide and reference patterns for DL/CV research at the ЛИСАД laboratory (NADEZHDA / SOFIA CVGL projects). Files: - Стандарт написания кода для DL CV исследований (CVGL).md - Правила написания Python-кода (Gin-Config Strict Pattern).md - REQUIREMENTS_GIN_STYLE.md - Gin-Config Strict Pattern Reference Examples.md - Переход от argparse и dataclass к gin-config.md - gin-parse.md - Рекомендуемые gin-config категории.md - config_loader_reference.py - README.md (this commit) - .gitignore (Python artifacts)
13 KiB
13 KiB
Требования к адаптации кода под gin-config стиль
Референсный проект: test_bb_uav
1. Структура директорий
Создать директорию для конфигурационных файлов:
depth_edges_annotate_worlduav/
├── in/
│ └── config_files/
│ ├── pipeline.gin # Стадии пайплайна, пути, форматы вывода
│ ├── hardware.gin # Профили GPU, batch size, FP16, workers
│ ├── models.gin # Идентификаторы моделей, fallback-стратегии
│ ├── input.gin # Размер изображений, нормализация, аугментации
│ └── segmentation.gin # Текстовые промпты, параметры сегментации
├── src/
│ ├── conf/
│ │ ├── __init__.py
│ │ ├── pipeline_conf.py # PipelineConfig (пути, стадии, resume, вывод)
│ │ ├── hardware_conf.py # HardwareConfig (GPU, batch, FP16, workers)
│ │ ├── models_conf.py # ModelsConfig (model IDs, fallback)
│ │ ├── input_conf.py # InputConfig (размер, нормализация)
│ │ └── seg_conf.py # SegConfig (промпты, параметры)
│ ├── augmentor/
│ │ ├── ... # Существующие модули (без изменения структуры)
│ └── augment_dataset.py # Точка входа (адаптировать)
2. Паттерн конфигурационных классов
Каждый конфиг-класс следует единому шаблону из test_bb_uav:
import gin
@gin.configurable
class HardwareConfig:
def __init__(self, profile_name='rtx4090', use_fp16=True,
batch_size=None, num_workers=4, reserve_gb=2.0):
self.profile_name = profile_name
self.use_fp16 = use_fp16
self.batch_size = batch_size
self.num_workers = num_workers
self.reserve_gb = reserve_gb
Правила:
- Декоратор
@gin.configurableтолько на классах (не на функциях) - Все параметры имеют значения по умолчанию в
__init__ - Класс хранит параметры как атрибуты экземпляра (
self.param = param) - Не использовать dataclass совместно с gin — заменить dataclass на обычные классы
- Допустима пост-обработка в
__init__(вычисление производных значений)
3. Загрузка конфигов
3.1 Центральный загрузчик (ПРОДАКШЕН)
Один файл src/conf/config_loader.py содержит единственную функцию, которая парсит все .gin файлы за один вызов:
def load_all_configs(path2cfg: str) -> dict[str, Any]:
"""Parse ALL .gin files at once and return all config objects."""
gin.clear_config() # ОБЯЗАТЕЛЬНО: сброс глобального состояния gin
gin_files = sorted(Path(path2cfg).glob("*.gin"))
gin.parse_config_files_and_bindings(
config_files=[str(f) for f in gin_files],
bindings=[],
)
return {
"pipeline": PipelineConfig(),
"hardware": HardwareConfig(),
"models": ModelsConfig(),
"input": InputConfig(),
"seg": SegConfig(),
}
Правила:
gin.clear_config()обязателен перед каждой загрузкой — без него параметры от предыдущих вызовов накапливаются (gin имеет глобальное состояние)- Все .gin файлы парсятся одним вызовом
gin.parse_config_files_and_bindings() - Конфиг-объекты создаются после полной загрузки всех .gin
- В main() — один вызов
load_all_configs(), не 5 отдельныхget_*_cfg()
3.2 Индивидуальные загрузчики (ТОЛЬКО ДЛЯ ТЕСТИРОВАНИЯ)
Для unit-тестов и отладки — отдельные get_<name>_cfg() функции в том же файле:
def get_hardware_cfg(path2cfg: str) -> HardwareConfig:
"""Load ONLY hardware config (for isolated testing)."""
gin.clear_config() # Обязательно!
gin.parse_config_file(f"{path2cfg}hardware.gin")
return HardwareConfig()
Правила:
- Имя функции:
get_<name>_cfg(path2cfg: str) -> ConfigClass - Обязательно
gin.clear_config()передgin.parse_config_file() - Используются только в тестах и notebooks, не в main()
Референс: develop_style_prompt/config_loader_reference.py
4. Формат .gin файлов
Плоский формат ClassName.param = value:
# hardware.gin
HardwareConfig.profile_name = 'rtx4090'
HardwareConfig.use_fp16 = True
HardwareConfig.batch_size = 8
HardwareConfig.num_workers = 4
HardwareConfig.reserve_gb = 2.0
Правила:
- Одна строка — один параметр
- Комментарии через
# - Строки в одинарных или двойных кавычках
- Списки в квадратных скобках:
[1, 2, 3] - Не использовать макросы, ссылки,
gin.constant()или другие продвинутые фичи gin - Каждый
.ginфайл соответствует одному конфиг-классу
5. Точка входа (main)
Адаптировать augment_dataset.py — использовать центральный загрузчик:
from src.conf.config_loader import load_all_configs
from src.utils.utils_file_dir import get_proj_dir
def main() -> None:
proj_dir = get_proj_dir()
path2cfg = f"{proj_dir}in/config_files/"
# ОДИН вызов загружает ВСЕ конфиги:
configs = load_all_configs(path2cfg)
# Явная передача в пайплайн:
run_pipeline(
configs["pipeline"],
configs["hardware"],
configs["models"],
configs["input"],
configs["seg"],
)
# Ищем pyproject.toml или .git как корень проекта:
MARKERS = ("pyproject.toml", ".git", "in")
def get_proj_dir() -> str:
current = Path(__file__).resolve().parent
for _ in range(10):
if any((current / m).exists() for m in MARKERS):
return str(current) + "/"
current = current.parent
raise RuntimeError("Project root not found")
Правила:
- Убрать
argparse— все параметры из gin-файлов - Один вызов
load_all_configs()вместо 5 отдельныхget_*_cfg() gin.clear_config()вызывается внутриload_all_configs()автоматически- Конфиг-объекты передаются явно через аргументы (не через глобальный gin)
- Функция
get_proj_dir()определяет корень проекта автоматически
6. Распределение параметров по конфиг-классам
PipelineConfig (pipeline.gin)
| Параметр | Тип | По умолчанию | Описание |
|---|---|---|---|
input_root |
str | — | Путь к входным данным |
output_root |
str | — | Путь для выходных данных |
stages |
list | ['depth', 'edges', 'segmentation'] |
Стадии пайплайна |
save_npy |
bool | True |
Сохранять .npy файлы |
save_vis |
bool | True |
Сохранять визуализации |
save_concat |
bool | True |
Сохранять 6-канальный результат |
resume |
bool | True |
Пропускать уже обработанные |
subset |
str | None |
Фильтр по подмножеству |
source |
str | None |
Фильтр по источнику (query/db) |
log_level |
str | 'INFO' |
Уровень логирования |
HardwareConfig (hardware.gin)
| Параметр | Тип | По умолчанию | Описание |
|---|---|---|---|
profile_name |
str | 'rtx4090' |
Имя профиля GPU |
use_fp16 |
bool | True |
Использовать half precision |
batch_size |
int | None |
Размер батча (None = авто) |
num_workers |
int | 4 |
Число DataLoader workers |
reserve_gb |
float | 2.0 |
Резерв VRAM в ГБ |
ModelsConfig (models.gin)
| Параметр | Тип | По умолчанию | Описание |
|---|---|---|---|
depth_model_id |
str | 'depth-anything/...' |
HuggingFace ID модели глубины |
depth_fallback_id |
str | '...' |
Fallback модель глубины |
seg_model_id |
str | '...' |
ID модели сегментации |
seg_fallback_id |
str | '...' |
Fallback модель сегментации |
depth_model_size |
str | 'Large' |
Размер модели глубины |
seg_model_size |
str | 'b5' |
Размер модели сегментации |
InputConfig (input.gin)
| Параметр | Тип | По умолчанию | Описание |
|---|---|---|---|
image_size |
int | 256 |
Размер изображения |
sobel_blur_ksize |
int | 3 |
Ядро Sobel для edges |
edge_normalize |
bool | True |
Нормализация карты краев |
SegConfig (segmentation.gin)
| Параметр | Тип | По умолчанию | Описание |
|---|---|---|---|
prompts |
list | [...] |
Текстовые промпты для OV-сегментации |
threshold |
float | 0.3 |
Порог сегментации |
7. Миграция существующих модулей
Что удалить:
argparseизaugment_dataset.py@dataclassизAugmentConfigиHardwareProfileвconfig.py- Словарь
PROFILESс хардкодом профилей (перенести в gin) DEFAULT_GEO_PROMPTSизmodels.py(перенести в gin)
Что сохранить:
- Структуру
src/augmentor/(dataset, inference, models, io_utils) - Логику fallback при загрузке моделей (но model ID из конфига)
- Логику discover_images, AugmentDataset
- Функции сохранения (save_depth, save_edges, save_segmentation)
Что адаптировать:
- Все функции, принимающие
AugmentConfig, должны принимать отдельные конфиг-объекты - Захардкоженные значения (model IDs, промпты, размер 256) — в gin-файлы
pipeline_256.py— удалить или адаптировать под новый стиль
8. Ограничения по использованию gin
Использовать минимальный набор возможностей gin:
- Да:
@gin.configurable,gin.parse_config_file() - Нет:
gin.register(),gin.constant(),gin.query_parameter(), макросы, ссылки между конфигами - Значения конфигов можно менять в runtime после загрузки (
config.param = new_value)
9. Порядок выполнения миграции
- Создать
src/conf/с конфиг-классами и функциями загрузки - Создать
in/config_files/с.ginфайлами - Адаптировать
augment_dataset.py— заменить argparse на gin-загрузку - Адаптировать
augmentor/models.py— model IDs из конфига - Адаптировать
augmentor/inference.py— параметры из конфига - Адаптировать
augmentor/dataset.py— принимать конфиг-объекты - Удалить старый
config.py(dataclass-версию) - Проверить, что
depth_edges_gen.pyиdepth_anything_v2_generate.pyиспользуют новые конфиги - Удалить или адаптировать
pipeline_256.py