DiffusionPipeline existente, ofreciendo una alternativa más flexible y composable.
En este artículo, exploraremos cómo funciona Modular Diffusers, desde la API familiar para ejecutar un pipeline modular, hasta la construcción de bloques totalmente personalizados y su composición en tu propio flujo de trabajo. También se mostrará cómo se integra con Mellon, una interfaz de flujo de trabajo visual basada en nodos que permite conectar bloques de Modular Diffusers.
Tabla de contenidos
Inicio Rápido
A continuación, se presenta un ejemplo sencillo de cómo realizar inferencia con FLUX.2 Klein 4B utilizando bloques preconstruidos:
import torch from diffusers import ModularPipeline pipe = ModularPipeline.from_pretrained( "black-forest-labs/FLUX.2-klein-4B" ) pipe.load_components(torch_dtype=torch.bfloat16) pipe.to("cuda") image = pipe( prompt="un paisaje sereno al atardecer", num_inference_steps=4, ).images[0] image.save("output.png")
Obtienes los mismos resultados que con un DiffusionPipeline estándar, pero la estructura del pipeline es diferente: se compone de bloques flexibles — codificación de texto, codificación de imagen, desruido y decodificación — que puedes inspeccionar directamente:
print(pipe.blocks)
Flux2KleinAutoBlocks( ... Sub-Blocks: [0] text_encoder (Flux2KleinTextEncoderStep) [1] vae_encoder (Flux2KleinAutoVaeEncoderStep) [2] denoise (Flux2KleinCoreDenoiseStep) [3] decode (Flux2DecodeStep) )
Cada bloque es autónomo con sus propios inputs y outputs. Puedes ejecutar cualquier bloque de forma independiente como su propio pipeline, o añadir, eliminar y cambiar bloques libremente, ya que se recompone dinámicamente para trabajar con los bloques restantes. Usa .init_pipeline() para convertir bloques en un pipeline ejecutable, y .load_components() para cargar los pesos del modelo.
Bloques Personalizados
Modular Diffusers brilla realmente al crear tus propios bloques. Un bloque personalizado es una clase de Python que define sus componentes, inputs, outputs y lógica de cálculo; una vez definido, puedes integrarlo en cualquier flujo de trabajo.
Escritura de un Bloque Personalizado
A continuación, se muestra un ejemplo de un bloque que extrae mapas de profundidad de imágenes utilizando Depth Anything V2.
class DepthProcessorBlock(ModularPipelineBlocks): @property def expected_components(self): return [ ComponentSpec("depth_processor", DepthPreprocessor, pretrained_model_name_or_path="depth-anything/Depth-Anything-V2-Large-hf") ] @property def inputs(self): return [ InputParam("image", required=True, description="Imagen(es) de las que extraer mapas de profundidad"), ] @property def intermediate_outputs(self): return [ OutputParam("control_image", type_hint=torch.Tensor, description="Mapa(s) de profundidad de la(s) imagen(es) de entrada"), ] @torch.no_grad() def __call__(self, components, state): block_state = self.get_block_state(state) depth_map = components.depth_processor(block_state.image) block_state.control_image = depth_map.to(block_state.device) self.set_block_state(state, block_state) return components, state
expected_componentsdefine qué modelos necesita el bloque — en este caso, un modelo de estimación de profundidad. El parámetropretrained_model_name_or_pathestablece un repositorio predeterminado para cargar, de modo queload_componentsobtenga automáticamente el modelo de profundidad a menos que lo sobrescribas enmodular_model_index.json.inputsyintermediate_outputsdefinen qué entra y qué sale.__call__es donde reside la lógica de cálculo.
Composición de Bloques en Flujos de Trabajo
Utilicemos este bloque con el flujo de trabajo ControlNet de Qwen. Extrae el flujo de trabajo ControlNet e inserta el bloque de profundidad al principio:
pipe = ModularPipeline.from_pretrained("Qwen/Qwen-Image") print(pipe.blocks.available_workflows) blocks = pipe.blocks.get_workflow("controlnet_text2image") print(blocks) blocks.sub_blocks.insert("depth", DepthProcessorBlock(), 0) blocks.sub_blocks['depth'].doc
Los bloques en una secuencia comparten datos automáticamente: la salida control_image del bloque de profundidad fluye hacia los bloques posteriores que la necesitan, y su input image se convierte en un input del pipeline, ya que ningún bloque anterior lo proporciona.
from diffusers import ComponentsManager, AutoModel from diffusers.utils import load_image manager = ComponentsManager() pipeline = blocks.init_pipeline("Qwen/Qwen-Image", comp) pipeline.load_components(torch_dtype=torch.bfloat16) controlnet = AutoModel.from_pretrained("InstantX/Qwen-Image-ControlNet-Union", torch_dtype=torch.bfloat16) pipeline.update_components(c) image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/astronaut.jpg") output = pipeline( prompt="un astronauta saliendo de un huevo, detallado, fantasía, Pixar, Disney", image=image, ).images[0]
Compartiendo Bloques Personalizados en el Hub
Puedes publicar tu bloque personalizado en el Hub para que cualquiera pueda cargarlo con trust_remote_code=True. Hemos creado una plantilla para comenzar — consulta la guía de Creación de Bloques Personalizados para un recorrido completo.
pipeline.save_pretrained(local_dir, repo_id="your-username/your-block-name", push_to_hub=True)
El DepthProcessorBlock de este artículo está publicado en diffusers/depth-processor-custom-block — puedes cargarlo y usarlo directamente:
from diffusers import ModularPipelineBlocks depth_block = ModularPipelineBlocks.from_pretrained( "diffusers/depth-processor-custom-block", trust_remote_code=True )
Hemos publicado una colección de bloques personalizados listos para usar aquí.
Repositorios Modulares
ModularPipeline.from_pretrained funciona con cualquier repositorio existente de Diffusers de inmediato, pero Modular Diffusers también introduce un nuevo tipo de repositorio: el Repositorio Modular.
Un repositorio modular puede referenciar componentes de sus repositorios de modelos originales. Por ejemplo, diffusers/flux2-bnb-4bit-modular contiene un transformador cuantificado y carga los componentes restantes desde el repositorio original.
{ "transformer": [ "diffusers", "Flux2Transformer2DModel", { "pretrained_model_name_or_path": "diffusers/flux2-bnb-4bit-modular", "subfolder": "transformer", "type_hint": ["diffusers", "Flux2Transformer2DModel"] } ], "vae": [ "diffusers", "AutoencoderKLFlux2", { "pretrained_model_name_or_path": "black-forest-labs/FLUX.2-dev", "subfolder": "vae", "type_hint": ["diffusers", "AutoencoderKLFlux2"] } ], ... }
Los repositorios modulares también pueden albergar bloques de pipeline personalizados como código Python y configuraciones de interfaz visual para herramientas como Mellon, todo en un solo lugar.
Pipelines de la Comunidad
La comunidad ya ha comenzado a construir pipelines completas con Modular Diffusers y publicarlas en el Hub, incluyendo pesos de modelos y código listo para ejecutar.
- Krea Realtime Video — Un modelo de generación de video en tiempo real de 14B parámetros destilado de Wan 2.1, logrando 11fps en una sola GPU B200. Soporta texto a video, video a video, y streaming video a video — todo construido como bloques modulares. Los usuarios pueden modificar prompts en medio de la generación, reestilizar videos al instante, y ver los primeros fotogramas en menos de 1 segundo.
import torch from diffusers import ModularPipeline pipe = ModularPipeline.from_pretrained("krea/krea-realtime-video", trust_remote_code=True) pipe.load_components( trust_remote_code=True, device_map="cuda", torch_dtype={"default": torch.bfloat16, "vae": torch.float16} )
- Waypoint-1 — Un modelo de difusión de mundo en tiempo real de 2.3B parámetros de Overworld. Genera mundos interactivos de forma autoregresiva a partir de entradas de control y prompts de texto — puedes explorar e interactuar con entornos generados en tiempo real en hardware de consumo.
Los equipos pueden construir arquitecturas novedosas, empaquetarlas como bloques y publicar todo el pipeline en el Hub para que cualquiera lo utilice con ModularPipeline.from_pretrained.
Consulta la colección completa de pipelines de la comunidad para más información.
Integración con Mellon
Mellon está en desarrollo inicial y no está listo para uso en producción aún. Considera esto como un adelanto de cómo funciona la integración.
Mellon es una interfaz de flujo de trabajo visual integrada con Modular Diffusers. Si estás familiarizado con herramientas basadas en nodos como ComfyUI, te sentirás como en casa, aunque hay algunas diferencias clave:
- Nodos dinámicos — En lugar de docenas de nodos específicos para modelos, tenemos un pequeño conjunto de nodos que se adaptan automáticamente según el modelo seleccionado. Apréndelos una vez, úsalos con cualquier modelo.
- Flujos de trabajo de un solo nodo — Gracias al sistema de bloques composables de Modular Diffusers, puedes colapsar un pipeline entero en un solo nodo. Ejecuta múltiples flujos de trabajo en el mismo lienzo sin el desorden.
- Integración con el Hub lista para usar — Los bloques personalizados publicados en el Hub funcionan al instante en Mellon. Proporcionamos una función de utilidad para generar automáticamente la interfaz del nodo a partir de la definición de tu bloque, sin necesidad de código de UI.
Esta integración es posible porque cada bloque expone las mismas propiedades (inputs, intermediate_outputs, expected_components). Esta API consistente significa que Mellon puede generar automáticamente la interfaz de un nodo a partir de cualquier definición de bloque y componer bloques en nodos de nivel superior.
Por ejemplo, diffusers/FLUX.2-klein-4B-modular contiene una definición de pipeline, referencias de componentes y un mellon_pipeline_config.json — todo en un solo repositorio. Cárgalo en Python con ModularPipeline.from_pretrained("diffusers/FLUX.2-klein-4B-modular") o en Mellon para crear un flujo de trabajo de un solo nodo o de múltiples nodos.
A continuación, un ejemplo rápido. Añadimos un nodo de expansión de prompt de Gemini — alojado como un repositorio modular en diffusers/gemini-prompt-expander-mellon — a un flujo de trabajo existente de texto a imagen:
- Arrastra un nodo de Bloque Dinámico e ingresa el
repo_id(es decir,diffusers/gemini-prompt-expander-mellon) - Haz clic en CARGAR BLOQUE PERSONALIZADO — el nodo automáticamente se expande para tu entrada de prompt y un socket de salida llamado «prompt», todo configurado desde el repositorio
- Escribe un prompt corto, conecta la salida al nodo de Codificar Prompt, y ejecuta
Gemini expande tu prompt corto en una descripción detallada antes de generar la imagen. Sin código, sin configuración — solo un ID de repositorio del Hub.
Este es solo un ejemplo. Para un recorrido detallado, consulta la guía Mellon x Modular Diffusers.
Conclusión
Modular Diffusers aporta la composabilidad y flexibilidad que la comunidad ha estado solicitando, sin comprometer las características que hacen que Diffusers sea potente. Aún es pronto — queremos tu opinión para moldear lo que vendrá. Pruébalo y cuéntanos qué funciona, qué no, y qué falta.
Recursos
Gracias a Chun Te Lee por la miniatura, y a Poli, Pedro, Lysandre, Linoy, Aritra y Steven por sus reseñas reflexivas.
Mellon está en desarrollo inicial y no está listo para uso en producción aún. Considera esto como un adelanto de cómo funciona la integración.

