Если вы хоть раз пытались запихнуть кастомный контроллер или лупер в стандартный DiffusionPipeline от Hugging Face, вы знаете это чувство. Будто пытаешься собрать IKEA-шкаф, но вместо инструкции - философский трактат на древнегреческом, а вместо шестигранного ключа - отвёртка для глаз. Всё это закончилось в 2025 году с появлением Modular Diffusers.
Что сломалось в старом мире
Классические пайплайны были монолитами. Хочешь добавить этап предварительной обработки промпта с помощью Qwen3 VL? Переписывай половину класса. Нужно встроить кастомный сэмплер между денойзерами? Удачи. Проблему пытались решить визуальными конструкторами вроде ComfyUI, но это было похоже на попытку нарисовать Венеру Милосскую в MS Paint - работает, но мучительно.
Ключевые возможности: почему это не просто ещё одна абстракция
- Стандартизированные интерфейсы: Каждый блок имеет четкие входы и выходы. Можете соединить блок для FLUX.2 Klein с блоком для старого Stable Diffusion 3? Технически - да. Практически - зачем? Но можно.
- Готовые фабрики блоков: Загрузка моделей из Hugging Face Hub, локально, даже конвертация весов на лету. Для новой архитектуры Differential Transformer V2 уже есть адаптеры.
- Визуальное проектирование через Mellon: Тот случай, когда интерфейс "перетащи-и-брось" не вызывает желание разбить монитор. Графы рендерятся чисто, связи не путаются.
- Сериализация всего: Весь пайплайн, включая версии всех блоков и их настройки, можно сохранить в один JSON-файл. Воспроизводимость на уровне "открыл файл - получил тот же результат".
1 Установка и первый пайплайн за 60 секунд
Никакой магии с установкой десятка зависимостей. Проще, чем кажется.
pip install modular-diffusers==2.8.0 # Самая актуальная версия на март 2026
pip install torch --index-url https://download.pytorch.org/whl/cu121 # Под вашу CUDA
А теперь базовый пайплайн для текстуры, который можно было бы использовать в BLIMP-подобном пайплайне для синтеза данных.
from modular_diffusers import ModularPipeline, load_block
from modular_diffusers.blocks import (
TextEncoderBlock,
DiffusionModelBlock,
VAE_DecoderBlock,
SchedulerBlock
)
# Сборка пайплайна - буквально как список
pipeline = ModularPipeline([
TextEncoderBlock.from_pretrained("stabilityai/stable-diffusion-3.5-medium"),
DiffusionModelBlock.from_pretrained("black-forge/flux2-klein-schnell"), # Новый FLUX.2 Klein
SchedulerBlock("flow_match", num_inference_steps=12),
VAE_DecoderBlock.from_pretrained("madebyollama/taesd3xl"),
])
# Генерация
image = pipeline(
prompt="texture of ancient concrete, cracks, PBR, seamless",
negative_prompt="blurry, smooth, shiny",
height=512,
width=512
)
image.save("texture.png")
Внимание на строку с FLUX.2 Klein. Если вы всё ещё используете старые модели Stable Diffusion в 2026 году, у вас есть проблемы, которые Modular Diffusers не решит. Архитектура FLUX.2 стала де-факто стандартом для качественной генерации, и библиотека это учитывает.
2 Создаём кастомный блок: Фильтр «Винтажная плёнка»
Допустим, нам нужен блок, который накладывает эффект плёнки на сгенерированное изображение. В классическом пайплайне пришлось бы лезть в исходники. Здесь - наследуемся от BaseBlock.
import torch
import torchvision.transforms as T
from modular_diffusers.blocks.base import BaseBlock
from PIL import Image, ImageFilter, ImageOps
class VintageFilmBlock(BaseBlock):
"""Блок для добавления эффекта винтажной плёнки.
Принимает tensor или PIL Image, возвращает PIL Image.
"""
def __init__(self, grain_intensity=0.1, vignette_strength=0.3):
super().__init__()
self.grain = grain_intensity
self.vignette = vignette_strength
# Блок имеет стандартные атрибуты name и version
self.name = "VintageFilmEffect"
self.version = "1.0"
def forward(self, image):
# Принимаем и tensor из VAE, и PIL от других блоков
if isinstance(image, torch.Tensor):
# Конвертируем tensor [1, C, H, W] в PIL
image = T.ToPILImage()(image.squeeze(0))
# Добавляем шум (зерно)
if self.grain > 0:
noise = Image.effect_noise(image.size, self.grain * 255)
image = Image.blend(image, noise, 0.05)
# Добавляем виньетку
if self.vignette > 0:
mask = Image.new("L", image.size, 255)
for y in range(image.size[1]):
for x in range(image.size[0]):
dist_x = abs(x - image.size[0] / 2) / (image.size[0] / 2)
dist_y = abs(y - image.size[1] / 2) / (image.size[1] / 2)
dist = (dist_x**2 + dist_y**2) ** 0.5
value = int(255 * (1 - dist * self.vignette))
mask.putpixel((x, y), value)
image = Image.composite(
Image.new("RGB", image.size, (20, 10, 5)),
image,
mask
)
return image
# Используем в пайплайне - просто добавляем в конец
pipeline.blocks.append(VintageFilmBlock(grain_intensity=0.15))
# Или вставим между другими блоками
pipeline.insert_block(3, VintageFilmBlock()) # После денойзера, перед VAE
Теперь у вас есть блок, который можно переиспользовать, делиться им и даже выложить на Hugging Face как отдельный компонент.
Интеграция с Mellon: когда кодом управляешь мышкой
Mellon - это визуальный редактор графов для AI-пайплайнов. Выглядит как нодальная система из Blender или того же ComfyUI, но без хаоса. Главное преимущество - он использует те же самые блоки Modular Diffusers, что и ваш код.
| Что можно делать в Mellon | Зачем это нужно |
|---|---|
| Перетаскивать блоки на канвас | Быстро прототипировать сложные воркфлоу без написания кода |
| Настраивать параметры блоков в UI | Искать оптимальные настройки для конкретной задачи |
| Экспортировать граф в код Python | Получить готовый скрипт для продакшена или шеринга |
| Импортировать кастомные блоки | Работать с вашим VintageFilmBlock через интерфейс |
Запускается Mellon просто:
mellon-server --port 7860 --library-path ./my_custom_blocks
Открываете localhost:7860 и видите интерфейс, где слева - палитра блоков, в центре - канвас, справа - настройки выбранного блока. Собрали граф, нажали "Export", получаете Python-скрипт с вашим ModularPipeline.
Сравнение с альтернативами: кто остался в дураках
- DiffusionPipeline (Hugging Face): Монолит. Гибкость на уровне «можно переписать всё». Подходит для базового использования, когда нужна одна модель и стандартный процесс. Всё.
- ComfyUI: Визуальная гибкость, но ад для версионирования и отладки. Граф из 150 нод, который падает с ошибкой «нода 73 получила не тот тип данных» - это квест на выживание. К тому же, как мы уже писали, Modular Diffusers убил его в производственной среде.
- Собственный велосипед: Потратите месяц, напишете 2000 строк кода, будет работать. Но поддерживать, обновлять и делиться им будет нереально. Не делайте так.
Кому на самом деле стоит использовать Modular Diffusers
Исследователям, которые экспериментируют с новыми сэмплерами, методами контроля или гибридными архитектурами. Собрали прототип из блоков, провели эксперименты, опубликовали блок как часть работы.
AI-инженерам в продакшене, которым нужен воспроизводимый, версионируемый и документированный пайплайн. JSON-конфиг пайплайна можно положить в Git, review-ить изменения, rollback-ить.
Артистам и дизайнерам, которые хотят кастомизировать процесс генерации без погружения в код, но через удобный интерфейс Mellon. Создали уникальный воркфлоу для своего стиля - сохранили, используете.
Преподавателям: Наглядно показывать студентам, из каких этапов состоит диффузия. Можно отключать блоки (например, VAE) и смотреть на латентные представления.
Совет напоследок: начните с малого. Возьмите готовый пример пайплайна из документации, замените в нём одну модель на другую (например, на свежий FLUX.2 Klein), добавьте простой кастомный блок-фильтр. Скорее всего, через час вы поймёте, что можете собрать то, на что раньше потратили бы день отладки в ComfyUI или неделю кодинга своего решения. И да, JSON-конфигурацию пайплайна теперь можно парсить без проблем, используя методы из статьи про заставку LLM парсить JSON.