[Spec] Move accept_tokens off EagleDraftInput; pass via method arg (#24735)
This commit is contained in:
@@ -213,7 +213,6 @@ class DFlashVerifyInput(SpecInput):
|
|||||||
last_loc,
|
last_loc,
|
||||||
len(batch.input_ids),
|
len(batch.input_ids),
|
||||||
)
|
)
|
||||||
self.last_loc = last_loc
|
|
||||||
|
|
||||||
bs = batch.batch_size()
|
bs = batch.batch_size()
|
||||||
assign_req_to_token_pool_func(
|
assign_req_to_token_pool_func(
|
||||||
|
|||||||
@@ -140,7 +140,6 @@ class EagleVerifyInput(SpecInput, EagleVerifyInputV2Mixin):
|
|||||||
last_loc,
|
last_loc,
|
||||||
len(batch.input_ids),
|
len(batch.input_ids),
|
||||||
)
|
)
|
||||||
self.last_loc = last_loc
|
|
||||||
|
|
||||||
bs = batch.batch_size()
|
bs = batch.batch_size()
|
||||||
assign_req_to_token_pool_func(
|
assign_req_to_token_pool_func(
|
||||||
@@ -241,23 +240,18 @@ class EagleVerifyInput(SpecInput, EagleVerifyInputV2Mixin):
|
|||||||
accepted token logits.
|
accepted token logits.
|
||||||
"""
|
"""
|
||||||
if batch.forward_mode.is_idle():
|
if batch.forward_mode.is_idle():
|
||||||
return EagleVerifyOutput(
|
next_draft_input = EagleDraftInput.create_idle_input(
|
||||||
draft_input=EagleDraftInput.create_idle_input(
|
device=batch.device,
|
||||||
device=batch.device,
|
hidden_size=batch.model_config.spec_hidden_size,
|
||||||
hidden_size=batch.model_config.spec_hidden_size,
|
dtype=batch.model_config.dtype,
|
||||||
dtype=batch.model_config.dtype,
|
topk=self.topk,
|
||||||
topk=self.topk,
|
capture_hidden_mode=CaptureHiddenMode.LAST,
|
||||||
capture_hidden_mode=CaptureHiddenMode.LAST,
|
)
|
||||||
),
|
return EagleVerifyOutput.create_idle(
|
||||||
|
next_draft_input=next_draft_input,
|
||||||
logits_output=logits_output,
|
logits_output=logits_output,
|
||||||
accept_tokens=torch.empty(0, dtype=torch.long, device=batch.device),
|
device=batch.device,
|
||||||
num_accepted_drafts_per_req_cpu=[],
|
spec_steps=self.spec_steps,
|
||||||
accepted_indices=torch.full(
|
|
||||||
(0, self.spec_steps + 1),
|
|
||||||
-1,
|
|
||||||
dtype=torch.int32,
|
|
||||||
device=batch.device,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
bs = self.retrieve_index.shape[0]
|
bs = self.retrieve_index.shape[0]
|
||||||
@@ -551,23 +545,22 @@ class EagleVerifyInput(SpecInput, EagleVerifyInputV2Mixin):
|
|||||||
batch.seq_lens.add_(num_accepted_drafts + 1)
|
batch.seq_lens.add_(num_accepted_drafts + 1)
|
||||||
batch.seq_lens_cpu.add_(num_accepted_tokens_cpu)
|
batch.seq_lens_cpu.add_(num_accepted_tokens_cpu)
|
||||||
|
|
||||||
draft_input = EagleDraftInput(
|
next_draft_input = EagleDraftInput(
|
||||||
hidden_states=batch.spec_info.hidden_states[accept_index],
|
hidden_states=batch.spec_info.hidden_states[accept_index],
|
||||||
accept_tokens=accept_tokens,
|
|
||||||
num_accepted_drafts=num_accepted_drafts,
|
num_accepted_drafts=num_accepted_drafts,
|
||||||
num_accepted_tokens=num_accepted_drafts + 1,
|
num_accepted_tokens=num_accepted_drafts + 1,
|
||||||
num_accepted_drafts_cpu=num_accepted_drafts_list,
|
|
||||||
num_accepted_tokens_cpu=num_accepted_tokens_list,
|
num_accepted_tokens_cpu=num_accepted_tokens_list,
|
||||||
seq_lens_for_draft_extend=batch.seq_lens,
|
|
||||||
seq_lens_for_draft_extend_cpu=batch.seq_lens_cpu,
|
|
||||||
req_pool_indices_for_draft_extend=batch.req_pool_indices,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
return EagleVerifyOutput(
|
return EagleVerifyOutput(
|
||||||
draft_input=draft_input,
|
next_draft_input=next_draft_input,
|
||||||
logits_output=logits_output,
|
logits_output=logits_output,
|
||||||
accept_tokens=accept_tokens,
|
accept_tokens=accept_tokens,
|
||||||
num_accepted_drafts_per_req_cpu=draft_input.num_accepted_drafts_cpu,
|
unfinished_accept_tokens=accept_tokens,
|
||||||
|
seq_lens_for_draft_extend=batch.seq_lens,
|
||||||
|
seq_lens_for_draft_extend_cpu=batch.seq_lens_cpu,
|
||||||
|
req_pool_indices_for_draft_extend=batch.req_pool_indices,
|
||||||
|
num_accepted_drafts_per_req_cpu=num_accepted_drafts_list,
|
||||||
accepted_indices=accept_index,
|
accepted_indices=accept_index,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
@@ -621,23 +614,36 @@ class EagleVerifyInput(SpecInput, EagleVerifyInputV2Mixin):
|
|||||||
unfinished_num_accepted_drafts = num_accepted_drafts[
|
unfinished_num_accepted_drafts = num_accepted_drafts[
|
||||||
unfinished_index_device
|
unfinished_index_device
|
||||||
]
|
]
|
||||||
draft_input = EagleDraftInput(
|
unfinished_accept_tokens = predict[unfinished_accept_index]
|
||||||
|
seq_lens_for_draft_extend = batch.seq_lens[unfinished_index_device]
|
||||||
|
seq_lens_for_draft_extend_cpu = batch.seq_lens_cpu[unfinished_index]
|
||||||
|
req_pool_indices_for_draft_extend = batch.req_pool_indices[
|
||||||
|
unfinished_index_device
|
||||||
|
]
|
||||||
|
next_draft_input = EagleDraftInput(
|
||||||
hidden_states=batch.spec_info.hidden_states[
|
hidden_states=batch.spec_info.hidden_states[
|
||||||
unfinished_accept_index
|
unfinished_accept_index
|
||||||
],
|
],
|
||||||
accept_tokens=predict[unfinished_accept_index],
|
|
||||||
num_accepted_drafts_cpu=draft_input_num_accepted_drafts_cpu,
|
|
||||||
num_accepted_tokens_cpu=draft_input_num_accepted_tokens_cpu,
|
num_accepted_tokens_cpu=draft_input_num_accepted_tokens_cpu,
|
||||||
num_accepted_drafts=unfinished_num_accepted_drafts,
|
num_accepted_drafts=unfinished_num_accepted_drafts,
|
||||||
num_accepted_tokens=unfinished_num_accepted_drafts + 1,
|
num_accepted_tokens=unfinished_num_accepted_drafts + 1,
|
||||||
seq_lens_for_draft_extend=batch.seq_lens[unfinished_index_device],
|
|
||||||
seq_lens_for_draft_extend_cpu=batch.seq_lens_cpu[unfinished_index],
|
|
||||||
req_pool_indices_for_draft_extend=batch.req_pool_indices[
|
|
||||||
unfinished_index_device
|
|
||||||
],
|
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
draft_input = EagleDraftInput.create_idle_input(
|
unfinished_accept_tokens = torch.empty(
|
||||||
|
(0,), dtype=accept_tokens.dtype, device=accept_tokens.device
|
||||||
|
)
|
||||||
|
seq_lens_for_draft_extend = torch.empty(
|
||||||
|
(0,), dtype=batch.seq_lens.dtype, device=batch.seq_lens.device
|
||||||
|
)
|
||||||
|
seq_lens_for_draft_extend_cpu = torch.empty(
|
||||||
|
(0,), dtype=batch.seq_lens_cpu.dtype
|
||||||
|
)
|
||||||
|
req_pool_indices_for_draft_extend = torch.empty(
|
||||||
|
(0,),
|
||||||
|
dtype=batch.req_pool_indices.dtype,
|
||||||
|
device=batch.req_pool_indices.device,
|
||||||
|
)
|
||||||
|
next_draft_input = EagleDraftInput.create_idle_input(
|
||||||
device=batch.device,
|
device=batch.device,
|
||||||
hidden_size=batch.model_config.spec_hidden_size,
|
hidden_size=batch.model_config.spec_hidden_size,
|
||||||
dtype=batch.model_config.dtype,
|
dtype=batch.model_config.dtype,
|
||||||
@@ -646,9 +652,13 @@ class EagleVerifyInput(SpecInput, EagleVerifyInputV2Mixin):
|
|||||||
)
|
)
|
||||||
|
|
||||||
return EagleVerifyOutput(
|
return EagleVerifyOutput(
|
||||||
draft_input=draft_input,
|
next_draft_input=next_draft_input,
|
||||||
logits_output=logits_output,
|
logits_output=logits_output,
|
||||||
accept_tokens=accept_tokens,
|
accept_tokens=accept_tokens,
|
||||||
|
unfinished_accept_tokens=unfinished_accept_tokens,
|
||||||
|
seq_lens_for_draft_extend=seq_lens_for_draft_extend,
|
||||||
|
seq_lens_for_draft_extend_cpu=seq_lens_for_draft_extend_cpu,
|
||||||
|
req_pool_indices_for_draft_extend=req_pool_indices_for_draft_extend,
|
||||||
num_accepted_drafts_per_req_cpu=num_accepted_drafts_list,
|
num_accepted_drafts_per_req_cpu=num_accepted_drafts_list,
|
||||||
accepted_indices=accept_index,
|
accepted_indices=accept_index,
|
||||||
)
|
)
|
||||||
@@ -660,7 +670,10 @@ class EagleDraftInput(SpecInput, EagleDraftInputV2Mixin):
|
|||||||
# shape: (b, topk)
|
# shape: (b, topk)
|
||||||
topk_p: torch.Tensor = None
|
topk_p: torch.Tensor = None
|
||||||
topk_index: torch.Tensor = None
|
topk_index: torch.Tensor = None
|
||||||
# shape: (b, hidden_size)
|
# shape: (b, hidden_size) when consumed by `draft` forward (one hidden per req);
|
||||||
|
# shape: (total_accepted, hidden_size) when consumed by `draft_extend` forward
|
||||||
|
# (one hidden per accepted token). Workers maintain this invariant locally;
|
||||||
|
# there is no type-level guard. Don't add new readers without checking phase.
|
||||||
hidden_states: torch.Tensor = None
|
hidden_states: torch.Tensor = None
|
||||||
capture_hidden_mode: CaptureHiddenMode = CaptureHiddenMode.FULL
|
capture_hidden_mode: CaptureHiddenMode = CaptureHiddenMode.FULL
|
||||||
|
|
||||||
@@ -670,16 +683,10 @@ class EagleDraftInput(SpecInput, EagleDraftInputV2Mixin):
|
|||||||
# `num_accepted_tokens = num_accepted_drafts + 1` (per-req, one bonus per req).
|
# `num_accepted_tokens = num_accepted_drafts + 1` (per-req, one bonus per req).
|
||||||
# Storing both avoids repeated `+ 1` at every consumer (attn backends, kernels).
|
# Storing both avoids repeated `+ 1` at every consumer (attn backends, kernels).
|
||||||
bonus_tokens: torch.Tensor = None
|
bonus_tokens: torch.Tensor = None
|
||||||
# Flat accepted-token tensor for draft-extend, shape `[sum_accepted]`.
|
|
||||||
# Set right after verify and consumed by `prepare_extend_after_decode` as
|
|
||||||
# the extend batch's `input_ids`. Dead after that method returns.
|
|
||||||
# TODO: drop this field and pass `accept_tokens` directly to
|
|
||||||
# `prepare_extend_after_decode` as a method arg. Its lifetime is bounded
|
|
||||||
# by verify -> prepare_extend, no need to live on the dataclass.
|
|
||||||
accept_tokens: torch.Tensor = None
|
|
||||||
num_accepted_drafts: torch.Tensor = None
|
num_accepted_drafts: torch.Tensor = None
|
||||||
num_accepted_tokens: torch.Tensor = None
|
num_accepted_tokens: torch.Tensor = None
|
||||||
num_accepted_drafts_cpu: List[int] = None
|
# Read by attention backends during draft-extend forward; kept on the
|
||||||
|
# dataclass because the backends access it via `forward_batch.spec_info`.
|
||||||
num_accepted_tokens_cpu: List[int] = None
|
num_accepted_tokens_cpu: List[int] = None
|
||||||
|
|
||||||
# Inputs for the attention backends
|
# Inputs for the attention backends
|
||||||
@@ -691,12 +698,6 @@ class EagleDraftInput(SpecInput, EagleDraftInputV2Mixin):
|
|||||||
num_tokens_per_req: int = -1
|
num_tokens_per_req: int = -1
|
||||||
num_tokens_for_logprob_per_req: int = -1
|
num_tokens_for_logprob_per_req: int = -1
|
||||||
|
|
||||||
# Inputs for draft extend
|
|
||||||
# shape: (b,)
|
|
||||||
seq_lens_for_draft_extend: torch.Tensor = None
|
|
||||||
seq_lens_for_draft_extend_cpu: torch.Tensor = None
|
|
||||||
req_pool_indices_for_draft_extend: torch.Tensor = None
|
|
||||||
|
|
||||||
# Inputs for V2 overlap worker
|
# Inputs for V2 overlap worker
|
||||||
future_indices: Optional[FutureIndices] = None
|
future_indices: Optional[FutureIndices] = None
|
||||||
new_seq_lens: Optional[torch.Tensor] = None
|
new_seq_lens: Optional[torch.Tensor] = None
|
||||||
@@ -735,7 +736,6 @@ class EagleDraftInput(SpecInput, EagleDraftInputV2Mixin):
|
|||||||
):
|
):
|
||||||
return cls(
|
return cls(
|
||||||
bonus_tokens=torch.empty((0,), device=device, dtype=torch.int32),
|
bonus_tokens=torch.empty((0,), device=device, dtype=torch.int32),
|
||||||
accept_tokens=torch.empty((0,), device=device, dtype=torch.int32),
|
|
||||||
hidden_states=torch.empty((0, hidden_size), device=device, dtype=dtype),
|
hidden_states=torch.empty((0, hidden_size), device=device, dtype=dtype),
|
||||||
topk_p=torch.empty((0, topk), device=device, dtype=torch.float32),
|
topk_p=torch.empty((0, topk), device=device, dtype=torch.float32),
|
||||||
topk_index=torch.empty((0, topk), device=device, dtype=torch.int64),
|
topk_index=torch.empty((0, topk), device=device, dtype=torch.int64),
|
||||||
@@ -743,29 +743,29 @@ class EagleDraftInput(SpecInput, EagleDraftInputV2Mixin):
|
|||||||
new_seq_lens=torch.empty((0,), device=device, dtype=torch.int32),
|
new_seq_lens=torch.empty((0,), device=device, dtype=torch.int32),
|
||||||
num_accepted_drafts=torch.empty((0,), device=device, dtype=torch.int32),
|
num_accepted_drafts=torch.empty((0,), device=device, dtype=torch.int32),
|
||||||
num_accepted_tokens=torch.empty((0,), device=device, dtype=torch.int32),
|
num_accepted_tokens=torch.empty((0,), device=device, dtype=torch.int32),
|
||||||
num_accepted_drafts_cpu=[],
|
|
||||||
num_accepted_tokens_cpu=[],
|
num_accepted_tokens_cpu=[],
|
||||||
)
|
)
|
||||||
|
|
||||||
def prepare_extend_after_decode(
|
def prepare_extend_after_decode(
|
||||||
self,
|
self,
|
||||||
batch: ScheduleBatch,
|
batch: ScheduleBatch,
|
||||||
|
verify_output: "EagleVerifyOutput",
|
||||||
speculative_num_steps: int,
|
speculative_num_steps: int,
|
||||||
):
|
):
|
||||||
|
|
||||||
if batch.forward_mode.is_idle():
|
if batch.forward_mode.is_idle():
|
||||||
return
|
return
|
||||||
|
|
||||||
# `self.accept_tokens` is the flat accepted-token tensor set by
|
# All transient verify->extend handoff state is read off `verify_output`,
|
||||||
# `EagleVerifyInput.verify`; use it as the extend batch's `input_ids`.
|
# not from `self`. The kernel below populates `self.bonus_tokens`
|
||||||
# The kernel below populates `self.bonus_tokens` ([bs] per-req) for
|
# ([bs] per-req) for the next decode round; that is the only state on
|
||||||
# the next decode round.
|
# `self` that survives past this method.
|
||||||
batch.input_ids = self.accept_tokens
|
batch.input_ids = verify_output.unfinished_accept_tokens
|
||||||
batch.extend_lens = batch.spec_info.num_accepted_tokens_cpu
|
batch.extend_lens = batch.spec_info.num_accepted_tokens_cpu
|
||||||
batch.extend_num_tokens = sum(batch.extend_lens)
|
batch.extend_num_tokens = sum(batch.extend_lens)
|
||||||
batch.seq_lens = batch.spec_info.seq_lens_for_draft_extend
|
batch.seq_lens = verify_output.seq_lens_for_draft_extend
|
||||||
batch.seq_lens_cpu = batch.spec_info.seq_lens_for_draft_extend_cpu
|
batch.seq_lens_cpu = verify_output.seq_lens_for_draft_extend_cpu
|
||||||
batch.req_pool_indices = batch.spec_info.req_pool_indices_for_draft_extend
|
batch.req_pool_indices = verify_output.req_pool_indices_for_draft_extend
|
||||||
batch.return_logprob = False
|
batch.return_logprob = False
|
||||||
batch.return_hidden_states = False
|
batch.return_hidden_states = False
|
||||||
|
|
||||||
@@ -873,13 +873,53 @@ class EagleDraftInput(SpecInput, EagleDraftInputV2Mixin):
|
|||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class EagleVerifyOutput:
|
class EagleVerifyOutput:
|
||||||
# Draft input batch
|
# Next iter's persistent draft state, ready to be installed as `batch.spec_info`.
|
||||||
draft_input: EagleDraftInput
|
next_draft_input: EagleDraftInput
|
||||||
# Logit outputs from target worker
|
# Logit outputs from target worker.
|
||||||
logits_output: LogitsProcessorOutput
|
logits_output: LogitsProcessorOutput
|
||||||
# Accepted token ids including the bonus token (flat, [sum_accepted])
|
# All accepted tokens flat across all reqs incl. those that finished this
|
||||||
|
# step. Includes the bonus token. Used for output processing.
|
||||||
accept_tokens: torch.Tensor
|
accept_tokens: torch.Tensor
|
||||||
# Accepted token length per sequence in a batch in CPU.
|
# Below are transient handoff fields for the next iter's draft-extend pass.
|
||||||
|
# They are scoped to the verify -> prepare_extend_after_decode window only;
|
||||||
|
# `prepare_extend_after_decode` reads them off this object via method arg
|
||||||
|
# rather than smuggling them through `EagleDraftInput`.
|
||||||
|
#
|
||||||
|
# Subset of `accept_tokens` for reqs continuing into next iter's draft-extend
|
||||||
|
# forward (= `accept_tokens` when no req finished; flat over unfinished
|
||||||
|
# reqs only otherwise). Becomes `batch.input_ids` for that forward pass.
|
||||||
|
unfinished_accept_tokens: torch.Tensor
|
||||||
|
# `batch.seq_lens` / `batch.seq_lens_cpu` / `batch.req_pool_indices` to
|
||||||
|
# use for the next iter's draft-extend forward; sliced to surviving reqs.
|
||||||
|
seq_lens_for_draft_extend: torch.Tensor
|
||||||
|
seq_lens_for_draft_extend_cpu: torch.Tensor
|
||||||
|
req_pool_indices_for_draft_extend: torch.Tensor
|
||||||
|
# Accepted token length per sequence in a batch in CPU (full set).
|
||||||
num_accepted_drafts_per_req_cpu: List[int]
|
num_accepted_drafts_per_req_cpu: List[int]
|
||||||
# Accepted indices from logits_output.next_token_logits
|
# Accepted indices from logits_output.next_token_logits
|
||||||
accepted_indices: torch.Tensor
|
accepted_indices: torch.Tensor
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def create_idle(
|
||||||
|
cls,
|
||||||
|
*,
|
||||||
|
next_draft_input: EagleDraftInput,
|
||||||
|
logits_output: LogitsProcessorOutput,
|
||||||
|
device: torch.device,
|
||||||
|
spec_steps: int,
|
||||||
|
) -> "EagleVerifyOutput":
|
||||||
|
return cls(
|
||||||
|
next_draft_input=next_draft_input,
|
||||||
|
logits_output=logits_output,
|
||||||
|
accept_tokens=torch.empty(0, dtype=torch.long, device=device),
|
||||||
|
unfinished_accept_tokens=torch.empty(0, dtype=torch.long, device=device),
|
||||||
|
seq_lens_for_draft_extend=torch.empty(0, dtype=torch.int32, device=device),
|
||||||
|
seq_lens_for_draft_extend_cpu=torch.empty(0, dtype=torch.int32),
|
||||||
|
req_pool_indices_for_draft_extend=torch.empty(
|
||||||
|
0, dtype=torch.int64, device=device
|
||||||
|
),
|
||||||
|
num_accepted_drafts_per_req_cpu=[],
|
||||||
|
accepted_indices=torch.full(
|
||||||
|
(0, spec_steps + 1), -1, dtype=torch.int32, device=device
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|||||||
@@ -505,10 +505,10 @@ class EAGLEWorker(TpModelWorker):
|
|||||||
# when DP attention is enabled, but it is slow. Skip it for now.
|
# when DP attention is enabled, but it is slow. Skip it for now.
|
||||||
if (
|
if (
|
||||||
self.server_args.enable_dp_attention
|
self.server_args.enable_dp_attention
|
||||||
or batch.spec_info.accept_tokens.shape[0] > 0
|
or verify_output.unfinished_accept_tokens.shape[0] > 0
|
||||||
):
|
):
|
||||||
# decode is not finished
|
# decode is not finished
|
||||||
self.forward_draft_extend_after_decode(batch)
|
self.forward_draft_extend_after_decode(batch, verify_output)
|
||||||
|
|
||||||
set_time_batch(
|
set_time_batch(
|
||||||
batch.reqs, "set_spec_draft_extend_end_time", trace_only=True
|
batch.reqs, "set_spec_draft_extend_end_time", trace_only=True
|
||||||
@@ -527,8 +527,10 @@ class EAGLEWorker(TpModelWorker):
|
|||||||
can_run_cuda_graph=can_run_cuda_graph,
|
can_run_cuda_graph=can_run_cuda_graph,
|
||||||
)
|
)
|
||||||
|
|
||||||
def check_forward_draft_extend_after_decode(self, batch: ScheduleBatch):
|
def check_forward_draft_extend_after_decode(
|
||||||
local_need_forward = batch.spec_info.accept_tokens.shape[0] > 0
|
self, batch: ScheduleBatch, verify_output: EagleVerifyOutput
|
||||||
|
):
|
||||||
|
local_need_forward = verify_output.unfinished_accept_tokens.shape[0] > 0
|
||||||
if not self.server_args.enable_dp_attention:
|
if not self.server_args.enable_dp_attention:
|
||||||
return local_need_forward
|
return local_need_forward
|
||||||
|
|
||||||
@@ -977,7 +979,7 @@ class EAGLEWorker(TpModelWorker):
|
|||||||
batch.forward_mode = (
|
batch.forward_mode = (
|
||||||
ForwardMode.DECODE if not batch.forward_mode.is_idle() else ForwardMode.IDLE
|
ForwardMode.DECODE if not batch.forward_mode.is_idle() else ForwardMode.IDLE
|
||||||
)
|
)
|
||||||
batch.spec_info = res.draft_input
|
batch.spec_info = res.next_draft_input
|
||||||
|
|
||||||
return logits_output, res, model_worker_batch, can_run_cuda_graph
|
return logits_output, res, model_worker_batch, can_run_cuda_graph
|
||||||
|
|
||||||
@@ -1104,7 +1106,9 @@ class EAGLEWorker(TpModelWorker):
|
|||||||
assert forward_batch.spec_info is batch.spec_info
|
assert forward_batch.spec_info is batch.spec_info
|
||||||
self.capture_for_decode(logits_output, forward_batch.spec_info)
|
self.capture_for_decode(logits_output, forward_batch.spec_info)
|
||||||
|
|
||||||
def forward_draft_extend_after_decode(self, batch: ScheduleBatch):
|
def forward_draft_extend_after_decode(
|
||||||
|
self, batch: ScheduleBatch, verify_output: EagleVerifyOutput
|
||||||
|
):
|
||||||
assert isinstance(batch.spec_info, EagleDraftInput)
|
assert isinstance(batch.spec_info, EagleDraftInput)
|
||||||
# Backup fields that will be modified in-place
|
# Backup fields that will be modified in-place
|
||||||
seq_lens_backup = batch.seq_lens.clone()
|
seq_lens_backup = batch.seq_lens.clone()
|
||||||
@@ -1116,7 +1120,7 @@ class EAGLEWorker(TpModelWorker):
|
|||||||
|
|
||||||
input_is_idle = batch.forward_mode.is_idle()
|
input_is_idle = batch.forward_mode.is_idle()
|
||||||
|
|
||||||
if not input_is_idle and batch.spec_info.accept_tokens.numel() == 0:
|
if not input_is_idle and verify_output.unfinished_accept_tokens.numel() == 0:
|
||||||
batch = batch.copy()
|
batch = batch.copy()
|
||||||
batch.prepare_for_idle()
|
batch.prepare_for_idle()
|
||||||
hidden_size = (
|
hidden_size = (
|
||||||
@@ -1137,7 +1141,8 @@ class EAGLEWorker(TpModelWorker):
|
|||||||
batch.spec_info.num_tokens_for_logprob_per_req = 1
|
batch.spec_info.num_tokens_for_logprob_per_req = 1
|
||||||
batch.spec_info.prepare_extend_after_decode(
|
batch.spec_info.prepare_extend_after_decode(
|
||||||
batch,
|
batch,
|
||||||
self.speculative_num_steps,
|
verify_output=verify_output,
|
||||||
|
speculative_num_steps=self.speculative_num_steps,
|
||||||
)
|
)
|
||||||
batch.forward_mode = (
|
batch.forward_mode = (
|
||||||
ForwardMode.DRAFT_EXTEND
|
ForwardMode.DRAFT_EXTEND
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ class FrozenKVMTPVerifyInput(EagleVerifyInput):
|
|||||||
|
|
||||||
def verify(self, *args, **kwargs) -> EagleVerifyOutput:
|
def verify(self, *args, **kwargs) -> EagleVerifyOutput:
|
||||||
output = super().verify(*args, **kwargs)
|
output = super().verify(*args, **kwargs)
|
||||||
output.draft_input = _to_frozen_kv_mtp_draft_input(output.draft_input)
|
output.next_draft_input = _to_frozen_kv_mtp_draft_input(output.next_draft_input)
|
||||||
return output
|
return output
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ from sglang.srt.model_executor.pool_configurator import MemoryPoolConfig
|
|||||||
from sglang.srt.observability.req_time_stats import set_time_batch
|
from sglang.srt.observability.req_time_stats import set_time_batch
|
||||||
from sglang.srt.observability.trace import get_global_tracing_enabled
|
from sglang.srt.observability.trace import get_global_tracing_enabled
|
||||||
from sglang.srt.server_args import ServerArgs
|
from sglang.srt.server_args import ServerArgs
|
||||||
|
from sglang.srt.speculative.eagle_info import EagleVerifyOutput
|
||||||
from sglang.srt.speculative.eagle_utils import (
|
from sglang.srt.speculative.eagle_utils import (
|
||||||
build_tree_kernel_efficient,
|
build_tree_kernel_efficient,
|
||||||
organize_draft_results,
|
organize_draft_results,
|
||||||
@@ -463,7 +464,7 @@ class FrozenKVMTPWorker(TpModelWorker):
|
|||||||
self.server_args.enable_dp_attention
|
self.server_args.enable_dp_attention
|
||||||
or batch.spec_info.bonus_tokens.numel()
|
or batch.spec_info.bonus_tokens.numel()
|
||||||
):
|
):
|
||||||
self.forward_draft_extend_after_decode(batch)
|
self.forward_draft_extend_after_decode(batch, verify_output)
|
||||||
set_time_batch(batch.reqs, "set_spec_draft_extend_end_time", trace_only=True)
|
set_time_batch(batch.reqs, "set_spec_draft_extend_end_time", trace_only=True)
|
||||||
|
|
||||||
return GenerationBatchResult(
|
return GenerationBatchResult(
|
||||||
@@ -504,7 +505,9 @@ class FrozenKVMTPWorker(TpModelWorker):
|
|||||||
mm_input_embeds=mm_input_embeds,
|
mm_input_embeds=mm_input_embeds,
|
||||||
)
|
)
|
||||||
|
|
||||||
def forward_draft_extend_after_decode(self, batch: ScheduleBatch) -> None:
|
def forward_draft_extend_after_decode(
|
||||||
|
self, batch: ScheduleBatch, verify_output: EagleVerifyOutput
|
||||||
|
) -> None:
|
||||||
assert isinstance(batch.spec_info, FrozenKVMTPDraftInput)
|
assert isinstance(batch.spec_info, FrozenKVMTPDraftInput)
|
||||||
input_is_idle = batch.forward_mode.is_idle()
|
input_is_idle = batch.forward_mode.is_idle()
|
||||||
if not input_is_idle and batch.spec_info.bonus_tokens.numel() == 0:
|
if not input_is_idle and batch.spec_info.bonus_tokens.numel() == 0:
|
||||||
@@ -527,19 +530,18 @@ class FrozenKVMTPWorker(TpModelWorker):
|
|||||||
req_pool_indices_backup = batch.req_pool_indices
|
req_pool_indices_backup = batch.req_pool_indices
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if draft_input.seq_lens_for_draft_extend is not None:
|
# Verify may leave finished requests in ScheduleBatch; seed only
|
||||||
# Verify may leave finished requests in ScheduleBatch; seed only
|
# the unfinished requests carried by `verify_output`.
|
||||||
# the unfinished requests carried by draft_input.
|
batch.seq_lens = verify_output.seq_lens_for_draft_extend
|
||||||
batch.seq_lens = draft_input.seq_lens_for_draft_extend
|
batch.seq_lens_cpu = verify_output.seq_lens_for_draft_extend_cpu
|
||||||
batch.seq_lens_cpu = draft_input.seq_lens_for_draft_extend_cpu
|
batch.req_pool_indices = verify_output.req_pool_indices_for_draft_extend
|
||||||
batch.req_pool_indices = draft_input.req_pool_indices_for_draft_extend
|
|
||||||
|
|
||||||
last_token_ids, last_hidden = self._select_last_verified_seed(draft_input)
|
last_token_ids, last_hidden = self._select_last_verified_seed(draft_input)
|
||||||
self._run_assistant_seed_step(
|
self._run_assistant_seed_step(
|
||||||
batch,
|
batch,
|
||||||
last_token_ids,
|
last_token_ids,
|
||||||
last_hidden,
|
last_hidden,
|
||||||
seq_lens_cpu=draft_input.seq_lens_for_draft_extend_cpu,
|
seq_lens_cpu=verify_output.seq_lens_for_draft_extend_cpu,
|
||||||
draft_input=draft_input,
|
draft_input=draft_input,
|
||||||
)
|
)
|
||||||
finally:
|
finally:
|
||||||
@@ -766,7 +768,7 @@ class FrozenKVMTPWorker(TpModelWorker):
|
|||||||
batch.forward_mode = (
|
batch.forward_mode = (
|
||||||
ForwardMode.DECODE if not batch.forward_mode.is_idle() else ForwardMode.IDLE
|
ForwardMode.DECODE if not batch.forward_mode.is_idle() else ForwardMode.IDLE
|
||||||
)
|
)
|
||||||
batch.spec_info = res.draft_input
|
batch.spec_info = res.next_draft_input
|
||||||
|
|
||||||
del seq_lens_pre_verify
|
del seq_lens_pre_verify
|
||||||
return logits_output, res, model_worker_batch, can_run_cuda_graph
|
return logits_output, res, model_worker_batch, can_run_cuda_graph
|
||||||
|
|||||||
@@ -283,10 +283,10 @@ class MultiLayerEagleWorker(TpModelWorker):
|
|||||||
# when DP attention is enabled, but it is slow. Skip it for now.
|
# when DP attention is enabled, but it is slow. Skip it for now.
|
||||||
if (
|
if (
|
||||||
self.server_args.enable_dp_attention
|
self.server_args.enable_dp_attention
|
||||||
or batch.spec_info.accept_tokens.shape[0] > 0
|
or verify_output.unfinished_accept_tokens.shape[0] > 0
|
||||||
):
|
):
|
||||||
# decode is not finished
|
# decode is not finished
|
||||||
self.forward_draft_extend_after_decode(batch)
|
self.forward_draft_extend_after_decode(batch, verify_output)
|
||||||
|
|
||||||
return GenerationBatchResult(
|
return GenerationBatchResult(
|
||||||
logits_output=logits_output,
|
logits_output=logits_output,
|
||||||
@@ -295,8 +295,10 @@ class MultiLayerEagleWorker(TpModelWorker):
|
|||||||
can_run_cuda_graph=can_run_cuda_graph,
|
can_run_cuda_graph=can_run_cuda_graph,
|
||||||
)
|
)
|
||||||
|
|
||||||
def check_forward_draft_extend_after_decode(self, batch: ScheduleBatch):
|
def check_forward_draft_extend_after_decode(
|
||||||
local_need_forward = batch.spec_info.accept_tokens.shape[0] > 0
|
self, batch: ScheduleBatch, verify_output: EagleVerifyOutput
|
||||||
|
):
|
||||||
|
local_need_forward = verify_output.unfinished_accept_tokens.shape[0] > 0
|
||||||
if not self.server_args.enable_dp_attention:
|
if not self.server_args.enable_dp_attention:
|
||||||
return local_need_forward
|
return local_need_forward
|
||||||
|
|
||||||
@@ -589,7 +591,7 @@ class MultiLayerEagleWorker(TpModelWorker):
|
|||||||
batch.forward_mode = (
|
batch.forward_mode = (
|
||||||
ForwardMode.DECODE if not batch.forward_mode.is_idle() else ForwardMode.IDLE
|
ForwardMode.DECODE if not batch.forward_mode.is_idle() else ForwardMode.IDLE
|
||||||
)
|
)
|
||||||
batch.spec_info = res.draft_input
|
batch.spec_info = res.next_draft_input
|
||||||
|
|
||||||
return logits_output, res, model_worker_batch, can_run_cuda_graph
|
return logits_output, res, model_worker_batch, can_run_cuda_graph
|
||||||
|
|
||||||
@@ -652,7 +654,9 @@ class MultiLayerEagleWorker(TpModelWorker):
|
|||||||
forward_batch.spec_info.topk_p = torch.cat(topk_p_list, dim=1)
|
forward_batch.spec_info.topk_p = torch.cat(topk_p_list, dim=1)
|
||||||
forward_batch.spec_info.topk_index = torch.cat(topk_index_list, dim=1)
|
forward_batch.spec_info.topk_index = torch.cat(topk_index_list, dim=1)
|
||||||
|
|
||||||
def forward_draft_extend_after_decode(self, batch: ScheduleBatch):
|
def forward_draft_extend_after_decode(
|
||||||
|
self, batch: ScheduleBatch, verify_output: EagleVerifyOutput
|
||||||
|
):
|
||||||
assert isinstance(batch.spec_info, EagleDraftInput)
|
assert isinstance(batch.spec_info, EagleDraftInput)
|
||||||
# Backup fields that will be modified in-place
|
# Backup fields that will be modified in-place
|
||||||
seq_lens_backup = batch.seq_lens.clone()
|
seq_lens_backup = batch.seq_lens.clone()
|
||||||
@@ -664,7 +668,7 @@ class MultiLayerEagleWorker(TpModelWorker):
|
|||||||
|
|
||||||
input_is_idle = batch.forward_mode.is_idle()
|
input_is_idle = batch.forward_mode.is_idle()
|
||||||
|
|
||||||
if not input_is_idle and batch.spec_info.accept_tokens.numel() == 0:
|
if not input_is_idle and verify_output.unfinished_accept_tokens.numel() == 0:
|
||||||
batch = batch.copy()
|
batch = batch.copy()
|
||||||
batch.prepare_for_idle()
|
batch.prepare_for_idle()
|
||||||
hidden_size = (
|
hidden_size = (
|
||||||
@@ -684,7 +688,8 @@ class MultiLayerEagleWorker(TpModelWorker):
|
|||||||
batch.spec_info.num_tokens_for_logprob_per_req = 1
|
batch.spec_info.num_tokens_for_logprob_per_req = 1
|
||||||
batch.spec_info.prepare_extend_after_decode(
|
batch.spec_info.prepare_extend_after_decode(
|
||||||
batch,
|
batch,
|
||||||
self.speculative_num_steps,
|
verify_output=verify_output,
|
||||||
|
speculative_num_steps=self.speculative_num_steps,
|
||||||
)
|
)
|
||||||
batch.forward_mode = (
|
batch.forward_mode = (
|
||||||
ForwardMode.DRAFT_EXTEND
|
ForwardMode.DRAFT_EXTEND
|
||||||
|
|||||||
@@ -106,7 +106,6 @@ class NgramVerifyInput(SpecInput):
|
|||||||
last_loc,
|
last_loc,
|
||||||
len(batch.input_ids),
|
len(batch.input_ids),
|
||||||
)
|
)
|
||||||
self.last_loc = last_loc
|
|
||||||
|
|
||||||
bs = batch.batch_size()
|
bs = batch.batch_size()
|
||||||
assign_req_to_token_pool[(bs,)](
|
assign_req_to_token_pool[(bs,)](
|
||||||
|
|||||||
Reference in New Issue
Block a user