Source code for omniloader.data.factory

"""Build datasets and schemas from declarative config entries.

This lets datasets be described in JSON/YAML (adapter + constructor args +
schema) so tools like the CLI and :class:`~omniloader.config.OmniConfig` can
assemble a dataset mix without Python glue. Only the registered *data adapters*
are ever constructed — never models.

A dataset entry looks like::

    {
      "adapter": "hdf5",
      "args": {"h5_path": "data/mosei.h5", "subset": "train"},
      "schema": {
        "features": [
          {"name": "video", "feature_dim": 1024, "time_dim": 300},
          {"name": "eye_image", "shape": [3, 64, 64], "time_dim": 15}
        ],
        "targets": [{"name": "sentiment", "placeholder": -5.0}]
      }
    }

``shape`` declares a structured (e.g. image) trailing shape instead of a flat
feature vector; see :class:`~omniloader.schema.spec.TensorSpec`.
"""

from __future__ import annotations

from typing import TYPE_CHECKING, Any

from omniloader.data.datasets import HDF5Dataset
from omniloader.data.npy import NpyFolderDataset
from omniloader.schema.spec import DatasetSchema, TensorSpec

if TYPE_CHECKING:
    from collections.abc import Mapping, Sequence

    from omniloader.loader import SizedDataset

#: Registry mapping adapter names to dataset classes.
ADAPTERS: dict[str, type] = {
    "hdf5": HDF5Dataset,
    "npy": NpyFolderDataset,
}


[docs] def schema_from_dict(data: Mapping[str, Any]) -> DatasetSchema: """Build a :class:`DatasetSchema` from a ``{"features": [...], "targets": [...]}`` dict. Each spec dict is forwarded to :class:`TensorSpec`/:class:`TensorSpec`; the ``dtype`` field may be a string name (e.g. ``"int64"``). Args: data: The schema mapping. Returns: The constructed schema. """ return DatasetSchema( features=[TensorSpec(**spec) for spec in data.get("features", [])], targets=[TensorSpec(**spec) for spec in data.get("targets", [])], )
[docs] def build_dataset(entry: Mapping[str, Any]) -> tuple[SizedDataset, DatasetSchema]: """Construct one ``(dataset, schema)`` pair from a config entry. Args: entry: A dict with ``adapter`` (a key of :data:`ADAPTERS`), ``args`` (the adapter constructor kwargs) and ``schema``. Returns: The dataset instance and its schema. Raises: ValueError: If ``adapter`` is not registered. """ adapter = entry["adapter"] if adapter not in ADAPTERS: raise ValueError(f"Unknown dataset adapter {adapter!r}; expected one of {sorted(ADAPTERS)}") dataset = ADAPTERS[adapter](**entry.get("args", {})) return dataset, schema_from_dict(entry["schema"])
[docs] def build_datasets( entries: Sequence[Mapping[str, Any]], ) -> tuple[list[SizedDataset], list[DatasetSchema]]: """Construct parallel lists of datasets and schemas from config entries. Args: entries: A list of dataset entries (see :func:`build_dataset`). Returns: A ``(datasets, schemas)`` tuple ready for :class:`~omniloader.loader.OmniLoader`. """ datasets: list[SizedDataset] = [] schemas: list[DatasetSchema] = [] for entry in entries: dataset, schema = build_dataset(entry) datasets.append(dataset) schemas.append(schema) return datasets, schemas