Skip to content

Fail fast on inconsistent class_token_index/vocab_size (fixes #332)#371

Open
Toadoum wants to merge 1 commit into
urchade:mainfrom
Toadoum:fix-332-validate-special-tokens
Open

Fail fast on inconsistent class_token_index/vocab_size (fixes #332)#371
Toadoum wants to merge 1 commit into
urchade:mainfrom
Toadoum:fix-332-validate-special-tokens

Conversation

@Toadoum

@Toadoum Toadoum commented Jul 2, 2026

Copy link
Copy Markdown

Fail fast on inconsistent class_token_index/vocab_size instead of training with silent zero loss

Fixes #332

Problem

When class_token_index and vocab_size are set explicitly in the config but the tokenizer does not actually contain the GLiNER special tokens, _resize_token_embeddings skips adding them and trusts the configured indices. The class-token mask (input_ids == class_token_index) then never matches anything, the entity prompt setup is effectively empty, and training runs to completion with loss=0 and grad_norm=0 — no error, no warning. As reported in #332, this looks like a normal run and is expensive to discover on long jobs.

Change

Adds BaseGLiNER.validate_special_token_config(config, tokenizer), called from _resize_token_embeddings when both class_token_index and vocab_size are explicit (i.e., exactly the branch where special tokens are not auto-added). It:

  • raises ValueError when class_token_index is out of range for the tokenizer (the mmBERT-base case from the issue: index 256001 with a 256000-entry vocab);
  • raises ValueError when ent_token (<<ENT>>) is missing from the tokenizer vocabulary, since that guarantees the zero-loss failure mode;
  • warns (does not raise) when sep_token/rel_token are missing, when class_token_index points at a different token id than ent_token, or when vocab_size disagrees with the tokenizer length.

Both error messages tell the user the concrete fix: set class_token_index: -1 and vocab_size: -1 so GLiNER adds the tokens and detects indices automatically (the workaround confirmed in the issue).

Validation is deliberately skipped when either value is -1 or when resize_token_embeddings=False is combined with a -1 sentinel, so manual setup workflows are unaffected. Loading published checkpoints (tokens present, indices consistent) passes silently.

Design notes / open questions

  • Only ent_token absence is a hard error; a missing sep_token degrades prompts but does not zero out the loss, so it warns. Happy to make it strict if you prefer.
  • The issue also suggests an early-training guard (raise after N warmup batches with all-zero positives). I kept that out of scope here to keep the diff small; can follow up in a separate PR if there is interest.

Testing

  • New tests/test_special_token_validation.py (6 tests, offline, fake tokenizer following the mock style of tests/test_models.py): out-of-range index raises, missing <<ENT>> raises, consistent config passes with zero warnings, index/ent-id mismatch warns, missing <<SEP>> warns, vocab-size mismatch warns.
  • Existing offline tests pass (test_infer_packing.py, mock-based test_models.py tests).

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.

Silent zero-loss training when vocab_size/class_token_index are hardcoded inconsistently (mmBERT token-level)

1 participant