Skip to content

Commit e217503

Browse files
Improved a few data types.
Made a few data types more specific and accurate. Improved some descriptions of CLI arguments.
1 parent cc0ed5f commit e217503

6 files changed

Lines changed: 119 additions & 27 deletions

File tree

docs/configs/interim_data.md

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,25 +30,25 @@ The purpose of the interim stage is to *transform raw data into memory-optimized
3030

3131
|Field|Type|Description|
3232
|:----|:---|:----------|
33-
|`data`|object|Dataset identity and output configuration|
34-
|`data_schema`|object|Expected schema of the interim dataset|
35-
|`raw_data_version`|string|Raw dataset version used as input|
36-
|`cleaning`|object|Column normalization rules|
37-
|`invariants`|object|Column-level validation and filtering rules|
38-
|`drop_duplicates`|bool|Whether duplicate rows should be removed|
39-
|`drop_missing_ints`|bool|Whether rows with missing integer values should be dropped|
40-
|`min_rows`|int|Minimum number of rows required after cleaning|
41-
|`lineage`|object|Metadata describing config provenance|
33+
|`data`|object|Dataset identity and output configuration.|
34+
|`data_schema`|object|Expected schema of the interim dataset.|
35+
|`raw_data_version`|string|Raw dataset version used as input.|
36+
|`cleaning`|object|Column normalization rules.|
37+
|`invariants`|object|Column-level validation and filtering rules.|
38+
|`drop_duplicates`|boolean|Whether duplicate rows should be removed.|
39+
|`drop_missing_ints`|boolean|Whether rows with missing integer values should be dropped. Defaults to True if not specified.|
40+
|`min_rows`|integer|Minimum number of rows required after cleaning. Defaults to 0 if not specified.|
41+
|`lineage`|object|Metadata describing config provenance.|
4242

4343
### `data`
4444

4545
Defines metadata for the produced interim dataset.
4646

4747
|Field|Type|Description|
4848
|:----|:---|:----------|
49-
|`name`|string|Dataset name|
50-
|`version`|string|Dataset version (`v{integer}` format)|
51-
|`output`|object|Output storage configuration|
49+
|`name`|string|Dataset name.|
50+
|`version`|string|Dataset version (`v{integer}` format).|
51+
|`output`|object|Output storage configuration.|
5252

5353
### `data.output`
5454

ml/config/schemas/model_specs.py

Lines changed: 60 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,6 @@ class TaskType(StrEnum):
2727

2828
classification = "classification"
2929
regression = "regression"
30-
ranking = "ranking"
31-
time_series = "time_series"
3230

