Initial commit — gin-config strict-pattern coding standard
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)
This commit is contained in:
278
REQUIREMENTS_GIN_STYLE.md
Normal file
278
REQUIREMENTS_GIN_STYLE.md
Normal file
@@ -0,0 +1,278 @@
|
||||
# Требования к адаптации кода под 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`:
|
||||
|
||||
```python
|
||||
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 файлы за один вызов:
|
||||
|
||||
```python
|
||||
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()` функции в том же файле:
|
||||
|
||||
```python
|
||||
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`:
|
||||
|
||||
```gin
|
||||
# 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` — использовать центральный загрузчик:
|
||||
|
||||
```python
|
||||
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"],
|
||||
)
|
||||
```
|
||||
|
||||
```python
|
||||
# Ищем 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. Порядок выполнения миграции
|
||||
|
||||
1. Создать `src/conf/` с конфиг-классами и функциями загрузки
|
||||
2. Создать `in/config_files/` с `.gin` файлами
|
||||
3. Адаптировать `augment_dataset.py` — заменить argparse на gin-загрузку
|
||||
4. Адаптировать `augmentor/models.py` — model IDs из конфига
|
||||
5. Адаптировать `augmentor/inference.py` — параметры из конфига
|
||||
6. Адаптировать `augmentor/dataset.py` — принимать конфиг-объекты
|
||||
7. Удалить старый `config.py` (dataclass-версию)
|
||||
8. Проверить, что `depth_edges_gen.py` и `depth_anything_v2_generate.py` используют новые конфиги
|
||||
9. Удалить или адаптировать `pipeline_256.py`
|
||||
Reference in New Issue
Block a user