diff --git a/docs/features/structured_outputs.md b/docs/features/structured_outputs.md index 1f955c6e30d6c..901d87e7ed3d9 100644 --- a/docs/features/structured_outputs.md +++ b/docs/features/structured_outputs.md @@ -6,6 +6,17 @@ vLLM supports the generation of structured outputs using This document shows you some examples of the different options that are available to generate structured outputs. +!!! warning + If you are still using the following deprecated API fields, please update your code to use `structured_outputs` as demonstrated in the rest of this document: + + - `guided_json` -> `{"structured_outputs": {"json": ...}}` or `StructuredOutputsParams(json=...)` + - `guided_regex` -> `{"structured_outputs": {"regex": ...}}` or `StructuredOutputsParams(regex=...)` + - `guided_choice` -> `{"structured_outputs": {"choice": ...}}` or `StructuredOutputsParams(choice=...)` + - `guided_grammar` -> `{"structured_outputs": {"grammar": ...}}` or `StructuredOutputsParams(grammar=...)` + - `guided_whitespace_pattern` -> `{"structured_outputs": {"whitespace_pattern": ...}}` or `StructuredOutputsParams(whitespace_pattern=...)` + - `structural_tag` -> `{"structured_outputs": {"structural_tag": ...}}` or `StructuredOutputsParams(structural_tag=...)` + - `guided_decoding_backend` -> Remove this field from your request + ## Online Serving (OpenAI API) You can generate structured outputs using the OpenAI's [Completions](https://platform.openai.com/docs/api-reference/completions) and [Chat](https://platform.openai.com/docs/api-reference/chat) API. diff --git a/vllm/entrypoints/openai/protocol.py b/vllm/entrypoints/openai/protocol.py index c30681318f693..8829fa4886f62 100644 --- a/vllm/entrypoints/openai/protocol.py +++ b/vllm/entrypoints/openai/protocol.py @@ -541,6 +541,56 @@ class ChatCompletionRequest(OpenAIBaseModel): default=None, description="Additional kwargs for structured outputs", ) + guided_json: Optional[Union[str, dict, BaseModel]] = Field( + default=None, + description=( + "`guided_json` is deprecated. " + "This will be removed in v0.12.0 or v1.0.0, whichever is soonest. " + "Please pass `json` to `structured_outputs` instead."), + ) + guided_regex: Optional[str] = Field( + default=None, + description=( + "`guided_regex` is deprecated. " + "This will be removed in v0.12.0 or v1.0.0, whichever is soonest. " + "Please pass `regex` to `structured_outputs` instead."), + ) + guided_choice: Optional[list[str]] = Field( + default=None, + description=( + "`guided_choice` is deprecated. " + "This will be removed in v0.12.0 or v1.0.0, whichever is soonest. " + "Please pass `choice` to `structured_outputs` instead."), + ) + guided_grammar: Optional[str] = Field( + default=None, + description=( + "`guided_grammar` is deprecated. " + "This will be removed in v0.12.0 or v1.0.0, whichever is soonest. " + "Please pass `grammar` to `structured_outputs` instead."), + ) + structural_tag: Optional[str] = Field( + default=None, + description=( + "`structural_tag` is deprecated. " + "This will be removed in v0.12.0 or v1.0.0, whichever is soonest. " + "Please pass `structural_tag` to `structured_outputs` instead."), + ) + guided_decoding_backend: Optional[str] = Field( + default=None, + description=( + "`guided_decoding_backend` is deprecated. " + "This will be removed in v0.12.0 or v1.0.0, whichever is soonest. " + "Please remove it from your request."), + ) + guided_whitespace_pattern: Optional[str] = Field( + default=None, + description=( + "`guided_whitespace_pattern` is deprecated. " + "This will be removed in v0.12.0 or v1.0.0, whichever is soonest. " + "Please pass `whitespace_pattern` to `structured_outputs` instead." + ), + ) priority: int = Field( default=0, description=( @@ -658,6 +708,20 @@ class ChatCompletionRequest(OpenAIBaseModel): if prompt_logprobs is None and self.echo: prompt_logprobs = self.top_logprobs + # Forward deprecated guided_* parameters to structured_outputs + if self.structured_outputs is None: + kwargs = dict[str, Any]( + json=self.guided_json, + regex=self.guided_regex, + choice=self.guided_choice, + grammar=self.guided_grammar, + whitespace_pattern=self.guided_whitespace_pattern, + structural_tag=self.structural_tag, + ) + kwargs = {k: v for k, v in kwargs.items() if v is not None} + if len(kwargs) > 0: + self.structured_outputs = StructuredOutputsParams(**kwargs) + response_format = self.response_format json_schema_from_tool = self._get_json_schema_from_tool() if response_format is not None or json_schema_from_tool is not None: @@ -839,7 +903,7 @@ class ChatCompletionRequest(OpenAIBaseModel): if isinstance(data, ValueError): raise data - if "structured_outputs" not in data: + if data.get("structured_outputs", None) is None: return data structured_outputs_kwargs = data['structured_outputs'] @@ -1016,6 +1080,49 @@ class CompletionRequest(OpenAIBaseModel): default=None, description="Additional kwargs for structured outputs", ) + guided_json: Optional[Union[str, dict, BaseModel]] = Field( + default=None, + description=( + "`guided_json` is deprecated. " + "This will be removed in v0.12.0 or v1.0.0, whichever is soonest. " + "Please pass `json` to `structured_outputs` instead."), + ) + guided_regex: Optional[str] = Field( + default=None, + description=( + "`guided_regex` is deprecated. " + "This will be removed in v0.12.0 or v1.0.0, whichever is soonest. " + "Please pass `regex` to `structured_outputs` instead."), + ) + guided_choice: Optional[list[str]] = Field( + default=None, + description=( + "`guided_choice` is deprecated. " + "This will be removed in v0.12.0 or v1.0.0, whichever is soonest. " + "Please pass `choice` to `structured_outputs` instead."), + ) + guided_grammar: Optional[str] = Field( + default=None, + description=( + "`guided_grammar` is deprecated. " + "This will be removed in v0.12.0 or v1.0.0, whichever is soonest. " + "Please pass `grammar` to `structured_outputs` instead."), + ) + guided_decoding_backend: Optional[str] = Field( + default=None, + description=( + "`guided_decoding_backend` is deprecated. " + "This will be removed in v0.12.0 or v1.0.0, whichever is soonest. " + "Please remove it from your request."), + ) + guided_whitespace_pattern: Optional[str] = Field( + default=None, + description=( + "`guided_whitespace_pattern` is deprecated. " + "This will be removed in v0.12.0 or v1.0.0, whichever is soonest. " + "Please pass `whitespace_pattern` to `structured_outputs` instead." + ), + ) priority: int = Field( default=0, description=( @@ -1145,6 +1252,19 @@ class CompletionRequest(OpenAIBaseModel): echo_without_generation = self.echo and self.max_tokens == 0 + # Forward deprecated guided_* parameters to structured_outputs + if self.structured_outputs is None: + kwargs = dict[str, Any]( + json=self.guided_json, + regex=self.guided_regex, + choice=self.guided_choice, + grammar=self.guided_grammar, + whitespace_pattern=self.guided_whitespace_pattern, + ) + kwargs = {k: v for k, v in kwargs.items() if v is not None} + if len(kwargs) > 0: + self.structured_outputs = StructuredOutputsParams(**kwargs) + if (self.structured_outputs is not None and self.response_format is not None and self.response_format.type == "json_object"): @@ -1189,7 +1309,7 @@ class CompletionRequest(OpenAIBaseModel): @model_validator(mode="before") @classmethod def check_structured_outputs_count(cls, data): - if "structured_outputs" not in data: + if data.get("structured_outputs", None) is None: return data structured_outputs_kwargs = data['structured_outputs']