Skip to content

Commit 1324f0a

Browse files
committed
feat: add structured outputs support
Add support for structured outputs (JSON schema, regex, choice, grammar, and structural_tag constraints) using vLLM 0.11.0+'s StructuredOutputsParams API. Changes: - Import StructuredOutputsParams from vllm.sampling_params - Extract structured_outputs from extra_body in sampling_params - Create StructuredOutputsParams instances for json, regex, choice, grammar, and structural_tag constraint types - Reject deprecated guided_json parameter (from vLLM <0.11.0) with clear error message pointing to migration guide This enables users to enforce JSON schemas and other structured output formats on model responses, as documented in vLLM 0.11.0. https://docs.vllm.ai/en/v0.11.0/features/structured_outputs.html Fixes #235
1 parent 7ea40eb commit 1324f0a

File tree

1 file changed

+42
-0
lines changed

1 file changed

+42
-0
lines changed

src/utils.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from functools import wraps
55
from time import time
66
from vllm.entrypoints.openai.protocol import RequestResponseMetadata
7+
from vllm.sampling_params import StructuredOutputsParams
78

89
try:
910
from vllm.utils import random_uuid
@@ -50,6 +51,47 @@ def __init__(self, job):
5051
self.apply_chat_template = job.get("apply_chat_template", False)
5152
self.use_openai_format = job.get("use_openai_format", False)
5253
samp_param = job.get("sampling_params", {})
54+
55+
# Reject deprecated old API format (top-level guided_json parameter)
56+
# worker-vllm v2.9.5+ updated to vLLM 0.11.0+, which uses
57+
# OpenAI-compatible extra_body.structured_outputs format
58+
if job.get("guided_json") is not None:
59+
raise ValueError(
60+
"The 'guided_json' parameter is deprecated in vLLM 0.11.0+. "
61+
"Please use 'structured_outputs' instead. "
62+
"See: https://docs.vllm.ai/en/v0.11.0/features/structured_outputs.html"
63+
)
64+
65+
# Extract extra_body (for new structured_outputs API) from sampling_params
66+
extra_body = samp_param.pop("extra_body", None)
67+
if extra_body and "structured_outputs" in extra_body:
68+
structured_outputs = extra_body["structured_outputs"]
69+
70+
# Create StructuredOutputsParams instance
71+
if "json" in structured_outputs:
72+
samp_param["structured_outputs"] = StructuredOutputsParams(
73+
json=structured_outputs["json"]
74+
)
75+
elif "regex" in structured_outputs:
76+
samp_param["structured_outputs"] = StructuredOutputsParams(
77+
regex=structured_outputs["regex"]
78+
)
79+
elif "choice" in structured_outputs:
80+
samp_param["structured_outputs"] = StructuredOutputsParams(
81+
choice=structured_outputs["choice"]
82+
)
83+
elif "grammar" in structured_outputs:
84+
samp_param["structured_outputs"] = StructuredOutputsParams(
85+
grammar=structured_outputs["grammar"]
86+
)
87+
elif "structural_tag" in structured_outputs:
88+
samp_param["structured_outputs"] = StructuredOutputsParams(
89+
structural_tag=structured_outputs["structural_tag"]
90+
)
91+
92+
# Store for potential use in OpenAI-compatible API
93+
self.extra_body = extra_body
94+
5395
if "max_tokens" not in samp_param:
5496
samp_param["max_tokens"] = 100
5597
self.sampling_params = SamplingParams(**samp_param)

0 commit comments

Comments
 (0)