Skip to content

Feat session preprocessing - #876

Open
Creylay wants to merge 16 commits into
developfrom
feat/session-preprocessing
Open

Feat session preprocessing#876
Creylay wants to merge 16 commits into
developfrom
feat/session-preprocessing

Conversation

@Creylay

@Creylay Creylay commented Sep 11, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds leak-safe preprocessing to Models-module sessions. Converters (scalers, encoders, Bag-of-Words, etc.) can now be configured as part of session creation, and are fit only on training data (once per fold for Cross-Validation, once for Holdout), instead of the current Notebooks behavior of fitting converters on the entire dataset before any split exists. Converters declare their output by type instead of by a concrete column name, so the wizard can reference "whatever this converter will produce" before any real fit happens, and later converters can chain off an earlier one's not yet materialized output (including one specific type, when that output is a mix of types).


Type of Change

Check all that apply like this [x]:

  • Backend change
  • Frontend change
  • CI / Workflow change
  • Build / Packaging change
  • Bug fix
  • Documentation

Changes (by file)

Backend, core engine

  • DashAI/back/converters/dataset_columns.py: extracted rebuild_dataset_with_transformed_columns (shared with Notebooks) into its own module.
  • DashAI/back/preprocessing/column_ref.py: new ColumnRef (raw/group, with an optional slot), ConverterStep, ConverterSequence (cycle safe scope validation), and resolve_refs.
  • DashAI/back/preprocessing/session_preprocessor.py: new SessionPreprocessor. Fits a ConverterSequence only on the train partition of a split, transforms every partition present, and classifies each step's real output columns by type using the converter's own get_output_type.

Backend, session

  • DashAI/back/job/preprocessing_job.py: new PreprocessingJob, dispatched once at session creation. Fits per fold (plus a final fit over the full training pool) or once for Holdout, persists the fitted SessionPreprocessor per fold/final, resolves the session's input column references to concrete columns, and validates against the task.
  • DashAI/back/dependencies/database/models.py, DashAI/alembic/versions/f4a91c62d8e7_add_preprocessing_to_model_session.py: ModelSession gains preprocessing, input_column_refs, preprocessing_status, preprocessing_error, preprocessing_artifacts_path, preprocessing_job_id.
  • DashAI/back/api/api_v1/endpoints/model_sessions.py: create_model_session dispatches PreprocessingJob and stores its job id, validate_columns runs a best effort, pre fit type check for group references.
  • DashAI/back/job/model_job.py, predict_job.py, explainer_job.py: load the already fitted preprocessor (never re-fit) before training, predicting or explaining.
  • DashAI/back/api/api_v1/endpoints/runs.py: rejects creating a Run while a session's preprocessing is pending or failed.

Backend, converter metadata and output types

  • DashAI/back/converters/base_converter.py: exposes output_type, output_dtype (best effort, from a bare instance) and preserves_input_type (true for a converter that only keeps or drops whole columns unchanged, e.g. feature selection).
  • DashAI/back/converters/category/feature_selection.py, scikit_learn/variance_threshold.py: declare PRESERVES_INPUT_TYPE = True.
  • DashAI/back/job/converter_job.py: reduced to reuse the extracted column rebuilding helper, no behavior change.

