[ROCm][Bugfix] fix(structured_output): Skip guidance backend for schemas with patternProperties (#30730)

Signed-off-by: Andreas Karatzas <akaratza@amd.com>
This commit is contained in:
Andreas Karatzas 2025-12-18 01:04:57 -06:00 committed by GitHub
parent a85724bd6e
commit be2ad5f920
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 45 additions and 2 deletions

View File

@ -24,7 +24,10 @@ from vllm.tokenizers.mistral import MistralTokenizer
from vllm.utils import length_from_prompt_token_ids_or_embeds
from vllm.v1.engine import EngineCoreRequest
from vllm.v1.metrics.stats import MultiModalCacheStats
from vllm.v1.structured_output.backend_guidance import validate_guidance_grammar
from vllm.v1.structured_output.backend_guidance import (
has_guidance_unsupported_json_features,
validate_guidance_grammar,
)
from vllm.v1.structured_output.backend_lm_format_enforcer import (
validate_structured_output_request_lm_format_enforcer,
)
@ -340,8 +343,22 @@ class InputProcessor:
# The request either failed validation
# or includes some jsonschema feature(s) that
# are not supported in xgrammar.
if isinstance(self.tokenizer, MistralTokenizer):
# Check if schema has features unsupported by guidance
so_params = params.structured_outputs
skip_guidance = False
if so_params.json:
if isinstance(so_params.json, str):
import json
schema = json.loads(so_params.json)
else:
schema = so_params.json
skip_guidance = has_guidance_unsupported_json_features(schema)
if isinstance(self.tokenizer, MistralTokenizer) or skip_guidance:
# Fall back to outlines if the tokenizer is Mistral
# or if schema contains features unsupported by guidance
validate_structured_output_request_outlines(params)
params.structured_outputs._backend = "outlines"
else:

View File

@ -44,6 +44,32 @@ def _walk_json_for_additional_properties(data: object):
_walk_json_for_additional_properties(item)
def has_guidance_unsupported_json_features(schema: dict[str, Any]) -> bool:
"""Check if JSON schema contains features unsupported by guidance/llguidance."""
def check_object(obj: dict[str, Any]) -> bool:
if not isinstance(obj, dict):
return False
# patternProperties is not supported by llguidance
if "patternProperties" in obj:
return True
# Recursively check all nested objects and arrays
for value in obj.values():
if isinstance(value, dict):
if check_object(value):
return True
elif isinstance(value, list):
for item in value:
if isinstance(item, dict) and check_object(item):
return True
return False
return check_object(schema)
def process_for_additional_properties(
guide_json: str | dict[str, Any],
) -> dict[str, Any]: