"Borrow the parts. Refuse the framework. The difference decides who owns your API forever."
The Same Library, Used Two Ways
The diffusers library (Hugging Face) is the standard toolkit for diffusion models. The engine depends on it heavily — and also refuses most of it. That's not a contradiction; it's a discipline. diffusers can be used as a parts library (borrow its components, assemble them yourself) or as a framework (let its pipeline classes dictate your structure). The engine does the first and forbids the second.
What You Borrow (the Parts)
diffusers ships excellent low-level pieces, and these the engine uses freely:
- Loaders — reading safetensors files, materializing tensors.
- Module classes — VAE, U-Net, DiT, MMDiT implementations you can instantiate directly.
- Scheduler implementations — Euler, DPM++, DDIM, flow-match, already correct.
- Attention primitives — the optimized kernels you don't want to rewrite.
These are parts: self-contained components with narrow jobs. You pick them up, hold them behind your own interfaces, and assemble the engine your way.
What You Refuse (the Framework)
diffusers also ships pipeline classes — the high-level SomePipeline.from_pretrained(...) objects that wire everything together and hand you a one-call generate. Convenient. Also a framework. Each pipeline class has opinions about job shape (sync vs async), error handling, the kwarg dance, conditioning conventions, and cache directories. Expose one through your API and you've adopted all of its opinions as your public contract.
Why the Distinction Is Existential
Here's the trap in concrete terms. If a route returns whatever a diffusers pipeline returns, then every client — the workspace, the brain, future tools — is now coupled to diffusers' output shape. The day diffusers changes that shape, or you want to swap to a different backend for one model, every client breaks. You didn't depend on diffusers; you married it, and made all your clients in-laws. Wrapping the parts behind your own interface keeps the divorce always available.
The Reference-Implementation Move
There's a bonus to this discipline. When a new model family ships, diffusers usually adds a pipeline class for it within days. You don't expose that pipeline — but you read it as a reference implementation of how to wire the new backbone, then build your own module behind your own interface. diffusers becomes documentation-that-runs: the fastest way to learn the new wiring, without inheriting the new opinions.