Files
wehub-resource-sync 94057c3d3e
PR Test (NPU) / check-changes (push) Has been cancelled
PR Test (NPU) / pr-gate (push) Has been cancelled
PR Test (NPU) / set-image-config (push) Has been cancelled
PR Test (NPU) / stage-b-test-1-npu-a2 (0) (push) Has been cancelled
PR Test (NPU) / stage-b-test-1-npu-a2 (1) (push) Has been cancelled
PR Test (NPU) / stage-b-test-2-npu-a2 (0) (push) Has been cancelled
PR Test (NPU) / stage-b-test-2-npu-a2 (1) (push) Has been cancelled
PR Test (NPU) / stage-b-test-4-npu-a3 (push) Has been cancelled
PR Test (NPU) / stage-b-test-16-npu-a3 (push) Has been cancelled
PR Test (NPU) / multimodal-gen-test-1-npu-a3 (push) Has been cancelled
PR Test (NPU) / multimodal-gen-test-2-npu-a3 (push) Has been cancelled
PR Test (Arm64) / pr-gate (push) Has been cancelled
PR Test (Arm64) / check-changes (push) Has been cancelled
PR Test (Arm64) / build-test (push) Has been cancelled
PR Test (sgl-router) / gate (push) Has been cancelled
PR Test (sgl-router) / tier-1 — lint (push) Has been cancelled
PR Test (sgl-router) / tier-2 — build + test (push) Has been cancelled
PR Test (sgl-router) / tier-3 — docker (placeholder) (push) Has been cancelled
PR Test (sgl-router) / tier-3 — k8s integration (push) Has been cancelled
PR Test (sgl-router) / tier-3 — e2e (push) Has been cancelled
PR Test (sgl-router) / finish (push) Has been cancelled
PR Test (NPU) / single-node-poc (map[name:qwen3_6_27b_w8a8_1p_in64k_out1k_50ms runner:linux-aarch64-a3-2 test_case:test/registered/ascend/performance/qwen3_6_27b/test_npu_qwen3_6_27b_w8a8_1p_in64k_out1k_50ms.py test_type:perf]) (push) Has been cancelled
PR Test (NPU) / pr-test-npu-finish (push) Has been cancelled
PR Test (Xeon) / pr-gate (push) Has been cancelled
PR Test (Xeon) / check-changes (push) Has been cancelled
PR Test (Xeon) / build-test (, xeon-gnr, base-b-test-cpu) (push) Has been cancelled
PR Test (XPU) / check-changes (push) Has been cancelled
PR Test (XPU) / pr-gate (push) Has been cancelled
PR Test (XPU) / stage-a-test-1-gpu-xpu (push) Has been cancelled
PR Test (XPU) / wait-for-stage-a (push) Has been cancelled
PR Test (XPU) / stage-b-test-1-gpu-xpu (push) Has been cancelled
PR Test (XPU) / finish (push) Has been cancelled
CI Model Inventory / build-inventory (push) Has been cancelled
Lint / lint (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark Compilation Check (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark - Manual Policy (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark - Request Processing (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark Summary (push) Has been cancelled
PR Test (SMG) / build-wheel (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on windows (x86_64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on macos (x86_64 - auto) (push) Has been cancelled
PR Test (SMG) / python-unit-tests (push) Has been cancelled
PR Test (SMG) / unit-tests (push) Has been cancelled
PR Test (SMG) / benchmarks (push) Has been cancelled
PR Test (SMG) / chat-completions (push) Has been cancelled
PR Test (SMG) / chat-completions-4gpu (push) Has been cancelled
PR Test (SMG) / e2e (push) Has been cancelled
PR Test (SMG) / docker-build-test (push) Has been cancelled
PR Test (SMG) / k8s-integration (push) Has been cancelled
PR Test (SMG) / finish (push) Has been cancelled
PR Test (SMG) / summarize-benchmarks (push) Has been cancelled
Release SGLang Model Gateway Docker Image / publish (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on macos (aarch64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (aarch64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (x86_64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (aarch64 - musllinux_1_1) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (x86_64 - musllinux_1_1) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / Build SDist (push) Has been cancelled
Release SGLang Model Gateway to PyPI / Upload to PyPI (push) Has been cancelled
Release SGLang Kernels / build-cu129-matrix (aarch64, 12.9, 3.10, arm-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / build-cu129-matrix (x86_64, 12.9, 3.10, x64-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / release-cu129 (push) Has been cancelled
Release SGLang Kernels / build-cu130-matrix (aarch64, 13.0, 3.10, arm-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / build-cu130-matrix (x86_64, 13.0, 3.10, x64-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / release-cu130 (push) Has been cancelled
Release SGLang Kernels / build-rocm-matrix (3.10, 700) (push) Has been cancelled
Release SGLang Kernels / build-rocm-matrix (3.10, 720) (push) Has been cancelled
Release SGLang Kernels / release-rocm700 (push) Has been cancelled
Release SGLang Kernels / release-rocm720 (push) Has been cancelled
Release SGLang Kernels / build-musa43 (43, 3.10) (push) Has been cancelled
Release SGLang Kernels / release-musa43 (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:38:16 +08:00

296 lines
10 KiB
Python

from __future__ import annotations
import json
import logging
from typing import TYPE_CHECKING, Any, List, Optional
import msgspec
from sglang.srt.speculative.dflash_utils import parse_dflash_draft_config
if TYPE_CHECKING:
from sglang.srt.server_args import ServerArgs
logger = logging.getLogger(__name__)
DEFAULT_DSPARK_GAMMA = 7
SUPPORTED_DSPARK_MARKOV_HEAD_TYPES = ("vanilla", "gated", "rnn")
# The dsv4 self-drafting checkpoint runs its draft attention on the dedicated
# DeepSeek-V4 backend instead of the generic draft-backend fallback.
DSV4_DRAFT_ATTENTION_BACKEND = "dsv4"
def draft_is_deepseek_v4(*, server_args: ServerArgs) -> bool:
from sglang.srt.configs.model_config import is_deepseek_v4
from sglang.srt.utils.hf_transformers_utils import get_config
draft_model_path = server_args.speculative_draft_model_path
if not draft_model_path:
return False
draft_hf_config = get_config(
draft_model_path,
trust_remote_code=server_args.trust_remote_code,
revision=server_args.speculative_draft_model_revision,
model_override_args=json.loads(server_args.json_model_override_args),
model_config_parser=server_args.model_config_parser,
)
return draft_hf_config is not None and is_deepseek_v4(draft_hf_config)
def dspark_gamma_from_num_draft_tokens(num_draft_tokens: int) -> int:
gamma = int(num_draft_tokens) - 1
if gamma < 1:
raise ValueError(
"DSpark speculative_num_draft_tokens must be >= 2 (= gamma + 1), "
f"got {num_draft_tokens}."
)
return gamma
class DSparkDraftConfig(msgspec.Struct, frozen=True):
num_hidden_layers: Optional[int]
num_target_layers: Optional[int]
gamma: Optional[int]
target_layer_ids: Optional[List[int]]
mask_token: str
mask_token_id: Optional[int]
markov_rank: int
markov_head_type: Optional[str]
def resolve_gamma(self, *, default: Optional[int] = None) -> Optional[int]:
return self.gamma if self.gamma is not None else default
def require_markov(self) -> bool:
return int(self.markov_rank) > 0
class DSparkRuntimeConfig(msgspec.Struct, frozen=True):
gamma: int
verify_num_draft_tokens: int
mask_token_id: int
def resolve_runtime_config(
*,
draft_hf_config: Any,
speculative_num_draft_tokens: Optional[int],
target_vocab_size: int,
) -> DSparkRuntimeConfig:
"""Resolve and validate the worker-facing DSpark runtime knobs (gamma,
verify window, mask token) from the draft checkpoint config, with
server_args.speculative_num_draft_tokens taking precedence for gamma."""
draft_config = parse_dspark_draft_config(draft_hf_config=draft_hf_config)
if not draft_config.require_markov():
raise ValueError(
"DSpark draft requires markov_rank > 0; got "
f"markov_rank={draft_config.markov_rank}."
)
if speculative_num_draft_tokens is None:
gamma = int(draft_config.resolve_gamma(default=None) or 0)
if gamma < 1:
raise ValueError(
"DSpark could not resolve gamma from the draft config and "
"speculative_num_draft_tokens is unset."
)
else:
gamma = dspark_gamma_from_num_draft_tokens(int(speculative_num_draft_tokens))
config_gamma = draft_config.resolve_gamma(default=None)
if config_gamma is not None and int(config_gamma) != gamma:
logger.warning(
"DSpark gamma mismatch: using gamma=%s (from "
"speculative_num_draft_tokens=%s) but draft config block_size=%s.",
gamma,
speculative_num_draft_tokens,
config_gamma,
)
if draft_config.mask_token_id is None:
raise ValueError(
"DSpark requires mask_token_id to be set in the draft model config."
)
mask_token_id = int(draft_config.mask_token_id)
if mask_token_id >= target_vocab_size:
raise ValueError(
f"DSpark mask_token_id={mask_token_id} is outside the target "
f"vocab size {target_vocab_size}."
)
return DSparkRuntimeConfig(
gamma=gamma,
verify_num_draft_tokens=gamma + 1,
mask_token_id=mask_token_id,
)
def read_draft_checkpoint_gamma(*, server_args: ServerArgs) -> Optional[int]:
"""Load the draft checkpoint's hf config and read its DSpark gamma
(block_size). Raises on config-load failure; callers pick the fallback."""
from sglang.srt.utils.hf_transformers_utils import get_config
draft_hf_config = get_config(
server_args.speculative_draft_model_path,
trust_remote_code=server_args.trust_remote_code,
revision=server_args.speculative_draft_model_revision,
model_override_args=json.loads(server_args.json_model_override_args),
)
return parse_dspark_draft_config(draft_hf_config=draft_hf_config).resolve_gamma(
default=None
)
def checkpoint_bundles_dspark_draft(hf_config: Any) -> bool:
"""The checkpoint carries a bundled DSpark draft head, marked by the
prefixed dspark_* keys on the target hf config. Single source of truth
for the bundling convention (draft-path defaulting, draft-arch remap)."""
return any(
_cfg_get(hf_config, key, None) is not None
for key in (
"dspark_block_size",
"dspark_markov_rank",
"dspark_noise_token_id",
"dspark_target_layer_ids",
)
)
def _cfg_get(config: Any, key: str, default: Any = None) -> Any:
if isinstance(config, dict):
return config.get(key, default)
return getattr(config, key, default)
def _get_text_config(config: Any) -> Any:
if config is None:
return None
if isinstance(config, dict):
return config.get("text_config", config)
text_config = getattr(config, "text_config", None)
if text_config is not None:
return text_config
return config
def _get_dspark_config(config: Any) -> dict:
cfg = _cfg_get(config, "dspark_config", None)
if cfg is None:
return {}
if isinstance(cfg, dict):
return cfg
try:
return dict(cfg)
except Exception:
return {}
def parse_dspark_draft_config(*, draft_hf_config: Any) -> DSparkDraftConfig:
base = parse_dflash_draft_config(draft_hf_config=draft_hf_config)
dspark_cfg = _get_dspark_config(draft_hf_config)
text_config = _get_text_config(draft_hf_config)
prefixed_block_size = _cfg_get(draft_hf_config, "dspark_block_size", None)
prefixed_markov_rank = _cfg_get(draft_hf_config, "dspark_markov_rank", None)
prefixed_markov_head_type = _cfg_get(
draft_hf_config, "dspark_markov_head_type", None
)
prefixed_noise_token_id = _cfg_get(draft_hf_config, "dspark_noise_token_id", None)
prefixed_target_layer_ids = _cfg_get(
draft_hf_config, "dspark_target_layer_ids", None
)
uses_prefixed = any(
value is not None
for value in (
prefixed_block_size,
prefixed_markov_rank,
prefixed_noise_token_id,
prefixed_target_layer_ids,
)
)
raw_markov_rank = (
prefixed_markov_rank
if prefixed_markov_rank is not None
else dspark_cfg.get(
"markov_rank",
_cfg_get(
text_config, "markov_rank", _cfg_get(draft_hf_config, "markov_rank", 0)
),
)
)
markov_rank = int(raw_markov_rank) if raw_markov_rank is not None else 0
if markov_rank < 0:
raise ValueError(f"DSpark markov_rank must be >= 0, got {markov_rank}.")
markov_head_type = (
prefixed_markov_head_type
if prefixed_markov_head_type is not None
else dspark_cfg.get(
"markov_head_type",
_cfg_get(
text_config,
"markov_head_type",
_cfg_get(draft_hf_config, "markov_head_type", None),
),
)
)
if markov_rank > 0 and markov_head_type is None and not uses_prefixed:
raise ValueError(
"DSpark requires markov_head_type when markov_rank > 0, got None."
)
if markov_head_type is not None:
markov_head_type = str(markov_head_type).lower()
if markov_head_type not in SUPPORTED_DSPARK_MARKOV_HEAD_TYPES:
raise ValueError(
f"Unsupported DSpark markov_head_type={markov_head_type!r}. "
f"Supported: {SUPPORTED_DSPARK_MARKOV_HEAD_TYPES}."
)
raw_mask_token_id = (
prefixed_noise_token_id
if prefixed_noise_token_id is not None
else dspark_cfg.get(
"mask_token_id",
_cfg_get(
text_config,
"mask_token_id",
_cfg_get(draft_hf_config, "mask_token_id", base.mask_token_id),
),
)
)
mask_token_id = int(raw_mask_token_id) if raw_mask_token_id is not None else None
if mask_token_id is not None and mask_token_id < 0:
raise ValueError(
f"DSpark mask_token_id must be non-negative, got {mask_token_id}."
)
gamma = (
int(prefixed_block_size) if prefixed_block_size is not None else base.block_size
)
if prefixed_target_layer_ids is not None:
if not isinstance(prefixed_target_layer_ids, (list, tuple)) or not len(
prefixed_target_layer_ids
):
raise ValueError(
"DSpark dspark_target_layer_ids must be a non-empty list of ints, "
f"got {prefixed_target_layer_ids!r}."
)
target_layer_ids: Optional[List[int]] = [
int(x) for x in prefixed_target_layer_ids
]
else:
target_layer_ids = base.target_layer_ids
return DSparkDraftConfig(
num_hidden_layers=base.num_hidden_layers,
num_target_layers=base.num_target_layers,
gamma=gamma,
target_layer_ids=target_layer_ids,
mask_token=base.mask_token,
mask_token_id=mask_token_id,
markov_rank=markov_rank,
markov_head_type=markov_head_type,
)