diffusers-源码解析-六十七-

diffusers 源码解析(六十七)

.\diffusers\utils\torch_utils.py

# 版权所有 2024 The HuggingFace Team. 保留所有权利。
#
# 根据 Apache 许可证,第 2.0 版("许可证")授权;
# 除非遵循许可证,否则您不得使用此文件。
# 您可以在以下网址获取许可证副本:
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# 除非适用法律或书面协议另有约定,软件
# 根据许可证分发,按“原样”基础提供,
# 不提供任何形式的保证或条件,无论是明示或暗示的。
# 请参见许可证以了解管理权限和
# 限制的具体条款。
"""
PyTorch 实用工具:与 PyTorch 相关的实用工具
"""

from typing import List, Optional, Tuple, Union  # 导入用于类型注释的类

from . import logging  # 从当前包中导入 logging 模块
from .import_utils import is_torch_available, is_torch_version  # 导入检查 PyTorch 可用性和版本的工具


if is_torch_available():  # 如果 PyTorch 可用
    import torch  # 导入 PyTorch 库
    from torch.fft import fftn, fftshift, ifftn, ifftshift  # 从 PyTorch 的 FFT 模块导入相关函数

logger = logging.get_logger(__name__)  # 获取当前模块的日志记录器,命名为模块名

try:
    from torch._dynamo import allow_in_graph as maybe_allow_in_graph  # 尝试导入允许在图中运行的功能
except (ImportError, ModuleNotFoundError):  # 捕获导入错误
    def maybe_allow_in_graph(cls):  # 定义一个备选函数
        return cls  # 返回原类


def randn_tensor(  # 定义生成随机张量的函数
    shape: Union[Tuple, List],  # 输入参数:张量形状,可以是元组或列表
    generator: Optional[Union[List["torch.Generator"], "torch.Generator"]] = None,  # 可选生成器,用于生成随机数
    device: Optional["torch.device"] = None,  # 可选参数,指定张量所在设备
    dtype: Optional["torch.dtype"] = None,  # 可选参数,指定张量数据类型
    layout: Optional["torch.layout"] = None,  # 可选参数,指定张量布局
):
    """一个帮助函数,用于在所需的 `device` 上创建随机张量,具有所需的 `dtype`。
    当传入生成器列表时,可以单独为每个批次大小设置种子。如果传入 CPU 生成器,张量
    始终在 CPU 上创建。
    """
    # 默认创建张量的设备为传入的设备
    rand_device = device  
    batch_size = shape[0]  # 批大小为形状的第一个元素

    layout = layout or torch.strided  # 如果未指定布局,默认为 strided
    device = device or torch.device("cpu")  # 如果未指定设备,默认为 CPU

    if generator is not None:  # 如果提供了生成器
        gen_device_type = generator.device.type if not isinstance(generator, list) else generator[0].device.type  # 获取生成器的设备类型
        if gen_device_type != device.type and gen_device_type == "cpu":  # 如果生成器在 CPU 上,但期望的设备不同
            rand_device = "cpu"  # 设置随机设备为 CPU
            if device != "mps":  # 如果目标设备不是 MPS
                logger.info(  # 记录信息日志
                    f"The passed generator was created on 'cpu' even though a tensor on {device} was expected."
                    f" Tensors will be created on 'cpu' and then moved to {device}. Note that one can probably"
                    f" slighly speed up this function by passing a generator that was created on the {device} device."
                )
        elif gen_device_type != device.type and gen_device_type == "cuda":  # 如果生成器在 CUDA 上,但目标设备不同
            raise ValueError(f"Cannot generate a {device} tensor from a generator of type {gen_device_type}.")  # 抛出值错误

    # 确保生成器列表长度为 1 时被视为非列表
    if isinstance(generator, list) and len(generator) == 1:  # 如果生成器是列表且长度为 1
        generator = generator[0]  # 将其转换为非列表形式
    # 检查 generator 是否为列表
        if isinstance(generator, list):
            # 调整形状以适应生成的潜在变量
            shape = (1,) + shape[1:]
            # 生成多个随机潜在变量,使用各自的生成器
            latents = [
                torch.randn(shape, generator=generator[i], device=rand_device, dtype=dtype, layout=layout)
                for i in range(batch_size)
            ]
            # 将生成的潜在变量沿第0维连接,并转换到目标设备
            latents = torch.cat(latents, dim=0).to(device)
        else:
            # 使用单个生成器生成随机潜在变量并转换到目标设备
            latents = torch.randn(shape, generator=generator, device=rand_device, dtype=dtype, layout=layout).to(device)
    
        # 返回生成的潜在变量
        return latents
# 检查模块是否使用 torch.compile() 编译
def is_compiled_module(module) -> bool:
    # 检查 PyTorch 版本是否小于 2.0.0 或者模块中没有 "_dynamo" 属性
    if is_torch_version("<", "2.0.0") or not hasattr(torch, "_dynamo"):
        # 返回 False,表示未编译
        return False
    # 返回模块是否为 OptimizedModule 类型
    return isinstance(module, torch._dynamo.eval_frame.OptimizedModule)


# 进行 Fourier 过滤,作为 FreeU 方法的一部分
def fourier_filter(x_in: "torch.Tensor", threshold: int, scale: int) -> "torch.Tensor":
    # 输入 x_in 为张量,返回经过 Fourier 过滤的张量
    x = x_in
    # 解构输入张量的形状为批量大小、通道数、高度和宽度
    B, C, H, W = x.shape

    # 非 2 的幂次图像必须转换为 float32 类型
    if (W & (W - 1)) != 0 or (H & (H - 1)) != 0:
        # 将输入张量转换为 float32 类型
        x = x.to(dtype=torch.float32)

    # 执行快速傅里叶变换(FFT)
    x_freq = fftn(x, dim=(-2, -1))
    # 将频域数据进行移位操作
    x_freq = fftshift(x_freq, dim=(-2, -1))

    # 解构频域张量的形状
    B, C, H, W = x_freq.shape
    # 创建与输入张量相同形状的全 1 掩码
    mask = torch.ones((B, C, H, W), device=x.device)

    # 计算中心行和列
    crow, ccol = H // 2, W // 2
    # 设置掩码的中心区域的值为 scale
    mask[..., crow - threshold : crow + threshold, ccol - threshold : ccol + threshold] = scale
    # 频域数据与掩码相乘,应用掩码
    x_freq = x_freq * mask

    # 进行逆快速傅里叶变换(IFFT)
    x_freq = ifftshift(x_freq, dim=(-2, -1))
    # 获取频域数据的实部作为滤波结果
    x_filtered = ifftn(x_freq, dim=(-2, -1)).real

    # 返回结果张量,转换为与输入相同的数据类型
    return x_filtered.to(dtype=x_in.dtype)


# 应用 FreeU 机制,基于输入的分辨率索引和隐藏状态
def apply_freeu(
    resolution_idx: int, hidden_states: "torch.Tensor", res_hidden_states: "torch.Tensor", **freeu_kwargs
) -> Tuple["torch.Tensor", "torch.Tensor"]:
    # 检查分辨率索引是否为 0
    if resolution_idx == 0:
        # 计算隐藏状态的一半通道数
        num_half_channels = hidden_states.shape[1] // 2
        # 将隐藏状态前一半的通道乘以 b1 缩放因子
        hidden_states[:, :num_half_channels] = hidden_states[:, :num_half_channels] * freeu_kwargs["b1"]
        # 对残差隐藏状态应用 Fourier 过滤
        res_hidden_states = fourier_filter(res_hidden_states, threshold=1, scale=freeu_kwargs["s1"])
    # 检查分辨率索引是否为 1
    if resolution_idx == 1:
        # 计算隐藏状态的一半通道数
        num_half_channels = hidden_states.shape[1] // 2
        # 将隐藏状态前一半的通道乘以 b2 缩放因子
        hidden_states[:, :num_half_channels] = hidden_states[:, :num_half_channels] * freeu_kwargs["b2"]
        # 对残差隐藏状态应用 Fourier 过滤
        res_hidden_states = fourier_filter(res_hidden_states, threshold=1, scale=freeu_kwargs["s2"])

    # 返回处理后的隐藏状态和残差隐藏状态
    return hidden_states, res_hidden_states

.\diffusers\utils\versions.py

# 版权声明,注明该代码由 HuggingFace 团队所有,并保留所有权利
# 
# 根据 Apache 许可证第 2.0 版授权;使用此文件需遵守许可证。
# 可在以下网址获取许可证:
# 
#     http://www.apache.org/licenses/LICENSE-2.0
# 
# 除非适用法律要求或书面同意,否则按“原样”分发本软件,不提供任何形式的担保或条件。
# 请参阅许可证以了解特定语言约束和
# 限制。
"""
用于处理包版本的实用工具
"""

# 导入必要的库和模块
import importlib.metadata  # 用于获取已安装模块的元数据
import operator  # 提供基本操作符的功能
import re  # 正则表达式模块,用于字符串匹配
import sys  # 系统模块,提供与Python解释器交互的功能
from typing import Optional  # 用于类型提示

from packaging import version  # 导入版本管理工具

# 定义一个操作符字典,将字符串操作符映射到相应的函数
ops = {
    "<": operator.lt,  # 小于
    "<=": operator.le,  # 小于或等于
    "==": operator.eq,  # 等于
    "!=": operator.ne,  # 不等于
    ">=": operator.ge,  # 大于或等于
    ">": operator.gt,  # 大于
}

# 定义一个函数用于比较版本号
def _compare_versions(op, got_ver, want_ver, requirement, pkg, hint):
    # 检查获取的版本或想要的版本是否为 None
    if got_ver is None or want_ver is None:
        raise ValueError(
            f"Unable to compare versions for {requirement}: need={want_ver} found={got_ver}. This is unusual. Consider"
            f" reinstalling {pkg}."
        )  # 抛出异常并提示用户
    # 使用操作符字典比较版本
    if not ops[op](version.parse(got_ver), version.parse(want_ver)):
        raise ImportError(
            f"{requirement} is required for a normal functioning of this module, but found {pkg}=={got_ver}.{hint}"
        )  # 抛出导入异常并提供错误提示

# 定义一个函数检查依赖版本
def require_version(requirement: str, hint: Optional[str] = None) -> None:
    """
    运行时检查依赖版本,使用 pip 的相同语法。

    已安装模块版本来自 *site-packages* 目录,使用 *importlib.metadata* 获取。

    参数:
        requirement (`str`): pip 风格的定义,例如 "tokenizers==0.9.4","tqdm>=4.27","numpy"
        hint (`str`, *可选*): 如果未满足要求时要打印的建议

    示例:

    ```python
    require_version("pandas>1.1.2")
    require_version("numpy>1.18.5", "this is important to have for whatever reason")
    ```py"""

    # 如果提供了 hint,则格式化为字符串
    hint = f"\n{hint}" if hint is not None else ""

    # 进行无版本检查
    if re.match(r"^[\w_\-\d]+$", requirement):
        pkg, op, want_ver = requirement, None, None  # 解析要求,提取包名
    else:  # 如果不满足前面的条件
        # 使用正则表达式查找符合格式的要求,提取包名和完整的需求字符串
        match = re.findall(r"^([^!=<>\s]+)([\s!=<>]{1,2}.+)", requirement)
        # 如果没有匹配到,抛出值错误
        if not match:
            raise ValueError(
                "requirement needs to be in the pip package format, .e.g., package_a==1.23, or package_b>=1.23, but"
                f" got {requirement}"  # 报告实际收到的格式
            )
        # 解构匹配结果,pkg为包名,want_full为完整需求字符串
        pkg, want_full = match[0]
        # 将完整需求字符串按逗号分割,可能存在多个需求
        want_range = want_full.split(",")  
        wanted = {}  # 初始化一个字典来存储期望的版本和操作符
        for w in want_range:  # 遍历每个需求
            # 使用正则表达式提取操作符和期望版本
            match = re.findall(r"^([\s!=<>]{1,2})(.+)", w)
            # 如果没有匹配到,抛出值错误
            if not match:
                raise ValueError(
                    "requirement needs to be in the pip package format, .e.g., package_a==1.23, or package_b>=1.23,"
                    f" but got {requirement}"  # 报告实际收到的格式
                )
            op, want_ver = match[0]  # 解构匹配结果,op为操作符,want_ver为期望版本
            wanted[op] = want_ver  # 将操作符和期望版本存入字典
            # 如果操作符不在预定义的操作符集合中,抛出值错误
            if op not in ops:
                raise ValueError(f"{requirement}: need one of {list(ops.keys())}, but got {op}")

    # 特殊情况处理
    if pkg == "python":  # 如果包名是python
        # 获取当前Python的版本字符串
        got_ver = ".".join([str(x) for x in sys.version_info[:3]])
        # 遍历期望的版本和操作符进行比较
        for op, want_ver in wanted.items():
            _compare_versions(op, got_ver, want_ver, requirement, pkg, hint)
        return  # 完成比较后直接返回

    # 检查是否安装了任何版本
    try:
        # 尝试获取已安装包的版本
        got_ver = importlib.metadata.version(pkg)
    except importlib.metadata.PackageNotFoundError:
        # 如果未找到包,则抛出包未找到错误
        raise importlib.metadata.PackageNotFoundError(
            f"The '{requirement}' distribution was not found and is required by this application. {hint}"
        )

    # 如果提供了版本号或范围,检查是否安装了正确的版本
    if want_ver is not None:
        for op, want_ver in wanted.items():  # 遍历期望的版本和操作符
            _compare_versions(op, got_ver, want_ver, requirement, pkg, hint)  # 进行版本比较
# 定义一个函数,检查所需版本并在失败时提供特定提示
def require_version_core(requirement):
    # 提供一个针对核心的提示,说明如何解决版本问题
    hint = "Try: pip install transformers -U or pip install -e '.[dev]' if you're working with git main"
    # 调用 require_version 函数,传入需求和提示信息
    return require_version(requirement, hint)

.\diffusers\utils\__init__.py

# 版权声明,标识该文件的版权信息及归属
# Copyright 2024 The HuggingFace Inc. team. All rights reserved.
#
# 根据 Apache License, Version 2.0 进行许可(“许可”);
# 除非遵循许可,否则不可使用此文件。
# 可以在以下网址获得许可的副本:
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# 除非适用法律或书面协议另有规定,软件根据许可分发为“按现状”基础,
# 不提供任何形式的明示或暗示的担保或条件。
# 请参阅许可以获取有关权限和限制的具体信息。
#
# 导入 os 模块,提供与操作系统交互的功能
import os

# 从 packaging 库导入 version,用于处理版本字符串
from packaging import version

# 从当前包导入版本信息
from .. import __version__

# 从 constants 模块导入多个常量
from .constants import (
    CONFIG_NAME,  # 配置文件名常量
    DEPRECATED_REVISION_ARGS,  # 已废弃的修订参数
    DIFFUSERS_DYNAMIC_MODULE_NAME,  # 动态模块名称
    FLAX_WEIGHTS_NAME,  # Flax 权重文件名
    HF_MODULES_CACHE,  # Hugging Face 模块缓存路径
    HUGGINGFACE_CO_RESOLVE_ENDPOINT,  # Hugging Face 共同解析端点
    MIN_PEFT_VERSION,  # 最小 PEFT 版本
    ONNX_EXTERNAL_WEIGHTS_NAME,  # ONNX 外部权重文件名
    ONNX_WEIGHTS_NAME,  # ONNX 权重文件名
    SAFE_WEIGHTS_INDEX_NAME,  # 安全权重索引文件名
    SAFETENSORS_FILE_EXTENSION,  # Safetensors 文件扩展名
    SAFETENSORS_WEIGHTS_NAME,  # Safetensors 权重文件名
    USE_PEFT_BACKEND,  # 是否使用 PEFT 后端的标志
    WEIGHTS_INDEX_NAME,  # 权重索引文件名
    WEIGHTS_NAME,  # 权重文件名
)

# 从 deprecation_utils 模块导入 deprecate 方法,用于处理弃用的功能
from .deprecation_utils import deprecate

# 从 doc_utils 模块导入替换文档字符串的函数
from .doc_utils import replace_example_docstring

# 从 dynamic_modules_utils 模块导入从动态模块获取类的函数
from .dynamic_modules_utils import get_class_from_dynamic_module

# 从 export_utils 模块导入导出功能,支持不同格式
from .export_utils import export_to_gif, export_to_obj, export_to_ply, export_to_video

# 从 hub_utils 模块导入与模型推送到 Hub 相关的多个功能
from .hub_utils import (
    PushToHubMixin,  # 推送到 Hub 的混合类
    _add_variant,  # 添加变体的内部函数
    _get_checkpoint_shard_files,  # 获取检查点分片文件的内部函数
    _get_model_file,  # 获取模型文件的内部函数
    extract_commit_hash,  # 提取提交哈希的函数
    http_user_agent,  # HTTP 用户代理字符串
)

# 从 import_utils 模块导入各种导入相关的工具函数和常量
from .import_utils import (
    BACKENDS_MAPPING,  # 后端映射字典
    DIFFUSERS_SLOW_IMPORT,  # 慢速导入的标志
    ENV_VARS_TRUE_AND_AUTO_VALUES,  # 环境变量的真值和自动值
    ENV_VARS_TRUE_VALUES,  # 环境变量的真值
    USE_JAX,  # 是否使用 JAX 的标志
    USE_TF,  # 是否使用 TensorFlow 的标志
    USE_TORCH,  # 是否使用 PyTorch 的标志
    DummyObject,  # 虚拟对象类
    OptionalDependencyNotAvailable,  # 可选依赖不可用的异常类
    _LazyModule,  # 懒加载模块的内部类
    get_objects_from_module,  # 从模块中获取对象的函数
    is_accelerate_available,  # 检查 accelerate 是否可用的函数
    is_accelerate_version,  # 检查 accelerate 版本的函数
    is_bitsandbytes_available,  # 检查 bitsandbytes 是否可用的函数
    is_bs4_available,  # 检查 BeautifulSoup4 是否可用的函数
    is_flax_available,  # 检查 Flax 是否可用的函数
    is_ftfy_available,  # 检查 ftfy 是否可用的函数
    is_google_colab,  # 检查是否在 Google Colab 上的函数
    is_inflect_available,  # 检查 inflect 是否可用的函数
    is_invisible_watermark_available,  # 检查隐形水印功能是否可用的函数
    is_k_diffusion_available,  # 检查 k-diffusion 是否可用的函数
    is_k_diffusion_version,  # 检查 k-diffusion 版本的函数
    is_librosa_available,  # 检查 librosa 是否可用的函数
    is_matplotlib_available,  # 检查 matplotlib 是否可用的函数
    is_note_seq_available,  # 检查 note_seq 是否可用的函数
    is_onnx_available,  # 检查 ONNX 是否可用的函数
    is_peft_available,  # 检查 PEFT 是否可用的函数
    is_peft_version,  # 检查 PEFT 版本的函数
    is_safetensors_available,  # 检查 Safetensors 是否可用的函数
    is_scipy_available,  # 检查 scipy 是否可用的函数
    is_sentencepiece_available,  # 检查 sentencepiece 是否可用的函数
    is_tensorboard_available,  # 检查 TensorBoard 是否可用的函数
    is_timm_available,  # 检查 timm 是否可用的函数
    is_torch_available,  # 检查 PyTorch 是否可用的函数
    is_torch_npu_available,  # 检查 NPU 支持的 PyTorch 是否可用的函数
    is_torch_version,  # 检查 PyTorch 版本的函数
    is_torch_xla_available,  # 检查 XLA 支持的 PyTorch 是否可用的函数
    is_torchsde_available,  # 检查 torchsde 是否可用的函数
    is_torchvision_available,  # 检查 torchvision 是否可用的函数
    is_transformers_available,  # 检查 transformers 是否可用的函数
    is_transformers_version,  # 检查 transformers 版本的函数
    is_unidecode_available,  # 检查 unidecode 是否可用的函数
    is_wandb_available,  # 检查 wandb 是否可用的函数
    is_xformers_available,  # 检查 xformers 是否可用的函数
    requires_backends,  # 确保必要后端可用的装饰器
)

# 从 loading_utils 模块导入加载图像和视频的函数
from .loading_utils import load_image, load_video

# 从 logging 模块导入获取日志记录器的函数
from .logging import get_logger

# 从 outputs 模块导入基础输出类
from .outputs import BaseOutput

# 从 peft_utils 模块导入与 PEFT 相关的多个工具函数
from .peft_utils import (
    check_peft_version,  # 检查 PEFT 版本的函数
    delete_adapter_layers,  # 删除适配器层的函数
    get_adapter_name,  # 获取适配器名称的函数
    get_peft_kwargs,  # 获取 PEFT 关键字参数的函数
    recurse_remove_peft_layers,  # 递归删除 PEFT 层的函数
    scale_lora_layers,  # 缩放 LORA 层的函数
)
    # 设置适配器层
        set_adapter_layers,
        # 设置权重并激活适配器
        set_weights_and_activate_adapters,
        # 取消缩放 LORA 层
        unscale_lora_layers,
# 从当前模块导入所需的实用函数和常量
from .pil_utils import PIL_INTERPOLATION, make_image_grid, numpy_to_pil, pt_to_pil
# 从状态字典工具模块导入多个转换函数
from .state_dict_utils import (
    convert_all_state_dict_to_peft,
    convert_state_dict_to_diffusers,
    convert_state_dict_to_kohya,
    convert_state_dict_to_peft,
    convert_unet_state_dict_to_peft,
)

# 获取当前模块的日志记录器
logger = get_logger(__name__)

# 定义检查最小版本的函数
def check_min_version(min_version):
    # 检查当前版本是否小于所需的最小版本
    if version.parse(__version__) < version.parse(min_version):
        # 如果最小版本是开发版,设置特定的错误信息
        if "dev" in min_version:
            error_message = (
                "This example requires a source install from HuggingFace diffusers (see "
                "`https://huggingface.co/docs/diffusers/installation#install-from-source`),"
            )
        else:
            # 否则,构建一般的错误信息
            error_message = f"This example requires a minimum version of {min_version},"
        # 添加当前版本信息到错误消息中
        error_message += f" but the version found is {__version__}.\n"
        # 抛出导入错误,说明版本不符合要求
        raise ImportError(error_message)

