fix: set full s3_input fields on QualityCheckStep baseline_dataset pipeline-variable input - #6322
Conversation
…peline-variable input When baseline_dataset is a pipeline variable, _generate_baseline_job_inputs built a ProcessingInput whose s3_input dict omitted s3_data_type (required by ProcessingS3Input -> ValidationError) and also left s3_input_mode / s3_data_distribution_type as the Unassigned() sentinel, which breaks pipeline.definition() serialization with 'TypeError: Object of type Unassigned is not JSON serializable'. Set all three to match what the non-pipeline-variable branch (_upload_and_convert_to_processing_input) produces. Fixes aws#6206
|
Claude finished @mohamedzeidan2021's task in 1m 6s —— View job Code ReviewI reviewed this PR against Task list
Correctness ✅The fix is exactly right. s3_input=ProcessingS3Input(
s3_uri=source,
local_path=destination,
s3_data_type="S3Prefix",
s3_input_mode="File",
s3_data_distribution_type="FullyReplicated",
),So the two branches now produce consistent inputs — the backward-compatibility claim holds. It's also consistent with the sibling The PR body's reasoning about the TestsThe added regression test fails on master and passes with the fix, and the core assertions are the right ones:
Minor nit (non-blocking): the Style-only observations (imports inside the test function, Security / PerformanceNo concerns — no credential handling, no new input surface, no perf implications. The values are static constants matching an existing code path. Nice, well-documented fix. The inline code comment explaining why all three fields are needed (not just |
Issue
Fixes #6206
QualityCheckStep._generate_baseline_job_inputs()builds aProcessingInputfrom ans3_inputdict whenbaseline_datasetis a pipeline variable (Join,ParameterString, ...). That dict omitteds3_data_type, whichProcessingS3Inputrequires, so constructing the step raised:Fix
Set the same fields on the pipeline-variable branch that the non-pipeline-variable branch already ships via
_upload_and_convert_to_processing_input(model_monitoring.py):s3_data_type="S3Prefix",s3_input_mode="File",s3_data_distribution_type="FullyReplicated".s3_data_typealone makes the model constructible, but is not sufficient: leavings3_input_modeunset keeps it as theUnassigned()sentinel, and theargumentsserializer emits that sentinel (itsgetattr(..., "File")fallback never applies because the attribute is set to the sentinel), sopipeline.definition()would then fail withTypeError: Object of type Unassigned is not JSON serializable. Setting all three fully unblocks the pipeline-variable path and keeps it consistent with both the else-branch and the siblingclarify_check_step.Testing
sagemaker-mlops/tests/unit/workflow/test_quality_check_step.py::test_generate_baseline_job_inputs_with_pipeline_variable_baseline_dataset: builds the step with aJoinbaseline dataset, asserts the resultings3_inputhass3_data_type="S3Prefix"and thats3_input_mode/s3_data_distribution_typeare concrete (notUnassigned), thenjson.dumpsof the serialized fields to guard the definition-serialization path. Fails on master, passes with the fix.Verified end to end: with the fix, the interpolated +
json.dumps'dS3Inputproduces a valid pipeline definition (S3Uri→ theJoinexpression{"Std:Join": {...}},S3DataType": "S3Prefix",S3InputMode": "File"); on master it raises the reportedValidationError.test_quality_check_step.py+test_quality_check_step_kms.py= 11 passed;black(100) /flake8(120) clean.Backwards compatibility
The non-pipeline-variable branch is untouched.
File/FullyReplicatedmatch the values the else-branch already sends, so the two branches now produce consistent inputs.