Add ray data for audio modality - #1592
Conversation
|
/ok to test a90a3af |
Signed-off-by: Onur Yilmaz <oyilmaz@nvidia.com>
|
/ok to test 235ef99 |
praateekmahajan
left a comment
There was a problem hiding this comment.
Thanks @oyilmaz-nvidia
In the PR description can you explain the intent to change the stages to actors, and similarly which ones you converted to fanout and why, vs which ones you didn't and why?
| script: alm_pipeline_benchmark.py | ||
| args: >- | ||
| --benchmark-results-path={session_entry_dir} | ||
| --input-manifest={curator_repo_dir}/tests/fixtures/audio/alm/sample_input.jsonl |
There was a problem hiding this comment.
To run alm benchmark on large scale real world data, below are the following steps:
- Get data here. Size is 1.17 GB.
- Update --input-manifest= param with path of said download.
- set --repeat-factor=1 in this command.
- set timeout_s: 6000 or max permissible.
Same instructions for both xenna and ray.
Based on completed time for repeat-factor=1; consider increasing repeat factor to any number between 2-10.
| --scratch-output-path={session_entry_dir}/scratch | ||
| --model-name=nvidia/stt_hy_fastconformer_hybrid_large_pc | ||
| --lang=hy_am | ||
| --split=dev |
There was a problem hiding this comment.
For large scale benchmarks, here set --split=train. You should run on ~9x more data.
Signed-off-by: Onur Yilmaz <oyilmaz@nvidia.com>
|
/ok to test da6bf1e |
…est.py Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> Signed-off-by: Onur Yilmaz <35306097+oyilmaz-nvidia@users.noreply.github.com>
| def ray_stage_spec(self) -> dict[str, Any]: | ||
| from nemo_curator.backends.experimental.utils import RayStageSpecKeys | ||
|
|
||
| return {RayStageSpecKeys.IS_FANOUT_STAGE: True} | ||
| from nemo_curator.stages.audio.datasets.file_utils import download_file, extract_archive |
There was a problem hiding this comment.
Syntax error: method definition floating between module-level imports
Lines 19–22 contain an indented def ray_stage_spec(self) body placed directly between top-level import statements. Python will raise an IndentationError the moment this module is collected, making the entire module unimportable. This is the complete implementation of the method (including the deferred RayStageSpecKeys import) that should have been placed inside the class body — it was apparently mis-applied here by mistake.
These four lines must be removed from the module scope entirely. The correct implementation already exists at line 146, but it is incomplete (see the companion comment below).
| def ray_stage_spec(self) -> dict[str, Any]: | |
| from nemo_curator.backends.experimental.utils import RayStageSpecKeys | |
| return {RayStageSpecKeys.IS_FANOUT_STAGE: True} | |
| from nemo_curator.stages.audio.datasets.file_utils import download_file, extract_archive | |
| from nemo_curator.stages.audio.datasets.file_utils import download_file, extract_archive |
Signed-off-by: Onur Yilmaz <oyilmaz@nvidia.com>
|
/ok to test 3b4cb6c |
| - name: audio_fleurs_raydata | ||
| enabled: true | ||
| script: audio_fleurs_benchmark.py | ||
| args: >- | ||
| --benchmark-results-path={session_entry_dir} | ||
| --scratch-output-path={session_entry_dir}/scratch | ||
| --model-name=nvidia/stt_hy_fastconformer_hybrid_large_pc | ||
| --lang=hy_am | ||
| --split=train | ||
| --wer-threshold=5.5 | ||
| --gpus=1 | ||
| --executor=ray_data | ||
| ray: | ||
| num_cpus: 64 | ||
| num_gpus: 4 | ||
| enable_object_spilling: false | ||
| sink_data: | ||
| - name: slack | ||
| ping_on_failure: | ||
| - U03C41SNADV # Aaftab V |
There was a problem hiding this comment.
No timeout_s for train-split benchmarks
Both audio_fleurs_raydata (new) and audio_fleurs_xenna (changed from dev → train) now process the full Armenian FLEURS training split, which is considerably larger than dev. Without a timeout_s, a slow download, a hung Ray worker, or unexpectedly slow ASR inference could cause these entries to block the entire nightly run indefinitely.
The alm_pipeline_ray_data entry added in this same PR does include timeout_s: 600 for reference. Consider adding a generous but bounded timeout to both audio-fleurs entries, e.g.:
- name: audio_fleurs_raydata
enabled: true
timeout_s: 7200 # 2 h ceiling for train-split download + inference
script: audio_fleurs_benchmark.py
...and similarly for audio_fleurs_xenna.
|
Looks Good to me. |
praateekmahajan
left a comment
There was a problem hiding this comment.
PR LGTM. I do think we should run with a larger dataset than this since a 2-3 minute tests won't tell us much about the autoscaling behaviors of the frameworks or help us catch regressions
|
/ok to test bd25cbc |
| from dataclasses import dataclass | ||
| from typing import Any | ||
|
|
||
| from nemo_curator.backends.experimental.utils import RayStageSpecKeys |
There was a problem hiding this comment.
Module-level Ray import still present
RayStageSpecKeys is imported at module level (line 19), and nemo_curator/backends/experimental/utils.py has import ray at its top level (line 19 of that file). This means every import of CreateInitialManifestFleursStage now transitively requires Ray to be installed — even in Xenna-only environments.
Concretely, test_get_fleurs_url_list_builds_urls and test_process_transcript_parses_tsv both call _import_stage_module(), which now pulls in ray and will raise an ImportError in environments without Ray installed. Since ray_stage_spec() is only ever called by the Ray Data backend, the import should be deferred to inside that method:
def ray_stage_spec(self) -> dict[str, Any]:
from nemo_curator.backends.experimental.utils import RayStageSpecKeys
return {RayStageSpecKeys.IS_FANOUT_STAGE: True}Then remove the module-level from nemo_curator.backends.experimental.utils import RayStageSpecKeys on line 19.
| - name: audio_fleurs_raydata | ||
| enabled: true | ||
| script: audio_fleurs_benchmark.py | ||
| args: >- | ||
| --benchmark-results-path={session_entry_dir} | ||
| --scratch-output-path={session_entry_dir}/scratch | ||
| --model-name=nvidia/stt_hy_fastconformer_hybrid_large_pc | ||
| --lang=hy_am | ||
| --split=train | ||
| --wer-threshold=5.5 | ||
| --gpus=1 | ||
| --executor=ray_data | ||
| ray: | ||
| num_cpus: 64 | ||
| num_gpus: 4 | ||
| enable_object_spilling: false | ||
| sink_data: | ||
| - name: slack | ||
| ping_on_failure: | ||
| - U03C41SNADV # Aaftab V |
There was a problem hiding this comment.
Missing requirements for audio_fleurs_raydata and audio_fleurs_xenna
Neither audio_fleurs_raydata nor audio_fleurs_xenna (both processing the full train split now) define a requirements block, while the other new entry in this PR — alm_pipeline_ray_data — does:
requirements:
- metric: is_success
exact_value: true
- metric: total_builder_windows
min_value: 1
- metric: total_filtered_windows
min_value: 1Without requirements, the nightly framework cannot distinguish between a run that crashes (and writes is_success: false) and a run that silently produces zero output records (all audio filtered by WER threshold). The benchmarking framework will mark these entries as "passed" as long as the script exits without an unhandled exception.
Consider adding at minimum an is_success requirement for both entries, and ideally a min_value guard on a count metric (e.g., number of audio samples that passed the WER filter) to catch regressions in result quality.
Description
This PR adds a few changes to test and benchmark Ray Data for audio workflows.
Fanouts
FLEURS is the only audio dataset with an initial manifest creation stage in this PR. The fanout is needed because CreateInitialManifestFleursStage takes a single input task and produces many AudioBatch tasks (one per transcript line). The other audio stages added in this PR (GetAudioDurationStage, ALMManifestWriterStage, InferenceAsrNemoStage) are 1-to-1 transforms, so they don't need fanout.
ALMManifestReaderStage also has IS_FANOUT_STAGE: True (it reads a JSONL and fans out one task per entry), but that's a pre-existing stage that just got ray_stage_spec() added.
Should You Add More Fanouts?
Not right now — the fanout is tied to a specific behavioral pattern (one-input → many-outputs), not to the audio modality itself. You'd only add fanouts for new audio stages that:
Checklist