Source code for sequifier.config.metadata
"""Typed preprocessing metadata used during config resolution."""
from __future__ import annotations
import copy
import json
from typing import Any
from pydantic import AliasChoices, BaseModel, ConfigDict, Field, field_validator
from sequifier.helpers import ModelWindowView, StoredWindowLayout
from sequifier.special_tokens import SPECIAL_TOKEN_IDS, validate_special_token_ids
RESOLVED_ONLY_CONFIG_KEYS = {
"categorical_columns",
"real_columns",
"id_maps",
"special_token_ids",
"storage_layout",
"window_view",
"n_classes",
"stored_context_width",
"max_target_offset",
"stored_window_layout_version",
}
[docs]class DatasetMetadata(BaseModel):
"""The stable subset of preprocessing metadata consumed by other commands."""
model_config = ConfigDict(extra="allow", populate_by_name=True)
split_paths: list[str] = Field(default_factory=list)
column_data_types: dict[str, str] = Field(
default_factory=dict,
validation_alias=AliasChoices("column_data_types", "column_types"),
)
n_classes: dict[str, int] = Field(default_factory=dict)
id_maps: dict[str, dict[str | int, int]] = Field(default_factory=dict)
special_token_ids: dict[str, int] = Field(
default_factory=lambda: dict(SPECIAL_TOKEN_IDS.ids_by_label)
)
selected_columns_statistics: dict[str, dict[str, float]] = Field(
default_factory=dict
)
normalize_real_columns: bool = True
stored_context_width: int = Field(gt=0)
max_target_offset: int = Field(default=1, ge=0)
stored_window_layout_version: int = 2
@field_validator("special_token_ids")
@classmethod
def validate_token_ids(cls, value: dict[str, int]) -> dict[str, int]:
return validate_special_token_ids(value, source="dataset metadata")
@property
def storage_layout(self) -> StoredWindowLayout:
return StoredWindowLayout(
stored_context_width=self.stored_context_width,
max_target_offset=self.max_target_offset,
version=self.stored_window_layout_version,
)
[docs]def load_dataset_metadata(path: str) -> DatasetMetadata:
"""Load and validate one preprocessing metadata JSON file."""
with open(path, "r") as file:
values: Any = json.load(file)
if not isinstance(values, dict):
raise ValueError(f"Metadata config '{path}' must contain a JSON object.")
return DatasetMetadata.model_validate(values)
[docs]def extract_inline_metadata(
values: dict[str, Any],
) -> tuple[dict[str, Any], dict[str, Any] | None]:
"""Split the historical ``skip_metadata`` representation into two mappings."""
authored = copy.deepcopy(values)
window_view = authored.get("window_view")
if "context_length" not in authored and isinstance(window_view, dict):
authored["context_length"] = window_view.get("context_length")
elif "context_length" not in authored and isinstance(window_view, ModelWindowView):
authored["context_length"] = window_view.context_length
if "target_offset" not in authored and isinstance(window_view, dict):
authored["target_offset"] = window_view.get("target_offset", 1)
elif "target_offset" not in authored and isinstance(window_view, ModelWindowView):
authored["target_offset"] = window_view.target_offset
metadata_values: dict[str, Any] = {
"split_paths": [
path
for path in (
authored.get("data_path"),
authored.get("validation_data_path"),
)
if path is not None
],
"column_data_types": authored.get("column_data_types", {}),
"n_classes": authored.get("n_classes", {}),
"id_maps": authored.get("id_maps", {}),
"special_token_ids": authored.get(
"special_token_ids", SPECIAL_TOKEN_IDS.ids_by_label
),
"selected_columns_statistics": authored.get("selected_columns_statistics", {}),
"normalize_real_columns": authored.get("normalize_real_columns", True),
}
storage_layout = authored.get("storage_layout")
if isinstance(storage_layout, StoredWindowLayout):
metadata_values.update(
{
"stored_context_width": storage_layout.stored_context_width,
"max_target_offset": storage_layout.max_target_offset,
"stored_window_layout_version": storage_layout.version,
}
)
elif isinstance(storage_layout, dict):
metadata_values.update(
{
"stored_context_width": storage_layout.get("stored_context_width"),
"max_target_offset": storage_layout.get("max_target_offset", 1),
"stored_window_layout_version": storage_layout.get("version", 2),
}
)
else:
metadata_values.update(
{
"stored_context_width": authored.get("stored_context_width"),
"max_target_offset": authored.get("max_target_offset", 1),
"stored_window_layout_version": authored.get(
"stored_window_layout_version", 2
),
}
)
for key in RESOLVED_ONLY_CONFIG_KEYS:
authored.pop(key, None)
for key in ("selected_columns_statistics", "normalize_real_columns"):
authored.pop(key, None)
if metadata_values["stored_context_width"] is None:
return authored, None
return authored, metadata_values