11
from vllm.outputs import (CompletionOutput, PoolingOutput,
12
PoolingRequestOutput, RequestOutput)
13
from vllm.sampling_params import RequestOutputKind
14
+from vllm.tracing import (SpanAttributes, SpanKind, Tracer,
15
+ extract_trace_context)
16
from vllm.transformers_utils.tokenizer import AnyTokenizer
17
from vllm.transformers_utils.tokenizer_group import TokenizerGroup
18
from vllm.v1.engine import EngineCoreOutput, EngineCoreRequest, FinishReason
73
74
@dataclass
75
class OutputProcessorOutput:
74
-
76
request_outputs: list[Union[RequestOutput, PoolingRequestOutput]]
77
reqs_to_abort: list[str]
78
94
arrival_time: float,
95
queue: Optional[RequestOutputCollector],
96
log_stats: bool,
97
+ top_p: Optional[float] = None,
98
+ n: Optional[int] = None,
99
+ temperature: Optional[float] = None,
100
):
101
self.request_id = request_id
102
self.parent_req = parent_req
109
self.logprobs_processor = logprobs_processor
110
self.detokenizer = detokenizer
111
self.max_tokens_param = max_tokens_param
112
+ self.top_p = top_p
113
+ self.n = n
114
+ self.temperature = temperature
115
self.is_prefilling = True
116
self.queue = queue
117
self.num_cached_tokens = 0
144
request=request,
145
)
146
max_tokens_param = sampling_params.max_tokens
147
+ top_p = sampling_params.top_p
148
+ n = sampling_params.n
149
+ temperature = sampling_params.temperature
150
else:
151
logprobs_processor = None
152
detokenizer = None
153
max_tokens_param = None
154
+ top_p = None
155
+ n = None
156
+ temperature = None
157
assert request.pooling_params is not None
158
output_kind = request.pooling_params.output_kind
159
169
logprobs_processor=logprobs_processor,
170
detokenizer=detokenizer,
171
max_tokens_param=max_tokens_param,
172
+ top_p=top_p,
173
+ n=n,
174
+ temperature=temperature,
175
arrival_time=request.arrival_time,
176
queue=queue,
177
log_stats=log_stats,
290
class OutputProcessor:
291
"""Process EngineCoreOutputs into RequestOutputs."""
292
277
- def __init__(
278
- self,
279
- tokenizer: TokenizerGroup,
280
- log_stats: bool,
281
- ):
293
+ def __init__(self, tokenizer: TokenizerGroup, log_stats: bool):
294
self.log_stats = log_stats
295
self.tokenizer = tokenizer
296
self.request_states: dict[str, RequestState] = {}
297
self.parent_requests: dict[str, ParentRequest] = {}
298
self.lora_states = LoRARequestStates()
299
+ self.tracer: Optional[Tracer] = None
300
301
def get_num_unfinished_requests(self):
302
return len(self.request_states)
454
# Track per-request stats
455
self._update_stats_from_finished(req_state, finish_reason,
456
iteration_stats)
444
-
457
+ if self.tracer:
458
+ self.do_tracing(engine_core_output, req_state,
459
+ iteration_stats)
460
self.lora_states.update_iteration_stats(iteration_stats)
461
462
return OutputProcessorOutput(
464
reqs_to_abort=reqs_to_abort,
465
)
466
467
+ def do_tracing(self, engine_core_output: EngineCoreOutput,
468
+ req_state: RequestState,
469
+ iteration_stats: Optional[IterationStats]) -> None:
470
+ assert req_state.stats is not None
471
+ assert iteration_stats is not None
472
+ assert self.tracer is not None
473
+
474
+ arrival_time_nano_seconds = int(req_state.stats.arrival_time * 1e9)
475
+ trace_context = extract_trace_context(engine_core_output.trace_headers)
476
+ with (self.tracer.start_as_current_span(
477
+ "llm_request",
478
+ kind=SpanKind.SERVER,
479
+ context=trace_context,
480
+ start_time=arrival_time_nano_seconds) as span):
481
+ metrics = req_state.stats
482
+ e2e_time = iteration_stats.iteration_timestamp - \
483
+ metrics.arrival_time
484
+ queued_time = metrics.scheduled_ts - metrics.queued_ts
485
+ prefill_time = metrics.first_token_ts - metrics.scheduled_ts
486
+ decode_time = metrics.last_token_ts - metrics.first_token_ts
487
+ inference_time = metrics.last_token_ts - metrics.scheduled_ts
488
+ span.set_attribute(
489
+ SpanAttributes.GEN_AI_LATENCY_TIME_TO_FIRST_TOKEN,
490
+ metrics.first_token_latency)
491
+ span.set_attribute(SpanAttributes.GEN_AI_LATENCY_E2E, e2e_time)
492
+ span.set_attribute(SpanAttributes.GEN_AI_LATENCY_TIME_IN_QUEUE,
493
+ queued_time)
494
+ span.set_attribute(SpanAttributes.GEN_AI_USAGE_PROMPT_TOKENS,
495
+ len(req_state.prompt_token_ids))
496
+ span.set_attribute(SpanAttributes.GEN_AI_USAGE_COMPLETION_TOKENS,
497
+ metrics.num_generation_tokens)
498
+ span.set_attribute(
499
+ SpanAttributes.GEN_AI_LATENCY_TIME_IN_MODEL_PREFILL,
500
+ prefill_time)
501
+ span.set_attribute(
502
+ SpanAttributes.GEN_AI_LATENCY_TIME_IN_MODEL_DECODE,
503
+ decode_time)
504
+ span.set_attribute(
505
+ SpanAttributes.GEN_AI_LATENCY_TIME_IN_MODEL_INFERENCE,
506
+ inference_time)
507
+
508
+ # meta
509
+ span.set_attribute(SpanAttributes.GEN_AI_REQUEST_ID,
510
+ req_state.request_id)
511
+ if req_state.top_p:
512
+ span.set_attribute(SpanAttributes.GEN_AI_REQUEST_TOP_P,
513
+ req_state.top_p)
514
+ if req_state.max_tokens_param:
515
+ span.set_attribute(SpanAttributes.GEN_AI_REQUEST_MAX_TOKENS,
516
+ req_state.max_tokens_param)
517
+ if req_state.temperature:
518
+ span.set_attribute(SpanAttributes.GEN_AI_REQUEST_TEMPERATURE,
519
+ req_state.temperature)
520
+ if req_state.n:
521
+ span.set_attribute(SpanAttributes.GEN_AI_REQUEST_N,
522
+ req_state.n)
523
+
524
def _update_stats_from_output(self, req_state: RequestState,
525
engine_core_output: EngineCoreOutput,
526
engine_core_timestamp: Optional[float],