Skip to content

feat(exporters): keep a resumed or resubmitted run in one MLflow run - #4762

Merged
AdamRajfer merged 2 commits into
NVIDIA-NeMo:mainfrom
AdamRajfer:feat/mlflow-one-run-per-evaluation
Oct 20, 2026
Merged

AdamRajfer merged 2 commits into
NVIDIA-NeMo:mainfrom
AdamRajfer:feat/mlflow-one-run-per-evaluation

Conversation

@AdamRajfer

Copy link
Copy Markdown
Contributor

Every job of an evaluation created its own MLflow run, so a run that auto-resumed or was resubmitted was split across MLflow runs with the same name, each with its own metrics.

Changes:

  • The MLflow exporter writes the run id to <output stem>_mlflow_run_id next to output_jsonl_fpath, and reopens that run when the same output starts again.
  • Deleting the file starts a new MLflow run.
  • The configuration docs describe the file.

Tested with a new unit test in tests/unit_tests/test_exporters.py: a second exporter on the same output reopens the recorded run instead of creating a new one.

🤖 Generated with Claude Code

Every job of an evaluation created its own MLflow run, so a run that
auto-resumed or was resubmitted was split across MLflow runs with the
same name, each with its own metrics. The exporter now writes the run
id to <output stem>_mlflow_run_id next to output_jsonl_fpath and
reopens that run when the same output starts again. Deleting the file
starts a new MLflow run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Adam Rajfer <arajfer@nvidia.com>
@AdamRajfer AdamRajfer self-assigned this Oct 19, 2026
@nemo-automation-bot
nemo-automation-bot Bot requested review from a team October 19, 2026 20:50
@github-actions

github-actions Bot commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

@yaoyu-33 yaoyu-33 added area:evaluation Evaluation, rollout collection, reward profiling, comparison, and exporters complexity:low Localized change in one scope with a small, straightforward review surface feature New capabilities, enhancements, or enablement work needs-review PR is ready for code review and waiting on a reviewer labels Oct 19, 2026
Comment thread nemo_gym/exporters/mlflow.py Resolved
…kend

The run id file moves from the MLflow exporter into BaseExporter, so every
backend keeps a resumed or resubmitted run in one run the same way: the id
is written to <output stem>_<backend>_run_id next to output_jsonl_fpath.
The MLflow file name and behaviour are unchanged. The W&B exporter now
records its run id too and resumes that run when the same output starts
again. Deleting the file starts a new run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Adam Rajfer <arajfer@nvidia.com>
@AdamRajfer

Copy link
Copy Markdown
Contributor Author

/ok to test 95d75cc

@AdamRajfer
AdamRajfer added this pull request to the merge queue Oct 20, 2026
@github-actions

Copy link
Copy Markdown
Contributor

🔄 Merge queue validation started! You can track the progress here: https://github.com/NVIDIA-NeMo/Gym/actions/runs/39416802760

Merged via the queue into NVIDIA-NeMo:main with commit 66eec25 Oct 20, 2026
48 of 53 checks passed
@AdamRajfer
AdamRajfer deleted the feat/mlflow-one-run-per-evaluation branch October 20, 2026 11:59
jin-nvidia pushed a commit to cparisien/Gym that referenced this pull request Oct 27, 2026
…nded rollout once (NVIDIA-NeMo#5029)

* fix(exporters): reopen a tracking run only when the run resumes, and log each rollout once

NVIDIA-NeMo#4762 reopens the MLflow or W&B run recorded next to an output, so that a
resumed or resubmitted run stays one tracking run. Three cases went wrong:
- A fresh run into an output that held an earlier run reopened that run,
  merging two evaluations. A run now reopens only when it resumes its
  output (resume_from_cache); otherwise it starts a new run.
- A resumed collection hands the exporters every rollout of its output,
  and MLflow's log_table appends, so a reopened run's table held the
  earlier rollouts twice. A reopened MLflow run now logs only rollouts
  its table does not hold yet.
- A deleted MLflow run could not be reopened, so logging stopped for that
  output. A new run now takes its place.

The new tests run against a real local MLflow store.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Adam Rajfer <arajfer@nvidia.com>

* fix(exporters): log a rollout that lands on resume after a failed attempt

A reopened MLflow run skipped every rollout whose task and rollout index
its table already held, failed attempts included. A rollout that failed
in one job and landed on resume therefore kept only its failure record
in the table. Now only the landed rollouts the table holds are skipped;
a failed attempt stays in the table as it was logged, next to the later
landing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Adam Rajfer <arajfer@nvidia.com>

* fix(exporters): reopen the tracking run on a resubmit too

A resubmitted job adds only resubmit=True to its config. Collection
turns that into a resume, but the exporters open earlier, while the
global config is parsed. The reopen gate therefore saw no resume and
started a new MLflow or W&B run for the job's continuation. A resubmit
now reopens the recorded run, as a resume does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Adam Rajfer <arajfer@nvidia.com>

* fix(exporters): keep the tracking run in step with what collection continues

The reopen gate and the landed-rollout filter got three cases wrong:

- A no-persist attempt is uploaded but written nowhere, yet it counted
  as landed, so a rollout that landed later for the same task was left
  out of the MLflow table. A rollout counts as landed now only without
  a failure class and without the no-persist flag.
- Judge-failure recovery in append mode adds its rows to the output it
  recovers, but started a new tracking run. It reopens the recorded run
  now, as a resume does.
- A resume that finds nothing to resume starts its output anew, after
  the exporters reopened the recorded run, so the MLflow filter dropped
  fresh rollouts whose keys were in the old table. Collection now tells
  the exporters: they leave the old run as the earlier job left it and
  track the output in a new run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Adam Rajfer <arajfer@nvidia.com>

* fix(exporters): let go of the reopened run even when restoring it fails

Starting over cleared the exporter's handle on the reopened run only
after restoring that run's status and resume count, or after finishing
the W&B run. When the tracking server refused that, the guard swallowed
the error before a new run opened, and the fresh output kept logging to
the old run, where the MLflow filter dropped its rollouts as landed.
Each backend now lets go of the reopened run first, and restoring it is
best effort: a failure is logged and the new run still opens.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Adam Rajfer <arajfer@nvidia.com>

* fix(exporters): keep restarted output in its replacement run

Defer a reopened run configuration until continuation is known, clear its
marker before replacement setup, and start a fresh tracking run when
reverification finds no cached output. Cover dispatcher ordering, saved
answers, masked configuration and best-effort cleanup with regressions.

Signed-off-by: Adam Rajfer <arajfer@nvidia.com>

* fix(exporters): parse continuation flags consistently

Signed-off-by: Adam Rajfer <arajfer@nvidia.com>

* fix(orchestration): normalize resume before exporter setup

Resubmitted Slurm jobs set resume_from_cache before exporters open.
Normalize the resubmit command in older saved job scripts under the
existing lock, preserving their tracking identity and rollout artifacts.
Exporters now use only resume and append-recovery flags.

Signed-off-by: Adam Rajfer <arajfer@nvidia.com>

---------

Signed-off-by: Adam Rajfer <arajfer@nvidia.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

This branch was previously deployed

1 inactive deployment
public — 95d75cc0 Deployed Oct 20, 2026 by copy-pr-bot[bot] via release / finalize / notify #5951
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:evaluation Evaluation, rollout collection, reward profiling, comparison, and exporters complexity:low Localized change in one scope with a small, straightforward review surface feature New capabilities, enhancements, or enablement work needs-review PR is ready for code review and waiting on a reviewer

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants