| 1 | # SPDX-License-Identifier: Apache-2.0 |
| 2 | # SPDX-FileCopyrightText: Copyright contributors to the vLLM project |
| 3 | |
| 4 | from typing import Any, Literal |
| 5 | |
| 6 | from pydantic import model_validator |
| 7 | from typing_extensions import Self |
| 8 | |
| 9 | from vllm.config.utils import config |
| 10 | from vllm.utils.hashing import safe_hash |
| 11 | |
| 12 | StructuredOutputsBackend = Literal[ |
| 13 | "auto", "xgrammar", "guidance", "outlines", "lm-format-enforcer" |
| 14 | ] |
| 15 | |
| 16 | |
| 17 | @config |
| 18 | class StructuredOutputsConfig: |
| 19 | """Dataclass which contains structured outputs config for the engine.""" |
| 20 | |
| 21 | backend: StructuredOutputsBackend = "auto" |
| 22 | """Which engine will be used for structured outputs (e.g. JSON schema, |
| 23 | regex, etc) by default. With "auto", we will make opinionated choices |
| 24 | based on request contents and what the backend libraries currently support, |
| 25 | so the behavior is subject to change in each release.""" |
| 26 | disable_any_whitespace: bool = False |
| 27 | """If `True`, json output will always be compact without any whitespace. |
| 28 | If `False`, the model may generate whitespace between JSON fields, |
| 29 | which is still valid JSON. This is only supported for xgrammar |
| 30 | and guidance backends.""" |
| 31 | disable_additional_properties: bool = False |
| 32 | """If `True`, the `guidance` backend will not use `additionalProperties` |
| 33 | in the JSON schema. This is only supported for the `guidance` backend and |
| 34 | is used to better align its behaviour with `outlines` and `xgrammar`.""" |
| 35 | reasoning_parser: str = "" |
| 36 | """Select the reasoning parser depending on the model that you're using. |
| 37 | This is used to parse the reasoning content into OpenAI API format.""" |
| 38 | reasoning_parser_plugin: str = "" |
| 39 | """Path to a dynamically reasoning parser plugin that can be dynamically |
| 40 | loaded and registered.""" |
| 41 | enable_in_reasoning: bool = False |
| 42 | """Whether to use structured input for reasoning.""" |
| 43 | |
| 44 | def compute_hash(self) -> str: |
| 45 | """WARNING: Whenever a new field is added to this config, |
| 46 | ensure that it is included in the factors list if |
| 47 | it affects the computation graph. |
| 48 | |
| 49 | Provide a hash that uniquely identifies all the configs |
| 50 | that affect the structure of the computation |
| 51 | graph from input ids/embeddings to the final hidden states, |
| 52 | excluding anything before input ids/embeddings and after |
| 53 | the final hidden states. |
| 54 | """ |
| 55 | # no factors to consider. |
| 56 | # this config will not affect the computation graph. |
| 57 | factors: list[Any] = [] |
| 58 | hash_str = safe_hash(str(factors).encode(), usedforsecurity=False).hexdigest() |
| 59 | return hash_str |
| 60 | |
| 61 | @model_validator(mode="after") |
| 62 | def _validate_structured_output_config(self) -> Self: |
| 63 | if self.disable_any_whitespace and self.backend not in ("xgrammar", "guidance"): |
| 64 | raise ValueError( |
| 65 | "disable_any_whitespace is only supported for " |
| 66 | "xgrammar and guidance backends." |
| 67 | ) |
| 68 | if self.disable_additional_properties and self.backend != "guidance": |
| 69 | raise ValueError( |
| 70 | "disable_additional_properties is only supported " |
| 71 | "for the guidance backend." |
| 72 | ) |
| 73 | return self |