SWIFT 后训练 Deepseek-VL2 命令
flyfish
后训练命令
CUDA_VISIBLE_DEVICES=1 swift sft --model deepseek-ai/deepseek-vl2-tiny --dataset coco-en-mini
swift/cli/sft.py
from swift.llm import sft_main
if __name__ == '__main__':
sft_main()
init.py
在类型检查阶段导入所有必要的类型信息,以帮助类型检查工具正常工作;在正常运行阶段,使用 _LazyModule
类实现模块的惰性加载,从而提高性能和减少内存占用。
from typing import TYPE_CHECKING
# 导入 _LazyModule 类,该类用于实现模块的惰性加载,即只有在真正使用模块中的对象时才进行加载,可提高性能和减少内存占用
from swift.utils.import_utils import _LazyModule
# TYPE_CHECKING 是一个布尔值常量,在类型检查工具(如 mypy)运行时为 True,在正常运行时为 False。
# 此条件判断用于区分类型检查阶段和正常运行阶段
if TYPE_CHECKING:
# 在类型检查阶段,导入以下模块中的函数和类,这样类型检查工具可以正确识别代码中的类型信息,
# 但这些导入不会在实际运行时产生开销
from .infer import (
# VllmEngine 是基于 vLLM 的推理引擎类
VllmEngine,
# RequestConfig 用于配置推理请求的参数
RequestConfig,
# LmdeployEngine 是基于 lmdeploy 的推理引擎类
LmdeployEngine,
# PtEngine 可能是基于 PyTorch 的推理引擎类
PtEngine,
# InferEngine 是通用的推理引擎基类
InferEngine,
# infer_main 是推理主函数,用于启动推理流程
infer_main,
# deploy_main 是部署主函数,用于启动推理服务的部署
deploy_main,
# InferClient 是推理客户端类,用于与推理服务进行交互
InferClient,
# run_deploy 用于运行部署操作
run_deploy,
# AdapterRequest 是适配器请求类,可能用于对请求进行适配处理
AdapterRequest,
# prepare_model_template 用于准备模型模板
prepare_model_template
)
from .export import (
# export_main 是导出主函数,用于将模型导出为特定格式
export_main,
# merge_lora 用于合并 LoRA(Low-Rank Adaptation)权重到基础模型中
merge_lora,
# quantize_model 用于对模型进行量化操作,以减少模型大小和计算量
quantize_model,
# export_to_ollama 用于将模型导出为 Ollama 支持的格式
export_to_ollama
)
from .eval import (
# eval_main 是评估主函数,用于对模型进行评估
eval_main
)
from .app import (
# app_main 是应用主函数,可能用于启动一个基于模型的应用程序
app_main
)
from .train import (
# sft_main 是监督微调主函数,用于对模型进行监督微调训练
sft_main,
# pt_main 可能是预训练主函数,用于对模型进行预训练
pt_main,
# rlhf_main 是基于强化学习的人类反馈微调主函数,用于使用人类反馈对模型进行微调
rlhf_main,
# get_multimodal_target_regex 用于获取多模态目标的正则表达式
get_multimodal_target_regex
)
from .argument import (
# EvalArguments 是评估参数类,用于配置评估过程中的参数
EvalArguments,
# InferArguments 是推理参数类,用于配置推理过程中的参数
InferArguments,
# TrainArguments 是训练参数类,用于配置训练过程中的参数
TrainArguments,
# ExportArguments 是导出参数类,用于配置模型导出过程中的参数
ExportArguments,
# DeployArguments 是部署参数类,用于配置模型部署过程中的参数
DeployArguments,
# RLHFArguments 是基于强化学习的人类反馈微调参数类,用于配置 RLHF 过程中的参数
RLHFArguments,
# WebUIArguments 是 Web 界面参数类,用于配置基于 Web 的用户界面的参数
WebUIArguments,
# BaseArguments 是基础参数类,可能包含一些通用的参数配置
BaseArguments,
# AppArguments 是应用参数类,用于配置应用程序的参数
AppArguments
)
from .template import (
# TEMPLATE_MAPPING 是模板映射字典,用于存储不同模板的映射关系
TEMPLATE_MAPPING,
# Template 是模板类,用于定义和处理模型输入输出的模板
Template,
# Word 可能是模板中的单词类,用于处理模板中的文本元素
Word,
# get_template 用于根据名称获取对应的模板
get_template,
# TemplateType 是模板类型枚举类,用于定义不同类型的模板
TemplateType,
# register_template 用于注册新的模板
register_template,
# TemplateInputs 是模板输入类,用于封装模板的输入信息
TemplateInputs,
# TemplateMeta 是模板元信息类,用于存储模板的元数据
TemplateMeta,
# get_template_meta 用于获取模板的元信息
get_template_meta,
# InferRequest 是推理请求类,用于封装推理请求的信息
InferRequest,
# load_image 用于加载图像数据
load_image,
# MaxLengthError 是最大长度错误类,用于处理输入超过最大长度的错误
MaxLengthError,
# load_file 用于加载文件数据
load_file,
# draw_bbox 用于绘制边界框,可能用于多模态任务中的图像标注
draw_bbox
)
from .model import (
# register_model 用于注册新的模型
register_model,
# MODEL_MAPPING 是模型映射字典,用于存储不同模型的映射关系
MODEL_MAPPING,
# ModelType 是模型类型枚举类,用于定义不同类型的模型
ModelType,
# get_model_tokenizer 用于获取模型和对应的分词器
get_model_tokenizer,
# safe_snapshot_download 用于安全地下载模型快照
safe_snapshot_download,
# HfConfigFactory 是 Hugging Face 配置工厂类,用于创建 Hugging Face 模型的配置
HfConfigFactory,
# ModelInfo 是模型信息类,用于存储模型的相关信息
ModelInfo,
# ModelMeta 是模型元信息类,用于存储模型的元数据
ModelMeta,
# ModelKeys 是模型键类,用于定义模型的关键信息
ModelKeys,
# register_model_arch 用于注册新的模型架构
register_model_arch,
# MultiModelKeys 是多模型键类,用于处理多个模型的关键信息
MultiModelKeys,
# ModelArch 是模型架构类,用于定义模型的架构
ModelArch,
# get_model_arch 用于获取模型的架构
get_model_arch,
# MODEL_ARCH_MAPPING 是模型架构映射字典,用于存储不同模型架构的映射关系
MODEL_ARCH_MAPPING,
# get_model_info_meta 用于获取模型的信息和元数据
get_model_info_meta,
# get_model_name 用于获取模型的名称
get_model_name,
# ModelGroup 是模型组类,用于管理多个模型
ModelGroup,
# Model 是模型类,可能是模型的基类
Model,
# get_model_tokenizer_with_flash_attn 用于获取支持 Flash Attention 的模型和分词器
get_model_tokenizer_with_flash_attn,
# get_model_tokenizer_multimodal 用于获取多模态模型和分词器
get_model_tokenizer_multimodal,
# load_by_unsloth 可能是使用 Unsloth 库加载模型的函数
load_by_unsloth,
# git_clone_github 用于从 GitHub 克隆模型仓库
git_clone_github,
# get_matched_model_meta 用于获取匹配的模型元信息
get_matched_model_meta
)
from .dataset import (
# AlpacaPreprocessor 是 Alpaca 数据集的预处理器类,用于对 Alpaca 数据集进行预处理
AlpacaPreprocessor,
# ResponsePreprocessor 是响应预处理器类,用于对模型的响应进行预处理
ResponsePreprocessor,
# MessagesPreprocessor 是消息预处理器类,用于对消息数据进行预处理
MessagesPreprocessor,
# AutoPreprocessor 是自动预处理器类,可根据数据集类型自动选择预处理器
AutoPreprocessor,
# DATASET_MAPPING 是数据集映射字典,用于存储不同数据集的映射关系
DATASET_MAPPING,
# MediaResource 是媒体资源类,用于处理数据集中的媒体资源
MediaResource,
# register_dataset 用于注册新的数据集
register_dataset,
# register_dataset_info 用于注册数据集的信息
register_dataset_info,
# EncodePreprocessor 是编码预处理器类,用于对数据进行编码处理
EncodePreprocessor,
# LazyLLMDataset 是惰性加载的大语言模型数据集类,可在需要时加载数据
LazyLLMDataset,
# ConstantLengthDataset 是固定长度数据集类,用于将数据集处理为固定长度
ConstantLengthDataset,
# load_dataset 用于加载数据集
load_dataset,
# DATASET_TYPE 是数据集类型枚举类,用于定义不同类型的数据集
DATASET_TYPE,
# sample_dataset 用于对数据集进行采样
sample_dataset,
# RowPreprocessor 是行预处理器类,用于对数据集中的每一行进行预处理
RowPreprocessor,
# DatasetMeta 是数据集元信息类,用于存储数据集的元数据
DatasetMeta
)
from .utils import (
# deep_getattr 是深度获取属性的函数,可递归获取对象的属性
deep_getattr,
# to_device 用于将数据移动到指定的设备(如 GPU)上
to_device,
# History 是历史记录类,用于存储对话历史等信息
History,
# Messages 是消息类,用于封装消息数据
Messages,
# history_to_messages 用于将历史记录转换为消息列表
history_to_messages,
# messages_to_history 用于将消息列表转换为历史记录
messages_to_history,
# Processor 是处理器基类,可用于定义各种数据处理逻辑
Processor,
# save_checkpoint 用于保存模型的检查点
save_checkpoint,
# ProcessorMixin 是处理器混合类,可用于为类添加处理功能
ProcessorMixin,
# get_temporary_cache_files_directory 用于获取临时缓存文件目录
get_temporary_cache_files_directory,
# get_cache_dir 用于获取缓存目录
get_cache_dir
)
from .base import (
# SwiftPipeline 是 Swift 管道类,可能用于定义和管理模型处理的流程
SwiftPipeline
)
else:
# 在正常运行阶段,定义一个字典,包含所有不以 '_' 开头的全局变量,这些变量将被包含在惰性加载的模块中
_extra_objects = {k: v for k, v in globals().items() if not k.startswith('_')}
# 定义一个字典,表示各个子模块及其导出的对象,这些对象将在需要时进行惰性加载
_import_structure = {
'rlhf': ['rlhf_main'],
'infer': [
'deploy_main', 'VllmEngine', 'RequestConfig', 'LmdeployEngine', 'PtEngine', 'infer_main', 'InferClient',
'run_deploy', 'InferEngine', 'AdapterRequest', 'prepare_model_template'
],
'export': ['export_main', 'merge_lora', 'quantize_model', 'export_to_ollama'],
'app': ['app_main'],
'eval': ['eval_main'],
'train': ['sft_main', 'pt_main', 'rlhf_main', 'get_multimodal_target_regex'],
'argument': [
'EvalArguments', 'InferArguments', 'TrainArguments', 'ExportArguments', 'WebUIArguments', 'DeployArguments',
'RLHFArguments', 'BaseArguments', 'AppArguments'
],
'template': [
'TEMPLATE_MAPPING', 'Template', 'Word', 'get_template', 'TemplateType', 'register_template',
'TemplateInputs', 'TemplateMeta', 'get_template_meta', 'InferRequest', 'load_image', 'MaxLengthError',
'load_file', 'draw_bbox'
],
'model': [
'MODEL_MAPPING', 'ModelType', 'get_model_tokenizer', 'safe_snapshot_download', 'HfConfigFactory',
'ModelInfo', 'ModelMeta', 'ModelKeys', 'register_model_arch', 'MultiModelKeys', 'ModelArch',
'MODEL_ARCH_MAPPING', 'get_model_arch', 'get_model_info_meta', 'get_model_name', 'register_model',
'ModelGroup', 'Model', 'get_model_tokenizer_with_flash_attn', 'get_model_tokenizer_multimodal',
'load_by_unsloth', 'git_clone_github', 'get_matched_model_meta'
],
'dataset': [
'AlpacaPreprocessor', 'MessagesPreprocessor', 'DATASET_MAPPING', 'MediaResource', 'register_dataset',
'register_dataset_info', 'EncodePreprocessor', 'LazyLLMDataset', 'ConstantLengthDataset', 'load_dataset',
'DATASET_TYPE', 'sample_dataset', 'RowPreprocessor', 'ResponsePreprocessor', 'DatasetMeta'
],
'utils': [
'deep_getattr', 'to_device', 'History', 'Messages', 'history_to_messages', 'messages_to_history',
'Processor', 'save_checkpoint', 'ProcessorMixin', 'get_temporary_cache_files_directory', 'get_cache_dir'
],
'base': ['SwiftPipeline'],
}
import sys
# 使用 _LazyModule 类替换当前模块,实现模块的惰性加载。
# 当代码尝试访问模块中的对象时,_LazyModule 会动态加载所需的子模块和对象,而不是在模块导入时就全部加载
sys.modules[__name__] = _LazyModule(
__name__, # 当前模块的名称
globals()['__file__'], # 当前模块的文件路径
_import_structure, # 子模块及其导出对象的映射字典
module_spec=__spec__, # 模块的规格信息
extra_objects=_extra_objects # 额外的全局对象
)
Python __init__.py
文件的作用
在Python中,__init__.py
文件是一个特殊的文件,用于将一个目录标记为一个Python包(package)。虽然从Python 3.3开始,引入了隐式命名空间包(Implicit Namespace Packages),允许没有 __init__.py
文件的目录也被视为包,但 __init__.py
文件仍然具有重要的作用。以下是 __init__.py
文件的主要用途和功能:
主要用途
标记包:
- 在Python 2中,
__init__.py
文件是必需的,用于将一个目录标记为包。虽然在Python 3中不再是强制要求,但它仍然是推荐的做法。 - 它明确地告诉Python解释器,这个目录应该被视为一个包,并且可以包含其他模块。
- 在Python 2中,
初始化代码:
- 可以在
__init__.py
文件中编写初始化代码,这些代码会在包第一次被导入时执行。例如,设置全局变量、配置日志记录、初始化资源等。
- 可以在
控制包的内容:
- 通过在
__init__.py
中定义__all__
列表,可以显式指定哪些模块或对象会被导出(即可以通过from package import *
导入)。 - 这有助于隐藏内部实现细节,只暴露必要的接口给外部使用。
- 通过在
简化导入路径:
- 可以在
__init__.py
中导入子模块或子包,使得用户可以直接从包名导入所需的功能,而不需要知道具体的子模块路径。例如:# 在 __init__.py 中 from .submodule import some_function # 用户可以直接这样导入 from package import some_function
- 可以在
惰性加载和按需加载:
- 如您之前提到的,可以利用
__init__.py
实现惰性加载(Lazy Loading),即在实际需要时才加载某些模块,从而优化性能和内存使用。
- 如您之前提到的,可以利用
示例
__init__.py
文件在Python包中扮演着多种角色,包括但不限于:
- 标记目录为包
- 执行初始化代码
- 控制包的内容和接口
- 简化导入路径
- 实现惰性加载
假设有一个项目结构如下:
my_package/
__init__.py
module_a.py
module_b.py
subpackage/
__init__.py
module_c.py
简单的 __init__.py
# my_package/__init__.py
print("Initializing my_package")
当您导入 my_package
时,这段打印语句会执行,表明包正在被初始化。
控制包内容
# my_package/__init__.py
from .module_a import function_a
from .module_b import function_b
__all__ = ['function_a', 'function_b']
在这种情况下,用户可以通过以下方式导入 function_a
和 function_b
:
from my_package import function_a, function_b
同时,from my_package import *
只会导入 __all__
列表中指定的对象。
惰性加载
如前所述,可以使用 _LazyModule
类实现惰性加载:
# my_package/__init__.py
import sys
from typing import TYPE_CHECKING
from swift.utils.import_utils import _LazyModule
if TYPE_CHECKING:
from .module_a import function_a
from .module_b import function_b
else:
_import_structure = {
'module_a': ['function_a'],
'module_b': ['function_b'],
}
sys.modules[__name__] = _LazyModule(
__name__,
globals()['__file__'],
_import_structure,
module_spec=__spec__,
)
在这个例子中,module_a
和 module_b
只有在它们的实际函数被调用时才会被加载。