资讯动态

Diffusers Modular Diffusers 快速入门:用可组合 Pipeline Blocks 构建与定制生成管线

发布时间:2026/9/11 12:25:58 来源:尧图企业网站定制
Diffusers Modular Diffusers 快速入门用可组合 Pipeline Blocks 构建与定制生成管线【免费下载链接】diffusers Diffusers: State-of-the-art diffusion models for image, video, and audio generation in PyTorch.项目地址: https://gitcode.com/GitHub_Trending/di/diffusersModular Diffusers 是 Diffusers 中一套用于快速构建灵活、可定制生成管线的框架它允许开发者用原子化的ModularPipelineBlocks组合出超越传统DiffusionPipeline能力的全新工作流。本指南基于 docs/source/en/modular_diffusers/quickstart.md 展开结合仓库源码深入讲解如何运行一个 Modular Pipeline、如何理解其定义 状态的双层结构、如何通过增删替换 Blocks 组合出全新的工作流例如为 ControlNet 管线插入 Canny 边缘检测块读完即可上手自定义自己的模块化生成流程。Modular Diffusers 的核心概念在深入代码之前先建立两个关键概念对应 modular_pipeline.py 中的两个核心类ModularPipelineBlocks管线的定义层。它是描述管线工作流、输入、输出与计算逻辑的单元也是可组合的最小积木。仓库中所有管线块都继承自ModularPipelineBlocks见 modular_pipeline.py 第 326 行包括顺序执行的SequentialPipelineBlocks、条件执行的ConditionalPipelineBlocks和支持多工作流的AutoPipelineBlocks。ModularPipeline管线的用户接口层。它负责从 Hub 加载、运行并管理整条模块化管线将 Blocks 的执行细节封装成类似传统DiffusionPipeline的友好调用方式。简单说Blocks 决定怎么做ModularPipeline 负责加载什么、跑起来。两者通过init_pipeline()建立联系见 modular_pipeline.py 第 500 行。运行一个 Modular PipelineModularPipeline是加载、运行和管理模块化管线的主要接口。以下代码以 Qwen-Image 为例展示一次完整的文生图调用import torch from diffusers import ModularPipeline, ComponentsManager # Use ComponentsManager to enable auto CPU offloading for memory efficiency manager ComponentsManager() manager.enable_auto_cpu_offload(devicecuda:0) pipe ModularPipeline.from_pretrained(Qwen/Qwen-Image, components_managermanager) pipe.load_components(dtypetorch.bfloat16) image pipe( promptcat wizard with red hat, gandalf, lord of the rings, detailed, fantasy, cute, adorable, Pixar, Disney, ).images[0] image惰性加载from_pretrained 与 load_components 分离ModularPipeline.from_pretrained采用惰性加载策略它只读取配置modular_model_index.json若不存在则回退到标准model_index.json来确定每个组件从哪里加载但不会真正下载模型权重直到你显式调用pipe.load_components()。从源码看from_pretrained的核心流程是解析 revision 与 Hub 参数_resolve_revision尝试通过ModularPipelineBlocks.from_pretrained加载 Blocks 定义若仓库没有 modular 配置则回退根据配置字典确定具体的 ModularPipeline 子类例如QwenImageModularPipeline见 qwenimage/modular_pipeline.py 第 175 行其default_blocks_name QwenImageAutoBlocks实例化管线但此时各组件属性仍为None。这种设计把何时加载、以何种精度加载的控制权完全交还给开发者。load_components见 modular_pipeline.py 第 2407 行默认加载所有default_creation_method from_pretrained的组件并支持灵活的精度传递方式单个值应用到所有组件pipe.load_components(dtypetorch.bfloat16)按组件名传字典pipe.load_components(dtype{unet: torch.bfloat16, default: torch.float32})只加载某个工作流用到的组件pipe.load_components(workflowinpainting)不能与names同时使用。ComponentsManager 自动 CPU OffloadingComponentsManager见 components_manager.py 第 302 行负责跨管线共享模型并管理内存。enable_auto_cpu_offload见 components_manager.py 第 708 行的工作机制是所有模型默认放在 CPU当某个模型的前向传播被调用时它被移动到执行设备execution_device若显存不足系统会把设备上其他模型移回 CPU且优先卸载能释放足够内存的最小模型组合默认AutoOffloadStrategy模型会一直驻留执行设备直到其他模型需要内存才被挤走。memory_reserve_margin默认3GB用于在执行设备上保留的可用内存避免中间激活值、梯度等导致 OOM。对于 Qwen-Image 这类大模型这是显著降低显存占用的关键手段。如果不需要 offloading直接去掉components_manager参数改为手动pipe.to(cuda)即可。理解 Pipeline 的结构定义与状态一个ModularPipeline由两部分组成定义Blocks和状态已加载的组件与配置。打印管线状态直接print(pipe)可以查看管线的状态——各组件的加载来源、配置与当前状态QwenImageModularPipeline { _blocks_class_name: QwenImageAutoBlocks, _class_name: QwenImageModularPipeline, _diffusers_version: 0.37.0.dev0, transformer: [ diffusers, QwenImageTransformer2DModel, { pretrained_model_name_or_path: Qwen/Qwen-Image, revision: null, subfolder: transformer, type_hint: [ diffusers, QwenImageTransformer2DModel ], variant: null } ], ... }这里每个组件的描述信息对应ComponentSpec见 modular_pipeline_utils.py 第 97 行它记录了组件的type_hint、pretrained_model_name_or_path、subfolder、variant、revision等加载元数据。打印 Blocks 定义通过pipe.blocks访问管线的定义层——也就是描述工作流、输入输出与计算逻辑的ModularPipelineBlocksprint(pipe.blocks)QwenImageAutoBlocks( Class: SequentialPipelineBlocks Description: Auto Modular pipeline for text-to-image, image-to-image, inpainting, and controlnet tasks using QwenImage. Supported workflows: - text2image: requires prompt - image2image: requires prompt, image - inpainting: requires prompt, mask_image, image - controlnet_text2image: requires prompt, control_image ... Components: text_encoder (Qwen2_5_VLForConditionalGeneration) vae (AutoencoderKLQwenImage) transformer (QwenImageTransformer2DModel) ... Sub-Blocks: [0] text_encoder (QwenImageAutoTextEncoderStep) [1] vae_encoder (QwenImageAutoVaeEncoderStep) [2] controlnet_vae_encoder (QwenImageOptionalControlNetVaeEncoderStep) [3] denoise (QwenImageAutoCoreDenoiseStep) [4] decode (QwenImageAutoDecodeStep) )这段输出会告诉你两类关键信息支持的工作流text2image、image2image、inpainting 等它由哪些 Sub-Blocks 组成text_encoder、vae_encoder、denoise、decode。QwenImageAutoBlocks的完整定义在 qwenimage/modular_blocks_qwenimage.py 第 1113 行它的_workflow_map第 1209 行起声明了 6 种工作流及其触发条件工作流触发输入均需非 Nonetext2imagepromptimage2imageprompt,imageinpaintingprompt,mask_image,imagecontrolnet_text2imageprompt,control_imagecontrolnet_image2imageprompt,image,control_imagecontrolnet_inpaintingprompt,mask_image,image,control_image工作流根据输入自动适配这条管线支持多种工作流并会根据你提供的输入自动切换行为。例如传入image就运行图生图而不是文生图from diffusers.utils import load_image input_image load_image(https://github.com/Trgtuan10/Image_storage/blob/main/cute_cat.png?rawtrue) image pipe( promptcat wizard with red hat, gandalf, lord of the rings, detailed, fantasy, cute, adorable, Pixar, Disney, imageinput_image, ).images[0]底层的工作流选择逻辑在SequentialPipelineBlocks.get_workflow见 modular_pipeline.py 第 1025 行它根据_workflow_map中的触发条件调用get_execution_blocks剪枝出该工作流实际执行的块序列。仓库测试 tests/modular_pipelines/qwen/test_modular_pipeline_qwenimage.py 中QWEN_IMAGE_TEXT2IMAGE_WORKFLOWS精确列出了每个工作流展开后的执行块顺序例如inpainting会依次执行text_encoder→vae_encoder.preprocessQwenImageInpaintProcessImagesInputStep→vae_encoder.encode→ 若干denoise子步骤 →decode等 14 个步骤。当你只想定制或调试某个特定工作流时可以用get_workflow()提取它的执行块img2img_blocks pipe.blocks.get_workflow(image2image)先用pipe.blocks.available_workflows查看所有可用工作流名称对应源码 modular_pipeline.py 第 1017 行 的available_workflows属性。Sub-Blocks块中套块Blocks 可以包含其他 Blocks。pipe.blocks给出的是顶层块定义这里是QwenImageAutoBlocks而sub_blocks属性InsertableDict见 modular_pipeline_utils.py 第 60 行允许你访问其内部的更小块。QwenImageAutoBlocks由text_encoder、vae_encoder、controlnet_vae_encoder、denoise、decode五个 Sub-Blocks 组成。它们按顺序执行数据线性流动——前一个块的intermediate_outputs会成为后一个块的inputs这正是SequentialPipelineBlocks见 modular_pipeline.py 第 974 行的工作方式。vae_encoder_block pipe.blocks.sub_blocks[vae_encoder] print(vae_encoder_block.doc)doc属性非常实用它会生成该块的完整文档包括输入、输出与所需组件生成逻辑见 modular_pipeline.py 第 603 行 与 modular_pipeline_utils.py 中的make_doc_string/format_params系列函数。更进一步单个块可以通过init_pipeline()独立转换为一条可单独运行的管线vae_encoder_pipe vae_encoder_block.init_pipeline() # Reuse the VAE we already loaded, we can reuse it with update_components() method vae_encoder_pipe.update_components(vaepipe.vae) # Run just this block image_latents vae_encoder_pipe(imageinput_image).image_latents print(image_latents.shape)这里复用了原管线中已加载的 VAE而不是重新加载一份从而保持内存高效。update_components()见 modular_pipeline.py 第 2326 行除了替换组件对象还会同步更新内部的_component_specs、_config_specs以及将被save_pretrained序列化的config字典——也就是说通过它替换组件后整个管线的定义与状态是保持一致且可保存的。组合全新的工作流为 ControlNet 管线插入 Canny 块Blocks 可组合的特性意味着你可以通过增、删、换Blocks 来修改管线的定义从而创造新工作流。下面演示一个经典场景为 ControlNet 管线插入一个 Canny 边缘检测块这样你就能直接传入普通图片而无需预先手动生成 Canny 边缘图。第一步从 Hub 加载现成的 Canny 块from diffusers.modular_pipelines import ModularPipelineBlocks # Load a canny block from the Hub canny_block ModularPipelineBlocks.from_pretrained( diffusers-internal-dev/canny-filtering, trust_remote_codeTrue, ) print(canny_block.doc)class CannyBlock Inputs: image (Union[Image, ndarray]): Image to compute canny filter on low_threshold (int, *optional*, defaults to 50): Low threshold for the canny filter. high_threshold (int, *optional*, defaults to 200): High threshold for the canny filter. ... Outputs: control_image (PIL.Image): Canny map for input image注意trust_remote_codeTrue该块是 Hub 上的自定义代码仓库ModularPipelineBlocks.from_pretrained见 modular_pipeline.py 第 424 行会读取仓库配置中的auto_map字段并通过动态模块机制加载自定义的块类。想创建自己的块可参考 自定义块构建指南。第二步提取目标工作流用get_workflow从QwenImageAutoBlocks中提取 ControlNet 工作流# Get the controlnet workflow that we want to work with blocks pipe.blocks.get_workflow(controlnet_text2image) print(blocks.doc)class SequentialPipelineBlocks Inputs: prompt (str): The prompt or prompts to guide image generation. control_image (Image): Control image for ControlNet conditioning. ...提取出的工作流是一个SequentialPipelineBlocks目前它要求外部传入control_image。第三步把 Canny 块插入到序列开头# Insert canny at the beginning blocks.sub_blocks.insert(canny, canny_block, 0) # Check the updated structure: CannyBlock is now listed as first sub-block print(blocks) # Check the updated doc print(blocks.doc)class SequentialPipelineBlocks Inputs: image (Union[Image, ndarray]): Image to compute canny filter on low_threshold (int, *optional*, defaults to 50): Low threshold for the canny filter. high_threshold (int, *optional*, defaults to 200): High threshold for the canny filter. prompt (str): The prompt or prompts to guide image generation. ...注意sub_blocks的类型是InsertableDict其insert(key, value, index)方法见 modular_pipeline_utils.py 第 61 行会先移除同名键再在指定索引处插入避免重复并支持链式调用。现在管线接受image作为输入而不是control_image了。这背后的机制是序列中的块自动共享数据——Canny 块的输出control_image自动流向需要它的 denoise 块而 Canny 块的输入image因为没有更早的块提供它就自动成为整条管线的输入。这种数据流由PipelineState见 modular_pipeline.py 第 165 行承载它以键值对存储所有输入与中间结果并在块之间传递。第四步从修改后的 Blocks 创建管线并加载 ControlNetpipeline blocks.init_pipeline(Qwen/Qwen-Image, components_managermanager) pipeline.load_components(dtypetorch.bfloat16) # Load the ControlNet model controlnet_spec pipeline.get_component_spec(controlnet) controlnet_spec.pretrained_model_name_or_path InstantX/Qwen-Image-ControlNet-Union controlnet controlnet_spec.load(dtypetorch.bfloat16) pipeline.update_components(controlnetcontrolnet)这里有个值得注意的细节ControlNet不属于原始模型仓库所以需要单独加载再通过update_components()注入。加载流程是get_component_spec(controlnet)见 modular_pipeline.py 第 2319 行取回该组件的规格副本修改其pretrained_model_name_or_path指向 ControlNet 仓库调用ComponentSpec.load()真正加载模型权重update_components(controlnetcontrolnet)把它注册进管线并同步更新内部组件规格。第五步运行新管线from diffusers.utils import load_image prompt cat wizard with red hat, gandalf, lord of the rings, detailed, fantasy, cute, adorable, Pixar, Disney image load_image(https://github.com/Trgtuan10/Image_storage/blob/main/cute_cat.png?rawtrue) output pipeline( promptprompt, imageimage, ).images[0] output至此Canny 块负责把普通图片预处理成边缘图ControlNet 再基于边缘图进行条件生成——一条全新的图片 → Canny 边缘 → ControlNet 文生图工作流就完成了全程无需手写任何预处理代码。深入ModularPipeline 的执行机制从源码看ModularPipeline.__call__见 modular_pipeline.py 第 2876 行的执行流程是若未传入state则新建一个PipelineState遍历self._blocks.inputs把用户传入的 kwargs 写入 state未提供的使用声明默认值对未知输入发出警告在torch.no_grad()下调用self._blocks(self, state)顺序执行各块根据output参数决定返回值None返回完整的PipelineState包含所有输入与中间值str返回指定中间值如outputimagelist[str]返回多个中间值的字典如output[image, latents]。由于state可以重复传入你甚至可以实现分段生成先跑一部分流程拿到中间状态再基于该状态继续执行后续块。继续深入下一步学习路径掌握了本文的运行、理解与组合能力之后可以根据兴趣继续探索理解基础积木ModularPipelineBlocks 指南——定义管线中一个步骤的基本单元顺序块指南——如何串联块按顺序执行自动块指南——如何创建支持多工作流的管线状态机制——块之间如何共享数据。构建自定义块参考 构建自定义块指南为你的业务编写带自定义逻辑的块。共享组件与内存管理使用 ComponentsManager 指南 在多个管线间共享模型并高效管理内存。可视化界面Modular Diffusers 构建的自定义块可以开箱即用地接入 Mellon 这个可视化节点式工作流界面无需编写任何 UI 代码。此外ModularPipeline 完整指南 提供了创建与加载管线的更详尽说明仓库中的 QwenImage 模块实现 与 模块化管线测试套件 也是研读真实 Block 定义与工作流展开顺序的绝佳范本。【免费下载链接】diffusers Diffusers: State-of-the-art diffusion models for image, video, and audio generation in PyTorch.项目地址: https://gitcode.com/GitHub_Trending/di/diffusers创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价