Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions src/diffusers/modular_pipelines/ernie_image/decoders.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,7 @@ def __call__(self, components: ErnieImageModularPipeline, state: PipelineState)

latents = block_state.latents
bn_mean = vae.bn.running_mean.view(1, -1, 1, 1).to(device=device, dtype=latents.dtype)
bn_std = torch.sqrt(vae.bn.running_var.view(1, -1, 1, 1) + vae.config.batch_norm_eps).to(
device=device, dtype=latents.dtype
)
bn_std = torch.sqrt(vae.bn.running_var.view(1, -1, 1, 1) + 1e-5).to(device=device, dtype=latents.dtype)
latents = latents * bn_std + bn_mean

latents = components.pachifier.unpack_latents(latents)
Expand Down
10 changes: 5 additions & 5 deletions src/diffusers/modular_pipelines/ernie_image/encoders.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
import json

import torch
from transformers import AutoModel, AutoModelForCausalLM, AutoTokenizer
from transformers import AutoTokenizer, Ministral3ForCausalLM, Mistral3Model

from ...configuration_utils import FrozenDict
from ...guiders import ClassifierFreeGuidance
Expand All @@ -38,7 +38,7 @@ def description(self) -> str:
@property
def expected_components(self) -> list[ComponentSpec]:
return [
ComponentSpec("pe", AutoModelForCausalLM),
ComponentSpec("pe", Ministral3ForCausalLM),
ComponentSpec("pe_tokenizer", AutoTokenizer),
]

Expand Down Expand Up @@ -83,7 +83,7 @@ def intermediate_outputs(self) -> list[OutputParam]:

