Skip to content

The Modular Diffusers #9672

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

Open
wants to merge 157 commits into
base: main
Choose a base branch
from
Open

The Modular Diffusers #9672

wants to merge 157 commits into from

Conversation

yiyixuxu
Copy link
Collaborator

@yiyixuxu yiyixuxu commented Oct 14, 2024

TO-DOs before merge

  • We overrode changes in this PR https://github.com/huggingface/diffusers/pull/11652/files, need to make sure the updated code works for this case
  • PAG needs to be a guider on its own
  • One more guide on how to write a PipelineBlock; and how to assemble SequentialPipelineBlocks and AutoPipelineBlocks
  • a simple test case: slow case for now

TO-DOs

  • guider needs to be a ConfigMixin
  • ModularPipelineBlocks.from_pretrained needs to work with official blocks
  • Merge the concept of ModularLoader into ModularPipeline
  • Flux/Wan/ITX
  • API docs

Documentations

  • Documentations are live here

@HuggingFaceDocBuilderDev

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.

@yoland68
Copy link

Very cool!

@oozzy77
Copy link

oozzy77 commented Oct 30, 2024

hi this is very interesting! I'm making a Python pipeline flow visual scripting tool, that can auto-convert functions to visual nodes for fast and modular UI blocks demo. Itself is a pip package: https://pypi.org/project/nozyio/

I wanted to integrate diffusers with my flow nodes UI project but found its not very modular. But this PR may change that! Looking forward to see how this evolves.

github: https://github.com/oozzy77/nozyio happy to connect!

@yiyixuxu
Copy link
Collaborator Author

@oozzy77 thanks!
do you want to join a slack channel with me? if you want to experiment building something with this PR I'm eager to hear your feedback and iterate base on that

@oozzy77
Copy link

oozzy77 commented Oct 31, 2024 via email

@yiyixuxu
Copy link
Collaborator Author

@oozzy77 I sent an invite!

@yiyixuxu yiyixuxu added the roadmap Add to current release roadmap label Dec 4, 2024
@hlky hlky mentioned this pull request Dec 5, 2024
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@DN6 @sayakpaul
I merged in this part of code without reviewing it (I need the save_pretrained() code and it works fine)
can you let me know if you want to keep it in here when we merge this PR or remove &convert it into a new PR


GuiderType = Union[
AdaptiveProjectedGuidance,
AutoGuidance,
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@a-r-r-o-w can we make sure PAG has its own class before we merge?

@@ -154,33 +159,87 @@ def check_imports(filename):
return get_relative_imports(filename)


def get_class_in_module(class_name, module_path, pretrained_model_name_or_path=None):
def _raise_timeout_error(signum, frame):
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@DN6 is there a test we can run for remote code? want to make sure we don't break anything here

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh no test yet. Can add one.

@yiyixuxu yiyixuxu requested review from stevhliu, a-r-r-o-w and asomoza and removed request for stevhliu July 1, 2025 02:39
@stevhliu
Copy link
Member

stevhliu commented Jul 2, 2025

Super comprehensive and nice set of guides! 👏

Here is my feedback:

  1. The getting_started.md doc is quite large and may be intimidating for new users, especially as a "getting started" guide. I think it may be better to take a more top-down approach here with a brief explanation of the block types and then follow it up with a practical example of using these blocks to create a workflow (maybe mention the 4-step process here). This way users can more concretely and immediately grasp the main focus of Modular Diffusers.
  2. Create a separate doc to go over PipelineState and BlockState.
  3. The write_your_own_pipeline_block.md doc can be split into a separate doc for each block type.
  4. Create a new doc for ModularPipeline now that users have gone over the state and block types.
  5. I think the end_to_end_guide.md is actually a very nice "quickstart" doc. It's seems pretty similar to this section here though? Maybe we can turn this into a nice blog post for announcing Modular Diffusers?

The docs would look something like this:

- local: getting_started
  title: Getting started
- local: modular_diffusers_states
  title: Pipeline and block states
- local: pipeline_block
  title: PipelineBlock
- local: sequential_pipeline_blocks
  title: SequentialPipelineBlocks
- local: loop_sequential_pipeline_blocks
  title: LoopSequentialPipelineBlocks
- local: auto_pipeline_blocks
  title: AutoPipelineBlocks
- local: modular_pipeline
  title: ModularPipeline

@yiyixuxu
Copy link
Collaborator Author

yiyixuxu commented Jul 3, 2025

@stevhliu
Thanks for the feedback! I'll wait to consolidate other feedback before making any changes, but I totally agree - reorganizing the docs into smaller, more digestible pieces makes a lot of sense.
I think maybe we can skip the getting_started doc for now and revisit it later though. It's not very clear yet what the bare minimum knowledge we need to get across is, since (at least for now) we're targeting more advanced users. This is a system for building new pipelines/workflows, so naturally there's a higher entry barrier.
We're not announcing Modular Diffusers publicly yet - current goal is to get it merged so it's easier to iterate with the team and the community members who are enthusiastic about this. That gives us some time to figure out the right onboarding approach.
I can consolidate the quickstart and end-to-end guide into one for now, but they won't be very "quick" at all 😅 - just have a more practical focus. And yeah, we can definitely turn them into a blog post when we're announcing it, and we should have a real "quick start" ready by then.

So I think we can aim for something like this for the merge, what do you think?

- local: modular_diffusers_states
  title: Pipeline and block states 
- local: pipeline_block
  title: PipelineBlock
- local: sequential_pipeline_blocks
  title: SequentialPipelineBlocks
- local: loop_sequential_pipeline_blocks
  title: LoopSequentialPipelineBlocks
- local: auto_pipeline_blocks
  title: AutoPipelineBlocks
- local: modular_pipeline
  title: ModularPipeline
 - local: end_to_end_guide
   title: An End-to-End Example (from building custom pipeline to UI node deployment) # look for better names lol

@stevhliu
Copy link
Member

stevhliu commented Jul 3, 2025

Sounds good to me, let me know how I can help!


<Tip>

💡 We recommend using `ModularPipeline` with Component Manager by passing a `components_manager`:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would just have the description of the ComponentManager before the code example.


```py
>>> components = ComponentsManager()
>>> pipeline = blocks.init_pipeline(modular_repo_id, components_manager=components)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if no component manager is set?

from diffusers import ComponentsManager
# Set up component manager and turn on the offloading
components = ComponentsManager()
components.enable_auto_cpu_offload(device="cuda")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would auto offloading work here? No components have been loaded into it yet?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah it works, once the strategy is on it's on, you can add/remove models
(currently I just reset it everytime a model is added/removed, so basically all the models get moved to cpu and start over; but we can certainly do it more efficiently if there is a demand for that)

a-r-r-o-w added 2 commits July 4, 2025 12:19
* update

* fix

* update
* update

* update

* register to config pag
Copy link
Member

@sayakpaul sayakpaul left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for leading the charge here, @yiyixuxu! 15k LoC changes might seem a lot but I do believe that it's for the greater good!

My comments are mostly in the docs because I think even for reviewers, that should be the entrypoint to understanding the different moving parts involed in the modular design.

Additionally, I also reviewed the changes made to the existing core modules and all of them are okay to me.

Apart from that, I am quite interested to grow the offloading part in components manager as I believe that will be crucial for the UI-based workflows!


**Important**: It is important to always check the docstring because arguments can be different from standard pipelines that you're familar with. For example, in Modular Diffusers we standardized controlnet image input as `control_image`, but regular pipelines have inconsistencies over the names, e.g. controlnet text-to-image uses `image` while SDXL controlnet img2img uses `control_image`.

**Note**: The `output` list might be longer than you expected - it includes everything in the intermediate state that you can choose to return. Most of the time, you'll just want `output="images"` or `output="latents"`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we could show an example output?

Comment on lines +709 to +711
```py
t2i_pipeline.doc
```
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it need to be here?


**Components Manager**: Create one manager and pass it to `init_pipeline` along with a collection name. All models loaded by that pipeline will be added to the manager under that collection.

**Auto Offloading**: All components are placed on CPU and only moved to device right before their forward pass. The manager monitors device memory and may move components off-device to make space for new ones. Unlike `DiffusionPipeline.enable_model_cpu_offload()`, this works across all components in the manager and all your workflows.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the component manager deserves its own section / page where we go deep into offloading, etc., and remove it from there.

I am also following what is meant by

Unlike DiffusionPipeline.enable_model_cpu_offload(), this works across all components in the manager and all your workflows.

If we do enable_model_cpu_offload() it works on all the model-components of the underlying pipeline, no?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it works across pipelines, say like you have 10 pipelines share 15 models, it works across these 15 models

for model_name, pipeline in task_mapping.items():
if pipeline.__name__ == pipeline_class_name:
return model_name
def _get_model(pipeline_class_name):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am guessing this is just refactoring?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
roadmap Add to current release roadmap
Projects
Status: In Progress
Development

Successfully merging this pull request may close these issues.