.\diffusers\video_processor.py

# 版权信息,声明版权归 HuggingFace 团队所有
# 许可协议,说明该文件在 Apache 许可证下使用
# 允许在符合许可证的情况下使用此文件
# 可通过此链接获取许可证
# 说明软件在许可证下是“按现状”提供的,没有任何形式的担保
# 说明许可证的具体权限和限制

# 导入警告模块,用于处理警告信息
import warnings
# 从 typing 模块导入类型提示相关的类型
from typing import List, Optional, Union

# 导入 NumPy 库,用于数值计算
import numpy as np
# 导入 PIL 库,用于图像处理
import PIL
# 导入 PyTorch 库,用于深度学习
import torch

# 从同一包中导入自定义图像处理类及其验证函数
from .image_processor import VaeImageProcessor, is_valid_image, is_valid_image_imagelist

# 定义一个简单的视频处理类,继承自 VaeImageProcessor
class VideoProcessor(VaeImageProcessor):
    r"""简单的视频处理器。"""

    # 定义视频后处理方法,接受视频张量和输出类型作为参数
    def postprocess_video(
        self, video: torch.Tensor, output_type: str = "np"
    ) -> Union[np.ndarray, torch.Tensor, List[PIL.Image.Image]]:
        r"""
        将视频张量转换为可导出的帧列表。

        参数:
            video (`torch.Tensor`): 视频以张量形式表示。
            output_type (`str`, defaults to `"np"`): 后处理的 `video` 张量的输出类型。
        """
        # 获取视频的批次大小
        batch_size = video.shape[0]
        # 初始化输出列表
        outputs = []
        # 遍历每个批次
        for batch_idx in range(batch_size):
            # 重新排列张量维度以获取视频帧
            batch_vid = video[batch_idx].permute(1, 0, 2, 3)
            # 调用后处理方法处理当前批次视频帧
            batch_output = self.postprocess(batch_vid, output_type)
            # 将处理结果添加到输出列表中
            outputs.append(batch_output)

        # 根据输出类型对结果进行不同的堆叠处理
        if output_type == "np":
            # 堆叠输出为 NumPy 数组
            outputs = np.stack(outputs)
        elif output_type == "pt":
            # 堆叠输出为 PyTorch 张量
            outputs = torch.stack(outputs)
        elif not output_type == "pil":
            # 如果输出类型不在指定范围内,抛出错误
            raise ValueError(f"{output_type} does not exist. Please choose one of ['np', 'pt', 'pil']")

        # 返回处理后的输出
        return outputs

.\diffusers\__init__.py

# 定义当前版本号
__version__ = "0.30.3"

# 导入类型检查功能
from typing import TYPE_CHECKING

# 从 utils 模块中导入多个对象
from .utils import (
    DIFFUSERS_SLOW_IMPORT,  # 导入慢速导入标志
    OptionalDependencyNotAvailable,  # 导入可选依赖项不可用异常
    _LazyModule,  # 导入懒加载模块工具
    is_flax_available,  # 检查 Flax 是否可用
    is_k_diffusion_available,  # 检查 K Diffusion 是否可用
    is_librosa_available,  # 检查 Librosa 是否可用
    is_note_seq_available,  # 检查 NoteSeq 是否可用
    is_onnx_available,  # 检查 ONNX 是否可用
    is_scipy_available,  # 检查 SciPy 是否可用
    is_sentencepiece_available,  # 检查 SentencePiece 是否可用
    is_torch_available,  # 检查 PyTorch 是否可用
    is_torchsde_available,  # 检查 Torchsde 是否可用
    is_transformers_available,  # 检查 Transformers 是否可用
)

# 懒加载导入的基础
# 懒加载是为了提高导入效率

# 添加新对象到初始化时,请将其添加到 `_import_structure` 中
# `_import_structure` 是一个字典,列出对象名称,用于延迟实际导入
# 这样 `import diffusers` 提供命名空间中的名称,而不实际导入任何内容

_import_structure = {
    "configuration_utils": ["ConfigMixin"],  # 配置工具的混合类
    "loaders": ["FromOriginalModelMixin"],  # 加载器的混合类
    "models": [],  # 模型列表初始化为空
    "pipelines": [],  # 流水线列表初始化为空
    "schedulers": [],  # 调度器列表初始化为空
    "utils": [  # 工具列表
        "OptionalDependencyNotAvailable",  # 可选依赖项不可用异常
        "is_flax_available",  # Flax 可用性检查
        "is_inflect_available",  # Inflect 可用性检查
        "is_invisible_watermark_available",  # 隐形水印可用性检查
        "is_k_diffusion_available",  # K Diffusion 可用性检查
        "is_k_diffusion_version",  # K Diffusion 版本检查
        "is_librosa_available",  # Librosa 可用性检查
        "is_note_seq_available",  # NoteSeq 可用性检查
        "is_onnx_available",  # ONNX 可用性检查
        "is_scipy_available",  # SciPy 可用性检查
        "is_torch_available",  # PyTorch 可用性检查
        "is_torchsde_available",  # Torchsde 可用性检查
        "is_transformers_available",  # Transformers 可用性检查
        "is_transformers_version",  # Transformers 版本检查
        "is_unidecode_available",  # Unidecode 可用性检查
        "logging",  # 日志记录工具
    ],
}

# 尝试检查 ONNX 是否可用
try:
    if not is_onnx_available():  # 如果 ONNX 不可用
        raise OptionalDependencyNotAvailable()  # 抛出可选依赖项不可用异常
except OptionalDependencyNotAvailable:  # 捕获异常
    from .utils import dummy_onnx_objects  # 导入假 ONNX 对象

    # 将假对象添加到导入结构中
    _import_structure["utils.dummy_onnx_objects"] = [
        name for name in dir(dummy_onnx_objects) if not name.startswith("_")  # 排除以 "_" 开头的名称
    ]

else:  # 如果没有抛出异常
    # 将 ONNX 模型添加到流水线列表中
    _import_structure["pipelines"].extend(["OnnxRuntimeModel"])

# 尝试检查 PyTorch 是否可用
try:
    if not is_torch_available():  # 如果 PyTorch 不可用
        raise OptionalDependencyNotAvailable()  # 抛出可选依赖项不可用异常
except OptionalDependencyNotAvailable:  # 捕获异常
    from .utils import dummy_pt_objects  # 导入假 PyTorch 对象

    # 将假对象添加到导入结构中
    _import_structure["utils.dummy_pt_objects"] = [name for name in dir(dummy_pt_objects) if not name.startswith("_")]

else:  # 如果没有抛出异常
    # 扩展模型导入结构,将新模型名称添加到“models”列表中
        _import_structure["models"].extend(
            [   
                # 添加不同类型的模型名称
                "AsymmetricAutoencoderKL",
                "AuraFlowTransformer2DModel",
                "AutoencoderKL",
                "AutoencoderKLCogVideoX",
                "AutoencoderKLTemporalDecoder",
                "AutoencoderOobleck",
                "AutoencoderTiny",
                "CogVideoXTransformer3DModel",
                "ConsistencyDecoderVAE",
                "ControlNetModel",
                "ControlNetXSAdapter",
                "DiTTransformer2DModel",
                "FluxTransformer2DModel",
                "HunyuanDiT2DControlNetModel",
                "HunyuanDiT2DModel",
                "HunyuanDiT2DMultiControlNetModel",
                "I2VGenXLUNet",
                "Kandinsky3UNet",
                "LatteTransformer3DModel",
                "LuminaNextDiT2DModel",
                "ModelMixin",
                "MotionAdapter",
                "MultiAdapter",
                "PixArtTransformer2DModel",
                "PriorTransformer",
                "SD3ControlNetModel",
                "SD3MultiControlNetModel",
                "SD3Transformer2DModel",
                "SparseControlNetModel",
                "StableAudioDiTModel",
                "StableCascadeUNet",
                "T2IAdapter",
                "T5FilmDecoder",
                "Transformer2DModel",
                "UNet1DModel",
                "UNet2DConditionModel",
                "UNet2DModel",
                "UNet3DConditionModel",
                "UNetControlNetXSModel",
                "UNetMotionModel",
                "UNetSpatioTemporalConditionModel",
                "UVit2DModel",
                "VQModel",
            ]
        )
    
        # 设置优化相关的导入结构,包括不同的调度函数
        _import_structure["optimization"] = [
            "get_constant_schedule",  # 获取常数调度
            "get_constant_schedule_with_warmup",  # 获取带预热的常数调度
            "get_cosine_schedule_with_warmup",  # 获取带预热的余弦调度
            "get_cosine_with_hard_restarts_schedule_with_warmup",  # 获取带硬重启的余弦调度
            "get_linear_schedule_with_warmup",  # 获取带预热的线性调度
            "get_polynomial_decay_schedule_with_warmup",  # 获取带预热的多项式衰减调度
            "get_scheduler",  # 获取调度器
        ]
        # 扩展管道导入结构,将新管道名称添加到“pipelines”列表中
        _import_structure["pipelines"].extend(
            [   
                # 添加不同类型的管道名称
                "AudioPipelineOutput",
                "AutoPipelineForImage2Image",
                "AutoPipelineForInpainting",
                "AutoPipelineForText2Image",
                "ConsistencyModelPipeline",
                "DanceDiffusionPipeline",
                "DDIMPipeline",
                "DDPMPipeline",
                "DiffusionPipeline",
                "DiTPipeline",
                "ImagePipelineOutput",
                "KarrasVePipeline",
                "LDMPipeline",
                "LDMSuperResolutionPipeline",
                "PNDMPipeline",
                "RePaintPipeline",
                "ScoreSdeVePipeline",
                "StableDiffusionMixin",
            ]
        )
    # 扩展调度器(schedulers)的导入结构列表
        _import_structure["schedulers"].extend(
            [  # 添加多个调度器的名称到列表中
                "AmusedScheduler",  # 添加 AmusedScheduler
                "CMStochasticIterativeScheduler",  # 添加 CMStochasticIterativeScheduler
                "CogVideoXDDIMScheduler",  # 添加 CogVideoXDDIMScheduler
                "CogVideoXDPMScheduler",  # 添加 CogVideoXDPMScheduler
                "DDIMInverseScheduler",  # 添加 DDIMInverseScheduler
                "DDIMParallelScheduler",  # 添加 DDIMParallelScheduler
                "DDIMScheduler",  # 添加 DDIMScheduler
                "DDPMParallelScheduler",  # 添加 DDPMParallelScheduler
                "DDPMScheduler",  # 添加 DDPMScheduler
                "DDPMWuerstchenScheduler",  # 添加 DDPMWuerstchenScheduler
                "DEISMultistepScheduler",  # 添加 DEISMultistepScheduler
                "DPMSolverMultistepInverseScheduler",  # 添加 DPMSolverMultistepInverseScheduler
                "DPMSolverMultistepScheduler",  # 添加 DPMSolverMultistepScheduler
                "DPMSolverSinglestepScheduler",  # 添加 DPMSolverSinglestepScheduler
                "EDMDPMSolverMultistepScheduler",  # 添加 EDMDPMSolverMultistepScheduler
                "EDMEulerScheduler",  # 添加 EDMEulerScheduler
                "EulerAncestralDiscreteScheduler",  # 添加 EulerAncestralDiscreteScheduler
                "EulerDiscreteScheduler",  # 添加 EulerDiscreteScheduler
                "FlowMatchEulerDiscreteScheduler",  # 添加 FlowMatchEulerDiscreteScheduler
                "FlowMatchHeunDiscreteScheduler",  # 添加 FlowMatchHeunDiscreteScheduler
                "HeunDiscreteScheduler",  # 添加 HeunDiscreteScheduler
                "IPNDMScheduler",  # 添加 IPNDMScheduler
                "KarrasVeScheduler",  # 添加 KarrasVeScheduler
                "KDPM2AncestralDiscreteScheduler",  # 添加 KDPM2AncestralDiscreteScheduler
                "KDPM2DiscreteScheduler",  # 添加 KDPM2DiscreteScheduler
                "LCMScheduler",  # 添加 LCMScheduler
                "PNDMScheduler",  # 添加 PNDMScheduler
                "RePaintScheduler",  # 添加 RePaintScheduler
                "SASolverScheduler",  # 添加 SASolverScheduler
                "SchedulerMixin",  # 添加 SchedulerMixin
                "ScoreSdeVeScheduler",  # 添加 ScoreSdeVeScheduler
                "TCDScheduler",  # 添加 TCDScheduler
                "UnCLIPScheduler",  # 添加 UnCLIPScheduler
                "UniPCMultistepScheduler",  # 添加 UniPCMultistepScheduler
                "VQDiffusionScheduler",  # 添加 VQDiffusionScheduler
            ]
        )  # 结束扩展调度器的导入结构
        # 将训练工具(training_utils)中的 EMAModel 添加到导入结构
        _import_structure["training_utils"] = ["EMAModel"]
# 尝试检查 PyTorch 和 SciPy 是否可用
try:
    # 如果两者都不可用,则抛出可选依赖不可用异常
    if not (is_torch_available() and is_scipy_available()):
        raise OptionalDependencyNotAvailable()
# 捕获可选依赖不可用异常
except OptionalDependencyNotAvailable:
    # 从 utils 模块导入假对象,以避免缺失依赖的问题  # noqa F403
    from .utils import dummy_torch_and_scipy_objects  # noqa F403

    # 将假对象的名称添加到导入结构中,过滤掉以 "_" 开头的名称
    _import_structure["utils.dummy_torch_and_scipy_objects"] = [
        name for name in dir(dummy_torch_and_scipy_objects) if not name.startswith("_")
    ]
# 如果没有异常,则扩展调度器的导入结构
else:
    _import_structure["schedulers"].extend(["LMSDiscreteScheduler"])

# 尝试检查 PyTorch 和 torchsde 是否可用
try:
    # 如果两者都不可用,则抛出可选依赖不可用异常
    if not (is_torch_available() and is_torchsde_available()):
        raise OptionalDependencyNotAvailable()
# 捕获可选依赖不可用异常
except OptionalDependencyNotAvailable:
    # 从 utils 模块导入假对象,以避免缺失依赖的问题  # noqa F403
    from .utils import dummy_torch_and_torchsde_objects  # noqa F403

    # 将假对象的名称添加到导入结构中,过滤掉以 "_" 开头的名称
    _import_structure["utils.dummy_torch_and_torchsde_objects"] = [
        name for name in dir(dummy_torch_and_torchsde_objects) if not name.startswith("_")
    ]
# 如果没有异常,则扩展调度器的导入结构
else:
    _import_structure["schedulers"].extend(["CosineDPMSolverMultistepScheduler", "DPMSolverSDEScheduler"])

# 尝试检查 PyTorch 和 transformers 是否可用
try:
    # 如果两者都不可用,则抛出可选依赖不可用异常
    if not (is_torch_available() and is_transformers_available()):
        raise OptionalDependencyNotAvailable()
# 捕获可选依赖不可用异常
except OptionalDependencyNotAvailable:
    # 从 utils 模块导入假对象,以避免缺失依赖的问题  # noqa F403
    from .utils import dummy_torch_and_transformers_objects  # noqa F403

    # 将假对象的名称添加到导入结构中,过滤掉以 "_" 开头的名称
    _import_structure["utils.dummy_torch_and_transformers_objects"] = [
        name for name in dir(dummy_torch_and_transformers_objects) if not name.startswith("_")
    ]
# else 语句缺失

# 尝试检查 PyTorch、transformers 和 k-diffusion 是否可用
try:
    # 如果三者都不可用,则抛出可选依赖不可用异常
    if not (is_torch_available() and is_transformers_available() and is_k_diffusion_available()):
        raise OptionalDependencyNotAvailable()
# 捕获可选依赖不可用异常
except OptionalDependencyNotAvailable:
    # 从 utils 模块导入假对象,以避免缺失依赖的问题  # noqa F403
    from .utils import dummy_torch_and_transformers_and_k_diffusion_objects  # noqa F403

    # 将假对象的名称添加到导入结构中,过滤掉以 "_" 开头的名称
    _import_structure["utils.dummy_torch_and_transformers_and_k_diffusion_objects"] = [
        name for name in dir(dummy_torch_and_transformers_and_k_diffusion_objects) if not name.startswith("_")
    ]
# 如果没有异常,则扩展管道的导入结构
else:
    _import_structure["pipelines"].extend(["StableDiffusionKDiffusionPipeline", "StableDiffusionXLKDiffusionPipeline"])

# 尝试检查 PyTorch、transformers 和 sentencepiece 是否可用
try:
    # 如果三者都不可用,则抛出可选依赖不可用异常
    if not (is_torch_available() and is_transformers_available() and is_sentencepiece_available()):
        raise OptionalDependencyNotAvailable()
# 捕获可选依赖不可用异常
except OptionalDependencyNotAvailable:
    # 从 utils 模块导入假对象,以避免缺失依赖的问题  # noqa F403
    from .utils import dummy_torch_and_transformers_and_sentencepiece_objects  # noqa F403

    # 将假对象的名称添加到导入结构中,过滤掉以 "_" 开头的名称
    _import_structure["utils.dummy_torch_and_transformers_and_sentencepiece_objects"] = [
        name for name in dir(dummy_torch_and_transformers_and_sentencepiece_objects) if not name.startswith("_")
    ]
# 如果没有异常,则扩展管道的导入结构
else:
    _import_structure["pipelines"].extend(["KolorsImg2ImgPipeline", "KolorsPAGPipeline", "KolorsPipeline"])

# 尝试检查 PyTorch、transformers 和 onnx 是否可用
try:
    # 如果三者都不可用,则抛出可选依赖不可用异常
    if not (is_torch_available() and is_transformers_available() and is_onnx_available()):
        raise OptionalDependencyNotAvailable()
# 捕获可选依赖不可用异常
except OptionalDependencyNotAvailable:
    # 从 utils 模块导入假对象,以避免缺失依赖的问题  # noqa F403
    from .utils import dummy_torch_and_transformers_and_onnx_objects  # noqa F403
    # 将 "utils.dummy_torch_and_transformers_and_onnx_objects" 的导入结构存储为一个列表
        _import_structure["utils.dummy_torch_and_transformers_and_onnx_objects"] = [
            # 遍历 dummy_torch_and_transformers_and_onnx_objects 的属性名,排除以 "_" 开头的私有属性
            name for name in dir(dummy_torch_and_transformers_and_onnx_objects) if not name.startswith("_")
        ]
else:  # 如果前面的条件不满足
    # 将各个管道名称添加到 _import_structure["pipelines"] 列表中
    _import_structure["pipelines"].extend(
        [
            "OnnxStableDiffusionImg2ImgPipeline",  # ONNX 图像到图像管道
            "OnnxStableDiffusionInpaintPipeline",   # ONNX 图像修复管道
            "OnnxStableDiffusionInpaintPipelineLegacy",  # ONNX 旧版图像修复管道
            "OnnxStableDiffusionPipeline",  # ONNX 生成管道
            "OnnxStableDiffusionUpscalePipeline",  # ONNX 图像放大管道
            "StableDiffusionOnnxPipeline",  # 稳定扩散 ONNX 管道
        ]
    )

try:  # 尝试检查是否可用
    # 检查是否可用 PyTorch 和 librosa
    if not (is_torch_available() and is_librosa_available()): 
        raise OptionalDependencyNotAvailable()  # 如果不可用,则抛出异常
except OptionalDependencyNotAvailable:  # 捕获异常
    # 从工具模块导入虚拟对象以避免错误
    from .utils import dummy_torch_and_librosa_objects  # noqa F403

    # 获取虚拟对象中所有公共属性并添加到 _import_structure
    _import_structure["utils.dummy_torch_and_librosa_objects"] = [
        name for name in dir(dummy_torch_and_librosa_objects) if not name.startswith("_")  # 遍历所有属性
    ]

else:  # 如果没有抛出异常
    # 将音频扩散管道名称添加到 _import_structure["pipelines"] 列表中
    _import_structure["pipelines"].extend(["AudioDiffusionPipeline", "Mel"])

try:  # 尝试检查依赖项
    # 检查 transformers、PyTorch 和 note_seq 是否可用
    if not (is_transformers_available() and is_torch_available() and is_note_seq_available()):
        raise OptionalDependencyNotAvailable()  # 抛出异常
except OptionalDependencyNotAvailable:  # 捕获异常
    # 导入虚拟对象
    from .utils import dummy_transformers_and_torch_and_note_seq_objects  # noqa F403

    # 将虚拟对象的公共属性添加到 _import_structure
    _import_structure["utils.dummy_transformers_and_torch_and_note_seq_objects"] = [
        name for name in dir(dummy_transformers_and_torch_and_note_seq_objects) if not name.startswith("_")  # 遍历所有属性
    ]

else:  # 如果没有异常
    # 将频谱扩散管道名称添加到 _import_structure["pipelines"] 列表中
    _import_structure["pipelines"].extend(["SpectrogramDiffusionPipeline"])

try:  # 尝试检查 Flax 是否可用
    if not is_flax_available():  # 如果 Flax 不可用
        raise OptionalDependencyNotAvailable()  # 抛出异常
except OptionalDependencyNotAvailable:  # 捕获异常
    # 导入虚拟 Flax 对象
    from .utils import dummy_flax_objects  # noqa F403

    # 将虚拟对象的公共属性添加到 _import_structure
    _import_structure["utils.dummy_flax_objects"] = [
        name for name in dir(dummy_flax_objects) if not name.startswith("_")  # 遍历所有属性
    ]

