Skip to main content

Modosaic

Modosaic is a multimodal image-dataset pipeline for generating, validating, and saving complementary modalities from a shared image source. It gives you:

  • A unified dataset layer for local image folders and parquet datasets.
  • A configurable generation pipeline for source images, captions, segmentation masks, depth maps, and surface-normal fields.
  • Validators and quality-gate constraints that decide which generated modalities are saved.
  • A CLI for default runs, fully configurable runs, and config-file driven runs.
  • A clean Python API for composing custom modalities, validators, and postprocessors.
  • Reproducible experiment folders with generated artifacts, validation JSON, and structured logs.

Installation

For an exact source-checkout installation, use the committed lockfile:

uv sync --locked

uv.lock pins the Python dependency graph and Git revisions; --locked fails instead of changing that graph. Python 3.13 is required.

For an editable convenience install from an activated environment:

pip install -e .

For the published package:

pip install modosaic

The pip routes do not reproduce the repository lock. Runtime dependencies are intentionally installed as one set because the default pipeline runs every modality and its cross-modal validators in one process. Splitting model families into optional groups would make the default workflow depend on several overlapping extras. Documentation tools are isolated in the docs dependency group.

Linux with NVIDIA CUDA

The Oxford-IIIT Pet CUDA benchmark in the paper used Google Cloud image pytorch-2-9-cu129-ubuntu-2404-nvidia-580-v20260518: Ubuntu 24.04, Python 3.12, PyTorch 2.9.0, CUDA 12.9, and NVIDIA driver 580. The exact GPU model and VRAM were not recorded.

For Modosaic 1.0.0post1, flake.nix and flake.lock define the current x86_64-linux CUDA development shell, including Python 3.13 and CUDA user-space libraries; uv.lock pins the Python packages. Together they define the locked software environment. A compatible host NVIDIA driver is still required and is not supplied by Nix. Check it with nvidia-smi.

If your Nix installation does not already allow flakes and the listed binary caches, add the following generic settings to /etc/nix/nix.conf:

experimental-features = nix-command flakes

extra-substituters = https://cache.nixos.org https://nix-community.cachix.org https://cache.nixos-cuda.org

extra-trusted-public-keys = nix-community.cachix.org-1:mB9ZQ+4kTq9qUqM96H8P6oz+ZWHR+Hh3wlgYx9oSt1A= cache.nixos-cuda.org:74DUi4Ye579gUqzH4ziL9IyiJBlDpMRn9MBN8oNan9M=

Restart the Nix daemon after changing its configuration, then enter the shell:

nix develop

The shell runs uv sync --locked, activates .venv, and downloads the preconfigured SAM ViT-B checkpoint when it is absent.

Apple Silicon and CPU

On macOS or a non-Nix setup, run uv sync --locked directly. Modosaic selects CUDA first, then Apple MPS, then CPU. CUDA is strongly recommended for the heavier text, segmentation, depth, and normals models; CPU execution is supported but slower. Third-party backend support and memory requirements vary by model, so no universal VRAM minimum is claimed. The Nix shell is currently limited to x86_64-linux.

Hugging Face model access

Most model weights are downloaded from their upstream repositories on first use, so allow network access and sufficient cache space. Local checkpoints can be placed under model_weights/.

If you use the SAM 3 segmentation model (sam3, backed by facebook/sam3), run Modosaic with HF_TOKEN set to a Hugging Face token from an account that has access to Meta's SAM 3 model:

export HF_TOKEN=hf_...
modosaic run --dataset local --root ./images --segmentation-model sam3

Do not commit tokens to the repository.


Quick Start

1. List supported modalities and models

modosaic models

When running directly from a checkout without installing the console script:

python -m modosaic.cli.cli models

2. Run the default pipeline on a local image folder

modosaic simple ./images --limit 10

This runs all default modalities in dependency-safe order:

image -> text -> segmentation -> depth -> normals

Artifacts are written under ./experiments/<timestamp>/.

