From 4a8a567e16f5e1b2809112442e6da5fc6d9a6aca Mon Sep 17 00:00:00 2001 From: ExtReMLapin <3909752+ExtReMLapin@users.noreply.github.com> Date: Wed, 22 Oct 2025 00:25:23 +0200 Subject: [PATCH] Updated xgrammar backend to not deny supported string formats (#27253) Signed-off-by: CNE Pierre FICHEPOIL Signed-off-by: ExtReMLapin <3909752+ExtReMLapin@users.noreply.github.com> Co-authored-by: CNE Pierre FICHEPOIL Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- tests/v1/structured_output/test_utils.py | 3 ++- vllm/v1/structured_output/backend_xgrammar.py | 25 ++++++++++++++++++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/tests/v1/structured_output/test_utils.py b/tests/v1/structured_output/test_utils.py index b285658af3d1a..513a21dd6bb39 100644 --- a/tests/v1/structured_output/test_utils.py +++ b/tests/v1/structured_output/test_utils.py @@ -13,7 +13,7 @@ pytestmark = pytest.mark.cpu_test @pytest.fixture def unsupported_string_schemas(): return [ - {"type": "string", "format": "email"}, + {"type": "string", "format": "non_existing_format"}, ] @@ -58,6 +58,7 @@ def supported_schema(): "properties": { "name": {"type": "string"}, "age": {"type": "integer"}, + "email": {"type": "string", "format": "email"}, "status": {"type": "string"}, "scores": {"type": "array", "items": {"type": "number"}}, "car_type": {"type": "string", "enum": ["sedan", "suv", "truck"]}, diff --git a/vllm/v1/structured_output/backend_xgrammar.py b/vllm/v1/structured_output/backend_xgrammar.py index 4fe4f8848d987..445a8df3799bf 100644 --- a/vllm/v1/structured_output/backend_xgrammar.py +++ b/vllm/v1/structured_output/backend_xgrammar.py @@ -200,6 +200,25 @@ class XgrammarGrammar(StructuredOutputGrammar): self.matcher.reset() +# cf https://github.com/mlc-ai/xgrammar/blob/a32ac892676d2eedc0327416105b9b06edfb94b2/cpp/json_schema_converter.cc +STRING_SUPPORTED_FORMATS = { + "email", + "date", + "time", + "date-time", + "duration", + "ipv4", + "ipv6", + "hostname", + "uuid", + "uri", + "uri-reference", + "uri-template", + "json-pointer", + "relative-json-pointer", +} + + def has_xgrammar_unsupported_json_features(schema: dict[str, Any]) -> bool: """Check if JSON schema contains features unsupported by xgrammar.""" @@ -219,7 +238,11 @@ def has_xgrammar_unsupported_json_features(schema: dict[str, Any]) -> bool: return True # Unsupported keywords for strings - if obj.get("type") == "string" and "format" in obj: + if ( + obj.get("type") == "string" + and "format" in obj + and obj["format"] not in STRING_SUPPORTED_FORMATS + ): return True # Unsupported keywords for objects