Skip to content

Expose translation control knobs - #2038

Merged
sarahyurick merged 4 commits into
NVIDIA-NeMo:mainfrom
rkalaniNV:rkalani/translation-control-knobs
Jun 3, 2026
Merged

sarahyurick merged 4 commits into
NVIDIA-NeMo:mainfrom
rkalaniNV:rkalani/translation-control-knobs

Conversation

@rkalaniNV

Copy link
Copy Markdown
Contributor

Description

Exposes knobs to customize the translation workflow for downstream repos.

Checklist

  • I am familiar with the Contributing Guide.
  • New or Existing tests cover these changes.
  • The documentation is up to date with these changes.

Signed-off-by: rkalani <rkalani@nvidia.com>
@rkalaniNV
rkalaniNV requested a review from a team as a code owner May 29, 2026 11:26
@rkalaniNV
rkalaniNV requested review from weijiac0619 and removed request for a team May 29, 2026 11:26
@copy-pr-bot

copy-pr-bot Bot commented May 29, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@rkalaniNV

Copy link
Copy Markdown
Contributor Author

/ok to test c03e067

@greptile-apps

greptile-apps Bot commented May 29, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR exposes translation control knobs — prompt_path, max_concurrent_requests, health_check, dry_run/dry_run_log_count for translation and the matching faith_* counterparts for FAITH evaluation — on both individual stages and the top-level TranslationStage. It also tightens empty-batch handling in SegmentationStage, ReassemblyStage, and RestoreSkippedRowsStage, fixing a crash path when all rows are already translated.

  • load_prompt_template now accepts an absolute path in addition to a packaged filename, enabling callers to supply fully custom YAML prompts without modifying packaged files.
  • ReassemblyStage's empty-batch fast-path now applies a _OUTPUT_COLUMN_DTYPES map so numeric and boolean output columns carry the correct pandas dtype rather than defaulting to object.
  • RestoreSkippedRowsStage short-circuits to skipped_df.reset_index(drop=True) when the processed DataFrame is empty, avoiding a pd.concat that could silently discard the skipped-row data.

Confidence Score: 5/5

Safe to merge — the changes are additive control-knob exposure with no modifications to existing defaults or core translation logic.

All new fields default to the same values previously hard-coded, so existing callers are unaffected. The empty-batch fast-paths in SegmentationStage, ReassemblyStage, and RestoreSkippedRowsStage are well-guarded and covered by a new end-to-end test. FaithEvalFilter and FaithThresholdFilterStage already had their own empty-batch guards prior to this PR, so the full pipeline is consistent. No logic paths are altered for non-empty batches.

No files require special attention.

Important Files Changed

Filename Overview
nemo_curator/stages/text/experimental/translation/utils/prompt_loader.py Refactored to accept absolute paths or packaged filenames; logic is clean and well-guarded with proper error messages.
nemo_curator/stages/text/experimental/translation/pipeline.py New control knobs correctly wired from TranslationStage down to SegmentTranslationStage and FaithEvalFilter; validation logic unchanged.
nemo_curator/stages/text/experimental/translation/stages/translate.py prompt_path, health_check, dry_run fields added; setup() correctly resolves the prompt; empty-batch path works naturally with 0-length segment list.
nemo_curator/stages/text/experimental/translation/evaluation/faith.py prompt_path field added with same resolution pattern as translate.py; FaithEvalFilter.process() already had an empty-batch guard (pre-existing).
nemo_curator/stages/text/experimental/translation/stages/reassembly.py Empty-batch fast-path added with _OUTPUT_COLUMN_DTYPES map; properly types float and bool output columns rather than defaulting to object.
nemo_curator/stages/text/experimental/translation/stages/skipped_rows.py Added warning for all-rows-skipped case; RestoreSkippedRowsStage now avoids pd.concat when the processed df is empty, correctly preserving skipped-row data.
tests/stages/text/experimental/translation/test_pipeline.py New tests cover custom prompt/generation/concurrency knob propagation, the all-rows-skipped path, and FaithEvalFilter custom prompt loading end-to-end.
tests/stages/text/experimental/translation/test_prompts.py Two new tests verify absolute-path loading and missing-key rejection in load_prompt_template.
tests/stages/text/experimental/translation/test_translate.py Adds custom prompt path test for SegmentTranslationStage and strengthens the existing mock assertion from assert_called_once() to assert_called_once_with('translate.yaml').