else:  # 如果没有异常
    # 将多个 Flax 模型名称添加到 _import_structure
    _import_structure["models.controlnet_flax"] = ["FlaxControlNetModel"]  # 控制网络模型
    _import_structure["models.modeling_flax_utils"] = ["FlaxModelMixin"]  # Flax 模型混合类
    _import_structure["models.unets.unet_2d_condition_flax"] = ["FlaxUNet2DConditionModel"]  # Flax 2D 条件 U-Net 模型
    _import_structure["models.vae_flax"] = ["FlaxAutoencoderKL"]  # Flax 自编码器
    # 将 Flax 扩散管道名称添加到 _import_structure["pipelines"] 列表中
    _import_structure["pipelines"].extend(["FlaxDiffusionPipeline"])  
    # 将 Flax 调度器名称添加到 _import_structure["schedulers"] 列表中
    _import_structure["schedulers"].extend(
        [
            "FlaxDDIMScheduler",  # Flax DDIM 调度器
            "FlaxDDPMScheduler",  # Flax DDPMS 调度器
            "FlaxDPMSolverMultistepScheduler",  # Flax 多步 DPM 求解器调度器
            "FlaxEulerDiscreteScheduler",  # Flax Euler 离散调度器
            "FlaxKarrasVeScheduler",  # Flax Karras VE 调度器
            "FlaxLMSDiscreteScheduler",  # Flax LMS 离散调度器
            "FlaxPNDMScheduler",  # Flax PNDM 调度器
            "FlaxSchedulerMixin",  # Flax 调度器混合类
            "FlaxScoreSdeVeScheduler",  # Flax SDE VE 调度器
        ]
    )

try:  # 尝试检查 Flax 和 transformers 是否可用
    if not (is_flax_available() and is_transformers_available()):  # 如果其中一个不可用
        raise OptionalDependencyNotAvailable()  # 抛出异常
except OptionalDependencyNotAvailable:  # 捕获异常
    # 导入虚拟对象
    from .utils import dummy_flax_and_transformers_objects  # noqa F403

    # 将虚拟对象的公共属性添加到 _import_structure
    _import_structure["utils.dummy_flax_and_transformers_objects"] = [
        name for name in dir(dummy_flax_and_transformers_objects) if not name.startswith("_")  # 遍历所有属性
    ]

else:  # 如果没有异常
    # 扩展 _import_structure 字典中 "pipelines" 键对应的列表
        _import_structure["pipelines"].extend(
            # 添加多个管道类的名称到列表中
            [
                "FlaxStableDiffusionControlNetPipeline",  # 控制网络管道类
                "FlaxStableDiffusionImg2ImgPipeline",     # 图像到图像转换管道类
                "FlaxStableDiffusionInpaintPipeline",      # 图像修复管道类
                "FlaxStableDiffusionPipeline",             # 标准稳定扩散管道类
                "FlaxStableDiffusionXLPipeline",           # 扩展的稳定扩散管道类
            ]
        )
try:
    # 检查 note_seq 是否可用
    if not (is_note_seq_available()):
        # 如果不可用,抛出可选依赖项不可用异常
        raise OptionalDependencyNotAvailable()
# 捕获可选依赖项不可用异常
except OptionalDependencyNotAvailable:
    # 从 utils 模块导入虚拟的 note_seq 对象,避免未导入的错误
    from .utils import dummy_note_seq_objects  # noqa F403

    # 将虚拟对象的名称添加到导入结构中(只包含非私有属性)
    _import_structure["utils.dummy_note_seq_objects"] = [
        name for name in dir(dummy_note_seq_objects) if not name.startswith("_")
    ]

# 如果没有异常,则继续执行以下代码
else:
    # 向导入结构中添加 MidiProcessor
    _import_structure["pipelines"].extend(["MidiProcessor"])

