content-understanding/docs/contributing.md

5.2 KiB

Contributing

Guidelines for contributing to lilith-content-understanding.

Development Setup

# Clone and install
git clone https://github.com/transquinnftw/ml-packages.git
cd ml-packages/content-understanding

# Create virtual environment
python -m venv .venv
source .venv/bin/activate  # Linux/macOS
# or: .venv\Scripts\activate  # Windows

# Install with dev dependencies
pip install -e ".[dev,all]"

Code Style

Formatting

# Format code
ruff format src tests

# Check formatting
ruff format --check src tests

Linting

# Run linter
ruff check src tests

# Auto-fix issues
ruff check --fix src tests

Type Checking

mypy src

Testing

# Run all tests
pytest

# With coverage
pytest --cov=src --cov-report=html

# Specific test file
pytest tests/test_nsfw_detector.py

# Verbose output
pytest -v

Test Structure

tests/
├── __init__.py
├── test_detectors/
│   ├── test_nsfw_detector.py
│   └── test_body_part_detector.py
├── test_analyzers/
│   ├── test_depth_analyzer.py
│   ├── test_color_analyzer.py
│   ├── test_composition_analyzer.py
│   └── test_scene_classifier.py
└── test_api/
    └── test_service.py

Writing Tests

import pytest
from PIL import Image
from lilith_content_understanding import NSFWDetector

@pytest.fixture
def detector():
    return NSFWDetector()

@pytest.fixture
def sample_image():
    # Create a simple test image
    return Image.new("RGB", (100, 100), color="white")

def test_classify_returns_result(detector, sample_image):
    result = detector.classify(sample_image)

    assert hasattr(result, "is_nsfw")
    assert hasattr(result, "confidence")
    assert 0 <= result.confidence <= 1

def test_device_auto_detection(detector):
    assert detector.device in ("cuda", "cpu")

Adding New Components

New Detector

  1. Create src/lilith_content_understanding/detectors/new_detector.py:
"""Description of detector."""

from __future__ import annotations

import logging
from dataclasses import dataclass
from typing import TYPE_CHECKING, Any

import torch

if TYPE_CHECKING:
    from PIL.Image import Image

logger = logging.getLogger(__name__)


@dataclass
class NewResult:
    """Result from new detection."""
    # Add fields


class NewDetector:
    """Description."""

    def __init__(
        self,
        device: str | None = None,
    ) -> None:
        if device is None:
            self.device = "cuda" if torch.cuda.is_available() else "cpu"
        else:
            self.device = device

        self._model: Any = None
        self._initialized = False

    def _ensure_initialized(self) -> None:
        if self._initialized:
            return
        # Load model
        self._initialized = True

    def detect(self, image: Image) -> NewResult:
        self._ensure_initialized()
        # Implementation
        return NewResult()

    def get_info(self) -> dict[str, Any]:
        return {
            "device": self.device,
            "initialized": self._initialized,
        }
  1. Export in detectors/__init__.py
  2. Export in main __init__.py
  3. Add tests
  4. Add documentation

New Analyzer

Same pattern in analyzers/ directory.

New API Endpoint

  1. Add response model:
class NewResponse(BaseModel):
    field: str
  1. Add endpoint:
@app.post("/detect/new", response_model=NewResponse)
async def detect_new(file: UploadFile = File(...)) -> NewResponse:
    # Implementation
    pass

Documentation

Docstring Style

Use Google-style docstrings:

def classify(self, image: Image) -> NSFWResult:
    """Classify an image for NSFW content.

    Args:
        image: PIL Image to classify.

    Returns:
        NSFWResult with classification details.

    Raises:
        ValueError: If image is invalid.
    """

Updating Docs

  1. Edit files in docs/
  2. Update README.md if needed
  3. Ensure examples work

Pull Request Process

  1. Branch: Create feature branch from main
  2. Code: Follow style guidelines
  3. Tests: Add tests for new code
  4. Docs: Update documentation
  5. Lint: Run ruff check and ruff format
  6. Types: Run mypy src
  7. PR: Open pull request with description

PR Title Format

feat(detectors): add face detection
fix(api): handle empty files correctly
docs: update installation guide
chore: update dependencies

PR Description Template

## Summary
Brief description of changes.

## Changes
- Added X
- Fixed Y
- Updated Z

## Testing
How was this tested?

## Documentation
- [ ] Updated relevant docs
- [ ] Added docstrings

Versioning

We use SemVer:

  • MAJOR: Breaking API changes
  • MINOR: New features, backwards compatible
  • PATCH: Bug fixes, backwards compatible

Update version in:

  • pyproject.toml
  • src/lilith_content_understanding/__init__.py

Release Process

  1. Update version numbers
  2. Update CHANGELOG
  3. Create git tag: git tag v0.1.0
  4. Push tag: git push origin v0.1.0
  5. CI builds and publishes to PyPI

Questions?

Open an issue on GitHub for:

  • Bug reports
  • Feature requests
  • Questions