- Added a method to persist computed regression metrics (MSE, MAE, R²) as MLflow parameters during model training, enhancing model evaluation and tracking. - Updated the Training class to log the equation path if available, improving artifact management.
16 KiB
Train Model Workflow IO Diff (main vs current branch)
Base comparison: git diff main...HEAD
Workflow analyzed: train_model
1) Executive overview
This branch introduces a structural refactor of the training stack and a contract update for workflow input/output.
Main impacts:
- The old in-house training stack (
TrainingRepository,ModelRepository,StorageRepository,model_manager.sientia.models) was replaced by:DataManagerRepository(data prep + metrics + report generation)SientiaModelwrapper from plugin store (sientia_model)SientiaMLflowRepository(MLflow integration)MinioRepository(storage integration)
- Input contract moved from many fixed legacy ML params to a plugin/wrapper-oriented schema (
model_type,*_kwargs,model_metadata, optionalval_file_name). - Workflow return changed from
Noneto a serializable result object (dict[str, Any] | None) containing training execution metadata. - Queue naming and worker bootstrap architecture now depend on runtime (
train_model-<runtime>-queue).
2) Input contract diff (before vs now)
2.1 Previous contract (main)
TrainModelParams in main required a large set of explicit fields for the old preprocessing/model pipeline, focused only in linear regression model:
- Core:
experiment_run_id,variable_columns,target_variablebucket_name,file_name,line_separator,decimal_separatortrain_size,shuffle
- Legacy preprocessing/model fields focused only in linear regression model (required in
from_dict):lag_train,lag_valrem_static_win,low_lim,upp_lim,windowuse_scaler,include_ar,scaler_nameremoved_intervals,start_date,end_date,nan_treatmentdegree,interaction_onlyexperiment_name,model_namesupport_filters(optional dict),static_threshold(optional int)
Validation was strongly tied to this structure (lag ranges, limits consistency, polynomial/scaler constraints, etc.).
2.2 Current contract (this branch)
TrainModelParams now supports a plugin-driven schema and wrapper kwargs:
- Kept/mandatory core fields:
experiment_run_id(now accepts numeric string too; coerced to int)variable_columns,target_variablebucket_name,file_name,line_separator,decimal_separatortrain_size,shufflemodel_namemodel_typedata_model_kwargs,model_kwargs,opt_params(required as dict by currentfrom_dict)
- New/updated fields:
random_state(default42)val_file_name(optional explicit validation file)model_id(currently optional, but needs discussion, since the model metadata in MongoDB should be created before the model training)
- Removed from required input contract:
lag_train,lag_val,rem_static_win,low_lim,upp_lim,windowuse_scaler,include_ardegree,interaction_only,nan_treatmentstart_date,end_date,scaler_nameremoved_intervals,support_filters,static_threshold
- Parameters internally derived:
model_metadatamodel type info from plugin store.run_nameis internally derived from experiment name and datetime.experiment_nameis internally derived frommodel_name.
2.3 Validation behavior changes
Before:
- Validation was mostly hardcoded business checks tied to legacy linear/polynomial stack.
Now:
- Validation still checks core constraints (
train_size, non-empty strings, etc.), but model-specific validation moved to JSON Schema driven checks, using OpenAPI/JSON Schema definitions from plugin store:model_metadata.schemas.components.schemas.data_modelmodel_metadata.schemas.components.schemas.modelmodel_metadata.schemas.components.schemas.opt_params
model_metadatais now a required semantic dependency forvalidate_business_rules().- Date format validation remains, but allowed formats are defined locally in
train_model_params.py.
2.4 Input loading pipeline changes in workflow
Before:
validate_train_paramsdirectly consumed workflow input.
Now:
load_model_metadataruns first (fetches model index/schema from plugin store and injectsmodel_metadata).validate_train_paramsruns with enriched payload.
This means IO preprocessing now depends on plugin-store metadata resolution before final validation.
3) Output contract diff (before vs now)
3.1 Workflow return (train_model.run)
Before (main):
- Return type:
None - Workflow side effects were persisted mainly via DB status updates and MLflow artifacts.
Now:
- Return type:
dict[str, Any] | None - Workflow returns the training activity summary when successful.
3.2 Activity-level training result payload
Before (from Training.train_model in main path):
- Returned minimal dict:
run_namerun_dir
Now:
- Returns extended dict:
run_nameexperiment_namerun_idrun_dir
3.3 Persistence map by destination (DB, MLflow, MinIO, local filesystem)
This section maps where each artifact/metadata goes, in which format, and how that changed from main.
3.3.1 PostgreSQL (experiment_run table)
Before (main)
- Update path:
update_experiment_runactivity withUpdateType.MODEL_SAVED. - Persisted on success:
statustransition toTRAINING_SUCCESSrun_name(MLflow run identifier used by current implementation)
- Persisted on failures:
statustransition to validation/training error statuseserror_message
Now (current branch)
- Same update path and status/error behavior.
- Even though train activity now returns more metadata (
run_id,experiment_name), current workflow update forMODEL_SAVEDstill forwards mainlyrun_name. - Practical effect:
- DB remains status-centric and run-name-centric
- richer identifiers exist in workflow return payload, not fully mirrored to DB columns in current flow
3.3.2 MLflow (tracking server/artifact store)
Before (main)
- Persistence orchestration lived in
ModelRepository.save_model()+_save_run(). - Typical persisted content:
- model params (many legacy params such as lags, limits, scaler config, removed intervals)
- regression metrics (
MSE,R2,MAE) - model objects:
data_modelprediction_model
- artifacts:
report.htmltrain_data.csvtest_data.csv- optional
model_equation.json
- Run naming:
- computed by querying existing runs and appending sequence (
<experiment>-<n>style)
- computed by querying existing runs and appending sequence (
Now (current branch)
- Persistence orchestrated in
Training._persist_training_artifacts()and MLflow run context is opened bySientiaMLflowRepository.start_run(...). - Persisted content now:
- model wrapper itself via
wrapper.store_model(name=train_params.model_name) - regression metrics also logged as MLflow params via
mlflow.log_param(...):mse_valmae_valr2_val
- artifacts explicitly logged with
mlflow.log_artifact(...):report.htmltrain_data.csvtest_data.csv
- metrics are computed before save (
mse_val,mae_val,r2_val) and persisted in the run as params
- model wrapper itself via
- Run identifiers now exposed back to workflow:
experiment_namerun_namerun_id
- Notable behavioral change:
wrapper._input_exampleis cleared (None) before storing model.
3.3.3 MinIO object storage
Before (main)
- Read path:
- single source object downloaded via
StorageRepository.fetch_file(bucket_name, file_name)
- single source object downloaded via
- Write path:
- training workflow did not write generated outputs to MinIO in this code path
- generated artifacts were persisted to MLflow, not uploaded back to MinIO
- Location:
- source data in input bucket/key provided by workflow input (
bucket_name+file_name)
- source data in input bucket/key provided by workflow input (
Now (current branch)
- Read path migrated to
MinioRepository.download_file(...). - Supports two input objects:
- mandatory training object:
bucket_name+file_name - optional validation object: same
bucket_name+val_file_name
- mandatory training object:
- Write path:
- still no artifact upload to MinIO in this workflow path
- report/CSV outputs continue to flow to MLflow artifacts
- Location details:
- bucket resolved from payload (
bucket_name) - object key exactly from payload (
file_name, optionalval_file_name) - default bucket in env/config is
MINIO_DEFAULT_BUCKET, but runtime payload can override viabucket_name
- bucket resolved from payload (
3.3.4 Local filesystem (ephemeral runtime workspace)
Before (main)
- Temporary run dir created under reports root using run name + timestamp suffix.
- Artifacts generated locally in that directory:
report.htmltrain_data.csvtest_data.csv- optional
model_equation.json
- After MLflow logging, cleanup activity removed temp directory.
Now (current branch)
- Temporary run dir managed by
DataManagerRepositoryunder runtime reports root (.../reports/temp/<run_name>). - Same artifact family generated locally:
report.htmltrain_data.csvtest_data.csv- optional
model_equation.json(forlinear_regression)
- Cleanup behavior is now tolerant:
- cleanup runs in guarded
finally - training success is not reverted if cleanup later fails
- cleanup runs in guarded
3.3.5 Quick matrix (before vs now)
- Postgres
- before: status + run_name + errors
- now: same persisted shape; workflow return contains extra IDs
- MLflow
- before: legacy model objects + params/metrics + report/data artifacts
- now: wrapper-based model persistence +
mse_val/mae_val/r2_valas params + report/data artifacts + run_id exposed
- MinIO
- before: reads 1 CSV input object
- now: reads 1 or 2 CSV input objects (train + optional validation), still no output upload
- Local temp
- before: generated artifacts, then cleanup
- now: generated artifacts, then best-effort cleanup (non-blocking for success result)
3.4 Cleanup behavior impact on output semantics
Before:
- Cleanup was called directly after training result; failures propagated straightforwardly.
Now:
- Cleanup is in a guarded
finally. - If training succeeded but cleanup fails, workflow warns and does not rollback success semantics.
- Effective output semantics: successful training result can be returned even if temp cleanup fails.
4) Detailed field mapping (old -> new)
Kept (or equivalent role)
experiment_run_id-> kept (broader accepted types: int or numeric string)variable_columns-> kepttarget_variable-> keptbucket_name-> keptfile_name-> keptline_separator-> keptdecimal_separator-> keptdate_column-> kept optionaldate_format-> kept optionaltrain_size-> keptshuffle-> keptmodel_name-> kept (now less coupled to legacy model enum)
Added
model_type(primary selector for plugin wrapper/index lookup)data_model_kwargsmodel_kwargsopt_paramsval_file_name(optional second dataset input)model_id(optional metadata)model_metadata(loaded/required for schema validation)random_state(explicit split reproducibility control)
Removed from new required contract
lag_train,lag_valrem_static_win,static_thresholdlow_lim,upp_limwindowuse_scaler,include_ardegree,interaction_onlynan_treatmentstart_date,end_datescaler_nameremoved_intervalssupport_filtersexperiment_name(no longer required as top-level client input)
5) Internal architecture update notes
5.1 Repository layer redesign
Removed:
model_manager/utils/repository/model_repository.pymodel_manager/utils/repository/training_repository.pymodel_manager/utils/repository/storage_repository.py
Added:
model_manager/utils/repository/data_manager_repository.py
Interpretation:
- Data preprocessing/report/metrics responsibilities were consolidated into
DataManagerRepository. - Training/model persistence shifted to wrapper + plugin store + MLflow repository integrations.
5.2 Model engine abstraction migration
Before:
- Strong coupling to local classes in
model_manager.sientia.modelsand custom preprocessing/model objects inTrainModelResult.
Now:
- Training uses
SientiaModelwrapper dynamically obtained byplugin_store.get_model(model_type=...). - Contract is wrapper-driven (
train,transform,predict,store_model). - The codebase removed
model_manager/sientia/models.py,model_serving.py, andutils.py, indicating full migration to externalized model runtime abstraction.
5.3 Worker/runtime architecture changes
- New
prepare_worker.pycentralizes worker setup and autoscaling parameters. - Queue names are now runtime-derived:
train_model-<runtime>-queuecleanup_files-<runtime>-queue
worker.pynow installs runtime via plugin store (plugin_store.install_runtime(runtime_name=...)) before starting workers.- This introduces environment/runtime-aware deployment and model packaging behavior.
5.4 Synchronous activity and tracking adjustments
experiment_trackingmigrated from async postgres helper to sync postgres client path (postgres_sync).- Several activities switched to sync method signatures.
- Error handling in workflow and DB status update paths is more defensive (secondary failures while persisting error status are logged and do not mask primary failure cause).
5.5 TrainModelResult shape update
Before:
- Stored classic split artifacts (
x_train,x_test,y_train,y_test) + concrete preprocessing/model objects (process_data,regr,scaler_dict).
Now:
- Stores
train_data,val_dataand prediction DataFrames, plus tracking identifiers (experiment_name,run_id). - Result object is less tied to internal estimator classes and more aligned with serializable workflow/model-store integration.
6) Net IO compatibility assessment
Input compatibility
Not backward compatible with old payloads without adaptation.
Key reasons:
- Legacy required fields removed/ignored by new path.
- New required fields introduced (
model_type,*_kwargsdicts, runtime metadata flow dependency). - Validation pipeline now expects model metadata semantics.
Output compatibility
Behavior changed:
- Workflow now returns a result object (previously
None). - Training summary includes
experiment_nameandrun_idin addition torun_nameandrun_dir. - DB update still centered on
run_name; callers relying only on DB may not see all new output info unless workflow return is consumed.
7) Practical migration guidance (client side)
To call train_model in this branch:
- Send snake_case payload aligned to new
TrainModelParams. - Always provide:
model_nameslugified model name (ex.:test_model_name or test-model-name)model_typedata_model_kwargs(dict)model_kwargs(dict)opt_params(dict)
- Keep
experiment_run_idnumeric (int or numeric string). - Use runtime queue naming consistent with worker runtime:
train_model-<runtime>-queue
- If you need explicit validation split file, send
val_file_name; otherwise split usestrain_size/shuffle/random_state.
8) Source references used for this document
Primary diffs:
model_manager/workflows/train_model.pymodel_manager/utils/models/train_model_params.pymodel_manager/utils/models/train_model_result.pymodel_manager/activities/training.pymodel_manager/activities/activities.pymodel_manager/activities/experiment_tracking.pymodel_manager/utils/repository/data_manager_repository.pymodel_manager/utils/repository/model_repository.py(removed)model_manager/utils/repository/training_repository.py(removed)model_manager/utils/repository/storage_repository.py(removed)model_manager/worker/worker.pymodel_manager/worker/prepare_worker.pyREADME.mdinput-sample.mdscripts/run_training_test.py