-
Notifications
You must be signed in to change notification settings - Fork 6k
[modular diffusers] introducing ModularLoader #11462
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[modular diffusers] introducing ModularLoader #11462
Conversation
… in from_pretrained
The docs for this PR live here. All of your documentation changes will be reflected on that endpoint. The docs are available until 30 days after the last update. |
# YiYi TODO: | ||
# 1. should support save some components too! currently only modular_model_index.json is saved | ||
# 2. maybe order the json file to make it more readable: configs first, then components | ||
def save_pretrained(self, save_directory: Union[str, os.PathLike], push_to_hub: bool = False, spec_only: bool = True, **kwargs): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TODO:
currently I only save config (a.k.a the model_index), we could totally save selected components into an subfolder too, so for example fine tune trainers could make a modular repo that contains fine tuned components and with the modular_model_index points to other repos for frozen components
same goes for from_pretrained()
cc @DN6 I left more info on this PR's description for Modular Loader, please read them if you have time this refactor is mainly based on your feedback from last time, so would love for you to help think through the design and implementation more |
ComponentSpec
ComponentSpec
was created to enable the "lazy loading" behavior needed for the Modular Diffusers system. This means you can define PipelineBlocks with their associated models, but the models are only created later when they're actually needed after blocks are assembled and ready to be executed.to create a
ComponentSpec
we use it to define
expected_components
for pipeline blocksit is just a
dataclass
, but it can load itself when needed, e.g. this would create a SDXL unetadditionally, each component created by a
ComponentSpec
is tagged with a unique_diffusers_load_id
attribute that encodes its creation parameters.load_id
is pretty useful for model management, e.g. our component manager system use this info to prevent duplicated loading; it also allows us to very easily build, packaging, and porting entire pipelines with guaranteed component identityModularLoader
Overview
ModularLoader
is designed to work with a newmodular_model_index.json
. Unlike traditionalmodel_index.json
that only loads models from subfolders within a single repo,ModularLoader
lets you reference components across different repositories for maximum flexibility.a modular_model_index.json looks like this (an example https://huggingface.co/YiYiXu/modular-loader-t2i/blob/main/modular_model_index.json)
each components contains 3 key elements: library, class and loading specs map
{}
You can load like this
Use with
DiffusionPipeline
the components will be registered to the loader along with config, just like
DiffusionPipeline
- in fact, they are compatible, you can usefrom_pipe
to transfer all the contents to a regular DiffusionPipelinerelated to #10413
Using ModularLoader (Basics)
create a simple modular pipeline
this is just the SDXL text-to-image pipeline but built with modular blocks. But since we had defined the models associated with each block with
ComponentSpec
s, when we put these blocks together into our final pipeline, we also assembled their model requirements too, check out itsexpected_components
attribute;(Click to see the outputs)
setup the built-in modular loader
Modular Pipeline blocks has a
setup_loader
method, it can create a build-inModularLoader
based on the requirement of the pipeline, and you can access the loader via theloader
attributeIt is pretty empty now, because we did not specify repo info when we defined pipelines, but you can see that it already has the name and type for each component, matching with what's in its
expected_components
(Click to see the outputs)
we can add a modular repo name (one contains
modular_model_index.json
) tosetup_loader()
method, the loader will be able to fetch all the loading related specs from the repo and will be able to load the required models when you callload()
we will use this repo
all the components are loaded into the loader now
(Click to see the outputs)
make a modular repo from scratch
When you're developing your custom pipeline and want to store all the component creation info conveniently in a modular repo (like the one I made), you can create one from scratch. This is my process: I set up an empty loader, run
save_pretrained()
to save the modular_model_index.json, push it to the hub, and update it with the components specs I need on the hub (you can also do it locally if you want)Use ModularLoader (with Components Manager)
We ran a basic example of setting up the built-in modular loader with a modular repo for a modular pipeline. Now I want to talk about how to work with multiple different workflows and manage your components efficiently.
Component Manager is the very important to the modular system when working with multiple pipelines. With modular model indexes, it's easy to accidentally load duplicated models since different repos can point to the same subfolders. You won't download the same file twice because the hub uses the same cache, but you could create duplicated model instances without realizing it.
A ComponentManager helps you:
To use it, just pass the component manager to setup_loader() with an optional collection name (like "t2i") to tag all models from this loader for easier retrieval later.
This same ComponentManager can now be used with a refiner pipeline:
Complete Example Script
Below is a complete example script more usage examples of the ModularLoader, including LoRA and IP-Adapter integration.
Code example (Click to expand)