v1.0
This commit is contained in:
94
v1/structured_output/request.py
Normal file
94
v1/structured_output/request.py
Normal file
@@ -0,0 +1,94 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
|
||||
import dataclasses
|
||||
import functools
|
||||
import json
|
||||
from concurrent.futures import Future
|
||||
from concurrent.futures._base import TimeoutError
|
||||
from typing import cast
|
||||
|
||||
from vllm.sampling_params import SamplingParams, StructuredOutputsParams
|
||||
from vllm.v1.structured_output.backend_types import (
|
||||
StructuredOutputGrammar,
|
||||
StructuredOutputKey,
|
||||
StructuredOutputOptions,
|
||||
)
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
class StructuredOutputRequest:
|
||||
params: StructuredOutputsParams
|
||||
_grammar: Future[StructuredOutputGrammar] | StructuredOutputGrammar | None = None
|
||||
reasoning_ended: bool | None = None
|
||||
|
||||
@staticmethod
|
||||
def from_sampling_params(
|
||||
sampling_params: SamplingParams | None,
|
||||
) -> "StructuredOutputRequest | None":
|
||||
if sampling_params is None:
|
||||
return None
|
||||
params = sampling_params.structured_outputs
|
||||
if params:
|
||||
if params.all_constraints_none():
|
||||
return None
|
||||
else:
|
||||
return StructuredOutputRequest(params=params)
|
||||
return None
|
||||
|
||||
def _check_grammar_completion(self) -> bool:
|
||||
# NOTE: We have to lazy import to gate circular imports
|
||||
from vllm.v1.request import RequestStatus
|
||||
|
||||
if isinstance(self._grammar, Future):
|
||||
try:
|
||||
# We will check whether the future is ready within 100 us
|
||||
self._grammar = self._grammar.result(timeout=0.0001)
|
||||
self.status = RequestStatus.WAITING
|
||||
except TimeoutError:
|
||||
return False
|
||||
return True
|
||||
|
||||
@property
|
||||
def is_grammar_ready(self) -> bool:
|
||||
return self._check_grammar_completion()
|
||||
|
||||
@property
|
||||
def grammar(self) -> StructuredOutputGrammar | None:
|
||||
completed = self._check_grammar_completion()
|
||||
return (
|
||||
cast(StructuredOutputGrammar | None, self._grammar) if completed else None
|
||||
)
|
||||
|
||||
@grammar.setter
|
||||
def grammar(
|
||||
self, grammar: StructuredOutputGrammar | Future[StructuredOutputGrammar]
|
||||
) -> None:
|
||||
self._grammar = grammar
|
||||
|
||||
@functools.cached_property
|
||||
def structured_output_key(self) -> StructuredOutputKey:
|
||||
return get_structured_output_key(self.params)
|
||||
|
||||
|
||||
def get_structured_output_key(params: StructuredOutputsParams) -> StructuredOutputKey:
|
||||
if params.json is not None:
|
||||
if not isinstance(params.json, str):
|
||||
json_str = json.dumps(params.json)
|
||||
else:
|
||||
json_str = params.json
|
||||
return StructuredOutputOptions.JSON, json_str
|
||||
if params.json_object:
|
||||
return StructuredOutputOptions.JSON_OBJECT, ""
|
||||
if params.regex is not None:
|
||||
return StructuredOutputOptions.REGEX, params.regex
|
||||
if params.choice is not None:
|
||||
if not isinstance(params.choice, str):
|
||||
json_str = json.dumps(params.choice)
|
||||
else:
|
||||
json_str = params.choice
|
||||
return StructuredOutputOptions.CHOICE, json_str
|
||||
if params.grammar is not None:
|
||||
return StructuredOutputOptions.GRAMMAR, params.grammar
|
||||
if params.structural_tag is not None:
|
||||
return StructuredOutputOptions.STRUCTURAL_TAG, params.structural_tag
|
||||
raise ValueError("No valid structured output parameter found")
|
||||
Reference in New Issue
Block a user