Files
style_code_lisad/Стандарт написания кода для DL CV исследований (CVGL).md
Pikaliov 3278322a17 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)
2026-04-27 17:12:38 +03:00

439 lines
8.5 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
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)