feat(interleaved): Foundation IO improvements — schema utilities, base-class fixes, and bug fixes - #1652
Merged
VibhuJawa merged 18 commits intoApr 1, 2026
Conversation
…e-class fixes, and bug fixes Splits out the foundation layer from PR NVIDIA-NeMo#1570 as a standalone PR: Schema utilities (utils/schema.py — new): - reconcile_schema(): canonical types for reserved columns, passthrough columns preserved - align_table(): pad, reorder, cast tables to a target schema; safe=True for passthrough columns to surface overflow errors instead of silently corrupting data (B5 fix) Reader base (readers/base.py): - Add schema= and schema_overrides= parameters for strict schema alignment - _resolve_schema() helper: schema > schema_overrides > INTERLEAVED_SCHEMA priority - Warn (not silently ignore) when both schema= and schema_overrides= are provided (C5) - Fix return type annotation: -> pa.Schema | None (C4) - Preserve nullable=False from INTERLEAVED_SCHEMA when applying schema_overrides (C6) Writer base (writers/base.py): - Add schema= and schema_overrides= for output alignment (same API as reader) - Add on_materialize_error= parameter: "error"|"warn"|"drop_row"|"drop_sample" - _materialize_dataframe(): apply error policy after fetch; guard binary_content column - Make _write_dataframe() non-abstract (default pass body) to allow WDS-style overrides (D3) Materialization (utils/materialization.py): - _build_global_range_index(): group paths by filesystem object so mixed-backend batches work correctly (B3 fix) WebDataset reader (readers/webdataset.py): - Rename tiff result variable to tiff_frame to remove variable shadowing (D5 fix) Parquet reader (readers/parquet.py): - Guard pq.read_schema() call behind if self.fields is not None to avoid N+1 schema reads in the common case (C1 fix) Tests: - test_base_writer.py (new): 9 tests covering on_materialize_error modes, schema alignment, and write_data orchestration - test_materialization.py: 4 new tests for multi-backend path grouping (B3) - test_multimodal_core.py: 4 new align_table tests for safe-cast behaviour (B5) - test_multimodal_reader.py: schema_overrides and nullable preservation tests (C5/C6) - conftest.py: additional helpers for new test patterns Note: InterleavedParquetReader, InterleavedParquetReaderStage, and InterleavedWebdatasetWriterStage are intentionally excluded from this branch; they will be added in the follow-up PR on feat/interleaved-io-readers-writers. Signed-off-by: Vibhu Jawa <vjawa@nvidia.com>
…oundation Signed-off-by: Vibhu Jawa <vjawa@nvidia.com> # Conflicts: # .github/workflows/config/.secrets.baseline
This override was added to work around ray[llm]'s unconditional nixl dep on ARM but is not part of the interleaved IO foundation work. Signed-off-by: Vibhu Jawa <vjawa@nvidia.com>
Reverts the removal — nixl-cu12 override is needed to work around ray[llm]'s unconditional nixl dep on ARM. Signed-off-by: Vibhu Jawa <vjawa@nvidia.com>
source_id_field was only used as a passthrough exclusion hint — the same effect is achievable via the fields= parameter. Having both source_id_field and sample_id_field was confusing with overlapping names. Removing source_id_field simplifies the API with no loss of functionality. Update all tests, benchmarking scripts, tutorials, and README to remove all references to source_id_field. Signed-off-by: Vibhu Jawa <vjawa@nvidia.com>
- align_table: remove redundant reconcile_schema(target) call; the safe/unsafe cast logic already handles large<->small conversions for reserved columns, and re-reconciling a user-provided schema would silently override intentional type overrides - _scatter_range_blobs: restore specific tuple type hints (list[tuple[str,int,int]]) lost when range key shape changed from (offset,size) to (fs_path,offset,size) - reconcile_schema: add comment explaining why dictionary-encoded passthrough columns are unwrapped to their value type Signed-off-by: Vibhu Jawa <vjawa@nvidia.com>
…der metadata - Fix interleaved_data_quickstart.ipynb: - max_aspect_ratio 1.0 -> 2.0 (was dropping 180 rows instead of 22) - write filtered_batch instead of unfiltered batch in Step 5 - Fix InterleavedWebdatasetReaderStage.process(): populate source_files in output metadata from task.data so the writer can use a deterministic hash-based filename instead of a UUID Signed-off-by: Vibhu Jawa <vjawa@nvidia.com>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com> Signed-off-by: Vibhu Jawa <vibhujawa@gmail.com>
The interleaved_data_quickstart.ipynb outputs contain base64-encoded PNG images and hex sha256 hashes flagged by detect-secrets. These are all false positives from inline cell output, not real credentials. Signed-off-by: Vibhu Jawa <vjawa@nvidia.com>
When max_batch_bytes splits a single tar into N batches, each batch
previously got the same source_files=[tar_path], making splits
indistinguishable by source_files alone.
Append '::split_{idx:05d}' to each path when there are multiple splits,
so each batch's source_files uniquely identifies both the source tar and
its position within the split sequence. Single-split output is unchanged.
Signed-off-by: Vibhu Jawa <vjawa@nvidia.com>
…t reader When max_batch_bytes causes the reader to emit multiple InterleavedBatch splits, each split's source_files metadata now lists only the tar files that actually contributed rows to that split, instead of all source tars. Also optimises the hot path: sample_id is recorded once per member (from the first/metadata row) rather than iterating every row, and unique() deduplicates the sample_id column in Arrow before conversion. Signed-off-by: Vibhu Jawa <vjawa@nvidia.com>
This was referenced Mar 24, 2026
…t reader When max_batch_bytes causes the reader to emit multiple InterleavedBatch splits, each split's source_files metadata now lists only the tar files that actually contributed rows to that split, instead of all source tars. Also optimises the hot path: sample_id is recorded once per member (from the first/metadata row) rather than iterating every row, and unique() deduplicates the sample_id column in Arrow before conversion. Signed-off-by: Vibhu Jawa <vjawa@nvidia.com>
- Add test_schema_utils.py: 8 tests for resolve_schema, reconcile_schema, align_table - Add 5 tests in test_multimodal_core.py: aspect ratio edge cases, iter_materialized_bytes paths - Add inputs/outputs contract test in test_base_writer.py - Remove dead metadata-propagation code from utils/schema.py Signed-off-by: Vibhu Jawa <vjawa@nvidia.com>
…oundation Signed-off-by: Vibhu Jawa <vjawa@nvidia.com>
abhinavg4
reviewed
Apr 1, 2026
abhinavg4
reviewed
Apr 1, 2026
| ) | ||
| pipeline.add_stage( | ||
| WebdatasetReader( | ||
| source_id_field="pdf_name", |
Contributor
There was a problem hiding this comment.
I think this change will affect pdf PR too. Why was this removed? Is the reading happening via schema now ?
Contributor
Author
There was a problem hiding this comment.
I just removed it , because it was excessive to have around. It now is just a passthrough column and not given special treatment.
Contributor
Author
There was a problem hiding this comment.
I think if you remove it and its in the dataset, it will just work. Happy to help with your PR too.
Contributor
Author
There was a problem hiding this comment.
We will revisit this discussion in 1657
abhinavg4
approved these changes
Apr 1, 2026
abhinavg4
left a comment
Contributor
There was a problem hiding this comment.
Looks good. left some minor comments.
Signed-off-by: Vibhu Jawa <vjawa@nvidia.com>
thomasdhc
reviewed
Apr 1, 2026
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Vibhu Jawa <vjawa@nvidia.com>
3 tasks
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
This is Part 1 of 2 splitting PR #1570. It contains only the foundation layer improvements (base classes, schema utilities, bug fixes) with no new reader/writer stages. Part 2 (new `InterleavedParquetReader` + `InterleavedWebdatasetWriter`) will follow as a separate PR building on top of this.
What's included
New: `utils/schema.py`
Centralized schema utilities shared by all arrow-based readers and writers:
Reader base (`readers/base.py`)
Writer base (`writers/base.py`)
Materialization (`utils/materialization.py`)
WebDataset reader (`readers/webdataset.py`)
`pyproject.toml`
Tests added / updated
149 / 149 tests pass. Ruff clean.
What's NOT included (Part 2)
Test plan