@@ -180,8 +180,7 @@ def __init__(
180180
181181 # Routed experts accumulation (prompt + sample chunks)
182182 self .routed_experts_chunks : list [np .ndarray ] = []
183- self .sampling_mask_token_ids : list [int ] = []
184- self .sampling_mask_offsets : list [int ] = [0 ]
183+ self .sampling_mask_chunks : list [SamplingMaskLists ] = []
185184
186185 # Stream Interval
187186 self .stream_interval = stream_interval
@@ -340,33 +339,6 @@ def make_request_output(
340339 ec_transfer_params ,
341340 )
342341
343- def update_sampling_mask (
344- self ,
345- new_token_ids : list [int ],
346- sampling_mask : SamplingMaskLists | None ,
347- ) -> None :
348- if sampling_mask is None :
349- if new_token_ids and len (self .sampling_mask_offsets ) > 1 :
350- raise RuntimeError (
351- f"missing sampling mask for request { self .request_id } "
352- )
353- return
354- if len (sampling_mask .counts ) != len (new_token_ids ):
355- raise RuntimeError (
356- f"sampling mask row count does not match tokens for request "
357- f"{ self .request_id } : { len (sampling_mask .counts )} rows for "
358- f"{ len (new_token_ids )} tokens"
359- )
360- for row , raw_count in zip (sampling_mask .token_ids , sampling_mask .counts ):
361- count = int (raw_count )
362- if count <= 0 or count > len (row ):
363- raise RuntimeError (
364- f"invalid sampling mask count { count } for request { self .request_id } "
365- )
366- kept_ids = [int (token_id ) for token_id in row [:count ]]
367- self .sampling_mask_token_ids .extend (kept_ids )
368- self .sampling_mask_offsets .append (len (self .sampling_mask_token_ids ))
369-
370342 def _new_request_output (
371343 self ,
372344 external_req_id : str ,
@@ -434,7 +406,14 @@ def _new_completion_output(
434406 if delta and logprobs :
435407 logprobs = logprobs [- len (token_ids ) :]
436408
437- sampling_mask = self ._get_sampling_mask (token_ids , delta )
409+ sampling_mask = None
410+ if (
411+ finished
412+ and self .output_kind == RequestOutputKind .FINAL_ONLY
413+ and self .sampling_mask_chunks
414+ ):
415+ merged = SamplingMaskLists .merge (self .sampling_mask_chunks )
416+ sampling_mask = SamplingMask (merged .token_ids , merged .offsets )
438417
439418 # Concatenate routed experts on finish
440419 routed_experts = None
@@ -453,27 +432,6 @@ def _new_completion_output(
453432 stop_reason = stop_reason if finished else None ,
454433 )
455434
456- def _get_sampling_mask (
457- self , token_ids : list [int ], delta : bool
458- ) -> SamplingMask | None :
459- if len (self .sampling_mask_offsets ) == 1 :
460- return None
461- num_rows = len (self .sampling_mask_offsets ) - 1
462- if num_rows != self .detokenizer .num_output_tokens ():
463- raise RuntimeError (
464- f"sampling mask is misaligned for request { self .request_id } : "
465- f"{ num_rows } rows for { self .detokenizer .num_output_tokens ()} tokens"
466- )
467- start_row = num_rows - len (token_ids ) if delta else 0
468- flat_start = self .sampling_mask_offsets [start_row ]
469- offsets = [
470- offset - flat_start for offset in self .sampling_mask_offsets [start_row :]
471- ]
472- return SamplingMask (
473- token_ids = self .sampling_mask_token_ids [flat_start :],
474- offsets = offsets ,
475- )
476-
477435 def _new_pooling_output (self , pooling_output : torch .Tensor ) -> PoolingOutput :
478436 return PoolingOutput (data = pooling_output )
479437
@@ -704,9 +662,13 @@ def process_outputs(
704662 if pooling_output is None :
705663 assert req_state .detokenizer is not None
706664 assert req_state .logprobs_processor is not None
707- req_state .update_sampling_mask (
708- new_token_ids , engine_core_output .new_sampling_mask
709- )
665+ if (
666+ engine_core_output .new_sampling_mask is not None
667+ and req_state .output_kind == RequestOutputKind .FINAL_ONLY
668+ ):
669+ req_state .sampling_mask_chunks .append (
670+ engine_core_output .new_sampling_mask
671+ )
710672 # 2) Detokenize the token ids into text and perform stop checks.
711673 stop_string = req_state .detokenizer .update (
712674 new_token_ids , finish_reason == FinishReason .STOP
0 commit comments