3331
class TaskConfig(BaseModel):
3432
"""Task type metadata for model execution and validation logic."""
@@ -165,14 +163,14 @@ def validate_filters_based_on_enabled(cls, v, info):
165163
@field_validator("include_in_model", mode="after")
166164
@classmethod
167165
def validate_include_in_model_based_on_enabled(cls, v, info):
168-
"""Validate model-include flag consistency with segmentation state.
166+
"""Validate include_in_model flag consistency with segmentation state.
169167
170168
Args:
171-
v: Include-in-model flag value.
169+
v: Include_in_model flag value.
172170
info: Pydantic field-validation context.
173171
174172
Returns:
175-
bool: Validated include-in-model flag.
173+
bool: Validated include_in_model flag.
176174
"""
177175

178176
enabled = info.data.get("enabled", False)
@@ -191,8 +189,26 @@ class FeatureSetConfig(BaseModel):
191189

192190
name: str
193191
version: str
194-
data_format: str
195-
file_name: str
192+
data_format: Literal['csv', 'parquet', 'json', 'arrow'] = "parquet"
193+
file_name: str = "features.parquet"
194+
195+
@field_validator("version", mode="before")
196+
@classmethod
197+
def validate_version_format(cls, v):
198+
"""Ensure feature set version follows ``v{number}`` convention.
199+
200+
Args:
201+
v: Feature set version value.
202+
203+
Returns:
204+
str: Validated feature set version string.
205+
"""
206+
207+
if not isinstance(v, str) or not v.startswith("v") or not v[1:].isdigit():
208+
msg = f"Version must be in format 'v{{number}}', e.g. 'v1', 'v2', etc. Got '{v}'."
209+
logger.error(msg)
210+
raise ConfigError(msg)
211+
return v
196212

197213
class SplitConfig(BaseModel):
198214
"""Train/validation/test split strategy settings."""
@@ -224,6 +240,24 @@ class PipelineConfig(BaseModel):
224240
version: str
225241
path: str
226242

243+
@field_validator("version", mode="before")
244+
@classmethod
245+
def validate_version_format(cls, v):
246+
"""Ensure pipeline config version follows ``v{number}`` convention.
247+
248+
Args:
249+
v: Pipeline config version value.
250+
251+
Returns:
252+
str: Validated pipeline config version string.
253+
"""
254+
255+
if not isinstance(v, str) or not v.startswith("v") or not v[1:].isdigit():
256+
msg = f"Version must be in format 'v{{number}}', e.g. 'v1', 'v2', etc. Got '{v}'."
257+
logger.error(msg)
258+
raise ConfigError(msg)
259+
return v
260+
227261
class ScoringConfig(BaseModel):
228262
"""Metric-scoring policy and optional thresholds."""
229263

@@ -342,7 +376,7 @@ class ExplainabilityConfig(BaseModel):
342376
top_k: int = 20
343377
methods: ExplainabilityMethodsConfig = Field(default_factory=ExplainabilityMethodsConfig)
344378

345-
DATA_TYPE = Literal["tabular", "time-series"]
379+
DATA_TYPE = Literal["tabular"]
346380

347381
class ModelSpecsLineageConfig(BaseModel):
348382
"""Lineage metadata for model specification creation."""
@@ -385,6 +419,24 @@ class ModelSpecs(BaseModel):
385419

386420
model_config = ConfigDict(extra="forbid", populate_by_name=True)
387421

422+
@field_validator("version", mode="before")
423+
@classmethod
424+
def validate_version_format(cls, v):
425+
"""Ensure model version follows ``v{number}`` convention.
426+
427+
Args:
428+
v: Model version value.
429+
430+
Returns:
431+
str: Validated model version string.
432+
"""
433+
434+
if not isinstance(v, str) or not v.startswith("v") or not v[1:].isdigit():
435+
msg = f"Version must be in format 'v{{number}}', e.g. 'v1', 'v2', etc. Got '{v}'."
436+
logger.error(msg)
437+
raise ConfigError(msg)
438+
return v
439+
388440
@model_validator(mode="after")
389441
def validate_task_target_consistency(self):
390442
"""Enforce consistency between task type and target class metadata.

ml/data/config/schemas/shared.py

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,42 @@
11
"""Shared schema blocks reused by interim and processed data configs."""
22

3+
import logging
34
from typing import Literal
45

5-
from pydantic import BaseModel, Field
6+
from pydantic import BaseModel, Field, field_validator
67

8+
from ml.exceptions import ConfigError
9+
10+
logger = logging.getLogger(__name__)
711

812
class Output(BaseModel):
913
"""Output artifact settings for persisted datasets."""
1014

1115
path_suffix: str = Field(..., description="Suffix for the output data file path, which will be combined with the data name and version to create the full path.")
12-
format: Literal["parquet"] = Field("parquet", description="Format to save the interim data.")
13-
compression: Literal['snappy', 'gzip', 'brotli', 'lz4', 'zstd'] | None = Field(None, description="Compression method to use when saving the data (default: 'snappy').")
16+
format: Literal["parquet"] = Field("parquet", description="Format to save the interim data (default: 'parquet').")
17+
compression: Literal['snappy', 'gzip', 'brotli', 'lz4', 'zstd'] | None = Field("snappy", description="Compression method to use when saving the data (default: 'snappy').")
1418

