SWIFT 后训练 Deepseek-VL2 命令

发布于:2025-02-13 ⋅ 阅读:(14) ⋅ 点赞:(0)

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 文件的主要用途和功能:

主要用途

  1. 标记包

    • 在Python 2中,__init__.py 文件是必需的,用于将一个目录标记为包。虽然在Python 3中不再是强制要求,但它仍然是推荐的做法。
    • 它明确地告诉Python解释器,这个目录应该被视为一个包,并且可以包含其他模块。
  2. 初始化代码

    • 可以在 __init__.py 文件中编写初始化代码,这些代码会在包第一次被导入时执行。例如,设置全局变量、配置日志记录、初始化资源等。
  3. 控制包的内容

    • 通过在 __init__.py 中定义 __all__ 列表,可以显式指定哪些模块或对象会被导出(即可以通过 from package import * 导入)。
    • 这有助于隐藏内部实现细节,只暴露必要的接口给外部使用。
  4. 简化导入路径

    • 可以在 __init__.py 中导入子模块或子包,使得用户可以直接从包名导入所需的功能,而不需要知道具体的子模块路径。例如:
      # 在 __init__.py 中
      from .submodule import some_function
      
      # 用户可以直接这样导入
      from package import some_function
      
  5. 惰性加载和按需加载

    • 如您之前提到的,可以利用 __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_afunction_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_amodule_b 只有在它们的实际函数被调用时才会被加载。