Re-add the API serving timing metrics. (#14744)
Signed-off-by: zhanghaotong <zhanghaotong.zht@antgroup.com> Co-authored-by: zhanghaotong <zhanghaotong.zht@antgroup.com>
This commit is contained in:
@@ -12,7 +12,7 @@ from fastapi import HTTPException, Request
|
||||
from fastapi.responses import ORJSONResponse, StreamingResponse
|
||||
|
||||
from sglang.srt.entrypoints.openai.protocol import ErrorResponse, OpenAIServingRequest
|
||||
from sglang.srt.managers.io_struct import GenerateReqInput
|
||||
from sglang.srt.managers.io_struct import EmbeddingReqInput, GenerateReqInput
|
||||
from sglang.srt.server_args import ServerArgs
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@@ -88,6 +88,9 @@ class OpenAIServingBase(ABC):
|
||||
"""Handle the specific request type with common pattern
|
||||
If you want to override this method, you should be careful to record the validation time.
|
||||
"""
|
||||
received_time = time.time()
|
||||
received_time_perf = time.perf_counter()
|
||||
|
||||
try:
|
||||
# Validate request
|
||||
validation_start = time.perf_counter()
|
||||
@@ -100,8 +103,12 @@ class OpenAIServingBase(ABC):
|
||||
adapted_request, processed_request = self._convert_to_internal_request(
|
||||
request, raw_request
|
||||
)
|
||||
if hasattr(adapted_request, "validation_time"):
|
||||
|
||||
if isinstance(adapted_request, (GenerateReqInput, EmbeddingReqInput)):
|
||||
# Only set timing fields if adapted_request supports them
|
||||
adapted_request.validation_time = validation_time
|
||||
adapted_request.received_time = received_time
|
||||
adapted_request.received_time_perf = received_time_perf
|
||||
|
||||
# Note(Xinyuan): raw_request below is only used for detecting the connection of the client
|
||||
if hasattr(request, "stream") and request.stream:
|
||||
|
||||
@@ -110,6 +110,23 @@ class SpeculativeDecodingMetricsMixin:
|
||||
spec_accepted_tokens: List[int]
|
||||
|
||||
|
||||
@dataclass
|
||||
class APIServingTimingMixin:
|
||||
# Validation step duration
|
||||
validation_time: Optional[float] = None
|
||||
|
||||
# For metrics
|
||||
received_time: Optional[float] = None
|
||||
|
||||
# Perf_counter equivalents for accurate time calculations
|
||||
received_time_perf: Optional[float] = None
|
||||
|
||||
|
||||
_API_SERVING_TIMING_MIXIN_FIELDS = tuple(
|
||||
APIServingTimingMixin.__dataclass_fields__.keys()
|
||||
)
|
||||
|
||||
|
||||
# Parameters for a session
|
||||
@dataclass
|
||||
class SessionParams:
|
||||
@@ -138,7 +155,7 @@ MultimodalDataInputFormat = Union[
|
||||
|
||||
|
||||
@dataclass
|
||||
class GenerateReqInput(BaseReq):
|
||||
class GenerateReqInput(BaseReq, APIServingTimingMixin):
|
||||
# The input prompt. It can be a single prompt or a batch of prompts.
|
||||
text: Optional[Union[List[str], str]] = None
|
||||
# The token ids for text; one can specify either text or input_ids
|
||||
@@ -201,9 +218,6 @@ class GenerateReqInput(BaseReq):
|
||||
# For reasoning
|
||||
reasoning: bool = False
|
||||
|
||||
# Validation step duration
|
||||
validation_time: Optional[float] = None
|
||||
|
||||
# For data parallel rank routing
|
||||
data_parallel_rank: Optional[int] = None
|
||||
|
||||
@@ -623,7 +637,6 @@ class GenerateReqInput(BaseReq):
|
||||
decode_tp_size=(
|
||||
self.decode_tp_size[i] if self.decode_tp_size is not None else None
|
||||
),
|
||||
validation_time=self.validation_time,
|
||||
data_parallel_rank=(
|
||||
self.data_parallel_rank if self.data_parallel_rank is not None else None
|
||||
),
|
||||
@@ -635,6 +648,10 @@ class GenerateReqInput(BaseReq):
|
||||
return_bytes=self.return_bytes,
|
||||
return_entropy=self.return_entropy,
|
||||
http_worker_ipc=self.http_worker_ipc,
|
||||
**{
|
||||
field: getattr(self, field)
|
||||
for field in _API_SERVING_TIMING_MIXIN_FIELDS
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@@ -724,7 +741,7 @@ class BatchTokenizedGenerateReqInput(BaseBatchReq):
|
||||
|
||||
|
||||
@dataclass
|
||||
class EmbeddingReqInput(BaseReq):
|
||||
class EmbeddingReqInput(BaseReq, APIServingTimingMixin):
|
||||
# The input prompt. It can be a single prompt or a batch of prompts.
|
||||
text: Optional[Union[List[List[str]], List[str], str]] = None
|
||||
# The image input. It can be an image instance, file name, URL, or base64 encoded string.
|
||||
@@ -840,9 +857,12 @@ class EmbeddingReqInput(BaseReq):
|
||||
video_data=self.video_data[i] if self.video_data is not None else None,
|
||||
sampling_params=self.sampling_params[i],
|
||||
rid=self.rid[i],
|
||||
validation_time=self.validation_time,
|
||||
dimensions=self.dimensions,
|
||||
http_worker_ipc=self.http_worker_ipc,
|
||||
**{
|
||||
field: getattr(self, field)
|
||||
for field in _API_SERVING_TIMING_MIXIN_FIELDS
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -408,7 +408,7 @@ class TokenizerManager(TokenizerCommunicatorMixin, TokenizerManagerMultiItemMixi
|
||||
obj: Union[GenerateReqInput, EmbeddingReqInput],
|
||||
request: Optional[fastapi.Request] = None,
|
||||
):
|
||||
created_time = time.time()
|
||||
created_time = obj.received_time if obj.received_time else time.time()
|
||||
self.auto_create_handle_loop()
|
||||
obj.normalize_batch_and_arguments()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user