fix: unify Parquet schemas when reading - #858
Conversation
Signed-off-by: Steve Han <sthan@nvidia.com>
Greptile SummaryThe PR updates Parquet dataset loading to unify compatible schemas across directory files before reading them.
|
| Filename | Overview |
|---|---|
| packages/data-designer-config/src/data_designer/config/utils/io_helpers.py | Adds permissive schema unification for directory-based Parquet reads, with the existing per-file concatenation behavior retained as fallback. |
| packages/data-designer-config/tests/config/utils/test_io_helpers.py | Adds coverage showing nested integer and fractional values from separate Parquet files are read through a unified floating-point schema. |
Reviews (3): Last reviewed commit: "fix: unify parquet schemas when reading ..." | Re-trigger Greptile
Code Review — PR #858:
|
Signed-off-by: Steve Han <sthan@nvidia.com>
|
Addressed the agentic review in ffc7f94:
Added coverage for boolean item/property/union schemas, both |
nabinchha
left a comment
There was a problem hiding this comment.
Thanks for putting this PR together and for adding a focused regression for #857, @shan-nvidia. A cleaner solution might be to reconcile schemas at the Parquet boundary instead of adding a recursive JSON Schema normalizer.
JSON Schema validation establishes whether a value is valid, but it does not define a canonical Python or Parquet representation—9 and 9.0 are both valid number values. Walking the schema to coerce values effectively reimplements Draft 2020-12 behavior for $ref, anyOf, patternProperties, and related applicators, creating unnecessary correctness and maintenance risks.
I tested the storage-layer approach using the exact reproduction from #857:
- The original directory read failed with the expected nested
int64/doubleArrowInvalid. - Reading with
pa.unify_schemas(..., promote_options="permissive")and passing the resulting schema to Arrow returned[9.0, 9.5]. - Casting and atomically rewriting the mismatched checkpoint files made the reproduction's original
pd.read_parquet(directory)call succeed unchanged.
I recommend:
- Reusing the schema-unification approach already implemented by
_export_parquet(). - Applying it in
read_parquet_dataset()so profiling and dataset loading use an explicit unified schema. - If raw checkpoint compatibility is required, adding a finalization step that atomically rewrites only batches whose schemas differ from the unified schema.
- Retaining the existing Decimal-specific normalization while avoiding generic JSON Schema numeric coercion.
This keeps validation focused on validation, puts physical type reconciliation in the storage layer where it belongs, and handles nested numeric drift regardless of whether the schema uses unions, references, or pattern properties.
This review was generated by an AI assistant.
andreatnvidia
left a comment
There was a problem hiding this comment.
Thanks for putting this together and for the thorough regression coverage. This is a useful fix for a pretty frustrating failure mode.
I found two things I think we should fix before merging, plus two JSON Schema edge cases worth handling while we're here. The blockers are the Decimal path crashing on valid strings and numeric unions narrowing floats back to integers, which can recreate the Parquet failure. I reproduced the cases below against ffc7f942.
Happy to take another look once these are addressed.
Signed-off-by: Steve Han <sthan@nvidia.com>
|
Thanks, @nabinchha. I agreed with the ownership boundary and refactored the PR in
I did not rewrite raw checkpoints because Data Designer's supported profiling/load paths already go through this helper and the repository already treats direct |
|
Fern preview: https://nvidia-preview-pr-858.docs.buildwithfern.com/nemo/datadesigner
|
Thanks @andreatnvidia for the comments! I did a refactoring suggested by Nabin's cleaner option, and change scope is much smaller now. |
andreatnvidia
left a comment
There was a problem hiding this comment.
Thanks for the contribution, @shan-nvidia! Moving schema reconciliation into the Parquet reader is a much cleaner and more focused fix, and it addresses all my earlier concerns. Looks good to me.
Summary
Reconcile compatible Parquet checkpoint schema drift when Data Designer reads a dataset directory. This fixes completed runs failing during profiling or dataset loading when separate batches infer different physical types for the same nested numeric field, such as
9becomingint64in one file and9.5becomingdoublein another.Related Issue
Fixes #857
Changes
read_parquet_dataset().9and9.5checkpoints.This follows the same physical-schema reconciliation approach already used by Parquet export and keeps JSON Schema validation focused on whether values are valid rather than choosing a canonical Python or Parquet representation.
Checkpoint Scope
The change fixes supported Data Designer paths that use
read_parquet_dataset(), including profiling,ArtifactStorage.load_dataset(), result loading, and processor-output loading. It does not rewrite completed checkpoint files. A directpandas.read_parquet(directory)call may therefore still fail on a mixed-schema artifact directory; callers should use the Data Designer result or artifact-storage APIs. The repository already preserves a per-file fallback for schema combinations that Arrow cannot unify.Testing
185 passedin focused config, storage, validator, and response-recipe tests.2901 passedacross the full config and engine suites.1089 passed, 1 skippedin the interface suite before sandbox-only localhost bind failures.31 passedwhen the complete OpenTelemetry test file was rerun with localhost socket access.[9.0, 9.5].Checklist
main