feat: require date_column in training parameters and update documentation
- Made `date_column` a required field in `TrainModelParams`, ensuring it must be present in the input data. - Updated related documentation in `input-sample.md`, `README.md`, and various test scenarios to reflect the change in requirement. - Adjusted the handling of `date_format` to default to `yyyy-MM-dd HH:mm:ss` if omitted, enhancing usability. - Refined test scenarios to include new examples and ensure compliance with the updated parameter structure. These changes improve the robustness of the model training workflow and clarify the expectations for input data.
This commit is contained in:
@@ -14,6 +14,9 @@ FRONTEND_DATE_FORMAT_TO_STRFTIME = {
|
||||
}
|
||||
ALLOWED_FRONTEND_DATE_FORMATS = frozenset(FRONTEND_DATE_FORMAT_TO_STRFTIME.keys())
|
||||
|
||||
# When the client omits date_format (or sends null/blank), parsing uses this frontend format.
|
||||
DEFAULT_TRAIN_DATE_FORMAT = 'yyyy-MM-dd HH:mm:ss'
|
||||
|
||||
|
||||
def validate_frontend_date_format(fmt: str | None) -> None:
|
||||
"""Raise ValueError if fmt is set and not one of the allowed frontend date formats."""
|
||||
@@ -49,8 +52,9 @@ class TrainModelParams:
|
||||
file_name (str): Name of the file in the MinIO bucket.
|
||||
line_separator (str): Line separator used in the CSV file.
|
||||
decimal_separator (str): Decimal separator used in the CSV file.
|
||||
date_column (str | None): Name of the date/time column. If set with date_format, the column is parsed as datetime.
|
||||
date_format (str | None): Format of the date column (e.g. dd/MM/yyyy HH:mm:ss). Used when date_column is set.
|
||||
date_column (str): Name of the date/time column in the dataset (required).
|
||||
date_format (str): Format of the date column (allowed frontend strings). If omitted or blank
|
||||
in the input dict, defaults to DEFAULT_TRAIN_DATE_FORMAT.
|
||||
train_size (int): Percentage of data to use for training (0-100).
|
||||
shuffle (bool): Whether to shuffle the data during train/test split.
|
||||
experiment_run_id (int): Unique identifier for the experiment run.
|
||||
@@ -70,8 +74,8 @@ class TrainModelParams:
|
||||
file_name: str
|
||||
line_separator: str
|
||||
decimal_separator: str
|
||||
date_column: str | None
|
||||
date_format: str | None
|
||||
date_column: str
|
||||
date_format: str
|
||||
train_size: int
|
||||
shuffle: bool
|
||||
random_state: int
|
||||
@@ -102,7 +106,8 @@ class TrainModelParams:
|
||||
|
||||
Args:
|
||||
data: Dictionary containing training parameters with keys matching the
|
||||
attribute names (e.g. variable_columns, data_model_kwargs, model_kwargs, opt_params).
|
||||
attribute names (e.g. variable_columns, date_column, data_model_kwargs, model_kwargs, opt_params).
|
||||
Unknown keys are ignored by from_dict; missing required snake_case keys raise.
|
||||
model_metadata may be omitted or None until load_model_metadata fills it.
|
||||
experiment_run_id may be an int or numeric string.
|
||||
|
||||
@@ -131,8 +136,8 @@ class TrainModelParams:
|
||||
decimal_separator=cls._check_none(
|
||||
data.get('decimal_separator'), str, 'decimal_separator'
|
||||
),
|
||||
date_column=data.get('date_column'),
|
||||
date_format=data.get('date_format'),
|
||||
date_column=cls._check_none(data.get('date_column'), str, 'date_column'),
|
||||
date_format=cls._resolve_date_format(data.get('date_format')),
|
||||
train_size=cls._check_none(data.get('train_size'), int, 'train_size'),
|
||||
shuffle=cls._check_none(data.get('shuffle'), bool, 'shuffle'),
|
||||
random_state=cls._check_none(data.get('random_state', 42), int, 'random_state'),
|
||||
@@ -150,6 +155,29 @@ class TrainModelParams:
|
||||
model_metadata=cls._parse_optional_model_metadata(data.get('model_metadata')),
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def _resolve_date_format(raw: Any) -> str:
|
||||
"""
|
||||
Resolve date_format from workflow input.
|
||||
|
||||
Omitted, null, or blank values use DEFAULT_TRAIN_DATE_FORMAT. Non-string types raise.
|
||||
|
||||
Args:
|
||||
raw: Raw date_format from the payload, or None if absent.
|
||||
|
||||
Return:
|
||||
str: Canonical frontend date format string.
|
||||
"""
|
||||
if raw is None:
|
||||
return DEFAULT_TRAIN_DATE_FORMAT
|
||||
if isinstance(raw, str) and not raw.strip():
|
||||
return DEFAULT_TRAIN_DATE_FORMAT
|
||||
if not isinstance(raw, str):
|
||||
raise TypeError(
|
||||
f'date_format must be a string or omitted, but got {type(raw).__name__}.'
|
||||
)
|
||||
return raw.strip()
|
||||
|
||||
def to_dict(self) -> dict[str, Any]:
|
||||
"""
|
||||
Convert TrainModelParams to a dictionary.
|
||||
@@ -327,7 +355,9 @@ class TrainModelParams:
|
||||
if not self.model_name.strip():
|
||||
raise ValueError('model_name cannot be empty or whitespace')
|
||||
|
||||
if not self.date_column.strip():
|
||||
raise ValueError('date_column cannot be empty or whitespace')
|
||||
|
||||
def _validate_date_format(self) -> None:
|
||||
"""Validate date_format is one of the allowed frontend formats when set."""
|
||||
if self.date_format:
|
||||
validate_frontend_date_format(self.date_format)
|
||||
"""Validate date_format is one of the allowed frontend formats."""
|
||||
validate_frontend_date_format(self.date_format)
|
||||
|
||||
Reference in New Issue
Block a user