Support return_logprob for spec v2 (overlap safe) (#19801)
Co-authored-by: Ratish1 <ratish1501@gmail.com> Co-authored-by: Ratish1 <formula733@gmail.com> Co-authored-by: hnyls2002 <lsyincs@gmail.com>
This commit is contained in:
@@ -17,10 +17,12 @@ from sglang.srt.layers.attention.trtllm_mla_backend import (
|
||||
TRTLLMMLAMultiStepDraftBackend,
|
||||
)
|
||||
from sglang.srt.layers.dp_attention import get_attention_tp_group
|
||||
from sglang.srt.layers.logits_processor import LogitsProcessorOutput
|
||||
from sglang.srt.layers.moe.utils import (
|
||||
speculative_moe_a2a_backend_context,
|
||||
speculative_moe_backend_context,
|
||||
)
|
||||
from sglang.srt.layers.utils.logprob import get_token_ids_logprobs, get_top_logprobs
|
||||
from sglang.srt.managers.io_struct import UpdateWeightsFromTensorReqInput
|
||||
from sglang.srt.managers.schedule_batch import ModelWorkerBatch
|
||||
from sglang.srt.managers.scheduler import GenerationBatchResult
|
||||
@@ -834,6 +836,9 @@ class EAGLEWorkerV2(BaseSpecWorker):
|
||||
else:
|
||||
verified_id = torch.empty((0,), device=self.device, dtype=torch.int32)
|
||||
|
||||
if batch.return_logprob and not batch.forward_mode.is_idle():
|
||||
self._compute_spec_v2_logprobs(batch, logits_output, predict, accept_index)
|
||||
|
||||
# Construct the next draft input
|
||||
next_draft_input = EagleDraftInput(
|
||||
verified_id=verified_id,
|
||||
@@ -849,6 +854,72 @@ class EAGLEWorkerV2(BaseSpecWorker):
|
||||
accept_lens=accept_length,
|
||||
)
|
||||
|
||||
def _compute_spec_v2_logprobs(
|
||||
self,
|
||||
batch: ModelWorkerBatch,
|
||||
logits_output: LogitsProcessorOutput,
|
||||
predict: torch.Tensor,
|
||||
accept_index: torch.Tensor,
|
||||
):
|
||||
"""Compute logprobs for accepted tokens on GPU in the forward stream.
|
||||
|
||||
Stores results in logits_output fields so they flow through copy_to_cpu().
|
||||
"""
|
||||
|
||||
bs = len(batch.seq_lens)
|
||||
max_accept = self.speculative_num_steps + 1
|
||||
device = predict.device
|
||||
|
||||
flat_accept_idx = accept_index.long().reshape(-1)
|
||||
gathered_logits = logits_output.next_token_logits[flat_accept_idx]
|
||||
|
||||
if (
|
||||
batch.sampling_info.is_all_greedy
|
||||
or envs.SGLANG_RETURN_ORIGINAL_LOGPROB.get()
|
||||
):
|
||||
gathered_logprobs = torch.nn.functional.log_softmax(gathered_logits, dim=-1)
|
||||
else:
|
||||
temperatures = torch.repeat_interleave(
|
||||
batch.sampling_info.temperatures,
|
||||
max_accept,
|
||||
dim=0,
|
||||
)
|
||||
gathered_logprobs = torch.nn.functional.log_softmax(
|
||||
gathered_logits / temperatures, dim=-1
|
||||
)
|
||||
gathered_logprobs.clamp_(min=torch.finfo(gathered_logprobs.dtype).min)
|
||||
|
||||
accepted_token_ids = predict[flat_accept_idx]
|
||||
token_logprobs = gathered_logprobs[
|
||||
torch.arange(bs * max_accept, device=device),
|
||||
accepted_token_ids.long(),
|
||||
]
|
||||
logits_output.next_token_logprobs = token_logprobs.reshape(bs, max_accept)
|
||||
|
||||
if batch.top_logprobs_nums and any(x > 0 for x in batch.top_logprobs_nums):
|
||||
top_logprobs_nums_expanded = [
|
||||
num for num in batch.top_logprobs_nums for _ in range(max_accept)
|
||||
]
|
||||
(
|
||||
logits_output.next_token_top_logprobs_val,
|
||||
logits_output.next_token_top_logprobs_idx,
|
||||
) = get_top_logprobs(
|
||||
gathered_logprobs, top_logprobs_nums_expanded, no_copy_to_cpu=True
|
||||
)
|
||||
|
||||
if batch.token_ids_logprobs and any(
|
||||
x is not None for x in batch.token_ids_logprobs
|
||||
):
|
||||
token_ids_logprobs_expanded = [
|
||||
ids for ids in batch.token_ids_logprobs for _ in range(max_accept)
|
||||
]
|
||||
(
|
||||
logits_output.next_token_token_ids_logprobs_val,
|
||||
logits_output.next_token_token_ids_logprobs_idx,
|
||||
) = get_token_ids_logprobs(
|
||||
gathered_logprobs, token_ids_logprobs_expanded, no_copy_to_cpu=True
|
||||
)
|
||||
|
||||
def _mamba_verify_update(
|
||||
self,
|
||||
batch: ModelWorkerBatch,
|
||||
|
||||
Reference in New Issue
Block a user