nextn subclass owns post_load_weights is_nextn (#24333)
This commit is contained in:
@@ -78,7 +78,6 @@ from sglang.srt.model_loader.remote_instance_weight_loader_utils import (
|
|||||||
)
|
)
|
||||||
from sglang.srt.model_loader.utils import (
|
from sglang.srt.model_loader.utils import (
|
||||||
get_model_architecture,
|
get_model_architecture,
|
||||||
post_load_weights,
|
|
||||||
set_default_torch_dtype,
|
set_default_torch_dtype,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -286,6 +285,15 @@ def _initialize_model(
|
|||||||
return model_class(**kwargs)
|
return model_class(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
def _post_load_weights(model: nn.Module) -> None:
|
||||||
|
# Loaders that bypass `model.load_weights()` (dummy / sharded state / remote instance /
|
||||||
|
# remote fs) must trigger the model's post-load fixup explicitly; `model.load_weights()`
|
||||||
|
# would normally do it internally. NextN subclasses override the method to fill in
|
||||||
|
# `is_nextn=True`, so the loader doesn't need to know.
|
||||||
|
if hasattr(model, "post_load_weights"):
|
||||||
|
model.post_load_weights()
|
||||||
|
|
||||||
|
|
||||||
class BaseModelLoader(ABC):
|
class BaseModelLoader(ABC):
|
||||||
"""Base class for model loaders."""
|
"""Base class for model loaders."""
|
||||||
|
|
||||||
@@ -1322,7 +1330,7 @@ class DummyModelLoader(BaseModelLoader):
|
|||||||
# random values to the weights.
|
# random values to the weights.
|
||||||
initialize_dummy_weights(model)
|
initialize_dummy_weights(model)
|
||||||
|
|
||||||
post_load_weights(model, model_config)
|
_post_load_weights(model)
|
||||||
|
|
||||||
return model.eval()
|
return model.eval()
|
||||||
|
|
||||||
@@ -1465,7 +1473,7 @@ class ShardedStateLoader(BaseModelLoader):
|
|||||||
if state_dict:
|
if state_dict:
|
||||||
raise ValueError(f"Missing keys {tuple(state_dict)} in loaded state!")
|
raise ValueError(f"Missing keys {tuple(state_dict)} in loaded state!")
|
||||||
|
|
||||||
post_load_weights(model, model_config)
|
_post_load_weights(model)
|
||||||
|
|
||||||
return model.eval()
|
return model.eval()
|
||||||
|
|
||||||
@@ -2228,8 +2236,7 @@ class RemoteInstanceModelLoader(BaseModelLoader):
|
|||||||
)
|
)
|
||||||
torch.cuda.synchronize()
|
torch.cuda.synchronize()
|
||||||
|
|
||||||
if hasattr(model, "post_load_weights"):
|
_post_load_weights(model)
|
||||||
model.post_load_weights()
|
|
||||||
end_get_weights_tic = time.time()
|
end_get_weights_tic = time.time()
|
||||||
logger.debug(
|
logger.debug(
|
||||||
f"finish getting all weights from remote instance, time used: {(end_get_weights_tic - start_get_weights_tic):.4f}s"
|
f"finish getting all weights from remote instance, time used: {(end_get_weights_tic - start_get_weights_tic):.4f}s"
|
||||||
@@ -2292,8 +2299,7 @@ class RemoteInstanceModelLoader(BaseModelLoader):
|
|||||||
logger.error(f"batch transfer failed, error: {ret}")
|
logger.error(f"batch transfer failed, error: {ret}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if hasattr(model, "post_load_weights"):
|
_post_load_weights(model)
|
||||||
model.post_load_weights()
|
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@@ -2414,8 +2420,7 @@ class RemoteInstanceModelLoader(BaseModelLoader):
|
|||||||
model, transfer_engine, source_worker, tp_rank
|
model, transfer_engine, source_worker, tp_rank
|
||||||
)
|
)
|
||||||
|
|
||||||
if hasattr(model, "post_load_weights"):
|
_post_load_weights(model)
|
||||||
model.post_load_weights()
|
|
||||||
|
|
||||||
logger.info("ModelExpress: weight transfer complete for tp_rank=%d", tp_rank)
|
logger.info("ModelExpress: weight transfer complete for tp_rank=%d", tp_rank)
|
||||||
|
|
||||||
@@ -2645,7 +2650,7 @@ class RemoteModelLoader(BaseModelLoader):
|
|||||||
if state_dict:
|
if state_dict:
|
||||||
raise ValueError(f"Missing keys {tuple(state_dict)} in loaded state!")
|
raise ValueError(f"Missing keys {tuple(state_dict)} in loaded state!")
|
||||||
|
|
||||||
post_load_weights(model, model_config)
|
_post_load_weights(model)
|
||||||
|
|
||||||
def _load_model_from_remote_fs(
|
def _load_model_from_remote_fs(
|
||||||
self, model, client, model_config: ModelConfig, device_config: DeviceConfig
|
self, model, client, model_config: ModelConfig, device_config: DeviceConfig
|
||||||
|
|||||||
@@ -247,18 +247,6 @@ def get_architecture_class_name(model_config: ModelConfig) -> str:
|
|||||||
return get_model_architecture(model_config)[1]
|
return get_model_architecture(model_config)[1]
|
||||||
|
|
||||||
|
|
||||||
def post_load_weights(model: nn.Module, model_config: ModelConfig):
|
|
||||||
# Model weight loading consists of two stages:
|
|
||||||
# 1. Initial weight loading.
|
|
||||||
# 2. Post-processing of weights, including assigning specific member variables.
|
|
||||||
# For `dummy_init`, only the second stage is required.
|
|
||||||
if hasattr(model, "post_load_weights"):
|
|
||||||
if model_config.hf_config.architectures[0] == "DeepseekV3ForCausalLMNextN":
|
|
||||||
model.post_load_weights(is_nextn=True)
|
|
||||||
else:
|
|
||||||
model.post_load_weights()
|
|
||||||
|
|
||||||
|
|
||||||
def should_deepgemm_weight_requant_ue8m0(weight_block_size):
|
def should_deepgemm_weight_requant_ue8m0(weight_block_size):
|
||||||
"""Should we requant fp8 weights into UE8M0 format when loading the model"""
|
"""Should we requant fp8 weights into UE8M0 format when loading the model"""
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -217,7 +217,8 @@ class BailingMoeForCausalLMNextN(nn.Module):
|
|||||||
self.post_load_weights_func = BailingMoeV2_5ForCausalLM.post_load_weights
|
self.post_load_weights_func = BailingMoeV2_5ForCausalLM.post_load_weights
|
||||||
else:
|
else:
|
||||||
self.base_load_weights_func = BailingMoEForCausalLM.load_weights
|
self.base_load_weights_func = BailingMoEForCausalLM.load_weights
|
||||||
self.post_load_weights_func = BailingMoEForCausalLM.post_load_weights
|
# V1 BailingMoeAttention is standard QKV (no kv_b_proj), no fixup needed.
|
||||||
|
self.post_load_weights_func = None
|
||||||
|
|
||||||
@torch.no_grad()
|
@torch.no_grad()
|
||||||
def forward(
|
def forward(
|
||||||
@@ -243,8 +244,13 @@ class BailingMoeForCausalLMNextN(nn.Module):
|
|||||||
def load_weights(self, weights: Iterable[Tuple[str, torch.Tensor]]):
|
def load_weights(self, weights: Iterable[Tuple[str, torch.Tensor]]):
|
||||||
self.base_load_weights_func(self, weights, is_nextn=True)
|
self.base_load_weights_func(self, weights, is_nextn=True)
|
||||||
|
|
||||||
def post_load_weights(self, is_nextn=False, weight_names=None):
|
def post_load_weights(self, is_nextn=True, weight_names=None):
|
||||||
self.post_load_weights_func(self, is_nextn=is_nextn, weight_names=weight_names)
|
# `is_nextn` is pinned to True for the NextN subclass; the parameter is kept
|
||||||
|
# only because the underlying `load_weights` flow calls `self.post_load_weights`
|
||||||
|
# with `is_nextn=...` as a kwarg.
|
||||||
|
if self.post_load_weights_func is None:
|
||||||
|
return
|
||||||
|
self.post_load_weights_func(self, is_nextn=True, weight_names=weight_names)
|
||||||
|
|
||||||
|
|
||||||
EntryClass = [BailingMoeForCausalLMNextN]
|
EntryClass = [BailingMoeForCausalLMNextN]
|
||||||
|
|||||||
@@ -313,5 +313,11 @@ class DeepseekV3ForCausalLMNextN(DeepseekV3ForCausalLM):
|
|||||||
def load_weights(self, weights: Iterable[Tuple[str, torch.Tensor]]):
|
def load_weights(self, weights: Iterable[Tuple[str, torch.Tensor]]):
|
||||||
super().load_weights(weights, is_nextn=True)
|
super().load_weights(weights, is_nextn=True)
|
||||||
|
|
||||||
|
def post_load_weights(self, is_nextn=True, weight_names=None):
|
||||||
|
# `is_nextn` is pinned to True for the NextN subclass; the parameter is kept
|
||||||
|
# only because the mixin's `do_load_weights` calls `self.post_load_weights`
|
||||||
|
# with `is_nextn=...` as a kwarg.
|
||||||
|
super().post_load_weights(is_nextn=True, weight_names=weight_names)
|
||||||
|
|
||||||
|
|
||||||
EntryClass = [DeepseekV3ForCausalLMNextN]
|
EntryClass = [DeepseekV3ForCausalLMNextN]
|
||||||
|
|||||||
Reference in New Issue
Block a user