Add flexible data source discovery to load_raw_dataset (#661)#675
Conversation
) ## Summary Extends `load_raw_dataset()` from two source types to a four-step resolution chain so a speculator can be trained on local file shards and arbitrary HuggingFace datasets without a preset, composing freely across mixed `--data` usage. ## Motivation Previously `--data` accepted only a local `.json`/`.jsonl` file or a named preset from `DATASET_CONFIGS`. Local data bundles had to be listed file by file, and any HF dataset not already in the registry required adding a preset. This implements the discovery piece of RFC vllm-project#661 (kept separate from the schema-normalization work) and promotes Magpie/Nemotron to shared presets. ## Changes - `load_raw_dataset` resolves a source in order: 1. Local `.json`/`.jsonl` file (existing). 2. Local directory: recursively glob `*.json`/`*.jsonl` and load as one dataset; an empty directory raises an actionable error. 3. Named preset from `DATASET_CONFIGS` (existing). 4. `hf:<id>[:<subset>:<split>]` for an arbitrary HF dataset. - New `_load_hf_dataset` helper parses the `hf:` spec (split defaults to `train`; `hf:<id>:<split>` selects a split without a subset). It raises if the loaded dataset has no `conversations` column, since `_preprocess_batch` otherwise only warns and silently yields zero samples — preventing silent data loss as required by the RFC. - Add `magpie` (conversations already in ShareGPT format, no normalize_fn) and `nemotron` (`nvidia/Llama-Nemotron-Post-Training-Dataset` SFT/chat, with `_normalize_nemotron` building conversations from input + output) presets. - Tests: local file, recursive directory bundle, empty-directory error, preset dispatch, unsupported source, `hf:` spec parsing, the conversations-format guard, malformed specs, and the new presets. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015hZBWmU32ZGrifozzK4DqQ Signed-off-by: Karthik Kothuri <karthikkothuri2009@gmail.com>
📝 WalkthroughWalkthroughAdds ChangesFlexible dataset source discovery
Possibly related issues
Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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 `@src/speculators/data_generation/preprocessing.py`:
- Around line 671-687: Reject empty hf: suffixes in the preprocessing parser
before load_dataset is called. In preprocessing.py, update the hf: parsing logic
around the spec.removeprefix("hf:").split(":") match in the helper that assigns
hf_id, subset, and split so that trailing-colon forms like hf:org/name: and
hf:org/name:subset: raise the local ValueError instead of falling through with
an empty split. Add validation for empty subset/split segments in this branch
and cover it with a regression test for the trailing-colon cases.
🪄 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: Pro
Run ID: 3da890cb-b47a-4f1f-9148-75e1484e4c32
📒 Files selected for processing (3)
src/speculators/data_generation/configs.pysrc/speculators/data_generation/preprocessing.pytests/integration/datagen/test_preprocessing.py
Trailing-colon forms (`hf:org/name:`, `hf:org/name:subset:`) and an empty subset (`hf:org/name::split`) previously parsed with an empty segment and fell through to load_dataset instead of raising locally. Validate empty subset/split here and cover the cases with regression tests. Also add a docstring to _normalize_nemotron and the test helpers. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015hZBWmU32ZGrifozzK4DqQ Signed-off-by: Karthik Kothuri <karthikkothuri2009@gmail.com>
The RFC asks for an integration test against a small public HF dataset. The other hf: tests mock load_dataset; this one exercises the real Hub download end to end using philschmid/guanaco-sharegpt-style (~9k rows, conversations format), asserting the dataset loads with no normalize_fn. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015hZBWmU32ZGrifozzK4DqQ Signed-off-by: Karthik Kothuri <karthikkothuri2009@gmail.com>
|
This pull request has merge conflicts that must be resolved before it can be |
Signed-off-by: Karthik Kothuri <karthikkothuri2009@gmail.com> # Conflicts: # tests/integration/datagen/test_preprocessing.py
|
@KKothuri @shanjiaz The local-directory path loads every discovered file in a single pass: load_dataset("json", data_files=[all .json/.jsonl], split="train") Loading each file/source separately and then concatenate_datasets on the common columns (dropping non-shared ones with a warning, and raising if no shared data column remains) handles heterogeneous bundles cleanly, and extends to parquet by grouping on schema. For homogeneous bundles it's identical to the current single-pass. I have this implemented and tested (directory-bundle slice of RFC #583). Happy to (a) push it as a follow-up on top of this PR, or (b) hand you the diff to fold in — your and @shanjiaz's call. The hf: handling and presets here are great as-is. |
The CI runners use a pre-baked HF cache (HF_HOME=/model-cache) and are network-restricted, so downloading philschmid/guanaco-sharegpt-style (not in that cache) failed the buildkite build. Skip the test on any fetch failure instead of failing; the hf: parsing and conversations guard remain covered deterministically by the mocked tests. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015hZBWmU32ZGrifozzK4DqQ Signed-off-by: Karthik Kothuri <karthikkothuri2009@gmail.com>
Head branch was pushed to by a user without write access
) (vllm-project#675) Resolves vllm-project#661. ## Summary Extends `load_raw_dataset()` in `src/speculators/data_generation/preprocessing.py` from two source types to the four-step resolution chain requested in RFC vllm-project#661, and promotes Magpie/Nemotron to shared presets. Scope is intentionally limited to **data source discovery** — schema/role normalization is left to a separate effort. ## Changes - `load_raw_dataset` now resolves a source in order: 1. Local `.json`/`.jsonl` file (existing). 2. **Local directory** — recursively glob `*.json`/`*.jsonl` (sorted for determinism) and load as one dataset; an empty directory raises an actionable error. 3. Named preset from `DATASET_CONFIGS` (existing). 4. **`hf:<id>[:<subset>:<split>]`** — load an arbitrary HuggingFace dataset. - New `_load_hf_dataset` helper parses the `hf:` spec (split defaults to `train`). It **raises if the loaded dataset has no `conversations` column**, since `_preprocess_batch` otherwise only warns and silently yields zero samples — satisfying the RFC's "no silent data corruption" requirement. - Adds `magpie` (already in ShareGPT `conversations` format, no `normalize_fn`) and `nemotron` (`nvidia/Llama-Nemotron-Post-Training-Dataset`, `SFT`/`chat`, with `_normalize_nemotron` building conversations from `input` + `output`) presets. Both schemas were verified against the live HF datasets-server before hardcoding. All source types compose across mixed `--data` usage, e.g.: ``` --data sharegpt --data /my/shards/ --data hf:nvidia/HelpSteer2 --data extra.jsonl ``` ### Note for the maintainer Beyond the RFC's literal `hf:<id>:<subset>:<split>`, I also accept the 2-part form `hf:<id>:<split>` (subset omitted), since single-config datasets with a non-`train` split (e.g. `HuggingFaceH4/ultrachat_200k:train_sft`) are common. Happy to make it strict if you'd prefer. ## Why this is not a duplicate vllm-project#637 (RFC vllm-project#583) touches the same function but bundles directory/HF discovery **together with** role/schema normalization. Per @shanjiaz's scoping on vllm-project#583 and the assignment of vllm-project#661, this PR delivers the **discovery slice only**, keeping it separate from normalization. The `hf:` handling here is also a different, more explicit design: an explicit `hf:` prefix (rather than treating any unmatched string as an HF path) plus a hard failure on non-conversations data. ## Tests New tests in `tests/integration/datagen/test_preprocessing.py`: local file, recursive directory bundle (incl. nested `.json`), empty-directory error, preset dispatch, unsupported source, `hf:` spec parsing (parametrized), the conversations-format guard, malformed `hf:` specs, and the new presets. The `hf:`/preset cases mock `load_dataset` so they are deterministic and network-free. Commands run (in the project venv): ``` python -m pytest tests/integration/datagen/test_preprocessing.py -q # 51 passed, 2 skipped ruff check src/speculators/data_generation/{preprocessing,configs}.py tests/integration/datagen/test_preprocessing.py # All checks passed ruff format --check <same files> # already formatted python -m mypy src/speculators/data_generation/{preprocessing,configs}.py # Success: no issues ``` ## AI assistance disclosure AI assistance (Claude Code) was used to help write this change. I (the submitter) have reviewed every changed line, understand the change end-to-end, and ran the tests above. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Signed-off-by: Karthik Kothuri <karthikkothuri2009@gmail.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
) (vllm-project#675) Resolves vllm-project#661. ## Summary Extends `load_raw_dataset()` in `src/speculators/data_generation/preprocessing.py` from two source types to the four-step resolution chain requested in RFC vllm-project#661, and promotes Magpie/Nemotron to shared presets. Scope is intentionally limited to **data source discovery** — schema/role normalization is left to a separate effort. ## Changes - `load_raw_dataset` now resolves a source in order: 1. Local `.json`/`.jsonl` file (existing). 2. **Local directory** — recursively glob `*.json`/`*.jsonl` (sorted for determinism) and load as one dataset; an empty directory raises an actionable error. 3. Named preset from `DATASET_CONFIGS` (existing). 4. **`hf:<id>[:<subset>:<split>]`** — load an arbitrary HuggingFace dataset. - New `_load_hf_dataset` helper parses the `hf:` spec (split defaults to `train`). It **raises if the loaded dataset has no `conversations` column**, since `_preprocess_batch` otherwise only warns and silently yields zero samples — satisfying the RFC's "no silent data corruption" requirement. - Adds `magpie` (already in ShareGPT `conversations` format, no `normalize_fn`) and `nemotron` (`nvidia/Llama-Nemotron-Post-Training-Dataset`, `SFT`/`chat`, with `_normalize_nemotron` building conversations from `input` + `output`) presets. Both schemas were verified against the live HF datasets-server before hardcoding. All source types compose across mixed `--data` usage, e.g.: ``` --data sharegpt --data /my/shards/ --data hf:nvidia/HelpSteer2 --data extra.jsonl ``` ### Note for the maintainer Beyond the RFC's literal `hf:<id>:<subset>:<split>`, I also accept the 2-part form `hf:<id>:<split>` (subset omitted), since single-config datasets with a non-`train` split (e.g. `HuggingFaceH4/ultrachat_200k:train_sft`) are common. Happy to make it strict if you'd prefer. ## Why this is not a duplicate vllm-project#637 (RFC vllm-project#583) touches the same function but bundles directory/HF discovery **together with** role/schema normalization. Per @shanjiaz's scoping on vllm-project#583 and the assignment of vllm-project#661, this PR delivers the **discovery slice only**, keeping it separate from normalization. The `hf:` handling here is also a different, more explicit design: an explicit `hf:` prefix (rather than treating any unmatched string as an HF path) plus a hard failure on non-conversations data. ## Tests New tests in `tests/integration/datagen/test_preprocessing.py`: local file, recursive directory bundle (incl. nested `.json`), empty-directory error, preset dispatch, unsupported source, `hf:` spec parsing (parametrized), the conversations-format guard, malformed `hf:` specs, and the new presets. The `hf:`/preset cases mock `load_dataset` so they are deterministic and network-free. Commands run (in the project venv): ``` python -m pytest tests/integration/datagen/test_preprocessing.py -q # 51 passed, 2 skipped ruff check src/speculators/data_generation/{preprocessing,configs}.py tests/integration/datagen/test_preprocessing.py # All checks passed ruff format --check <same files> # already formatted python -m mypy src/speculators/data_generation/{preprocessing,configs}.py # Success: no issues ``` ## AI assistance disclosure AI assistance (Claude Code) was used to help write this change. I (the submitter) have reviewed every changed line, understand the change end-to-end, and ran the tests above. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Signed-off-by: Karthik Kothuri <karthikkothuri2009@gmail.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> Signed-off-by: Eros483 <arnabmandal2912@gmail.com>
Resolves #661.
Summary
Extends
load_raw_dataset()insrc/speculators/data_generation/preprocessing.pyfrom two source types to the four-step resolution chain requested in RFC #661, and promotes Magpie/Nemotron to shared presets. Scope is intentionally limited to data source discovery — schema/role normalization is left to a separate effort.Changes
load_raw_datasetnow resolves a source in order:.json/.jsonlfile (existing).*.json/*.jsonl(sorted for determinism) and load as one dataset; an empty directory raises an actionable error.DATASET_CONFIGS(existing).hf:<id>[:<subset>:<split>]— load an arbitrary HuggingFace dataset._load_hf_datasethelper parses thehf:spec (split defaults totrain). It raises if the loaded dataset has noconversationscolumn, since_preprocess_batchotherwise only warns and silently yields zero samples — satisfying the RFC's "no silent data corruption" requirement.magpie(already in ShareGPTconversationsformat, nonormalize_fn) andnemotron(nvidia/Llama-Nemotron-Post-Training-Dataset,SFT/chat, with_normalize_nemotronbuilding conversations frominput+output) presets. Both schemas were verified against the live HF datasets-server before hardcoding.All source types compose across mixed
--datausage, e.g.:Note for the maintainer
Beyond the RFC's literal
hf:<id>:<subset>:<split>, I also accept the 2-part formhf:<id>:<split>(subset omitted), since single-config datasets with a non-trainsplit (e.g.HuggingFaceH4/ultrachat_200k:train_sft) are common. Happy to make it strict if you'd prefer.Why this is not a duplicate
#637 (RFC #583) touches the same function but bundles directory/HF discovery together with role/schema normalization. Per @shanjiaz's scoping on #583 and the assignment of #661, this PR delivers the discovery slice only, keeping it separate from normalization. The
hf:handling here is also a different, more explicit design: an explicithf:prefix (rather than treating any unmatched string as an HF path) plus a hard failure on non-conversations data.Tests
New tests in
tests/integration/datagen/test_preprocessing.py: local file, recursive directory bundle (incl. nested.json), empty-directory error, preset dispatch, unsupported source,hf:spec parsing (parametrized), the conversations-format guard, malformedhf:specs, and the new presets. Thehf:/preset cases mockload_datasetso they are deterministic and network-free.Commands run (in the project venv):
AI assistance disclosure
AI assistance (Claude Code) was used to help write this change. I (the submitter) have reviewed every changed line, understand the change end-to-end, and ran the tests above.
🤖 Generated with Claude Code