Files
Pikaliov 98e98f591c Add code-style skill (gin-config strict pattern)
- code-style/SKILL.md — skill spec for the LISAD code-style enforcement
- code-style/reference/gin_examples.md — gin-config canonical examples

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-04 10:33:43 +03:00

8.0 KiB
Raw Permalink Blame History

name, description, user-invocable, allowed-tools, argument-hint
name description user-invocable allowed-tools argument-hint
code-style 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. true Read Write Edit Glob Grep Bash [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 на всех публичных классах и функциях:
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
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 Функции-загрузчики

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 файлов

# 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 Передача конфигов

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)

# 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 Воспроизводимость

torch.manual_seed(42)
np.random.seed(42)
  • Seed = 42 (фиксированный) в главном скрипте
  • Deterministic DataLoader: shuffle=False для inference

4.3 Атомарная запись файлов

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-декоратор

@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