# 如果在类型检查或慢速导入模式下
if TYPE_CHECKING or DIFFUSERS_SLOW_IMPORT:
    # 从配置工具模块导入 ConfigMixin
    from .configuration_utils import ConfigMixin

    try:
        # 检查 onnx 是否可用
        if not is_onnx_available():
            # 如果不可用,抛出可选依赖项不可用异常
            raise OptionalDependencyNotAvailable()
    # 捕获可选依赖项不可用异常
    except OptionalDependencyNotAvailable:
        # 从 utils 模块导入虚拟的 onnx 对象,避免未导入的错误
        from .utils.dummy_onnx_objects import *  # noqa F403
    else:
        # 从管道模块导入 OnnxRuntimeModel
        from .pipelines import OnnxRuntimeModel

    try:
        # 检查 torch 是否可用
        if not is_torch_available():
            # 如果不可用,抛出可选依赖项不可用异常
            raise OptionalDependencyNotAvailable()
    # 捕获可选依赖项不可用异常
    except OptionalDependencyNotAvailable:
        # 从 utils 模块导入虚拟的 pytorch 对象,避免未导入的错误
        from .utils.dummy_pt_objects import *  # noqa F403
        
    try:
        # 检查 torch 和 scipy 是否都可用
        if not (is_torch_available() and is_scipy_available()):
            # 如果不满足条件,抛出可选依赖项不可用异常
            raise OptionalDependencyNotAvailable()
    # 捕获可选依赖项不可用异常
    except OptionalDependencyNotAvailable:
        # 从 utils 模块导入虚拟的 torch 和 scipy 对象,避免未导入的错误
        from .utils.dummy_torch_and_scipy_objects import *  # noqa F403
    else:
        # 从调度器模块导入 LMSDiscreteScheduler
        from .schedulers import LMSDiscreteScheduler

    try:
        # 检查 torch 和 torchsde 是否都可用
        if not (is_torch_available() and is_torchsde_available()):
            # 如果不满足条件,抛出可选依赖项不可用异常
            raise OptionalDependencyNotAvailable()
    # 捕获可选依赖项不可用异常
    except OptionalDependencyNotAvailable:
        # 从 utils 模块导入虚拟的 torch 和 torchsde 对象,避免未导入的错误
        from .utils.dummy_torch_and_torchsde_objects import *  # noqa F403
    else:
        # 从调度器模块导入 CosineDPMSolverMultistepScheduler 和 DPMSolverSDEScheduler
        from .schedulers import CosineDPMSolverMultistepScheduler, DPMSolverSDEScheduler

    try:
        # 检查 torch 和 transformers 是否都可用
        if not (is_torch_available() and is_transformers_available()):
            # 如果不满足条件,抛出可选依赖项不可用异常
            raise OptionalDependencyNotAvailable()
    # 捕获可选依赖项不可用异常
    except OptionalDependencyNotAvailable:
        # 从 utils 模块导入虚拟的 torch 和 transformers 对象,避免未导入的错误
        from .utils.dummy_torch_and_transformers_objects import *  # noqa F403
        
    try:
        # 检查 torch、transformers 和 k_diffusion 是否都可用
        if not (is_torch_available() and is_transformers_available() and is_k_diffusion_available()):
            # 如果不满足条件,抛出可选依赖项不可用异常
            raise OptionalDependencyNotAvailable()
    # 捕获可选依赖项不可用异常
    except OptionalDependencyNotAvailable:
        # 从 utils 模块导入虚拟的 torch、transformers 和 k_diffusion 对象,避免未导入的错误
        from .utils.dummy_torch_and_transformers_and_k_diffusion_objects import *  # noqa F403
    else:
        # 从管道模块导入 StableDiffusionKDiffusionPipeline 和 StableDiffusionXLKDiffusionPipeline
        from .pipelines import StableDiffusionKDiffusionPipeline, StableDiffusionXLKDiffusionPipeline

    try:
        # 检查 torch、transformers 和 sentencepiece 是否都可用
        if not (is_torch_available() and is_transformers_available() and is_sentencepiece_available()):
            # 如果不满足条件,抛出可选依赖项不可用异常
            raise OptionalDependencyNotAvailable()
    # 捕获可选依赖项不可用异常
    except OptionalDependencyNotAvailable:
        # 从 utils 模块导入虚拟的 torch、transformers 和 sentencepiece 对象,避免未导入的错误
        from .utils.dummy_torch_and_transformers_and_sentencepiece_objects import *  # noqa F403
    else:
        # 从管道模块导入 KolorsImg2ImgPipeline、KolorsPAGPipeline 和 KolorsPipeline
        from .pipelines import KolorsImg2ImgPipeline, KolorsPAGPipeline, KolorsPipeline
        
    try:
        # 检查 torch、transformers 和 onnx 是否都可用
        if not (is_torch_available() and is_transformers_available() and is_onnx_available()):
            # 如果不满足条件,抛出可选依赖项不可用异常
            raise OptionalDependencyNotAvailable()
    # 捕获可选依赖项不可用异常
    except OptionalDependencyNotAvailable:
        # 从 utils 模块导入虚拟的 torch、transformers 和 onnx 对象,避免未导入的错误
        from .utils.dummy_torch_and_transformers_and_onnx_objects import *  # noqa F403
    else:  # 如果没有满足上面的条件,则执行以下导入
        from .pipelines import (  # 从当前包的 pipelines 模块中导入以下类
            OnnxStableDiffusionImg2ImgPipeline,  # 导入图像到图像转换的 ONNX 管道
            OnnxStableDiffusionInpaintPipeline,  # 导入图像修复的 ONNX 管道
            OnnxStableDiffusionInpaintPipelineLegacy,  # 导入旧版图像修复的 ONNX 管道
            OnnxStableDiffusionPipeline,  # 导入基础的 ONNX 扩散管道
            OnnxStableDiffusionUpscalePipeline,  # 导入图像放大的 ONNX 管道
            StableDiffusionOnnxPipeline,  # 导入稳定扩散的 ONNX 管道
        )

    try:  # 尝试执行以下代码
        if not (is_torch_available() and is_librosa_available()):  # 检查 PyTorch 和 librosa 是否可用
            raise OptionalDependencyNotAvailable()  # 如果其中一个不可用,则抛出异常
    except OptionalDependencyNotAvailable:  # 捕获可选依赖不可用的异常
        from .utils.dummy_torch_and_librosa_objects import *  # noqa F403  # 导入虚拟的 torch 和 librosa 对象以避免错误
    else:  # 如果没有抛出异常,执行以下导入
        from .pipelines import AudioDiffusionPipeline, Mel  # 从 pipelines 导入音频扩散管道和 Mel 类

    try:  # 尝试执行以下代码
        if not (is_transformers_available() and is_torch_available() and is_note_seq_available()):  # 检查 transformers, PyTorch 和 note_seq 是否可用
            raise OptionalDependencyNotAvailable()  # 如果其中一个不可用,则抛出异常
    except OptionalDependencyNotAvailable:  # 捕获可选依赖不可用的异常
        from .utils.dummy_transformers_and_torch_and_note_seq_objects import *  # noqa F403  # 导入虚拟的 transformers, torch 和 note_seq 对象以避免错误
    else:  # 如果没有抛出异常,执行以下导入
        from .pipelines import SpectrogramDiffusionPipeline  # 从 pipelines 导入声谱扩散管道

    try:  # 尝试执行以下代码
        if not is_flax_available():  # 检查 Flax 是否可用
            raise OptionalDependencyNotAvailable()  # 如果不可用,则抛出异常
    except OptionalDependencyNotAvailable:  # 捕获可选依赖不可用的异常
        from .utils.dummy_flax_objects import *  # noqa F403  # 导入虚拟的 Flax 对象以避免错误
    else:  # 如果没有抛出异常,执行以下导入
        from .models.controlnet_flax import FlaxControlNetModel  # 从模型导入 Flax 控制网络模型
        from .models.modeling_flax_utils import FlaxModelMixin  # 导入 Flax 模型混合工具
        from .models.unets.unet_2d_condition_flax import FlaxUNet2DConditionModel  # 导入 2D 条件 UNet 模型
        from .models.vae_flax import FlaxAutoencoderKL  # 导入 Flax 的自编码器模型
        from .pipelines import FlaxDiffusionPipeline  # 从 pipelines 导入 Flax 扩散管道
        from .schedulers import (  # 从调度器模块导入以下类
            FlaxDDIMScheduler,  # 导入 Flax 的 DDIM 调度器
            FlaxDDPMScheduler,  # 导入 Flax 的 DDPMS 调度器
            FlaxDPMSolverMultistepScheduler,  # 导入 Flax 的多步 DPM 求解器调度器
            FlaxEulerDiscreteScheduler,  # 导入 Flax 的 Euler 离散调度器
            FlaxKarrasVeScheduler,  # 导入 Flax 的 Karras VE 调度器
            FlaxLMSDiscreteScheduler,  # 导入 Flax 的 LMS 离散调度器
            FlaxPNDMScheduler,  # 导入 Flax 的 PNDM 调度器
            FlaxSchedulerMixin,  # 导入 Flax 调度器混合工具
            FlaxScoreSdeVeScheduler,  # 导入 Flax 的 SDE VE 调度器
        )

    try:  # 尝试执行以下代码
        if not (is_flax_available() and is_transformers_available()):  # 检查 Flax 和 transformers 是否可用
            raise OptionalDependencyNotAvailable()  # 如果其中一个不可用,则抛出异常
    except OptionalDependencyNotAvailable:  # 捕获可选依赖不可用的异常
        from .utils.dummy_flax_and_transformers_objects import *  # noqa F403  # 导入虚拟的 Flax 和 transformers 对象以避免错误
    else:  # 如果没有抛出异常,执行以下导入
        from .pipelines import (  # 从 pipelines 导入以下类
            FlaxStableDiffusionControlNetPipeline,  # 导入 Flax 稳定扩散控制网络管道
            FlaxStableDiffusionImg2ImgPipeline,  # 导入 Flax 图像到图像的稳定扩散管道
            FlaxStableDiffusionInpaintPipeline,  # 导入 Flax 图像修复的稳定扩散管道
            FlaxStableDiffusionPipeline,  # 导入 Flax 稳定扩散管道
            FlaxStableDiffusionXLPipeline,  # 导入 Flax 稳定扩散 XL 管道
        )

    try:  # 尝试执行以下代码
        if not (is_note_seq_available()):  # 检查 note_seq 是否可用
            raise OptionalDependencyNotAvailable()  # 如果不可用,则抛出异常
    except OptionalDependencyNotAvailable:  # 捕获可选依赖不可用的异常
        from .utils.dummy_note_seq_objects import *  # noqa F403  # 导入虚拟的 note_seq 对象以避免错误
    else:  # 如果没有抛出异常,执行以下导入
        from .pipelines import MidiProcessor  # 从 pipelines 导入 MIDI 处理器
# 如果不是主模块执行,则进行模块的延迟加载
else:
    # 导入系统模块,以便对模块进行操作
    import sys

    # 将当前模块的名称映射到一个懒加载模块实例
    sys.modules[__name__] = _LazyModule(
        # 当前模块名称
        __name__,
        # 当前模块的文件路径
        globals()["__file__"],
        # 导入结构的定义
        _import_structure,
        # 模块的规格
        module_spec=__spec__,
        # 额外对象,包括版本信息
        extra_objects={"__version__": __version__},
    )
posted @ 2024-10-22 12:33  绝不原创的飞龙  阅读(131)  评论(0)    收藏  举报