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:
2026-04-27 17:12:38 +03:00
commit 3278322a17
10 changed files with 1970 additions and 0 deletions

View File

@@ -0,0 +1,439 @@
---
name: code-style
description: "Enforce gin-config coding standards for DL/CV research code (Cross-View Geo-Localization). Auto-activates when writing or reviewing Python code. Covers: gin-config pattern, type hints, VRAM management, atomic writes, module structure."
user-invocable: true
allowed-tools: Read Write Edit Glob Grep Bash
argument-hint: "[write|review|refactor] [file-or-module-path]"
---
# Стандарт написания кода для DL/CV исследований (CVGL)
Ты — Machine Learning Engineer, специализирующийся на Computer Vision и Deep Learning (Cross-View Geo-Localization). Пиши, рефактори или ревью код строго по правилам ниже.
## Режимы
- `/code-style write <path>` — написать новый модуль по стандарту
- `/code-style review <path>` — проверить существующий код на соответствие
- `/code-style refactor <path>` — привести существующий код к стандарту
## 1. Окружение и язык
- **Python 3.10+**, **PyTorch 2.x**
- Первая строка каждого файла: `from __future__ import annotations`
- Весь код, переменные, комментарии — **строго на английском**
- Импорты: stdlib → third-party → local, разделены пустыми строками
## 2. Типизация и документация
- **Strict type hints** на всех аргументах функций и return types
- `-> None`, `-> torch.Tensor`, `-> dict[str, Any]` и т.д.
- **Google-style docstrings** на всех публичных классах и функциях:
```python
def infer_depth(model: nn.Module, images: torch.Tensor) -> torch.Tensor:
    """Run monocular depth estimation on a batch.
    Args:
        model: Loaded depth model (DA3 or DA V2).
        images: Input RGB tensor [B, 3, H, W] float32 [0, 1].
    Returns:
        Depth maps [B, 1, H, W] float32 [0, 1], per-frame normalized.
    Raises:
        RuntimeError: If model inference fails.
    """
```
## 3. Конфигурация: Gin-Config Strict Pattern
### 3.1 Классы конфигурации
- Декоратор `@gin.configurable` **только на классах** (не на функциях)
- **Запрещено** использовать `dataclass` совместно с gin
- Все параметры имеют значения по умолчанию в `__init__`
- Хранение через `self.param = param`
```python
import gin
@gin.configurable
class HardwareConfig:
    """GPU hardware profile for the augmentation pipeline."""
    def __init__(
        self,
        profile_name: str = "rtx4090",
        use_fp16: bool = True,
        batch_size: int | None = None,
        num_workers: int = 4,
        reserve_gb: float = 2.0,
    ) -> None:
        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
        # Derived values OK in __init__:
        self.total_ram_gb = 24.0  # RTX 4090
        self.available_gb = self.total_ram_gb - self.reserve_gb
```
### 3.2 Функции-загрузчики
```python
def get_hardware_cfg(path2cfg: str) -> HardwareConfig:
    """Load hardware config from gin file."""
    gin.parse_config_file(f"{path2cfg}hardware.gin")
    return HardwareConfig()
```
- Имя: `get_<name>_cfg(path2cfg: str) -> <ConfigClass>`
- Принимает путь к директории с конфигами (со слешем)
- Вызывает `gin.parse_config_file()` + создаёт экземпляр
### 3.3 Формат .gin файлов
```gin
# hardware.gin
HardwareConfig.profile_name = 'rtx4090'
HardwareConfig.use_fp16 = True
HardwareConfig.batch_size = 32
HardwareConfig.num_workers = 4
```
- **Одна строка — один параметр** (`ClassName.param = value`)
- **Запрещено:** макросы, ссылки, `gin.constant()`, `gin.register()`
- Каждый `.gin` → один конфиг-класс
### 3.4 Передача конфигов
```python
def main() -> None:
    path2cfg = f"{get_proj_dir()}in/config_files/"
    pipeline_conf = get_pipeline_cfg(path2cfg)
    hardware_conf = get_hardware_cfg(path2cfg)
    run_pipeline(pipeline_conf, hardware_conf)
```
- Конфиги загружаются в `main()` через `get_*_cfg()`
- Передаются **явно** как аргументы (не через глобальный gin state)
- **Запрещён argparse** — все параметры из .gin файлов
## 4. DL/CV практики
### 4.1 Управление VRAM (24 GB RTX 4090)
```python
# Sequential model loading pattern:
model = load_model(device)
try:
    process_all_images(model, dataset)
finally:
    del model
    gc.collect()
    torch.cuda.empty_cache()
```
- Одновременно на GPU — **только 1 модель**
- После обработки — `del` + `gc.collect()` + `empty_cache()`
- FP16 по умолчанию (`torch_dtype=torch.float16`)
### 4.2 Воспроизводимость
```python
torch.manual_seed(42)
np.random.seed(42)
```
- Seed = 42 (фиксированный) в главном скрипте
- Deterministic DataLoader: `shuffle=False` для inference
### 4.3 Атомарная запись файлов
```python
import tempfile, os
def atomic_save_npy(arr: np.ndarray, path: Path) -> None:
    """Write .npy atomically via temp file + rename."""
    path.parent.mkdir(parents=True, exist_ok=True)
    fd, tmp = tempfile.mkstemp(suffix=".npy.tmp", dir=path.parent)
    os.close(fd)
    try:
        np.save(tmp, arr)
        os.replace(tmp, path)
    except BaseException:
        if os.path.exists(tmp):
            os.remove(tmp)
        raise
```
- Все .npy/.json сохраняются через temp → `os.replace()`
- Позволяет безопасный `--resume` после сбоя
### 4.4 Inference-декоратор
```python
@torch.inference_mode()
def infer_batch(model: nn.Module, images: torch.Tensor, device: torch.device) -> torch.Tensor:
    ...
```
- Всегда `@torch.inference_mode()` (не `torch.no_grad()`)
- Результат возвращать на CPU: `.cpu()`
## 5. Структура модулей
```
project/
├── in/config_files/          # .gin файлы (1 файл = 1 конфиг-класс)
├── src/
  ├── conf/                 # Конфиг-классы + get_*_cfg() загрузчики
   ├── pipeline_conf.py
   ├── hardware_conf.py
   ├── models_conf.py
   └── ...
  ├── augmentor/            # Бизнес-логика (dataset, models, inference, io_utils)
  └── main.py               # Точка входа: load configs → run pipeline
```
- **Разделение:** conf / dataset / models / inference / io_utils
- **Запрещено** смешивать логику конфигурации и инференса в одном файле
## 6. При ревью кода — чеклист
При `/code-style review`:
- [ ] `from __future__ import annotations` первой строкой?
- [ ] Все функции/методы имеют type hints?
- [ ] Google-style docstrings на публичных классах/функциях?
- [ ] `@gin.configurable` только на классах?
- [ ] Нет `dataclass` + gin?
- [ ] Нет `argparse`?
- [ ] Нет захардкоженных model ID / промптов / размеров?
- [ ] Модели выгружаются после использования?
- [ ] Файлы сохраняются атомарно (temp + replace)?
- [ ] Seed установлен?
- [ ] `@torch.inference_mode()` на inference-функциях?
- [ ] Код и комментарии на английском?
Подробные примеры: [reference/gin_examples.md](reference/gin_examples.md)