@@ -1463,6 +1463,17 @@ def set_mamba_track_indices_from_reqs(batch):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _compute_chunked_req_next_prompt_token(
|
||||||
|
chunked_req: Optional[Req],
|
||||||
|
) -> Optional[int]:
|
||||||
|
if chunked_req is None:
|
||||||
|
return None
|
||||||
|
fill_len = len(chunked_req.fill_ids)
|
||||||
|
if fill_len >= len(chunked_req.origin_input_ids):
|
||||||
|
return None
|
||||||
|
return int(chunked_req.origin_input_ids[fill_len])
|
||||||
|
|
||||||
|
|
||||||
@dataclasses.dataclass
|
@dataclasses.dataclass
|
||||||
class ScheduleBatch(ScheduleBatchDisaggregationDecodeMixin):
|
class ScheduleBatch(ScheduleBatchDisaggregationDecodeMixin):
|
||||||
"""Store all information of a batch on the scheduler."""
|
"""Store all information of a batch on the scheduler."""
|
||||||
@@ -1494,6 +1505,7 @@ class ScheduleBatch(ScheduleBatchDisaggregationDecodeMixin):
|
|||||||
|
|
||||||
# For chunked prefill in PP
|
# For chunked prefill in PP
|
||||||
chunked_req: Optional[Req] = None
|
chunked_req: Optional[Req] = None
|
||||||
|
chunked_req_next_prompt_token: Optional[int] = None
|
||||||
contains_last_prefill_chunk: bool = True
|
contains_last_prefill_chunk: bool = True
|
||||||
|
|
||||||
# For DP attention
|
# For DP attention
|
||||||
@@ -1660,6 +1672,9 @@ class ScheduleBatch(ScheduleBatchDisaggregationDecodeMixin):
|
|||||||
return_hidden_states=any(req.return_hidden_states for req in reqs),
|
return_hidden_states=any(req.return_hidden_states for req in reqs),
|
||||||
is_prefill_only=all(req.is_prefill_only for req in reqs),
|
is_prefill_only=all(req.is_prefill_only for req in reqs),
|
||||||
chunked_req=chunked_req,
|
chunked_req=chunked_req,
|
||||||
|
chunked_req_next_prompt_token=_compute_chunked_req_next_prompt_token(
|
||||||
|
chunked_req
|
||||||
|
),
|
||||||
dllm_config=dllm_config,
|
dllm_config=dllm_config,
|
||||||
)
|
)
|
||||||
return batch
|
return batch
|
||||||
|
|||||||
@@ -66,10 +66,27 @@ def apply_eagle_prefill_input_rotation(
|
|||||||
seg_ends = extend_lens.cumsum(0) - 1
|
seg_ends = extend_lens.cumsum(0) - 1
|
||||||
rotated = torch.empty_like(batch.input_ids)
|
rotated = torch.empty_like(batch.input_ids)
|
||||||
rotated[:-1] = batch.input_ids[1:]
|
rotated[:-1] = batch.input_ids[1:]
|
||||||
|
# TODO: chunked-prefill chain divergence at non-final-chunk seg end; fix per PR #26329.
|
||||||
rotated[seg_ends] = next_token_ids.to(batch.input_ids.dtype)
|
rotated[seg_ends] = next_token_ids.to(batch.input_ids.dtype)
|
||||||
batch.input_ids = rotated
|
batch.input_ids = rotated
|
||||||
|
|
||||||
|
|
||||||
|
def _eagle_prefill_tail_tokens(
|
||||||
|
batch: ScheduleBatch, next_token_ids: torch.Tensor
|
||||||
|
) -> torch.Tensor:
|
||||||
|
"""Per-seq tail token for EAGLE prefill rotation; uses next prompt token for
|
||||||
|
non-final chunks (chunked-prefill chain consistency, see PR #26329)."""
|
||||||
|
tail_tokens = next_token_ids.to(batch.input_ids.dtype)
|
||||||
|
next_prompt_token = batch.chunked_req_next_prompt_token
|
||||||
|
if next_prompt_token is not None:
|
||||||
|
for i, r in enumerate(batch.reqs):
|
||||||
|
if r is batch.chunked_req:
|
||||||
|
tail_tokens = tail_tokens.clone()
|
||||||
|
tail_tokens[i] = next_prompt_token
|
||||||
|
break
|
||||||
|
return tail_tokens
|
||||||
|
|
||||||
|
|
||||||
def organize_draft_results(
|
def organize_draft_results(
|
||||||
score_list: List[torch.Tensor],
|
score_list: List[torch.Tensor],
|
||||||
token_list: List[torch.Tensor],
|
token_list: List[torch.Tensor],
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ from sglang.srt.speculative.eagle_info_v2 import (
|
|||||||
)
|
)
|
||||||
from sglang.srt.speculative.eagle_utils import (
|
from sglang.srt.speculative.eagle_utils import (
|
||||||
TreeMaskMode,
|
TreeMaskMode,
|
||||||
|
_eagle_prefill_tail_tokens,
|
||||||
build_tree_kernel_efficient,
|
build_tree_kernel_efficient,
|
||||||
per_step_draft_out_cache_loc,
|
per_step_draft_out_cache_loc,
|
||||||
)
|
)
|
||||||
@@ -579,11 +580,13 @@ class EagleDraftWorker(BaseDraftWorker):
|
|||||||
"""
|
"""
|
||||||
# Construct input_ids
|
# Construct input_ids
|
||||||
if not batch.forward_mode.is_idle():
|
if not batch.forward_mode.is_idle():
|
||||||
|
# Chunked-prefill-aware tail tokens (see PR #26329).
|
||||||
|
tail_tokens = _eagle_prefill_tail_tokens(batch, next_token_ids)
|
||||||
pt = 0
|
pt = 0
|
||||||
for i, extend_len in enumerate(batch.extend_lens):
|
for i, extend_len in enumerate(batch.extend_lens):
|
||||||
input_ids = batch.input_ids[pt : pt + extend_len]
|
input_ids = batch.input_ids[pt : pt + extend_len]
|
||||||
batch.input_ids[pt : pt + extend_len] = torch.cat(
|
batch.input_ids[pt : pt + extend_len] = torch.cat(
|
||||||
(input_ids[1:], next_token_ids[i].reshape(1))
|
(input_ids[1:], tail_tokens[i].reshape(1))
|
||||||
)
|
)
|
||||||
pt += extend_len
|
pt += extend_len
|
||||||
|
|
||||||
|
|||||||
@@ -410,6 +410,7 @@ class MultiLayerEagleDraftWorker(BaseDraftWorker):
|
|||||||
forward_batch = ForwardBatch.init_new(batch, self.draft_runner_list[0])
|
forward_batch = ForwardBatch.init_new(batch, self.draft_runner_list[0])
|
||||||
|
|
||||||
# Construct input_ids
|
# Construct input_ids
|
||||||
|
# TODO: same chunked-prefill chain divergence as PR #26329.
|
||||||
if not batch.forward_mode.is_idle():
|
if not batch.forward_mode.is_idle():
|
||||||
rotate_input_ids_triton(
|
rotate_input_ids_triton(
|
||||||
forward_batch.input_ids,
|
forward_batch.input_ids,
|
||||||
|
|||||||
Reference in New Issue
Block a user