3. Run a selected local-folder experiment

modosaic run \
  --dataset local \
  --root ./images \
  --modality image \
  --modality segmentation \
  --modality depth \
  --segmentation-model sam3 \
  --depth-model depth-anything-v2-small \
  --segmentation-mask-quality-min 0.70 \
  --depth-segmentation-boundary-min 0.15 \
  --limit 20 \
  --experiment-root ./experiments \
  --experiment-name local-seg-depth

Validators can be disabled with --no-validators. To run validators without using them as save/discard gates, pass --no-constraints.

4. Run from a parquet dataset

modosaic run \
  --dataset parquet \
  --parquet-path ./data/imagenet-a \
  --image-column image.bytes \
  --metadata-column label \
  --modality image \
  --modality text \
  --text-model qwen-2-2b \
  --text-siglip-min 0.65 \
  --limit 20

Parquet image columns can contain bytes, bytearray/memoryview values, list[int], nested fields such as image.bytes, or paths relative to the parquet file.


Full Pipeline From Config

Pipeline config files can be JSON, TOML, YAML, or YML. YAML requires PyYAML. The config maps directly into modosaic.cli.config.RunConfig.

Example examples/config.yaml:

dataset:
  type: local
  root: ./images
  recursive: true
  extensions: [.jpg, .png]

modalities:
  enabled: [image, segmentation, depth]
  models:
    segmentation: sam3
    depth: depth-anything-v2-small

validators:
  enabled: true
  constraints:
    enabled: true
    segmentation_mask_quality_minimum: 0.70
    segmentation_boundary_minimum: 0.20
    depth_imagebind_minimum: 0.55
    depth_segmentation_boundary_minimum: 0.15
  segmentation_boundary_thickness: 1
  segmentation_tolerance_radius: 2
  segmentation_rgb_edge_quantile: 0.90
  depth_boundary_thickness: 1
  depth_tolerance_radius: 2
  depth_edge_quantile: 0.90

run:
  limit: 20
  experiment_root: ./experiments
  experiment_name: local-seg-depth
  log_path: ./.logs
  seed: 42

Run it with:

modosaic pipeline examples/config.yaml

Override selected config values at execution time:

modosaic pipeline examples/config.yaml --limit 5 --seed 123 --json

Python API

from pathlib import Path

from modosaic import ExperimentService, ImageDataset, LoggingService, Pipeline
from modosaic.depth.preconfigured_modality import build_preconfigured_depth_modality
from modosaic.image import build_preconfigured_image_modality
from modosaic.segmentation.preconfigured_modality import (
    build_preconfigured_segmentation_modality,
)
from modosaic.services.seeding import SeedingService

LoggingService.setup_logging()
SeedingService.set_global_seed(42)

dataset = ImageDataset.from_local_folder(Path("images"))

pipeline = Pipeline(
    dataset=dataset,
    modalities=[
        build_preconfigured_image_modality(),
        build_preconfigured_segmentation_modality(),
        build_preconfigured_depth_modality(),
    ],
    experiment=ExperimentService(
        root="experiments",
        experiment_name="local-seg-depth",
    ),
)

results = pipeline.run(limit=10)

for result in results:
    print(result.record.sample_id, result.artifact_paths)

Each ConfiguredModality owns a generator, validators, and a postprocessor. Plain validators receive (record, generated). A ValidatorStep can also pass generated outputs from earlier modalities as keyword dependencies.

from modosaic.core.validation_constraint import ValidationConstraint
from modosaic.core.validator_step import ValidatorStep
from modosaic.segmentation.validators.impl.mask_statistics import MaskStatsValidator

mask_quality_gate = ValidatorStep(
    validator=MaskStatsValidator(),
    constraint=ValidationConstraint(
        minimum=0.75,
        score_name="weighted_mask_quality",
        score_fn=lambda stats: (
            0.4 * stats.coverage_score
            + 0.3 * stats.distinctness_score
            + 0.3 * stats.fragmentation_score
        ),
    ),
)

