Repository navigation
Conversation
…equest fallback `auto` chose each request's backend from its content: xgrammar first, then guidance or outlines when xgrammar rejected the constraint. EngineCore keeps the backend of the first structured request and, since vllm-project#49625, rejects requests naming another one, so a request's outcome depended on the traffic before it. `auto` now resolves from the tokenizer alone: guidance for Tekken-based Mistral tokenizers, whose tool parser generates llguidance Lark, and xgrammar otherwise. A constraint the selected backend cannot enforce is rejected; selecting a backend explicitly restores the other backends' features. The now unused `has_guidance_unsupported_json_features` is removed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Bugen Zhao <i@bugenzhao.com>
Contributor
|
Documentation preview: https://vllm--62877.org.readthedocs.build/en/62877/ |
auto from the tokenizer, without per-request fallbackauto pick one backend per server instead of per request
Contributor
|
This pull request has merge conflicts that must be resolved before it can be |
6 tasks done
This branch has not been deployed
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.
Overview
With the default
structured_outputs_config.backend="auto", each request picks its backend from its own content: xgrammar first, then guidance or outlines when xgrammar rejects the constraint. EngineCore keeps a single backend, the one the first structured request chose, so a request's outcome depends on the traffic before it. Before #49625 a request that resolved to the other backend was compiled by the wrong one, silently dropping constraints or failing with HTTP 500; since #49625 it is a 400. This PR makesautochoose one backend per server from the tokenizer alone, so every request on a server names the same backend and the result no longer depends on request order.Claims
autoresolves toguidancefor Tekken-based Mistral tokenizers and toxgrammarfor every other tokenizer, for every request. It no longer falls back per request.multipleOfunder xgrammar) is rejected with the backend's validation error (400), on a fresh server and after any other traffic alike. Selectingguidanceexplicitly restores it.Validation
tests/v1/structured_output/andtests/test_sampling_params.py: 325 passed, 1 xfailed. New tests:test_auto_backend_rejects_schema_without_fallback(a supported schema resolves to xgrammar;multipleOfandpatternPropertiesschemas are rejected instead of falling back) andtest_auto_selects_guidance_for_tekken_mistral. All three fail onmain.tests/entrypoints/llm/test_struct_output_generate.py::test_structured_output_auto_mode(GB200, Qwen2.5-1.5B-Instruct and Ministral-8B-Instruct-2410): 2 passed. The test now expectsautoto rejectUNSUPPORTED_JSON_SCHEMA(multipleOf) unless the tokenizer is Tekken Mistral, where it generates valid JSON with guidance. Withtokenizer_mode=mistral, Ministral-8B loads a TekkenMistralTokenizerandautoresolves to guidance; I did not confirm which tokenizer the test'stokenizer_mode=autoloads.pre-commiton the changed files, including mypy.Details
Why per request is the wrong granularity.
StructuredOutputManagerbuilds one backend from the first structured request and #49625 now rejects requests naming another one. Under the oldauto, a server receiving both an xgrammar-compatible schema and amultipleOfschema answered the second one differently depending on which came first:multipleOfschema (resolves to guidance)multipleOfschema (guidance)The tokenizer is fixed for the server's lifetime, so resolving from it gives one backend per server, consistent with what EngineCore can serve.
Why Tekken Mistral selects guidance. The Mistral tool parser emits llguidance-dialect Lark for grammar-capable Mistral tokenizers, and the xgrammar backend declares no special tokens for Mistral tokenizers, so a regex like
.can match[TOOL_CALLS]as text (#58321). Before this PR only those Lark grammars went to guidance; JSON schema and regex requests on the same server went to xgrammar, so Mistral servers mixed backends too. Guidance handles both.Behavior change. Requests that relied on the fallback are now rejected under
auto:multipleOf,uniqueItems/contains, unsupported stringformats,patternwith length bounds, ...), and regexes or grammars xgrammar cannot compile. They previously worked only while the engine had not latched xgrammar.--structured-outputs-config.backend guidance(oroutlines) selects those backends for the whole server. The removed fallback also leaveshas_guidance_unsupported_json_featuresunused, so it is deleted.Migration. This changes the default behavior, so it could instead first ship one release in which
autostill falls back but logs a deprecation warning naming the backend to configure. The rejection message is the selected backend's own; anauto-specific hint pointing to--structured-outputs-config.backendcould be added.Rust frontend. #62456 gives the Rust frontend the same model: one configured backend,
automeaning xgrammar. The Rust frontend does not load Mistral tokenizers, so the Tekken rule does not apply there.Not a duplicate. No open PR changes how
autoresolves. #49625 (merged) rejects mismatched backends in EngineCore; #62246 (draft) would let EngineCore hold several backends, which would allow request-level selection later.Pull Request Checklist
I used vLLM's
/pr-checklistskill. (Mandatory for agents, optional for humans).AI assistance was used during the creation of this PR.
Design Fit: Minimizes impact on core components, reuses existing functionality, and justifies added complexity.
Testing and Validation: Validates the change and ensures any added tests are meaningful and reliable, with CI coverage or documented CI resource constraints and validation performed outside CI.
Code Quality and Style: Keeps code and comments clear and concise, and updates relevant documentation and examples.
Pull Request Contents: Includes a brief summary and relevant links, supports claims with evidence, explains root causes and implementation trade-offs, and follows the contributing guide.
AI assistance (Claude) was used to investigate, write, and test this change. I reviewed every changed line and ran the tests above.
🤖 Generated with Claude Code