[Spec] Support logprobs with DSpark speculative decoding (#34696)
Co-authored-by: QAQEthan <QAQEthan@users.noreply.github.com>
This commit is contained in:
@@ -2510,11 +2510,7 @@ class Scheduler(
|
|||||||
self._maybe_namespace_elastic_radix_cache(req)
|
self._maybe_namespace_elastic_radix_cache(req)
|
||||||
|
|
||||||
if self.spec_algorithm.is_dflash_family():
|
if self.spec_algorithm.is_dflash_family():
|
||||||
error_msg = (
|
error_msg = validate_dflash_request(req, self.enable_overlap)
|
||||||
"DSpark speculative decoding does not support return_logprob yet."
|
|
||||||
if self.spec_algorithm.is_dspark() and req.return_logprob
|
|
||||||
else validate_dflash_request(req, self.enable_overlap)
|
|
||||||
)
|
|
||||||
if error_msg is not None:
|
if error_msg is not None:
|
||||||
req.set_finish_with_abort(error_msg)
|
req.set_finish_with_abort(error_msg)
|
||||||
self.init_req_max_new_tokens(req)
|
self.init_req_max_new_tokens(req)
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ from sglang.kernels.ops.attention.dsv4.unified_kv_kernels.env_gate import (
|
|||||||
from sglang.srt.configs.hybrid_arch import mambaish_config
|
from sglang.srt.configs.hybrid_arch import mambaish_config
|
||||||
from sglang.srt.distributed.parallel_state_wrapper import ParallelState
|
from sglang.srt.distributed.parallel_state_wrapper import ParallelState
|
||||||
from sglang.srt.environ import envs
|
from sglang.srt.environ import envs
|
||||||
|
from sglang.srt.layers.logprob_processor import compute_spec_v2_logprobs
|
||||||
from sglang.srt.managers.schedule_batch import ScheduleBatch
|
from sglang.srt.managers.schedule_batch import ScheduleBatch
|
||||||
from sglang.srt.managers.scheduler import GenerationBatchResult
|
from sglang.srt.managers.scheduler import GenerationBatchResult
|
||||||
from sglang.srt.managers.tp_worker import TpModelWorker
|
from sglang.srt.managers.tp_worker import TpModelWorker
|
||||||
@@ -405,17 +406,25 @@ class DSparkWorkerV2(BaseSpecWorker):
|
|||||||
def note_request_finished(self, *, rid: str, natural_stop: bool) -> None:
|
def note_request_finished(self, *, rid: str, natural_stop: bool) -> None:
|
||||||
self._observers.note_request_finished(rid=rid, natural_stop=natural_stop)
|
self._observers.note_request_finished(rid=rid, natural_stop=natural_stop)
|
||||||
|
|
||||||
|
def _linear_accept_indices(self, bs: int) -> torch.Tensor:
|
||||||
|
num_indices = bs * self.verify_num_draft_tokens
|
||||||
|
if (
|
||||||
|
self._linear_accept_index_cache is None
|
||||||
|
or self._linear_accept_index_cache.numel() < num_indices
|
||||||
|
):
|
||||||
|
self._linear_accept_index_cache = torch.arange(
|
||||||
|
num_indices, dtype=torch.int64, device=self.device
|
||||||
|
)
|
||||||
|
return self._linear_accept_index_cache[:num_indices].view(
|
||||||
|
bs, self.verify_num_draft_tokens
|
||||||
|
)
|
||||||
|
|
||||||
def forward_batch_generation(
|
def forward_batch_generation(
|
||||||
self,
|
self,
|
||||||
batch: ScheduleBatch,
|
batch: ScheduleBatch,
|
||||||
on_publish=None,
|
on_publish=None,
|
||||||
grammar_barrier=None,
|
grammar_barrier=None,
|
||||||
) -> GenerationBatchResult:
|
) -> GenerationBatchResult:
|
||||||
if getattr(batch, "return_logprob", False):
|
|
||||||
raise ValueError(
|
|
||||||
"DSpark speculative decoding does not support return_logprob yet."
|
|
||||||
)
|
|
||||||
|
|
||||||
if batch.forward_mode.is_extend() or batch.is_extend_in_batch:
|
if batch.forward_mode.is_extend() or batch.is_extend_in_batch:
|
||||||
self._verify_planner.note_non_decode_step()
|
self._verify_planner.note_non_decode_step()
|
||||||
self._observers.note_prefill_step()
|
self._observers.note_prefill_step()
|
||||||
@@ -708,6 +717,15 @@ class DSparkWorkerV2(BaseSpecWorker):
|
|||||||
prefix_lens=prefix_lens,
|
prefix_lens=prefix_lens,
|
||||||
draft_tokens=draft_tokens,
|
draft_tokens=draft_tokens,
|
||||||
)
|
)
|
||||||
|
if batch.return_logprob:
|
||||||
|
compute_spec_v2_logprobs(
|
||||||
|
batch,
|
||||||
|
logits_output,
|
||||||
|
accept.out_tokens.reshape(-1),
|
||||||
|
self._linear_accept_indices(bs),
|
||||||
|
self.verify_num_draft_tokens - 1,
|
||||||
|
)
|
||||||
|
|
||||||
if on_publish is not None:
|
if on_publish is not None:
|
||||||
if confidence is not None:
|
if confidence is not None:
|
||||||
on_publish(accept.new_seq_lens, confidence=confidence)
|
on_publish(accept.new_seq_lens, confidence=confidence)
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ from sglang.test.kits.basic_scheduler_stress_kit import BasicSchedulerStressMixi
|
|||||||
from sglang.test.kits.eval_accuracy_kit import GSM8KMixin
|
from sglang.test.kits.eval_accuracy_kit import GSM8KMixin
|
||||||
from sglang.test.kits.fwd_occupancy_kit import FwdOccupancyMixin
|
from sglang.test.kits.fwd_occupancy_kit import FwdOccupancyMixin
|
||||||
from sglang.test.kits.json_constrained_kit import JSONConstrainedMixin
|
from sglang.test.kits.json_constrained_kit import JSONConstrainedMixin
|
||||||
from sglang.test.kits.spec_server_kits import SpecGrammarKit
|
from sglang.test.kits.spec_server_kits import SpecGrammarKit, SpecLogprobKit
|
||||||
from sglang.test.test_utils import (
|
from sglang.test.test_utils import (
|
||||||
DEFAULT_TIMEOUT_FOR_SERVER_LAUNCH,
|
DEFAULT_TIMEOUT_FOR_SERVER_LAUNCH,
|
||||||
DEFAULT_URL_FOR_TEST,
|
DEFAULT_URL_FOR_TEST,
|
||||||
@@ -38,6 +38,7 @@ class TestBasicSanityDSpark(
|
|||||||
GSM8KMixin,
|
GSM8KMixin,
|
||||||
JSONConstrainedMixin,
|
JSONConstrainedMixin,
|
||||||
SpecGrammarKit,
|
SpecGrammarKit,
|
||||||
|
SpecLogprobKit,
|
||||||
CustomTestCase,
|
CustomTestCase,
|
||||||
):
|
):
|
||||||
served_model_name = TARGET_MODEL
|
served_model_name = TARGET_MODEL
|
||||||
@@ -88,10 +89,6 @@ class TestBasicSanityDSpark(
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
@unittest.skip("DSPARK rejects return_logprob at admission")
|
|
||||||
def test_grammar_logprob_count_matches_completion_tokens(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def tearDownClass(cls):
|
def tearDownClass(cls):
|
||||||
if cls.process is not None:
|
if cls.process is not None:
|
||||||
|
|||||||
Reference in New Issue
Block a user