A constrained modality is saved only when every configured constraint passes. Rejected modalities do not write generated artifacts or validation JSON, and later validators cannot use them as dependencies.


CLI Reference

modosaic simple ROOT [--limit N]

Run the default Modosaic pipeline on a local image folder.

modosaic run [OPTIONS]

Run with CLI-provided dataset, modality, model, validator, constraint, and experiment settings.

modosaic pipeline CONFIG_PATH [--limit N] [--seed SEED] [--json]

Run from a JSON, TOML, YAML, or YML config file.

modosaic models

Print valid modality and model names for CLI options and config files.


Concepts & Extensibility

  • Dataset adapters -> modosaic.providers: local folders and parquet data.
  • Generators -> modosaic.<modality>.generators: model-backed modality generation.
  • Validators -> modosaic.<modality>.validators: quality checks and cross-modality consistency checks.
  • Constraints -> modosaic.core.validation_constraint: pass/fail gates over validator output.
  • Postprocessors -> modosaic.<modality>.postprocessor: conversion from model output to saved experiment artifacts.
  • Services -> logging, seeding, image conversion, artifact persistence, boundaries, edges, and tolerances.

Add custom components by subclassing:

DatasetAdapter -> providers.adapters.adapter.DatasetAdapter
ModalityGenerator -> core.modality_generator.ModalityGenerator
ModalityValidator -> core.validator.ModalityValidator
ModalityPostprocessor -> core.postprocessor.ModalityPostprocessor
Modality -> core.modality.Modality

or by composing existing pieces with ConfiguredModality.


Experiment Outputs

ExperimentService writes every accepted artifact beneath the configured run folder. Typical output includes:

experiments/<run>/
  image/
  text/
  segmentation/
  depth/
  normals/
  validations/

Validation files include the validator name, raw value, optional score, threshold, and pass/fail result.


Documentation

MkDocs pages live in docs/, and API pages are generated from Google-style Python docstrings through mkdocstrings.

Public classes, functions, and methods should carry useful Google-style docstrings because they form the API reference. Module docstrings are optional for simple implementation modules; add them when a file exposes important package-level behavior, re-exports public symbols, or needs context that is not clear from the documented objects inside it.

uv run --group docs mkdocs serve
uv run --group docs mkdocs build --strict

Examples

See examples/main.py for a complete local demo that loads a parquet dataset, runs the preconfigured modality stack, and prints validation summaries.


License

This project is licensed under the MIT License. See the LICENSE file for details.

Metadata

Release files for modosaic 1.0.0.post1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for modosaic 1.0.0.post1
File Size Uploaded
modosaic-1.0.0.post1.tar.gz 71.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for modosaic 1.0.0.post1
File Interpreter ABI Platform
modosaic-1.0.0.post1-py3-none-any.whl Python 3 none any Details

Total release size: 181.0 kB

Release files / modosaic-1.0.0.post1.tar.gz

Download URL modosaic-1.0.0.post1.tar.gz
Size 71.7 kB
Tags Source
SHA-256 checksum
How to use checksums
d2837dbd84eccfc1b96ef794b8f5d8e9762d220dffed02d35d2770a34ffa998a
BLAKE2b-256 checksum
How to use checksums
c0b6939f8ddffe411af567f0613d0a3d38265324f3dc9f520086be65ff0e3d7d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.0 {"installer":{"name":"uv","version":"0.12.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / modosaic-1.0.0.post1-py3-none-any.whl

Download URL modosaic-1.0.0.post1-py3-none-any.whl
Size 109.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
34513a234945200ef0ea2fb9a744a494e12ac52239377b061b490d5359ff41d2
BLAKE2b-256 checksum
How to use checksums
e4d4201d15e06261578c2d3868e5b7561171081563dd39ab926db709911137bf
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.0 {"installer":{"name":"uv","version":"0.12.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release history Release notifications | RSS feed

This release

1.0.0.post1 This release

2 release files

1.0.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page