Compare commits
48 Commits
ci-test-cache
...
v0.30.1
| Author | SHA1 | Date | |
|---|---|---|---|
| 8b9bfaea80 | |||
| b12c7f8390 | |||
| 06f36713ae | |||
| 19c5d7b376 | |||
| 99a64aa63c | |||
| 1bb419672d | |||
| a655574710 | |||
| 67a80dfbd5 | |||
| 1f77300d23 | |||
| 8a79d8ec39 | |||
| 2dad462d9b | |||
| e3568d14ba | |||
| f6df22447c | |||
| 9b5180cb5f | |||
| 16a93f1a25 | |||
| 2d753b6fb5 | |||
| 39e1f7eaa4 | |||
| e1b603dc2e | |||
| e4325606db | |||
| 926daa30f9 | |||
| 325a5de3a9 | |||
| 4c6152c2fb | |||
| 87e50a2f1d | |||
| a57a7af45c | |||
| 52f1378e64 | |||
| 3dc97bd148 | |||
| 6d32b29239 | |||
| bc3c73ad0b | |||
| 5934873b8f | |||
| b7058d142c | |||
| e1d508ae92 | |||
| fc6a91e383 | |||
| 2b76099610 | |||
| 4f0d01d387 | |||
| 3dc10a535f | |||
| c370b90ff1 | |||
| ebf3ab1477 | |||
| fbe29c6298 | |||
| 7071b7461b | |||
| a054c78495 | |||
| b1f43d7189 | |||
| 0e460675e2 | |||
| 7b98c4cc67 | |||
| 27637a5402 | |||
| 2ea22e1cc7 | |||
| 95a7832879 | |||
| c646fbc124 | |||
| 05b706c003 |
@@ -32,7 +32,7 @@ jobs:
|
|||||||
fetch-depth: 2
|
fetch-depth: 2
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
pip install -e .
|
pip install -e .[test]
|
||||||
pip install huggingface_hub
|
pip install huggingface_hub
|
||||||
- name: Fetch Pipeline Matrix
|
- name: Fetch Pipeline Matrix
|
||||||
id: fetch_pipeline_matrix
|
id: fetch_pipeline_matrix
|
||||||
|
|||||||
+1
-1
@@ -63,7 +63,7 @@ In the same spirit, you are of immense help to the community by answering such q
|
|||||||
|
|
||||||
**Please** keep in mind that the more effort you put into asking or answering a question, the higher
|
**Please** keep in mind that the more effort you put into asking or answering a question, the higher
|
||||||
the quality of the publicly documented knowledge. In the same way, well-posed and well-answered questions create a high-quality knowledge database accessible to everybody, while badly posed questions or answers reduce the overall quality of the public knowledge database.
|
the quality of the publicly documented knowledge. In the same way, well-posed and well-answered questions create a high-quality knowledge database accessible to everybody, while badly posed questions or answers reduce the overall quality of the public knowledge database.
|
||||||
In short, a high quality question or answer is *precise*, *concise*, *relevant*, *easy-to-understand*, *accessible*, and *well-formated/well-posed*. For more information, please have a look through the [How to write a good issue](#how-to-write-a-good-issue) section.
|
In short, a high quality question or answer is *precise*, *concise*, *relevant*, *easy-to-understand*, *accessible*, and *well-formatted/well-posed*. For more information, please have a look through the [How to write a good issue](#how-to-write-a-good-issue) section.
|
||||||
|
|
||||||
**NOTE about channels**:
|
**NOTE about channels**:
|
||||||
[*The forum*](https://discuss.huggingface.co/c/discussion-related-to-httpsgithubcomhuggingfacediffusers/63) is much better indexed by search engines, such as Google. Posts are ranked by popularity rather than chronologically. Hence, it's easier to look up questions and answers that we posted some time ago.
|
[*The forum*](https://discuss.huggingface.co/c/discussion-related-to-httpsgithubcomhuggingfacediffusers/63) is much better indexed by search engines, such as Google. Posts are ranked by popularity rather than chronologically. Hence, it's easier to look up questions and answers that we posted some time ago.
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ Please refer to the [How to use Stable Diffusion in Apple Silicon](https://huggi
|
|||||||
|
|
||||||
## Quickstart
|
## Quickstart
|
||||||
|
|
||||||
Generating outputs is super easy with 🤗 Diffusers. To generate an image from text, use the `from_pretrained` method to load any pretrained diffusion model (browse the [Hub](https://huggingface.co/models?library=diffusers&sort=downloads) for 27.000+ checkpoints):
|
Generating outputs is super easy with 🤗 Diffusers. To generate an image from text, use the `from_pretrained` method to load any pretrained diffusion model (browse the [Hub](https://huggingface.co/models?library=diffusers&sort=downloads) for 30,000+ checkpoints):
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from diffusers import DiffusionPipeline
|
from diffusers import DiffusionPipeline
|
||||||
@@ -209,7 +209,7 @@ Also, say 👋 in our public Discord channel <a href="https://discord.gg/G7tWnz9
|
|||||||
- https://github.com/deep-floyd/IF
|
- https://github.com/deep-floyd/IF
|
||||||
- https://github.com/bentoml/BentoML
|
- https://github.com/bentoml/BentoML
|
||||||
- https://github.com/bmaltais/kohya_ss
|
- https://github.com/bmaltais/kohya_ss
|
||||||
- +12.000 other amazing GitHub repositories 💪
|
- +14,000 other amazing GitHub repositories 💪
|
||||||
|
|
||||||
Thank you for using us ❤️.
|
Thank you for using us ❤️.
|
||||||
|
|
||||||
|
|||||||
@@ -190,6 +190,10 @@
|
|||||||
- local: conceptual/evaluation
|
- local: conceptual/evaluation
|
||||||
title: Evaluating Diffusion Models
|
title: Evaluating Diffusion Models
|
||||||
title: Conceptual Guides
|
title: Conceptual Guides
|
||||||
|
- sections:
|
||||||
|
- local: community_projects
|
||||||
|
title: Projects built with Diffusers
|
||||||
|
title: Community Projects
|
||||||
- sections:
|
- sections:
|
||||||
- isExpanded: false
|
- isExpanded: false
|
||||||
sections:
|
sections:
|
||||||
@@ -235,8 +239,12 @@
|
|||||||
title: VQModel
|
title: VQModel
|
||||||
- local: api/models/autoencoderkl
|
- local: api/models/autoencoderkl
|
||||||
title: AutoencoderKL
|
title: AutoencoderKL
|
||||||
|
- local: api/models/autoencoderkl_cogvideox
|
||||||
|
title: AutoencoderKLCogVideoX
|
||||||
- local: api/models/asymmetricautoencoderkl
|
- local: api/models/asymmetricautoencoderkl
|
||||||
title: AsymmetricAutoencoderKL
|
title: AsymmetricAutoencoderKL
|
||||||
|
- local: api/models/stable_cascade_unet
|
||||||
|
title: StableCascadeUNet
|
||||||
- local: api/models/autoencoder_tiny
|
- local: api/models/autoencoder_tiny
|
||||||
title: Tiny AutoEncoder
|
title: Tiny AutoEncoder
|
||||||
- local: api/models/autoencoder_oobleck
|
- local: api/models/autoencoder_oobleck
|
||||||
@@ -253,8 +261,12 @@
|
|||||||
title: HunyuanDiT2DModel
|
title: HunyuanDiT2DModel
|
||||||
- local: api/models/aura_flow_transformer2d
|
- local: api/models/aura_flow_transformer2d
|
||||||
title: AuraFlowTransformer2DModel
|
title: AuraFlowTransformer2DModel
|
||||||
|
- local: api/models/flux_transformer
|
||||||
|
title: FluxTransformer2DModel
|
||||||
- local: api/models/latte_transformer3d
|
- local: api/models/latte_transformer3d
|
||||||
title: LatteTransformer3DModel
|
title: LatteTransformer3DModel
|
||||||
|
- local: api/models/cogvideox_transformer3d
|
||||||
|
title: CogVideoXTransformer3DModel
|
||||||
- local: api/models/lumina_nextdit2d
|
- local: api/models/lumina_nextdit2d
|
||||||
title: LuminaNextDiT2DModel
|
title: LuminaNextDiT2DModel
|
||||||
- local: api/models/transformer_temporal
|
- local: api/models/transformer_temporal
|
||||||
@@ -294,6 +306,8 @@
|
|||||||
title: AutoPipeline
|
title: AutoPipeline
|
||||||
- local: api/pipelines/blip_diffusion
|
- local: api/pipelines/blip_diffusion
|
||||||
title: BLIP-Diffusion
|
title: BLIP-Diffusion
|
||||||
|
- local: api/pipelines/cogvideox
|
||||||
|
title: CogVideoX
|
||||||
- local: api/pipelines/consistency_models
|
- local: api/pipelines/consistency_models
|
||||||
title: Consistency Models
|
title: Consistency Models
|
||||||
- local: api/pipelines/controlnet
|
- local: api/pipelines/controlnet
|
||||||
@@ -320,6 +334,8 @@
|
|||||||
title: DiffEdit
|
title: DiffEdit
|
||||||
- local: api/pipelines/dit
|
- local: api/pipelines/dit
|
||||||
title: DiT
|
title: DiT
|
||||||
|
- local: api/pipelines/flux
|
||||||
|
title: Flux
|
||||||
- local: api/pipelines/hunyuandit
|
- local: api/pipelines/hunyuandit
|
||||||
title: Hunyuan-DiT
|
title: Hunyuan-DiT
|
||||||
- local: api/pipelines/i2vgenxl
|
- local: api/pipelines/i2vgenxl
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ The [`~loaders.FromSingleFileMixin.from_single_file`] method allows you to load:
|
|||||||
|
|
||||||
## Supported pipelines
|
## Supported pipelines
|
||||||
|
|
||||||
|
- [`CogVideoXPipeline`]
|
||||||
- [`StableDiffusionPipeline`]
|
- [`StableDiffusionPipeline`]
|
||||||
- [`StableDiffusionImg2ImgPipeline`]
|
- [`StableDiffusionImg2ImgPipeline`]
|
||||||
- [`StableDiffusionInpaintPipeline`]
|
- [`StableDiffusionInpaintPipeline`]
|
||||||
@@ -49,8 +50,10 @@ The [`~loaders.FromSingleFileMixin.from_single_file`] method allows you to load:
|
|||||||
- [`UNet2DConditionModel`]
|
- [`UNet2DConditionModel`]
|
||||||
- [`StableCascadeUNet`]
|
- [`StableCascadeUNet`]
|
||||||
- [`AutoencoderKL`]
|
- [`AutoencoderKL`]
|
||||||
|
- [`AutoencoderKLCogVideoX`]
|
||||||
- [`ControlNetModel`]
|
- [`ControlNetModel`]
|
||||||
- [`SD3Transformer2DModel`]
|
- [`SD3Transformer2DModel`]
|
||||||
|
- [`FluxTransformer2DModel`]
|
||||||
|
|
||||||
## FromSingleFileMixin
|
## FromSingleFileMixin
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
<!--Copyright 2024 The HuggingFace Team. All rights reserved.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||||
|
the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||||
|
an "AS IS" BASIS, 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. -->
|
||||||
|
|
||||||
|
# AutoencoderKLCogVideoX
|
||||||
|
|
||||||
|
The 3D variational autoencoder (VAE) model with KL loss used in [CogVideoX](https://github.com/THUDM/CogVideo) was introduced in [CogVideoX: Text-to-Video Diffusion Models with An Expert Transformer](https://github.com/THUDM/CogVideo/blob/main/resources/CogVideoX.pdf) by Tsinghua University & ZhipuAI.
|
||||||
|
|
||||||
|
The model can be loaded with the following code snippet.
|
||||||
|
|
||||||
|
```python
|
||||||
|
from diffusers import AutoencoderKLCogVideoX
|
||||||
|
|
||||||
|
vae = AutoencoderKLCogVideoX.from_pretrained("THUDM/CogVideoX-2b", subfolder="vae", torch_dtype=torch.float16).to("cuda")
|
||||||
|
```
|
||||||
|
|
||||||
|
## AutoencoderKLCogVideoX
|
||||||
|
|
||||||
|
[[autodoc]] AutoencoderKLCogVideoX
|
||||||
|
- decode
|
||||||
|
- encode
|
||||||
|
- all
|
||||||
|
|
||||||
|
## AutoencoderKLOutput
|
||||||
|
|
||||||
|
[[autodoc]] models.autoencoders.autoencoder_kl.AutoencoderKLOutput
|
||||||
|
|
||||||
|
## DecoderOutput
|
||||||
|
|
||||||
|
[[autodoc]] models.autoencoders.vae.DecoderOutput
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
<!--Copyright 2024 The HuggingFace Team. All rights reserved.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||||
|
the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||||
|
an "AS IS" BASIS, 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. -->
|
||||||
|
|
||||||
|
# CogVideoXTransformer3DModel
|
||||||
|
|
||||||
|
A Diffusion Transformer model for 3D data from [CogVideoX](https://github.com/THUDM/CogVideo) was introduced in [CogVideoX: Text-to-Video Diffusion Models with An Expert Transformer](https://github.com/THUDM/CogVideo/blob/main/resources/CogVideoX.pdf) by Tsinghua University & ZhipuAI.
|
||||||
|
|
||||||
|
The model can be loaded with the following code snippet.
|
||||||
|
|
||||||
|
```python
|
||||||
|
from diffusers import CogVideoXTransformer3DModel
|
||||||
|
|
||||||
|
vae = CogVideoXTransformer3DModel.from_pretrained("THUDM/CogVideoX-2b", subfolder="transformer", torch_dtype=torch.float16).to("cuda")
|
||||||
|
```
|
||||||
|
|
||||||
|
## CogVideoXTransformer3DModel
|
||||||
|
|
||||||
|
[[autodoc]] CogVideoXTransformer3DModel
|
||||||
|
|
||||||
|
## Transformer2DModelOutput
|
||||||
|
|
||||||
|
[[autodoc]] models.modeling_outputs.Transformer2DModelOutput
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
<!--Copyright 2024 The HuggingFace Team. All rights reserved.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||||
|
the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||||
|
an "AS IS" BASIS, 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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
# FluxTransformer2DModel
|
||||||
|
|
||||||
|
A Transformer model for image-like data from [Flux](https://blackforestlabs.ai/announcing-black-forest-labs/).
|
||||||
|
|
||||||
|
## FluxTransformer2DModel
|
||||||
|
|
||||||
|
[[autodoc]] FluxTransformer2DModel
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
<!--Copyright 2024 The HuggingFace Team. All rights reserved.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||||
|
the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||||
|
an "AS IS" BASIS, 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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
# StableCascadeUNet
|
||||||
|
|
||||||
|
A UNet model from the [Stable Cascade pipeline](../pipelines/stable_cascade.md).
|
||||||
|
|
||||||
|
## StableCascadeUNet
|
||||||
|
|
||||||
|
[[autodoc]] models.unets.unet_stable_cascade.StableCascadeUNet
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
<!--Copyright 2024 The HuggingFace Team. All rights reserved.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# 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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
# CogVideoX
|
||||||
|
|
||||||
|
[CogVideoX: Text-to-Video Diffusion Models with An Expert Transformer](https://arxiv.org/abs/2408.06072) from Tsinghua University & ZhipuAI, by Zhuoyi Yang, Jiayan Teng, Wendi Zheng, Ming Ding, Shiyu Huang, Jiazheng Xu, Yuanming Yang, Wenyi Hong, Xiaohan Zhang, Guanyu Feng, Da Yin, Xiaotao Gu, Yuxuan Zhang, Weihan Wang, Yean Cheng, Ting Liu, Bin Xu, Yuxiao Dong, Jie Tang.
|
||||||
|
|
||||||
|
The abstract from the paper is:
|
||||||
|
|
||||||
|
*We introduce CogVideoX, a large-scale diffusion transformer model designed for generating videos based on text prompts. To efficently model video data, we propose to levearge a 3D Variational Autoencoder (VAE) to compresses videos along both spatial and temporal dimensions. To improve the text-video alignment, we propose an expert transformer with the expert adaptive LayerNorm to facilitate the deep fusion between the two modalities. By employing a progressive training technique, CogVideoX is adept at producing coherent, long-duration videos characterized by significant motion. In addition, we develop an effectively text-video data processing pipeline that includes various data preprocessing strategies and a video captioning method. It significantly helps enhance the performance of CogVideoX, improving both generation quality and semantic alignment. Results show that CogVideoX demonstrates state-of-the-art performance across both multiple machine metrics and human evaluations. The model weight of CogVideoX-2B is publicly available at https://github.com/THUDM/CogVideo.*
|
||||||
|
|
||||||
|
<Tip>
|
||||||
|
|
||||||
|
Make sure to check out the Schedulers [guide](../../using-diffusers/schedulers.md) to learn how to explore the tradeoff between scheduler speed and quality, and see the [reuse components across pipelines](../../using-diffusers/loading.md#reuse-a-pipeline) section to learn how to efficiently load the same components into multiple pipelines.
|
||||||
|
|
||||||
|
</Tip>
|
||||||
|
|
||||||
|
This pipeline was contributed by [zRzRzRzRzRzRzR](https://github.com/zRzRzRzRzRzRzR). The original codebase can be found [here](https://huggingface.co/THUDM). The original weights can be found under [hf.co/THUDM](https://huggingface.co/THUDM).
|
||||||
|
|
||||||
|
There are two models available that can be used with the CogVideoX pipeline:
|
||||||
|
- [`THUDM/CogVideoX-2b`](https://huggingface.co/THUDM/CogVideoX-2b)
|
||||||
|
- [`THUDM/CogVideoX-5b`](https://huggingface.co/THUDM/CogVideoX-5b)
|
||||||
|
|
||||||
|
## Inference
|
||||||
|
|
||||||
|
Use [`torch.compile`](https://huggingface.co/docs/diffusers/main/en/tutorials/fast_diffusion#torchcompile) to reduce the inference latency.
|
||||||
|
|
||||||
|
First, load the pipeline:
|
||||||
|
|
||||||
|
```python
|
||||||
|
import torch
|
||||||
|
from diffusers import CogVideoXPipeline
|
||||||
|
from diffusers.utils import export_to_video
|
||||||
|
|
||||||
|
pipe = CogVideoXPipeline.from_pretrained("THUDM/CogVideoX-2b").to("cuda")
|
||||||
|
```
|
||||||
|
|
||||||
|
Then change the memory layout of the pipelines `transformer` component to `torch.channels_last`:
|
||||||
|
|
||||||
|
```python
|
||||||
|
pipe.transformer.to(memory_format=torch.channels_last)
|
||||||
|
```
|
||||||
|
|
||||||
|
Finally, compile the components and run inference:
|
||||||
|
|
||||||
|
```python
|
||||||
|
pipe.transformer = torch.compile(pipeline.transformer, mode="max-autotune", fullgraph=True)
|
||||||
|
|
||||||
|
# CogVideoX works well with long and well-described prompts
|
||||||
|
prompt = "A panda, dressed in a small, red jacket and a tiny hat, sits on a wooden stool in a serene bamboo forest. The panda's fluffy paws strum a miniature acoustic guitar, producing soft, melodic tunes. Nearby, a few other pandas gather, watching curiously and some clapping in rhythm. Sunlight filters through the tall bamboo, casting a gentle glow on the scene. The panda's face is expressive, showing concentration and joy as it plays. The background includes a small, flowing stream and vibrant green foliage, enhancing the peaceful and magical atmosphere of this unique musical performance."
|
||||||
|
video = pipe(prompt=prompt, guidance_scale=6, num_inference_steps=50).frames[0]
|
||||||
|
```
|
||||||
|
|
||||||
|
The [benchmark](https://gist.github.com/a-r-r-o-w/5183d75e452a368fd17448fcc810bd3f) results on an 80GB A100 machine are:
|
||||||
|
|
||||||
|
```
|
||||||
|
Without torch.compile(): Average inference time: 96.89 seconds.
|
||||||
|
With torch.compile(): Average inference time: 76.27 seconds.
|
||||||
|
```
|
||||||
|
|
||||||
|
### Memory optimization
|
||||||
|
|
||||||
|
CogVideoX-2b requires about 19 GB of GPU memory to decode 49 frames (6 seconds of video at 8 FPS) with output resolution 720x480 (W x H), which makes it not possible to run on consumer GPUs or free-tier T4 Colab. The following memory optimizations could be used to reduce the memory footprint. For replication, you can refer to [this](https://gist.github.com/a-r-r-o-w/3959a03f15be5c9bd1fe545b09dfcc93) script.
|
||||||
|
|
||||||
|
- `pipe.enable_model_cpu_offload()`:
|
||||||
|
- Without enabling cpu offloading, memory usage is `33 GB`
|
||||||
|
- With enabling cpu offloading, memory usage is `19 GB`
|
||||||
|
- `pipe.vae.enable_tiling()`:
|
||||||
|
- With enabling cpu offloading and tiling, memory usage is `11 GB`
|
||||||
|
- `pipe.vae.enable_slicing()`
|
||||||
|
|
||||||
|
## CogVideoXPipeline
|
||||||
|
|
||||||
|
[[autodoc]] CogVideoXPipeline
|
||||||
|
- all
|
||||||
|
- __call__
|
||||||
|
|
||||||
|
## CogVideoXPipelineOutput
|
||||||
|
|
||||||
|
[[autodoc]] pipelines.cogvideo.pipeline_cogvideox.CogVideoXPipelineOutput
|
||||||
@@ -0,0 +1,165 @@
|
|||||||
|
<!--Copyright 2024 The HuggingFace Team. All rights reserved.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||||
|
the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||||
|
an "AS IS" BASIS, 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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
# Flux
|
||||||
|
|
||||||
|
Flux is a series of text-to-image generation models based on diffusion transformers. To know more about Flux, check out the original [blog post](https://blackforestlabs.ai/announcing-black-forest-labs/) by the creators of Flux, Black Forest Labs.
|
||||||
|
|
||||||
|
Original model checkpoints for Flux can be found [here](https://huggingface.co/black-forest-labs). Original inference code can be found [here](https://github.com/black-forest-labs/flux).
|
||||||
|
|
||||||
|
<Tip>
|
||||||
|
|
||||||
|
Flux can be quite expensive to run on consumer hardware devices. However, you can perform a suite of optimizations to run it faster and in a more memory-friendly manner. Check out [this section](https://huggingface.co/blog/sd3#memory-optimizations-for-sd3) for more details. Additionally, Flux can benefit from quantization for memory efficiency with a trade-off in inference latency. Refer to [this blog post](https://huggingface.co/blog/quanto-diffusers) to learn more. For an exhaustive list of resources, check out [this gist](https://gist.github.com/sayakpaul/b664605caf0aa3bf8585ab109dd5ac9c).
|
||||||
|
|
||||||
|
</Tip>
|
||||||
|
|
||||||
|
Flux comes in two variants:
|
||||||
|
|
||||||
|
* Timestep-distilled (`black-forest-labs/FLUX.1-schnell`)
|
||||||
|
* Guidance-distilled (`black-forest-labs/FLUX.1-dev`)
|
||||||
|
|
||||||
|
Both checkpoints have slightly difference usage which we detail below.
|
||||||
|
|
||||||
|
### Timestep-distilled
|
||||||
|
|
||||||
|
* `max_sequence_length` cannot be more than 256.
|
||||||
|
* `guidance_scale` needs to be 0.
|
||||||
|
* As this is a timestep-distilled model, it benefits from fewer sampling steps.
|
||||||
|
|
||||||
|
```python
|
||||||
|
import torch
|
||||||
|
from diffusers import FluxPipeline
|
||||||
|
|
||||||
|
pipe = FluxPipeline.from_pretrained("black-forest-labs/FLUX.1-schnell", torch_dtype=torch.bfloat16)
|
||||||
|
pipe.enable_model_cpu_offload()
|
||||||
|
|
||||||
|
prompt = "A cat holding a sign that says hello world"
|
||||||
|
out = pipe(
|
||||||
|
prompt=prompt,
|
||||||
|
guidance_scale=0.,
|
||||||
|
height=768,
|
||||||
|
width=1360,
|
||||||
|
num_inference_steps=4,
|
||||||
|
max_sequence_length=256,
|
||||||
|
).images[0]
|
||||||
|
out.save("image.png")
|
||||||
|
```
|
||||||
|
|
||||||
|
### Guidance-distilled
|
||||||
|
|
||||||
|
* The guidance-distilled variant takes about 50 sampling steps for good-quality generation.
|
||||||
|
* It doesn't have any limitations around the `max_sequence_length`.
|
||||||
|
|
||||||
|
```python
|
||||||
|
import torch
|
||||||
|
from diffusers import FluxPipeline
|
||||||
|
|
||||||
|
pipe = FluxPipeline.from_pretrained("black-forest-labs/FLUX.1-dev", torch_dtype=torch.bfloat16)
|
||||||
|
pipe.enable_model_cpu_offload()
|
||||||
|
|
||||||
|
prompt = "a tiny astronaut hatching from an egg on the moon"
|
||||||
|
out = pipe(
|
||||||
|
prompt=prompt,
|
||||||
|
guidance_scale=3.5,
|
||||||
|
height=768,
|
||||||
|
width=1360,
|
||||||
|
num_inference_steps=50,
|
||||||
|
).images[0]
|
||||||
|
out.save("image.png")
|
||||||
|
```
|
||||||
|
|
||||||
|
## Running FP16 inference
|
||||||
|
Flux can generate high-quality images with FP16 (i.e. to accelerate inference on Turing/Volta GPUs) but produces different outputs compared to FP32/BF16. The issue is that some activations in the text encoders have to be clipped when running in FP16, which affects the overall image. Forcing text encoders to run with FP32 inference thus removes this output difference. See [here](https://github.com/huggingface/diffusers/pull/9097#issuecomment-2272292516) for details.
|
||||||
|
|
||||||
|
FP16 inference code:
|
||||||
|
```python
|
||||||
|
import torch
|
||||||
|
from diffusers import FluxPipeline
|
||||||
|
|
||||||
|
pipe = FluxPipeline.from_pretrained("black-forest-labs/FLUX.1-schnell", torch_dtype=torch.bfloat16) # can replace schnell with dev
|
||||||
|
# to run on low vram GPUs (i.e. between 4 and 32 GB VRAM)
|
||||||
|
pipe.enable_sequential_cpu_offload()
|
||||||
|
pipe.vae.enable_slicing()
|
||||||
|
pipe.vae.enable_tiling()
|
||||||
|
|
||||||
|
pipe.to(torch.float16) # casting here instead of in the pipeline constructor because doing so in the constructor loads all models into CPU memory at once
|
||||||
|
|
||||||
|
prompt = "A cat holding a sign that says hello world"
|
||||||
|
out = pipe(
|
||||||
|
prompt=prompt,
|
||||||
|
guidance_scale=0.,
|
||||||
|
height=768,
|
||||||
|
width=1360,
|
||||||
|
num_inference_steps=4,
|
||||||
|
max_sequence_length=256,
|
||||||
|
).images[0]
|
||||||
|
out.save("image.png")
|
||||||
|
```
|
||||||
|
|
||||||
|
## Single File Loading for the `FluxTransformer2DModel`
|
||||||
|
|
||||||
|
The `FluxTransformer2DModel` supports loading checkpoints in the original format shipped by Black Forest Labs. This is also useful when trying to load finetunes or quantized versions of the models that have been published by the community.
|
||||||
|
|
||||||
|
<Tip>
|
||||||
|
`FP8` inference can be brittle depending on the GPU type, CUDA version, and `torch` version that you are using. It is recommended that you use the `optimum-quanto` library in order to run FP8 inference on your machine.
|
||||||
|
</Tip>
|
||||||
|
|
||||||
|
The following example demonstrates how to run Flux with less than 16GB of VRAM.
|
||||||
|
|
||||||
|
First install `optimum-quanto`
|
||||||
|
|
||||||
|
```shell
|
||||||
|
pip install optimum-quanto
|
||||||
|
```
|
||||||
|
|
||||||
|
Then run the following example
|
||||||
|
|
||||||
|
```python
|
||||||
|
import torch
|
||||||
|
from diffusers import FluxTransformer2DModel, FluxPipeline
|
||||||
|
from transformers import T5EncoderModel, CLIPTextModel
|
||||||
|
from optimum.quanto import freeze, qfloat8, quantize
|
||||||
|
|
||||||
|
bfl_repo = "black-forest-labs/FLUX.1-dev"
|
||||||
|
dtype = torch.bfloat16
|
||||||
|
|
||||||
|
transformer = FluxTransformer2DModel.from_single_file("https://huggingface.co/Kijai/flux-fp8/blob/main/flux1-dev-fp8.safetensors", torch_dtype=dtype)
|
||||||
|
quantize(transformer, weights=qfloat8)
|
||||||
|
freeze(transformer)
|
||||||
|
|
||||||
|
text_encoder_2 = T5EncoderModel.from_pretrained(bfl_repo, subfolder="text_encoder_2", torch_dtype=dtype)
|
||||||
|
quantize(text_encoder_2, weights=qfloat8)
|
||||||
|
freeze(text_encoder_2)
|
||||||
|
|
||||||
|
pipe = FluxPipeline.from_pretrained(bfl_repo, transformer=None, text_encoder_2=None, torch_dtype=dtype)
|
||||||
|
pipe.transformer = transformer
|
||||||
|
pipe.text_encoder_2 = text_encoder_2
|
||||||
|
|
||||||
|
pipe.enable_model_cpu_offload()
|
||||||
|
|
||||||
|
prompt = "A cat holding a sign that says hello world"
|
||||||
|
image = pipe(
|
||||||
|
prompt,
|
||||||
|
guidance_scale=3.5,
|
||||||
|
output_type="pil",
|
||||||
|
num_inference_steps=20,
|
||||||
|
generator=torch.Generator("cpu").manual_seed(0)
|
||||||
|
).images[0]
|
||||||
|
|
||||||
|
image.save("flux-fp8-dev.png")
|
||||||
|
```
|
||||||
|
|
||||||
|
## FluxPipeline
|
||||||
|
|
||||||
|
[[autodoc]] FluxPipeline
|
||||||
|
- all
|
||||||
|
- __call__
|
||||||
@@ -20,6 +20,34 @@ The abstract from the paper is:
|
|||||||
|
|
||||||
*Recent studies have demonstrated that diffusion models are capable of generating high-quality samples, but their quality heavily depends on sampling guidance techniques, such as classifier guidance (CG) and classifier-free guidance (CFG). These techniques are often not applicable in unconditional generation or in various downstream tasks such as image restoration. In this paper, we propose a novel sampling guidance, called Perturbed-Attention Guidance (PAG), which improves diffusion sample quality across both unconditional and conditional settings, achieving this without requiring additional training or the integration of external modules. PAG is designed to progressively enhance the structure of samples throughout the denoising process. It involves generating intermediate samples with degraded structure by substituting selected self-attention maps in diffusion U-Net with an identity matrix, by considering the self-attention mechanisms' ability to capture structural information, and guiding the denoising process away from these degraded samples. In both ADM and Stable Diffusion, PAG surprisingly improves sample quality in conditional and even unconditional scenarios. Moreover, PAG significantly improves the baseline performance in various downstream tasks where existing guidances such as CG or CFG cannot be fully utilized, including ControlNet with empty prompts and image restoration such as inpainting and deblurring.*
|
*Recent studies have demonstrated that diffusion models are capable of generating high-quality samples, but their quality heavily depends on sampling guidance techniques, such as classifier guidance (CG) and classifier-free guidance (CFG). These techniques are often not applicable in unconditional generation or in various downstream tasks such as image restoration. In this paper, we propose a novel sampling guidance, called Perturbed-Attention Guidance (PAG), which improves diffusion sample quality across both unconditional and conditional settings, achieving this without requiring additional training or the integration of external modules. PAG is designed to progressively enhance the structure of samples throughout the denoising process. It involves generating intermediate samples with degraded structure by substituting selected self-attention maps in diffusion U-Net with an identity matrix, by considering the self-attention mechanisms' ability to capture structural information, and guiding the denoising process away from these degraded samples. In both ADM and Stable Diffusion, PAG surprisingly improves sample quality in conditional and even unconditional scenarios. Moreover, PAG significantly improves the baseline performance in various downstream tasks where existing guidances such as CG or CFG cannot be fully utilized, including ControlNet with empty prompts and image restoration such as inpainting and deblurring.*
|
||||||
|
|
||||||
|
PAG can be used by specifying the `pag_applied_layers` as a parameter when instantiating a PAG pipeline. It can be a single string or a list of strings. Each string can be a unique layer identifier or a regular expression to identify one or more layers.
|
||||||
|
|
||||||
|
- Full identifier as a normal string: `down_blocks.2.attentions.0.transformer_blocks.0.attn1.processor`
|
||||||
|
- Full identifier as a RegEx: `down_blocks.2.(attentions|motion_modules).0.transformer_blocks.0.attn1.processor`
|
||||||
|
- Partial identifier as a RegEx: `down_blocks.2`, or `attn1`
|
||||||
|
- List of identifiers (can be combo of strings and ReGex): `["blocks.1", "blocks.(14|20)", r"down_blocks\.(2,3)"]`
|
||||||
|
|
||||||
|
<Tip warning={true}>
|
||||||
|
|
||||||
|
Since RegEx is supported as a way for matching layer identifiers, it is crucial to use it correctly otherwise there might be unexpected behaviour. The recommended way to use PAG is by specifying layers as `blocks.{layer_index}` and `blocks.({layer_index_1|layer_index_2|...})`. Using it in any other way, while doable, may bypass our basic validation checks and give you unexpected results.
|
||||||
|
|
||||||
|
</Tip>
|
||||||
|
|
||||||
|
## AnimateDiffPAGPipeline
|
||||||
|
[[autodoc]] AnimateDiffPAGPipeline
|
||||||
|
- all
|
||||||
|
- __call__
|
||||||
|
|
||||||
|
## HunyuanDiTPAGPipeline
|
||||||
|
[[autodoc]] HunyuanDiTPAGPipeline
|
||||||
|
- all
|
||||||
|
- __call__
|
||||||
|
|
||||||
|
## KolorsPAGPipeline
|
||||||
|
[[autodoc]] KolorsPAGPipeline
|
||||||
|
- all
|
||||||
|
- __call__
|
||||||
|
|
||||||
## StableDiffusionPAGPipeline
|
## StableDiffusionPAGPipeline
|
||||||
[[autodoc]] StableDiffusionPAGPipeline
|
[[autodoc]] StableDiffusionPAGPipeline
|
||||||
- all
|
- all
|
||||||
@@ -49,3 +77,15 @@ The abstract from the paper is:
|
|||||||
[[autodoc]] StableDiffusionXLControlNetPAGPipeline
|
[[autodoc]] StableDiffusionXLControlNetPAGPipeline
|
||||||
- all
|
- all
|
||||||
- __call__
|
- __call__
|
||||||
|
|
||||||
|
|
||||||
|
## StableDiffusion3PAGPipeline
|
||||||
|
[[autodoc]] StableDiffusion3PAGPipeline
|
||||||
|
- all
|
||||||
|
- __call__
|
||||||
|
|
||||||
|
|
||||||
|
## PixArtSigmaPAGPipeline
|
||||||
|
[[autodoc]] PixArtSigmaPAGPipeline
|
||||||
|
- all
|
||||||
|
- __call__
|
||||||
|
|||||||
@@ -0,0 +1,78 @@
|
|||||||
|
<!--Copyright 2024 The HuggingFace Team. All rights reserved.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||||
|
the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||||
|
an "AS IS" BASIS, 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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
# Community Projects
|
||||||
|
|
||||||
|
Welcome to Community Projects. This space is dedicated to showcasing the incredible work and innovative applications created by our vibrant community using the `diffusers` library.
|
||||||
|
|
||||||
|
This section aims to:
|
||||||
|
|
||||||
|
- Highlight diverse and inspiring projects built with `diffusers`
|
||||||
|
- Foster knowledge sharing within our community
|
||||||
|
- Provide real-world examples of how `diffusers` can be leveraged
|
||||||
|
|
||||||
|
Happy exploring, and thank you for being part of the Diffusers community!
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<th>Project Name</th>
|
||||||
|
<th>Description</th>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-top: 2px solid black">
|
||||||
|
<td><a href="https://github.com/carson-katri/dream-textures"> dream-textures </a></td>
|
||||||
|
<td>Stable Diffusion built-in to Blender</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-top: 2px solid black">
|
||||||
|
<td><a href="https://github.com/megvii-research/HiDiffusion"> HiDiffusion </a></td>
|
||||||
|
<td>Increases the resolution and speed of your diffusion model by only adding a single line of code</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-top: 2px solid black">
|
||||||
|
<td><a href="https://github.com/lllyasviel/IC-Light"> IC-Light </a></td>
|
||||||
|
<td>IC-Light is a project to manipulate the illumination of images</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-top: 2px solid black">
|
||||||
|
<td><a href="https://github.com/InstantID/InstantID"> InstantID </a></td>
|
||||||
|
<td>InstantID : Zero-shot Identity-Preserving Generation in Seconds</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-top: 2px solid black">
|
||||||
|
<td><a href="https://github.com/Sanster/IOPaint"> IOPaint </a></td>
|
||||||
|
<td>Image inpainting tool powered by SOTA AI Model. Remove any unwanted object, defect, people from your pictures or erase and replace(powered by stable diffusion) any thing on your pictures.</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-top: 2px solid black">
|
||||||
|
<td><a href="https://github.com/bmaltais/kohya_ss"> Kohya </a></td>
|
||||||
|
<td>Gradio GUI for Kohya's Stable Diffusion trainers</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-top: 2px solid black">
|
||||||
|
<td><a href="https://github.com/magic-research/magic-animate"> MagicAnimate </a></td>
|
||||||
|
<td>MagicAnimate: Temporally Consistent Human Image Animation using Diffusion Model</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-top: 2px solid black">
|
||||||
|
<td><a href="https://github.com/levihsu/OOTDiffusion"> OOTDiffusion </a></td>
|
||||||
|
<td>Outfitting Fusion based Latent Diffusion for Controllable Virtual Try-on</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-top: 2px solid black">
|
||||||
|
<td><a href="https://github.com/vladmandic/automatic"> SD.Next </a></td>
|
||||||
|
<td>SD.Next: Advanced Implementation of Stable Diffusion and other Diffusion-based generative image models</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-top: 2px solid black">
|
||||||
|
<td><a href="https://github.com/ashawkey/stable-dreamfusion"> stable-dreamfusion </a></td>
|
||||||
|
<td>Text-to-3D & Image-to-3D & Mesh Exportation with NeRF + Diffusion</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-top: 2px solid black">
|
||||||
|
<td><a href="https://github.com/HVision-NKU/StoryDiffusion"> StoryDiffusion </a></td>
|
||||||
|
<td>StoryDiffusion can create a magic story by generating consistent images and videos.</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-top: 2px solid black">
|
||||||
|
<td><a href="https://github.com/cumulo-autumn/StreamDiffusion"> StreamDiffusion </a></td>
|
||||||
|
<td>A Pipeline-Level Solution for Real-Time Interactive Generation</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
@@ -14,7 +14,7 @@ specific language governing permissions and limitations under the License.
|
|||||||
|
|
||||||
[InstructPix2Pix](https://hf.co/papers/2211.09800) is a Stable Diffusion model trained to edit images from human-provided instructions. For example, your prompt can be "turn the clouds rainy" and the model will edit the input image accordingly. This model is conditioned on the text prompt (or editing instruction) and the input image.
|
[InstructPix2Pix](https://hf.co/papers/2211.09800) is a Stable Diffusion model trained to edit images from human-provided instructions. For example, your prompt can be "turn the clouds rainy" and the model will edit the input image accordingly. This model is conditioned on the text prompt (or editing instruction) and the input image.
|
||||||
|
|
||||||
This guide will explore the [train_instruct_pix2pix.py](https://github.com/huggingface/diffusers/blob/main/examples/instruct_pix2pix/train_instruct_pix2pix.py) training script to help you become familiar with it, and how you can adapt it for your own use-case.
|
This guide will explore the [train_instruct_pix2pix.py](https://github.com/huggingface/diffusers/blob/main/examples/instruct_pix2pix/train_instruct_pix2pix.py) training script to help you become familiar with it, and how you can adapt it for your own use case.
|
||||||
|
|
||||||
Before running the script, make sure you install the library from source:
|
Before running the script, make sure you install the library from source:
|
||||||
|
|
||||||
@@ -117,7 +117,7 @@ optimizer = optimizer_cls(
|
|||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
Next, the edited images and and edit instructions are [preprocessed](https://github.com/huggingface/diffusers/blob/64603389da01082055a901f2883c4810d1144edb/examples/instruct_pix2pix/train_instruct_pix2pix.py#L624) and [tokenized](https://github.com/huggingface/diffusers/blob/64603389da01082055a901f2883c4810d1144edb/examples/instruct_pix2pix/train_instruct_pix2pix.py#L610C24-L610C24). It is important the same image transformations are applied to the original and edited images.
|
Next, the edited images and edit instructions are [preprocessed](https://github.com/huggingface/diffusers/blob/64603389da01082055a901f2883c4810d1144edb/examples/instruct_pix2pix/train_instruct_pix2pix.py#L624) and [tokenized](https://github.com/huggingface/diffusers/blob/64603389da01082055a901f2883c4810d1144edb/examples/instruct_pix2pix/train_instruct_pix2pix.py#L610C24-L610C24). It is important the same image transformations are applied to the original and edited images.
|
||||||
|
|
||||||
```py
|
```py
|
||||||
def preprocess_train(examples):
|
def preprocess_train(examples):
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ pipe_id = "stabilityai/stable-diffusion-xl-base-1.0"
|
|||||||
pipe = DiffusionPipeline.from_pretrained(pipe_id, torch_dtype=torch.float16).to("cuda")
|
pipe = DiffusionPipeline.from_pretrained(pipe_id, torch_dtype=torch.float16).to("cuda")
|
||||||
```
|
```
|
||||||
|
|
||||||
Next, load a [CiroN2022/toy-face](https://huggingface.co/CiroN2022/toy-face) adapter with the [`~diffusers.loaders.StableDiffusionXLLoraLoaderMixin.load_lora_weights`] method. With the 🤗 PEFT integration, you can assign a specific `adapter_name` to the checkpoint, which let's you easily switch between different LoRA checkpoints. Let's call this adapter `"toy"`.
|
Next, load a [CiroN2022/toy-face](https://huggingface.co/CiroN2022/toy-face) adapter with the [`~diffusers.loaders.StableDiffusionXLLoraLoaderMixin.load_lora_weights`] method. With the 🤗 PEFT integration, you can assign a specific `adapter_name` to the checkpoint, which lets you easily switch between different LoRA checkpoints. Let's call this adapter `"toy"`.
|
||||||
|
|
||||||
```python
|
```python
|
||||||
pipe.load_lora_weights("CiroN2022/toy-face", weight_name="toy_face_sdxl.safetensors", adapter_name="toy")
|
pipe.load_lora_weights("CiroN2022/toy-face", weight_name="toy_face_sdxl.safetensors", adapter_name="toy")
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ specific language governing permissions and limitations under the License.
|
|||||||
|
|
||||||
# Pipeline callbacks
|
# Pipeline callbacks
|
||||||
|
|
||||||
The denoising loop of a pipeline can be modified with custom defined functions using the `callback_on_step_end` parameter. The callback function is executed at the end of each step, and modifies the pipeline attributes and variables for the next step. This is really useful for *dynamically* adjusting certain pipeline attributes or modifying tensor variables. This versatility allows for interesting use-cases such as changing the prompt embeddings at each timestep, assigning different weights to the prompt embeddings, and editing the guidance scale. With callbacks, you can implement new features without modifying the underlying code!
|
The denoising loop of a pipeline can be modified with custom defined functions using the `callback_on_step_end` parameter. The callback function is executed at the end of each step, and modifies the pipeline attributes and variables for the next step. This is really useful for *dynamically* adjusting certain pipeline attributes or modifying tensor variables. This versatility allows for interesting use cases such as changing the prompt embeddings at each timestep, assigning different weights to the prompt embeddings, and editing the guidance scale. With callbacks, you can implement new features without modifying the underlying code!
|
||||||
|
|
||||||
> [!TIP]
|
> [!TIP]
|
||||||
> 🤗 Diffusers currently only supports `callback_on_step_end`, but feel free to open a [feature request](https://github.com/huggingface/diffusers/issues/new/choose) if you have a cool use-case and require a callback function with a different execution point!
|
> 🤗 Diffusers currently only supports `callback_on_step_end`, but feel free to open a [feature request](https://github.com/huggingface/diffusers/issues/new/choose) if you have a cool use-case and require a callback function with a different execution point!
|
||||||
@@ -75,7 +75,7 @@ out.images[0].save("official_callback.png")
|
|||||||
<figcaption class="mt-2 text-center text-sm text-gray-500">without SDXLCFGCutoffCallback</figcaption>
|
<figcaption class="mt-2 text-center text-sm text-gray-500">without SDXLCFGCutoffCallback</figcaption>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<img class="rounded-xl" src="https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/with_cfg_callback.png" alt="generated image of a a sports car at the road with cfg callback" />
|
<img class="rounded-xl" src="https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/with_cfg_callback.png" alt="generated image of a sports car at the road with cfg callback" />
|
||||||
<figcaption class="mt-2 text-center text-sm text-gray-500">with SDXLCFGCutoffCallback</figcaption>
|
<figcaption class="mt-2 text-center text-sm text-gray-500">with SDXLCFGCutoffCallback</figcaption>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -256,7 +256,7 @@ make_image_grid([init_image, mask_image, output], rows=1, cols=3)
|
|||||||
|
|
||||||
## Guess mode
|
## Guess mode
|
||||||
|
|
||||||
[Guess mode](https://github.com/lllyasviel/ControlNet/discussions/188) does not require supplying a prompt to a ControlNet at all! This forces the ControlNet encoder to do it's best to "guess" the contents of the input control map (depth map, pose estimation, canny edge, etc.).
|
[Guess mode](https://github.com/lllyasviel/ControlNet/discussions/188) does not require supplying a prompt to a ControlNet at all! This forces the ControlNet encoder to do its best to "guess" the contents of the input control map (depth map, pose estimation, canny edge, etc.).
|
||||||
|
|
||||||
Guess mode adjusts the scale of the output residuals from a ControlNet by a fixed ratio depending on the block depth. The shallowest `DownBlock` corresponds to 0.1, and as the blocks get deeper, the scale increases exponentially such that the scale of the `MidBlock` output becomes 1.0.
|
Guess mode adjusts the scale of the output residuals from a ControlNet by a fixed ratio depending on the block depth. The shallowest `DownBlock` corresponds to 0.1, and as the blocks get deeper, the scale increases exponentially such that the scale of the `MidBlock` output becomes 1.0.
|
||||||
|
|
||||||
|
|||||||
@@ -289,9 +289,9 @@ scheduler = DPMSolverMultistepScheduler.from_pretrained(pipe_id, subfolder="sche
|
|||||||
3. Load an image processor:
|
3. Load an image processor:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from transformers import CLIPFeatureExtractor
|
from transformers import CLIPImageProcessor
|
||||||
|
|
||||||
feature_extractor = CLIPFeatureExtractor.from_pretrained(pipe_id, subfolder="feature_extractor")
|
feature_extractor = CLIPImageProcessor.from_pretrained(pipe_id, subfolder="feature_extractor")
|
||||||
```
|
```
|
||||||
|
|
||||||
<Tip warning={true}>
|
<Tip warning={true}>
|
||||||
|
|||||||
@@ -212,14 +212,14 @@ TCD-LoRA is very versatile, and it can be combined with other adapter types like
|
|||||||
import torch
|
import torch
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
from transformers import DPTFeatureExtractor, DPTForDepthEstimation
|
from transformers import DPTImageProcessor, DPTForDepthEstimation
|
||||||
from diffusers import ControlNetModel, StableDiffusionXLControlNetPipeline
|
from diffusers import ControlNetModel, StableDiffusionXLControlNetPipeline
|
||||||
from diffusers.utils import load_image, make_image_grid
|
from diffusers.utils import load_image, make_image_grid
|
||||||
from scheduling_tcd import TCDScheduler
|
from scheduling_tcd import TCDScheduler
|
||||||
|
|
||||||
device = "cuda"
|
device = "cuda"
|
||||||
depth_estimator = DPTForDepthEstimation.from_pretrained("Intel/dpt-hybrid-midas").to(device)
|
depth_estimator = DPTForDepthEstimation.from_pretrained("Intel/dpt-hybrid-midas").to(device)
|
||||||
feature_extractor = DPTFeatureExtractor.from_pretrained("Intel/dpt-hybrid-midas")
|
feature_extractor = DPTImageProcessor.from_pretrained("Intel/dpt-hybrid-midas")
|
||||||
|
|
||||||
def get_depth_map(image):
|
def get_depth_map(image):
|
||||||
image = feature_extractor(images=image, return_tensors="pt").pixel_values.to(device)
|
image = feature_extractor(images=image, return_tensors="pt").pixel_values.to(device)
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ This guide will show you how to use PAG for various tasks and use cases.
|
|||||||
You can apply PAG to the [`StableDiffusionXLPipeline`] for tasks such as text-to-image, image-to-image, and inpainting. To enable PAG for a specific task, load the pipeline using the [AutoPipeline](../api/pipelines/auto_pipeline) API with the `enable_pag=True` flag and the `pag_applied_layers` argument.
|
You can apply PAG to the [`StableDiffusionXLPipeline`] for tasks such as text-to-image, image-to-image, and inpainting. To enable PAG for a specific task, load the pipeline using the [AutoPipeline](../api/pipelines/auto_pipeline) API with the `enable_pag=True` flag and the `pag_applied_layers` argument.
|
||||||
|
|
||||||
> [!TIP]
|
> [!TIP]
|
||||||
> 🤗 Diffusers currently only supports using PAG with selected SDXL pipelines, but feel free to open a [feature request](https://github.com/huggingface/diffusers/issues/new/choose) if you want to add PAG support to a new pipeline!
|
> 🤗 Diffusers currently only supports using PAG with selected SDXL pipelines and [`PixArtSigmaPAGPipeline`]. But feel free to open a [feature request](https://github.com/huggingface/diffusers/issues/new/choose) if you want to add PAG support to a new pipeline!
|
||||||
|
|
||||||
<hfoptions id="tasks">
|
<hfoptions id="tasks">
|
||||||
<hfoption id="Text-to-image">
|
<hfoption id="Text-to-image">
|
||||||
|
|||||||
@@ -307,7 +307,7 @@ print(pipeline)
|
|||||||
|
|
||||||
위의 코드 출력 결과를 확인해보면, `pipeline`은 [`StableDiffusionPipeline`]의 인스턴스이며, 다음과 같이 총 7개의 컴포넌트로 구성된다는 것을 알 수 있습니다.
|
위의 코드 출력 결과를 확인해보면, `pipeline`은 [`StableDiffusionPipeline`]의 인스턴스이며, 다음과 같이 총 7개의 컴포넌트로 구성된다는 것을 알 수 있습니다.
|
||||||
|
|
||||||
- `"feature_extractor"`: [`~transformers.CLIPFeatureExtractor`]의 인스턴스
|
- `"feature_extractor"`: [`~transformers.CLIPImageProcessor`]의 인스턴스
|
||||||
- `"safety_checker"`: 유해한 컨텐츠를 스크리닝하기 위한 [컴포넌트](https://github.com/huggingface/diffusers/blob/e55687e1e15407f60f32242027b7bb8170e58266/src/diffusers/pipelines/stable_diffusion/safety_checker.py#L32)
|
- `"safety_checker"`: 유해한 컨텐츠를 스크리닝하기 위한 [컴포넌트](https://github.com/huggingface/diffusers/blob/e55687e1e15407f60f32242027b7bb8170e58266/src/diffusers/pipelines/stable_diffusion/safety_checker.py#L32)
|
||||||
- `"scheduler"`: [`PNDMScheduler`]의 인스턴스
|
- `"scheduler"`: [`PNDMScheduler`]의 인스턴스
|
||||||
- `"text_encoder"`: [`~transformers.CLIPTextModel`]의 인스턴스
|
- `"text_encoder"`: [`~transformers.CLIPTextModel`]의 인스턴스
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ import PIL
|
|||||||
from PIL import Image
|
from PIL import Image
|
||||||
|
|
||||||
from diffusers import StableDiffusionPipeline
|
from diffusers import StableDiffusionPipeline
|
||||||
from transformers import CLIPFeatureExtractor, CLIPTextModel, CLIPTokenizer
|
from transformers import CLIPImageProcessor, CLIPTextModel, CLIPTokenizer
|
||||||
|
|
||||||
|
|
||||||
def image_grid(imgs, rows, cols):
|
def image_grid(imgs, rows, cols):
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ from diffusers.utils.import_utils import is_xformers_available
|
|||||||
|
|
||||||
|
|
||||||
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
||||||
check_min_version("0.30.0.dev0")
|
check_min_version("0.30.0")
|
||||||
|
|
||||||
logger = get_logger(__name__)
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ if is_wandb_available():
|
|||||||
import wandb
|
import wandb
|
||||||
|
|
||||||
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
||||||
check_min_version("0.30.0.dev0")
|
check_min_version("0.30.0")
|
||||||
|
|
||||||
logger = get_logger(__name__)
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
|
|||||||
@@ -1435,9 +1435,9 @@ import requests
|
|||||||
import torch
|
import torch
|
||||||
from diffusers import DiffusionPipeline
|
from diffusers import DiffusionPipeline
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
from transformers import CLIPFeatureExtractor, CLIPModel
|
from transformers import CLIPImageProcessor, CLIPModel
|
||||||
|
|
||||||
feature_extractor = CLIPFeatureExtractor.from_pretrained(
|
feature_extractor = CLIPImageProcessor.from_pretrained(
|
||||||
"laion/CLIP-ViT-B-32-laion2B-s34B-b79K"
|
"laion/CLIP-ViT-B-32-laion2B-s34B-b79K"
|
||||||
)
|
)
|
||||||
clip_model = CLIPModel.from_pretrained(
|
clip_model = CLIPModel.from_pretrained(
|
||||||
@@ -1487,17 +1487,16 @@ NOTE: The ONNX conversions and TensorRT engine build may take up to 30 minutes.
|
|||||||
```python
|
```python
|
||||||
import torch
|
import torch
|
||||||
from diffusers import DDIMScheduler
|
from diffusers import DDIMScheduler
|
||||||
from diffusers.pipelines.stable_diffusion import StableDiffusionPipeline
|
from diffusers.pipelines import DiffusionPipeline
|
||||||
|
|
||||||
# Use the DDIMScheduler scheduler here instead
|
# Use the DDIMScheduler scheduler here instead
|
||||||
scheduler = DDIMScheduler.from_pretrained("stabilityai/stable-diffusion-2-1",
|
scheduler = DDIMScheduler.from_pretrained("stabilityai/stable-diffusion-2-1", subfolder="scheduler")
|
||||||
subfolder="scheduler")
|
|
||||||
|
|
||||||
pipe = StableDiffusionPipeline.from_pretrained("stabilityai/stable-diffusion-2-1",
|
pipe = DiffusionPipeline.from_pretrained("stabilityai/stable-diffusion-2-1",
|
||||||
custom_pipeline="stable_diffusion_tensorrt_txt2img",
|
custom_pipeline="stable_diffusion_tensorrt_txt2img",
|
||||||
variant='fp16',
|
variant='fp16',
|
||||||
torch_dtype=torch.float16,
|
torch_dtype=torch.float16,
|
||||||
scheduler=scheduler,)
|
scheduler=scheduler,)
|
||||||
|
|
||||||
# re-use cached folder to save ONNX models and TensorRT Engines
|
# re-use cached folder to save ONNX models and TensorRT Engines
|
||||||
pipe.set_cached_folder("stabilityai/stable-diffusion-2-1", variant='fp16',)
|
pipe.set_cached_folder("stabilityai/stable-diffusion-2-1", variant='fp16',)
|
||||||
@@ -2123,7 +2122,7 @@ import torch
|
|||||||
import open_clip
|
import open_clip
|
||||||
from open_clip import SimpleTokenizer
|
from open_clip import SimpleTokenizer
|
||||||
from diffusers import DiffusionPipeline
|
from diffusers import DiffusionPipeline
|
||||||
from transformers import CLIPFeatureExtractor, CLIPModel
|
from transformers import CLIPImageProcessor, CLIPModel
|
||||||
|
|
||||||
|
|
||||||
def download_image(url):
|
def download_image(url):
|
||||||
@@ -2131,7 +2130,7 @@ def download_image(url):
|
|||||||
return PIL.Image.open(BytesIO(response.content)).convert("RGB")
|
return PIL.Image.open(BytesIO(response.content)).convert("RGB")
|
||||||
|
|
||||||
# Loading additional models
|
# Loading additional models
|
||||||
feature_extractor = CLIPFeatureExtractor.from_pretrained(
|
feature_extractor = CLIPImageProcessor.from_pretrained(
|
||||||
"laion/CLIP-ViT-B-32-laion2B-s34B-b79K"
|
"laion/CLIP-ViT-B-32-laion2B-s34B-b79K"
|
||||||
)
|
)
|
||||||
clip_model = CLIPModel.from_pretrained(
|
clip_model = CLIPModel.from_pretrained(
|
||||||
@@ -2231,12 +2230,12 @@ from io import BytesIO
|
|||||||
from PIL import Image
|
from PIL import Image
|
||||||
import torch
|
import torch
|
||||||
from diffusers import PNDMScheduler
|
from diffusers import PNDMScheduler
|
||||||
from diffusers.pipelines.stable_diffusion import StableDiffusionInpaintPipeline
|
from diffusers.pipelines import DiffusionPipeline
|
||||||
|
|
||||||
# Use the PNDMScheduler scheduler here instead
|
# Use the PNDMScheduler scheduler here instead
|
||||||
scheduler = PNDMScheduler.from_pretrained("stabilityai/stable-diffusion-2-inpainting", subfolder="scheduler")
|
scheduler = PNDMScheduler.from_pretrained("stabilityai/stable-diffusion-2-inpainting", subfolder="scheduler")
|
||||||
|
|
||||||
pipe = StableDiffusionInpaintPipeline.from_pretrained("stabilityai/stable-diffusion-2-inpainting",
|
pipe = DiffusionPipeline.from_pretrained("stabilityai/stable-diffusion-2-inpainting",
|
||||||
custom_pipeline="stable_diffusion_tensorrt_inpaint",
|
custom_pipeline="stable_diffusion_tensorrt_inpaint",
|
||||||
variant='fp16',
|
variant='fp16',
|
||||||
torch_dtype=torch.float16,
|
torch_dtype=torch.float16,
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import PIL.Image
|
|||||||
import torch
|
import torch
|
||||||
from torch.nn import functional as F
|
from torch.nn import functional as F
|
||||||
from torchvision import transforms
|
from torchvision import transforms
|
||||||
from transformers import CLIPFeatureExtractor, CLIPModel, CLIPTextModel, CLIPTokenizer
|
from transformers import CLIPImageProcessor, CLIPModel, CLIPTextModel, CLIPTokenizer
|
||||||
|
|
||||||
from diffusers import (
|
from diffusers import (
|
||||||
AutoencoderKL,
|
AutoencoderKL,
|
||||||
@@ -86,7 +86,7 @@ class CLIPGuidedImagesMixingStableDiffusion(DiffusionPipeline, StableDiffusionMi
|
|||||||
tokenizer: CLIPTokenizer,
|
tokenizer: CLIPTokenizer,
|
||||||
unet: UNet2DConditionModel,
|
unet: UNet2DConditionModel,
|
||||||
scheduler: Union[PNDMScheduler, LMSDiscreteScheduler, DDIMScheduler, DPMSolverMultistepScheduler],
|
scheduler: Union[PNDMScheduler, LMSDiscreteScheduler, DDIMScheduler, DPMSolverMultistepScheduler],
|
||||||
feature_extractor: CLIPFeatureExtractor,
|
feature_extractor: CLIPImageProcessor,
|
||||||
coca_model=None,
|
coca_model=None,
|
||||||
coca_tokenizer=None,
|
coca_tokenizer=None,
|
||||||
coca_transform=None,
|
coca_transform=None,
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import torch
|
|||||||
from torch import nn
|
from torch import nn
|
||||||
from torch.nn import functional as F
|
from torch.nn import functional as F
|
||||||
from torchvision import transforms
|
from torchvision import transforms
|
||||||
from transformers import CLIPFeatureExtractor, CLIPModel, CLIPTextModel, CLIPTokenizer
|
from transformers import CLIPImageProcessor, CLIPModel, CLIPTextModel, CLIPTokenizer
|
||||||
|
|
||||||
from diffusers import (
|
from diffusers import (
|
||||||
AutoencoderKL,
|
AutoencoderKL,
|
||||||
@@ -32,9 +32,9 @@ EXAMPLE_DOC_STRING = """
|
|||||||
import torch
|
import torch
|
||||||
from diffusers import DiffusionPipeline
|
from diffusers import DiffusionPipeline
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
from transformers import CLIPFeatureExtractor, CLIPModel
|
from transformers import CLIPImageProcessor, CLIPModel
|
||||||
|
|
||||||
feature_extractor = CLIPFeatureExtractor.from_pretrained(
|
feature_extractor = CLIPImageProcessor.from_pretrained(
|
||||||
"laion/CLIP-ViT-B-32-laion2B-s34B-b79K"
|
"laion/CLIP-ViT-B-32-laion2B-s34B-b79K"
|
||||||
)
|
)
|
||||||
clip_model = CLIPModel.from_pretrained(
|
clip_model = CLIPModel.from_pretrained(
|
||||||
@@ -139,7 +139,7 @@ class CLIPGuidedStableDiffusion(DiffusionPipeline, StableDiffusionMixin):
|
|||||||
tokenizer: CLIPTokenizer,
|
tokenizer: CLIPTokenizer,
|
||||||
unet: UNet2DConditionModel,
|
unet: UNet2DConditionModel,
|
||||||
scheduler: Union[PNDMScheduler, LMSDiscreteScheduler, DDIMScheduler, DPMSolverMultistepScheduler],
|
scheduler: Union[PNDMScheduler, LMSDiscreteScheduler, DDIMScheduler, DPMSolverMultistepScheduler],
|
||||||
feature_extractor: CLIPFeatureExtractor,
|
feature_extractor: CLIPImageProcessor,
|
||||||
):
|
):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.register_modules(
|
self.register_modules(
|
||||||
|
|||||||
@@ -2436,7 +2436,7 @@ class FrescoV2VPipeline(StableDiffusionControlNetImg2ImgPipeline):
|
|||||||
)
|
)
|
||||||
|
|
||||||
if guess_mode and self.do_classifier_free_guidance:
|
if guess_mode and self.do_classifier_free_guidance:
|
||||||
# Infered ControlNet only for the conditional batch.
|
# Inferred ControlNet only for the conditional batch.
|
||||||
# To apply the output of ControlNet to both the unconditional and conditional batches,
|
# To apply the output of ControlNet to both the unconditional and conditional batches,
|
||||||
# add 0 to the unconditional batch to keep it unchanged.
|
# add 0 to the unconditional batch to keep it unchanged.
|
||||||
down_block_res_samples = [torch.cat([torch.zeros_like(d), d]) for d in down_block_res_samples]
|
down_block_res_samples = [torch.cat([torch.zeros_like(d), d]) for d in down_block_res_samples]
|
||||||
|
|||||||
@@ -43,8 +43,7 @@ from diffusers.utils import BaseOutput, check_min_version
|
|||||||
|
|
||||||
|
|
||||||
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
||||||
check_min_version("0.30.0.dev0")
|
check_min_version("0.30.0")
|
||||||
|
|
||||||
|
|
||||||
class MarigoldDepthOutput(BaseOutput):
|
class MarigoldDepthOutput(BaseOutput):
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import torch
|
|||||||
from numpy import exp, pi, sqrt
|
from numpy import exp, pi, sqrt
|
||||||
from torchvision.transforms.functional import resize
|
from torchvision.transforms.functional import resize
|
||||||
from tqdm.auto import tqdm
|
from tqdm.auto import tqdm
|
||||||
from transformers import CLIPFeatureExtractor, CLIPTextModel, CLIPTokenizer
|
from transformers import CLIPImageProcessor, CLIPTextModel, CLIPTokenizer
|
||||||
|
|
||||||
from diffusers.models import AutoencoderKL, UNet2DConditionModel
|
from diffusers.models import AutoencoderKL, UNet2DConditionModel
|
||||||
from diffusers.pipelines.pipeline_utils import DiffusionPipeline, StableDiffusionMixin
|
from diffusers.pipelines.pipeline_utils import DiffusionPipeline, StableDiffusionMixin
|
||||||
@@ -275,7 +275,7 @@ class StableDiffusionCanvasPipeline(DiffusionPipeline, StableDiffusionMixin):
|
|||||||
unet: UNet2DConditionModel,
|
unet: UNet2DConditionModel,
|
||||||
scheduler: Union[DDIMScheduler, LMSDiscreteScheduler, PNDMScheduler],
|
scheduler: Union[DDIMScheduler, LMSDiscreteScheduler, PNDMScheduler],
|
||||||
safety_checker: StableDiffusionSafetyChecker,
|
safety_checker: StableDiffusionSafetyChecker,
|
||||||
feature_extractor: CLIPFeatureExtractor,
|
feature_extractor: CLIPImageProcessor,
|
||||||
):
|
):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.register_modules(
|
self.register_modules(
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ from diffusers.utils import logging
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
from ligo.segments import segment
|
from ligo.segments import segment
|
||||||
from transformers import CLIPFeatureExtractor, CLIPTextModel, CLIPTokenizer
|
from transformers import CLIPImageProcessor, CLIPTextModel, CLIPTokenizer
|
||||||
except ImportError:
|
except ImportError:
|
||||||
raise ImportError("Please install transformers and ligo-segments to use the mixture pipeline")
|
raise ImportError("Please install transformers and ligo-segments to use the mixture pipeline")
|
||||||
|
|
||||||
@@ -144,7 +144,7 @@ class StableDiffusionTilingPipeline(DiffusionPipeline, StableDiffusionExtrasMixi
|
|||||||
unet: UNet2DConditionModel,
|
unet: UNet2DConditionModel,
|
||||||
scheduler: Union[DDIMScheduler, PNDMScheduler],
|
scheduler: Union[DDIMScheduler, PNDMScheduler],
|
||||||
safety_checker: StableDiffusionSafetyChecker,
|
safety_checker: StableDiffusionSafetyChecker,
|
||||||
feature_extractor: CLIPFeatureExtractor,
|
feature_extractor: CLIPImageProcessor,
|
||||||
):
|
):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.register_modules(
|
self.register_modules(
|
||||||
|
|||||||
@@ -189,7 +189,7 @@ class StableDiffusionXLControlNetAdapterPipeline(
|
|||||||
safety_checker ([`StableDiffusionSafetyChecker`]):
|
safety_checker ([`StableDiffusionSafetyChecker`]):
|
||||||
Classification module that estimates whether generated images could be considered offensive or harmful.
|
Classification module that estimates whether generated images could be considered offensive or harmful.
|
||||||
Please, refer to the [model card](https://huggingface.co/runwayml/stable-diffusion-v1-5) for details.
|
Please, refer to the [model card](https://huggingface.co/runwayml/stable-diffusion-v1-5) for details.
|
||||||
feature_extractor ([`CLIPFeatureExtractor`]):
|
feature_extractor ([`CLIPImageProcessor`]):
|
||||||
Model that extracts features from generated images to be used as inputs for the `safety_checker`.
|
Model that extracts features from generated images to be used as inputs for the `safety_checker`.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|||||||
@@ -332,7 +332,7 @@ class StableDiffusionXLControlNetAdapterInpaintPipeline(
|
|||||||
safety_checker ([`StableDiffusionSafetyChecker`]):
|
safety_checker ([`StableDiffusionSafetyChecker`]):
|
||||||
Classification module that estimates whether generated images could be considered offensive or harmful.
|
Classification module that estimates whether generated images could be considered offensive or harmful.
|
||||||
Please, refer to the [model card](https://huggingface.co/runwayml/stable-diffusion-v1-5) for details.
|
Please, refer to the [model card](https://huggingface.co/runwayml/stable-diffusion-v1-5) for details.
|
||||||
feature_extractor ([`CLIPFeatureExtractor`]):
|
feature_extractor ([`CLIPImageProcessor`]):
|
||||||
Model that extracts features from generated images to be used as inputs for the `safety_checker`.
|
Model that extracts features from generated images to be used as inputs for the `safety_checker`.
|
||||||
requires_aesthetics_score (`bool`, *optional*, defaults to `"False"`):
|
requires_aesthetics_score (`bool`, *optional*, defaults to `"False"`):
|
||||||
Whether the `unet` requires a aesthetic_score condition to be passed during inference. Also see the config
|
Whether the `unet` requires a aesthetic_score condition to be passed during inference. Also see the config
|
||||||
|
|||||||
@@ -1002,7 +1002,7 @@ class StableDiffusionXLInstantIDImg2ImgPipeline(StableDiffusionXLControlNetImg2I
|
|||||||
)
|
)
|
||||||
|
|
||||||
if guess_mode and self.do_classifier_free_guidance:
|
if guess_mode and self.do_classifier_free_guidance:
|
||||||
# Infered ControlNet only for the conditional batch.
|
# Inferred ControlNet only for the conditional batch.
|
||||||
# To apply the output of ControlNet to both the unconditional and conditional batches,
|
# To apply the output of ControlNet to both the unconditional and conditional batches,
|
||||||
# add 0 to the unconditional batch to keep it unchanged.
|
# add 0 to the unconditional batch to keep it unchanged.
|
||||||
down_block_res_samples = [torch.cat([torch.zeros_like(d), d]) for d in down_block_res_samples]
|
down_block_res_samples = [torch.cat([torch.zeros_like(d), d]) for d in down_block_res_samples]
|
||||||
|
|||||||
@@ -991,7 +991,7 @@ class StableDiffusionXLInstantIDPipeline(StableDiffusionXLControlNetPipeline):
|
|||||||
)
|
)
|
||||||
|
|
||||||
if guess_mode and self.do_classifier_free_guidance:
|
if guess_mode and self.do_classifier_free_guidance:
|
||||||
# Infered ControlNet only for the conditional batch.
|
# Inferred ControlNet only for the conditional batch.
|
||||||
# To apply the output of ControlNet to both the unconditional and conditional batches,
|
# To apply the output of ControlNet to both the unconditional and conditional batches,
|
||||||
# add 0 to the unconditional batch to keep it unchanged.
|
# add 0 to the unconditional batch to keep it unchanged.
|
||||||
down_block_res_samples = [torch.cat([torch.zeros_like(d), d]) for d in down_block_res_samples]
|
down_block_res_samples = [torch.cat([torch.zeros_like(d), d]) for d in down_block_res_samples]
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import numpy as np
|
|||||||
import PIL.Image
|
import PIL.Image
|
||||||
import torch
|
import torch
|
||||||
from packaging import version
|
from packaging import version
|
||||||
from transformers import CLIPFeatureExtractor, CLIPVisionModelWithProjection
|
from transformers import CLIPImageProcessor, CLIPVisionModelWithProjection
|
||||||
|
|
||||||
# from ...configuration_utils import FrozenDict
|
# from ...configuration_utils import FrozenDict
|
||||||
# from ...models import AutoencoderKL, UNet2DConditionModel
|
# from ...models import AutoencoderKL, UNet2DConditionModel
|
||||||
@@ -87,7 +87,7 @@ class Zero1to3StableDiffusionPipeline(DiffusionPipeline, StableDiffusionMixin):
|
|||||||
safety_checker ([`StableDiffusionSafetyChecker`]):
|
safety_checker ([`StableDiffusionSafetyChecker`]):
|
||||||
Classification module that estimates whether generated images could be considered offensive or harmful.
|
Classification module that estimates whether generated images could be considered offensive or harmful.
|
||||||
Please, refer to the [model card](https://huggingface.co/runwayml/stable-diffusion-v1-5) for details.
|
Please, refer to the [model card](https://huggingface.co/runwayml/stable-diffusion-v1-5) for details.
|
||||||
feature_extractor ([`CLIPFeatureExtractor`]):
|
feature_extractor ([`CLIPImageProcessor`]):
|
||||||
Model that extracts features from generated images to be used as inputs for the `safety_checker`.
|
Model that extracts features from generated images to be used as inputs for the `safety_checker`.
|
||||||
cc_projection ([`CCProjection`]):
|
cc_projection ([`CCProjection`]):
|
||||||
Projection layer to project the concated CLIP features and pose embeddings to the original CLIP feature size.
|
Projection layer to project the concated CLIP features and pose embeddings to the original CLIP feature size.
|
||||||
@@ -102,7 +102,7 @@ class Zero1to3StableDiffusionPipeline(DiffusionPipeline, StableDiffusionMixin):
|
|||||||
unet: UNet2DConditionModel,
|
unet: UNet2DConditionModel,
|
||||||
scheduler: KarrasDiffusionSchedulers,
|
scheduler: KarrasDiffusionSchedulers,
|
||||||
safety_checker: StableDiffusionSafetyChecker,
|
safety_checker: StableDiffusionSafetyChecker,
|
||||||
feature_extractor: CLIPFeatureExtractor,
|
feature_extractor: CLIPImageProcessor,
|
||||||
cc_projection: CCProjection,
|
cc_projection: CCProjection,
|
||||||
requires_safety_checker: bool = True,
|
requires_safety_checker: bool = True,
|
||||||
):
|
):
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ from typing import Dict, Optional
|
|||||||
|
|
||||||
import torch
|
import torch
|
||||||
import torchvision.transforms.functional as FF
|
import torchvision.transforms.functional as FF
|
||||||
from transformers import CLIPFeatureExtractor, CLIPTextModel, CLIPTokenizer
|
from transformers import CLIPImageProcessor, CLIPTextModel, CLIPTokenizer
|
||||||
|
|
||||||
from diffusers import StableDiffusionPipeline
|
from diffusers import StableDiffusionPipeline
|
||||||
from diffusers.models import AutoencoderKL, UNet2DConditionModel
|
from diffusers.models import AutoencoderKL, UNet2DConditionModel
|
||||||
@@ -69,7 +69,7 @@ class RegionalPromptingStableDiffusionPipeline(StableDiffusionPipeline):
|
|||||||
unet: UNet2DConditionModel,
|
unet: UNet2DConditionModel,
|
||||||
scheduler: KarrasDiffusionSchedulers,
|
scheduler: KarrasDiffusionSchedulers,
|
||||||
safety_checker: StableDiffusionSafetyChecker,
|
safety_checker: StableDiffusionSafetyChecker,
|
||||||
feature_extractor: CLIPFeatureExtractor,
|
feature_extractor: CLIPImageProcessor,
|
||||||
requires_safety_checker: bool = True,
|
requires_safety_checker: bool = True,
|
||||||
):
|
):
|
||||||
super().__init__(
|
super().__init__(
|
||||||
|
|||||||
@@ -864,7 +864,7 @@ class RerenderAVideoPipeline(StableDiffusionControlNetImg2ImgPipeline):
|
|||||||
)
|
)
|
||||||
|
|
||||||
if guess_mode and do_classifier_free_guidance:
|
if guess_mode and do_classifier_free_guidance:
|
||||||
# Infered ControlNet only for the conditional batch.
|
# Inferred ControlNet only for the conditional batch.
|
||||||
# To apply the output of ControlNet to both the unconditional and conditional batches,
|
# To apply the output of ControlNet to both the unconditional and conditional batches,
|
||||||
# add 0 to the unconditional batch to keep it unchanged.
|
# add 0 to the unconditional batch to keep it unchanged.
|
||||||
down_block_res_samples = [torch.cat([torch.zeros_like(d), d]) for d in down_block_res_samples]
|
down_block_res_samples = [torch.cat([torch.zeros_like(d), d]) for d in down_block_res_samples]
|
||||||
@@ -1038,7 +1038,7 @@ class RerenderAVideoPipeline(StableDiffusionControlNetImg2ImgPipeline):
|
|||||||
)
|
)
|
||||||
|
|
||||||
if guess_mode and do_classifier_free_guidance:
|
if guess_mode and do_classifier_free_guidance:
|
||||||
# Infered ControlNet only for the conditional batch.
|
# Inferred ControlNet only for the conditional batch.
|
||||||
# To apply the output of ControlNet to both the unconditional and conditional batches,
|
# To apply the output of ControlNet to both the unconditional and conditional batches,
|
||||||
# add 0 to the unconditional batch to keep it unchanged.
|
# add 0 to the unconditional batch to keep it unchanged.
|
||||||
down_block_res_samples = [
|
down_block_res_samples = [
|
||||||
|
|||||||
@@ -752,7 +752,7 @@ class StableDiffusionControlNetReferencePipeline(StableDiffusionControlNetPipeli
|
|||||||
)
|
)
|
||||||
|
|
||||||
if guess_mode and do_classifier_free_guidance:
|
if guess_mode and do_classifier_free_guidance:
|
||||||
# Infered ControlNet only for the conditional batch.
|
# Inferred ControlNet only for the conditional batch.
|
||||||
# To apply the output of ControlNet to both the unconditional and conditional batches,
|
# To apply the output of ControlNet to both the unconditional and conditional batches,
|
||||||
# add 0 to the unconditional batch to keep it unchanged.
|
# add 0 to the unconditional batch to keep it unchanged.
|
||||||
down_block_res_samples = [torch.cat([torch.zeros_like(d), d]) for d in down_block_res_samples]
|
down_block_res_samples = [torch.cat([torch.zeros_like(d), d]) for d in down_block_res_samples]
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ from typing import Any, Callable, Dict, List, Optional, Union
|
|||||||
import intel_extension_for_pytorch as ipex
|
import intel_extension_for_pytorch as ipex
|
||||||
import torch
|
import torch
|
||||||
from packaging import version
|
from packaging import version
|
||||||
from transformers import CLIPFeatureExtractor, CLIPTextModel, CLIPTokenizer
|
from transformers import CLIPImageProcessor, CLIPTextModel, CLIPTokenizer
|
||||||
|
|
||||||
from diffusers.configuration_utils import FrozenDict
|
from diffusers.configuration_utils import FrozenDict
|
||||||
from diffusers.loaders import StableDiffusionLoraLoaderMixin, TextualInversionLoaderMixin
|
from diffusers.loaders import StableDiffusionLoraLoaderMixin, TextualInversionLoaderMixin
|
||||||
@@ -86,7 +86,7 @@ class StableDiffusionIPEXPipeline(
|
|||||||
safety_checker ([`StableDiffusionSafetyChecker`]):
|
safety_checker ([`StableDiffusionSafetyChecker`]):
|
||||||
Classification module that estimates whether generated images could be considered offensive or harmful.
|
Classification module that estimates whether generated images could be considered offensive or harmful.
|
||||||
Please, refer to the [model card](https://huggingface.co/runwayml/stable-diffusion-v1-5) for details.
|
Please, refer to the [model card](https://huggingface.co/runwayml/stable-diffusion-v1-5) for details.
|
||||||
feature_extractor ([`CLIPFeatureExtractor`]):
|
feature_extractor ([`CLIPImageProcessor`]):
|
||||||
Model that extracts features from generated images to be used as inputs for the `safety_checker`.
|
Model that extracts features from generated images to be used as inputs for the `safety_checker`.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -100,7 +100,7 @@ class StableDiffusionIPEXPipeline(
|
|||||||
unet: UNet2DConditionModel,
|
unet: UNet2DConditionModel,
|
||||||
scheduler: KarrasDiffusionSchedulers,
|
scheduler: KarrasDiffusionSchedulers,
|
||||||
safety_checker: StableDiffusionSafetyChecker,
|
safety_checker: StableDiffusionSafetyChecker,
|
||||||
feature_extractor: CLIPFeatureExtractor,
|
feature_extractor: CLIPImageProcessor,
|
||||||
requires_safety_checker: bool = True,
|
requires_safety_checker: bool = True,
|
||||||
):
|
):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ from polygraphy.backend.trt import (
|
|||||||
network_from_onnx_path,
|
network_from_onnx_path,
|
||||||
save_engine,
|
save_engine,
|
||||||
)
|
)
|
||||||
from transformers import CLIPFeatureExtractor, CLIPTextModel, CLIPTokenizer, CLIPVisionModelWithProjection
|
from transformers import CLIPImageProcessor, CLIPTextModel, CLIPTokenizer, CLIPVisionModelWithProjection
|
||||||
|
|
||||||
from diffusers import DiffusionPipeline
|
from diffusers import DiffusionPipeline
|
||||||
from diffusers.configuration_utils import FrozenDict, deprecate
|
from diffusers.configuration_utils import FrozenDict, deprecate
|
||||||
@@ -60,7 +60,7 @@ from diffusers.utils import logging
|
|||||||
"""
|
"""
|
||||||
Installation instructions
|
Installation instructions
|
||||||
python3 -m pip install --upgrade transformers diffusers>=0.16.0
|
python3 -m pip install --upgrade transformers diffusers>=0.16.0
|
||||||
python3 -m pip install --upgrade tensorrt-cu12==10.2.0
|
python3 -m pip install --upgrade tensorrt~=10.2.0
|
||||||
python3 -m pip install --upgrade polygraphy>=0.47.0 onnx-graphsurgeon --extra-index-url https://pypi.ngc.nvidia.com
|
python3 -m pip install --upgrade polygraphy>=0.47.0 onnx-graphsurgeon --extra-index-url https://pypi.ngc.nvidia.com
|
||||||
python3 -m pip install onnxruntime
|
python3 -m pip install onnxruntime
|
||||||
"""
|
"""
|
||||||
@@ -659,7 +659,7 @@ class TensorRTStableDiffusionImg2ImgPipeline(DiffusionPipeline):
|
|||||||
r"""
|
r"""
|
||||||
Pipeline for image-to-image generation using TensorRT accelerated Stable Diffusion.
|
Pipeline for image-to-image generation using TensorRT accelerated Stable Diffusion.
|
||||||
|
|
||||||
This model inherits from [`StableDiffusionImg2ImgPipeline`]. Check the superclass documentation for the generic methods the
|
This model inherits from [`DiffusionPipeline`]. Check the superclass documentation for the generic methods the
|
||||||
library implements for all the pipelines (such as downloading or saving, running on a particular device, etc.)
|
library implements for all the pipelines (such as downloading or saving, running on a particular device, etc.)
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@@ -679,7 +679,7 @@ class TensorRTStableDiffusionImg2ImgPipeline(DiffusionPipeline):
|
|||||||
safety_checker ([`StableDiffusionSafetyChecker`]):
|
safety_checker ([`StableDiffusionSafetyChecker`]):
|
||||||
Classification module that estimates whether generated images could be considered offensive or harmful.
|
Classification module that estimates whether generated images could be considered offensive or harmful.
|
||||||
Please, refer to the [model card](https://huggingface.co/runwayml/stable-diffusion-v1-5) for details.
|
Please, refer to the [model card](https://huggingface.co/runwayml/stable-diffusion-v1-5) for details.
|
||||||
feature_extractor ([`CLIPFeatureExtractor`]):
|
feature_extractor ([`CLIPImageProcessor`]):
|
||||||
Model that extracts features from generated images to be used as inputs for the `safety_checker`.
|
Model that extracts features from generated images to be used as inputs for the `safety_checker`.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -693,7 +693,7 @@ class TensorRTStableDiffusionImg2ImgPipeline(DiffusionPipeline):
|
|||||||
unet: UNet2DConditionModel,
|
unet: UNet2DConditionModel,
|
||||||
scheduler: DDIMScheduler,
|
scheduler: DDIMScheduler,
|
||||||
safety_checker: StableDiffusionSafetyChecker,
|
safety_checker: StableDiffusionSafetyChecker,
|
||||||
feature_extractor: CLIPFeatureExtractor,
|
feature_extractor: CLIPImageProcessor,
|
||||||
image_encoder: CLIPVisionModelWithProjection = None,
|
image_encoder: CLIPVisionModelWithProjection = None,
|
||||||
requires_safety_checker: bool = True,
|
requires_safety_checker: bool = True,
|
||||||
stages=["clip", "unet", "vae", "vae_encoder"],
|
stages=["clip", "unet", "vae", "vae_encoder"],
|
||||||
|
|||||||
@@ -18,8 +18,7 @@
|
|||||||
import gc
|
import gc
|
||||||
import os
|
import os
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from copy import copy
|
from typing import List, Optional, Tuple, Union
|
||||||
from typing import List, Optional, Union
|
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import onnx
|
import onnx
|
||||||
@@ -27,9 +26,11 @@ import onnx_graphsurgeon as gs
|
|||||||
import PIL.Image
|
import PIL.Image
|
||||||
import tensorrt as trt
|
import tensorrt as trt
|
||||||
import torch
|
import torch
|
||||||
|
from cuda import cudart
|
||||||
from huggingface_hub import snapshot_download
|
from huggingface_hub import snapshot_download
|
||||||
from huggingface_hub.utils import validate_hf_hub_args
|
from huggingface_hub.utils import validate_hf_hub_args
|
||||||
from onnx import shape_inference
|
from onnx import shape_inference
|
||||||
|
from packaging import version
|
||||||
from polygraphy import cuda
|
from polygraphy import cuda
|
||||||
from polygraphy.backend.common import bytes_from_path
|
from polygraphy.backend.common import bytes_from_path
|
||||||
from polygraphy.backend.onnx.loader import fold_constants
|
from polygraphy.backend.onnx.loader import fold_constants
|
||||||
@@ -41,24 +42,29 @@ from polygraphy.backend.trt import (
|
|||||||
network_from_onnx_path,
|
network_from_onnx_path,
|
||||||
save_engine,
|
save_engine,
|
||||||
)
|
)
|
||||||
from polygraphy.backend.trt import util as trt_util
|
from transformers import CLIPImageProcessor, CLIPTextModel, CLIPTokenizer, CLIPVisionModelWithProjection
|
||||||
from transformers import CLIPFeatureExtractor, CLIPTextModel, CLIPTokenizer, CLIPVisionModelWithProjection
|
|
||||||
|
|
||||||
|
from diffusers import DiffusionPipeline
|
||||||
|
from diffusers.configuration_utils import FrozenDict, deprecate
|
||||||
|
from diffusers.image_processor import VaeImageProcessor
|
||||||
from diffusers.models import AutoencoderKL, UNet2DConditionModel
|
from diffusers.models import AutoencoderKL, UNet2DConditionModel
|
||||||
from diffusers.pipelines.stable_diffusion import (
|
from diffusers.pipelines.stable_diffusion import (
|
||||||
StableDiffusionInpaintPipeline,
|
|
||||||
StableDiffusionPipelineOutput,
|
StableDiffusionPipelineOutput,
|
||||||
StableDiffusionSafetyChecker,
|
StableDiffusionSafetyChecker,
|
||||||
)
|
)
|
||||||
from diffusers.pipelines.stable_diffusion.pipeline_stable_diffusion_inpaint import prepare_mask_and_masked_image
|
from diffusers.pipelines.stable_diffusion.pipeline_stable_diffusion_inpaint import (
|
||||||
|
prepare_mask_and_masked_image,
|
||||||
|
retrieve_latents,
|
||||||
|
)
|
||||||
from diffusers.schedulers import DDIMScheduler
|
from diffusers.schedulers import DDIMScheduler
|
||||||
from diffusers.utils import logging
|
from diffusers.utils import logging
|
||||||
|
from diffusers.utils.torch_utils import randn_tensor
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Installation instructions
|
Installation instructions
|
||||||
python3 -m pip install --upgrade transformers diffusers>=0.16.0
|
python3 -m pip install --upgrade transformers diffusers>=0.16.0
|
||||||
python3 -m pip install --upgrade tensorrt>=8.6.1
|
python3 -m pip install --upgrade tensorrt~=10.2.0
|
||||||
python3 -m pip install --upgrade polygraphy>=0.47.0 onnx-graphsurgeon --extra-index-url https://pypi.ngc.nvidia.com
|
python3 -m pip install --upgrade polygraphy>=0.47.0 onnx-graphsurgeon --extra-index-url https://pypi.ngc.nvidia.com
|
||||||
python3 -m pip install onnxruntime
|
python3 -m pip install onnxruntime
|
||||||
"""
|
"""
|
||||||
@@ -88,10 +94,6 @@ else:
|
|||||||
torch_to_numpy_dtype_dict = {value: key for (key, value) in numpy_to_torch_dtype_dict.items()}
|
torch_to_numpy_dtype_dict = {value: key for (key, value) in numpy_to_torch_dtype_dict.items()}
|
||||||
|
|
||||||
|
|
||||||
def device_view(t):
|
|
||||||
return cuda.DeviceView(ptr=t.data_ptr(), shape=t.shape, dtype=torch_to_numpy_dtype_dict[t.dtype])
|
|
||||||
|
|
||||||
|
|
||||||
def preprocess_image(image):
|
def preprocess_image(image):
|
||||||
"""
|
"""
|
||||||
image: torch.Tensor
|
image: torch.Tensor
|
||||||
@@ -125,10 +127,8 @@ class Engine:
|
|||||||
onnx_path,
|
onnx_path,
|
||||||
fp16,
|
fp16,
|
||||||
input_profile=None,
|
input_profile=None,
|
||||||
enable_preview=False,
|
|
||||||
enable_all_tactics=False,
|
enable_all_tactics=False,
|
||||||
timing_cache=None,
|
timing_cache=None,
|
||||||
workspace_size=0,
|
|
||||||
):
|
):
|
||||||
logger.warning(f"Building TensorRT engine for {onnx_path}: {self.engine_path}")
|
logger.warning(f"Building TensorRT engine for {onnx_path}: {self.engine_path}")
|
||||||
p = Profile()
|
p = Profile()
|
||||||
@@ -137,20 +137,13 @@ class Engine:
|
|||||||
assert len(dims) == 3
|
assert len(dims) == 3
|
||||||
p.add(name, min=dims[0], opt=dims[1], max=dims[2])
|
p.add(name, min=dims[0], opt=dims[1], max=dims[2])
|
||||||
|
|
||||||
config_kwargs = {}
|
extra_build_args = {}
|
||||||
|
|
||||||
config_kwargs["preview_features"] = [trt.PreviewFeature.DISABLE_EXTERNAL_TACTIC_SOURCES_FOR_CORE_0805]
|
|
||||||
if enable_preview:
|
|
||||||
# Faster dynamic shapes made optional since it increases engine build time.
|
|
||||||
config_kwargs["preview_features"].append(trt.PreviewFeature.FASTER_DYNAMIC_SHAPES_0805)
|
|
||||||
if workspace_size > 0:
|
|
||||||
config_kwargs["memory_pool_limits"] = {trt.MemoryPoolType.WORKSPACE: workspace_size}
|
|
||||||
if not enable_all_tactics:
|
if not enable_all_tactics:
|
||||||
config_kwargs["tactic_sources"] = []
|
extra_build_args["tactic_sources"] = []
|
||||||
|
|
||||||
engine = engine_from_network(
|
engine = engine_from_network(
|
||||||
network_from_onnx_path(onnx_path, flags=[trt.OnnxParserFlag.NATIVE_INSTANCENORM]),
|
network_from_onnx_path(onnx_path, flags=[trt.OnnxParserFlag.NATIVE_INSTANCENORM]),
|
||||||
config=CreateConfig(fp16=fp16, profiles=[p], load_timing_cache=timing_cache, **config_kwargs),
|
config=CreateConfig(fp16=fp16, profiles=[p], load_timing_cache=timing_cache, **extra_build_args),
|
||||||
save_timing_cache=timing_cache,
|
save_timing_cache=timing_cache,
|
||||||
)
|
)
|
||||||
save_engine(engine, path=self.engine_path)
|
save_engine(engine, path=self.engine_path)
|
||||||
@@ -163,28 +156,24 @@ class Engine:
|
|||||||
self.context = self.engine.create_execution_context()
|
self.context = self.engine.create_execution_context()
|
||||||
|
|
||||||
def allocate_buffers(self, shape_dict=None, device="cuda"):
|
def allocate_buffers(self, shape_dict=None, device="cuda"):
|
||||||
for idx in range(trt_util.get_bindings_per_profile(self.engine)):
|
for binding in range(self.engine.num_io_tensors):
|
||||||
binding = self.engine[idx]
|
name = self.engine.get_tensor_name(binding)
|
||||||
if shape_dict and binding in shape_dict:
|
if shape_dict and name in shape_dict:
|
||||||
shape = shape_dict[binding]
|
shape = shape_dict[name]
|
||||||
else:
|
else:
|
||||||
shape = self.engine.get_binding_shape(binding)
|
shape = self.engine.get_tensor_shape(name)
|
||||||
dtype = trt.nptype(self.engine.get_binding_dtype(binding))
|
dtype = trt.nptype(self.engine.get_tensor_dtype(name))
|
||||||
if self.engine.binding_is_input(binding):
|
if self.engine.get_tensor_mode(name) == trt.TensorIOMode.INPUT:
|
||||||
self.context.set_binding_shape(idx, shape)
|
self.context.set_input_shape(name, shape)
|
||||||
tensor = torch.empty(tuple(shape), dtype=numpy_to_torch_dtype_dict[dtype]).to(device=device)
|
tensor = torch.empty(tuple(shape), dtype=numpy_to_torch_dtype_dict[dtype]).to(device=device)
|
||||||
self.tensors[binding] = tensor
|
self.tensors[name] = tensor
|
||||||
self.buffers[binding] = cuda.DeviceView(ptr=tensor.data_ptr(), shape=shape, dtype=dtype)
|
|
||||||
|
|
||||||
def infer(self, feed_dict, stream):
|
def infer(self, feed_dict, stream):
|
||||||
start_binding, end_binding = trt_util.get_active_profile_bindings(self.context)
|
|
||||||
# shallow copy of ordered dict
|
|
||||||
device_buffers = copy(self.buffers)
|
|
||||||
for name, buf in feed_dict.items():
|
for name, buf in feed_dict.items():
|
||||||
assert isinstance(buf, cuda.DeviceView)
|
self.tensors[name].copy_(buf)
|
||||||
device_buffers[name] = buf
|
for name, tensor in self.tensors.items():
|
||||||
bindings = [0] * start_binding + [buf.ptr for buf in device_buffers.values()]
|
self.context.set_tensor_address(name, tensor.data_ptr())
|
||||||
noerror = self.context.execute_async_v2(bindings=bindings, stream_handle=stream.ptr)
|
noerror = self.context.execute_async_v3(stream)
|
||||||
if not noerror:
|
if not noerror:
|
||||||
raise ValueError("ERROR: inference failed.")
|
raise ValueError("ERROR: inference failed.")
|
||||||
|
|
||||||
@@ -325,10 +314,8 @@ def build_engines(
|
|||||||
force_engine_rebuild=False,
|
force_engine_rebuild=False,
|
||||||
static_batch=False,
|
static_batch=False,
|
||||||
static_shape=True,
|
static_shape=True,
|
||||||
enable_preview=False,
|
|
||||||
enable_all_tactics=False,
|
enable_all_tactics=False,
|
||||||
timing_cache=None,
|
timing_cache=None,
|
||||||
max_workspace_size=0,
|
|
||||||
):
|
):
|
||||||
built_engines = {}
|
built_engines = {}
|
||||||
if not os.path.isdir(onnx_dir):
|
if not os.path.isdir(onnx_dir):
|
||||||
@@ -393,9 +380,7 @@ def build_engines(
|
|||||||
static_batch=static_batch,
|
static_batch=static_batch,
|
||||||
static_shape=static_shape,
|
static_shape=static_shape,
|
||||||
),
|
),
|
||||||
enable_preview=enable_preview,
|
|
||||||
timing_cache=timing_cache,
|
timing_cache=timing_cache,
|
||||||
workspace_size=max_workspace_size,
|
|
||||||
)
|
)
|
||||||
built_engines[model_name] = engine
|
built_engines[model_name] = engine
|
||||||
|
|
||||||
@@ -674,11 +659,11 @@ def make_VAEEncoder(model, device, max_batch_size, embedding_dim, inpaint=False)
|
|||||||
return VAEEncoder(model, device=device, max_batch_size=max_batch_size, embedding_dim=embedding_dim)
|
return VAEEncoder(model, device=device, max_batch_size=max_batch_size, embedding_dim=embedding_dim)
|
||||||
|
|
||||||
|
|
||||||
class TensorRTStableDiffusionInpaintPipeline(StableDiffusionInpaintPipeline):
|
class TensorRTStableDiffusionInpaintPipeline(DiffusionPipeline):
|
||||||
r"""
|
r"""
|
||||||
Pipeline for inpainting using TensorRT accelerated Stable Diffusion.
|
Pipeline for inpainting using TensorRT accelerated Stable Diffusion.
|
||||||
|
|
||||||
This model inherits from [`StableDiffusionInpaintPipeline`]. Check the superclass documentation for the generic methods the
|
This model inherits from [`DiffusionPipeline`]. Check the superclass documentation for the generic methods the
|
||||||
library implements for all the pipelines (such as downloading or saving, running on a particular device, etc.)
|
library implements for all the pipelines (such as downloading or saving, running on a particular device, etc.)
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@@ -698,10 +683,12 @@ class TensorRTStableDiffusionInpaintPipeline(StableDiffusionInpaintPipeline):
|
|||||||
safety_checker ([`StableDiffusionSafetyChecker`]):
|
safety_checker ([`StableDiffusionSafetyChecker`]):
|
||||||
Classification module that estimates whether generated images could be considered offensive or harmful.
|
Classification module that estimates whether generated images could be considered offensive or harmful.
|
||||||
Please, refer to the [model card](https://huggingface.co/runwayml/stable-diffusion-v1-5) for details.
|
Please, refer to the [model card](https://huggingface.co/runwayml/stable-diffusion-v1-5) for details.
|
||||||
feature_extractor ([`CLIPFeatureExtractor`]):
|
feature_extractor ([`CLIPImageProcessor`]):
|
||||||
Model that extracts features from generated images to be used as inputs for the `safety_checker`.
|
Model that extracts features from generated images to be used as inputs for the `safety_checker`.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
_optional_components = ["safety_checker", "feature_extractor", "image_encoder"]
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
vae: AutoencoderKL,
|
vae: AutoencoderKL,
|
||||||
@@ -710,7 +697,7 @@ class TensorRTStableDiffusionInpaintPipeline(StableDiffusionInpaintPipeline):
|
|||||||
unet: UNet2DConditionModel,
|
unet: UNet2DConditionModel,
|
||||||
scheduler: DDIMScheduler,
|
scheduler: DDIMScheduler,
|
||||||
safety_checker: StableDiffusionSafetyChecker,
|
safety_checker: StableDiffusionSafetyChecker,
|
||||||
feature_extractor: CLIPFeatureExtractor,
|
feature_extractor: CLIPImageProcessor,
|
||||||
image_encoder: CLIPVisionModelWithProjection = None,
|
image_encoder: CLIPVisionModelWithProjection = None,
|
||||||
requires_safety_checker: bool = True,
|
requires_safety_checker: bool = True,
|
||||||
stages=["clip", "unet", "vae", "vae_encoder"],
|
stages=["clip", "unet", "vae", "vae_encoder"],
|
||||||
@@ -722,24 +709,86 @@ class TensorRTStableDiffusionInpaintPipeline(StableDiffusionInpaintPipeline):
|
|||||||
onnx_dir: str = "onnx",
|
onnx_dir: str = "onnx",
|
||||||
# TensorRT engine build parameters
|
# TensorRT engine build parameters
|
||||||
engine_dir: str = "engine",
|
engine_dir: str = "engine",
|
||||||
build_preview_features: bool = True,
|
|
||||||
force_engine_rebuild: bool = False,
|
force_engine_rebuild: bool = False,
|
||||||
timing_cache: str = "timing_cache",
|
timing_cache: str = "timing_cache",
|
||||||
):
|
):
|
||||||
super().__init__(
|
super().__init__()
|
||||||
vae,
|
|
||||||
text_encoder,
|
if hasattr(scheduler.config, "steps_offset") and scheduler.config.steps_offset != 1:
|
||||||
tokenizer,
|
deprecation_message = (
|
||||||
unet,
|
f"The configuration file of this scheduler: {scheduler} is outdated. `steps_offset`"
|
||||||
scheduler,
|
f" should be set to 1 instead of {scheduler.config.steps_offset}. Please make sure "
|
||||||
|
"to update the config accordingly as leaving `steps_offset` might led to incorrect results"
|
||||||
|
" in future versions. If you have downloaded this checkpoint from the Hugging Face Hub,"
|
||||||
|
" it would be very nice if you could open a Pull request for the `scheduler/scheduler_config.json`"
|
||||||
|
" file"
|
||||||
|
)
|
||||||
|
deprecate("steps_offset!=1", "1.0.0", deprecation_message, standard_warn=False)
|
||||||
|
new_config = dict(scheduler.config)
|
||||||
|
new_config["steps_offset"] = 1
|
||||||
|
scheduler._internal_dict = FrozenDict(new_config)
|
||||||
|
|
||||||
|
if hasattr(scheduler.config, "clip_sample") and scheduler.config.clip_sample is True:
|
||||||
|
deprecation_message = (
|
||||||
|
f"The configuration file of this scheduler: {scheduler} has not set the configuration `clip_sample`."
|
||||||
|
" `clip_sample` should be set to False in the configuration file. Please make sure to update the"
|
||||||
|
" config accordingly as not setting `clip_sample` in the config might lead to incorrect results in"
|
||||||
|
" future versions. If you have downloaded this checkpoint from the Hugging Face Hub, it would be very"
|
||||||
|
" nice if you could open a Pull request for the `scheduler/scheduler_config.json` file"
|
||||||
|
)
|
||||||
|
deprecate("clip_sample not set", "1.0.0", deprecation_message, standard_warn=False)
|
||||||
|
new_config = dict(scheduler.config)
|
||||||
|
new_config["clip_sample"] = False
|
||||||
|
scheduler._internal_dict = FrozenDict(new_config)
|
||||||
|
|
||||||
|
if safety_checker is None and requires_safety_checker:
|
||||||
|
logger.warning(
|
||||||
|
f"You have disabled the safety checker for {self.__class__} by passing `safety_checker=None`. Ensure"
|
||||||
|
" that you abide to the conditions of the Stable Diffusion license and do not expose unfiltered"
|
||||||
|
" results in services or applications open to the public. Both the diffusers team and Hugging Face"
|
||||||
|
" strongly recommend to keep the safety filter enabled in all public facing circumstances, disabling"
|
||||||
|
" it only for use-cases that involve analyzing network behavior or auditing its results. For more"
|
||||||
|
" information, please have a look at https://github.com/huggingface/diffusers/pull/254 ."
|
||||||
|
)
|
||||||
|
|
||||||
|
if safety_checker is not None and feature_extractor is None:
|
||||||
|
raise ValueError(
|
||||||
|
"Make sure to define a feature extractor when loading {self.__class__} if you want to use the safety"
|
||||||
|
" checker. If you do not want to use the safety checker, you can pass `'safety_checker=None'` instead."
|
||||||
|
)
|
||||||
|
|
||||||
|
is_unet_version_less_0_9_0 = hasattr(unet.config, "_diffusers_version") and version.parse(
|
||||||
|
version.parse(unet.config._diffusers_version).base_version
|
||||||
|
) < version.parse("0.9.0.dev0")
|
||||||
|
is_unet_sample_size_less_64 = hasattr(unet.config, "sample_size") and unet.config.sample_size < 64
|
||||||
|
if is_unet_version_less_0_9_0 and is_unet_sample_size_less_64:
|
||||||
|
deprecation_message = (
|
||||||
|
"The configuration file of the unet has set the default `sample_size` to smaller than"
|
||||||
|
" 64 which seems highly unlikely. If your checkpoint is a fine-tuned version of any of the"
|
||||||
|
" following: \n- CompVis/stable-diffusion-v1-4 \n- CompVis/stable-diffusion-v1-3 \n-"
|
||||||
|
" CompVis/stable-diffusion-v1-2 \n- CompVis/stable-diffusion-v1-1 \n- runwayml/stable-diffusion-v1-5"
|
||||||
|
" \n- runwayml/stable-diffusion-inpainting \n you should change 'sample_size' to 64 in the"
|
||||||
|
" configuration file. Please make sure to update the config accordingly as leaving `sample_size=32`"
|
||||||
|
" in the config might lead to incorrect results in future versions. If you have downloaded this"
|
||||||
|
" checkpoint from the Hugging Face Hub, it would be very nice if you could open a Pull request for"
|
||||||
|
" the `unet/config.json` file"
|
||||||
|
)
|
||||||
|
deprecate("sample_size<64", "1.0.0", deprecation_message, standard_warn=False)
|
||||||
|
new_config = dict(unet.config)
|
||||||
|
new_config["sample_size"] = 64
|
||||||
|
unet._internal_dict = FrozenDict(new_config)
|
||||||
|
|
||||||
|
self.register_modules(
|
||||||
|
vae=vae,
|
||||||
|
text_encoder=text_encoder,
|
||||||
|
tokenizer=tokenizer,
|
||||||
|
unet=unet,
|
||||||
|
scheduler=scheduler,
|
||||||
safety_checker=safety_checker,
|
safety_checker=safety_checker,
|
||||||
feature_extractor=feature_extractor,
|
feature_extractor=feature_extractor,
|
||||||
image_encoder=image_encoder,
|
image_encoder=image_encoder,
|
||||||
requires_safety_checker=requires_safety_checker,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
self.vae.forward = self.vae.decode
|
|
||||||
|
|
||||||
self.stages = stages
|
self.stages = stages
|
||||||
self.image_height, self.image_width = image_height, image_width
|
self.image_height, self.image_width = image_height, image_width
|
||||||
self.inpaint = True
|
self.inpaint = True
|
||||||
@@ -750,7 +799,6 @@ class TensorRTStableDiffusionInpaintPipeline(StableDiffusionInpaintPipeline):
|
|||||||
self.timing_cache = timing_cache
|
self.timing_cache = timing_cache
|
||||||
self.build_static_batch = False
|
self.build_static_batch = False
|
||||||
self.build_dynamic_shape = False
|
self.build_dynamic_shape = False
|
||||||
self.build_preview_features = build_preview_features
|
|
||||||
|
|
||||||
self.max_batch_size = max_batch_size
|
self.max_batch_size = max_batch_size
|
||||||
# TODO: Restrict batch size to 4 for larger image dimensions as a WAR for TensorRT limitation.
|
# TODO: Restrict batch size to 4 for larger image dimensions as a WAR for TensorRT limitation.
|
||||||
@@ -761,6 +809,11 @@ class TensorRTStableDiffusionInpaintPipeline(StableDiffusionInpaintPipeline):
|
|||||||
self.models = {} # loaded in __loadModels()
|
self.models = {} # loaded in __loadModels()
|
||||||
self.engine = {} # loaded in build_engines()
|
self.engine = {} # loaded in build_engines()
|
||||||
|
|
||||||
|
self.vae.forward = self.vae.decode
|
||||||
|
self.vae_scale_factor = 2 ** (len(self.vae.config.block_out_channels) - 1)
|
||||||
|
self.image_processor = VaeImageProcessor(vae_scale_factor=self.vae_scale_factor)
|
||||||
|
self.register_to_config(requires_safety_checker=requires_safety_checker)
|
||||||
|
|
||||||
def __loadModels(self):
|
def __loadModels(self):
|
||||||
# Load pipeline models
|
# Load pipeline models
|
||||||
self.embedding_dim = self.text_encoder.config.hidden_size
|
self.embedding_dim = self.text_encoder.config.hidden_size
|
||||||
@@ -779,6 +832,112 @@ class TensorRTStableDiffusionInpaintPipeline(StableDiffusionInpaintPipeline):
|
|||||||
if "vae_encoder" in self.stages:
|
if "vae_encoder" in self.stages:
|
||||||
self.models["vae_encoder"] = make_VAEEncoder(self.vae, **models_args)
|
self.models["vae_encoder"] = make_VAEEncoder(self.vae, **models_args)
|
||||||
|
|
||||||
|
# Copied from diffusers.pipelines.stable_diffusion.pipeline_stable_diffusion_inpaint.StableDiffusionInpaintPipeline
|
||||||
|
|
||||||
|
def _encode_vae_image(self, image: torch.Tensor, generator: torch.Generator):
|
||||||
|
if isinstance(generator, list):
|
||||||
|
image_latents = [
|
||||||
|
retrieve_latents(self.vae.encode(image[i : i + 1]), generator=generator[i])
|
||||||
|
for i in range(image.shape[0])
|
||||||
|
]
|
||||||
|
image_latents = torch.cat(image_latents, dim=0)
|
||||||
|
else:
|
||||||
|
image_latents = retrieve_latents(self.vae.encode(image), generator=generator)
|
||||||
|
|
||||||
|
image_latents = self.vae.config.scaling_factor * image_latents
|
||||||
|
|
||||||
|
return image_latents
|
||||||
|
|
||||||
|
def prepare_latents(
|
||||||
|
self,
|
||||||
|
batch_size,
|
||||||
|
num_channels_latents,
|
||||||
|
height,
|
||||||
|
width,
|
||||||
|
dtype,
|
||||||
|
device,
|
||||||
|
generator,
|
||||||
|
latents=None,
|
||||||
|
image=None,
|
||||||
|
timestep=None,
|
||||||
|
is_strength_max=True,
|
||||||
|
return_noise=False,
|
||||||
|
return_image_latents=False,
|
||||||
|
):
|
||||||
|
shape = (
|
||||||
|
batch_size,
|
||||||
|
num_channels_latents,
|
||||||
|
int(height) // self.vae_scale_factor,
|
||||||
|
int(width) // self.vae_scale_factor,
|
||||||
|
)
|
||||||
|
if isinstance(generator, list) and len(generator) != batch_size:
|
||||||
|
raise ValueError(
|
||||||
|
f"You have passed a list of generators of length {len(generator)}, but requested an effective batch"
|
||||||
|
f" size of {batch_size}. Make sure the batch size matches the length of the generators."
|
||||||
|
)
|
||||||
|
|
||||||
|
if (image is None or timestep is None) and not is_strength_max:
|
||||||
|
raise ValueError(
|
||||||
|
"Since strength < 1. initial latents are to be initialised as a combination of Image + Noise."
|
||||||
|
"However, either the image or the noise timestep has not been provided."
|
||||||
|
)
|
||||||
|
|
||||||
|
if return_image_latents or (latents is None and not is_strength_max):
|
||||||
|
image = image.to(device=device, dtype=dtype)
|
||||||
|
|
||||||
|
if image.shape[1] == 4:
|
||||||
|
image_latents = image
|
||||||
|
else:
|
||||||
|
image_latents = self._encode_vae_image(image=image, generator=generator)
|
||||||
|
image_latents = image_latents.repeat(batch_size // image_latents.shape[0], 1, 1, 1)
|
||||||
|
|
||||||
|
if latents is None:
|
||||||
|
noise = randn_tensor(shape, generator=generator, device=device, dtype=dtype)
|
||||||
|
# if strength is 1. then initialise the latents to noise, else initial to image + noise
|
||||||
|
latents = noise if is_strength_max else self.scheduler.add_noise(image_latents, noise, timestep)
|
||||||
|
# if pure noise then scale the initial latents by the Scheduler's init sigma
|
||||||
|
latents = latents * self.scheduler.init_noise_sigma if is_strength_max else latents
|
||||||
|
else:
|
||||||
|
noise = latents.to(device)
|
||||||
|
latents = noise * self.scheduler.init_noise_sigma
|
||||||
|
|
||||||
|
outputs = (latents,)
|
||||||
|
|
||||||
|
if return_noise:
|
||||||
|
outputs += (noise,)
|
||||||
|
|
||||||
|
if return_image_latents:
|
||||||
|
outputs += (image_latents,)
|
||||||
|
|
||||||
|
return outputs
|
||||||
|
|
||||||
|
# Copied from diffusers.pipelines.stable_diffusion.pipeline_stable_diffusion.StableDiffusionPipeline.run_safety_checker
|
||||||
|
def run_safety_checker(
|
||||||
|
self, image: Union[torch.Tensor, PIL.Image.Image], device: torch.device, dtype: torch.dtype
|
||||||
|
) -> Tuple[Union[torch.Tensor, PIL.Image.Image], Optional[bool]]:
|
||||||
|
r"""
|
||||||
|
Runs the safety checker on the given image.
|
||||||
|
Args:
|
||||||
|
image (Union[torch.Tensor, PIL.Image.Image]): The input image to be checked.
|
||||||
|
device (torch.device): The device to run the safety checker on.
|
||||||
|
dtype (torch.dtype): The data type of the input image.
|
||||||
|
Returns:
|
||||||
|
(image, has_nsfw_concept) Tuple[Union[torch.Tensor, PIL.Image.Image], Optional[bool]]: A tuple containing the processed image and
|
||||||
|
a boolean indicating whether the image has a NSFW (Not Safe for Work) concept.
|
||||||
|
"""
|
||||||
|
if self.safety_checker is None:
|
||||||
|
has_nsfw_concept = None
|
||||||
|
else:
|
||||||
|
if torch.is_tensor(image):
|
||||||
|
feature_extractor_input = self.image_processor.postprocess(image, output_type="pil")
|
||||||
|
else:
|
||||||
|
feature_extractor_input = self.image_processor.numpy_to_pil(image)
|
||||||
|
safety_checker_input = self.feature_extractor(feature_extractor_input, return_tensors="pt").to(device)
|
||||||
|
image, has_nsfw_concept = self.safety_checker(
|
||||||
|
images=image, clip_input=safety_checker_input.pixel_values.to(dtype)
|
||||||
|
)
|
||||||
|
return image, has_nsfw_concept
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@validate_hf_hub_args
|
@validate_hf_hub_args
|
||||||
def set_cached_folder(cls, pretrained_model_name_or_path: Optional[Union[str, os.PathLike]], **kwargs):
|
def set_cached_folder(cls, pretrained_model_name_or_path: Optional[Union[str, os.PathLike]], **kwargs):
|
||||||
@@ -826,7 +985,6 @@ class TensorRTStableDiffusionInpaintPipeline(StableDiffusionInpaintPipeline):
|
|||||||
force_engine_rebuild=self.force_engine_rebuild,
|
force_engine_rebuild=self.force_engine_rebuild,
|
||||||
static_batch=self.build_static_batch,
|
static_batch=self.build_static_batch,
|
||||||
static_shape=not self.build_dynamic_shape,
|
static_shape=not self.build_dynamic_shape,
|
||||||
enable_preview=self.build_preview_features,
|
|
||||||
timing_cache=self.timing_cache,
|
timing_cache=self.timing_cache,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -850,9 +1008,7 @@ class TensorRTStableDiffusionInpaintPipeline(StableDiffusionInpaintPipeline):
|
|||||||
return tuple(init_images)
|
return tuple(init_images)
|
||||||
|
|
||||||
def __encode_image(self, init_image):
|
def __encode_image(self, init_image):
|
||||||
init_latents = runEngine(self.engine["vae_encoder"], {"images": device_view(init_image)}, self.stream)[
|
init_latents = runEngine(self.engine["vae_encoder"], {"images": init_image}, self.stream)["latent"]
|
||||||
"latent"
|
|
||||||
]
|
|
||||||
init_latents = 0.18215 * init_latents
|
init_latents = 0.18215 * init_latents
|
||||||
return init_latents
|
return init_latents
|
||||||
|
|
||||||
@@ -881,9 +1037,8 @@ class TensorRTStableDiffusionInpaintPipeline(StableDiffusionInpaintPipeline):
|
|||||||
.to(self.torch_device)
|
.to(self.torch_device)
|
||||||
)
|
)
|
||||||
|
|
||||||
text_input_ids_inp = device_view(text_input_ids)
|
|
||||||
# NOTE: output tensor for CLIP must be cloned because it will be overwritten when called again for negative prompt
|
# NOTE: output tensor for CLIP must be cloned because it will be overwritten when called again for negative prompt
|
||||||
text_embeddings = runEngine(self.engine["clip"], {"input_ids": text_input_ids_inp}, self.stream)[
|
text_embeddings = runEngine(self.engine["clip"], {"input_ids": text_input_ids}, self.stream)[
|
||||||
"text_embeddings"
|
"text_embeddings"
|
||||||
].clone()
|
].clone()
|
||||||
|
|
||||||
@@ -899,8 +1054,7 @@ class TensorRTStableDiffusionInpaintPipeline(StableDiffusionInpaintPipeline):
|
|||||||
.input_ids.type(torch.int32)
|
.input_ids.type(torch.int32)
|
||||||
.to(self.torch_device)
|
.to(self.torch_device)
|
||||||
)
|
)
|
||||||
uncond_input_ids_inp = device_view(uncond_input_ids)
|
uncond_embeddings = runEngine(self.engine["clip"], {"input_ids": uncond_input_ids}, self.stream)[
|
||||||
uncond_embeddings = runEngine(self.engine["clip"], {"input_ids": uncond_input_ids_inp}, self.stream)[
|
|
||||||
"text_embeddings"
|
"text_embeddings"
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -924,18 +1078,15 @@ class TensorRTStableDiffusionInpaintPipeline(StableDiffusionInpaintPipeline):
|
|||||||
# Predict the noise residual
|
# Predict the noise residual
|
||||||
timestep_float = timestep.float() if timestep.dtype != torch.float32 else timestep
|
timestep_float = timestep.float() if timestep.dtype != torch.float32 else timestep
|
||||||
|
|
||||||
sample_inp = device_view(latent_model_input)
|
|
||||||
timestep_inp = device_view(timestep_float)
|
|
||||||
embeddings_inp = device_view(text_embeddings)
|
|
||||||
noise_pred = runEngine(
|
noise_pred = runEngine(
|
||||||
self.engine["unet"],
|
self.engine["unet"],
|
||||||
{"sample": sample_inp, "timestep": timestep_inp, "encoder_hidden_states": embeddings_inp},
|
{"sample": latent_model_input, "timestep": timestep_float, "encoder_hidden_states": text_embeddings},
|
||||||
self.stream,
|
self.stream,
|
||||||
)["latent"]
|
)["latent"]
|
||||||
|
|
||||||
# Perform guidance
|
# Perform guidance
|
||||||
noise_pred_uncond, noise_pred_text = noise_pred.chunk(2)
|
noise_pred_uncond, noise_pred_text = noise_pred.chunk(2)
|
||||||
noise_pred = noise_pred_uncond + self.guidance_scale * (noise_pred_text - noise_pred_uncond)
|
noise_pred = noise_pred_uncond + self._guidance_scale * (noise_pred_text - noise_pred_uncond)
|
||||||
|
|
||||||
latents = self.scheduler.step(noise_pred, timestep, latents).prev_sample
|
latents = self.scheduler.step(noise_pred, timestep, latents).prev_sample
|
||||||
|
|
||||||
@@ -943,12 +1094,12 @@ class TensorRTStableDiffusionInpaintPipeline(StableDiffusionInpaintPipeline):
|
|||||||
return latents
|
return latents
|
||||||
|
|
||||||
def __decode_latent(self, latents):
|
def __decode_latent(self, latents):
|
||||||
images = runEngine(self.engine["vae"], {"latent": device_view(latents)}, self.stream)["images"]
|
images = runEngine(self.engine["vae"], {"latent": latents}, self.stream)["images"]
|
||||||
images = (images / 2 + 0.5).clamp(0, 1)
|
images = (images / 2 + 0.5).clamp(0, 1)
|
||||||
return images.cpu().permute(0, 2, 3, 1).float().numpy()
|
return images.cpu().permute(0, 2, 3, 1).float().numpy()
|
||||||
|
|
||||||
def __loadResources(self, image_height, image_width, batch_size):
|
def __loadResources(self, image_height, image_width, batch_size):
|
||||||
self.stream = cuda.Stream()
|
self.stream = cudart.cudaStreamCreate()[1]
|
||||||
|
|
||||||
# Allocate buffers for TensorRT engine bindings
|
# Allocate buffers for TensorRT engine bindings
|
||||||
for model_name, obj in self.models.items():
|
for model_name, obj in self.models.items():
|
||||||
@@ -1112,5 +1263,6 @@ class TensorRTStableDiffusionInpaintPipeline(StableDiffusionInpaintPipeline):
|
|||||||
# VAE decode latent
|
# VAE decode latent
|
||||||
images = self.__decode_latent(latents)
|
images = self.__decode_latent(latents)
|
||||||
|
|
||||||
|
images, has_nsfw_concept = self.run_safety_checker(images, self.torch_device, text_embeddings.dtype)
|
||||||
images = self.numpy_to_pil(images)
|
images = self.numpy_to_pil(images)
|
||||||
return StableDiffusionPipelineOutput(images=images, nsfw_content_detected=None)
|
return StableDiffusionPipelineOutput(images=images, nsfw_content_detected=has_nsfw_concept)
|
||||||
|
|||||||
@@ -18,17 +18,19 @@
|
|||||||
import gc
|
import gc
|
||||||
import os
|
import os
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from copy import copy
|
from typing import List, Optional, Tuple, Union
|
||||||
from typing import List, Optional, Union
|
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import onnx
|
import onnx
|
||||||
import onnx_graphsurgeon as gs
|
import onnx_graphsurgeon as gs
|
||||||
|
import PIL.Image
|
||||||
import tensorrt as trt
|
import tensorrt as trt
|
||||||
import torch
|
import torch
|
||||||
|
from cuda import cudart
|
||||||
from huggingface_hub import snapshot_download
|
from huggingface_hub import snapshot_download
|
||||||
from huggingface_hub.utils import validate_hf_hub_args
|
from huggingface_hub.utils import validate_hf_hub_args
|
||||||
from onnx import shape_inference
|
from onnx import shape_inference
|
||||||
|
from packaging import version
|
||||||
from polygraphy import cuda
|
from polygraphy import cuda
|
||||||
from polygraphy.backend.common import bytes_from_path
|
from polygraphy.backend.common import bytes_from_path
|
||||||
from polygraphy.backend.onnx.loader import fold_constants
|
from polygraphy.backend.onnx.loader import fold_constants
|
||||||
@@ -40,23 +42,25 @@ from polygraphy.backend.trt import (
|
|||||||
network_from_onnx_path,
|
network_from_onnx_path,
|
||||||
save_engine,
|
save_engine,
|
||||||
)
|
)
|
||||||
from polygraphy.backend.trt import util as trt_util
|
from transformers import CLIPImageProcessor, CLIPTextModel, CLIPTokenizer, CLIPVisionModelWithProjection
|
||||||
from transformers import CLIPFeatureExtractor, CLIPTextModel, CLIPTokenizer, CLIPVisionModelWithProjection
|
|
||||||
|
|
||||||
|
from diffusers import DiffusionPipeline
|
||||||
|
from diffusers.configuration_utils import FrozenDict, deprecate
|
||||||
|
from diffusers.image_processor import VaeImageProcessor
|
||||||
from diffusers.models import AutoencoderKL, UNet2DConditionModel
|
from diffusers.models import AutoencoderKL, UNet2DConditionModel
|
||||||
from diffusers.pipelines.stable_diffusion import (
|
from diffusers.pipelines.stable_diffusion import (
|
||||||
StableDiffusionPipeline,
|
|
||||||
StableDiffusionPipelineOutput,
|
StableDiffusionPipelineOutput,
|
||||||
StableDiffusionSafetyChecker,
|
StableDiffusionSafetyChecker,
|
||||||
)
|
)
|
||||||
from diffusers.schedulers import DDIMScheduler
|
from diffusers.schedulers import DDIMScheduler
|
||||||
from diffusers.utils import logging
|
from diffusers.utils import logging
|
||||||
|
from diffusers.utils.torch_utils import randn_tensor
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Installation instructions
|
Installation instructions
|
||||||
python3 -m pip install --upgrade transformers diffusers>=0.16.0
|
python3 -m pip install --upgrade transformers diffusers>=0.16.0
|
||||||
python3 -m pip install --upgrade tensorrt>=8.6.1
|
python3 -m pip install --upgrade tensorrt~=10.2.0
|
||||||
python3 -m pip install --upgrade polygraphy>=0.47.0 onnx-graphsurgeon --extra-index-url https://pypi.ngc.nvidia.com
|
python3 -m pip install --upgrade polygraphy>=0.47.0 onnx-graphsurgeon --extra-index-url https://pypi.ngc.nvidia.com
|
||||||
python3 -m pip install onnxruntime
|
python3 -m pip install onnxruntime
|
||||||
"""
|
"""
|
||||||
@@ -86,10 +90,6 @@ else:
|
|||||||
torch_to_numpy_dtype_dict = {value: key for (key, value) in numpy_to_torch_dtype_dict.items()}
|
torch_to_numpy_dtype_dict = {value: key for (key, value) in numpy_to_torch_dtype_dict.items()}
|
||||||
|
|
||||||
|
|
||||||
def device_view(t):
|
|
||||||
return cuda.DeviceView(ptr=t.data_ptr(), shape=t.shape, dtype=torch_to_numpy_dtype_dict[t.dtype])
|
|
||||||
|
|
||||||
|
|
||||||
class Engine:
|
class Engine:
|
||||||
def __init__(self, engine_path):
|
def __init__(self, engine_path):
|
||||||
self.engine_path = engine_path
|
self.engine_path = engine_path
|
||||||
@@ -110,10 +110,8 @@ class Engine:
|
|||||||
onnx_path,
|
onnx_path,
|
||||||
fp16,
|
fp16,
|
||||||
input_profile=None,
|
input_profile=None,
|
||||||
enable_preview=False,
|
|
||||||
enable_all_tactics=False,
|
enable_all_tactics=False,
|
||||||
timing_cache=None,
|
timing_cache=None,
|
||||||
workspace_size=0,
|
|
||||||
):
|
):
|
||||||
logger.warning(f"Building TensorRT engine for {onnx_path}: {self.engine_path}")
|
logger.warning(f"Building TensorRT engine for {onnx_path}: {self.engine_path}")
|
||||||
p = Profile()
|
p = Profile()
|
||||||
@@ -122,20 +120,13 @@ class Engine:
|
|||||||
assert len(dims) == 3
|
assert len(dims) == 3
|
||||||
p.add(name, min=dims[0], opt=dims[1], max=dims[2])
|
p.add(name, min=dims[0], opt=dims[1], max=dims[2])
|
||||||
|
|
||||||
config_kwargs = {}
|
extra_build_args = {}
|
||||||
|
|
||||||
config_kwargs["preview_features"] = [trt.PreviewFeature.DISABLE_EXTERNAL_TACTIC_SOURCES_FOR_CORE_0805]
|
|
||||||
if enable_preview:
|
|
||||||
# Faster dynamic shapes made optional since it increases engine build time.
|
|
||||||
config_kwargs["preview_features"].append(trt.PreviewFeature.FASTER_DYNAMIC_SHAPES_0805)
|
|
||||||
if workspace_size > 0:
|
|
||||||
config_kwargs["memory_pool_limits"] = {trt.MemoryPoolType.WORKSPACE: workspace_size}
|
|
||||||
if not enable_all_tactics:
|
if not enable_all_tactics:
|
||||||
config_kwargs["tactic_sources"] = []
|
extra_build_args["tactic_sources"] = []
|
||||||
|
|
||||||
engine = engine_from_network(
|
engine = engine_from_network(
|
||||||
network_from_onnx_path(onnx_path, flags=[trt.OnnxParserFlag.NATIVE_INSTANCENORM]),
|
network_from_onnx_path(onnx_path, flags=[trt.OnnxParserFlag.NATIVE_INSTANCENORM]),
|
||||||
config=CreateConfig(fp16=fp16, profiles=[p], load_timing_cache=timing_cache, **config_kwargs),
|
config=CreateConfig(fp16=fp16, profiles=[p], load_timing_cache=timing_cache, **extra_build_args),
|
||||||
save_timing_cache=timing_cache,
|
save_timing_cache=timing_cache,
|
||||||
)
|
)
|
||||||
save_engine(engine, path=self.engine_path)
|
save_engine(engine, path=self.engine_path)
|
||||||
@@ -148,28 +139,24 @@ class Engine:
|
|||||||
self.context = self.engine.create_execution_context()
|
self.context = self.engine.create_execution_context()
|
||||||
|
|
||||||
def allocate_buffers(self, shape_dict=None, device="cuda"):
|
def allocate_buffers(self, shape_dict=None, device="cuda"):
|
||||||
for idx in range(trt_util.get_bindings_per_profile(self.engine)):
|
for binding in range(self.engine.num_io_tensors):
|
||||||
binding = self.engine[idx]
|
name = self.engine.get_tensor_name(binding)
|
||||||
if shape_dict and binding in shape_dict:
|
if shape_dict and name in shape_dict:
|
||||||
shape = shape_dict[binding]
|
shape = shape_dict[name]
|
||||||
else:
|
else:
|
||||||
shape = self.engine.get_binding_shape(binding)
|
shape = self.engine.get_tensor_shape(name)
|
||||||
dtype = trt.nptype(self.engine.get_binding_dtype(binding))
|
dtype = trt.nptype(self.engine.get_tensor_dtype(name))
|
||||||
if self.engine.binding_is_input(binding):
|
if self.engine.get_tensor_mode(name) == trt.TensorIOMode.INPUT:
|
||||||
self.context.set_binding_shape(idx, shape)
|
self.context.set_input_shape(name, shape)
|
||||||
tensor = torch.empty(tuple(shape), dtype=numpy_to_torch_dtype_dict[dtype]).to(device=device)
|
tensor = torch.empty(tuple(shape), dtype=numpy_to_torch_dtype_dict[dtype]).to(device=device)
|
||||||
self.tensors[binding] = tensor
|
self.tensors[name] = tensor
|
||||||
self.buffers[binding] = cuda.DeviceView(ptr=tensor.data_ptr(), shape=shape, dtype=dtype)
|
|
||||||
|
|
||||||
def infer(self, feed_dict, stream):
|
def infer(self, feed_dict, stream):
|
||||||
start_binding, end_binding = trt_util.get_active_profile_bindings(self.context)
|
|
||||||
# shallow copy of ordered dict
|
|
||||||
device_buffers = copy(self.buffers)
|
|
||||||
for name, buf in feed_dict.items():
|
for name, buf in feed_dict.items():
|
||||||
assert isinstance(buf, cuda.DeviceView)
|
self.tensors[name].copy_(buf)
|
||||||
device_buffers[name] = buf
|
for name, tensor in self.tensors.items():
|
||||||
bindings = [0] * start_binding + [buf.ptr for buf in device_buffers.values()]
|
self.context.set_tensor_address(name, tensor.data_ptr())
|
||||||
noerror = self.context.execute_async_v2(bindings=bindings, stream_handle=stream.ptr)
|
noerror = self.context.execute_async_v3(stream)
|
||||||
if not noerror:
|
if not noerror:
|
||||||
raise ValueError("ERROR: inference failed.")
|
raise ValueError("ERROR: inference failed.")
|
||||||
|
|
||||||
@@ -310,10 +297,8 @@ def build_engines(
|
|||||||
force_engine_rebuild=False,
|
force_engine_rebuild=False,
|
||||||
static_batch=False,
|
static_batch=False,
|
||||||
static_shape=True,
|
static_shape=True,
|
||||||
enable_preview=False,
|
|
||||||
enable_all_tactics=False,
|
enable_all_tactics=False,
|
||||||
timing_cache=None,
|
timing_cache=None,
|
||||||
max_workspace_size=0,
|
|
||||||
):
|
):
|
||||||
built_engines = {}
|
built_engines = {}
|
||||||
if not os.path.isdir(onnx_dir):
|
if not os.path.isdir(onnx_dir):
|
||||||
@@ -378,9 +363,7 @@ def build_engines(
|
|||||||
static_batch=static_batch,
|
static_batch=static_batch,
|
||||||
static_shape=static_shape,
|
static_shape=static_shape,
|
||||||
),
|
),
|
||||||
enable_preview=enable_preview,
|
|
||||||
timing_cache=timing_cache,
|
timing_cache=timing_cache,
|
||||||
workspace_size=max_workspace_size,
|
|
||||||
)
|
)
|
||||||
built_engines[model_name] = engine
|
built_engines[model_name] = engine
|
||||||
|
|
||||||
@@ -588,11 +571,11 @@ def make_VAE(model, device, max_batch_size, embedding_dim, inpaint=False):
|
|||||||
return VAE(model, device=device, max_batch_size=max_batch_size, embedding_dim=embedding_dim)
|
return VAE(model, device=device, max_batch_size=max_batch_size, embedding_dim=embedding_dim)
|
||||||
|
|
||||||
|
|
||||||
class TensorRTStableDiffusionPipeline(StableDiffusionPipeline):
|
class TensorRTStableDiffusionPipeline(DiffusionPipeline):
|
||||||
r"""
|
r"""
|
||||||
Pipeline for text-to-image generation using TensorRT accelerated Stable Diffusion.
|
Pipeline for text-to-image generation using TensorRT accelerated Stable Diffusion.
|
||||||
|
|
||||||
This model inherits from [`StableDiffusionPipeline`]. Check the superclass documentation for the generic methods the
|
This model inherits from [`DiffusionPipeline`]. Check the superclass documentation for the generic methods the
|
||||||
library implements for all the pipelines (such as downloading or saving, running on a particular device, etc.)
|
library implements for all the pipelines (such as downloading or saving, running on a particular device, etc.)
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@@ -612,10 +595,12 @@ class TensorRTStableDiffusionPipeline(StableDiffusionPipeline):
|
|||||||
safety_checker ([`StableDiffusionSafetyChecker`]):
|
safety_checker ([`StableDiffusionSafetyChecker`]):
|
||||||
Classification module that estimates whether generated images could be considered offensive or harmful.
|
Classification module that estimates whether generated images could be considered offensive or harmful.
|
||||||
Please, refer to the [model card](https://huggingface.co/runwayml/stable-diffusion-v1-5) for details.
|
Please, refer to the [model card](https://huggingface.co/runwayml/stable-diffusion-v1-5) for details.
|
||||||
feature_extractor ([`CLIPFeatureExtractor`]):
|
feature_extractor ([`CLIPImageProcessor`]):
|
||||||
Model that extracts features from generated images to be used as inputs for the `safety_checker`.
|
Model that extracts features from generated images to be used as inputs for the `safety_checker`.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
_optional_components = ["safety_checker", "feature_extractor"]
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
vae: AutoencoderKL,
|
vae: AutoencoderKL,
|
||||||
@@ -624,7 +609,7 @@ class TensorRTStableDiffusionPipeline(StableDiffusionPipeline):
|
|||||||
unet: UNet2DConditionModel,
|
unet: UNet2DConditionModel,
|
||||||
scheduler: DDIMScheduler,
|
scheduler: DDIMScheduler,
|
||||||
safety_checker: StableDiffusionSafetyChecker,
|
safety_checker: StableDiffusionSafetyChecker,
|
||||||
feature_extractor: CLIPFeatureExtractor,
|
feature_extractor: CLIPImageProcessor,
|
||||||
image_encoder: CLIPVisionModelWithProjection = None,
|
image_encoder: CLIPVisionModelWithProjection = None,
|
||||||
requires_safety_checker: bool = True,
|
requires_safety_checker: bool = True,
|
||||||
stages=["clip", "unet", "vae"],
|
stages=["clip", "unet", "vae"],
|
||||||
@@ -632,28 +617,90 @@ class TensorRTStableDiffusionPipeline(StableDiffusionPipeline):
|
|||||||
image_width: int = 768,
|
image_width: int = 768,
|
||||||
max_batch_size: int = 16,
|
max_batch_size: int = 16,
|
||||||
# ONNX export parameters
|
# ONNX export parameters
|
||||||
onnx_opset: int = 17,
|
onnx_opset: int = 18,
|
||||||
onnx_dir: str = "onnx",
|
onnx_dir: str = "onnx",
|
||||||
# TensorRT engine build parameters
|
# TensorRT engine build parameters
|
||||||
engine_dir: str = "engine",
|
engine_dir: str = "engine",
|
||||||
build_preview_features: bool = True,
|
|
||||||
force_engine_rebuild: bool = False,
|
force_engine_rebuild: bool = False,
|
||||||
timing_cache: str = "timing_cache",
|
timing_cache: str = "timing_cache",
|
||||||
):
|
):
|
||||||
super().__init__(
|
super().__init__()
|
||||||
vae,
|
|
||||||
text_encoder,
|
if hasattr(scheduler.config, "steps_offset") and scheduler.config.steps_offset != 1:
|
||||||
tokenizer,
|
deprecation_message = (
|
||||||
unet,
|
f"The configuration file of this scheduler: {scheduler} is outdated. `steps_offset`"
|
||||||
scheduler,
|
f" should be set to 1 instead of {scheduler.config.steps_offset}. Please make sure "
|
||||||
|
"to update the config accordingly as leaving `steps_offset` might led to incorrect results"
|
||||||
|
" in future versions. If you have downloaded this checkpoint from the Hugging Face Hub,"
|
||||||
|
" it would be very nice if you could open a Pull request for the `scheduler/scheduler_config.json`"
|
||||||
|
" file"
|
||||||
|
)
|
||||||
|
deprecate("steps_offset!=1", "1.0.0", deprecation_message, standard_warn=False)
|
||||||
|
new_config = dict(scheduler.config)
|
||||||
|
new_config["steps_offset"] = 1
|
||||||
|
scheduler._internal_dict = FrozenDict(new_config)
|
||||||
|
|
||||||
|
if hasattr(scheduler.config, "clip_sample") and scheduler.config.clip_sample is True:
|
||||||
|
deprecation_message = (
|
||||||
|
f"The configuration file of this scheduler: {scheduler} has not set the configuration `clip_sample`."
|
||||||
|
" `clip_sample` should be set to False in the configuration file. Please make sure to update the"
|
||||||
|
" config accordingly as not setting `clip_sample` in the config might lead to incorrect results in"
|
||||||
|
" future versions. If you have downloaded this checkpoint from the Hugging Face Hub, it would be very"
|
||||||
|
" nice if you could open a Pull request for the `scheduler/scheduler_config.json` file"
|
||||||
|
)
|
||||||
|
deprecate("clip_sample not set", "1.0.0", deprecation_message, standard_warn=False)
|
||||||
|
new_config = dict(scheduler.config)
|
||||||
|
new_config["clip_sample"] = False
|
||||||
|
scheduler._internal_dict = FrozenDict(new_config)
|
||||||
|
|
||||||
|
if safety_checker is None and requires_safety_checker:
|
||||||
|
logger.warning(
|
||||||
|
f"You have disabled the safety checker for {self.__class__} by passing `safety_checker=None`. Ensure"
|
||||||
|
" that you abide to the conditions of the Stable Diffusion license and do not expose unfiltered"
|
||||||
|
" results in services or applications open to the public. Both the diffusers team and Hugging Face"
|
||||||
|
" strongly recommend to keep the safety filter enabled in all public facing circumstances, disabling"
|
||||||
|
" it only for use-cases that involve analyzing network behavior or auditing its results. For more"
|
||||||
|
" information, please have a look at https://github.com/huggingface/diffusers/pull/254 ."
|
||||||
|
)
|
||||||
|
|
||||||
|
if safety_checker is not None and feature_extractor is None:
|
||||||
|
raise ValueError(
|
||||||
|
"Make sure to define a feature extractor when loading {self.__class__} if you want to use the safety"
|
||||||
|
" checker. If you do not want to use the safety checker, you can pass `'safety_checker=None'` instead."
|
||||||
|
)
|
||||||
|
|
||||||
|
is_unet_version_less_0_9_0 = hasattr(unet.config, "_diffusers_version") and version.parse(
|
||||||
|
version.parse(unet.config._diffusers_version).base_version
|
||||||
|
) < version.parse("0.9.0.dev0")
|
||||||
|
is_unet_sample_size_less_64 = hasattr(unet.config, "sample_size") and unet.config.sample_size < 64
|
||||||
|
if is_unet_version_less_0_9_0 and is_unet_sample_size_less_64:
|
||||||
|
deprecation_message = (
|
||||||
|
"The configuration file of the unet has set the default `sample_size` to smaller than"
|
||||||
|
" 64 which seems highly unlikely. If your checkpoint is a fine-tuned version of any of the"
|
||||||
|
" following: \n- CompVis/stable-diffusion-v1-4 \n- CompVis/stable-diffusion-v1-3 \n-"
|
||||||
|
" CompVis/stable-diffusion-v1-2 \n- CompVis/stable-diffusion-v1-1 \n- runwayml/stable-diffusion-v1-5"
|
||||||
|
" \n- runwayml/stable-diffusion-inpainting \n you should change 'sample_size' to 64 in the"
|
||||||
|
" configuration file. Please make sure to update the config accordingly as leaving `sample_size=32`"
|
||||||
|
" in the config might lead to incorrect results in future versions. If you have downloaded this"
|
||||||
|
" checkpoint from the Hugging Face Hub, it would be very nice if you could open a Pull request for"
|
||||||
|
" the `unet/config.json` file"
|
||||||
|
)
|
||||||
|
deprecate("sample_size<64", "1.0.0", deprecation_message, standard_warn=False)
|
||||||
|
new_config = dict(unet.config)
|
||||||
|
new_config["sample_size"] = 64
|
||||||
|
unet._internal_dict = FrozenDict(new_config)
|
||||||
|
|
||||||
|
self.register_modules(
|
||||||
|
vae=vae,
|
||||||
|
text_encoder=text_encoder,
|
||||||
|
tokenizer=tokenizer,
|
||||||
|
unet=unet,
|
||||||
|
scheduler=scheduler,
|
||||||
safety_checker=safety_checker,
|
safety_checker=safety_checker,
|
||||||
feature_extractor=feature_extractor,
|
feature_extractor=feature_extractor,
|
||||||
image_encoder=image_encoder,
|
image_encoder=image_encoder,
|
||||||
requires_safety_checker=requires_safety_checker,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
self.vae.forward = self.vae.decode
|
|
||||||
|
|
||||||
self.stages = stages
|
self.stages = stages
|
||||||
self.image_height, self.image_width = image_height, image_width
|
self.image_height, self.image_width = image_height, image_width
|
||||||
self.inpaint = False
|
self.inpaint = False
|
||||||
@@ -664,7 +711,6 @@ class TensorRTStableDiffusionPipeline(StableDiffusionPipeline):
|
|||||||
self.timing_cache = timing_cache
|
self.timing_cache = timing_cache
|
||||||
self.build_static_batch = False
|
self.build_static_batch = False
|
||||||
self.build_dynamic_shape = False
|
self.build_dynamic_shape = False
|
||||||
self.build_preview_features = build_preview_features
|
|
||||||
|
|
||||||
self.max_batch_size = max_batch_size
|
self.max_batch_size = max_batch_size
|
||||||
# TODO: Restrict batch size to 4 for larger image dimensions as a WAR for TensorRT limitation.
|
# TODO: Restrict batch size to 4 for larger image dimensions as a WAR for TensorRT limitation.
|
||||||
@@ -675,6 +721,11 @@ class TensorRTStableDiffusionPipeline(StableDiffusionPipeline):
|
|||||||
self.models = {} # loaded in __loadModels()
|
self.models = {} # loaded in __loadModels()
|
||||||
self.engine = {} # loaded in build_engines()
|
self.engine = {} # loaded in build_engines()
|
||||||
|
|
||||||
|
self.vae.forward = self.vae.decode
|
||||||
|
self.vae_scale_factor = 2 ** (len(self.vae.config.block_out_channels) - 1)
|
||||||
|
self.image_processor = VaeImageProcessor(vae_scale_factor=self.vae_scale_factor)
|
||||||
|
self.register_to_config(requires_safety_checker=requires_safety_checker)
|
||||||
|
|
||||||
def __loadModels(self):
|
def __loadModels(self):
|
||||||
# Load pipeline models
|
# Load pipeline models
|
||||||
self.embedding_dim = self.text_encoder.config.hidden_size
|
self.embedding_dim = self.text_encoder.config.hidden_size
|
||||||
@@ -691,6 +742,75 @@ class TensorRTStableDiffusionPipeline(StableDiffusionPipeline):
|
|||||||
if "vae" in self.stages:
|
if "vae" in self.stages:
|
||||||
self.models["vae"] = make_VAE(self.vae, **models_args)
|
self.models["vae"] = make_VAE(self.vae, **models_args)
|
||||||
|
|
||||||
|
# Copied from diffusers.pipelines.stable_diffusion.pipeline_stable_diffusion.StableDiffusionPipeline.prepare_latents
|
||||||
|
def prepare_latents(
|
||||||
|
self,
|
||||||
|
batch_size: int,
|
||||||
|
num_channels_latents: int,
|
||||||
|
height: int,
|
||||||
|
width: int,
|
||||||
|
dtype: torch.dtype,
|
||||||
|
device: torch.device,
|
||||||
|
generator: Union[torch.Generator, List[torch.Generator]],
|
||||||
|
latents: Optional[torch.Tensor] = None,
|
||||||
|
) -> torch.Tensor:
|
||||||
|
r"""
|
||||||
|
Prepare the latent vectors for diffusion.
|
||||||
|
Args:
|
||||||
|
batch_size (int): The number of samples in the batch.
|
||||||
|
num_channels_latents (int): The number of channels in the latent vectors.
|
||||||
|
height (int): The height of the latent vectors.
|
||||||
|
width (int): The width of the latent vectors.
|
||||||
|
dtype (torch.dtype): The data type of the latent vectors.
|
||||||
|
device (torch.device): The device to place the latent vectors on.
|
||||||
|
generator (Union[torch.Generator, List[torch.Generator]]): The generator(s) to use for random number generation.
|
||||||
|
latents (Optional[torch.Tensor]): The pre-existing latent vectors. If None, new latent vectors will be generated.
|
||||||
|
Returns:
|
||||||
|
torch.Tensor: The prepared latent vectors.
|
||||||
|
"""
|
||||||
|
shape = (batch_size, num_channels_latents, height // self.vae_scale_factor, width // self.vae_scale_factor)
|
||||||
|
if isinstance(generator, list) and len(generator) != batch_size:
|
||||||
|
raise ValueError(
|
||||||
|
f"You have passed a list of generators of length {len(generator)}, but requested an effective batch"
|
||||||
|
f" size of {batch_size}. Make sure the batch size matches the length of the generators."
|
||||||
|
)
|
||||||
|
|
||||||
|
if latents is None:
|
||||||
|
latents = randn_tensor(shape, generator=generator, device=device, dtype=dtype)
|
||||||
|
else:
|
||||||
|
latents = latents.to(device)
|
||||||
|
|
||||||
|
# scale the initial noise by the standard deviation required by the scheduler
|
||||||
|
latents = latents * self.scheduler.init_noise_sigma
|
||||||
|
return latents
|
||||||
|
|
||||||
|
# Copied from diffusers.pipelines.stable_diffusion.pipeline_stable_diffusion.StableDiffusionPipeline.run_safety_checker
|
||||||
|
def run_safety_checker(
|
||||||
|
self, image: Union[torch.Tensor, PIL.Image.Image], device: torch.device, dtype: torch.dtype
|
||||||
|
) -> Tuple[Union[torch.Tensor, PIL.Image.Image], Optional[bool]]:
|
||||||
|
r"""
|
||||||
|
Runs the safety checker on the given image.
|
||||||
|
Args:
|
||||||
|
image (Union[torch.Tensor, PIL.Image.Image]): The input image to be checked.
|
||||||
|
device (torch.device): The device to run the safety checker on.
|
||||||
|
dtype (torch.dtype): The data type of the input image.
|
||||||
|
Returns:
|
||||||
|
(image, has_nsfw_concept) Tuple[Union[torch.Tensor, PIL.Image.Image], Optional[bool]]: A tuple containing the processed image and
|
||||||
|
a boolean indicating whether the image has a NSFW (Not Safe for Work) concept.
|
||||||
|
"""
|
||||||
|
if self.safety_checker is None:
|
||||||
|
has_nsfw_concept = None
|
||||||
|
else:
|
||||||
|
if torch.is_tensor(image):
|
||||||
|
feature_extractor_input = self.image_processor.postprocess(image, output_type="pil")
|
||||||
|
else:
|
||||||
|
feature_extractor_input = self.image_processor.numpy_to_pil(image)
|
||||||
|
safety_checker_input = self.feature_extractor(feature_extractor_input, return_tensors="pt").to(device)
|
||||||
|
image, has_nsfw_concept = self.safety_checker(
|
||||||
|
images=image, clip_input=safety_checker_input.pixel_values.to(dtype)
|
||||||
|
)
|
||||||
|
return image, has_nsfw_concept
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@validate_hf_hub_args
|
@validate_hf_hub_args
|
||||||
def set_cached_folder(cls, pretrained_model_name_or_path: Optional[Union[str, os.PathLike]], **kwargs):
|
def set_cached_folder(cls, pretrained_model_name_or_path: Optional[Union[str, os.PathLike]], **kwargs):
|
||||||
@@ -738,7 +858,6 @@ class TensorRTStableDiffusionPipeline(StableDiffusionPipeline):
|
|||||||
force_engine_rebuild=self.force_engine_rebuild,
|
force_engine_rebuild=self.force_engine_rebuild,
|
||||||
static_batch=self.build_static_batch,
|
static_batch=self.build_static_batch,
|
||||||
static_shape=not self.build_dynamic_shape,
|
static_shape=not self.build_dynamic_shape,
|
||||||
enable_preview=self.build_preview_features,
|
|
||||||
timing_cache=self.timing_cache,
|
timing_cache=self.timing_cache,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -769,9 +888,8 @@ class TensorRTStableDiffusionPipeline(StableDiffusionPipeline):
|
|||||||
.to(self.torch_device)
|
.to(self.torch_device)
|
||||||
)
|
)
|
||||||
|
|
||||||
text_input_ids_inp = device_view(text_input_ids)
|
|
||||||
# NOTE: output tensor for CLIP must be cloned because it will be overwritten when called again for negative prompt
|
# NOTE: output tensor for CLIP must be cloned because it will be overwritten when called again for negative prompt
|
||||||
text_embeddings = runEngine(self.engine["clip"], {"input_ids": text_input_ids_inp}, self.stream)[
|
text_embeddings = runEngine(self.engine["clip"], {"input_ids": text_input_ids}, self.stream)[
|
||||||
"text_embeddings"
|
"text_embeddings"
|
||||||
].clone()
|
].clone()
|
||||||
|
|
||||||
@@ -787,8 +905,7 @@ class TensorRTStableDiffusionPipeline(StableDiffusionPipeline):
|
|||||||
.input_ids.type(torch.int32)
|
.input_ids.type(torch.int32)
|
||||||
.to(self.torch_device)
|
.to(self.torch_device)
|
||||||
)
|
)
|
||||||
uncond_input_ids_inp = device_view(uncond_input_ids)
|
uncond_embeddings = runEngine(self.engine["clip"], {"input_ids": uncond_input_ids}, self.stream)[
|
||||||
uncond_embeddings = runEngine(self.engine["clip"], {"input_ids": uncond_input_ids_inp}, self.stream)[
|
|
||||||
"text_embeddings"
|
"text_embeddings"
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -812,18 +929,15 @@ class TensorRTStableDiffusionPipeline(StableDiffusionPipeline):
|
|||||||
# Predict the noise residual
|
# Predict the noise residual
|
||||||
timestep_float = timestep.float() if timestep.dtype != torch.float32 else timestep
|
timestep_float = timestep.float() if timestep.dtype != torch.float32 else timestep
|
||||||
|
|
||||||
sample_inp = device_view(latent_model_input)
|
|
||||||
timestep_inp = device_view(timestep_float)
|
|
||||||
embeddings_inp = device_view(text_embeddings)
|
|
||||||
noise_pred = runEngine(
|
noise_pred = runEngine(
|
||||||
self.engine["unet"],
|
self.engine["unet"],
|
||||||
{"sample": sample_inp, "timestep": timestep_inp, "encoder_hidden_states": embeddings_inp},
|
{"sample": latent_model_input, "timestep": timestep_float, "encoder_hidden_states": text_embeddings},
|
||||||
self.stream,
|
self.stream,
|
||||||
)["latent"]
|
)["latent"]
|
||||||
|
|
||||||
# Perform guidance
|
# Perform guidance
|
||||||
noise_pred_uncond, noise_pred_text = noise_pred.chunk(2)
|
noise_pred_uncond, noise_pred_text = noise_pred.chunk(2)
|
||||||
noise_pred = noise_pred_uncond + self.guidance_scale * (noise_pred_text - noise_pred_uncond)
|
noise_pred = noise_pred_uncond + self._guidance_scale * (noise_pred_text - noise_pred_uncond)
|
||||||
|
|
||||||
latents = self.scheduler.step(noise_pred, timestep, latents).prev_sample
|
latents = self.scheduler.step(noise_pred, timestep, latents).prev_sample
|
||||||
|
|
||||||
@@ -831,12 +945,12 @@ class TensorRTStableDiffusionPipeline(StableDiffusionPipeline):
|
|||||||
return latents
|
return latents
|
||||||
|
|
||||||
def __decode_latent(self, latents):
|
def __decode_latent(self, latents):
|
||||||
images = runEngine(self.engine["vae"], {"latent": device_view(latents)}, self.stream)["images"]
|
images = runEngine(self.engine["vae"], {"latent": latents}, self.stream)["images"]
|
||||||
images = (images / 2 + 0.5).clamp(0, 1)
|
images = (images / 2 + 0.5).clamp(0, 1)
|
||||||
return images.cpu().permute(0, 2, 3, 1).float().numpy()
|
return images.cpu().permute(0, 2, 3, 1).float().numpy()
|
||||||
|
|
||||||
def __loadResources(self, image_height, image_width, batch_size):
|
def __loadResources(self, image_height, image_width, batch_size):
|
||||||
self.stream = cuda.Stream()
|
self.stream = cudart.cudaStreamCreate()[1]
|
||||||
|
|
||||||
# Allocate buffers for TensorRT engine bindings
|
# Allocate buffers for TensorRT engine bindings
|
||||||
for model_name, obj in self.models.items():
|
for model_name, obj in self.models.items():
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ if is_wandb_available():
|
|||||||
import wandb
|
import wandb
|
||||||
|
|
||||||
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
||||||
check_min_version("0.30.0.dev0")
|
check_min_version("0.30.0")
|
||||||
|
|
||||||
logger = get_logger(__name__)
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ if is_wandb_available():
|
|||||||
import wandb
|
import wandb
|
||||||
|
|
||||||
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
||||||
check_min_version("0.30.0.dev0")
|
check_min_version("0.30.0")
|
||||||
|
|
||||||
logger = get_logger(__name__)
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ if is_wandb_available():
|
|||||||
import wandb
|
import wandb
|
||||||
|
|
||||||
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
||||||
check_min_version("0.30.0.dev0")
|
check_min_version("0.30.0")
|
||||||
|
|
||||||
logger = get_logger(__name__)
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ if is_wandb_available():
|
|||||||
import wandb
|
import wandb
|
||||||
|
|
||||||
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
||||||
check_min_version("0.30.0.dev0")
|
check_min_version("0.30.0")
|
||||||
|
|
||||||
logger = get_logger(__name__)
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ if is_wandb_available():
|
|||||||
import wandb
|
import wandb
|
||||||
|
|
||||||
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
||||||
check_min_version("0.30.0.dev0")
|
check_min_version("0.30.0")
|
||||||
|
|
||||||
logger = get_logger(__name__)
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ if is_wandb_available():
|
|||||||
import wandb
|
import wandb
|
||||||
|
|
||||||
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
||||||
check_min_version("0.30.0.dev0")
|
check_min_version("0.30.0")
|
||||||
|
|
||||||
logger = get_logger(__name__)
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ if is_wandb_available():
|
|||||||
import wandb
|
import wandb
|
||||||
|
|
||||||
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
||||||
check_min_version("0.30.0.dev0")
|
check_min_version("0.30.0")
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ if is_wandb_available():
|
|||||||
import wandb
|
import wandb
|
||||||
|
|
||||||
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
||||||
check_min_version("0.30.0.dev0")
|
check_min_version("0.30.0")
|
||||||
|
|
||||||
logger = get_logger(__name__)
|
logger = get_logger(__name__)
|
||||||
if is_torch_npu_available():
|
if is_torch_npu_available():
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ from diffusers.utils.import_utils import is_xformers_available
|
|||||||
|
|
||||||
|
|
||||||
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
||||||
check_min_version("0.30.0.dev0")
|
check_min_version("0.30.0")
|
||||||
|
|
||||||
logger = get_logger(__name__)
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ if is_wandb_available():
|
|||||||
import wandb
|
import wandb
|
||||||
|
|
||||||
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
||||||
check_min_version("0.30.0.dev0")
|
check_min_version("0.30.0")
|
||||||
|
|
||||||
logger = get_logger(__name__)
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ from diffusers.utils import check_min_version
|
|||||||
|
|
||||||
|
|
||||||
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
||||||
check_min_version("0.30.0.dev0")
|
check_min_version("0.30.0")
|
||||||
|
|
||||||
# Cache compiled models across invocations of this script.
|
# Cache compiled models across invocations of this script.
|
||||||
cc.initialize_cache(os.path.expanduser("~/.cache/jax/compilation_cache"))
|
cc.initialize_cache(os.path.expanduser("~/.cache/jax/compilation_cache"))
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ if is_wandb_available():
|
|||||||
import wandb
|
import wandb
|
||||||
|
|
||||||
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
||||||
check_min_version("0.30.0.dev0")
|
check_min_version("0.30.0")
|
||||||
|
|
||||||
logger = get_logger(__name__)
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ if is_wandb_available():
|
|||||||
import wandb
|
import wandb
|
||||||
|
|
||||||
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
||||||
check_min_version("0.30.0.dev0")
|
check_min_version("0.30.0")
|
||||||
|
|
||||||
logger = get_logger(__name__)
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
@@ -1271,7 +1271,7 @@ def main(args):
|
|||||||
lora_state_dict = StableDiffusion3Pipeline.lora_state_dict(input_dir)
|
lora_state_dict = StableDiffusion3Pipeline.lora_state_dict(input_dir)
|
||||||
|
|
||||||
transformer_state_dict = {
|
transformer_state_dict = {
|
||||||
f'{k.replace("transformer.", "")}': v for k, v in lora_state_dict.items() if k.startswith("unet.")
|
f'{k.replace("transformer.", "")}': v for k, v in lora_state_dict.items() if k.startswith("transformer.")
|
||||||
}
|
}
|
||||||
transformer_state_dict = convert_unet_state_dict_to_peft(transformer_state_dict)
|
transformer_state_dict = convert_unet_state_dict_to_peft(transformer_state_dict)
|
||||||
incompatible_keys = set_peft_model_state_dict(transformer_, transformer_state_dict, adapter_name="default")
|
incompatible_keys = set_peft_model_state_dict(transformer_, transformer_state_dict, adapter_name="default")
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ if is_wandb_available():
|
|||||||
import wandb
|
import wandb
|
||||||
|
|
||||||
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
||||||
check_min_version("0.30.0.dev0")
|
check_min_version("0.30.0")
|
||||||
|
|
||||||
logger = get_logger(__name__)
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ if is_wandb_available():
|
|||||||
import wandb
|
import wandb
|
||||||
|
|
||||||
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
||||||
check_min_version("0.30.0.dev0")
|
check_min_version("0.30.0")
|
||||||
|
|
||||||
logger = get_logger(__name__)
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ if is_wandb_available():
|
|||||||
import wandb
|
import wandb
|
||||||
|
|
||||||
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
||||||
check_min_version("0.30.0.dev0")
|
check_min_version("0.30.0")
|
||||||
|
|
||||||
logger = get_logger(__name__, log_level="INFO")
|
logger = get_logger(__name__, log_level="INFO")
|
||||||
|
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ if is_wandb_available():
|
|||||||
import wandb
|
import wandb
|
||||||
|
|
||||||
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
||||||
check_min_version("0.30.0.dev0")
|
check_min_version("0.30.0")
|
||||||
|
|
||||||
logger = get_logger(__name__, log_level="INFO")
|
logger = get_logger(__name__, log_level="INFO")
|
||||||
|
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ if is_wandb_available():
|
|||||||
|
|
||||||
|
|
||||||
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
||||||
check_min_version("0.30.0.dev0")
|
check_min_version("0.30.0")
|
||||||
|
|
||||||
logger = get_logger(__name__, log_level="INFO")
|
logger = get_logger(__name__, log_level="INFO")
|
||||||
|
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ from diffusers.utils import check_min_version, is_wandb_available
|
|||||||
|
|
||||||
|
|
||||||
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
||||||
check_min_version("0.30.0.dev0")
|
check_min_version("0.30.0")
|
||||||
|
|
||||||
logger = get_logger(__name__, log_level="INFO")
|
logger = get_logger(__name__, log_level="INFO")
|
||||||
|
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ from diffusers.utils import check_min_version, is_wandb_available
|
|||||||
|
|
||||||
|
|
||||||
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
||||||
check_min_version("0.30.0.dev0")
|
check_min_version("0.30.0")
|
||||||
|
|
||||||
logger = get_logger(__name__, log_level="INFO")
|
logger = get_logger(__name__, log_level="INFO")
|
||||||
|
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ if is_wandb_available():
|
|||||||
|
|
||||||
|
|
||||||
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
||||||
check_min_version("0.30.0.dev0")
|
check_min_version("0.30.0")
|
||||||
|
|
||||||
logger = get_logger(__name__, log_level="INFO")
|
logger = get_logger(__name__, log_level="INFO")
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ from PIL import Image
|
|||||||
from torch.utils.data import default_collate
|
from torch.utils.data import default_collate
|
||||||
from torchvision import transforms
|
from torchvision import transforms
|
||||||
from tqdm.auto import tqdm
|
from tqdm.auto import tqdm
|
||||||
from transformers import AutoTokenizer, DPTFeatureExtractor, DPTForDepthEstimation, PretrainedConfig
|
from transformers import AutoTokenizer, DPTForDepthEstimation, DPTImageProcessor, PretrainedConfig
|
||||||
from webdataset.tariterators import (
|
from webdataset.tariterators import (
|
||||||
base_plus_ext,
|
base_plus_ext,
|
||||||
tar_file_expander,
|
tar_file_expander,
|
||||||
@@ -205,7 +205,7 @@ class Text2ImageDataset:
|
|||||||
pin_memory: bool = False,
|
pin_memory: bool = False,
|
||||||
persistent_workers: bool = False,
|
persistent_workers: bool = False,
|
||||||
control_type: str = "canny",
|
control_type: str = "canny",
|
||||||
feature_extractor: Optional[DPTFeatureExtractor] = None,
|
feature_extractor: Optional[DPTImageProcessor] = None,
|
||||||
):
|
):
|
||||||
if not isinstance(train_shards_path_or_url, str):
|
if not isinstance(train_shards_path_or_url, str):
|
||||||
train_shards_path_or_url = [list(braceexpand(urls)) for urls in train_shards_path_or_url]
|
train_shards_path_or_url = [list(braceexpand(urls)) for urls in train_shards_path_or_url]
|
||||||
@@ -1011,7 +1011,7 @@ def main(args):
|
|||||||
controlnet = pre_controlnet
|
controlnet = pre_controlnet
|
||||||
|
|
||||||
if args.control_type == "depth":
|
if args.control_type == "depth":
|
||||||
feature_extractor = DPTFeatureExtractor.from_pretrained("Intel/dpt-hybrid-midas")
|
feature_extractor = DPTImageProcessor.from_pretrained("Intel/dpt-hybrid-midas")
|
||||||
depth_model = DPTForDepthEstimation.from_pretrained("Intel/dpt-hybrid-midas")
|
depth_model = DPTForDepthEstimation.from_pretrained("Intel/dpt-hybrid-midas")
|
||||||
depth_model.requires_grad_(False)
|
depth_model.requires_grad_(False)
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -45,7 +45,7 @@
|
|||||||
" UniPCMultistepScheduler,\n",
|
" UniPCMultistepScheduler,\n",
|
||||||
" EulerDiscreteScheduler,\n",
|
" EulerDiscreteScheduler,\n",
|
||||||
")\n",
|
")\n",
|
||||||
"from transformers import CLIPFeatureExtractor, CLIPTextModel, CLIPTokenizer\n",
|
"from transformers import CLIPImageProcessor, CLIPTextModel, CLIPTokenizer\n",
|
||||||
"# pretrained_model_name_or_path = 'masterful/gligen-1-4-generation-text-box'\n",
|
"# pretrained_model_name_or_path = 'masterful/gligen-1-4-generation-text-box'\n",
|
||||||
"\n",
|
"\n",
|
||||||
"pretrained_model_name_or_path = '/root/data/zhizhonghuang/checkpoints/models--masterful--gligen-1-4-generation-text-box/snapshots/d2820dc1e9ba6ca082051ce79cfd3eb468ae2c83'\n",
|
"pretrained_model_name_or_path = '/root/data/zhizhonghuang/checkpoints/models--masterful--gligen-1-4-generation-text-box/snapshots/d2820dc1e9ba6ca082051ce79cfd3eb468ae2c83'\n",
|
||||||
|
|||||||
@@ -46,5 +46,4 @@ pipe.enable_model_cpu_offload()
|
|||||||
# generate image
|
# generate image
|
||||||
generator = torch.manual_seed(0)
|
generator = torch.manual_seed(0)
|
||||||
image = pipe("a tortoise", num_inference_steps=20, generator=generator, image_pair=[image_a,image_b], image=query).images[0]
|
image = pipe("a tortoise", num_inference_steps=20, generator=generator, image_pair=[image_a,image_b], image=query).images[0]
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|||||||
+1
-1
@@ -2051,7 +2051,7 @@ if __name__ == "__main__":
|
|||||||
default=512,
|
default=512,
|
||||||
type=int,
|
type=int,
|
||||||
help=(
|
help=(
|
||||||
"The image size that the model was trained on. Use 512 for Stable Diffusion v1.X and Stable Siffusion v2"
|
"The image size that the model was trained on. Use 512 for Stable Diffusion v1.X and Stable Diffusion v2"
|
||||||
" Base. Use 768 for Stable Diffusion v2."
|
" Base. Use 768 for Stable Diffusion v2."
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1253,7 +1253,7 @@ class PromptDiffusionPipeline(
|
|||||||
)
|
)
|
||||||
|
|
||||||
if guess_mode and self.do_classifier_free_guidance:
|
if guess_mode and self.do_classifier_free_guidance:
|
||||||
# Infered ControlNet only for the conditional batch.
|
# Inferred ControlNet only for the conditional batch.
|
||||||
# To apply the output of ControlNet to both the unconditional and conditional batches,
|
# To apply the output of ControlNet to both the unconditional and conditional batches,
|
||||||
# add 0 to the unconditional batch to keep it unchanged.
|
# add 0 to the unconditional batch to keep it unchanged.
|
||||||
down_block_res_samples = [torch.cat([torch.zeros_like(d), d]) for d in down_block_res_samples]
|
down_block_res_samples = [torch.cat([torch.zeros_like(d), d]) for d in down_block_res_samples]
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ from typing import Callable, List, Optional, Union
|
|||||||
import torch
|
import torch
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
from retriever import Retriever, normalize_images, preprocess_images
|
from retriever import Retriever, normalize_images, preprocess_images
|
||||||
from transformers import CLIPFeatureExtractor, CLIPModel, CLIPTokenizer
|
from transformers import CLIPImageProcessor, CLIPModel, CLIPTokenizer
|
||||||
|
|
||||||
from diffusers import (
|
from diffusers import (
|
||||||
AutoencoderKL,
|
AutoencoderKL,
|
||||||
@@ -47,7 +47,7 @@ class RDMPipeline(DiffusionPipeline, StableDiffusionMixin):
|
|||||||
scheduler ([`SchedulerMixin`]):
|
scheduler ([`SchedulerMixin`]):
|
||||||
A scheduler to be used in combination with `unet` to denoise the encoded image latents. Can be one of
|
A scheduler to be used in combination with `unet` to denoise the encoded image latents. Can be one of
|
||||||
[`DDIMScheduler`], [`LMSDiscreteScheduler`], or [`PNDMScheduler`].
|
[`DDIMScheduler`], [`LMSDiscreteScheduler`], or [`PNDMScheduler`].
|
||||||
feature_extractor ([`CLIPFeatureExtractor`]):
|
feature_extractor ([`CLIPImageProcessor`]):
|
||||||
Model that extracts features from generated images to be used as inputs for the `safety_checker`.
|
Model that extracts features from generated images to be used as inputs for the `safety_checker`.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -65,7 +65,7 @@ class RDMPipeline(DiffusionPipeline, StableDiffusionMixin):
|
|||||||
EulerAncestralDiscreteScheduler,
|
EulerAncestralDiscreteScheduler,
|
||||||
DPMSolverMultistepScheduler,
|
DPMSolverMultistepScheduler,
|
||||||
],
|
],
|
||||||
feature_extractor: CLIPFeatureExtractor,
|
feature_extractor: CLIPImageProcessor,
|
||||||
retriever: Optional[Retriever] = None,
|
retriever: Optional[Retriever] = None,
|
||||||
):
|
):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import numpy as np
|
|||||||
import torch
|
import torch
|
||||||
from datasets import Dataset, load_dataset
|
from datasets import Dataset, load_dataset
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
from transformers import CLIPFeatureExtractor, CLIPModel, PretrainedConfig
|
from transformers import CLIPImageProcessor, CLIPModel, PretrainedConfig
|
||||||
|
|
||||||
from diffusers import logging
|
from diffusers import logging
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@ def normalize_images(images: List[Image.Image]):
|
|||||||
return images
|
return images
|
||||||
|
|
||||||
|
|
||||||
def preprocess_images(images: List[np.array], feature_extractor: CLIPFeatureExtractor) -> torch.Tensor:
|
def preprocess_images(images: List[np.array], feature_extractor: CLIPImageProcessor) -> torch.Tensor:
|
||||||
"""
|
"""
|
||||||
Preprocesses a list of images into a batch of tensors.
|
Preprocesses a list of images into a batch of tensors.
|
||||||
|
|
||||||
@@ -95,14 +95,12 @@ class Index:
|
|||||||
def build_index(
|
def build_index(
|
||||||
self,
|
self,
|
||||||
model=None,
|
model=None,
|
||||||
feature_extractor: CLIPFeatureExtractor = None,
|
feature_extractor: CLIPImageProcessor = None,
|
||||||
torch_dtype=torch.float32,
|
torch_dtype=torch.float32,
|
||||||
):
|
):
|
||||||
if not self.index_initialized:
|
if not self.index_initialized:
|
||||||
model = model or CLIPModel.from_pretrained(self.config.clip_name_or_path).to(dtype=torch_dtype)
|
model = model or CLIPModel.from_pretrained(self.config.clip_name_or_path).to(dtype=torch_dtype)
|
||||||
feature_extractor = feature_extractor or CLIPFeatureExtractor.from_pretrained(
|
feature_extractor = feature_extractor or CLIPImageProcessor.from_pretrained(self.config.clip_name_or_path)
|
||||||
self.config.clip_name_or_path
|
|
||||||
)
|
|
||||||
self.dataset = get_dataset_with_emb_from_clip_model(
|
self.dataset = get_dataset_with_emb_from_clip_model(
|
||||||
self.dataset,
|
self.dataset,
|
||||||
model,
|
model,
|
||||||
@@ -136,7 +134,7 @@ class Retriever:
|
|||||||
index: Index = None,
|
index: Index = None,
|
||||||
dataset: Dataset = None,
|
dataset: Dataset = None,
|
||||||
model=None,
|
model=None,
|
||||||
feature_extractor: CLIPFeatureExtractor = None,
|
feature_extractor: CLIPImageProcessor = None,
|
||||||
):
|
):
|
||||||
self.config = config
|
self.config = config
|
||||||
self.index = index or self._build_index(config, dataset, model=model, feature_extractor=feature_extractor)
|
self.index = index or self._build_index(config, dataset, model=model, feature_extractor=feature_extractor)
|
||||||
@@ -148,7 +146,7 @@ class Retriever:
|
|||||||
index: Index = None,
|
index: Index = None,
|
||||||
dataset: Dataset = None,
|
dataset: Dataset = None,
|
||||||
model=None,
|
model=None,
|
||||||
feature_extractor: CLIPFeatureExtractor = None,
|
feature_extractor: CLIPImageProcessor = None,
|
||||||
**kwargs,
|
**kwargs,
|
||||||
):
|
):
|
||||||
config = kwargs.pop("config", None) or IndexConfig.from_pretrained(retriever_name_or_path, **kwargs)
|
config = kwargs.pop("config", None) or IndexConfig.from_pretrained(retriever_name_or_path, **kwargs)
|
||||||
@@ -156,7 +154,7 @@ class Retriever:
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _build_index(
|
def _build_index(
|
||||||
config: IndexConfig, dataset: Dataset = None, model=None, feature_extractor: CLIPFeatureExtractor = None
|
config: IndexConfig, dataset: Dataset = None, model=None, feature_extractor: CLIPImageProcessor = None
|
||||||
):
|
):
|
||||||
dataset = dataset or load_dataset(config.dataset_name)
|
dataset = dataset or load_dataset(config.dataset_name)
|
||||||
dataset = dataset[config.dataset_set]
|
dataset = dataset[config.dataset_set]
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ cc.initialize_cache("/tmp/sdxl_cache")
|
|||||||
NUM_DEVICES = jax.device_count()
|
NUM_DEVICES = jax.device_count()
|
||||||
|
|
||||||
# 1. Let's start by downloading the model and loading it into our pipeline class
|
# 1. Let's start by downloading the model and loading it into our pipeline class
|
||||||
# Adhering to JAX's functional approach, the model's parameters are returned seperatetely and
|
# Adhering to JAX's functional approach, the model's parameters are returned separately and
|
||||||
# will have to be passed to the pipeline during inference
|
# will have to be passed to the pipeline during inference
|
||||||
pipeline, params = FlaxStableDiffusionXLPipeline.from_pretrained(
|
pipeline, params = FlaxStableDiffusionXLPipeline.from_pretrained(
|
||||||
"stabilityai/stable-diffusion-xl-base-1.0", revision="refs/pr/95", split_head_dim=True
|
"stabilityai/stable-diffusion-xl-base-1.0", revision="refs/pr/95", split_head_dim=True
|
||||||
@@ -69,7 +69,7 @@ def replicate_all(prompt_ids, neg_prompt_ids, seed):
|
|||||||
# to the function and tell JAX which are static arguments, that is, arguments that
|
# to the function and tell JAX which are static arguments, that is, arguments that
|
||||||
# are known at compile time and won't change. In our case, it is num_inference_steps,
|
# are known at compile time and won't change. In our case, it is num_inference_steps,
|
||||||
# height, width and return_latents.
|
# height, width and return_latents.
|
||||||
# Once the function is compiled, these parameters are ommited from future calls and
|
# Once the function is compiled, these parameters are omitted from future calls and
|
||||||
# cannot be changed without modifying the code and recompiling.
|
# cannot be changed without modifying the code and recompiling.
|
||||||
def aot_compile(
|
def aot_compile(
|
||||||
prompt=default_prompt,
|
prompt=default_prompt,
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ if is_wandb_available():
|
|||||||
import wandb
|
import wandb
|
||||||
|
|
||||||
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
||||||
check_min_version("0.30.0.dev0")
|
check_min_version("0.30.0")
|
||||||
|
|
||||||
logger = get_logger(__name__)
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ if is_wandb_available():
|
|||||||
|
|
||||||
|
|
||||||
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
||||||
check_min_version("0.30.0.dev0")
|
check_min_version("0.30.0")
|
||||||
|
|
||||||
logger = get_logger(__name__, log_level="INFO")
|
logger = get_logger(__name__, log_level="INFO")
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ from diffusers.utils import check_min_version
|
|||||||
|
|
||||||
|
|
||||||
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
||||||
check_min_version("0.30.0.dev0")
|
check_min_version("0.30.0")
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ if is_wandb_available():
|
|||||||
import wandb
|
import wandb
|
||||||
|
|
||||||
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
||||||
check_min_version("0.30.0.dev0")
|
check_min_version("0.30.0")
|
||||||
|
|
||||||
logger = get_logger(__name__, log_level="INFO")
|
logger = get_logger(__name__, log_level="INFO")
|
||||||
|
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ if is_wandb_available():
|
|||||||
import wandb
|
import wandb
|
||||||
|
|
||||||
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
||||||
check_min_version("0.30.0.dev0")
|
check_min_version("0.30.0")
|
||||||
|
|
||||||
logger = get_logger(__name__)
|
logger = get_logger(__name__)
|
||||||
if is_torch_npu_available():
|
if is_torch_npu_available():
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ from diffusers.utils.torch_utils import is_compiled_module
|
|||||||
|
|
||||||
|
|
||||||
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
||||||
check_min_version("0.30.0.dev0")
|
check_min_version("0.30.0")
|
||||||
|
|
||||||
logger = get_logger(__name__)
|
logger = get_logger(__name__)
|
||||||
if is_torch_npu_available():
|
if is_torch_npu_available():
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ else:
|
|||||||
|
|
||||||
|
|
||||||
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
||||||
check_min_version("0.30.0.dev0")
|
check_min_version("0.30.0")
|
||||||
|
|
||||||
logger = get_logger(__name__)
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ else:
|
|||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
||||||
check_min_version("0.30.0.dev0")
|
check_min_version("0.30.0")
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ else:
|
|||||||
|
|
||||||
|
|
||||||
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
||||||
check_min_version("0.30.0.dev0")
|
check_min_version("0.30.0")
|
||||||
|
|
||||||
logger = get_logger(__name__)
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ from diffusers.utils.import_utils import is_xformers_available
|
|||||||
|
|
||||||
|
|
||||||
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
||||||
check_min_version("0.30.0.dev0")
|
check_min_version("0.30.0")
|
||||||
|
|
||||||
logger = get_logger(__name__, log_level="INFO")
|
logger = get_logger(__name__, log_level="INFO")
|
||||||
|
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ if is_wandb_available():
|
|||||||
import wandb
|
import wandb
|
||||||
|
|
||||||
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
||||||
check_min_version("0.30.0.dev0")
|
check_min_version("0.30.0")
|
||||||
|
|
||||||
logger = get_logger(__name__, log_level="INFO")
|
logger = get_logger(__name__, log_level="INFO")
|
||||||
|
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ if is_wandb_available():
|
|||||||
|
|
||||||
|
|
||||||
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
||||||
check_min_version("0.30.0.dev0")
|
check_min_version("0.30.0")
|
||||||
|
|
||||||
logger = get_logger(__name__, log_level="INFO")
|
logger = get_logger(__name__, log_level="INFO")
|
||||||
|
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ if is_wandb_available():
|
|||||||
|
|
||||||
|
|
||||||
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
# Will error if the minimal version of diffusers is not installed. Remove at your own risks.
|
||||||
check_min_version("0.30.0.dev0")
|
check_min_version("0.30.0")
|
||||||
|
|
||||||
logger = get_logger(__name__, log_level="INFO")
|
logger = get_logger(__name__, log_level="INFO")
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,268 @@
|
|||||||
|
import argparse
|
||||||
|
from typing import Any, Dict
|
||||||
|
|
||||||
|
import torch
|
||||||
|
from transformers import T5EncoderModel, T5Tokenizer
|
||||||
|
|
||||||
|
from diffusers import AutoencoderKLCogVideoX, CogVideoXDDIMScheduler, CogVideoXPipeline, CogVideoXTransformer3DModel
|
||||||
|
|
||||||
|
|
||||||
|
def reassign_query_key_value_inplace(key: str, state_dict: Dict[str, Any]):
|
||||||
|
to_q_key = key.replace("query_key_value", "to_q")
|
||||||
|
to_k_key = key.replace("query_key_value", "to_k")
|
||||||
|
to_v_key = key.replace("query_key_value", "to_v")
|
||||||
|
to_q, to_k, to_v = torch.chunk(state_dict[key], chunks=3, dim=0)
|
||||||
|
state_dict[to_q_key] = to_q
|
||||||
|
state_dict[to_k_key] = to_k
|
||||||
|
state_dict[to_v_key] = to_v
|
||||||
|
state_dict.pop(key)
|
||||||
|
|
||||||
|
|
||||||
|
def reassign_query_key_layernorm_inplace(key: str, state_dict: Dict[str, Any]):
|
||||||
|
layer_id, weight_or_bias = key.split(".")[-2:]
|
||||||
|
|
||||||
|
if "query" in key:
|
||||||
|
new_key = f"transformer_blocks.{layer_id}.attn1.norm_q.{weight_or_bias}"
|
||||||
|
elif "key" in key:
|
||||||
|
new_key = f"transformer_blocks.{layer_id}.attn1.norm_k.{weight_or_bias}"
|
||||||
|
|
||||||
|
state_dict[new_key] = state_dict.pop(key)
|
||||||
|
|
||||||
|
|
||||||
|
def reassign_adaln_norm_inplace(key: str, state_dict: Dict[str, Any]):
|
||||||
|
layer_id, _, weight_or_bias = key.split(".")[-3:]
|
||||||
|
|
||||||
|
weights_or_biases = state_dict[key].chunk(12, dim=0)
|
||||||
|
norm1_weights_or_biases = torch.cat(weights_or_biases[0:3] + weights_or_biases[6:9])
|
||||||
|
norm2_weights_or_biases = torch.cat(weights_or_biases[3:6] + weights_or_biases[9:12])
|
||||||
|
|
||||||
|
norm1_key = f"transformer_blocks.{layer_id}.norm1.linear.{weight_or_bias}"
|
||||||
|
state_dict[norm1_key] = norm1_weights_or_biases
|
||||||
|
|
||||||
|
norm2_key = f"transformer_blocks.{layer_id}.norm2.linear.{weight_or_bias}"
|
||||||
|
state_dict[norm2_key] = norm2_weights_or_biases
|
||||||
|
|
||||||
|
state_dict.pop(key)
|
||||||
|
|
||||||
|
|
||||||
|
def remove_keys_inplace(key: str, state_dict: Dict[str, Any]):
|
||||||
|
state_dict.pop(key)
|
||||||
|
|
||||||
|
|
||||||
|
def replace_up_keys_inplace(key: str, state_dict: Dict[str, Any]):
|
||||||
|
key_split = key.split(".")
|
||||||
|
layer_index = int(key_split[2])
|
||||||
|
replace_layer_index = 4 - 1 - layer_index
|
||||||
|
|
||||||
|
key_split[1] = "up_blocks"
|
||||||
|
key_split[2] = str(replace_layer_index)
|
||||||
|
new_key = ".".join(key_split)
|
||||||
|
|
||||||
|
state_dict[new_key] = state_dict.pop(key)
|
||||||
|
|
||||||
|
|
||||||
|
TRANSFORMER_KEYS_RENAME_DICT = {
|
||||||
|
"transformer.final_layernorm": "norm_final",
|
||||||
|
"transformer": "transformer_blocks",
|
||||||
|
"attention": "attn1",
|
||||||
|
"mlp": "ff.net",
|
||||||
|
"dense_h_to_4h": "0.proj",
|
||||||
|
"dense_4h_to_h": "2",
|
||||||
|
".layers": "",
|
||||||
|
"dense": "to_out.0",
|
||||||
|
"input_layernorm": "norm1.norm",
|
||||||
|
"post_attn1_layernorm": "norm2.norm",
|
||||||
|
"time_embed.0": "time_embedding.linear_1",
|
||||||
|
"time_embed.2": "time_embedding.linear_2",
|
||||||
|
"mixins.patch_embed": "patch_embed",
|
||||||
|
"mixins.final_layer.norm_final": "norm_out.norm",
|
||||||
|
"mixins.final_layer.linear": "proj_out",
|
||||||
|
"mixins.final_layer.adaLN_modulation.1": "norm_out.linear",
|
||||||
|
}
|
||||||
|
|
||||||
|
TRANSFORMER_SPECIAL_KEYS_REMAP = {
|
||||||
|
"query_key_value": reassign_query_key_value_inplace,
|
||||||
|
"query_layernorm_list": reassign_query_key_layernorm_inplace,
|
||||||
|
"key_layernorm_list": reassign_query_key_layernorm_inplace,
|
||||||
|
"adaln_layer.adaLN_modulations": reassign_adaln_norm_inplace,
|
||||||
|
"embed_tokens": remove_keys_inplace,
|
||||||
|
"freqs_sin": remove_keys_inplace,
|
||||||
|
"freqs_cos": remove_keys_inplace,
|
||||||
|
"position_embedding": remove_keys_inplace,
|
||||||
|
}
|
||||||
|
|
||||||
|
VAE_KEYS_RENAME_DICT = {
|
||||||
|
"block.": "resnets.",
|
||||||
|
"down.": "down_blocks.",
|
||||||
|
"downsample": "downsamplers.0",
|
||||||
|
"upsample": "upsamplers.0",
|
||||||
|
"nin_shortcut": "conv_shortcut",
|
||||||
|
"encoder.mid.block_1": "encoder.mid_block.resnets.0",
|
||||||
|
"encoder.mid.block_2": "encoder.mid_block.resnets.1",
|
||||||
|
"decoder.mid.block_1": "decoder.mid_block.resnets.0",
|
||||||
|
"decoder.mid.block_2": "decoder.mid_block.resnets.1",
|
||||||
|
}
|
||||||
|
|
||||||
|
VAE_SPECIAL_KEYS_REMAP = {
|
||||||
|
"loss": remove_keys_inplace,
|
||||||
|
"up.": replace_up_keys_inplace,
|
||||||
|
}
|
||||||
|
|
||||||
|
TOKENIZER_MAX_LENGTH = 226
|
||||||
|
|
||||||
|
|
||||||
|
def get_state_dict(saved_dict: Dict[str, Any]) -> Dict[str, Any]:
|
||||||
|
state_dict = saved_dict
|
||||||
|
if "model" in saved_dict.keys():
|
||||||
|
state_dict = state_dict["model"]
|
||||||
|
if "module" in saved_dict.keys():
|
||||||
|
state_dict = state_dict["module"]
|
||||||
|
if "state_dict" in saved_dict.keys():
|
||||||
|
state_dict = state_dict["state_dict"]
|
||||||
|
return state_dict
|
||||||
|
|
||||||
|
|
||||||
|
def update_state_dict_inplace(state_dict: Dict[str, Any], old_key: str, new_key: str) -> Dict[str, Any]:
|
||||||
|
state_dict[new_key] = state_dict.pop(old_key)
|
||||||
|
|
||||||
|
|
||||||
|
def convert_transformer(
|
||||||
|
ckpt_path: str,
|
||||||
|
num_layers: int,
|
||||||
|
num_attention_heads: int,
|
||||||
|
use_rotary_positional_embeddings: bool,
|
||||||
|
dtype: torch.dtype,
|
||||||
|
):
|
||||||
|
PREFIX_KEY = "model.diffusion_model."
|
||||||
|
|
||||||
|
original_state_dict = get_state_dict(torch.load(ckpt_path, map_location="cpu", mmap=True))
|
||||||
|
transformer = CogVideoXTransformer3DModel(
|
||||||
|
num_layers=num_layers,
|
||||||
|
num_attention_heads=num_attention_heads,
|
||||||
|
use_rotary_positional_embeddings=use_rotary_positional_embeddings,
|
||||||
|
).to(dtype=dtype)
|
||||||
|
|
||||||
|
for key in list(original_state_dict.keys()):
|
||||||
|
new_key = key[len(PREFIX_KEY) :]
|
||||||
|
for replace_key, rename_key in TRANSFORMER_KEYS_RENAME_DICT.items():
|
||||||
|
new_key = new_key.replace(replace_key, rename_key)
|
||||||
|
update_state_dict_inplace(original_state_dict, key, new_key)
|
||||||
|
|
||||||
|
for key in list(original_state_dict.keys()):
|
||||||
|
for special_key, handler_fn_inplace in TRANSFORMER_SPECIAL_KEYS_REMAP.items():
|
||||||
|
if special_key not in key:
|
||||||
|
continue
|
||||||
|
handler_fn_inplace(key, original_state_dict)
|
||||||
|
|
||||||
|
transformer.load_state_dict(original_state_dict, strict=True)
|
||||||
|
return transformer
|
||||||
|
|
||||||
|
|
||||||
|
def convert_vae(ckpt_path: str, scaling_factor: float, dtype: torch.dtype):
|
||||||
|
original_state_dict = get_state_dict(torch.load(ckpt_path, map_location="cpu", mmap=True))
|
||||||
|
vae = AutoencoderKLCogVideoX(scaling_factor=scaling_factor).to(dtype=dtype)
|
||||||
|
|
||||||
|
for key in list(original_state_dict.keys()):
|
||||||
|
new_key = key[:]
|
||||||
|
for replace_key, rename_key in VAE_KEYS_RENAME_DICT.items():
|
||||||
|
new_key = new_key.replace(replace_key, rename_key)
|
||||||
|
update_state_dict_inplace(original_state_dict, key, new_key)
|
||||||
|
|
||||||
|
for key in list(original_state_dict.keys()):
|
||||||
|
for special_key, handler_fn_inplace in VAE_SPECIAL_KEYS_REMAP.items():
|
||||||
|
if special_key not in key:
|
||||||
|
continue
|
||||||
|
handler_fn_inplace(key, original_state_dict)
|
||||||
|
|
||||||
|
vae.load_state_dict(original_state_dict, strict=True)
|
||||||
|
return vae
|
||||||
|
|
||||||
|
|
||||||
|
def get_args():
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument(
|
||||||
|
"--transformer_ckpt_path", type=str, default=None, help="Path to original transformer checkpoint"
|
||||||
|
)
|
||||||
|
parser.add_argument("--vae_ckpt_path", type=str, default=None, help="Path to original vae checkpoint")
|
||||||
|
parser.add_argument("--output_path", type=str, required=True, help="Path where converted model should be saved")
|
||||||
|
parser.add_argument("--fp16", action="store_true", default=False, help="Whether to save the model weights in fp16")
|
||||||
|
parser.add_argument("--bf16", action="store_true", default=False, help="Whether to save the model weights in bf16")
|
||||||
|
parser.add_argument(
|
||||||
|
"--push_to_hub", action="store_true", default=False, help="Whether to push to HF Hub after saving"
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--text_encoder_cache_dir", type=str, default=None, help="Path to text encoder cache directory"
|
||||||
|
)
|
||||||
|
# For CogVideoX-2B, num_layers is 30. For 5B, it is 42
|
||||||
|
parser.add_argument("--num_layers", type=int, default=30, help="Number of transformer blocks")
|
||||||
|
# For CogVideoX-2B, num_attention_heads is 30. For 5B, it is 48
|
||||||
|
parser.add_argument("--num_attention_heads", type=int, default=30, help="Number of attention heads")
|
||||||
|
# For CogVideoX-2B, use_rotary_positional_embeddings is False. For 5B, it is True
|
||||||
|
parser.add_argument(
|
||||||
|
"--use_rotary_positional_embeddings", action="store_true", default=False, help="Whether to use RoPE or not"
|
||||||
|
)
|
||||||
|
# For CogVideoX-2B, scaling_factor is 1.15258426. For 5B, it is 0.7
|
||||||
|
parser.add_argument("--scaling_factor", type=float, default=1.15258426, help="Scaling factor in the VAE")
|
||||||
|
# For CogVideoX-2B, snr_shift_scale is 3.0. For 5B, it is 1.0
|
||||||
|
parser.add_argument("--snr_shift_scale", type=float, default=3.0, help="Scaling factor in the VAE")
|
||||||
|
return parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
args = get_args()
|
||||||
|
|
||||||
|
transformer = None
|
||||||
|
vae = None
|
||||||
|
|
||||||
|
if args.fp16 and args.bf16:
|
||||||
|
raise ValueError("You cannot pass both --fp16 and --bf16 at the same time.")
|
||||||
|
|
||||||
|
dtype = torch.float16 if args.fp16 else torch.bfloat16 if args.bf16 else torch.float32
|
||||||
|
|
||||||
|
if args.transformer_ckpt_path is not None:
|
||||||
|
transformer = convert_transformer(
|
||||||
|
args.transformer_ckpt_path,
|
||||||
|
args.num_layers,
|
||||||
|
args.num_attention_heads,
|
||||||
|
args.use_rotary_positional_embeddings,
|
||||||
|
dtype,
|
||||||
|
)
|
||||||
|
if args.vae_ckpt_path is not None:
|
||||||
|
vae = convert_vae(args.vae_ckpt_path, args.scaling_factor, dtype)
|
||||||
|
|
||||||
|
text_encoder_id = "google/t5-v1_1-xxl"
|
||||||
|
tokenizer = T5Tokenizer.from_pretrained(text_encoder_id, model_max_length=TOKENIZER_MAX_LENGTH)
|
||||||
|
text_encoder = T5EncoderModel.from_pretrained(text_encoder_id, cache_dir=args.text_encoder_cache_dir)
|
||||||
|
|
||||||
|
# Apparently, the conversion does not work any more without this :shrug:
|
||||||
|
for param in text_encoder.parameters():
|
||||||
|
param.data = param.data.contiguous()
|
||||||
|
|
||||||
|
scheduler = CogVideoXDDIMScheduler.from_config(
|
||||||
|
{
|
||||||
|
"snr_shift_scale": args.snr_shift_scale,
|
||||||
|
"beta_end": 0.012,
|
||||||
|
"beta_schedule": "scaled_linear",
|
||||||
|
"beta_start": 0.00085,
|
||||||
|
"clip_sample": False,
|
||||||
|
"num_train_timesteps": 1000,
|
||||||
|
"prediction_type": "v_prediction",
|
||||||
|
"rescale_betas_zero_snr": True,
|
||||||
|
"set_alpha_to_one": True,
|
||||||
|
"timestep_spacing": "trailing",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
pipe = CogVideoXPipeline(
|
||||||
|
tokenizer=tokenizer, text_encoder=text_encoder, vae=vae, transformer=transformer, scheduler=scheduler
|
||||||
|
)
|
||||||
|
|
||||||
|
if args.fp16:
|
||||||
|
pipe = pipe.to(dtype=torch.float16)
|
||||||
|
if args.bf16:
|
||||||
|
pipe = pipe.to(dtype=torch.bfloat16)
|
||||||
|
|
||||||
|
# We don't use variant here because the model must be run in fp16 (2B) or bf16 (5B). It would be weird
|
||||||
|
# for users to specify variant when the default is not fp32 and they want to run with the correct default (which
|
||||||
|
# is either fp16/bf16 here).
|
||||||
|
pipe.save_pretrained(args.output_path, safe_serialization=True, push_to_hub=args.push_to_hub)
|
||||||
@@ -0,0 +1,303 @@
|
|||||||
|
import argparse
|
||||||
|
from contextlib import nullcontext
|
||||||
|
|
||||||
|
import safetensors.torch
|
||||||
|
import torch
|
||||||
|
from accelerate import init_empty_weights
|
||||||
|
from huggingface_hub import hf_hub_download
|
||||||
|
|
||||||
|
from diffusers import AutoencoderKL, FluxTransformer2DModel
|
||||||
|
from diffusers.loaders.single_file_utils import convert_ldm_vae_checkpoint
|
||||||
|
from diffusers.utils.import_utils import is_accelerate_available
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
# Transformer
|
||||||
|
|
||||||
|
python scripts/convert_flux_to_diffusers.py \
|
||||||
|
--original_state_dict_repo_id "black-forest-labs/FLUX.1-schnell" \
|
||||||
|
--filename "flux1-schnell.sft"
|
||||||
|
--output_path "flux-schnell" \
|
||||||
|
--transformer
|
||||||
|
"""
|
||||||
|
|
||||||
|
"""
|
||||||
|
# VAE
|
||||||
|
|
||||||
|
python scripts/convert_flux_to_diffusers.py \
|
||||||
|
--original_state_dict_repo_id "black-forest-labs/FLUX.1-schnell" \
|
||||||
|
--filename "ae.sft"
|
||||||
|
--output_path "flux-schnell" \
|
||||||
|
--vae
|
||||||
|
"""
|
||||||
|
|
||||||
|
CTX = init_empty_weights if is_accelerate_available else nullcontext
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument("--original_state_dict_repo_id", default=None, type=str)
|
||||||
|
parser.add_argument("--filename", default="flux.safetensors", type=str)
|
||||||
|
parser.add_argument("--checkpoint_path", default=None, type=str)
|
||||||
|
parser.add_argument("--vae", action="store_true")
|
||||||
|
parser.add_argument("--transformer", action="store_true")
|
||||||
|
parser.add_argument("--output_path", type=str)
|
||||||
|
parser.add_argument("--dtype", type=str, default="bf16")
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
dtype = torch.bfloat16 if args.dtype == "bf16" else torch.float32
|
||||||
|
|
||||||
|
|
||||||
|
def load_original_checkpoint(args):
|
||||||
|
if args.original_state_dict_repo_id is not None:
|
||||||
|
ckpt_path = hf_hub_download(repo_id=args.original_state_dict_repo_id, filename=args.filename)
|
||||||
|
elif args.checkpoint_path is not None:
|
||||||
|
ckpt_path = args.checkpoint_path
|
||||||
|
else:
|
||||||
|
raise ValueError(" please provide either `original_state_dict_repo_id` or a local `checkpoint_path`")
|
||||||
|
|
||||||
|
original_state_dict = safetensors.torch.load_file(ckpt_path)
|
||||||
|
return original_state_dict
|
||||||
|
|
||||||
|
|
||||||
|
# in SD3 original implementation of AdaLayerNormContinuous, it split linear projection output into shift, scale;
|
||||||
|
# while in diffusers it split into scale, shift. Here we swap the linear projection weights in order to be able to use diffusers implementation
|
||||||
|
def swap_scale_shift(weight):
|
||||||
|
shift, scale = weight.chunk(2, dim=0)
|
||||||
|
new_weight = torch.cat([scale, shift], dim=0)
|
||||||
|
return new_weight
|
||||||
|
|
||||||
|
|
||||||
|
def convert_flux_transformer_checkpoint_to_diffusers(
|
||||||
|
original_state_dict, num_layers, num_single_layers, inner_dim, mlp_ratio=4.0
|
||||||
|
):
|
||||||
|
converted_state_dict = {}
|
||||||
|
|
||||||
|
## time_text_embed.timestep_embedder <- time_in
|
||||||
|
converted_state_dict["time_text_embed.timestep_embedder.linear_1.weight"] = original_state_dict.pop(
|
||||||
|
"time_in.in_layer.weight"
|
||||||
|
)
|
||||||
|
converted_state_dict["time_text_embed.timestep_embedder.linear_1.bias"] = original_state_dict.pop(
|
||||||
|
"time_in.in_layer.bias"
|
||||||
|
)
|
||||||
|
converted_state_dict["time_text_embed.timestep_embedder.linear_2.weight"] = original_state_dict.pop(
|
||||||
|
"time_in.out_layer.weight"
|
||||||
|
)
|
||||||
|
converted_state_dict["time_text_embed.timestep_embedder.linear_2.bias"] = original_state_dict.pop(
|
||||||
|
"time_in.out_layer.bias"
|
||||||
|
)
|
||||||
|
|
||||||
|
## time_text_embed.text_embedder <- vector_in
|
||||||
|
converted_state_dict["time_text_embed.text_embedder.linear_1.weight"] = original_state_dict.pop(
|
||||||
|
"vector_in.in_layer.weight"
|
||||||
|
)
|
||||||
|
converted_state_dict["time_text_embed.text_embedder.linear_1.bias"] = original_state_dict.pop(
|
||||||
|
"vector_in.in_layer.bias"
|
||||||
|
)
|
||||||
|
converted_state_dict["time_text_embed.text_embedder.linear_2.weight"] = original_state_dict.pop(
|
||||||
|
"vector_in.out_layer.weight"
|
||||||
|
)
|
||||||
|
converted_state_dict["time_text_embed.text_embedder.linear_2.bias"] = original_state_dict.pop(
|
||||||
|
"vector_in.out_layer.bias"
|
||||||
|
)
|
||||||
|
|
||||||
|
# guidance
|
||||||
|
has_guidance = any("guidance" in k for k in original_state_dict)
|
||||||
|
if has_guidance:
|
||||||
|
converted_state_dict["time_text_embed.guidance_embedder.linear_1.weight"] = original_state_dict.pop(
|
||||||
|
"guidance_in.in_layer.weight"
|
||||||
|
)
|
||||||
|
converted_state_dict["time_text_embed.guidance_embedder.linear_1.bias"] = original_state_dict.pop(
|
||||||
|
"guidance_in.in_layer.bias"
|
||||||
|
)
|
||||||
|
converted_state_dict["time_text_embed.guidance_embedder.linear_2.weight"] = original_state_dict.pop(
|
||||||
|
"guidance_in.out_layer.weight"
|
||||||
|
)
|
||||||
|
converted_state_dict["time_text_embed.guidance_embedder.linear_2.bias"] = original_state_dict.pop(
|
||||||
|
"guidance_in.out_layer.bias"
|
||||||
|
)
|
||||||
|
|
||||||
|
# context_embedder
|
||||||
|
converted_state_dict["context_embedder.weight"] = original_state_dict.pop("txt_in.weight")
|
||||||
|
converted_state_dict["context_embedder.bias"] = original_state_dict.pop("txt_in.bias")
|
||||||
|
|
||||||
|
# x_embedder
|
||||||
|
converted_state_dict["x_embedder.weight"] = original_state_dict.pop("img_in.weight")
|
||||||
|
converted_state_dict["x_embedder.bias"] = original_state_dict.pop("img_in.bias")
|
||||||
|
|
||||||
|
# double transformer blocks
|
||||||
|
for i in range(num_layers):
|
||||||
|
block_prefix = f"transformer_blocks.{i}."
|
||||||
|
# norms.
|
||||||
|
## norm1
|
||||||
|
converted_state_dict[f"{block_prefix}norm1.linear.weight"] = original_state_dict.pop(
|
||||||
|
f"double_blocks.{i}.img_mod.lin.weight"
|
||||||
|
)
|
||||||
|
converted_state_dict[f"{block_prefix}norm1.linear.bias"] = original_state_dict.pop(
|
||||||
|
f"double_blocks.{i}.img_mod.lin.bias"
|
||||||
|
)
|
||||||
|
## norm1_context
|
||||||
|
converted_state_dict[f"{block_prefix}norm1_context.linear.weight"] = original_state_dict.pop(
|
||||||
|
f"double_blocks.{i}.txt_mod.lin.weight"
|
||||||
|
)
|
||||||
|
converted_state_dict[f"{block_prefix}norm1_context.linear.bias"] = original_state_dict.pop(
|
||||||
|
f"double_blocks.{i}.txt_mod.lin.bias"
|
||||||
|
)
|
||||||
|
# Q, K, V
|
||||||
|
sample_q, sample_k, sample_v = torch.chunk(
|
||||||
|
original_state_dict.pop(f"double_blocks.{i}.img_attn.qkv.weight"), 3, dim=0
|
||||||
|
)
|
||||||
|
context_q, context_k, context_v = torch.chunk(
|
||||||
|
original_state_dict.pop(f"double_blocks.{i}.txt_attn.qkv.weight"), 3, dim=0
|
||||||
|
)
|
||||||
|
sample_q_bias, sample_k_bias, sample_v_bias = torch.chunk(
|
||||||
|
original_state_dict.pop(f"double_blocks.{i}.img_attn.qkv.bias"), 3, dim=0
|
||||||
|
)
|
||||||
|
context_q_bias, context_k_bias, context_v_bias = torch.chunk(
|
||||||
|
original_state_dict.pop(f"double_blocks.{i}.txt_attn.qkv.bias"), 3, dim=0
|
||||||
|
)
|
||||||
|
converted_state_dict[f"{block_prefix}attn.to_q.weight"] = torch.cat([sample_q])
|
||||||
|
converted_state_dict[f"{block_prefix}attn.to_q.bias"] = torch.cat([sample_q_bias])
|
||||||
|
converted_state_dict[f"{block_prefix}attn.to_k.weight"] = torch.cat([sample_k])
|
||||||
|
converted_state_dict[f"{block_prefix}attn.to_k.bias"] = torch.cat([sample_k_bias])
|
||||||
|
converted_state_dict[f"{block_prefix}attn.to_v.weight"] = torch.cat([sample_v])
|
||||||
|
converted_state_dict[f"{block_prefix}attn.to_v.bias"] = torch.cat([sample_v_bias])
|
||||||
|
converted_state_dict[f"{block_prefix}attn.add_q_proj.weight"] = torch.cat([context_q])
|
||||||
|
converted_state_dict[f"{block_prefix}attn.add_q_proj.bias"] = torch.cat([context_q_bias])
|
||||||
|
converted_state_dict[f"{block_prefix}attn.add_k_proj.weight"] = torch.cat([context_k])
|
||||||
|
converted_state_dict[f"{block_prefix}attn.add_k_proj.bias"] = torch.cat([context_k_bias])
|
||||||
|
converted_state_dict[f"{block_prefix}attn.add_v_proj.weight"] = torch.cat([context_v])
|
||||||
|
converted_state_dict[f"{block_prefix}attn.add_v_proj.bias"] = torch.cat([context_v_bias])
|
||||||
|
# qk_norm
|
||||||
|
converted_state_dict[f"{block_prefix}attn.norm_q.weight"] = original_state_dict.pop(
|
||||||
|
f"double_blocks.{i}.img_attn.norm.query_norm.scale"
|
||||||
|
)
|
||||||
|
converted_state_dict[f"{block_prefix}attn.norm_k.weight"] = original_state_dict.pop(
|
||||||
|
f"double_blocks.{i}.img_attn.norm.key_norm.scale"
|
||||||
|
)
|
||||||
|
converted_state_dict[f"{block_prefix}attn.norm_added_q.weight"] = original_state_dict.pop(
|
||||||
|
f"double_blocks.{i}.txt_attn.norm.query_norm.scale"
|
||||||
|
)
|
||||||
|
converted_state_dict[f"{block_prefix}attn.norm_added_k.weight"] = original_state_dict.pop(
|
||||||
|
f"double_blocks.{i}.txt_attn.norm.key_norm.scale"
|
||||||
|
)
|
||||||
|
# ff img_mlp
|
||||||
|
converted_state_dict[f"{block_prefix}ff.net.0.proj.weight"] = original_state_dict.pop(
|
||||||
|
f"double_blocks.{i}.img_mlp.0.weight"
|
||||||
|
)
|
||||||
|
converted_state_dict[f"{block_prefix}ff.net.0.proj.bias"] = original_state_dict.pop(
|
||||||
|
f"double_blocks.{i}.img_mlp.0.bias"
|
||||||
|
)
|
||||||
|
converted_state_dict[f"{block_prefix}ff.net.2.weight"] = original_state_dict.pop(
|
||||||
|
f"double_blocks.{i}.img_mlp.2.weight"
|
||||||
|
)
|
||||||
|
converted_state_dict[f"{block_prefix}ff.net.2.bias"] = original_state_dict.pop(
|
||||||
|
f"double_blocks.{i}.img_mlp.2.bias"
|
||||||
|
)
|
||||||
|
converted_state_dict[f"{block_prefix}ff_context.net.0.proj.weight"] = original_state_dict.pop(
|
||||||
|
f"double_blocks.{i}.txt_mlp.0.weight"
|
||||||
|
)
|
||||||
|
converted_state_dict[f"{block_prefix}ff_context.net.0.proj.bias"] = original_state_dict.pop(
|
||||||
|
f"double_blocks.{i}.txt_mlp.0.bias"
|
||||||
|
)
|
||||||
|
converted_state_dict[f"{block_prefix}ff_context.net.2.weight"] = original_state_dict.pop(
|
||||||
|
f"double_blocks.{i}.txt_mlp.2.weight"
|
||||||
|
)
|
||||||
|
converted_state_dict[f"{block_prefix}ff_context.net.2.bias"] = original_state_dict.pop(
|
||||||
|
f"double_blocks.{i}.txt_mlp.2.bias"
|
||||||
|
)
|
||||||
|
# output projections.
|
||||||
|
converted_state_dict[f"{block_prefix}attn.to_out.0.weight"] = original_state_dict.pop(
|
||||||
|
f"double_blocks.{i}.img_attn.proj.weight"
|
||||||
|
)
|
||||||
|
converted_state_dict[f"{block_prefix}attn.to_out.0.bias"] = original_state_dict.pop(
|
||||||
|
f"double_blocks.{i}.img_attn.proj.bias"
|
||||||
|
)
|
||||||
|
converted_state_dict[f"{block_prefix}attn.to_add_out.weight"] = original_state_dict.pop(
|
||||||
|
f"double_blocks.{i}.txt_attn.proj.weight"
|
||||||
|
)
|
||||||
|
converted_state_dict[f"{block_prefix}attn.to_add_out.bias"] = original_state_dict.pop(
|
||||||
|
f"double_blocks.{i}.txt_attn.proj.bias"
|
||||||
|
)
|
||||||
|
|
||||||
|
# single transfomer blocks
|
||||||
|
for i in range(num_single_layers):
|
||||||
|
block_prefix = f"single_transformer_blocks.{i}."
|
||||||
|
# norm.linear <- single_blocks.0.modulation.lin
|
||||||
|
converted_state_dict[f"{block_prefix}norm.linear.weight"] = original_state_dict.pop(
|
||||||
|
f"single_blocks.{i}.modulation.lin.weight"
|
||||||
|
)
|
||||||
|
converted_state_dict[f"{block_prefix}norm.linear.bias"] = original_state_dict.pop(
|
||||||
|
f"single_blocks.{i}.modulation.lin.bias"
|
||||||
|
)
|
||||||
|
# Q, K, V, mlp
|
||||||
|
mlp_hidden_dim = int(inner_dim * mlp_ratio)
|
||||||
|
split_size = (inner_dim, inner_dim, inner_dim, mlp_hidden_dim)
|
||||||
|
q, k, v, mlp = torch.split(original_state_dict.pop(f"single_blocks.{i}.linear1.weight"), split_size, dim=0)
|
||||||
|
q_bias, k_bias, v_bias, mlp_bias = torch.split(
|
||||||
|
original_state_dict.pop(f"single_blocks.{i}.linear1.bias"), split_size, dim=0
|
||||||
|
)
|
||||||
|
converted_state_dict[f"{block_prefix}attn.to_q.weight"] = torch.cat([q])
|
||||||
|
converted_state_dict[f"{block_prefix}attn.to_q.bias"] = torch.cat([q_bias])
|
||||||
|
converted_state_dict[f"{block_prefix}attn.to_k.weight"] = torch.cat([k])
|
||||||
|
converted_state_dict[f"{block_prefix}attn.to_k.bias"] = torch.cat([k_bias])
|
||||||
|
converted_state_dict[f"{block_prefix}attn.to_v.weight"] = torch.cat([v])
|
||||||
|
converted_state_dict[f"{block_prefix}attn.to_v.bias"] = torch.cat([v_bias])
|
||||||
|
converted_state_dict[f"{block_prefix}proj_mlp.weight"] = torch.cat([mlp])
|
||||||
|
converted_state_dict[f"{block_prefix}proj_mlp.bias"] = torch.cat([mlp_bias])
|
||||||
|
# qk norm
|
||||||
|
converted_state_dict[f"{block_prefix}attn.norm_q.weight"] = original_state_dict.pop(
|
||||||
|
f"single_blocks.{i}.norm.query_norm.scale"
|
||||||
|
)
|
||||||
|
converted_state_dict[f"{block_prefix}attn.norm_k.weight"] = original_state_dict.pop(
|
||||||
|
f"single_blocks.{i}.norm.key_norm.scale"
|
||||||
|
)
|
||||||
|
# output projections.
|
||||||
|
converted_state_dict[f"{block_prefix}proj_out.weight"] = original_state_dict.pop(
|
||||||
|
f"single_blocks.{i}.linear2.weight"
|
||||||
|
)
|
||||||
|
converted_state_dict[f"{block_prefix}proj_out.bias"] = original_state_dict.pop(
|
||||||
|
f"single_blocks.{i}.linear2.bias"
|
||||||
|
)
|
||||||
|
|
||||||
|
converted_state_dict["proj_out.weight"] = original_state_dict.pop("final_layer.linear.weight")
|
||||||
|
converted_state_dict["proj_out.bias"] = original_state_dict.pop("final_layer.linear.bias")
|
||||||
|
converted_state_dict["norm_out.linear.weight"] = swap_scale_shift(
|
||||||
|
original_state_dict.pop("final_layer.adaLN_modulation.1.weight")
|
||||||
|
)
|
||||||
|
converted_state_dict["norm_out.linear.bias"] = swap_scale_shift(
|
||||||
|
original_state_dict.pop("final_layer.adaLN_modulation.1.bias")
|
||||||
|
)
|
||||||
|
|
||||||
|
return converted_state_dict
|
||||||
|
|
||||||
|
|
||||||
|
def main(args):
|
||||||
|
original_ckpt = load_original_checkpoint(args)
|
||||||
|
has_guidance = any("guidance" in k for k in original_ckpt)
|
||||||
|
|
||||||
|
if args.transformer:
|
||||||
|
num_layers = 19
|
||||||
|
num_single_layers = 38
|
||||||
|
inner_dim = 3072
|
||||||
|
mlp_ratio = 4.0
|
||||||
|
converted_transformer_state_dict = convert_flux_transformer_checkpoint_to_diffusers(
|
||||||
|
original_ckpt, num_layers, num_single_layers, inner_dim, mlp_ratio=mlp_ratio
|
||||||
|
)
|
||||||
|
transformer = FluxTransformer2DModel(guidance_embeds=has_guidance)
|
||||||
|
transformer.load_state_dict(converted_transformer_state_dict, strict=True)
|
||||||
|
|
||||||
|
print(
|
||||||
|
f"Saving Flux Transformer in Diffusers format. Variant: {'guidance-distilled' if has_guidance else 'timestep-distilled'}"
|
||||||
|
)
|
||||||
|
transformer.to(dtype).save_pretrained(f"{args.output_path}/transformer")
|
||||||
|
|
||||||
|
if args.vae:
|
||||||
|
config = AutoencoderKL.load_config("stabilityai/stable-diffusion-3-medium-diffusers", subfolder="vae")
|
||||||
|
vae = AutoencoderKL.from_config(config, scaling_factor=0.3611, shift_factor=0.1159).to(torch.bfloat16)
|
||||||
|
|
||||||
|
converted_vae_state_dict = convert_ldm_vae_checkpoint(original_ckpt, vae.config)
|
||||||
|
vae.load_state_dict(converted_vae_state_dict, strict=True)
|
||||||
|
vae.to(dtype).save_pretrained(f"{args.output_path}/vae")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main(args)
|
||||||
@@ -42,7 +42,7 @@ if __name__ == "__main__":
|
|||||||
default=512,
|
default=512,
|
||||||
type=int,
|
type=int,
|
||||||
help=(
|
help=(
|
||||||
"The image size that the model was trained on. Use 512 for Stable Diffusion v1.X and Stable Siffusion v2"
|
"The image size that the model was trained on. Use 512 for Stable Diffusion v1.X and Stable Diffusion v2"
|
||||||
" Base. Use 768 for Stable Diffusion v2."
|
" Base. Use 768 for Stable Diffusion v2."
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ if __name__ == "__main__":
|
|||||||
default=None,
|
default=None,
|
||||||
type=int,
|
type=int,
|
||||||
help=(
|
help=(
|
||||||
"The image size that the model was trained on. Use 512 for Stable Diffusion v1.X and Stable Siffusion v2"
|
"The image size that the model was trained on. Use 512 for Stable Diffusion v1.X and Stable Diffusion v2"
|
||||||
" Base. Use 768 for Stable Diffusion v2."
|
" Base. Use 768 for Stable Diffusion v2."
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -254,7 +254,7 @@ version_range_max = max(sys.version_info[1], 10) + 1
|
|||||||
|
|
||||||
setup(
|
setup(
|
||||||
name="diffusers",
|
name="diffusers",
|
||||||
version="0.30.0.dev0", # expected format is one of x.y.z.dev0, or x.y.z.rc1 or x.y.z (no to dashes, yes to dots)
|
version="0.30.1", # expected format is one of x.y.z.dev0, or x.y.z.rc1 or x.y.z (no to dashes, yes to dots)
|
||||||
description="State-of-the-art diffusion in PyTorch and JAX.",
|
description="State-of-the-art diffusion in PyTorch and JAX.",
|
||||||
long_description=open("README.md", "r", encoding="utf-8").read(),
|
long_description=open("README.md", "r", encoding="utf-8").read(),
|
||||||
long_description_content_type="text/markdown",
|
long_description_content_type="text/markdown",
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
__version__ = "0.30.0.dev0"
|
__version__ = "0.30.1"
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
@@ -12,6 +12,7 @@ from .utils import (
|
|||||||
is_note_seq_available,
|
is_note_seq_available,
|
||||||
is_onnx_available,
|
is_onnx_available,
|
||||||
is_scipy_available,
|
is_scipy_available,
|
||||||
|
is_sentencepiece_available,
|
||||||
is_torch_available,
|
is_torch_available,
|
||||||
is_torchsde_available,
|
is_torchsde_available,
|
||||||
is_transformers_available,
|
is_transformers_available,
|
||||||
@@ -78,13 +79,16 @@ else:
|
|||||||
"AsymmetricAutoencoderKL",
|
"AsymmetricAutoencoderKL",
|
||||||
"AuraFlowTransformer2DModel",
|
"AuraFlowTransformer2DModel",
|
||||||
"AutoencoderKL",
|
"AutoencoderKL",
|
||||||
|
"AutoencoderKLCogVideoX",
|
||||||
"AutoencoderKLTemporalDecoder",
|
"AutoencoderKLTemporalDecoder",
|
||||||
"AutoencoderOobleck",
|
"AutoencoderOobleck",
|
||||||
"AutoencoderTiny",
|
"AutoencoderTiny",
|
||||||
|
"CogVideoXTransformer3DModel",
|
||||||
"ConsistencyDecoderVAE",
|
"ConsistencyDecoderVAE",
|
||||||
"ControlNetModel",
|
"ControlNetModel",
|
||||||
"ControlNetXSAdapter",
|
"ControlNetXSAdapter",
|
||||||
"DiTTransformer2DModel",
|
"DiTTransformer2DModel",
|
||||||
|
"FluxTransformer2DModel",
|
||||||
"HunyuanDiT2DControlNetModel",
|
"HunyuanDiT2DControlNetModel",
|
||||||
"HunyuanDiT2DModel",
|
"HunyuanDiT2DModel",
|
||||||
"HunyuanDiT2DMultiControlNetModel",
|
"HunyuanDiT2DMultiControlNetModel",
|
||||||
@@ -153,6 +157,8 @@ else:
|
|||||||
[
|
[
|
||||||
"AmusedScheduler",
|
"AmusedScheduler",
|
||||||
"CMStochasticIterativeScheduler",
|
"CMStochasticIterativeScheduler",
|
||||||
|
"CogVideoXDDIMScheduler",
|
||||||
|
"CogVideoXDPMScheduler",
|
||||||
"DDIMInverseScheduler",
|
"DDIMInverseScheduler",
|
||||||
"DDIMParallelScheduler",
|
"DDIMParallelScheduler",
|
||||||
"DDIMScheduler",
|
"DDIMScheduler",
|
||||||
@@ -233,6 +239,7 @@ else:
|
|||||||
"AmusedInpaintPipeline",
|
"AmusedInpaintPipeline",
|
||||||
"AmusedPipeline",
|
"AmusedPipeline",
|
||||||
"AnimateDiffControlNetPipeline",
|
"AnimateDiffControlNetPipeline",
|
||||||
|
"AnimateDiffPAGPipeline",
|
||||||
"AnimateDiffPipeline",
|
"AnimateDiffPipeline",
|
||||||
"AnimateDiffSDXLPipeline",
|
"AnimateDiffSDXLPipeline",
|
||||||
"AnimateDiffSparseControlNetPipeline",
|
"AnimateDiffSparseControlNetPipeline",
|
||||||
@@ -244,11 +251,12 @@ else:
|
|||||||
"AuraFlowPipeline",
|
"AuraFlowPipeline",
|
||||||
"BlipDiffusionControlNetPipeline",
|
"BlipDiffusionControlNetPipeline",
|
||||||
"BlipDiffusionPipeline",
|
"BlipDiffusionPipeline",
|
||||||
"ChatGLMModel",
|
|
||||||
"ChatGLMTokenizer",
|
|
||||||
"CLIPImageProjection",
|
"CLIPImageProjection",
|
||||||
|
"CogVideoXPipeline",
|
||||||
"CycleDiffusionPipeline",
|
"CycleDiffusionPipeline",
|
||||||
|
"FluxPipeline",
|
||||||
"HunyuanDiTControlNetPipeline",
|
"HunyuanDiTControlNetPipeline",
|
||||||
|
"HunyuanDiTPAGPipeline",
|
||||||
"HunyuanDiTPipeline",
|
"HunyuanDiTPipeline",
|
||||||
"I2VGenXLPipeline",
|
"I2VGenXLPipeline",
|
||||||
"IFImg2ImgPipeline",
|
"IFImg2ImgPipeline",
|
||||||
@@ -277,8 +285,6 @@ else:
|
|||||||
"KandinskyV22Pipeline",
|
"KandinskyV22Pipeline",
|
||||||
"KandinskyV22PriorEmb2EmbPipeline",
|
"KandinskyV22PriorEmb2EmbPipeline",
|
||||||
"KandinskyV22PriorPipeline",
|
"KandinskyV22PriorPipeline",
|
||||||
"KolorsImg2ImgPipeline",
|
|
||||||
"KolorsPipeline",
|
|
||||||
"LatentConsistencyModelImg2ImgPipeline",
|
"LatentConsistencyModelImg2ImgPipeline",
|
||||||
"LatentConsistencyModelPipeline",
|
"LatentConsistencyModelPipeline",
|
||||||
"LattePipeline",
|
"LattePipeline",
|
||||||
@@ -292,6 +298,7 @@ else:
|
|||||||
"PaintByExamplePipeline",
|
"PaintByExamplePipeline",
|
||||||
"PIAPipeline",
|
"PIAPipeline",
|
||||||
"PixArtAlphaPipeline",
|
"PixArtAlphaPipeline",
|
||||||
|
"PixArtSigmaPAGPipeline",
|
||||||
"PixArtSigmaPipeline",
|
"PixArtSigmaPipeline",
|
||||||
"SemanticStableDiffusionPipeline",
|
"SemanticStableDiffusionPipeline",
|
||||||
"ShapEImg2ImgPipeline",
|
"ShapEImg2ImgPipeline",
|
||||||
@@ -304,6 +311,7 @@ else:
|
|||||||
"StableDiffusion3ControlNetPipeline",
|
"StableDiffusion3ControlNetPipeline",
|
||||||
"StableDiffusion3Img2ImgPipeline",
|
"StableDiffusion3Img2ImgPipeline",
|
||||||
"StableDiffusion3InpaintPipeline",
|
"StableDiffusion3InpaintPipeline",
|
||||||
|
"StableDiffusion3PAGPipeline",
|
||||||
"StableDiffusion3Pipeline",
|
"StableDiffusion3Pipeline",
|
||||||
"StableDiffusionAdapterPipeline",
|
"StableDiffusionAdapterPipeline",
|
||||||
"StableDiffusionAttendAndExcitePipeline",
|
"StableDiffusionAttendAndExcitePipeline",
|
||||||
@@ -381,6 +389,19 @@ except OptionalDependencyNotAvailable:
|
|||||||
else:
|
else:
|
||||||
_import_structure["pipelines"].extend(["StableDiffusionKDiffusionPipeline", "StableDiffusionXLKDiffusionPipeline"])
|
_import_structure["pipelines"].extend(["StableDiffusionKDiffusionPipeline", "StableDiffusionXLKDiffusionPipeline"])
|
||||||
|
|
||||||
|
try:
|
||||||
|
if not (is_torch_available() and is_transformers_available() and is_sentencepiece_available()):
|
||||||
|
raise OptionalDependencyNotAvailable()
|
||||||
|
except OptionalDependencyNotAvailable:
|
||||||
|
from .utils import dummy_torch_and_transformers_and_sentencepiece_objects # noqa F403
|
||||||
|
|
||||||
|
_import_structure["utils.dummy_torch_and_transformers_and_sentencepiece_objects"] = [
|
||||||
|
name for name in dir(dummy_torch_and_transformers_and_sentencepiece_objects) if not name.startswith("_")
|
||||||
|
]
|
||||||
|
|
||||||
|
else:
|
||||||
|
_import_structure["pipelines"].extend(["KolorsImg2ImgPipeline", "KolorsPAGPipeline", "KolorsPipeline"])
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if not (is_torch_available() and is_transformers_available() and is_onnx_available()):
|
if not (is_torch_available() and is_transformers_available() and is_onnx_available()):
|
||||||
raise OptionalDependencyNotAvailable()
|
raise OptionalDependencyNotAvailable()
|
||||||
@@ -519,13 +540,16 @@ if TYPE_CHECKING or DIFFUSERS_SLOW_IMPORT:
|
|||||||
AsymmetricAutoencoderKL,
|
AsymmetricAutoencoderKL,
|
||||||
AuraFlowTransformer2DModel,
|
AuraFlowTransformer2DModel,
|
||||||
AutoencoderKL,
|
AutoencoderKL,
|
||||||
|
AutoencoderKLCogVideoX,
|
||||||
AutoencoderKLTemporalDecoder,
|
AutoencoderKLTemporalDecoder,
|
||||||
AutoencoderOobleck,
|
AutoencoderOobleck,
|
||||||
AutoencoderTiny,
|
AutoencoderTiny,
|
||||||
|
CogVideoXTransformer3DModel,
|
||||||
ConsistencyDecoderVAE,
|
ConsistencyDecoderVAE,
|
||||||
ControlNetModel,
|
ControlNetModel,
|
||||||
ControlNetXSAdapter,
|
ControlNetXSAdapter,
|
||||||
DiTTransformer2DModel,
|
DiTTransformer2DModel,
|
||||||
|
FluxTransformer2DModel,
|
||||||
HunyuanDiT2DControlNetModel,
|
HunyuanDiT2DControlNetModel,
|
||||||
HunyuanDiT2DModel,
|
HunyuanDiT2DModel,
|
||||||
HunyuanDiT2DMultiControlNetModel,
|
HunyuanDiT2DMultiControlNetModel,
|
||||||
@@ -591,6 +615,8 @@ if TYPE_CHECKING or DIFFUSERS_SLOW_IMPORT:
|
|||||||
from .schedulers import (
|
from .schedulers import (
|
||||||
AmusedScheduler,
|
AmusedScheduler,
|
||||||
CMStochasticIterativeScheduler,
|
CMStochasticIterativeScheduler,
|
||||||
|
CogVideoXDDIMScheduler,
|
||||||
|
CogVideoXDPMScheduler,
|
||||||
DDIMInverseScheduler,
|
DDIMInverseScheduler,
|
||||||
DDIMParallelScheduler,
|
DDIMParallelScheduler,
|
||||||
DDIMScheduler,
|
DDIMScheduler,
|
||||||
@@ -654,6 +680,7 @@ if TYPE_CHECKING or DIFFUSERS_SLOW_IMPORT:
|
|||||||
AmusedInpaintPipeline,
|
AmusedInpaintPipeline,
|
||||||
AmusedPipeline,
|
AmusedPipeline,
|
||||||
AnimateDiffControlNetPipeline,
|
AnimateDiffControlNetPipeline,
|
||||||
|
AnimateDiffPAGPipeline,
|
||||||
AnimateDiffPipeline,
|
AnimateDiffPipeline,
|
||||||
AnimateDiffSDXLPipeline,
|
AnimateDiffSDXLPipeline,
|
||||||
AnimateDiffSparseControlNetPipeline,
|
AnimateDiffSparseControlNetPipeline,
|
||||||
@@ -663,11 +690,12 @@ if TYPE_CHECKING or DIFFUSERS_SLOW_IMPORT:
|
|||||||
AudioLDM2UNet2DConditionModel,
|
AudioLDM2UNet2DConditionModel,
|
||||||
AudioLDMPipeline,
|
AudioLDMPipeline,
|
||||||
AuraFlowPipeline,
|
AuraFlowPipeline,
|
||||||
ChatGLMModel,
|
|
||||||
ChatGLMTokenizer,
|
|
||||||
CLIPImageProjection,
|
CLIPImageProjection,
|
||||||
|
CogVideoXPipeline,
|
||||||
CycleDiffusionPipeline,
|
CycleDiffusionPipeline,
|
||||||
|
FluxPipeline,
|
||||||
HunyuanDiTControlNetPipeline,
|
HunyuanDiTControlNetPipeline,
|
||||||
|
HunyuanDiTPAGPipeline,
|
||||||
HunyuanDiTPipeline,
|
HunyuanDiTPipeline,
|
||||||
I2VGenXLPipeline,
|
I2VGenXLPipeline,
|
||||||
IFImg2ImgPipeline,
|
IFImg2ImgPipeline,
|
||||||
@@ -696,8 +724,6 @@ if TYPE_CHECKING or DIFFUSERS_SLOW_IMPORT:
|
|||||||
KandinskyV22Pipeline,
|
KandinskyV22Pipeline,
|
||||||
KandinskyV22PriorEmb2EmbPipeline,
|
KandinskyV22PriorEmb2EmbPipeline,
|
||||||
KandinskyV22PriorPipeline,
|
KandinskyV22PriorPipeline,
|
||||||
KolorsImg2ImgPipeline,
|
|
||||||
KolorsPipeline,
|
|
||||||
LatentConsistencyModelImg2ImgPipeline,
|
LatentConsistencyModelImg2ImgPipeline,
|
||||||
LatentConsistencyModelPipeline,
|
LatentConsistencyModelPipeline,
|
||||||
LattePipeline,
|
LattePipeline,
|
||||||
@@ -711,6 +737,7 @@ if TYPE_CHECKING or DIFFUSERS_SLOW_IMPORT:
|
|||||||
PaintByExamplePipeline,
|
PaintByExamplePipeline,
|
||||||
PIAPipeline,
|
PIAPipeline,
|
||||||
PixArtAlphaPipeline,
|
PixArtAlphaPipeline,
|
||||||
|
PixArtSigmaPAGPipeline,
|
||||||
PixArtSigmaPipeline,
|
PixArtSigmaPipeline,
|
||||||
SemanticStableDiffusionPipeline,
|
SemanticStableDiffusionPipeline,
|
||||||
ShapEImg2ImgPipeline,
|
ShapEImg2ImgPipeline,
|
||||||
@@ -723,6 +750,7 @@ if TYPE_CHECKING or DIFFUSERS_SLOW_IMPORT:
|
|||||||
StableDiffusion3ControlNetPipeline,
|
StableDiffusion3ControlNetPipeline,
|
||||||
StableDiffusion3Img2ImgPipeline,
|
StableDiffusion3Img2ImgPipeline,
|
||||||
StableDiffusion3InpaintPipeline,
|
StableDiffusion3InpaintPipeline,
|
||||||
|
StableDiffusion3PAGPipeline,
|
||||||
StableDiffusion3Pipeline,
|
StableDiffusion3Pipeline,
|
||||||
StableDiffusionAdapterPipeline,
|
StableDiffusionAdapterPipeline,
|
||||||
StableDiffusionAttendAndExcitePipeline,
|
StableDiffusionAttendAndExcitePipeline,
|
||||||
@@ -794,6 +822,13 @@ if TYPE_CHECKING or DIFFUSERS_SLOW_IMPORT:
|
|||||||
else:
|
else:
|
||||||
from .pipelines import StableDiffusionKDiffusionPipeline, StableDiffusionXLKDiffusionPipeline
|
from .pipelines import StableDiffusionKDiffusionPipeline, StableDiffusionXLKDiffusionPipeline
|
||||||
|
|
||||||
|
try:
|
||||||
|
if not (is_torch_available() and is_transformers_available() and is_sentencepiece_available()):
|
||||||
|
raise OptionalDependencyNotAvailable()
|
||||||
|
except OptionalDependencyNotAvailable:
|
||||||
|
from .utils.dummy_torch_and_transformers_and_sentencepiece_objects import * # noqa F403
|
||||||
|
else:
|
||||||
|
from .pipelines import KolorsImg2ImgPipeline, KolorsPAGPipeline, KolorsPipeline
|
||||||
try:
|
try:
|
||||||
if not (is_torch_available() and is_transformers_available() and is_onnx_available()):
|
if not (is_torch_available() and is_transformers_available() and is_onnx_available()):
|
||||||
raise OptionalDependencyNotAvailable()
|
raise OptionalDependencyNotAvailable()
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ if is_torch_available():
|
|||||||
"SD3LoraLoaderMixin",
|
"SD3LoraLoaderMixin",
|
||||||
"StableDiffusionXLLoraLoaderMixin",
|
"StableDiffusionXLLoraLoaderMixin",
|
||||||
"LoraLoaderMixin",
|
"LoraLoaderMixin",
|
||||||
|
"FluxLoraLoaderMixin",
|
||||||
]
|
]
|
||||||
_import_structure["textual_inversion"] = ["TextualInversionLoaderMixin"]
|
_import_structure["textual_inversion"] = ["TextualInversionLoaderMixin"]
|
||||||
_import_structure["ip_adapter"] = ["IPAdapterMixin"]
|
_import_structure["ip_adapter"] = ["IPAdapterMixin"]
|
||||||
@@ -83,6 +84,7 @@ if TYPE_CHECKING or DIFFUSERS_SLOW_IMPORT:
|
|||||||
from .ip_adapter import IPAdapterMixin
|
from .ip_adapter import IPAdapterMixin
|
||||||
from .lora_pipeline import (
|
from .lora_pipeline import (
|
||||||
AmusedLoraLoaderMixin,
|
AmusedLoraLoaderMixin,
|
||||||
|
FluxLoraLoaderMixin,
|
||||||
LoraLoaderMixin,
|
LoraLoaderMixin,
|
||||||
SD3LoraLoaderMixin,
|
SD3LoraLoaderMixin,
|
||||||
StableDiffusionLoraLoaderMixin,
|
StableDiffusionLoraLoaderMixin,
|
||||||
|
|||||||
@@ -1475,6 +1475,511 @@ class SD3LoraLoaderMixin(LoraBaseMixin):
|
|||||||
super().unfuse_lora(components=components)
|
super().unfuse_lora(components=components)
|
||||||
|
|
||||||
|
|
||||||
|
class FluxLoraLoaderMixin(LoraBaseMixin):
|
||||||
|
r"""
|
||||||
|
Load LoRA layers into [`FluxTransformer2DModel`],
|
||||||
|
[`CLIPTextModel`](https://huggingface.co/docs/transformers/model_doc/clip#transformers.CLIPTextModel).
|
||||||
|
|
||||||
|
Specific to [`StableDiffusion3Pipeline`].
|
||||||
|
"""
|
||||||
|
|
||||||
|
_lora_loadable_modules = ["transformer", "text_encoder"]
|
||||||
|
transformer_name = TRANSFORMER_NAME
|
||||||
|
text_encoder_name = TEXT_ENCODER_NAME
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@validate_hf_hub_args
|
||||||
|
def lora_state_dict(
|
||||||
|
cls,
|
||||||
|
pretrained_model_name_or_path_or_dict: Union[str, Dict[str, torch.Tensor]],
|
||||||
|
return_alphas: bool = False,
|
||||||
|
**kwargs,
|
||||||
|
):
|
||||||
|
r"""
|
||||||
|
Return state dict for lora weights and the network alphas.
|
||||||
|
|
||||||
|
<Tip warning={true}>
|
||||||
|
|
||||||
|
We support loading A1111 formatted LoRA checkpoints in a limited capacity.
|
||||||
|
|
||||||
|
This function is experimental and might change in the future.
|
||||||
|
|
||||||
|
</Tip>
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
pretrained_model_name_or_path_or_dict (`str` or `os.PathLike` or `dict`):
|
||||||
|
Can be either:
|
||||||
|
|
||||||
|
- A string, the *model id* (for example `google/ddpm-celebahq-256`) of a pretrained model hosted on
|
||||||
|
the Hub.
|
||||||
|
- A path to a *directory* (for example `./my_model_directory`) containing the model weights saved
|
||||||
|
with [`ModelMixin.save_pretrained`].
|
||||||
|
- A [torch state
|
||||||
|
dict](https://pytorch.org/tutorials/beginner/saving_loading_models.html#what-is-a-state-dict).
|
||||||
|
|
||||||
|
cache_dir (`Union[str, os.PathLike]`, *optional*):
|
||||||
|
Path to a directory where a downloaded pretrained model configuration is cached if the standard cache
|
||||||
|
is not used.
|
||||||
|
force_download (`bool`, *optional*, defaults to `False`):
|
||||||
|
Whether or not to force the (re-)download of the model weights and configuration files, overriding the
|
||||||
|
cached versions if they exist.
|
||||||
|
|
||||||
|
proxies (`Dict[str, str]`, *optional*):
|
||||||
|
A dictionary of proxy servers to use by protocol or endpoint, for example, `{'http': 'foo.bar:3128',
|
||||||
|
'http://hostname': 'foo.bar:4012'}`. The proxies are used on each request.
|
||||||
|
local_files_only (`bool`, *optional*, defaults to `False`):
|
||||||
|
Whether to only load local model weights and configuration files or not. If set to `True`, the model
|
||||||
|
won't be downloaded from the Hub.
|
||||||
|
token (`str` or *bool*, *optional*):
|
||||||
|
The token to use as HTTP bearer authorization for remote files. If `True`, the token generated from
|
||||||
|
`diffusers-cli login` (stored in `~/.huggingface`) is used.
|
||||||
|
revision (`str`, *optional*, defaults to `"main"`):
|
||||||
|
The specific model version to use. It can be a branch name, a tag name, a commit id, or any identifier
|
||||||
|
allowed by Git.
|
||||||
|
subfolder (`str`, *optional*, defaults to `""`):
|
||||||
|
The subfolder location of a model file within a larger model repository on the Hub or locally.
|
||||||
|
|
||||||
|
"""
|
||||||
|
# Load the main state dict first which has the LoRA layers for either of
|
||||||
|
# transformer and text encoder or both.
|
||||||
|
cache_dir = kwargs.pop("cache_dir", None)
|
||||||
|
force_download = kwargs.pop("force_download", False)
|
||||||
|
proxies = kwargs.pop("proxies", None)
|
||||||
|
local_files_only = kwargs.pop("local_files_only", None)
|
||||||
|
token = kwargs.pop("token", None)
|
||||||
|
revision = kwargs.pop("revision", None)
|
||||||
|
subfolder = kwargs.pop("subfolder", None)
|
||||||
|
weight_name = kwargs.pop("weight_name", None)
|
||||||
|
use_safetensors = kwargs.pop("use_safetensors", None)
|
||||||
|
|
||||||
|
allow_pickle = False
|
||||||
|
if use_safetensors is None:
|
||||||
|
use_safetensors = True
|
||||||
|
allow_pickle = True
|
||||||
|
|
||||||
|
user_agent = {
|
||||||
|
"file_type": "attn_procs_weights",
|
||||||
|
"framework": "pytorch",
|
||||||
|
}
|
||||||
|
|
||||||
|
state_dict = cls._fetch_state_dict(
|
||||||
|
pretrained_model_name_or_path_or_dict=pretrained_model_name_or_path_or_dict,
|
||||||
|
weight_name=weight_name,
|
||||||
|
use_safetensors=use_safetensors,
|
||||||
|
local_files_only=local_files_only,
|
||||||
|
cache_dir=cache_dir,
|
||||||
|
force_download=force_download,
|
||||||
|
proxies=proxies,
|
||||||
|
token=token,
|
||||||
|
revision=revision,
|
||||||
|
subfolder=subfolder,
|
||||||
|
user_agent=user_agent,
|
||||||
|
allow_pickle=allow_pickle,
|
||||||
|
)
|
||||||
|
|
||||||
|
# For state dicts like
|
||||||
|
# https://huggingface.co/TheLastBen/Jon_Snow_Flux_LoRA
|
||||||
|
keys = list(state_dict.keys())
|
||||||
|
network_alphas = {}
|
||||||
|
for k in keys:
|
||||||
|
if "alpha" in k:
|
||||||
|
alpha_value = state_dict.get(k)
|
||||||
|
if (torch.is_tensor(alpha_value) and torch.is_floating_point(alpha_value)) or isinstance(
|
||||||
|
alpha_value, float
|
||||||
|
):
|
||||||
|
network_alphas[k] = state_dict.pop(k)
|
||||||
|
else:
|
||||||
|
raise ValueError(
|
||||||
|
f"The alpha key ({k}) seems to be incorrect. If you think this error is unexpected, please open as issue."
|
||||||
|
)
|
||||||
|
|
||||||
|
if return_alphas:
|
||||||
|
return state_dict, network_alphas
|
||||||
|
else:
|
||||||
|
return state_dict
|
||||||
|
|
||||||
|
def load_lora_weights(
|
||||||
|
self, pretrained_model_name_or_path_or_dict: Union[str, Dict[str, torch.Tensor]], adapter_name=None, **kwargs
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Load LoRA weights specified in `pretrained_model_name_or_path_or_dict` into `self.transformer` and
|
||||||
|
`self.text_encoder`.
|
||||||
|
|
||||||
|
All kwargs are forwarded to `self.lora_state_dict`.
|
||||||
|
|
||||||
|
See [`~loaders.StableDiffusionLoraLoaderMixin.lora_state_dict`] for more details on how the state dict is
|
||||||
|
loaded.
|
||||||
|
|
||||||
|
See [`~loaders.StableDiffusionLoraLoaderMixin.load_lora_into_transformer`] for more details on how the state
|
||||||
|
dict is loaded into `self.transformer`.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
pretrained_model_name_or_path_or_dict (`str` or `os.PathLike` or `dict`):
|
||||||
|
See [`~loaders.StableDiffusionLoraLoaderMixin.lora_state_dict`].
|
||||||
|
kwargs (`dict`, *optional*):
|
||||||
|
See [`~loaders.StableDiffusionLoraLoaderMixin.lora_state_dict`].
|
||||||
|
adapter_name (`str`, *optional*):
|
||||||
|
Adapter name to be used for referencing the loaded adapter model. If not specified, it will use
|
||||||
|
`default_{i}` where i is the total number of adapters being loaded.
|
||||||
|
"""
|
||||||
|
if not USE_PEFT_BACKEND:
|
||||||
|
raise ValueError("PEFT backend is required for this method.")
|
||||||
|
|
||||||
|
# if a dict is passed, copy it instead of modifying it inplace
|
||||||
|
if isinstance(pretrained_model_name_or_path_or_dict, dict):
|
||||||
|
pretrained_model_name_or_path_or_dict = pretrained_model_name_or_path_or_dict.copy()
|
||||||
|
|
||||||
|
# First, ensure that the checkpoint is a compatible one and can be successfully loaded.
|
||||||
|
state_dict, network_alphas = self.lora_state_dict(
|
||||||
|
pretrained_model_name_or_path_or_dict, return_alphas=True, **kwargs
|
||||||
|
)
|
||||||
|
|
||||||
|
is_correct_format = all("lora" in key or "dora_scale" in key for key in state_dict.keys())
|
||||||
|
if not is_correct_format:
|
||||||
|
raise ValueError("Invalid LoRA checkpoint.")
|
||||||
|
|
||||||
|
self.load_lora_into_transformer(
|
||||||
|
state_dict,
|
||||||
|
network_alphas=network_alphas,
|
||||||
|
transformer=getattr(self, self.transformer_name) if not hasattr(self, "transformer") else self.transformer,
|
||||||
|
adapter_name=adapter_name,
|
||||||
|
_pipeline=self,
|
||||||
|
)
|
||||||
|
|
||||||
|
text_encoder_state_dict = {k: v for k, v in state_dict.items() if "text_encoder." in k}
|
||||||
|
if len(text_encoder_state_dict) > 0:
|
||||||
|
self.load_lora_into_text_encoder(
|
||||||
|
text_encoder_state_dict,
|
||||||
|
network_alphas=network_alphas,
|
||||||
|
text_encoder=self.text_encoder,
|
||||||
|
prefix="text_encoder",
|
||||||
|
lora_scale=self.lora_scale,
|
||||||
|
adapter_name=adapter_name,
|
||||||
|
_pipeline=self,
|
||||||
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def load_lora_into_transformer(cls, state_dict, network_alphas, transformer, adapter_name=None, _pipeline=None):
|
||||||
|
"""
|
||||||
|
This will load the LoRA layers specified in `state_dict` into `transformer`.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
state_dict (`dict`):
|
||||||
|
A standard state dict containing the lora layer parameters. The keys can either be indexed directly
|
||||||
|
into the unet or prefixed with an additional `unet` which can be used to distinguish between text
|
||||||
|
encoder lora layers.
|
||||||
|
network_alphas (`Dict[str, float]`):
|
||||||
|
The value of the network alpha used for stable learning and preventing underflow. This value has the
|
||||||
|
same meaning as the `--network_alpha` option in the kohya-ss trainer script. Refer to [this
|
||||||
|
link](https://github.com/darkstorm2150/sd-scripts/blob/main/docs/train_network_README-en.md#execute-learning).
|
||||||
|
transformer (`SD3Transformer2DModel`):
|
||||||
|
The Transformer model to load the LoRA layers into.
|
||||||
|
adapter_name (`str`, *optional*):
|
||||||
|
Adapter name to be used for referencing the loaded adapter model. If not specified, it will use
|
||||||
|
`default_{i}` where i is the total number of adapters being loaded.
|
||||||
|
"""
|
||||||
|
from peft import LoraConfig, inject_adapter_in_model, set_peft_model_state_dict
|
||||||
|
|
||||||
|
keys = list(state_dict.keys())
|
||||||
|
|
||||||
|
transformer_keys = [k for k in keys if k.startswith(cls.transformer_name)]
|
||||||
|
state_dict = {
|
||||||
|
k.replace(f"{cls.transformer_name}.", ""): v for k, v in state_dict.items() if k in transformer_keys
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(state_dict.keys()) > 0:
|
||||||
|
# check with first key if is not in peft format
|
||||||
|
first_key = next(iter(state_dict.keys()))
|
||||||
|
if "lora_A" not in first_key:
|
||||||
|
state_dict = convert_unet_state_dict_to_peft(state_dict)
|
||||||
|
|
||||||
|
if adapter_name in getattr(transformer, "peft_config", {}):
|
||||||
|
raise ValueError(
|
||||||
|
f"Adapter name {adapter_name} already in use in the transformer - please select a new adapter name."
|
||||||
|
)
|
||||||
|
|
||||||
|
rank = {}
|
||||||
|
for key, val in state_dict.items():
|
||||||
|
if "lora_B" in key:
|
||||||
|
rank[key] = val.shape[1]
|
||||||
|
|
||||||
|
if network_alphas is not None and len(network_alphas) >= 1:
|
||||||
|
prefix = cls.transformer_name
|
||||||
|
alpha_keys = [k for k in network_alphas.keys() if k.startswith(prefix) and k.split(".")[0] == prefix]
|
||||||
|
network_alphas = {k.replace(f"{prefix}.", ""): v for k, v in network_alphas.items() if k in alpha_keys}
|
||||||
|
|
||||||
|
lora_config_kwargs = get_peft_kwargs(rank, network_alpha_dict=network_alphas, peft_state_dict=state_dict)
|
||||||
|
if "use_dora" in lora_config_kwargs:
|
||||||
|
if lora_config_kwargs["use_dora"] and is_peft_version("<", "0.9.0"):
|
||||||
|
raise ValueError(
|
||||||
|
"You need `peft` 0.9.0 at least to use DoRA-enabled LoRAs. Please upgrade your installation of `peft`."
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
lora_config_kwargs.pop("use_dora")
|
||||||
|
lora_config = LoraConfig(**lora_config_kwargs)
|
||||||
|
|
||||||
|
# adapter_name
|
||||||
|
if adapter_name is None:
|
||||||
|
adapter_name = get_adapter_name(transformer)
|
||||||
|
|
||||||
|
# In case the pipeline has been already offloaded to CPU - temporarily remove the hooks
|
||||||
|
# otherwise loading LoRA weights will lead to an error
|
||||||
|
is_model_cpu_offload, is_sequential_cpu_offload = cls._optionally_disable_offloading(_pipeline)
|
||||||
|
|
||||||
|
inject_adapter_in_model(lora_config, transformer, adapter_name=adapter_name)
|
||||||
|
incompatible_keys = set_peft_model_state_dict(transformer, state_dict, adapter_name)
|
||||||
|
|
||||||
|
if incompatible_keys is not None:
|
||||||
|
# check only for unexpected keys
|
||||||
|
unexpected_keys = getattr(incompatible_keys, "unexpected_keys", None)
|
||||||
|
if unexpected_keys:
|
||||||
|
logger.warning(
|
||||||
|
f"Loading adapter weights from state_dict led to unexpected keys not found in the model: "
|
||||||
|
f" {unexpected_keys}. "
|
||||||
|
)
|
||||||
|
|
||||||
|
# Offload back.
|
||||||
|
if is_model_cpu_offload:
|
||||||
|
_pipeline.enable_model_cpu_offload()
|
||||||
|
elif is_sequential_cpu_offload:
|
||||||
|
_pipeline.enable_sequential_cpu_offload()
|
||||||
|
# Unsafe code />
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
# Copied from diffusers.loaders.lora_pipeline.StableDiffusionLoraLoaderMixin.load_lora_into_text_encoder
|
||||||
|
def load_lora_into_text_encoder(
|
||||||
|
cls,
|
||||||
|
state_dict,
|
||||||
|
network_alphas,
|
||||||
|
text_encoder,
|
||||||
|
prefix=None,
|
||||||
|
lora_scale=1.0,
|
||||||
|
adapter_name=None,
|
||||||
|
_pipeline=None,
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
This will load the LoRA layers specified in `state_dict` into `text_encoder`
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
state_dict (`dict`):
|
||||||
|
A standard state dict containing the lora layer parameters. The key should be prefixed with an
|
||||||
|
additional `text_encoder` to distinguish between unet lora layers.
|
||||||
|
network_alphas (`Dict[str, float]`):
|
||||||
|
See `LoRALinearLayer` for more details.
|
||||||
|
text_encoder (`CLIPTextModel`):
|
||||||
|
The text encoder model to load the LoRA layers into.
|
||||||
|
prefix (`str`):
|
||||||
|
Expected prefix of the `text_encoder` in the `state_dict`.
|
||||||
|
lora_scale (`float`):
|
||||||
|
How much to scale the output of the lora linear layer before it is added with the output of the regular
|
||||||
|
lora layer.
|
||||||
|
adapter_name (`str`, *optional*):
|
||||||
|
Adapter name to be used for referencing the loaded adapter model. If not specified, it will use
|
||||||
|
`default_{i}` where i is the total number of adapters being loaded.
|
||||||
|
"""
|
||||||
|
if not USE_PEFT_BACKEND:
|
||||||
|
raise ValueError("PEFT backend is required for this method.")
|
||||||
|
|
||||||
|
from peft import LoraConfig
|
||||||
|
|
||||||
|
# If the serialization format is new (introduced in https://github.com/huggingface/diffusers/pull/2918),
|
||||||
|
# then the `state_dict` keys should have `self.unet_name` and/or `self.text_encoder_name` as
|
||||||
|
# their prefixes.
|
||||||
|
keys = list(state_dict.keys())
|
||||||
|
prefix = cls.text_encoder_name if prefix is None else prefix
|
||||||
|
|
||||||
|
# Safe prefix to check with.
|
||||||
|
if any(cls.text_encoder_name in key for key in keys):
|
||||||
|
# Load the layers corresponding to text encoder and make necessary adjustments.
|
||||||
|
text_encoder_keys = [k for k in keys if k.startswith(prefix) and k.split(".")[0] == prefix]
|
||||||
|
text_encoder_lora_state_dict = {
|
||||||
|
k.replace(f"{prefix}.", ""): v for k, v in state_dict.items() if k in text_encoder_keys
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(text_encoder_lora_state_dict) > 0:
|
||||||
|
logger.info(f"Loading {prefix}.")
|
||||||
|
rank = {}
|
||||||
|
text_encoder_lora_state_dict = convert_state_dict_to_diffusers(text_encoder_lora_state_dict)
|
||||||
|
|
||||||
|
# convert state dict
|
||||||
|
text_encoder_lora_state_dict = convert_state_dict_to_peft(text_encoder_lora_state_dict)
|
||||||
|
|
||||||
|
for name, _ in text_encoder_attn_modules(text_encoder):
|
||||||
|
for module in ("out_proj", "q_proj", "k_proj", "v_proj"):
|
||||||
|
rank_key = f"{name}.{module}.lora_B.weight"
|
||||||
|
if rank_key not in text_encoder_lora_state_dict:
|
||||||
|
continue
|
||||||
|
rank[rank_key] = text_encoder_lora_state_dict[rank_key].shape[1]
|
||||||
|
|
||||||
|
for name, _ in text_encoder_mlp_modules(text_encoder):
|
||||||
|
for module in ("fc1", "fc2"):
|
||||||
|
rank_key = f"{name}.{module}.lora_B.weight"
|
||||||
|
if rank_key not in text_encoder_lora_state_dict:
|
||||||
|
continue
|
||||||
|
rank[rank_key] = text_encoder_lora_state_dict[rank_key].shape[1]
|
||||||
|
|
||||||
|
if network_alphas is not None:
|
||||||
|
alpha_keys = [
|
||||||
|
k for k in network_alphas.keys() if k.startswith(prefix) and k.split(".")[0] == prefix
|
||||||
|
]
|
||||||
|
network_alphas = {
|
||||||
|
k.replace(f"{prefix}.", ""): v for k, v in network_alphas.items() if k in alpha_keys
|
||||||
|
}
|
||||||
|
|
||||||
|
lora_config_kwargs = get_peft_kwargs(rank, network_alphas, text_encoder_lora_state_dict, is_unet=False)
|
||||||
|
if "use_dora" in lora_config_kwargs:
|
||||||
|
if lora_config_kwargs["use_dora"]:
|
||||||
|
if is_peft_version("<", "0.9.0"):
|
||||||
|
raise ValueError(
|
||||||
|
"You need `peft` 0.9.0 at least to use DoRA-enabled LoRAs. Please upgrade your installation of `peft`."
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
if is_peft_version("<", "0.9.0"):
|
||||||
|
lora_config_kwargs.pop("use_dora")
|
||||||
|
lora_config = LoraConfig(**lora_config_kwargs)
|
||||||
|
|
||||||
|
# adapter_name
|
||||||
|
if adapter_name is None:
|
||||||
|
adapter_name = get_adapter_name(text_encoder)
|
||||||
|
|
||||||
|
is_model_cpu_offload, is_sequential_cpu_offload = cls._optionally_disable_offloading(_pipeline)
|
||||||
|
|
||||||
|
# inject LoRA layers and load the state dict
|
||||||
|
# in transformers we automatically check whether the adapter name is already in use or not
|
||||||
|
text_encoder.load_adapter(
|
||||||
|
adapter_name=adapter_name,
|
||||||
|
adapter_state_dict=text_encoder_lora_state_dict,
|
||||||
|
peft_config=lora_config,
|
||||||
|
)
|
||||||
|
|
||||||
|
# scale LoRA layers with `lora_scale`
|
||||||
|
scale_lora_layers(text_encoder, weight=lora_scale)
|
||||||
|
|
||||||
|
text_encoder.to(device=text_encoder.device, dtype=text_encoder.dtype)
|
||||||
|
|
||||||
|
# Offload back.
|
||||||
|
if is_model_cpu_offload:
|
||||||
|
_pipeline.enable_model_cpu_offload()
|
||||||
|
elif is_sequential_cpu_offload:
|
||||||
|
_pipeline.enable_sequential_cpu_offload()
|
||||||
|
# Unsafe code />
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
# Copied from diffusers.loaders.lora_pipeline.StableDiffusionLoraLoaderMixin.save_lora_weights with unet->transformer
|
||||||
|
def save_lora_weights(
|
||||||
|
cls,
|
||||||
|
save_directory: Union[str, os.PathLike],
|
||||||
|
transformer_lora_layers: Dict[str, Union[torch.nn.Module, torch.Tensor]] = None,
|
||||||
|
text_encoder_lora_layers: Dict[str, torch.nn.Module] = None,
|
||||||
|
is_main_process: bool = True,
|
||||||
|
weight_name: str = None,
|
||||||
|
save_function: Callable = None,
|
||||||
|
safe_serialization: bool = True,
|
||||||
|
):
|
||||||
|
r"""
|
||||||
|
Save the LoRA parameters corresponding to the UNet and text encoder.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
save_directory (`str` or `os.PathLike`):
|
||||||
|
Directory to save LoRA parameters to. Will be created if it doesn't exist.
|
||||||
|
transformer_lora_layers (`Dict[str, torch.nn.Module]` or `Dict[str, torch.Tensor]`):
|
||||||
|
State dict of the LoRA layers corresponding to the `transformer`.
|
||||||
|
text_encoder_lora_layers (`Dict[str, torch.nn.Module]` or `Dict[str, torch.Tensor]`):
|
||||||
|
State dict of the LoRA layers corresponding to the `text_encoder`. Must explicitly pass the text
|
||||||
|
encoder LoRA state dict because it comes from 🤗 Transformers.
|
||||||
|
is_main_process (`bool`, *optional*, defaults to `True`):
|
||||||
|
Whether the process calling this is the main process or not. Useful during distributed training and you
|
||||||
|
need to call this function on all processes. In this case, set `is_main_process=True` only on the main
|
||||||
|
process to avoid race conditions.
|
||||||
|
save_function (`Callable`):
|
||||||
|
The function to use to save the state dictionary. Useful during distributed training when you need to
|
||||||
|
replace `torch.save` with another method. Can be configured with the environment variable
|
||||||
|
`DIFFUSERS_SAVE_MODE`.
|
||||||
|
safe_serialization (`bool`, *optional*, defaults to `True`):
|
||||||
|
Whether to save the model using `safetensors` or the traditional PyTorch way with `pickle`.
|
||||||
|
"""
|
||||||
|
state_dict = {}
|
||||||
|
|
||||||
|
if not (transformer_lora_layers or text_encoder_lora_layers):
|
||||||
|
raise ValueError("You must pass at least one of `transformer_lora_layers` and `text_encoder_lora_layers`.")
|
||||||
|
|
||||||
|
if transformer_lora_layers:
|
||||||
|
state_dict.update(cls.pack_weights(transformer_lora_layers, cls.transformer_name))
|
||||||
|
|
||||||
|
if text_encoder_lora_layers:
|
||||||
|
state_dict.update(cls.pack_weights(text_encoder_lora_layers, cls.text_encoder_name))
|
||||||
|
|
||||||
|
# Save the model
|
||||||
|
cls.write_lora_layers(
|
||||||
|
state_dict=state_dict,
|
||||||
|
save_directory=save_directory,
|
||||||
|
is_main_process=is_main_process,
|
||||||
|
weight_name=weight_name,
|
||||||
|
save_function=save_function,
|
||||||
|
safe_serialization=safe_serialization,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Copied from diffusers.loaders.lora_pipeline.StableDiffusionLoraLoaderMixin.fuse_lora with unet->transformer
|
||||||
|
def fuse_lora(
|
||||||
|
self,
|
||||||
|
components: List[str] = ["transformer", "text_encoder"],
|
||||||
|
lora_scale: float = 1.0,
|
||||||
|
safe_fusing: bool = False,
|
||||||
|
adapter_names: Optional[List[str]] = None,
|
||||||
|
**kwargs,
|
||||||
|
):
|
||||||
|
r"""
|
||||||
|
Fuses the LoRA parameters into the original parameters of the corresponding blocks.
|
||||||
|
|
||||||
|
<Tip warning={true}>
|
||||||
|
|
||||||
|
This is an experimental API.
|
||||||
|
|
||||||
|
</Tip>
|
||||||
|
|
||||||
|
Args:
|
||||||
|
components: (`List[str]`): List of LoRA-injectable components to fuse the LoRAs into.
|
||||||
|
lora_scale (`float`, defaults to 1.0):
|
||||||
|
Controls how much to influence the outputs with the LoRA parameters.
|
||||||
|
safe_fusing (`bool`, defaults to `False`):
|
||||||
|
Whether to check fused weights for NaN values before fusing and if values are NaN not fusing them.
|
||||||
|
adapter_names (`List[str]`, *optional*):
|
||||||
|
Adapter names to be used for fusing. If nothing is passed, all active adapters will be fused.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```py
|
||||||
|
from diffusers import DiffusionPipeline
|
||||||
|
import torch
|
||||||
|
|
||||||
|
pipeline = DiffusionPipeline.from_pretrained(
|
||||||
|
"stabilityai/stable-diffusion-xl-base-1.0", torch_dtype=torch.float16
|
||||||
|
).to("cuda")
|
||||||
|
pipeline.load_lora_weights("nerijs/pixel-art-xl", weight_name="pixel-art-xl.safetensors", adapter_name="pixel")
|
||||||
|
pipeline.fuse_lora(lora_scale=0.7)
|
||||||
|
```
|
||||||
|
"""
|
||||||
|
super().fuse_lora(
|
||||||
|
components=components, lora_scale=lora_scale, safe_fusing=safe_fusing, adapter_names=adapter_names
|
||||||
|
)
|
||||||
|
|
||||||
|
def unfuse_lora(self, components: List[str] = ["transformer", "text_encoder"], **kwargs):
|
||||||
|
r"""
|
||||||
|
Reverses the effect of
|
||||||
|
[`pipe.fuse_lora()`](https://huggingface.co/docs/diffusers/main/en/api/loaders#diffusers.loaders.LoraBaseMixin.fuse_lora).
|
||||||
|
|
||||||
|
<Tip warning={true}>
|
||||||
|
|
||||||
|
This is an experimental API.
|
||||||
|
|
||||||
|
</Tip>
|
||||||
|
|
||||||
|
Args:
|
||||||
|
components (`List[str]`): List of LoRA-injectable components to unfuse LoRA from.
|
||||||
|
"""
|
||||||
|
super().unfuse_lora(components=components)
|
||||||
|
|
||||||
|
|
||||||
# The reason why we subclass from `StableDiffusionLoraLoaderMixin` here is because Amused initially
|
# The reason why we subclass from `StableDiffusionLoraLoaderMixin` here is because Amused initially
|
||||||
# relied on `StableDiffusionLoraLoaderMixin` for its LoRA support.
|
# relied on `StableDiffusionLoraLoaderMixin` for its LoRA support.
|
||||||
class AmusedLoraLoaderMixin(StableDiffusionLoraLoaderMixin):
|
class AmusedLoraLoaderMixin(StableDiffusionLoraLoaderMixin):
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ _SET_ADAPTER_SCALE_FN_MAPPING = {
|
|||||||
"UNet2DConditionModel": _maybe_expand_lora_scales,
|
"UNet2DConditionModel": _maybe_expand_lora_scales,
|
||||||
"UNetMotionModel": _maybe_expand_lora_scales,
|
"UNetMotionModel": _maybe_expand_lora_scales,
|
||||||
"SD3Transformer2DModel": lambda model_cls, weights: weights,
|
"SD3Transformer2DModel": lambda model_cls, weights: weights,
|
||||||
|
"FluxTransformer2DModel": lambda model_cls, weights: weights,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ from packaging import version
|
|||||||
from ..utils import deprecate, is_transformers_available, logging
|
from ..utils import deprecate, is_transformers_available, logging
|
||||||
from .single_file_utils import (
|
from .single_file_utils import (
|
||||||
SingleFileComponentError,
|
SingleFileComponentError,
|
||||||
|
_is_legacy_scheduler_kwargs,
|
||||||
_is_model_weights_in_cached_folder,
|
_is_model_weights_in_cached_folder,
|
||||||
_legacy_load_clip_tokenizer,
|
_legacy_load_clip_tokenizer,
|
||||||
_legacy_load_safety_checker,
|
_legacy_load_safety_checker,
|
||||||
@@ -42,7 +43,6 @@ logger = logging.get_logger(__name__)
|
|||||||
# Legacy behaviour. `from_single_file` does not load the safety checker unless explicitly provided
|
# Legacy behaviour. `from_single_file` does not load the safety checker unless explicitly provided
|
||||||
SINGLE_FILE_OPTIONAL_COMPONENTS = ["safety_checker"]
|
SINGLE_FILE_OPTIONAL_COMPONENTS = ["safety_checker"]
|
||||||
|
|
||||||
|
|
||||||
if is_transformers_available():
|
if is_transformers_available():
|
||||||
import transformers
|
import transformers
|
||||||
from transformers import PreTrainedModel, PreTrainedTokenizer
|
from transformers import PreTrainedModel, PreTrainedTokenizer
|
||||||
@@ -135,7 +135,7 @@ def load_single_file_sub_model(
|
|||||||
class_obj, checkpoint=checkpoint, config=cached_model_config_path, local_files_only=local_files_only
|
class_obj, checkpoint=checkpoint, config=cached_model_config_path, local_files_only=local_files_only
|
||||||
)
|
)
|
||||||
|
|
||||||
elif is_diffusers_scheduler and is_legacy_loading:
|
elif is_diffusers_scheduler and (is_legacy_loading or _is_legacy_scheduler_kwargs(kwargs)):
|
||||||
loaded_sub_model = _legacy_load_scheduler(
|
loaded_sub_model = _legacy_load_scheduler(
|
||||||
class_obj, checkpoint=checkpoint, component_name=name, original_config=original_config, **kwargs
|
class_obj, checkpoint=checkpoint, component_name=name, original_config=original_config, **kwargs
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ from .single_file_utils import (
|
|||||||
SingleFileComponentError,
|
SingleFileComponentError,
|
||||||
convert_animatediff_checkpoint_to_diffusers,
|
convert_animatediff_checkpoint_to_diffusers,
|
||||||
convert_controlnet_checkpoint,
|
convert_controlnet_checkpoint,
|
||||||
|
convert_flux_transformer_checkpoint_to_diffusers,
|
||||||
convert_ldm_unet_checkpoint,
|
convert_ldm_unet_checkpoint,
|
||||||
convert_ldm_vae_checkpoint,
|
convert_ldm_vae_checkpoint,
|
||||||
convert_sd3_transformer_checkpoint_to_diffusers,
|
convert_sd3_transformer_checkpoint_to_diffusers,
|
||||||
@@ -74,6 +75,13 @@ SINGLE_FILE_LOADABLE_CLASSES = {
|
|||||||
"MotionAdapter": {
|
"MotionAdapter": {
|
||||||
"checkpoint_mapping_fn": convert_animatediff_checkpoint_to_diffusers,
|
"checkpoint_mapping_fn": convert_animatediff_checkpoint_to_diffusers,
|
||||||
},
|
},
|
||||||
|
"SparseControlNetModel": {
|
||||||
|
"checkpoint_mapping_fn": convert_animatediff_checkpoint_to_diffusers,
|
||||||
|
},
|
||||||
|
"FluxTransformer2DModel": {
|
||||||
|
"checkpoint_mapping_fn": convert_flux_transformer_checkpoint_to_diffusers,
|
||||||
|
"default_subfolder": "transformer",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -74,9 +74,15 @@ CHECKPOINT_KEY_NAMES = {
|
|||||||
"stable_cascade_stage_b": "down_blocks.1.0.channelwise.0.weight",
|
"stable_cascade_stage_b": "down_blocks.1.0.channelwise.0.weight",
|
||||||
"stable_cascade_stage_c": "clip_txt_mapper.weight",
|
"stable_cascade_stage_c": "clip_txt_mapper.weight",
|
||||||
"sd3": "model.diffusion_model.joint_blocks.0.context_block.adaLN_modulation.1.bias",
|
"sd3": "model.diffusion_model.joint_blocks.0.context_block.adaLN_modulation.1.bias",
|
||||||
"animatediff": "down_blocks.0.motion_modules.0.temporal_transformer.transformer_blocks.0.attention_blocks.1.pos_encoder.pe",
|
"animatediff": "down_blocks.0.motion_modules.0.temporal_transformer.transformer_blocks.0.attention_blocks.0.pos_encoder.pe",
|
||||||
"animatediff_v2": "mid_block.motion_modules.0.temporal_transformer.norm.bias",
|
"animatediff_v2": "mid_block.motion_modules.0.temporal_transformer.norm.bias",
|
||||||
"animatediff_sdxl_beta": "up_blocks.2.motion_modules.0.temporal_transformer.norm.weight",
|
"animatediff_sdxl_beta": "up_blocks.2.motion_modules.0.temporal_transformer.norm.weight",
|
||||||
|
"animatediff_scribble": "controlnet_cond_embedding.conv_in.weight",
|
||||||
|
"animatediff_rgb": "controlnet_cond_embedding.weight",
|
||||||
|
"flux": [
|
||||||
|
"double_blocks.0.img_attn.norm.key_norm.scale",
|
||||||
|
"model.diffusion_model.double_blocks.0.img_attn.norm.key_norm.scale",
|
||||||
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
DIFFUSERS_DEFAULT_PIPELINE_PATHS = {
|
DIFFUSERS_DEFAULT_PIPELINE_PATHS = {
|
||||||
@@ -110,6 +116,10 @@ DIFFUSERS_DEFAULT_PIPELINE_PATHS = {
|
|||||||
"animatediff_v2": {"pretrained_model_name_or_path": "guoyww/animatediff-motion-adapter-v1-5-2"},
|
"animatediff_v2": {"pretrained_model_name_or_path": "guoyww/animatediff-motion-adapter-v1-5-2"},
|
||||||
"animatediff_v3": {"pretrained_model_name_or_path": "guoyww/animatediff-motion-adapter-v1-5-3"},
|
"animatediff_v3": {"pretrained_model_name_or_path": "guoyww/animatediff-motion-adapter-v1-5-3"},
|
||||||
"animatediff_sdxl_beta": {"pretrained_model_name_or_path": "guoyww/animatediff-motion-adapter-sdxl-beta"},
|
"animatediff_sdxl_beta": {"pretrained_model_name_or_path": "guoyww/animatediff-motion-adapter-sdxl-beta"},
|
||||||
|
"animatediff_scribble": {"pretrained_model_name_or_path": "guoyww/animatediff-sparsectrl-scribble"},
|
||||||
|
"animatediff_rgb": {"pretrained_model_name_or_path": "guoyww/animatediff-sparsectrl-rgb"},
|
||||||
|
"flux-dev": {"pretrained_model_name_or_path": "black-forest-labs/FLUX.1-dev"},
|
||||||
|
"flux-schnell": {"pretrained_model_name_or_path": "black-forest-labs/FLUX.1-schnell"},
|
||||||
}
|
}
|
||||||
|
|
||||||
# Use to configure model sample size when original config is provided
|
# Use to configure model sample size when original config is provided
|
||||||
@@ -251,7 +261,7 @@ SCHEDULER_DEFAULT_CONFIG = {
|
|||||||
"timestep_spacing": "leading",
|
"timestep_spacing": "leading",
|
||||||
}
|
}
|
||||||
|
|
||||||
LDM_VAE_KEY = "first_stage_model."
|
LDM_VAE_KEYS = ["first_stage_model.", "vae."]
|
||||||
LDM_VAE_DEFAULT_SCALING_FACTOR = 0.18215
|
LDM_VAE_DEFAULT_SCALING_FACTOR = 0.18215
|
||||||
PLAYGROUND_VAE_SCALING_FACTOR = 0.5
|
PLAYGROUND_VAE_SCALING_FACTOR = 0.5
|
||||||
LDM_UNET_KEY = "model.diffusion_model."
|
LDM_UNET_KEY = "model.diffusion_model."
|
||||||
@@ -260,8 +270,8 @@ LDM_CLIP_PREFIX_TO_REMOVE = [
|
|||||||
"cond_stage_model.transformer.",
|
"cond_stage_model.transformer.",
|
||||||
"conditioner.embedders.0.transformer.",
|
"conditioner.embedders.0.transformer.",
|
||||||
]
|
]
|
||||||
OPEN_CLIP_PREFIX = "conditioner.embedders.0.model."
|
|
||||||
LDM_OPEN_CLIP_TEXT_PROJECTION_DIM = 1024
|
LDM_OPEN_CLIP_TEXT_PROJECTION_DIM = 1024
|
||||||
|
SCHEDULER_LEGACY_KWARGS = ["prediction_type", "scheduler_type"]
|
||||||
|
|
||||||
VALID_URL_PREFIXES = ["https://huggingface.co/", "huggingface.co/", "hf.co/", "https://hf.co/"]
|
VALID_URL_PREFIXES = ["https://huggingface.co/", "huggingface.co/", "hf.co/", "https://hf.co/"]
|
||||||
|
|
||||||
@@ -311,6 +321,10 @@ def _is_model_weights_in_cached_folder(cached_folder, name):
|
|||||||
return weights_exist
|
return weights_exist
|
||||||
|
|
||||||
|
|
||||||
|
def _is_legacy_scheduler_kwargs(kwargs):
|
||||||
|
return any(k in SCHEDULER_LEGACY_KWARGS for k in kwargs.keys())
|
||||||
|
|
||||||
|
|
||||||
def load_single_file_checkpoint(
|
def load_single_file_checkpoint(
|
||||||
pretrained_model_link_or_path,
|
pretrained_model_link_or_path,
|
||||||
force_download=False,
|
force_download=False,
|
||||||
@@ -491,7 +505,13 @@ def infer_diffusers_model_type(checkpoint):
|
|||||||
model_type = "sd3"
|
model_type = "sd3"
|
||||||
|
|
||||||
elif CHECKPOINT_KEY_NAMES["animatediff"] in checkpoint:
|
elif CHECKPOINT_KEY_NAMES["animatediff"] in checkpoint:
|
||||||
if CHECKPOINT_KEY_NAMES["animatediff_v2"] in checkpoint:
|
if CHECKPOINT_KEY_NAMES["animatediff_scribble"] in checkpoint:
|
||||||
|
model_type = "animatediff_scribble"
|
||||||
|
|
||||||
|
elif CHECKPOINT_KEY_NAMES["animatediff_rgb"] in checkpoint:
|
||||||
|
model_type = "animatediff_rgb"
|
||||||
|
|
||||||
|
elif CHECKPOINT_KEY_NAMES["animatediff_v2"] in checkpoint:
|
||||||
model_type = "animatediff_v2"
|
model_type = "animatediff_v2"
|
||||||
|
|
||||||
elif checkpoint[CHECKPOINT_KEY_NAMES["animatediff_sdxl_beta"]].shape[-1] == 320:
|
elif checkpoint[CHECKPOINT_KEY_NAMES["animatediff_sdxl_beta"]].shape[-1] == 320:
|
||||||
@@ -503,6 +523,13 @@ def infer_diffusers_model_type(checkpoint):
|
|||||||
else:
|
else:
|
||||||
model_type = "animatediff_v3"
|
model_type = "animatediff_v3"
|
||||||
|
|
||||||
|
elif any(key in checkpoint for key in CHECKPOINT_KEY_NAMES["flux"]):
|
||||||
|
if any(
|
||||||
|
g in checkpoint for g in ["guidance_in.in_layer.bias", "model.diffusion_model.guidance_in.in_layer.bias"]
|
||||||
|
):
|
||||||
|
model_type = "flux-dev"
|
||||||
|
else:
|
||||||
|
model_type = "flux-schnell"
|
||||||
else:
|
else:
|
||||||
model_type = "v1"
|
model_type = "v1"
|
||||||
|
|
||||||
@@ -1158,7 +1185,11 @@ def convert_ldm_vae_checkpoint(checkpoint, config):
|
|||||||
# remove the LDM_VAE_KEY prefix from the ldm checkpoint keys so that it is easier to map them to diffusers keys
|
# remove the LDM_VAE_KEY prefix from the ldm checkpoint keys so that it is easier to map them to diffusers keys
|
||||||
vae_state_dict = {}
|
vae_state_dict = {}
|
||||||
keys = list(checkpoint.keys())
|
keys = list(checkpoint.keys())
|
||||||
vae_key = LDM_VAE_KEY if any(k.startswith(LDM_VAE_KEY) for k in keys) else ""
|
vae_key = ""
|
||||||
|
for ldm_vae_key in LDM_VAE_KEYS:
|
||||||
|
if any(k.startswith(ldm_vae_key) for k in keys):
|
||||||
|
vae_key = ldm_vae_key
|
||||||
|
|
||||||
for key in keys:
|
for key in keys:
|
||||||
if key.startswith(vae_key):
|
if key.startswith(vae_key):
|
||||||
vae_state_dict[key.replace(vae_key, "")] = checkpoint.get(key)
|
vae_state_dict[key.replace(vae_key, "")] = checkpoint.get(key)
|
||||||
@@ -1459,14 +1490,22 @@ def _legacy_load_scheduler(
|
|||||||
|
|
||||||
if scheduler_type is not None:
|
if scheduler_type is not None:
|
||||||
deprecation_message = (
|
deprecation_message = (
|
||||||
"Please pass an instance of a Scheduler object directly to the `scheduler` argument in `from_single_file`."
|
"Please pass an instance of a Scheduler object directly to the `scheduler` argument in `from_single_file`\n\n"
|
||||||
|
"Example:\n\n"
|
||||||
|
"from diffusers import StableDiffusionPipeline, DDIMScheduler\n\n"
|
||||||
|
"scheduler = DDIMScheduler()\n"
|
||||||
|
"pipe = StableDiffusionPipeline.from_single_file(<checkpoint path>, scheduler=scheduler)\n"
|
||||||
)
|
)
|
||||||
deprecate("scheduler_type", "1.0.0", deprecation_message)
|
deprecate("scheduler_type", "1.0.0", deprecation_message)
|
||||||
|
|
||||||
if prediction_type is not None:
|
if prediction_type is not None:
|
||||||
deprecation_message = (
|
deprecation_message = (
|
||||||
"Please configure an instance of a Scheduler with the appropriate `prediction_type` "
|
"Please configure an instance of a Scheduler with the appropriate `prediction_type` and "
|
||||||
"and pass the object directly to the `scheduler` argument in `from_single_file`."
|
"pass the object directly to the `scheduler` argument in `from_single_file`.\n\n"
|
||||||
|
"Example:\n\n"
|
||||||
|
"from diffusers import StableDiffusionPipeline, DDIMScheduler\n\n"
|
||||||
|
'scheduler = DDIMScheduler(prediction_type="v_prediction")\n'
|
||||||
|
"pipe = StableDiffusionPipeline.from_single_file(<checkpoint path>, scheduler=scheduler)\n"
|
||||||
)
|
)
|
||||||
deprecate("prediction_type", "1.0.0", deprecation_message)
|
deprecate("prediction_type", "1.0.0", deprecation_message)
|
||||||
|
|
||||||
@@ -1859,3 +1898,199 @@ def convert_animatediff_checkpoint_to_diffusers(checkpoint, **kwargs):
|
|||||||
] = v
|
] = v
|
||||||
|
|
||||||
return converted_state_dict
|
return converted_state_dict
|
||||||
|
|
||||||
|
|
||||||
|
def convert_flux_transformer_checkpoint_to_diffusers(checkpoint, **kwargs):
|
||||||
|
converted_state_dict = {}
|
||||||
|
keys = list(checkpoint.keys())
|
||||||
|
for k in keys:
|
||||||
|
if "model.diffusion_model." in k:
|
||||||
|
checkpoint[k.replace("model.diffusion_model.", "")] = checkpoint.pop(k)
|
||||||
|
|
||||||
|
num_layers = list(set(int(k.split(".", 2)[1]) for k in checkpoint if "double_blocks." in k))[-1] + 1 # noqa: C401
|
||||||
|
num_single_layers = list(set(int(k.split(".", 2)[1]) for k in checkpoint if "single_blocks." in k))[-1] + 1 # noqa: C401
|
||||||
|
mlp_ratio = 4.0
|
||||||
|
inner_dim = 3072
|
||||||
|
|
||||||
|
# in SD3 original implementation of AdaLayerNormContinuous, it split linear projection output into shift, scale;
|
||||||
|
# while in diffusers it split into scale, shift. Here we swap the linear projection weights in order to be able to use diffusers implementation
|
||||||
|
def swap_scale_shift(weight):
|
||||||
|
shift, scale = weight.chunk(2, dim=0)
|
||||||
|
new_weight = torch.cat([scale, shift], dim=0)
|
||||||
|
return new_weight
|
||||||
|
|
||||||
|
## time_text_embed.timestep_embedder <- time_in
|
||||||
|
converted_state_dict["time_text_embed.timestep_embedder.linear_1.weight"] = checkpoint.pop(
|
||||||
|
"time_in.in_layer.weight"
|
||||||
|
)
|
||||||
|
converted_state_dict["time_text_embed.timestep_embedder.linear_1.bias"] = checkpoint.pop("time_in.in_layer.bias")
|
||||||
|
converted_state_dict["time_text_embed.timestep_embedder.linear_2.weight"] = checkpoint.pop(
|
||||||
|
"time_in.out_layer.weight"
|
||||||
|
)
|
||||||
|
converted_state_dict["time_text_embed.timestep_embedder.linear_2.bias"] = checkpoint.pop("time_in.out_layer.bias")
|
||||||
|
|
||||||
|
## time_text_embed.text_embedder <- vector_in
|
||||||
|
converted_state_dict["time_text_embed.text_embedder.linear_1.weight"] = checkpoint.pop("vector_in.in_layer.weight")
|
||||||
|
converted_state_dict["time_text_embed.text_embedder.linear_1.bias"] = checkpoint.pop("vector_in.in_layer.bias")
|
||||||
|
converted_state_dict["time_text_embed.text_embedder.linear_2.weight"] = checkpoint.pop(
|
||||||
|
"vector_in.out_layer.weight"
|
||||||
|
)
|
||||||
|
converted_state_dict["time_text_embed.text_embedder.linear_2.bias"] = checkpoint.pop("vector_in.out_layer.bias")
|
||||||
|
|
||||||
|
# guidance
|
||||||
|
has_guidance = any("guidance" in k for k in checkpoint)
|
||||||
|
if has_guidance:
|
||||||
|
converted_state_dict["time_text_embed.guidance_embedder.linear_1.weight"] = checkpoint.pop(
|
||||||
|
"guidance_in.in_layer.weight"
|
||||||
|
)
|
||||||
|
converted_state_dict["time_text_embed.guidance_embedder.linear_1.bias"] = checkpoint.pop(
|
||||||
|
"guidance_in.in_layer.bias"
|
||||||
|
)
|
||||||
|
converted_state_dict["time_text_embed.guidance_embedder.linear_2.weight"] = checkpoint.pop(
|
||||||
|
"guidance_in.out_layer.weight"
|
||||||
|
)
|
||||||
|
converted_state_dict["time_text_embed.guidance_embedder.linear_2.bias"] = checkpoint.pop(
|
||||||
|
"guidance_in.out_layer.bias"
|
||||||
|
)
|
||||||
|
|
||||||
|
# context_embedder
|
||||||
|
converted_state_dict["context_embedder.weight"] = checkpoint.pop("txt_in.weight")
|
||||||
|
converted_state_dict["context_embedder.bias"] = checkpoint.pop("txt_in.bias")
|
||||||
|
|
||||||
|
# x_embedder
|
||||||
|
converted_state_dict["x_embedder.weight"] = checkpoint.pop("img_in.weight")
|
||||||
|
converted_state_dict["x_embedder.bias"] = checkpoint.pop("img_in.bias")
|
||||||
|
|
||||||
|
# double transformer blocks
|
||||||
|
for i in range(num_layers):
|
||||||
|
block_prefix = f"transformer_blocks.{i}."
|
||||||
|
# norms.
|
||||||
|
## norm1
|
||||||
|
converted_state_dict[f"{block_prefix}norm1.linear.weight"] = checkpoint.pop(
|
||||||
|
f"double_blocks.{i}.img_mod.lin.weight"
|
||||||
|
)
|
||||||
|
converted_state_dict[f"{block_prefix}norm1.linear.bias"] = checkpoint.pop(
|
||||||
|
f"double_blocks.{i}.img_mod.lin.bias"
|
||||||
|
)
|
||||||
|
## norm1_context
|
||||||
|
converted_state_dict[f"{block_prefix}norm1_context.linear.weight"] = checkpoint.pop(
|
||||||
|
f"double_blocks.{i}.txt_mod.lin.weight"
|
||||||
|
)
|
||||||
|
converted_state_dict[f"{block_prefix}norm1_context.linear.bias"] = checkpoint.pop(
|
||||||
|
f"double_blocks.{i}.txt_mod.lin.bias"
|
||||||
|
)
|
||||||
|
# Q, K, V
|
||||||
|
sample_q, sample_k, sample_v = torch.chunk(checkpoint.pop(f"double_blocks.{i}.img_attn.qkv.weight"), 3, dim=0)
|
||||||
|
context_q, context_k, context_v = torch.chunk(
|
||||||
|
checkpoint.pop(f"double_blocks.{i}.txt_attn.qkv.weight"), 3, dim=0
|
||||||
|
)
|
||||||
|
sample_q_bias, sample_k_bias, sample_v_bias = torch.chunk(
|
||||||
|
checkpoint.pop(f"double_blocks.{i}.img_attn.qkv.bias"), 3, dim=0
|
||||||
|
)
|
||||||
|
context_q_bias, context_k_bias, context_v_bias = torch.chunk(
|
||||||
|
checkpoint.pop(f"double_blocks.{i}.txt_attn.qkv.bias"), 3, dim=0
|
||||||
|
)
|
||||||
|
converted_state_dict[f"{block_prefix}attn.to_q.weight"] = torch.cat([sample_q])
|
||||||
|
converted_state_dict[f"{block_prefix}attn.to_q.bias"] = torch.cat([sample_q_bias])
|
||||||
|
converted_state_dict[f"{block_prefix}attn.to_k.weight"] = torch.cat([sample_k])
|
||||||
|
converted_state_dict[f"{block_prefix}attn.to_k.bias"] = torch.cat([sample_k_bias])
|
||||||
|
converted_state_dict[f"{block_prefix}attn.to_v.weight"] = torch.cat([sample_v])
|
||||||
|
converted_state_dict[f"{block_prefix}attn.to_v.bias"] = torch.cat([sample_v_bias])
|
||||||
|
converted_state_dict[f"{block_prefix}attn.add_q_proj.weight"] = torch.cat([context_q])
|
||||||
|
converted_state_dict[f"{block_prefix}attn.add_q_proj.bias"] = torch.cat([context_q_bias])
|
||||||
|
converted_state_dict[f"{block_prefix}attn.add_k_proj.weight"] = torch.cat([context_k])
|
||||||
|
converted_state_dict[f"{block_prefix}attn.add_k_proj.bias"] = torch.cat([context_k_bias])
|
||||||
|
converted_state_dict[f"{block_prefix}attn.add_v_proj.weight"] = torch.cat([context_v])
|
||||||
|
converted_state_dict[f"{block_prefix}attn.add_v_proj.bias"] = torch.cat([context_v_bias])
|
||||||
|
# qk_norm
|
||||||
|
converted_state_dict[f"{block_prefix}attn.norm_q.weight"] = checkpoint.pop(
|
||||||
|
f"double_blocks.{i}.img_attn.norm.query_norm.scale"
|
||||||
|
)
|
||||||
|
converted_state_dict[f"{block_prefix}attn.norm_k.weight"] = checkpoint.pop(
|
||||||
|
f"double_blocks.{i}.img_attn.norm.key_norm.scale"
|
||||||
|
)
|
||||||
|
converted_state_dict[f"{block_prefix}attn.norm_added_q.weight"] = checkpoint.pop(
|
||||||
|
f"double_blocks.{i}.txt_attn.norm.query_norm.scale"
|
||||||
|
)
|
||||||
|
converted_state_dict[f"{block_prefix}attn.norm_added_k.weight"] = checkpoint.pop(
|
||||||
|
f"double_blocks.{i}.txt_attn.norm.key_norm.scale"
|
||||||
|
)
|
||||||
|
# ff img_mlp
|
||||||
|
converted_state_dict[f"{block_prefix}ff.net.0.proj.weight"] = checkpoint.pop(
|
||||||
|
f"double_blocks.{i}.img_mlp.0.weight"
|
||||||
|
)
|
||||||
|
converted_state_dict[f"{block_prefix}ff.net.0.proj.bias"] = checkpoint.pop(f"double_blocks.{i}.img_mlp.0.bias")
|
||||||
|
converted_state_dict[f"{block_prefix}ff.net.2.weight"] = checkpoint.pop(f"double_blocks.{i}.img_mlp.2.weight")
|
||||||
|
converted_state_dict[f"{block_prefix}ff.net.2.bias"] = checkpoint.pop(f"double_blocks.{i}.img_mlp.2.bias")
|
||||||
|
converted_state_dict[f"{block_prefix}ff_context.net.0.proj.weight"] = checkpoint.pop(
|
||||||
|
f"double_blocks.{i}.txt_mlp.0.weight"
|
||||||
|
)
|
||||||
|
converted_state_dict[f"{block_prefix}ff_context.net.0.proj.bias"] = checkpoint.pop(
|
||||||
|
f"double_blocks.{i}.txt_mlp.0.bias"
|
||||||
|
)
|
||||||
|
converted_state_dict[f"{block_prefix}ff_context.net.2.weight"] = checkpoint.pop(
|
||||||
|
f"double_blocks.{i}.txt_mlp.2.weight"
|
||||||
|
)
|
||||||
|
converted_state_dict[f"{block_prefix}ff_context.net.2.bias"] = checkpoint.pop(
|
||||||
|
f"double_blocks.{i}.txt_mlp.2.bias"
|
||||||
|
)
|
||||||
|
# output projections.
|
||||||
|
converted_state_dict[f"{block_prefix}attn.to_out.0.weight"] = checkpoint.pop(
|
||||||
|
f"double_blocks.{i}.img_attn.proj.weight"
|
||||||
|
)
|
||||||
|
converted_state_dict[f"{block_prefix}attn.to_out.0.bias"] = checkpoint.pop(
|
||||||
|
f"double_blocks.{i}.img_attn.proj.bias"
|
||||||
|
)
|
||||||
|
converted_state_dict[f"{block_prefix}attn.to_add_out.weight"] = checkpoint.pop(
|
||||||
|
f"double_blocks.{i}.txt_attn.proj.weight"
|
||||||
|
)
|
||||||
|
converted_state_dict[f"{block_prefix}attn.to_add_out.bias"] = checkpoint.pop(
|
||||||
|
f"double_blocks.{i}.txt_attn.proj.bias"
|
||||||
|
)
|
||||||
|
|
||||||
|
# single transfomer blocks
|
||||||
|
for i in range(num_single_layers):
|
||||||
|
block_prefix = f"single_transformer_blocks.{i}."
|
||||||
|
# norm.linear <- single_blocks.0.modulation.lin
|
||||||
|
converted_state_dict[f"{block_prefix}norm.linear.weight"] = checkpoint.pop(
|
||||||
|
f"single_blocks.{i}.modulation.lin.weight"
|
||||||
|
)
|
||||||
|
converted_state_dict[f"{block_prefix}norm.linear.bias"] = checkpoint.pop(
|
||||||
|
f"single_blocks.{i}.modulation.lin.bias"
|
||||||
|
)
|
||||||
|
# Q, K, V, mlp
|
||||||
|
mlp_hidden_dim = int(inner_dim * mlp_ratio)
|
||||||
|
split_size = (inner_dim, inner_dim, inner_dim, mlp_hidden_dim)
|
||||||
|
q, k, v, mlp = torch.split(checkpoint.pop(f"single_blocks.{i}.linear1.weight"), split_size, dim=0)
|
||||||
|
q_bias, k_bias, v_bias, mlp_bias = torch.split(
|
||||||
|
checkpoint.pop(f"single_blocks.{i}.linear1.bias"), split_size, dim=0
|
||||||
|
)
|
||||||
|
converted_state_dict[f"{block_prefix}attn.to_q.weight"] = torch.cat([q])
|
||||||
|
converted_state_dict[f"{block_prefix}attn.to_q.bias"] = torch.cat([q_bias])
|
||||||
|
converted_state_dict[f"{block_prefix}attn.to_k.weight"] = torch.cat([k])
|
||||||
|
converted_state_dict[f"{block_prefix}attn.to_k.bias"] = torch.cat([k_bias])
|
||||||
|
converted_state_dict[f"{block_prefix}attn.to_v.weight"] = torch.cat([v])
|
||||||
|
converted_state_dict[f"{block_prefix}attn.to_v.bias"] = torch.cat([v_bias])
|
||||||
|
converted_state_dict[f"{block_prefix}proj_mlp.weight"] = torch.cat([mlp])
|
||||||
|
converted_state_dict[f"{block_prefix}proj_mlp.bias"] = torch.cat([mlp_bias])
|
||||||
|
# qk norm
|
||||||
|
converted_state_dict[f"{block_prefix}attn.norm_q.weight"] = checkpoint.pop(
|
||||||
|
f"single_blocks.{i}.norm.query_norm.scale"
|
||||||
|
)
|
||||||
|
converted_state_dict[f"{block_prefix}attn.norm_k.weight"] = checkpoint.pop(
|
||||||
|
f"single_blocks.{i}.norm.key_norm.scale"
|
||||||
|
)
|
||||||
|
# output projections.
|
||||||
|
converted_state_dict[f"{block_prefix}proj_out.weight"] = checkpoint.pop(f"single_blocks.{i}.linear2.weight")
|
||||||
|
converted_state_dict[f"{block_prefix}proj_out.bias"] = checkpoint.pop(f"single_blocks.{i}.linear2.bias")
|
||||||
|
|
||||||
|
converted_state_dict["proj_out.weight"] = checkpoint.pop("final_layer.linear.weight")
|
||||||
|
converted_state_dict["proj_out.bias"] = checkpoint.pop("final_layer.linear.bias")
|
||||||
|
converted_state_dict["norm_out.linear.weight"] = swap_scale_shift(
|
||||||
|
checkpoint.pop("final_layer.adaLN_modulation.1.weight")
|
||||||
|
)
|
||||||
|
converted_state_dict["norm_out.linear.bias"] = swap_scale_shift(
|
||||||
|
checkpoint.pop("final_layer.adaLN_modulation.1.bias")
|
||||||
|
)
|
||||||
|
|
||||||
|
return converted_state_dict
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ if is_torch_available():
|
|||||||
_import_structure["adapter"] = ["MultiAdapter", "T2IAdapter"]
|
_import_structure["adapter"] = ["MultiAdapter", "T2IAdapter"]
|
||||||
_import_structure["autoencoders.autoencoder_asym_kl"] = ["AsymmetricAutoencoderKL"]
|
_import_structure["autoencoders.autoencoder_asym_kl"] = ["AsymmetricAutoencoderKL"]
|
||||||
_import_structure["autoencoders.autoencoder_kl"] = ["AutoencoderKL"]
|
_import_structure["autoencoders.autoencoder_kl"] = ["AutoencoderKL"]
|
||||||
|
_import_structure["autoencoders.autoencoder_kl_cogvideox"] = ["AutoencoderKLCogVideoX"]
|
||||||
_import_structure["autoencoders.autoencoder_kl_temporal_decoder"] = ["AutoencoderKLTemporalDecoder"]
|
_import_structure["autoencoders.autoencoder_kl_temporal_decoder"] = ["AutoencoderKLTemporalDecoder"]
|
||||||
_import_structure["autoencoders.autoencoder_oobleck"] = ["AutoencoderOobleck"]
|
_import_structure["autoencoders.autoencoder_oobleck"] = ["AutoencoderOobleck"]
|
||||||
_import_structure["autoencoders.autoencoder_tiny"] = ["AutoencoderTiny"]
|
_import_structure["autoencoders.autoencoder_tiny"] = ["AutoencoderTiny"]
|
||||||
@@ -41,6 +42,7 @@ if is_torch_available():
|
|||||||
_import_structure["embeddings"] = ["ImageProjection"]
|
_import_structure["embeddings"] = ["ImageProjection"]
|
||||||
_import_structure["modeling_utils"] = ["ModelMixin"]
|
_import_structure["modeling_utils"] = ["ModelMixin"]
|
||||||
_import_structure["transformers.auraflow_transformer_2d"] = ["AuraFlowTransformer2DModel"]
|
_import_structure["transformers.auraflow_transformer_2d"] = ["AuraFlowTransformer2DModel"]
|
||||||
|
_import_structure["transformers.cogvideox_transformer_3d"] = ["CogVideoXTransformer3DModel"]
|
||||||
_import_structure["transformers.dit_transformer_2d"] = ["DiTTransformer2DModel"]
|
_import_structure["transformers.dit_transformer_2d"] = ["DiTTransformer2DModel"]
|
||||||
_import_structure["transformers.dual_transformer_2d"] = ["DualTransformer2DModel"]
|
_import_structure["transformers.dual_transformer_2d"] = ["DualTransformer2DModel"]
|
||||||
_import_structure["transformers.hunyuan_transformer_2d"] = ["HunyuanDiT2DModel"]
|
_import_structure["transformers.hunyuan_transformer_2d"] = ["HunyuanDiT2DModel"]
|
||||||
@@ -51,6 +53,7 @@ if is_torch_available():
|
|||||||
_import_structure["transformers.stable_audio_transformer"] = ["StableAudioDiTModel"]
|
_import_structure["transformers.stable_audio_transformer"] = ["StableAudioDiTModel"]
|
||||||
_import_structure["transformers.t5_film_transformer"] = ["T5FilmDecoder"]
|
_import_structure["transformers.t5_film_transformer"] = ["T5FilmDecoder"]
|
||||||
_import_structure["transformers.transformer_2d"] = ["Transformer2DModel"]
|
_import_structure["transformers.transformer_2d"] = ["Transformer2DModel"]
|
||||||
|
_import_structure["transformers.transformer_flux"] = ["FluxTransformer2DModel"]
|
||||||
_import_structure["transformers.transformer_sd3"] = ["SD3Transformer2DModel"]
|
_import_structure["transformers.transformer_sd3"] = ["SD3Transformer2DModel"]
|
||||||
_import_structure["transformers.transformer_temporal"] = ["TransformerTemporalModel"]
|
_import_structure["transformers.transformer_temporal"] = ["TransformerTemporalModel"]
|
||||||
_import_structure["unets.unet_1d"] = ["UNet1DModel"]
|
_import_structure["unets.unet_1d"] = ["UNet1DModel"]
|
||||||
@@ -76,6 +79,7 @@ if TYPE_CHECKING or DIFFUSERS_SLOW_IMPORT:
|
|||||||
from .autoencoders import (
|
from .autoencoders import (
|
||||||
AsymmetricAutoencoderKL,
|
AsymmetricAutoencoderKL,
|
||||||
AutoencoderKL,
|
AutoencoderKL,
|
||||||
|
AutoencoderKLCogVideoX,
|
||||||
AutoencoderKLTemporalDecoder,
|
AutoencoderKLTemporalDecoder,
|
||||||
AutoencoderOobleck,
|
AutoencoderOobleck,
|
||||||
AutoencoderTiny,
|
AutoencoderTiny,
|
||||||
@@ -91,8 +95,10 @@ if TYPE_CHECKING or DIFFUSERS_SLOW_IMPORT:
|
|||||||
from .modeling_utils import ModelMixin
|
from .modeling_utils import ModelMixin
|
||||||
from .transformers import (
|
from .transformers import (
|
||||||
AuraFlowTransformer2DModel,
|
AuraFlowTransformer2DModel,
|
||||||
|
CogVideoXTransformer3DModel,
|
||||||
DiTTransformer2DModel,
|
DiTTransformer2DModel,
|
||||||
DualTransformer2DModel,
|
DualTransformer2DModel,
|
||||||
|
FluxTransformer2DModel,
|
||||||
HunyuanDiT2DModel,
|
HunyuanDiT2DModel,
|
||||||
LatteTransformer3DModel,
|
LatteTransformer3DModel,
|
||||||
LuminaNextDiT2DModel,
|
LuminaNextDiT2DModel,
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
from typing import Any, Dict, Optional
|
from typing import Any, Dict, List, Optional, Tuple
|
||||||
|
|
||||||
import torch
|
import torch
|
||||||
import torch.nn.functional as F
|
import torch.nn.functional as F
|
||||||
@@ -272,6 +272,17 @@ class BasicTransformerBlock(nn.Module):
|
|||||||
attention_out_bias: bool = True,
|
attention_out_bias: bool = True,
|
||||||
):
|
):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
self.dim = dim
|
||||||
|
self.num_attention_heads = num_attention_heads
|
||||||
|
self.attention_head_dim = attention_head_dim
|
||||||
|
self.dropout = dropout
|
||||||
|
self.cross_attention_dim = cross_attention_dim
|
||||||
|
self.activation_fn = activation_fn
|
||||||
|
self.attention_bias = attention_bias
|
||||||
|
self.double_self_attention = double_self_attention
|
||||||
|
self.norm_elementwise_affine = norm_elementwise_affine
|
||||||
|
self.positional_embeddings = positional_embeddings
|
||||||
|
self.num_positional_embeddings = num_positional_embeddings
|
||||||
self.only_cross_attention = only_cross_attention
|
self.only_cross_attention = only_cross_attention
|
||||||
|
|
||||||
# We keep these boolean flags for backward-compatibility.
|
# We keep these boolean flags for backward-compatibility.
|
||||||
@@ -376,7 +387,7 @@ class BasicTransformerBlock(nn.Module):
|
|||||||
"layer_norm",
|
"layer_norm",
|
||||||
)
|
)
|
||||||
|
|
||||||
elif norm_type in ["ada_norm_zero", "ada_norm", "layer_norm", "ada_norm_continuous"]:
|
elif norm_type in ["ada_norm_zero", "ada_norm", "layer_norm"]:
|
||||||
self.norm3 = nn.LayerNorm(dim, norm_eps, norm_elementwise_affine)
|
self.norm3 = nn.LayerNorm(dim, norm_eps, norm_elementwise_affine)
|
||||||
elif norm_type == "layer_norm_i2vgen":
|
elif norm_type == "layer_norm_i2vgen":
|
||||||
self.norm3 = None
|
self.norm3 = None
|
||||||
@@ -782,6 +793,319 @@ class SkipFFTransformerBlock(nn.Module):
|
|||||||
return hidden_states
|
return hidden_states
|
||||||
|
|
||||||
|
|
||||||
|
@maybe_allow_in_graph
|
||||||
|
class FreeNoiseTransformerBlock(nn.Module):
|
||||||
|
r"""
|
||||||
|
A FreeNoise Transformer block.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
dim (`int`):
|
||||||
|
The number of channels in the input and output.
|
||||||
|
num_attention_heads (`int`):
|
||||||
|
The number of heads to use for multi-head attention.
|
||||||
|
attention_head_dim (`int`):
|
||||||
|
The number of channels in each head.
|
||||||
|
dropout (`float`, *optional*, defaults to 0.0):
|
||||||
|
The dropout probability to use.
|
||||||
|
cross_attention_dim (`int`, *optional*):
|
||||||
|
The size of the encoder_hidden_states vector for cross attention.
|
||||||
|
activation_fn (`str`, *optional*, defaults to `"geglu"`):
|
||||||
|
Activation function to be used in feed-forward.
|
||||||
|
num_embeds_ada_norm (`int`, *optional*):
|
||||||
|
The number of diffusion steps used during training. See `Transformer2DModel`.
|
||||||
|
attention_bias (`bool`, defaults to `False`):
|
||||||
|
Configure if the attentions should contain a bias parameter.
|
||||||
|
only_cross_attention (`bool`, defaults to `False`):
|
||||||
|
Whether to use only cross-attention layers. In this case two cross attention layers are used.
|
||||||
|
double_self_attention (`bool`, defaults to `False`):
|
||||||
|
Whether to use two self-attention layers. In this case no cross attention layers are used.
|
||||||
|
upcast_attention (`bool`, defaults to `False`):
|
||||||
|
Whether to upcast the attention computation to float32. This is useful for mixed precision training.
|
||||||
|
norm_elementwise_affine (`bool`, defaults to `True`):
|
||||||
|
Whether to use learnable elementwise affine parameters for normalization.
|
||||||
|
norm_type (`str`, defaults to `"layer_norm"`):
|
||||||
|
The normalization layer to use. Can be `"layer_norm"`, `"ada_norm"` or `"ada_norm_zero"`.
|
||||||
|
final_dropout (`bool` defaults to `False`):
|
||||||
|
Whether to apply a final dropout after the last feed-forward layer.
|
||||||
|
attention_type (`str`, defaults to `"default"`):
|
||||||
|
The type of attention to use. Can be `"default"` or `"gated"` or `"gated-text-image"`.
|
||||||
|
positional_embeddings (`str`, *optional*):
|
||||||
|
The type of positional embeddings to apply to.
|
||||||
|
num_positional_embeddings (`int`, *optional*, defaults to `None`):
|
||||||
|
The maximum number of positional embeddings to apply.
|
||||||
|
ff_inner_dim (`int`, *optional*):
|
||||||
|
Hidden dimension of feed-forward MLP.
|
||||||
|
ff_bias (`bool`, defaults to `True`):
|
||||||
|
Whether or not to use bias in feed-forward MLP.
|
||||||
|
attention_out_bias (`bool`, defaults to `True`):
|
||||||
|
Whether or not to use bias in attention output project layer.
|
||||||
|
context_length (`int`, defaults to `16`):
|
||||||
|
The maximum number of frames that the FreeNoise block processes at once.
|
||||||
|
context_stride (`int`, defaults to `4`):
|
||||||
|
The number of frames to be skipped before starting to process a new batch of `context_length` frames.
|
||||||
|
weighting_scheme (`str`, defaults to `"pyramid"`):
|
||||||
|
The weighting scheme to use for weighting averaging of processed latent frames. As described in the
|
||||||
|
Equation 9. of the [FreeNoise](https://arxiv.org/abs/2310.15169) paper, "pyramid" is the default setting
|
||||||
|
used.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
dim: int,
|
||||||
|
num_attention_heads: int,
|
||||||
|
attention_head_dim: int,
|
||||||
|
dropout: float = 0.0,
|
||||||
|
cross_attention_dim: Optional[int] = None,
|
||||||
|
activation_fn: str = "geglu",
|
||||||
|
num_embeds_ada_norm: Optional[int] = None,
|
||||||
|
attention_bias: bool = False,
|
||||||
|
only_cross_attention: bool = False,
|
||||||
|
double_self_attention: bool = False,
|
||||||
|
upcast_attention: bool = False,
|
||||||
|
norm_elementwise_affine: bool = True,
|
||||||
|
norm_type: str = "layer_norm",
|
||||||
|
norm_eps: float = 1e-5,
|
||||||
|
final_dropout: bool = False,
|
||||||
|
positional_embeddings: Optional[str] = None,
|
||||||
|
num_positional_embeddings: Optional[int] = None,
|
||||||
|
ff_inner_dim: Optional[int] = None,
|
||||||
|
ff_bias: bool = True,
|
||||||
|
attention_out_bias: bool = True,
|
||||||
|
context_length: int = 16,
|
||||||
|
context_stride: int = 4,
|
||||||
|
weighting_scheme: str = "pyramid",
|
||||||
|
):
|
||||||
|
super().__init__()
|
||||||
|
self.dim = dim
|
||||||
|
self.num_attention_heads = num_attention_heads
|
||||||
|
self.attention_head_dim = attention_head_dim
|
||||||
|
self.dropout = dropout
|
||||||
|
self.cross_attention_dim = cross_attention_dim
|
||||||
|
self.activation_fn = activation_fn
|
||||||
|
self.attention_bias = attention_bias
|
||||||
|
self.double_self_attention = double_self_attention
|
||||||
|
self.norm_elementwise_affine = norm_elementwise_affine
|
||||||
|
self.positional_embeddings = positional_embeddings
|
||||||
|
self.num_positional_embeddings = num_positional_embeddings
|
||||||
|
self.only_cross_attention = only_cross_attention
|
||||||
|
|
||||||
|
self.set_free_noise_properties(context_length, context_stride, weighting_scheme)
|
||||||
|
|
||||||
|
# We keep these boolean flags for backward-compatibility.
|
||||||
|
self.use_ada_layer_norm_zero = (num_embeds_ada_norm is not None) and norm_type == "ada_norm_zero"
|
||||||
|
self.use_ada_layer_norm = (num_embeds_ada_norm is not None) and norm_type == "ada_norm"
|
||||||
|
self.use_ada_layer_norm_single = norm_type == "ada_norm_single"
|
||||||
|
self.use_layer_norm = norm_type == "layer_norm"
|
||||||
|
self.use_ada_layer_norm_continuous = norm_type == "ada_norm_continuous"
|
||||||
|
|
||||||
|
if norm_type in ("ada_norm", "ada_norm_zero") and num_embeds_ada_norm is None:
|
||||||
|
raise ValueError(
|
||||||
|
f"`norm_type` is set to {norm_type}, but `num_embeds_ada_norm` is not defined. Please make sure to"
|
||||||
|
f" define `num_embeds_ada_norm` if setting `norm_type` to {norm_type}."
|
||||||
|
)
|
||||||
|
|
||||||
|
self.norm_type = norm_type
|
||||||
|
self.num_embeds_ada_norm = num_embeds_ada_norm
|
||||||
|
|
||||||
|
if positional_embeddings and (num_positional_embeddings is None):
|
||||||
|
raise ValueError(
|
||||||
|
"If `positional_embedding` type is defined, `num_positition_embeddings` must also be defined."
|
||||||
|
)
|
||||||
|
|
||||||
|
if positional_embeddings == "sinusoidal":
|
||||||
|
self.pos_embed = SinusoidalPositionalEmbedding(dim, max_seq_length=num_positional_embeddings)
|
||||||
|
else:
|
||||||
|
self.pos_embed = None
|
||||||
|
|
||||||
|
# Define 3 blocks. Each block has its own normalization layer.
|
||||||
|
# 1. Self-Attn
|
||||||
|
self.norm1 = nn.LayerNorm(dim, elementwise_affine=norm_elementwise_affine, eps=norm_eps)
|
||||||
|
|
||||||
|
self.attn1 = Attention(
|
||||||
|
query_dim=dim,
|
||||||
|
heads=num_attention_heads,
|
||||||
|
dim_head=attention_head_dim,
|
||||||
|
dropout=dropout,
|
||||||
|
bias=attention_bias,
|
||||||
|
cross_attention_dim=cross_attention_dim if only_cross_attention else None,
|
||||||
|
upcast_attention=upcast_attention,
|
||||||
|
out_bias=attention_out_bias,
|
||||||
|
)
|
||||||
|
|
||||||
|
# 2. Cross-Attn
|
||||||
|
if cross_attention_dim is not None or double_self_attention:
|
||||||
|
self.norm2 = nn.LayerNorm(dim, norm_eps, norm_elementwise_affine)
|
||||||
|
|
||||||
|
self.attn2 = Attention(
|
||||||
|
query_dim=dim,
|
||||||
|
cross_attention_dim=cross_attention_dim if not double_self_attention else None,
|
||||||
|
heads=num_attention_heads,
|
||||||
|
dim_head=attention_head_dim,
|
||||||
|
dropout=dropout,
|
||||||
|
bias=attention_bias,
|
||||||
|
upcast_attention=upcast_attention,
|
||||||
|
out_bias=attention_out_bias,
|
||||||
|
) # is self-attn if encoder_hidden_states is none
|
||||||
|
|
||||||
|
# 3. Feed-forward
|
||||||
|
self.ff = FeedForward(
|
||||||
|
dim,
|
||||||
|
dropout=dropout,
|
||||||
|
activation_fn=activation_fn,
|
||||||
|
final_dropout=final_dropout,
|
||||||
|
inner_dim=ff_inner_dim,
|
||||||
|
bias=ff_bias,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.norm3 = nn.LayerNorm(dim, norm_eps, norm_elementwise_affine)
|
||||||
|
|
||||||
|
# let chunk size default to None
|
||||||
|
self._chunk_size = None
|
||||||
|
self._chunk_dim = 0
|
||||||
|
|
||||||
|
def _get_frame_indices(self, num_frames: int) -> List[Tuple[int, int]]:
|
||||||
|
frame_indices = []
|
||||||
|
for i in range(0, num_frames - self.context_length + 1, self.context_stride):
|
||||||
|
window_start = i
|
||||||
|
window_end = min(num_frames, i + self.context_length)
|
||||||
|
frame_indices.append((window_start, window_end))
|
||||||
|
return frame_indices
|
||||||
|
|
||||||
|
def _get_frame_weights(self, num_frames: int, weighting_scheme: str = "pyramid") -> List[float]:
|
||||||
|
if weighting_scheme == "pyramid":
|
||||||
|
if num_frames % 2 == 0:
|
||||||
|
# num_frames = 4 => [1, 2, 2, 1]
|
||||||
|
weights = list(range(1, num_frames // 2 + 1))
|
||||||
|
weights = weights + weights[::-1]
|
||||||
|
else:
|
||||||
|
# num_frames = 5 => [1, 2, 3, 2, 1]
|
||||||
|
weights = list(range(1, num_frames // 2 + 1))
|
||||||
|
weights = weights + [num_frames // 2 + 1] + weights[::-1]
|
||||||
|
else:
|
||||||
|
raise ValueError(f"Unsupported value for weighting_scheme={weighting_scheme}")
|
||||||
|
|
||||||
|
return weights
|
||||||
|
|
||||||
|
def set_free_noise_properties(
|
||||||
|
self, context_length: int, context_stride: int, weighting_scheme: str = "pyramid"
|
||||||
|
) -> None:
|
||||||
|
self.context_length = context_length
|
||||||
|
self.context_stride = context_stride
|
||||||
|
self.weighting_scheme = weighting_scheme
|
||||||
|
|
||||||
|
def set_chunk_feed_forward(self, chunk_size: Optional[int], dim: int = 0) -> None:
|
||||||
|
# Sets chunk feed-forward
|
||||||
|
self._chunk_size = chunk_size
|
||||||
|
self._chunk_dim = dim
|
||||||
|
|
||||||
|
def forward(
|
||||||
|
self,
|
||||||
|
hidden_states: torch.Tensor,
|
||||||
|
attention_mask: Optional[torch.Tensor] = None,
|
||||||
|
encoder_hidden_states: Optional[torch.Tensor] = None,
|
||||||
|
encoder_attention_mask: Optional[torch.Tensor] = None,
|
||||||
|
cross_attention_kwargs: Dict[str, Any] = None,
|
||||||
|
*args,
|
||||||
|
**kwargs,
|
||||||
|
) -> torch.Tensor:
|
||||||
|
if cross_attention_kwargs is not None:
|
||||||
|
if cross_attention_kwargs.get("scale", None) is not None:
|
||||||
|
logger.warning("Passing `scale` to `cross_attention_kwargs` is deprecated. `scale` will be ignored.")
|
||||||
|
|
||||||
|
cross_attention_kwargs = cross_attention_kwargs.copy() if cross_attention_kwargs is not None else {}
|
||||||
|
|
||||||
|
# hidden_states: [B x H x W, F, C]
|
||||||
|
device = hidden_states.device
|
||||||
|
dtype = hidden_states.dtype
|
||||||
|
|
||||||
|
num_frames = hidden_states.size(1)
|
||||||
|
frame_indices = self._get_frame_indices(num_frames)
|
||||||
|
frame_weights = self._get_frame_weights(self.context_length, self.weighting_scheme)
|
||||||
|
frame_weights = torch.tensor(frame_weights, device=device, dtype=dtype).unsqueeze(0).unsqueeze(-1)
|
||||||
|
is_last_frame_batch_complete = frame_indices[-1][1] == num_frames
|
||||||
|
|
||||||
|
# Handle out-of-bounds case if num_frames isn't perfectly divisible by context_length
|
||||||
|
# For example, num_frames=25, context_length=16, context_stride=4, then we expect the ranges:
|
||||||
|
# [(0, 16), (4, 20), (8, 24), (10, 26)]
|
||||||
|
if not is_last_frame_batch_complete:
|
||||||
|
if num_frames < self.context_length:
|
||||||
|
raise ValueError(f"Expected {num_frames=} to be greater or equal than {self.context_length=}")
|
||||||
|
last_frame_batch_length = num_frames - frame_indices[-1][1]
|
||||||
|
frame_indices.append((num_frames - self.context_length, num_frames))
|
||||||
|
|
||||||
|
num_times_accumulated = torch.zeros((1, num_frames, 1), device=device)
|
||||||
|
accumulated_values = torch.zeros_like(hidden_states)
|
||||||
|
|
||||||
|
for i, (frame_start, frame_end) in enumerate(frame_indices):
|
||||||
|
# The reason for slicing here is to ensure that if (frame_end - frame_start) is to handle
|
||||||
|
# cases like frame_indices=[(0, 16), (16, 20)], if the user provided a video with 19 frames, or
|
||||||
|
# essentially a non-multiple of `context_length`.
|
||||||
|
weights = torch.ones_like(num_times_accumulated[:, frame_start:frame_end])
|
||||||
|
weights *= frame_weights
|
||||||
|
|
||||||
|
hidden_states_chunk = hidden_states[:, frame_start:frame_end]
|
||||||
|
|
||||||
|
# Notice that normalization is always applied before the real computation in the following blocks.
|
||||||
|
# 1. Self-Attention
|
||||||
|
norm_hidden_states = self.norm1(hidden_states_chunk)
|
||||||
|
|
||||||
|
if self.pos_embed is not None:
|
||||||
|
norm_hidden_states = self.pos_embed(norm_hidden_states)
|
||||||
|
|
||||||
|
attn_output = self.attn1(
|
||||||
|
norm_hidden_states,
|
||||||
|
encoder_hidden_states=encoder_hidden_states if self.only_cross_attention else None,
|
||||||
|
attention_mask=attention_mask,
|
||||||
|
**cross_attention_kwargs,
|
||||||
|
)
|
||||||
|
|
||||||
|
hidden_states_chunk = attn_output + hidden_states_chunk
|
||||||
|
if hidden_states_chunk.ndim == 4:
|
||||||
|
hidden_states_chunk = hidden_states_chunk.squeeze(1)
|
||||||
|
|
||||||
|
# 2. Cross-Attention
|
||||||
|
if self.attn2 is not None:
|
||||||
|
norm_hidden_states = self.norm2(hidden_states_chunk)
|
||||||
|
|
||||||
|
if self.pos_embed is not None and self.norm_type != "ada_norm_single":
|
||||||
|
norm_hidden_states = self.pos_embed(norm_hidden_states)
|
||||||
|
|
||||||
|
attn_output = self.attn2(
|
||||||
|
norm_hidden_states,
|
||||||
|
encoder_hidden_states=encoder_hidden_states,
|
||||||
|
attention_mask=encoder_attention_mask,
|
||||||
|
**cross_attention_kwargs,
|
||||||
|
)
|
||||||
|
hidden_states_chunk = attn_output + hidden_states_chunk
|
||||||
|
|
||||||
|
if i == len(frame_indices) - 1 and not is_last_frame_batch_complete:
|
||||||
|
accumulated_values[:, -last_frame_batch_length:] += (
|
||||||
|
hidden_states_chunk[:, -last_frame_batch_length:] * weights[:, -last_frame_batch_length:]
|
||||||
|
)
|
||||||
|
num_times_accumulated[:, -last_frame_batch_length:] += weights[:, -last_frame_batch_length]
|
||||||
|
else:
|
||||||
|
accumulated_values[:, frame_start:frame_end] += hidden_states_chunk * weights
|
||||||
|
num_times_accumulated[:, frame_start:frame_end] += weights
|
||||||
|
|
||||||
|
hidden_states = torch.where(
|
||||||
|
num_times_accumulated > 0, accumulated_values / num_times_accumulated, accumulated_values
|
||||||
|
).to(dtype)
|
||||||
|
|
||||||
|
# 3. Feed-forward
|
||||||
|
norm_hidden_states = self.norm3(hidden_states)
|
||||||
|
|
||||||
|
if self._chunk_size is not None:
|
||||||
|
ff_output = _chunked_feed_forward(self.ff, norm_hidden_states, self._chunk_dim, self._chunk_size)
|
||||||
|
else:
|
||||||
|
ff_output = self.ff(norm_hidden_states)
|
||||||
|
|
||||||
|
hidden_states = ff_output + hidden_states
|
||||||
|
if hidden_states.ndim == 4:
|
||||||
|
hidden_states = hidden_states.squeeze(1)
|
||||||
|
|
||||||
|
return hidden_states
|
||||||
|
|
||||||
|
|
||||||
class FeedForward(nn.Module):
|
class FeedForward(nn.Module):
|
||||||
r"""
|
r"""
|
||||||
A feed-forward layer.
|
A feed-forward layer.
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user