Generalize auxiliary outputs (#39164)

Co-authored-by: jasonjk <jasonjk@twshared0085.36.lco2.facebook.com>
This commit is contained in:
jasonjk-park
2026-09-15 12:05:13 -07:00
committed by GitHub
co-authored by jasonjk
parent 49f540f3c0
commit 073fdf97cc
7 changed files with 144 additions and 46 deletions
+1 -1
View File
@@ -51,13 +51,13 @@ from sglang.srt.layers.logprob_processor import (
get_top_logprobs_raw,
)
from sglang.srt.layers.vocab_parallel_embedding import VocabParallelEmbedding
from sglang.srt.managers.auxiliary_output import DeviceAuxiliaryOutput
from sglang.srt.model_executor.forward_batch_info import (
CaptureHiddenMode,
ForwardBatch,
ForwardMode,
)
from sglang.srt.runtime_context import get_exec, get_parallel
from sglang.srt.sampling.sampling_observer import DeviceAuxiliaryOutput
from sglang.srt.utils.common import (
is_cpu,
is_npu,
@@ -0,0 +1,93 @@
"""Auxiliary outputs carried through the generation-result lifecycle."""
from __future__ import annotations
from dataclasses import dataclass
from typing import TYPE_CHECKING, Callable, Optional, Protocol, Sequence
import torch
if TYPE_CHECKING:
from sglang.srt.managers.schedule_batch import ScheduleBatch
@dataclass(frozen=True)
class CommittedTokens:
output_index: int
token_ids: tuple[int, ...]
class DeviceAuxiliaryOutput(Protocol):
"""Device output copied later by the scheduler.
Tensors must not alias CUDA-graph static buffers that a later replay can
overwrite before the scheduler-side copy completes.
"""
def copy_to_host(
self, copy_tensor: Callable[[torch.Tensor], torch.Tensor]
) -> HostAuxiliaryOutput: ...
class HostAuxiliaryOutput(Protocol):
"""Scheduler-side result produced by ``DeviceAuxiliaryOutput``.
``consume`` runs after sampled tokens have been committed to each request
and immediately before response streaming. ``commits`` is aligned with
``batch.reqs`` and identifies only the newly visible tokens. Implementations
can buffer per-request values for a ``SchedulerOutputStreamer`` subclass to
expose through customized response metadata.
"""
def consume(
self,
batch: ScheduleBatch,
commits: Sequence[Optional[CommittedTokens]],
) -> None: ...
@dataclass(frozen=True)
class CompositeHostAuxiliaryOutput:
outputs: tuple[HostAuxiliaryOutput, ...]
def consume(
self,
batch: ScheduleBatch,
commits: Sequence[Optional[CommittedTokens]],
) -> None:
for output in self.outputs:
output.consume(batch, commits)
@dataclass(frozen=True)
class CompositeDeviceAuxiliaryOutput:
outputs: tuple[DeviceAuxiliaryOutput, ...]
def copy_to_host(
self, copy_tensor: Callable[[torch.Tensor], torch.Tensor]
) -> CompositeHostAuxiliaryOutput:
return CompositeHostAuxiliaryOutput(
tuple(output.copy_to_host(copy_tensor) for output in self.outputs)
)
def append_auxiliary_output(
current: Optional[DeviceAuxiliaryOutput],
output: Optional[DeviceAuxiliaryOutput],
) -> Optional[DeviceAuxiliaryOutput]:
if output is None:
return current
if current is None:
return output
current_outputs = (
current.outputs
if isinstance(current, CompositeDeviceAuxiliaryOutput)
else (current,)
)
new_outputs = (
output.outputs
if isinstance(output, CompositeDeviceAuxiliaryOutput)
else (output,)
)
return CompositeDeviceAuxiliaryOutput(current_outputs + new_outputs)
@@ -20,6 +20,7 @@ from sglang.srt.layers.logits_processor import (
LogitsProcessorOutput,
SamplingMaskStatus,
)
from sglang.srt.managers.auxiliary_output import CommittedTokens
from sglang.srt.managers.schedule_batch import (
FINISH_ABORT,
FINISH_MATCHED_TOKEN,
@@ -44,7 +45,6 @@ from sglang.srt.runtime_context import (
mamba_track_grid,
max_speculative_num_draft_tokens,
)
from sglang.srt.sampling.sampling_observer import CommittedTokens
from sglang.srt.sampling.sampling_params import (
get_request_reasoning_end_token_ids,
)
@@ -58,6 +58,7 @@ if TYPE_CHECKING:
from sglang.srt.disaggregation.decode_kvcache_offload_manager import (
DecodeKVCacheOffloadManager,
)
from sglang.srt.managers.auxiliary_output import HostAuxiliaryOutput
from sglang.srt.managers.hisparse_coordinator import HiSparseCoordinator
from sglang.srt.managers.scheduler_components.logprob_result_processor import (
SchedulerLogprobResultProcessor,
@@ -77,7 +78,6 @@ if TYPE_CHECKING:
from sglang.srt.mem_cache.base_prefix_cache import BasePrefixCache
from sglang.srt.mem_cache.memory_pool import ReqToTokenPool
from sglang.srt.observability.metrics_collector import SchedulerMetricsCollector
from sglang.srt.sampling.sampling_observer import HostAuxiliaryOutput
logger = logging.getLogger(__name__)
+1 -1
View File
@@ -23,8 +23,8 @@ from sglang.srt.speculative.spec_info import SpeculativeAlgorithm
from sglang.srt.state_capturer.base import TopkCaptureOutput
if TYPE_CHECKING:
from sglang.srt.managers.auxiliary_output import HostAuxiliaryOutput
from sglang.srt.managers.scheduler import GenerationBatchResult
from sglang.srt.sampling.sampling_observer import HostAuxiliaryOutput
from sglang.srt.speculative.spec_info import SpecInput
@@ -9,51 +9,16 @@ manager consumes the resulting customized response fields.
from __future__ import annotations
from dataclasses import dataclass
from typing import TYPE_CHECKING, Any, Callable, Optional, Protocol, Sequence
from typing import TYPE_CHECKING, Any, Optional, Protocol
import torch
from sglang.srt.managers.auxiliary_output import DeviceAuxiliaryOutput
if TYPE_CHECKING:
from sglang.srt.managers.schedule_batch import ScheduleBatch
from sglang.srt.sampling.sampling_batch_info import SamplingBatchInfo
@dataclass(frozen=True)
class CommittedTokens:
output_index: int
token_ids: tuple[int, ...]
class DeviceAuxiliaryOutput(Protocol):
"""Device output copied later by the scheduler.
Tensors must not alias CUDA-graph static buffers that a later replay can
overwrite before the scheduler-side copy completes.
"""
def copy_to_host(
self, copy_tensor: Callable[[torch.Tensor], torch.Tensor]
) -> HostAuxiliaryOutput: ...
class HostAuxiliaryOutput(Protocol):
"""Scheduler-side result produced by ``DeviceAuxiliaryOutput``.
``consume`` runs after sampled tokens have been committed to each request
and immediately before response streaming. ``commits`` is aligned with
``batch.reqs`` and identifies only the newly visible tokens. Implementations
can buffer per-request values for a ``SchedulerOutputStreamer`` subclass to
expose through customized response metadata.
"""
def consume(
self,
batch: ScheduleBatch,
commits: Sequence[Optional[CommittedTokens]],
) -> None: ...
class SamplingObserver(Protocol):
"""Invocation-scoped hooks around the production grammar mask and sampler.
@@ -11,10 +11,8 @@ from typing import (
import torch
from sglang.srt.sampling.sampling_observer import (
DeviceAuxiliaryOutput,
SamplingObserver,
)
from sglang.srt.managers.auxiliary_output import DeviceAuxiliaryOutput
from sglang.srt.sampling.sampling_observer import SamplingObserver
@runtime_checkable