Feat session preprocessing - #876
Open
Creylay wants to merge 16 commits into
Open
Conversation
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.
…n references for manual predictions
…ups in SelectColumnsStep
Creylay
added this pull request to stack #879
September 11, 2026 16:28
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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]:
Changes (by file)
Backend, core engine
DashAI/back/converters/dataset_columns.py: extractedrebuild_dataset_with_transformed_columns(shared with Notebooks) into its own module.DashAI/back/preprocessing/column_ref.py: newColumnRef(raw/group, with an optionalslot),ConverterStep,ConverterSequence(cycle safe scope validation), andresolve_refs.DashAI/back/preprocessing/session_preprocessor.py: newSessionPreprocessor. Fits aConverterSequenceonly on thetrainpartition of a split, transforms every partition present, and classifies each step's real output columns by type using the converter's ownget_output_type.Backend, session
DashAI/back/job/preprocessing_job.py: newPreprocessingJob, dispatched once at session creation. Fits per fold (plus a final fit over the full training pool) or once for Holdout, persists the fittedSessionPreprocessorper 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:ModelSessiongainspreprocessing,input_column_refs,preprocessing_status,preprocessing_error,preprocessing_artifacts_path,preprocessing_job_id.DashAI/back/api/api_v1/endpoints/model_sessions.py:create_model_sessiondispatchesPreprocessingJoband stores its job id,validate_columnsruns 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 ispendingorfailed.Backend, converter metadata and output types
DashAI/back/converters/base_converter.py: exposesoutput_type,output_dtype(best effort, from a bare instance) andpreserves_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: declarePRESERVES_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
tests/back/preprocessing/,tests/back/converters/test_dataset_columns.py,tests/back/test_config_builder.py,tests/back/migrations/, plus extensions totests/back/api/test_model_session_api.pyand newtest_model_job_preprocessing.py,test_run_preprocessing_guard.py,test_predict_preprocessing.py,test_explainer_preprocessing.py.sessionColumnRefs.test.js,AppliedConvertersView.test.jsx,PreprocessingStep.test.jsx,DivideDatasetColumns.test.jsx,modelSession.test.ts.Testing (optional)
uv run pytest tests/back/(full suite passes, except one pre existing failure intest_component_metadata_contract.pyunrelated to this branch and already present ondevelop).yarn test(full suite passes).Notes (optional)
SessionPreprocessoris (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.