Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Fix EtaLogitsWarper on fully masked logits#45413

Closed
ezylopx5 wants to merge 4 commits into
huggingface:mainfrom
ezylopx5:fix/eta-warper-all-inf
Closed

Fix EtaLogitsWarper on fully masked logits#45413
ezylopx5 wants to merge 4 commits into
huggingface:mainfrom
ezylopx5:fix/eta-warper-all-inf

Conversation

@ezylopx5

Copy link
Copy Markdown

I ran into an edge case in eta sampling where EtaLogitsWarper crashes if a row is fully masked (scores == -inf for all tokens).

The previous entropy computation used Categorical(logits=scores).entropy(), which fails on that input. This change computes entropy from NaN-safe probabilities instead, so fully masked rows stay fully masked without raising.

I also added a regression assertion to the existing eta warper test for the all--inf case.

Local test run:
python -m pytest tests/generation/test_logits_process.py -x -q (45 passed).

AI-assisted: I used AI help for drafting, but I personally reproduced the bug, reviewed the diff, and ran local tests.

@Rocketknight1

Copy link
Copy Markdown
Member

cc @Cyrilvallez for generation!

@ezylopx5 ezylopx5 force-pushed the fix/eta-warper-all-inf branch from 0d1e9bc to d8932ab Compare April 15, 2026 13:36
@Cyrilvallez

Copy link
Copy Markdown
Member

Could you please provide a reproducer? I don't see how all logits could end up at -inf...

@ezylopx5

ezylopx5 commented Apr 20, 2026

Copy link
Copy Markdown
Author

A full -inf row can happen if a previous logits processor masks everything for a step (misconfigured constraints/custom callback). A minimal reproducer is:

import torch
from transformers.generation.logits_process import SuppressTokensLogitsProcessor, EtaLogitsWarper

input_ids = torch.tensor([[0]])
scores = torch.tensor([[5.0, 1.0, -1.0, 0.2]])

# Previous processor masks all vocab entries
masked = SuppressTokensLogitsProcessor([0, 1, 2, 3])(input_ids, scores)
print(masked)
# tensor([[-inf, -inf, -inf, -inf]])

# This PR keeps eta stable on this input
out = EtaLogitsWarper(epsilon=1e-3, device="cpu")(input_ids, masked)
print(out, torch.isnan(out).any())
# tensor([[-inf, -inf, -inf, -inf]]) tensor(False)

Before this PR, the entropy path used in EtaLogitsWarper would go through Categorical(logits=scores).entropy(), which raises here because softmax([-inf, ...]) becomes NaN.

So this patch is mainly a robustness guard: preserve the fully masked state and avoid NaNs/crash in eta when upstream processors produce that edge case.

@Cyrilvallez

Copy link
Copy Markdown
Member

Humm, I think it actually makes more sense to keep the error and crash on such cases, rather than silently fail when something is wrong. A full row should never be all -inf, and if it's the case as you said something is really wrong and it's better to crash.

@ezylopx5

ezylopx5 commented Apr 23, 2026

Copy link
Copy Markdown
Author

yup, thanks for the feedback.
I updated the PR accordingly: it now fails fast instead of silently recovering.
n EtaLogitsWarper, if any row is fully masked (all -inf), we now raise a clear ValueError immediately, the regression test was updated to assert that explicit error behavior.
So this now keeps the crash semantics you suggested, but with a more direct error message indicating that an upstream processor masked every token.

@ezylopx5

ezylopx5 commented Apr 23, 2026

Copy link
Copy Markdown
Author

Small follow-up pushed on top: moved the fully-masked-row guard in EtaLogitsWarper to run before softmax, so we fail fast without doing any NaN-producing computation first.

@ezylopx5

Copy link
Copy Markdown
Author

Hi @Cyrilvallez , just a quick follow-up on this PR. Is there anything still blocking it, or is it simply waiting for review? Happy to make any additional changes if needed.

@Cyrilvallez

Copy link
Copy Markdown
Member

My main issue with the PR is that we perform runtime value checks that should not be necessary. I.e. we never do it in any other Processor, because there is no reason in general to end up with fully masked rows...

@ezylopx5

Copy link
Copy Markdown
Author

My main issue with the PR is that we perform runtime value checks that should not be necessary. I.e. we never do it in any other Processor, because there is no reason in general to end up with fully masked rows...

That makes sense , I’ll close this PR. Thanks for the review and clarification.

@ezylopx5 ezylopx5 closed this Jun 18, 2026
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.

4 participants