Frontend, model session

  • DashAI/front/src/components/models/CreateSessionSteps.jsx: converted the session wizard into a real 3 step flow (Prepare Dataset, Preprocessing, Select Columns).
  • DashAI/front/src/components/models/modelSession/PreprocessingStep.jsx, AppliedConvertersView.jsx, SessionConvertersRightBar.jsx, FormSessionConverterSection.jsx, ScopeStepSessionConverter.jsx: the new preprocessing step, mirroring Notebooks' converter picker (search, list/grid, drag and drop), applied converter cards, and scope selection (including chaining onto an earlier step's output, or one specific type of it).
  • DashAI/front/src/components/models/modelSession/sessionColumnRefs.js: synthetic key representation of a column reference (raw column, or a converter's output group, optionally narrowed to one type), used anywhere a flat column list is expected.
  • DashAI/front/src/components/models/modelSession/SelectColumnsStep.jsx, DivideDatasetColumns.jsx: final input/output column selection, offering a converter's output group alongside raw columns, defaulting the input selection to the last configured step's output when preprocessing is set.
  • DashAI/front/src/components/models/modelSession/PrepareDatasetStep.jsx: trimmed down, adds the "Apply preprocessing" toggle.

Frontend, session status and error handling

  • DashAI/front/src/components/models/ModelsContext.jsx, SessionVisualization.jsx: track a session's preprocessing status through the same shared job polling mechanism every other job backed indicator already uses, instead of an independent timer that could drift out of sync with it.
  • DashAI/front/src/components/models/AddModelDialog.jsx: surfaces the backend's real error detail when creating a Run fails, instead of a generic message.
  • DashAI/front/src/components/models/ManualPredictionsTable.jsx: manual prediction now asks for the raw dataset columns a session's preprocessing needs, not its already resolved output columns (the backend only ever accepts real dataset columns as manual input).

Tests

  • Backend: tests/back/preprocessing/, tests/back/converters/test_dataset_columns.py, tests/back/test_config_builder.py, tests/back/migrations/, plus extensions to tests/back/api/test_model_session_api.py and new test_model_job_preprocessing.py, test_run_preprocessing_guard.py, test_predict_preprocessing.py, test_explainer_preprocessing.py.
  • Frontend: sessionColumnRefs.test.js, AppliedConvertersView.test.jsx, PreprocessingStep.test.jsx, DivideDatasetColumns.test.jsx, modelSession.test.ts.

Testing (optional)

  • Backend: uv run pytest tests/back/ (full suite passes, except one pre existing failure in test_component_metadata_contract.py unrelated to this branch and already present on develop).
  • Frontend: yarn test (full suite passes).
  • Manual: created Holdout and Cross-Validation sessions with converter chains (Bag of Words, PCA, One-Hot Encoder, Standardizer, Simple Imputer) across text, tabular and regression datasets, trained runs, ran manual and dataset predictions, and local/global explanations.

Notes (optional)

  • Output columns (the session's target) must stay raw in this version. Letting the target be a converter's output would require splitting/stratifying before any fit exists, which needs its own design pass.
  • No transformed dataset is ever persisted. Only the fitted SessionPreprocessor is (one per fold, plus a final one), and every transformed view is rebuilt on demand from the original dataset by re-applying it, never by re-fitting.

Fits a session's converter sequence once at creation time (per fold for
Cross-Validation, once for Holdout) instead of applying converters on the
full dataset before any split exists, which leaked validation/test data
into the fit. Resolves the session's input columns from the fitted
sequence and persists preprocessing status/errors on the session.
…nation

Training reuses the SessionPreprocessor already fitted by PreprocessingJob
instead of ever re-fitting on new data. Prediction and explanation apply
the final fitted preprocessor to raw/manual input before running. Run
creation is blocked with a clear error while a session's preprocessing is
still pending or failed.
…ut group

BagOfWordsConverter (and any converter with the same shape, e.g. Binarizer)
keeps its scope column unchanged and appends new derived columns instead
of replacing it. SessionPreprocessor was recording every column the
converter's transform() returned as the step's output group, so the
untouched original column leaked into it too — selecting only "this
converter's output" as a session's input still smuggled in the raw column,
which fails task validation when it isn't an allowed input type (e.g. Text).
output_type already reported the semantic type name (e.g. "Integer") from
a default-constructed instance; output_dtype adds the concrete storage
dtype (e.g. "int64") the same way, so a converter's not-yet-materialized
output group can show a real dtype instead of falling back to unknown.
…nverter picker

A Models-module session can now optionally configure a sequence of
converters as part of creation. The wizard reuses Notebooks' own tool
picker (search, list/grid, drag-and-drop) and column selector so the
scope/output-group UX matches exactly, and represents a converter's
not-yet-materialized output group as a synthetic column key so it can be
picked as an input before any real fit exists (and chained into a later
converter's own scope).
…echanism

Uses useJobTracker (the same mechanism every other job-backed indicator in
the app already relies on: RunnerDialog, ComponentDownloadControl,
prediction/explainer panels) instead of an independent timer polling
preprocessing_status, so the session's processing/failed views never drift
out of sync with what the Job Queue widget shows for the same job.
handleCreateRun always showed the same generic message regardless of
cause, so a session blocked by the preprocessing-not-ready guard (or any
other backend rejection) never told the user why. Uses the project's
existing getApiErrorMessage helper (already used by RAG) to show the
backend's actual detail, falling back to the generic message only when
there isn't one.
… column types

- Introduced `_classify_by_type` method in `SessionPreprocessor` to categorize output columns by their types.
- Updated the fitting process to resolve output slots for each step, allowing converters to handle mixed types.
- Modified `AppliedConvertersView` to display output entries as chips for each declared slot.
- Adjusted tests to cover new functionality, including validation of slotted group references and output slot resolution.
- Enhanced `resolveDeclaredOutputSlots` to determine output types based on the converter's scope and type preservation.
- Updated frontend components to accommodate changes in output structure and ensure proper rendering of converter outputs.
@Creylay Creylay changed the title Feat/session preprocessing Feat session preprocessing Sep 11, 2026
@Creylay Creylay added front Frontend work back Backend work labels Sep 11, 2026
@Creylay
Creylay added this pull request to stack #879 September 11, 2026 16:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

back Backend work front Frontend work

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant