Skip to content

feat(datasets): add DatasetProfile contract - #650

Merged
albcui merged 5 commits into
mainfrom
albcui/dataset-profile-contract
Jul 31, 2026
Merged

feat(datasets): add DatasetProfile contract#650
albcui merged 5 commits into
mainfrom
albcui/dataset-profile-contract

Conversation

@albcui

@albcui albcui commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • New Features

    • Introduced a versioned dataset profiler storage contract to persist dataset metadata, sampling details, per-partition feature schemas, column statistics, and objective classifications, including optional verifiability and evidence.
  • Tests

    • Added fixture-driven coverage validating schema version defaults, lossless JSON round-trips, dataset-specific contract shape constraints, deep semantic-role parsing, permissive handling of open vocabularies, forward-compatible parsing of unknown fields, and correct construction of quantiles and message statistics.

@albcui
albcui marked this pull request as ready for review July 13, 2026 16:13
@albcui
albcui requested review from a team as code owners July 13, 2026 16:13
@github-actions github-actions Bot added the feat label Jul 13, 2026
@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds a Pydantic stored contract for dataset profiles, including classification, recursive schemas, statistics, partition metadata, sampling, and serialization. Tests cover YAML fixtures, JSON round trips, nested semantic roles, open vocabularies, forward compatibility, and message statistics.

Changes

Dataset profile contract

Layer / File(s) Summary
Classification and statistics models
packages/nemo_platform_plugin/src/nemo_platform_plugin/files/dataset_profile.py
Defines evidence, classification, recursive feature-schema, and column-statistics models.
Profile containers and envelope
packages/nemo_platform_plugin/src/nemo_platform_plugin/files/dataset_profile.py
Adds file, split, partition, sampling, and root dataset profile models, then rebuilds the recursive schema model.
Fixtures and contract validation
packages/nemo_platform_plugin/tests/files/test_dataset_profile.py
Adds representative YAML profiles and tests serialization, fixture structure, nested semantic roles, vocabulary handling, unknown fields, and statistics construction.

Suggested reviewers: soluwalana

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 60.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: adding the DatasetProfile contract.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch albcui/dataset-profile-contract

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
packages/nemo_platform_plugin/src/nemo_platform_plugin/files/dataset_profile.py (1)

32-32: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Scope the forward reference instead of stringifying the whole module.

from __future__ import annotations makes every annotation in the file a string, which conflicts with the "prefer concrete type hints over string-based type hints" guideline — even though only the two self-referencing FeatureSchema.fields/items fields actually need it. Pydantic v2 resolves a quoted self-reference on just those fields without the future import (model_rebuild() still required either way).

♻️ Narrow the forward reference to the two self-referencing fields
-from __future__ import annotations
-
 from datetime import datetime
@@
-    fields: list[FeatureSchema] | None = Field(default=None, description="dtype == struct: named child fields.")
-    items: FeatureSchema | None = Field(default=None, description="dtype in {list, messages}: element schema.")
+    fields: list["FeatureSchema"] | None = Field(default=None, description="dtype == struct: named child fields.")
+    items: "FeatureSchema" | None = Field(default=None, description="dtype in {list, messages}: element schema.")

As per coding guidelines, **/*.py should "prefer concrete type hints over string-based type hints," and the plugin-scoped rule reiterates the same preference.

Also applies to: 189-190, 361-361

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@packages/nemo_platform_plugin/src/nemo_platform_plugin/files/dataset_profile.py`
at line 32, Remove the module-wide `from __future__ import annotations` in
`dataset_profile.py` and scope forward references only to the self-referencing
`FeatureSchema.fields` and `FeatureSchema.items` annotations using quoted types.
Preserve the existing `model_rebuild()` behavior and keep all unrelated
annotations concrete.

Source: Coding guidelines

packages/nemo_platform_plugin/tests/files/test_dataset_profile.py (1)

171-206: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

_build_profile doesn't actually exercise TextStats/NumericStats.

ColumnStats(text=None) and ColumnStats(numeric=None) are no-ops (both default to None already), so despite the docstring claiming to exercise "every model in the contract," TextStats/NumericStats/Quantiles are never directly constructed here — only reached indirectly via the YAML fixtures elsewhere in the file.

♻️ Populate real stat objects
                 stats={
-                    "prompt": ColumnStats(text=None),
-                    "response": ColumnStats(numeric=None),
+                    "prompt": ColumnStats(text=TextStats(chars=Quantiles(p50=10, p95=40, p99=60, max=100))),
+                    "response": ColumnStats(numeric=NumericStats(min=0.0, max=1.0, mean=0.5)),
                 },

(Requires importing TextStats/NumericStats alongside the existing imports.)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/nemo_platform_plugin/tests/files/test_dataset_profile.py` around
lines 171 - 206, Update _build_profile to construct and assign actual TextStats
and NumericStats instances in the prompt and response ColumnStats entries,
including a populated Quantiles instance where required by those models. Add the
corresponding TextStats and NumericStats imports alongside the existing model
imports so the hand-built profile directly exercises these contract models.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In
`@packages/nemo_platform_plugin/src/nemo_platform_plugin/files/dataset_profile.py`:
- Line 32: Remove the module-wide `from __future__ import annotations` in
`dataset_profile.py` and scope forward references only to the self-referencing
`FeatureSchema.fields` and `FeatureSchema.items` annotations using quoted types.
Preserve the existing `model_rebuild()` behavior and keep all unrelated
annotations concrete.

In `@packages/nemo_platform_plugin/tests/files/test_dataset_profile.py`:
- Around line 171-206: Update _build_profile to construct and assign actual
TextStats and NumericStats instances in the prompt and response ColumnStats
entries, including a populated Quantiles instance where required by those
models. Add the corresponding TextStats and NumericStats imports alongside the
existing model imports so the hand-built profile directly exercises these
contract models.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: d067794a-2f37-457d-ae8d-ab85c5354104

📥 Commits

Reviewing files that changed from the base of the PR and between 275c8cd and 6c3fb39.

📒 Files selected for processing (2)
  • packages/nemo_platform_plugin/src/nemo_platform_plugin/files/dataset_profile.py
  • packages/nemo_platform_plugin/tests/files/test_dataset_profile.py

@albcui
albcui force-pushed the albcui/dataset-profile-contract branch from 6c3fb39 to adc3f32 Compare July 13, 2026 16:28
@github-actions

github-actions Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor
Suite Lines Covered Line Rate Branch Rate
Unit Tests 27336/35059 78.0% 62.2%
Integration Tests 16090/33771 47.6% 19.9%

@albcui
albcui requested a review from soluwalana July 13, 2026 21:20
@albcui
albcui force-pushed the albcui/dataset-profile-contract branch 2 times, most recently from f571cbb to c284981 Compare July 16, 2026 18:33

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@packages/nemo_platform_plugin/src/nemo_platform_plugin/files/dataset_profile.py`:
- Around line 193-202: Update the CategoricalStats values field to accept
integer categorical values alongside strings, using the existing contract’s
typing conventions. Preserve the optional default and the requirement that
values represent exhaustive enumerations with distinct_count <= 32.
- Around line 174-182: Enforce the schema invariants in FeatureSchema: allow
fields only for struct dtypes, items only for list or messages dtypes, and
fixed_length only for list dtypes, rejecting incompatible combinations during
validation. In PartitionProfile.stats, validate that every stats key matches a
top-level feature name, covering both the FeatureSchema definition and the stats
validation site.
- Around line 62-65: Constrain the fraction fields in the dataset profile
model—coverage, ends_with_assistant_rate, valid_alternation_rate,
whitespace_ratio, non_ascii_ratio, and null_rate—by adding inclusive lower and
upper bounds of 0 and 1 to each Field declaration. Preserve their existing
defaults and descriptions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 03b76d9b-3745-486e-8059-7890e0750d13

📥 Commits

Reviewing files that changed from the base of the PR and between adc3f32 and c284981.

📒 Files selected for processing (2)
  • packages/nemo_platform_plugin/src/nemo_platform_plugin/files/dataset_profile.py
  • packages/nemo_platform_plugin/tests/files/test_dataset_profile.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/nemo_platform_plugin/tests/files/test_dataset_profile.py

@albcui
albcui force-pushed the albcui/dataset-profile-contract branch from c284981 to 6af01ec Compare July 16, 2026 19:25
@albcui
albcui force-pushed the albcui/dataset-profile-contract branch from 6af01ec to 4e2e467 Compare July 24, 2026 20:02
Comment thread packages/nemo_platform_plugin/src/nemo_platform_plugin/files/dataset_profile.py Outdated
albcui added 5 commits July 27, 2026 13:24
Signed-off-by: Albert Cui <albcui@nvidia.com>
Signed-off-by: Albert Cui <albcui@nvidia.com>
A feature node is either a named-field container or has a single element
schema, never both. Enforce that invariant, and only that one: it holds
for any dtype, so it costs no forward compatibility. Tying fields /
items / fixed_length to specific dtype values would reject a profile
written by a newer profiler that added a container dtype, which is what
the open vocabulary exists to prevent.

Signed-off-by: Albert Cui <albcui@nvidia.com>
Address review comments on fields whose descriptions said when a value
was trustworthy without saying what it counted:

- rows_total: the whole-fileset denominator rows_scanned is a fraction
  of; None means unknown, never zero and never an estimate.
- files_scanned: a count, not a list; points at SplitProfile.files.
- SplitProfile.files: was undescribed; state the exhaustive-and-disjoint
  split partitioning the PartitionProfile docstring already relies on.
- num_examples: counts every file in the split, scanned or not.
- roles_seen: record why this is not an enum. Unlike dataset_type or
  modality, which are vocabularies the profiler picks from, this is
  verbatim row content — ShareGPT emits human/gpt, Llama tooling emits
  ipython. Normalizing or dropping an unexpected role would hide the
  signal a consumer needs to choose a chat template.

Signed-off-by: Albert Cui <albcui@nvidia.com>
…ontract

"Inference" collides with LLM inference, which is the wrong association
for a profiler that matches column names and probes content. Replace all
ten occurrences with "detected" / "detection", already the module vocabulary
("new detectors" in the schema-version note, "when nothing was detected"
on semantic_role).

Deliberately not "derived": the file uses that for the measured side --
"the derived row schema", "derived de novo from the data" -- and reusing
it would blur the fact-vs-judgment split the two-layer design rests on.

Signed-off-by: Albert Cui <albcui@nvidia.com>
@albcui
albcui force-pushed the albcui/dataset-profile-contract branch from 33b39b9 to 59b0b0b Compare July 27, 2026 17:24
@albcui
albcui enabled auto-merge July 31, 2026 19:12
@albcui
albcui added this pull request to the merge queue Jul 31, 2026
Merged via the queue into main with commit 1c64d4c Jul 31, 2026
58 checks passed
@albcui
albcui deleted the albcui/dataset-profile-contract branch July 31, 2026 19:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants