-
Notifications
You must be signed in to change notification settings - Fork 581
ar_validate: fail loudly when every sample fails #2288
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -123,7 +123,24 @@ def main(): | |
| accelerator.device, | ||
| ) | ||
|
|
||
| if results and accelerator.is_main_process: | ||
| # validate_ar() clamps to len(ds), so report what was actually attempted rather than the | ||
| # requested --num_samples, which can be larger than the dataset. A non-positive count means | ||
| # nothing ran at all -- distinct from "everything ran and failed", so say so separately. | ||
| attempted = min(args.num_samples, len(ds)) | ||
| if attempted <= 0: | ||
| raise ValueError( | ||
| f"No samples to validate: --num_samples={args.num_samples} with a dataset of " | ||
| f"{len(ds)} prompts. Pass a positive --num_samples." | ||
| ) | ||
|
|
||
| if not results: | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [SUGGESTION] The guard is all-or-nothing, so a near-total failure still exits 0 with a meaningless AR. The reasoning in the PR description — "a run where 100% of samples failed was indistinguishable from a successful one" — applies just as well at 98.75%. If 79 of 80 samples die and one survives,
results, attempted, failures = validate_ar(...)
if failures / attempted > args.max_failure_rate:
raise RuntimeError(
f"AR validation failed for {failures}/{attempted} samples, above the "
f"--max_failure_rate of {args.max_failure_rate}. See the per-sample WARNING "
"lines above for the underlying error."
)Reasonable to defer as out of scope for a targeted bug fix — the current change is a strict improvement either way.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed the gap is real — 79/80 failing still prints an AR from one sample and exits 0, and the argument I make in the description does apply there. Postponing rather than folding it in here: a failure-rate bound changes behavior for runs that currently pass, so it deserves its own PR with a default chosen deliberately (and probably a Separately, thanks for the |
||
| raise RuntimeError( | ||
| f"AR validation produced no results: all {attempted} samples failed. " | ||
| "See the per-sample WARNING lines above for the underlying error. " | ||
| "Exiting non-zero so this is not mistaken for a successful validation." | ||
| ) | ||
|
|
||
| if accelerator.is_main_process: | ||
| all_ars = [ar for _, ar in results] | ||
| avg_ar = sum(all_ars) / len(all_ars) | ||
| print(f"\n==== AR Validation Results (osl={args.osl}, steps={args.steps}) ====") | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[SUGGESTION] The non-positive-count guard runs after
validate_ar(), so--num_samples 0still pays for the full model load andaccelerator.prepare()across all GPUs before erroring out. It also duplicates themin(num_samples, len(ds))clamp that already lives at line 63, so the two can drift apart if either side changes.Both go away if the block moves up to just after
dsis loaded and before thevalidate_ar()call —len(ds)is available there, and it becomes a genuine "reject before processing" check rather than a post-hoc one:Non-blocking — the current ordering is functionally correct (the empty loop yields no results, and
attempted <= 0is checked beforenot results, so the two failure modes still get distinct messages). This only saves a wasted load on a typo'd flag and keeps the clamp in one place.