Add customized sampler registration (#15423)
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
import logging
|
import logging
|
||||||
from typing import List, Optional, Tuple
|
from typing import Callable, Dict, List, Optional, Tuple
|
||||||
|
|
||||||
import torch
|
import torch
|
||||||
import torch.distributed as dist
|
import torch.distributed as dist
|
||||||
@@ -31,6 +31,8 @@ logger = logging.getLogger(__name__)
|
|||||||
|
|
||||||
SYNC_TOKEN_IDS_ACROSS_TP = get_bool_env_var("SYNC_TOKEN_IDS_ACROSS_TP")
|
SYNC_TOKEN_IDS_ACROSS_TP = get_bool_env_var("SYNC_TOKEN_IDS_ACROSS_TP")
|
||||||
SGLANG_RETURN_ORIGINAL_LOGPROB = get_bool_env_var("SGLANG_RETURN_ORIGINAL_LOGPROB")
|
SGLANG_RETURN_ORIGINAL_LOGPROB = get_bool_env_var("SGLANG_RETURN_ORIGINAL_LOGPROB")
|
||||||
|
_CUSTOM_SAMPLER_FACTORIES: Dict[str, Callable[[], "Sampler"]] = {}
|
||||||
|
_BUILT_IN_SAMPLING_BACKENDS = {"flashinfer", "pytorch", "ascend"}
|
||||||
|
|
||||||
|
|
||||||
class Sampler(nn.Module):
|
class Sampler(nn.Module):
|
||||||
@@ -268,6 +270,42 @@ class Sampler(nn.Module):
|
|||||||
) = get_token_ids_logprobs_batch_optimized(logprobs, token_ids_logprobs)
|
) = get_token_ids_logprobs_batch_optimized(logprobs, token_ids_logprobs)
|
||||||
|
|
||||||
|
|
||||||
|
def register_sampler_backend(backend: str, factory: Callable[[], "Sampler"]) -> None:
|
||||||
|
"""Register a custom sampler factory for a backend string."""
|
||||||
|
|
||||||
|
if not backend:
|
||||||
|
raise ValueError("backend must be a non-empty string")
|
||||||
|
|
||||||
|
from sglang.srt.server_args import SAMPLING_BACKEND_CHOICES
|
||||||
|
|
||||||
|
if backend in _CUSTOM_SAMPLER_FACTORIES:
|
||||||
|
logger.warning("Overriding existing sampler factory for backend '%s'", backend)
|
||||||
|
SAMPLING_BACKEND_CHOICES.add(backend)
|
||||||
|
_CUSTOM_SAMPLER_FACTORIES[backend] = factory
|
||||||
|
|
||||||
|
|
||||||
|
def create_sampler(backend: Optional[str] = None) -> "Sampler":
|
||||||
|
"""Create a sampler honoring custom backend registrations."""
|
||||||
|
|
||||||
|
server_args = get_global_server_args()
|
||||||
|
backend = backend or (server_args.sampling_backend if server_args else None)
|
||||||
|
|
||||||
|
if backend in _CUSTOM_SAMPLER_FACTORIES:
|
||||||
|
sampler = _CUSTOM_SAMPLER_FACTORIES[backend]()
|
||||||
|
if not isinstance(sampler, Sampler):
|
||||||
|
raise TypeError(
|
||||||
|
f"Custom sampler factory for backend '{backend}' must return a Sampler"
|
||||||
|
)
|
||||||
|
return sampler
|
||||||
|
|
||||||
|
if backend is None or backend in _BUILT_IN_SAMPLING_BACKENDS:
|
||||||
|
return Sampler()
|
||||||
|
|
||||||
|
raise ValueError(
|
||||||
|
f"Unknown sampling backend '{backend}'. Register it via register_sampler_backend()."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def top_k_top_p_min_p_sampling_from_probs_torch(
|
def top_k_top_p_min_p_sampling_from_probs_torch(
|
||||||
probs: torch.Tensor,
|
probs: torch.Tensor,
|
||||||
top_ks: torch.Tensor,
|
top_ks: torch.Tensor,
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ from sglang.srt.layers.dp_attention import (
|
|||||||
from sglang.srt.layers.logits_processor import LogitsProcessorOutput
|
from sglang.srt.layers.logits_processor import LogitsProcessorOutput
|
||||||
from sglang.srt.layers.pooler import EmbeddingPoolerOutput
|
from sglang.srt.layers.pooler import EmbeddingPoolerOutput
|
||||||
from sglang.srt.layers.quantization.fp8_kernel import fp8_dtype
|
from sglang.srt.layers.quantization.fp8_kernel import fp8_dtype
|
||||||
from sglang.srt.layers.sampler import Sampler
|
from sglang.srt.layers.sampler import create_sampler
|
||||||
from sglang.srt.layers.torchao_utils import apply_torchao_config_to_model
|
from sglang.srt.layers.torchao_utils import apply_torchao_config_to_model
|
||||||
from sglang.srt.lora.lora_manager import LoRAManager
|
from sglang.srt.lora.lora_manager import LoRAManager
|
||||||
from sglang.srt.lora.lora_registry import LoRARef
|
from sglang.srt.lora.lora_registry import LoRARef
|
||||||
@@ -451,7 +451,7 @@ class ModelRunner:
|
|||||||
else None
|
else None
|
||||||
)
|
)
|
||||||
# Load the model
|
# Load the model
|
||||||
self.sampler = Sampler()
|
self.sampler = create_sampler()
|
||||||
self.load_model()
|
self.load_model()
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ from sglang.srt.layers.moe.topk import TopK
|
|||||||
from sglang.srt.layers.quantization.base_config import QuantizationConfig
|
from sglang.srt.layers.quantization.base_config import QuantizationConfig
|
||||||
from sglang.srt.layers.radix_attention import RadixAttention
|
from sglang.srt.layers.radix_attention import RadixAttention
|
||||||
from sglang.srt.layers.rotary_embedding import get_rope
|
from sglang.srt.layers.rotary_embedding import get_rope
|
||||||
from sglang.srt.layers.sampler import Sampler
|
from sglang.srt.layers.sampler import create_sampler
|
||||||
from sglang.srt.layers.vocab_parallel_embedding import (
|
from sglang.srt.layers.vocab_parallel_embedding import (
|
||||||
ParallelLMHead,
|
ParallelLMHead,
|
||||||
VocabParallelEmbedding,
|
VocabParallelEmbedding,
|
||||||
@@ -603,7 +603,7 @@ class HunYuanMoEV1ForCausalLM(nn.Module):
|
|||||||
|
|
||||||
logit_scale = getattr(config, "logit_scale", 1.0)
|
logit_scale = getattr(config, "logit_scale", 1.0)
|
||||||
self.logits_processor = LogitsProcessor(config, logit_scale=logit_scale)
|
self.logits_processor = LogitsProcessor(config, logit_scale=logit_scale)
|
||||||
self.sampler = Sampler()
|
self.sampler = create_sampler()
|
||||||
|
|
||||||
def forward(
|
def forward(
|
||||||
self,
|
self,
|
||||||
|
|||||||
@@ -89,8 +89,15 @@ class SamplingBatchInfo:
|
|||||||
)
|
)
|
||||||
sampling_seed = (
|
sampling_seed = (
|
||||||
torch.tensor(
|
torch.tensor(
|
||||||
[r.sampling_params.sampling_seed for r in reqs],
|
[
|
||||||
dtype=torch.int32,
|
(
|
||||||
|
r.sampling_params.sampling_seed
|
||||||
|
if r.sampling_params.sampling_seed is not None
|
||||||
|
else 42
|
||||||
|
)
|
||||||
|
for r in reqs
|
||||||
|
],
|
||||||
|
dtype=torch.int64,
|
||||||
device=device,
|
device=device,
|
||||||
)
|
)
|
||||||
if enable_deterministic
|
if enable_deterministic
|
||||||
@@ -173,8 +180,13 @@ class SamplingBatchInfo:
|
|||||||
device=device,
|
device=device,
|
||||||
logit_bias=logit_bias,
|
logit_bias=logit_bias,
|
||||||
)
|
)
|
||||||
|
ret.adjusted_from_schedule_batch(batch, vocab_size)
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
# placeholder for override
|
||||||
|
def adjusted_from_schedule_batch(self, batch: ScheduleBatch, vocab_size: int):
|
||||||
|
pass
|
||||||
|
|
||||||
def __len__(self):
|
def __len__(self):
|
||||||
return len(self.temperatures)
|
return len(self.temperatures)
|
||||||
|
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ class SamplingParams:
|
|||||||
custom_params: Optional[Dict[str, Any]] = None,
|
custom_params: Optional[Dict[str, Any]] = None,
|
||||||
stream_interval: Optional[int] = None,
|
stream_interval: Optional[int] = None,
|
||||||
logit_bias: Optional[Dict[str, float]] = None,
|
logit_bias: Optional[Dict[str, float]] = None,
|
||||||
sampling_seed: int = 42,
|
sampling_seed: Optional[int] = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
self.max_new_tokens = max_new_tokens
|
self.max_new_tokens = max_new_tokens
|
||||||
self.stop_strs = stop
|
self.stop_strs = stop
|
||||||
@@ -146,8 +146,6 @@ class SamplingParams:
|
|||||||
f"logit_bias must has keys in [0, {vocab_size - 1}], got "
|
f"logit_bias must has keys in [0, {vocab_size - 1}], got "
|
||||||
f"{token_id}."
|
f"{token_id}."
|
||||||
)
|
)
|
||||||
if self.sampling_seed is None:
|
|
||||||
raise ValueError("sampling_seed should not be None")
|
|
||||||
|
|
||||||
grammars = [
|
grammars = [
|
||||||
self.json_schema,
|
self.json_schema,
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ logger = logging.getLogger(__name__)
|
|||||||
|
|
||||||
|
|
||||||
# Define constants
|
# Define constants
|
||||||
|
SAMPLING_BACKEND_CHOICES = {"flashinfer", "pytorch", "ascend"}
|
||||||
LOAD_FORMAT_CHOICES = [
|
LOAD_FORMAT_CHOICES = [
|
||||||
"auto",
|
"auto",
|
||||||
"pt",
|
"pt",
|
||||||
@@ -3220,7 +3221,7 @@ class ServerArgs:
|
|||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--sampling-backend",
|
"--sampling-backend",
|
||||||
type=str,
|
type=str,
|
||||||
choices=["flashinfer", "pytorch", "ascend"],
|
choices=SAMPLING_BACKEND_CHOICES,
|
||||||
default=ServerArgs.sampling_backend,
|
default=ServerArgs.sampling_backend,
|
||||||
help="Choose the kernels for sampling layers.",
|
help="Choose the kernels for sampling layers.",
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user