@staticmethod
def _enhance_prompt(
pe: AutoModelForCausalLM,
pe: Ministral3ForCausalLM,
pe_tokenizer: AutoTokenizer,
prompt: str,
device: torch.device,
Expand Down Expand Up @@ -160,7 +160,7 @@ def description(self) -> str:
@property
def expected_components(self) -> list[ComponentSpec]:
return [
ComponentSpec("text_encoder", AutoModel),
ComponentSpec("text_encoder", Mistral3Model),
ComponentSpec("tokenizer", AutoTokenizer),
ComponentSpec(
"guider",
Expand Down Expand Up @@ -200,7 +200,7 @@ def intermediate_outputs(self) -> list[OutputParam]:

@staticmethod
def _encode(
text_encoder: AutoModel,
text_encoder: Mistral3Model,
tokenizer: AutoTokenizer,
prompt: list[str],
device: torch.device,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
# limitations under the License.

from ...utils import logging
from ..modular_pipeline import AutoPipelineBlocks, SequentialPipelineBlocks
from ..modular_pipeline import ConditionalPipelineBlocks, SequentialPipelineBlocks
from ..modular_pipeline_utils import OutputParam
from .before_denoise import (
ErnieImagePrepareLatentsStep,
Expand All @@ -29,11 +29,11 @@


# auto_docstring
class ErnieImageAutoPromptEnhancerStep(AutoPipelineBlocks):
class ErnieImageAutoPromptEnhancerStep(ConditionalPipelineBlocks):
"""
Auto block that runs the optional prompt enhancer when `use_pe` is provided.
- `ErnieImagePromptEnhancerStep` is used when `use_pe` is set.
- If `use_pe` is not provided, the step is skipped.
Conditional block that runs the optional prompt enhancer when `use_pe` is truthy.
- `ErnieImagePromptEnhancerStep` is used when `use_pe=True`.
- If `use_pe` is `None` or `False`, the step is skipped.

Components:
pe (`AutoModelForCausalLM`) pe_tokenizer (`AutoTokenizer`)
Expand Down Expand Up @@ -66,12 +66,17 @@ class ErnieImageAutoPromptEnhancerStep(AutoPipelineBlocks):
block_names = ["prompt_enhancer"]
block_trigger_inputs = ["use_pe"]

def select_block(self, use_pe=None) -> str | None:
if use_pe:
return "prompt_enhancer"
return None

@property
def description(self):
return (
"Auto block that runs the optional prompt enhancer when `use_pe` is provided.\n"
" - `ErnieImagePromptEnhancerStep` is used when `use_pe` is set.\n"
" - If `use_pe` is not provided, the step is skipped."
"Conditional block that runs the optional prompt enhancer when `use_pe` is truthy.\n"
" - `ErnieImagePromptEnhancerStep` is used when `use_pe=True`.\n"
" - If `use_pe` is `None` or `False`, the step is skipped."
)


Expand Down
38 changes: 19 additions & 19 deletions src/diffusers/pipelines/ernie_image/pipeline_ernie_image.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

import torch
from PIL import Image
from transformers import AutoModel, AutoModelForCausalLM, AutoTokenizer
from transformers import AutoTokenizer, Ministral3ForCausalLM, Mistral3Model

from ...models import AutoencoderKLFlux2
from ...models.transformers import ErnieImageTransformer2DModel
Expand Down Expand Up @@ -51,10 +51,10 @@ def __init__(
self,
transformer: ErnieImageTransformer2DModel,
vae: AutoencoderKLFlux2,
text_encoder: AutoModel,
text_encoder: Mistral3Model,
tokenizer: AutoTokenizer,
scheduler: FlowMatchEulerDiscreteScheduler,
pe: Optional[AutoModelForCausalLM] = None,
pe: Optional[Ministral3ForCausalLM] = None,
pe_tokenizer: Optional[AutoTokenizer] = None,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

can we also take the opportunity to change the auto classes for the real classes, it gets confusing for some users that pass the text encoder e.g. quantization and also kind of annoying to get the warning all the time.

):
super().__init__()
Expand Down Expand Up @@ -361,26 +361,26 @@ def __call__(
progress_bar.update()

if output_type == "latent":
return latents

# Decode latents to images
# Unnormalize latents using VAE's BN stats
bn_mean = self.vae.bn.running_mean.view(1, -1, 1, 1).to(device)
bn_std = torch.sqrt(self.vae.bn.running_var.view(1, -1, 1, 1) + 1e-5).to(device)
latents = latents * bn_std + bn_mean
images = latents
else:
# Decode latents to images
# Unnormalize latents using VAE's BN stats
bn_mean = self.vae.bn.running_mean.view(1, -1, 1, 1).to(device)
bn_std = torch.sqrt(self.vae.bn.running_var.view(1, -1, 1, 1) + 1e-5).to(device)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

dtype casting to be safe and for consistency with modular

Suggested change
bn_mean = self.vae.bn.running_mean.view(1, -1, 1, 1).to(device)
bn_std = torch.sqrt(self.vae.bn.running_var.view(1, -1, 1, 1) + 1e-5).to(device)
bn_mean = self.vae.bn.running_mean.view(1, -1, 1, 1).to(device=device, dtype=latents.dtype)
bn_std = torch.sqrt(self.vae.bn.running_var.view(1, -1, 1, 1) + 1e-5).to(device=device, dtype=latents.dtype)

There could be a TODO regarding vae.config.batch_norm_eps, it should be used in the future if the checkpoint config is changed

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Added

latents = latents * bn_std + bn_mean

# Unpatchify
latents = self._unpatchify_latents(latents)
# Unpatchify
latents = self._unpatchify_latents(latents)

# Decode
images = self.vae.decode(latents, return_dict=False)[0]
# Decode
images = self.vae.decode(latents, return_dict=False)[0]

# Post-process
images = (images.clamp(-1, 1) + 1) / 2
images = images.cpu().permute(0, 2, 3, 1).float().numpy()
# Post-process
images = (images.clamp(-1, 1) + 1) / 2
images = images.cpu().permute(0, 2, 3, 1).float().numpy()

if output_type == "pil":
images = [Image.fromarray((img * 255).astype("uint8")) for img in images]
if output_type == "pil":
images = [Image.fromarray((img * 255).astype("uint8")) for img in images]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Can VaeImageProcessor be used here? cc @yiyixuxu Enforcing VaeImageProcessor could be another agent review rule?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Switched both standard and modular to VaeImageProcessor.postprocess. Also fixes output_type="pt" in the standard pipeline (was returning numpy).


# Offload all models
self.maybe_free_model_hooks()
Expand Down
Loading