Files
wehub-resource-sync a203934033
Lint test / lint (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:34:58 +08:00

510 lines
21 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Copyright (c) ModelScope Contributors. All rights reserved.
import sys
import torch
from transformers import AutoModel, PretrainedConfig, PreTrainedModel
from typing import Any, Dict
from swift.template import TemplateType
from swift.utils import Processor, get_logger, git_clone_github
from ..constant import LLMModelType, MLLMModelType
from ..model_arch import ModelArch
from ..model_meta import Model, ModelGroup, ModelMeta
from ..patcher import patch_output_clone, patch_output_to_input_device
from ..register import ModelLoader, register_model
from ..utils import use_submodel_func
class DeepseekLoader(ModelLoader):
def get_model(self, model_dir: str, *args, **kwargs) -> PreTrainedModel:
model = super().get_model(model_dir, *args, **kwargs)
# fix dtype bug
mlp_cls = model.model.layers[-1].mlp.__class__
for module in model.modules():
if isinstance(module, mlp_cls):
patch_output_to_input_device(module)
return model
register_model(
ModelMeta(
LLMModelType.deepseek,
[
ModelGroup([
Model('deepseek-ai/deepseek-moe-16b-chat', 'deepseek-ai/deepseek-moe-16b-chat'),
Model('deepseek-ai/deepseek-moe-16b-base', 'deepseek-ai/deepseek-moe-16b-base'),
], ),
],
DeepseekLoader,
template=TemplateType.deepseek,
architectures=['DeepseekForCausalLM'],
))
register_model(
ModelMeta(
LLMModelType.deepseek_v2,
[
ModelGroup([
Model('deepseek-ai/DeepSeek-Coder-V2-Instruct', 'deepseek-ai/DeepSeek-Coder-V2-Instruct'),
Model('deepseek-ai/DeepSeek-Coder-V2-Lite-Instruct', 'deepseek-ai/DeepSeek-Coder-V2-Lite-Instruct'),
Model('deepseek-ai/DeepSeek-Coder-V2-Base', 'deepseek-ai/DeepSeek-Coder-V2-Base'),
Model('deepseek-ai/DeepSeek-Coder-V2-Lite-Base', 'deepseek-ai/DeepSeek-Coder-V2-Lite-Base'),
Model('deepseek-ai/DeepSeek-V2-Lite', 'deepseek-ai/DeepSeek-V2-Lite'),
Model('deepseek-ai/DeepSeek-V2-Lite-Chat', 'deepseek-ai/DeepSeek-V2-Lite-Chat'),
Model('deepseek-ai/DeepSeek-V2', 'deepseek-ai/DeepSeek-V2'),
Model('deepseek-ai/DeepSeek-V2-Chat', 'deepseek-ai/DeepSeek-V2-Chat'),
], TemplateType.deepseek),
ModelGroup([
Model('deepseek-ai/DeepSeek-V2.5', 'deepseek-ai/DeepSeek-V2.5'),
Model('deepseek-ai/DeepSeek-V2.5-1210', 'deepseek-ai/DeepSeek-V2.5-1210')
], TemplateType.deepseek_v2_5)
],
DeepseekLoader,
model_arch=ModelArch.deepseek_v2,
architectures=['DeepseekV2ForCausalLM'],
requires=['transformers>=4.39.3'],
))
register_model(
ModelMeta(
LLMModelType.deepseek_v3,
[
ModelGroup([
Model('deepseek-ai/DeepSeek-V3-Base', 'deepseek-ai/DeepSeek-V3-Base'),
Model('deepseek-ai/DeepSeek-V3', 'deepseek-ai/DeepSeek-V3'),
Model('deepseek-ai/DeepSeek-V3-0324', 'deepseek-ai/DeepSeek-V3-0324'),
], TemplateType.deepseek_v2_5),
ModelGroup([
Model('cognitivecomputations/DeepSeek-V3-awq', 'cognitivecomputations/DeepSeek-V3-AWQ'),
Model('cognitivecomputations/DeepSeek-V3-0324-AWQ', 'cognitivecomputations/DeepSeek-V3-0324-AWQ')
], TemplateType.deepseek_v2_5),
ModelGroup([
Model('deepseek-ai/DeepSeek-Prover-V2-7B', 'deepseek-ai/DeepSeek-Prover-V2-7B'),
Model('deepseek-ai/DeepSeek-Prover-V2-671B', 'deepseek-ai/DeepSeek-Prover-V2-671B'),
], TemplateType.deepseek_v2_5),
ModelGroup([
Model('unsloth/DeepSeek-V3-bf16', 'unsloth/DeepSeek-V3-bf16'),
Model('unsloth/DeepSeek-V3-0324-BF16', 'unsloth/DeepSeek-V3-0324-BF16'),
Model('unsloth/DeepSeek-Prover-V2-671B-BF16', 'unsloth/DeepSeek-Prover-V2-671B-BF16'),
], TemplateType.deepseek_v2_5),
ModelGroup([
Model('deepseek-ai/DeepSeek-R1', 'deepseek-ai/DeepSeek-R1'),
Model('deepseek-ai/DeepSeek-R1-Zero', 'deepseek-ai/DeepSeek-R1-Zero'),
Model('deepseek-ai/DeepSeek-R1-0528', 'deepseek-ai/DeepSeek-R1-0528'),
], TemplateType.deepseek_r1),
ModelGroup([
Model('cognitivecomputations/DeepSeek-R1-awq', 'cognitivecomputations/DeepSeek-R1-AWQ'),
Model('cognitivecomputations/DeepSeek-R1-0528-AWQ', 'cognitivecomputations/DeepSeek-R1-0528-AWQ'),
], TemplateType.deepseek_r1),
ModelGroup([
Model('unsloth/DeepSeek-R1-BF16', 'unsloth/DeepSeek-R1-BF16'),
Model('unsloth/DeepSeek-R1-Zero-BF16', 'unsloth/DeepSeek-R1-Zero-BF16'),
Model('unsloth/DeepSeek-R1-0528-BF16', 'unsloth/DeepSeek-R1-0528-BF16'),
], TemplateType.deepseek_r1),
ModelGroup([
Model('moonshotai/Moonlight-16B-A3B', 'moonshotai/Moonlight-16B-A3B'),
Model('moonshotai/Moonlight-16B-A3B-Instruct', 'moonshotai/Moonlight-16B-A3B-Instruct'),
],
TemplateType.moonlight,
requires=['transformers<4.49']),
ModelGroup([
Model('moonshotai/Kimi-K2-Base', 'moonshotai/Kimi-K2-Base'),
Model('moonshotai/Kimi-K2-Instruct', 'moonshotai/Kimi-K2-Instruct'),
Model('moonshotai/Kimi-K2-Instruct-0905', 'moonshotai/Kimi-K2-Instruct-0905'),
Model('moonshotai/Kimi-K2-Thinking', 'moonshotai/Kimi-K2-Thinking'),
], TemplateType.kimi_k2),
ModelGroup([
Model('deepseek-ai/DeepSeek-V3.1-Base', 'deepseek-ai/DeepSeek-V3.1-Base'),
Model('deepseek-ai/DeepSeek-V3.1', 'deepseek-ai/DeepSeek-V3.1'),
Model('deepseek-ai/DeepSeek-V3.1-Terminus', 'deepseek-ai/DeepSeek-V3.1-Terminus'),
], TemplateType.deepseek_v3_1),
],
DeepseekLoader,
model_arch=ModelArch.deepseek_v2,
architectures=['DeepseekV3ForCausalLM'],
requires=['transformers>=4.39.3'],
))
class DeepseekV32Loader(ModelLoader):
def get_config(self, model_dir: str):
try:
from transformers.models.deepseek_v32 import DeepseekV32Config
except ImportError:
from transformers.models.deepseek_v3 import DeepseekV3Config as DeepseekV32Config
return DeepseekV32Config.from_pretrained(model_dir)
def get_model(self, model_dir: str, *args, **kwargs) -> PreTrainedModel:
try:
from transformers.models.deepseek_v32 import DeepseekV32ForCausalLM
except ImportError:
# Its only for compatibility with Megatron training or vllm/sglang infer,
# while we wait for Transformers to support deepseek_v32.
from transformers.models.deepseek_v3 import DeepseekV3ForCausalLM as DeepseekV32ForCausalLM
if not self.return_dummy_model:
raise ValueError('DeepSeek-V3.2 is not supported in transformers.')
self.auto_model_cls = DeepseekV32ForCausalLM
return super().get_model(model_dir, *args, **kwargs)
register_model(
ModelMeta(
LLMModelType.deepseek_v32,
[
ModelGroup([
Model('deepseek-ai/DeepSeek-V3.2', 'deepseek-ai/DeepSeek-V3.2'),
Model('deepseek-ai/DeepSeek-V3.2-Speciale', 'deepseek-ai/DeepSeek-V3.2-Speciale'),
Model('deepseek-ai/DeepSeek-V3.2-Exp', 'deepseek-ai/DeepSeek-V3.2-Exp'),
Model('deepseek-ai/DeepSeek-V3.2-Exp-Base', 'deepseek-ai/DeepSeek-V3.2-Exp-Base'),
Model('deepseek-ai/DeepSeek-Math-V2', 'deepseek-ai/DeepSeek-Math-V2'),
]),
],
DeepseekV32Loader,
template=TemplateType.deepseek_v3_1,
architectures=['DeepseekV32ForCausalLM'],
))
register_model(
ModelMeta(
LLMModelType.deepseek_v4,
[
ModelGroup([
Model('deepseek-ai/DeepSeek-V4-Flash', 'deepseek-ai/DeepSeek-V4-Flash'),
Model('deepseek-ai/DeepSeek-V4-Flash-Base', 'deepseek-ai/DeepSeek-V4-Flash-Base'),
]),
ModelGroup([
Model('deepseek-ai/DeepSeek-V4-Pro', 'deepseek-ai/DeepSeek-V4-Pro'),
Model('deepseek-ai/DeepSeek-V4-Pro-Base', 'deepseek-ai/DeepSeek-V4-Pro-Base'),
]),
],
template=TemplateType.deepseek_v4,
architectures=['DeepseekV4ForCausalLM'],
))
class DeepseekVLLoader(ModelLoader):
def get_config(self, model_dir: str):
# compat with python==3.10
if sys.version_info.minor >= 10:
import collections
import collections.abc
for type_name in collections.abc.__all__:
setattr(collections, type_name, getattr(collections.abc, type_name))
local_repo_path = self.local_repo_path
if not local_repo_path:
local_repo_path = git_clone_github('https://github.com/deepseek-ai/DeepSeek-VL')
sys.path.append(local_repo_path)
from deepseek_vl.models import VLChatProcessor
self.auto_tokenizer_cls = VLChatProcessor
return super().get_config(model_dir)
def _get_model(self, model_dir: str, llm_prefix, *args, **kwargs) -> PreTrainedModel:
model = super().get_model(model_dir, *args, **kwargs)
llm = getattr(model, llm_prefix)
patch_output_clone(llm.model.embed_tokens)
patch_output_to_input_device(llm.model.embed_tokens)
use_submodel_func(model, llm_prefix)
model.generation_config = llm.generation_config
return model
def get_model(self, model_dir: str, *args, **kwargs) -> PreTrainedModel:
return self._get_model(model_dir, 'language_model', *args, **kwargs)
register_model(
ModelMeta(
MLLMModelType.deepseek_vl,
[
ModelGroup([
Model('deepseek-ai/deepseek-vl-1.3b-chat', 'deepseek-ai/deepseek-vl-1.3b-chat'),
Model('deepseek-ai/deepseek-vl-7b-chat', 'deepseek-ai/deepseek-vl-7b-chat'),
], ),
],
DeepseekVLLoader,
template=TemplateType.deepseek_vl,
architectures=['MultiModalityCausalLM'],
model_arch=ModelArch.deepseek_vl,
tags=['vision'],
))
class DeepseekJanusLoader(DeepseekVLLoader):
def get_model(self, model_dir: str, *args, **kwargs) -> PreTrainedModel:
return self._get_model(model_dir, 'language_model', *args, **kwargs)
def get_config(self, model_dir: str):
local_repo_path = self.local_repo_path
if not local_repo_path:
local_repo_path = git_clone_github('https://github.com/deepseek-ai/Janus')
sys.path.append(local_repo_path)
from janus.models import VLChatProcessor
self.auto_tokenizer_cls = VLChatProcessor
return super(DeepseekVLLoader, self).get_config(model_dir)
register_model(
ModelMeta(
MLLMModelType.deepseek_janus,
[
ModelGroup([
Model('deepseek-ai/Janus-1.3B', 'deepseek-ai/Janus-1.3B'),
]),
],
DeepseekJanusLoader,
template=TemplateType.deepseek_janus,
model_arch=ModelArch.deepseek_janus,
tags=['vision'],
))
register_model(
ModelMeta(
MLLMModelType.deepseek_janus_pro,
[
ModelGroup([
Model('deepseek-ai/Janus-Pro-1B', 'deepseek-ai/Janus-Pro-1B'),
Model('deepseek-ai/Janus-Pro-7B', 'deepseek-ai/Janus-Pro-7B'),
]),
],
DeepseekJanusLoader,
template=TemplateType.deepseek_janus_pro,
model_arch=ModelArch.deepseek_janus,
tags=['vision'],
))
class DeepseekVL2Loader(DeepseekVLLoader):
def get_config(self, model_dir: str):
local_repo_path = self.local_repo_path
if not local_repo_path:
local_repo_path = git_clone_github('https://github.com/deepseek-ai/DeepSeek-VL2')
sys.path.append(local_repo_path)
try:
from deepseek_vl2.models import DeepseekVLV2Processor
except ImportError:
# compat transformers>=4.42
import transformers
transformers.models.llama.modeling_llama.LlamaFlashAttention2 = None
from deepseek_vl2.models import DeepseekVLV2Processor
self.auto_tokenizer_cls = DeepseekVLV2Processor
return super(DeepseekVLLoader, self).get_config(model_dir)
def get_model(self, model_dir: str, *args, **kwargs) -> PreTrainedModel:
return super()._get_model(model_dir, 'language', *args, **kwargs)
register_model(
ModelMeta(
MLLMModelType.deepseek_vl2,
[
ModelGroup([
Model('deepseek-ai/deepseek-vl2-tiny', 'deepseek-ai/deepseek-vl2-tiny'),
Model('deepseek-ai/deepseek-vl2-small', 'deepseek-ai/deepseek-vl2-small'),
Model('deepseek-ai/deepseek-vl2', 'deepseek-ai/deepseek-vl2'),
]),
],
DeepseekVL2Loader,
template=TemplateType.deepseek_vl2,
model_arch=ModelArch.deepseek_vl2,
requires=['transformers<4.42'],
tags=['vision'],
))
class DeepseekOCRLoader(ModelLoader):
visual_name = 'vision_model'
def get_model(self, model_dir: str, *args, **kwargs) -> PreTrainedModel:
self.auto_model_cls = self.auto_model_cls or AutoModel
model = super().get_model(model_dir, *args, **kwargs)
patch_output_clone(model.model.embed_tokens)
patch_output_to_input_device(model.model.sam_model)
patch_output_to_input_device(getattr(model.model, self.visual_name))
patch_output_to_input_device(model.model.projector)
return model
def get_processor(self, model_dir: str, config: PretrainedConfig) -> Processor:
from transformers import AutoProcessor, AutoTokenizer
# When not loading model (e.g., vllm backend), avoid triggering AutoConfig which would execute
# trust_remote_code and cause transformers version compatibility issues
# For vllm backend, we only need the processor/tokenizer
try:
processor = AutoProcessor.from_pretrained(model_dir, trust_remote_code=True)
except Exception:
# Fallback to AutoTokenizer if AutoProcessor is not available
processor = AutoTokenizer.from_pretrained(model_dir, trust_remote_code=True)
return processor
class DeepseekOCR2Loader(DeepseekOCRLoader):
visual_name = 'qwen2_model'
register_model(
ModelMeta(
MLLMModelType.deepseek_ocr,
[
ModelGroup([
Model('deepseek-ai/DeepSeek-OCR', 'deepseek-ai/DeepSeek-OCR'),
]),
],
DeepseekOCRLoader,
template=TemplateType.deepseek_ocr,
model_arch=ModelArch.deepseek_ocr,
architectures=['DeepseekOCRForCausalLM'],
requires=['transformers==4.46.3', 'easydict'],
tags=['vision'],
))
register_model(
ModelMeta(
MLLMModelType.deepseek_ocr2,
[
ModelGroup([
Model('deepseek-ai/DeepSeek-OCR-2', 'deepseek-ai/DeepSeek-OCR-2'),
]),
],
DeepseekOCR2Loader,
template=TemplateType.deepseek_ocr2,
model_arch=ModelArch.deepseek_ocr2,
architectures=['DeepseekOCR2ForCausalLM'],
requires=['transformers==4.46.3', 'easydict'],
tags=['vision'],
))
class UnlimitedOCRLoader(DeepseekOCRLoader):
visual_name = 'vision_model'
@staticmethod
def _apply_multi_gpu_patch():
"""
Fixed two bugs affecting `UnlimitedOCRModel` in multi-GPU scenarios using `device_map='auto'`:
Bug 1 - Device mismatch in `torch.cat`:
`image_newline` and `view_seperator` are `nn.Parameter`s;
under `device_map='auto'`, their device placement might not align
with the image features.
Bug 2 - Device mismatch in `masked_scatter_`:
Hard-coded `.cuda()` usage caused a conflict where `images_in_this_batch`
resided on the projector's device (e.g., `cuda:7`),
while `inputs_embeds` resided on the device hosting `embed_tokens` (e.g., `cuda:0`).
Fix strategy: Temporarily replace `torch.cat` and `torch.Tensor.masked_scatter_` during the forward pass
to handle device placement automatically, then restore the original methods after execution.
"""
modeling_module = None
for mod_name, mod in sys.modules.items():
if 'modeling_unlimitedocr' in mod_name:
modeling_module = mod
break
if modeling_module is None:
return False
UnlimitedOCRModel = getattr(modeling_module, 'UnlimitedOCRModel', None)
if UnlimitedOCRModel is None:
return False
# Avoid redundant patching
if getattr(UnlimitedOCRModel, '_swift_multi_gpu_patched', False):
return True
_original_forward = UnlimitedOCRModel.forward
def _patched_forward(self, *args, **kwargs):
_orig_cat = torch.cat
_orig_masked_scatter_ = torch.Tensor.masked_scatter_
def _safe_cat(tensors, dim=0, **cat_kwargs):
# Using the device of the first tensor as the reference, the others are aligned to it.
ref_device = None
for t in tensors:
if isinstance(t, torch.Tensor):
ref_device = t.device
break
if ref_device is None:
return _orig_cat(tensors, dim, **cat_kwargs)
aligned = [
t.to(ref_device) if isinstance(t, torch.Tensor) and t.device != ref_device else t for t in tensors
]
return _orig_cat(aligned, dim, **cat_kwargs)
def _safe_masked_scatter_(tensor_self, mask, source):
# Use the device of tensor_self (inputs_embeds[idx]) as the reference.
dev = tensor_self.device
if mask.device != dev:
mask = mask.to(dev)
if source.device != dev:
source = source.to(dev)
return _orig_masked_scatter_(tensor_self, mask, source)
# Simultaneously replace the module namespace and the global scope (double insurance).
modeling_module.torch.cat = _safe_cat
torch.cat = _safe_cat
torch.Tensor.masked_scatter_ = _safe_masked_scatter_
try:
return _original_forward(self, *args, **kwargs)
finally:
# Restore the state to avoid contaminating other modules.
modeling_module.torch.cat = _orig_cat
torch.cat = _orig_cat
torch.Tensor.masked_scatter_ = _orig_masked_scatter_
UnlimitedOCRModel.forward = _patched_forward
UnlimitedOCRModel._swift_multi_gpu_patched = True
return True
def get_model(self, model_dir: str, *args, **kwargs) -> PreTrainedModel:
logger = get_logger()
self.auto_model_cls = self.auto_model_cls or AutoModel
model = super(DeepseekOCRLoader, self).get_model(model_dir, *args, **kwargs)
patch_output_clone(model.model.embed_tokens)
patch_output_to_input_device(model.model.sam_model)
patch_output_to_input_device(getattr(model.model, self.visual_name))
patch_output_to_input_device(model.model.projector)
patch_output_to_input_device(model.model)
_orig_sw = (getattr(model.config, 'sliding_window_size', None) or getattr(model.config, 'sliding_window', None))
if _orig_sw is not None:
model.config._ring_window = _orig_sw
model.config.sliding_window = None
logger.info('[UnlimitedOCR] R-SWA enabled: ring_window=%d', _orig_sw)
else:
logger.warning('[UnlimitedOCR] sliding_window config not found, R-SWA may not work.')
n_devices = len(set(str(p.device) for p in model.parameters() if p.device.type == 'cuda'))
if n_devices > 1:
if self._apply_multi_gpu_patch():
logger.info('[UnlimitedOCR] Multi-GPU patch applied (%d GPUs).', n_devices)
else:
logger.warning('[UnlimitedOCR] Multi-GPU deployment failed to apply patch.'
'If an inference error occurs, please check whether'
' `modeling_unlimitedocr` has been loaded correctly.')
return model
register_model(
ModelMeta(
MLLMModelType.unlimited_ocr,
[
ModelGroup([
Model('PaddlePaddle/Unlimited-OCR', 'PaddlePaddle/Unlimited-OCR'),
]),
],
UnlimitedOCRLoader,
template=TemplateType.unlimited_ocr,
model_arch=ModelArch.unlimited_ocr,
architectures=['UnlimitedOCRForCausalLM'],
requires=['transformers==4.46.3', 'easydict'],
tags=['vision'],
))