Use this skill to port a NeMo training config from streaming/replay-style Lhotse
loading to indexed access plus torchdata.StatefulDataLoader checkpoint/restore.
The migration is fragile because YAML flags, launcher seed policy, index paths,
storage backend, and resume topology all interact.
Core concepts
- Indexed sources need
.idxsidecars for random access into JSONL, tar, and supported Shar-style data. Build these once per blend/source set. - For datasets with very many shards, an optional dataset-level
.idxpackcombines existing sidecars into one memory-mapped catalog. Prefer one pack per independently configured outerinput_cfg; do not create one global pack for an entire mixture. use_stateful_dataloader: truelets Lightning checkpoint the dataloader iterator state, but only if seeds, worker counts, and distributed topology are stable across chunks.- Training configs must use
force_map_dataset: falseso indexed sources partition across data-parallel ranks and workers without map-style sampler overhead. Treatforce_map_dataset: truefor training as not launch-ready unless the user explicitly approves a temporary exception; every source in the training iteration graph must be indexed and partition-compatible before launch. - Remote audio on AIStore/S3 generally needs
USE_AIS_GET_BATCH=trueso audio fetches are deferred to sample time instead of constructing eager tar readers for every shard.
Inputs
| input | required | source | purpose |
|---|---|---|---|
| Training YAML | yes | argument or --config= |
Inspect data.train_ds, data.validation_ds, trainer, exp_manager, and any model fields that affect resume. |
| Launcher script | no | argument or auto-detect from project conventions | Check per-chunk seed policy, resume topology invariance, Python path setup, AIStore env vars, and optional index staging. |
| Data-blend YAML | no | resolved from data.train_ds.input_cfg when possible |
Check indexability: compressed paths, non-seekable paths, unsupported extra_fields, slice_length, and mixed indexed/non-indexed chains. |
| Runtime context | no | argument, config file, or user-provided notes | Detect storage backend, AIStore endpoint availability, container constraints, and index mirror destination. |
Outputs
Every output lands in migrate-resumable/<config-stem>/ in the current repo:
| output | purpose |
|---|---|
migration-report.md |
Findings, rationale, patched fields, and unresolved blockers. |
<config-stem>-resumable.yaml |
Patched training config when safe automatic edits are possible. |
<blend-stem>-resumable.yaml |
Patched blend, only when a blend was inspected and safe changes are possible. |
pre-flight-checklist.md |
User-run steps before submitting training. |
build-indexes-cmd.sh |
One-shot sidecar-build command and, when packs are selected, one conversion command per outer dataset. Use a project wrapper when available, otherwise the generic NeMo scripts. |
Workflow
1. Discover and parse inputs
- Resolve the training YAML path and read it with OmegaConf or a comment-preserving YAML parser.
- Resolve any referenced blend YAMLs from
data.*.input_cfg. Prefer project conventions when obvious, but fall back to paths relative to the config. - If a launcher path is supplied, read it. Otherwise inspect likely project
launchers (
train.py,pretrain.py, shell wrappers, or rawtorchrun/pythoncommands) and pick the closest match. - If runtime context is supplied, read it for container image, environment variables, filesystem mounts, worker counts, and AIStore endpoint settings.
- Detect remote storage from source paths (
s3://,ais://,http(s)://) and local filesystem storage from ordinary absolute or relative paths.
2. Run lint pipeline
Run every relevant check in:
references/option-reference.mdreferences/conflict-matrix.mdreferences/failure-modes.mdreferences/aistore-vs-non-aistore.mdwhen remote storage is present
Each finding should include severity, field/path, current value, recommended value, and a short rationale.
Severities:
- fatal: automatic patching is not possible; user must preprocess data or change the source layout.
- error: automatic patching is safe and should be applied.
- warning: context-dependent; emit a report item and optional YAML comment.
- note: informational; no patch.
3. Emit patched YAML and blend
Apply safe error-severity patches. Preserve comments when possible with
ruamel.yaml; otherwise serialize with OmegaConf/YAML and rely on the report for
rationale. For blend edits, never silently drop data: leave an explicit report
entry and comment for every excluded or rewritten source.
4. Generate migration-report.md
Use templates/migration-report.md. Include:
- Summary of storage workflow, counts by severity, and readiness.
- Inputs inspected.
- Findings table.
- Walkthrough for train data, validation data, trainer/exp manager, launcher, and storage backend.
- Data-blend audit.
- Verification and pre-flight steps.
5. Generate pre-flight-checklist.md
Use templates/pre-flight-checklist.md when present. Required steps:
- Build
.idxsidecars for every training/validation/test blend involved. - When startup would open many loose sidecars, build and validate one
.idxpackper supported outer dataset after the sidecars exist. Record the owninginput_cfgentry and output filename explicitly. - Verify
indexes_rootpoints at the same stable mirror used by the runtime, or that explicit node-local index staging populates it before training starts. - If AIStore is in play: verify
aistoreSDK availability,AIS_ENDPOINT, and whetherUSE_AIS_GET_BATCHorUSE_AIS_INDIVIDUAL_GETSis required. - Verify one invariant seed across resumable chunks.
- Verify
num_workers,world_size, and relevant distributed topology do not change across resume boundaries. - Recommend a small smoke ladder: single-node single chunk, single-node resume, then full topology.
6. Generate build-indexes-cmd.sh
Prefer a project-provided wrapper when one is clearly present. Otherwise emit a generic command using:
python <NeMo>/scripts/dataloading/build_indexes.py \
--indexes-root <shared-index-mirror> \
--workers <N> \
<blend>.yaml [<validation-blend>.yaml ...]
When an outer dataset is supported and has enough shards to benefit from one
memory map, append a command for that dataset (repeat for every independently
configured outer input_cfg):
python <NeMo>/scripts/dataloading/convert_indexes_to_idxpack.py \
--indexes-root <shared-index-mirror> \
--output <index-pack-root>/<dataset-name>.idxpack \
<dataset-input-cfg>.yaml
Patch the owning outer entry with index_pack: <dataset-name>.idxpack and set
index_pack_root at the dataloader level. Never infer a pack by filename: an
explicit declaration is part of the runtime validation contract. If the
converter rejects a type, keep that adapter on loose sidecars and report it.
If running through a managed runtime or container wrapper, include comments for required container image, mounts, environment variables, worker count, and any CPU/GPU container-hook workaround the project requires.
7. Print final summary to chat
Keep the final chat response under 10 lines: output directory, finding counts, report path, and the next command the user should run.
Knowledge base
references/option-reference.md: field-by-field reference for YAML and launcher settings.references/failure-modes.md: known failure signatures, triggers, and fixes.references/conflict-matrix.md: incompatible option pairs.references/best-practices.md: priority-ordered checklist.references/aistore-vs-non-aistore.md: storage workflow selection.templates/migration-report.md: report template.templates/pre-flight-checklist.md: checklist template, when present.scripts/analyze.py: optional static-analysis helper, when present.
Constraints
- Prefer static analysis. Do not launch training, build indexes, prefetch data, or modify external runtime state unless the user explicitly asks.
- Cross-check recommendations against the actual NeMo/Lhotse code in the user's
checkout when paths are available. Relevant areas are common Lhotse dataloader
config, indexed adapters,
lhotse.indexing, AIStore batch loading, and NeMo dataloader construction. - Treat project wrappers as optional conveniences, not as part of the generic migration contract.
- When evidence is missing, say so. Do not encode project-specific run history or local experiment names as general guidance.