[Bugfix][Structured Output] Mask request stop tokens in xgrammar until grammar terminates - #49227
Merged
Conversation
sfeng33
marked this pull request as ready for review
July 20, 2026 16:51
sfeng33
requested review from
aarnphm,
benchislett,
mgoin and
russellb
as code owners
July 20, 2026 16:51
Contributor
|
This pull request has merge conflicts that must be resolved before it can be |
yzong-rh
approved these changes
Jul 24, 2026
yzong-rh
left a comment
Contributor
There was a problem hiding this comment.
LGTM. Reproduces cleanly, test passes.
The issue occur in guidance as well, but it doesn't seem mask out stop tokens even if we override eos_token in llguidance_hf.from_tokenizer. Separate fix required.
Collaborator
Author
|
/ci run |
|
✅ Triggered Buildkite CI #83175 for commit |
bbrowning
approved these changes
Aug 10, 2026
bbrowning
left a comment
Collaborator
There was a problem hiding this comment.
Pulled locally, reviewed, and confirmed the new test properly catches this regression. Looks good!
bbrowning
added a commit
to bbrowning/upstream-city
that referenced
this pull request
Aug 10, 2026
…e README path
Backlog note in the pack README ("Growing up (later)"): let `gc dev-pack review`
(and materialize) accept a rig-carrying PR spec so --rig isn't needed —
`vllm#49227` (<rig>#<PR> split) and a full GitHub PR URL
(vllm-project/vllm#49227 → map owner/repo to the local rig
by matching each rig's origin remote). Bare-number + --rig stays as the override.
Also fix a stale post-rename path in the "More reviewers" bullet
(agents/reviewer/ -> agents/pr-reviewer/).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Purpose
Fixes #42403.
With structured outputs (e.g. JSON schema), a model can sample a stop token while the grammar FSM is still mid-object, truncating generation into invalid JSON. On Gemma this is
<end_of_turn>(id 106).Root cause: xgrammar only knows the tokenizer's single eos, but a request's real stop set is
generation_config's eos list plus any userstop_token_ids. On Gemma-4 that gap is concrete —generation_configeos is[1, 106, 50]while the tokenizer eos is just<eos>(1). Tokens 106/50 are invisible to the grammar, so they escape the bitmask in non-terminal states.Fix
Forward the request's
sampling_params.all_stop_token_idsthroughcompile_grammar(...)into xgrammar's nativeGrammarMatcher(override_stop_tokens=...). xgrammar then gates every one of the request's stop tokens to the grammar-terminal state — masked mid-object, allowed only once the schema is satisfied.Test Plan
Force <end_of_turn> (id 106) via logit_bias + greedy:
Test Result
{"name": " (truncated, stop_reason=106){"name": "Elara Vance", "bio": "..."} (stop_reason=106)