Fix DeepSeek V4 loading with RunAI Model Streamer. (#30240)

This commit is contained in:
Broduker
2026-07-30 23:03:34 +08:00
committed by GitHub
parent c5bd3d7dce
commit b61cb5f9de
3 changed files with 185 additions and 14 deletions
+60 -10
View File
@@ -119,7 +119,10 @@ from sglang.srt.model_executor.runner_backend_utils.tc_piecewise_cuda_graph impo
get_tc_piecewise_forward_context,
)
from sglang.srt.model_loader.utils import maybe_executor_submit, should_async_load
from sglang.srt.model_loader.weight_utils import default_weight_loader
from sglang.srt.model_loader.weight_utils import (
RUNAI_STREAMER_TENSOR_ATTR,
default_weight_loader,
)
from sglang.srt.models.dbrx import ReplicatedLinear
from sglang.srt.models.deepseek_common.amd.deepseek_v4_fused_mhc import (
try_fused_hc_post_pre,
@@ -2814,13 +2817,7 @@ class DeepseekV4ForCausalLM(nn.Module):
raise ValueError("num_nextn_predict_layers is not in the config")
if not envs.SGLANG_OPT_FP8_WO_A_GEMM.get():
weights = list(weights)
exists_wo_a_scale = any(n.endswith(".wo_a.scale") for n, t in weights)
if exists_wo_a_scale:
logger.info("Execute dequant fp8 wo_a")
weights = _dequant_fp8_wo_a(weights)
else:
logger.info("Skip dequant fp8 wo_a")
weights = _dequant_fp8_wo_a_streaming(weights)
stacked_params_mapping = DEEPSEEK_V4_STACKED_PARAMS_MAPPING
@@ -3026,7 +3023,7 @@ class DeepseekV4ForCausalLM(nn.Module):
if key not in cache_compressor_weight:
cache_compressor_weight[key] = (
is_kv,
loaded_weight,
_clone_if_runai_streamed_tensor(loaded_weight),
)
else:
assert key in cache_compressor_weight
@@ -3064,7 +3061,9 @@ class DeepseekV4ForCausalLM(nn.Module):
assert (
shard_key not in bucket
), f"duplicate shard {shard_key} for {param_name}"
bucket[shard_key] = loaded_weight
bucket[shard_key] = _clone_if_runai_streamed_tensor(
loaded_weight
)
if len(bucket) == 2:
fused_weight = torch.cat(
[bucket["q"], bucket["kv"]], dim=0
@@ -3194,6 +3193,57 @@ def _dequant_fp8(weight: torch.Tensor, scale: torch.Tensor) -> torch.Tensor:
return result.to(torch.bfloat16)
def _clone_if_runai_streamed_tensor(tensor: torch.Tensor) -> torch.Tensor:
if getattr(tensor, RUNAI_STREAMER_TENSOR_ATTR, False):
return tensor.clone().detach()
return tensor
def _dequant_fp8_wo_a_streaming(
weights: Iterable[Tuple[str, torch.Tensor]],
) -> Iterable[Tuple[str, torch.Tensor]]:
pending: dict[str, dict[str, torch.Tensor]] = {}
saw_wo_a_scale = False
emitted = False
for name, tensor in weights:
if name.endswith(".wo_a.weight"):
prefix = name[: -len(".weight")]
bucket = pending.setdefault(prefix, {})
scale = bucket.pop("scale", None)
if scale is not None:
pending.pop(prefix, None)
emitted = True
yield name, _dequant_fp8(tensor, scale)
else:
bucket["weight"] = _clone_if_runai_streamed_tensor(tensor)
continue
if name.endswith(".wo_a.scale"):
saw_wo_a_scale = True
prefix = name[: -len(".scale")]
bucket = pending.setdefault(prefix, {})
weight = bucket.pop("weight", None)
if weight is not None:
pending.pop(prefix, None)
emitted = True
yield prefix + ".weight", _dequant_fp8(weight, tensor)
else:
bucket["scale"] = _clone_if_runai_streamed_tensor(tensor)
continue
yield name, tensor
if emitted:
logger.info("Finished streaming dequant fp8 wo_a")
for prefix, bucket in pending.items():
if "weight" in bucket:
assert not saw_wo_a_scale, f"{prefix}.scale is missing"
yield prefix + ".weight", bucket["weight"]
if "scale" in bucket:
yield prefix + ".scale", bucket["scale"]
def _dequant_fp8_wo_a(
weights: Iterable[Tuple[str, torch.Tensor]],
) -> Iterable[Tuple[str, torch.Tensor]]:
@@ -30,7 +30,7 @@ from sglang.srt.models.deepseek_v4 import (
DEEPSEEK_V4_STACKED_PARAMS_MAPPING,
DeepseekV4DecoderLayer,
MqaAttentionBase,
_dequant_fp8_wo_a,
_dequant_fp8_wo_a_streaming,
hc_head_torch,
make_hc_head_params,
)
@@ -761,9 +761,7 @@ class DeepseekV4ForCausalLMDSpark(nn.Module):
params_dict = dict(self.named_parameters())
loaded_params = set()
weights = list(weights)
if any(name.endswith(".wo_a.scale") for name, _ in weights):
weights = list(_dequant_fp8_wo_a(weights))
weights = _dequant_fp8_wo_a_streaming(weights)
stacked_params_mapping = DEEPSEEK_V4_STACKED_PARAMS_MAPPING
from sglang.srt.layers.moe.fused_moe_triton import FusedMoE