1519
class DataInfo(BaseModel):
1620
"""Dataset identity and output target metadata."""
1721

1822
name: str = Field(..., description="Name of the data being processed.")
1923
version: str = Field(..., description="Version of the interim data being created.")
2024
output: Output
25+
26+
@field_validator("version", mode="before")
27+
@classmethod
28+
def validate_version_format(cls, v):
29+
"""Ensure dataset version follows ``v{number}`` convention.
30+
31+
Args:
32+
v: Dataset version value.
33+
34+
Returns:
35+
str: Validated dataset version string.
36+
"""
37+
38+
if not isinstance(v, str) or not v.startswith("v") or not v[1:].isdigit():
39+
msg = f"Version must be in format 'v{{number}}', e.g. 'v1', 'v2', etc. Got '{v}'."
40+
logger.error(msg)
41+
raise ConfigError(msg)
42+
return v

ml/feature_freezing/freeze_strategies/tabular/config/models.py

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ class DatasetConfig(BaseModel):
3030
ref: str = Field("data/processed", description="Reference path for the dataset, e.g., 'data/processed'")
3131
name: str = Field(..., description="Name of the dataset, e.g., 'hotel_bookings'")
3232
version: str = Field(..., description="Version of the dataset, e.g., 'v1'")
33-
format: Literal["csv", "parquet"]
33+
format: Literal["csv", "parquet", "json", "arrow"]
3434
merge_key: str | list[str] = Field(
3535
"row_id", description="Key(s) to merge datasets on, default is 'row_id'"
3636
)
@@ -44,6 +44,24 @@ class DatasetConfig(BaseModel):
4444
"data.{format}", description="Suffix for the dataset file, supports {format} placeholder"
4545
)
4646

47+
@field_validator("version", mode="before")
48+
@classmethod
49+
def validate_version_format(cls, v):
50+
"""Ensure dataset version follows ``v{number}`` convention.
51+
52+
Args:
53+
v: Dataset version value.
54+
55+
Returns:
56+
str: Validated dataset version string.
57+
"""
58+
59+
if not isinstance(v, str) or not v.startswith("v") or not v[1:].isdigit():
60+
msg = f"Version must be in format 'v{{number}}', e.g. 'v1', 'v2', etc. Got '{v}'."
61+
logger.error(msg)
62+
raise ConfigError(msg)
63+
return v
64+
4765
@field_validator("merge_key", mode="before")
4866
def ensure_merge_key_list(cls, v):
4967
"""Always convert merge_key to a list internally."""
@@ -101,7 +119,7 @@ class StorageConfig(BaseModel):
101119
"""Snapshot storage format and compression settings."""
102120

103121
format: Literal["parquet"]
104-
compression: str | None = "snappy"
122+
compression: Literal['snappy', 'gzip', 'brotli', 'lz4', 'zstd'] | None = Field("snappy", description="Compression method to use when saving the data (default: 'snappy').")
105123

106124
class LineageConfig(BaseModel):
107125
"""Lineage metadata for feature registry config provenance."""

ml/pipelines/models.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ class PipelineConfig(BaseModel):
2121
version: str = Field(..., description="Version of the pipeline (e.g., v1)")
2222
description: str | None = Field(None, description="Optional description of the pipeline")
2323
steps: list[str] = Field(..., description="Ordered list of pipeline steps")
24-
assumptions: dict = Field(..., description="Assumptions about supported tasks and categorical handling")
24+
assumptions: dict[str, bool] = Field(..., description="Assumptions about supported tasks and categorical handling")
2525
lineage: LineageConfig
2626

2727
@field_validator("version")

scripts/generators/generate_fake_data.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ def parse_args():
102102
"--model-path",
103103
type=str,
104104
default=None,
105-
help="Path to a pre-trained CTGAN model to load. If not provided, uses a default path."
105+
help="Path to a pre-trained CTGAN model to load. If not provided, trains a new model."
106106
)
107107

108108
parser.add_argument(

0 commit comments

Comments
 (0)