Sequence Diagram

sequenceDiagram
    participant C as Caller
    participant TS as TranslationStage
    participant Skip as SkipExistingTranslationsStage
    participant Seg as SegmentationStage
    participant Tr as SegmentTranslationStage
    participant FE as FaithEvalFilter
    participant Re as ReassemblyStage
    participant Res as RestoreSkippedRowsStage

    C->>TS: process(batch)
    TS->>Skip: process(batch) [if skip_translated]
    Note over Skip: Stash already-translated rows in metadata, warn if all rows skipped
    Skip-->>TS: remaining_df (may be empty)

    TS->>Seg: process(batch)
    Note over Seg: Empty-batch guard returns typed _seg_* columns
    Seg-->>TS: segmented rows (or empty)

    TS->>Tr: process(batch)
    Note over Tr: New knobs: prompt_path, health_check, dry_run, max_concurrent_requests
    Tr-->>TS: translated segments (or empty)

    TS->>FE: process(batch) [if enable_faith_eval]
    Note over FE: New knobs: faith_prompt_path, faith_generation_config, faith_max_concurrent_requests
    FE-->>TS: scored segments (or empty)

    TS->>Re: process(batch)
    Note over Re: Empty-batch guard applies _OUTPUT_COLUMN_DTYPES for float64/bool columns
    Re-->>TS: reassembled docs (or typed empty df)

    TS->>Res: process(batch) [if skip_translated]
    Note over Res: df.empty uses skipped_df.reset_index() instead of pd.concat
    Res-->>TS: merged result

    TS-->>C: DocumentBatch
Loading

Reviews (3): Last reviewed commit: "Merge branch 'main' into rkalani/transla..." | Re-trigger Greptile

Comment thread nemo_curator/stages/text/experimental/translation/stages/reassembly.py Outdated
Comment on lines +106 to +107
prompt_file = self.prompt_path or "translate.yaml"
self._system_prompt, self._user_template = load_prompt_template(prompt_file)

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.

P2 prompt_path = "" silently falls back to the default

self.prompt_path or "translate.yaml" treats an empty string as falsy, so a caller who accidentally passes prompt_path="" gets the packaged prompt with no warning. The type annotation (str | None) implies the only "no-op" value is None, so the guard should be explicit. The same pattern appears in FaithEvalFilter.setup() at the corresponding line.

@sarahyurick sarahyurick 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.

LGTM!

"""
if not self._initialized:
self._system_prompt, self._user_template = load_prompt_template("faith_eval.yaml")
prompt_file = self.prompt_path or "faith_eval.yaml"

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.

what if prompt_path=""

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.

Empty string will go to "faith_eval.yaml".

logger.info("ReassemblyStage: no translated segment rows to reassemble")
base_cols = [col for col in df.columns if col not in _INTERNAL_COLUMNS]
out_df = df.loc[:, base_cols].copy()
for col in self.outputs()[1]:

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.

is it a bit fragile that it requires outputs() returning a tuple where index [1] contains the output column names

@sarahyurick sarahyurick Jun 3, 2026 •

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.

Agree it looks a bit fragile but it follows the convention that should be used by text stages with DocumentBatch everywhere.

@sarahyurick

Copy link
Copy Markdown
Contributor

/ok to test 4fb2a98

This branch was previously deployed

3 inactive deployments
nemo-ci — 4fb2a98a Deployed Jun 3, 2026 by copy-pr-bot[bot] via L0_Unit_Test_GPU-video #4577
public — 4fb2a98a Deployed Jun 3, 2026 by copy-pr-bot[bot] via release / finalize / notify #207
test — 4fb2a98a Deployed Jun 3, 2026 by copy-pr-bot[bot] via cicd-wait-in-queue #4577
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants