Signed-off-by: Huang, Zeyu <11222265+fhfuih@users.noreply.github.com> Co-authored-by: Hongsheng Liu <liuhongsheng4@huawei.com>
185 lines
6.4 KiB
Python
185 lines
6.4 KiB
Python
from types import SimpleNamespace
|
|
|
|
import pytest
|
|
import torch
|
|
from torch import nn
|
|
|
|
from vllm_omni.diffusion.models.flux.pipeline_flux import FluxPipeline
|
|
from vllm_omni.diffusion.worker.request_batch import DiffusionRequestBatch
|
|
|
|
pytestmark = [pytest.mark.core_model, pytest.mark.cpu]
|
|
|
|
|
|
def _make_flux_sampling(**overrides):
|
|
values = {
|
|
"height": 32,
|
|
"width": 32,
|
|
"num_inference_steps": 2,
|
|
"sigmas": None,
|
|
"guidance_scale": 3.5,
|
|
"generator": None,
|
|
"true_cfg_scale": 4.0,
|
|
"num_outputs_per_prompt": 0,
|
|
"latents": None,
|
|
"output_type": None,
|
|
"max_sequence_length": None,
|
|
}
|
|
values.update(overrides)
|
|
return SimpleNamespace(**values)
|
|
|
|
|
|
def _make_flux_pipeline():
|
|
pipeline = object.__new__(FluxPipeline)
|
|
nn.Module.__init__(pipeline)
|
|
pipeline.default_sample_size = 128
|
|
pipeline.vae_scale_factor = 8
|
|
pipeline.device = torch.device("cpu")
|
|
pipeline.text_encoder = None
|
|
pipeline.transformer = SimpleNamespace(
|
|
in_channels=4,
|
|
guidance_embeds=False,
|
|
dtype=torch.float32,
|
|
)
|
|
return pipeline
|
|
|
|
|
|
def test_forward_collates_request_prompt_tensors_for_flux(monkeypatch):
|
|
monkeypatch.setattr(
|
|
"vllm_omni.diffusion.models.flux.pipeline_flux.get_classifier_free_guidance_world_size",
|
|
lambda: 1,
|
|
)
|
|
pipeline = _make_flux_pipeline()
|
|
encode_calls = []
|
|
prepare_latents_call = {}
|
|
diffuse_call = {}
|
|
|
|
def _fake_encode_prompt(**kwargs):
|
|
encode_calls.append(kwargs)
|
|
return (
|
|
kwargs["prompt_embeds"],
|
|
kwargs["pooled_prompt_embeds"],
|
|
torch.zeros(kwargs["prompt_embeds"].shape[1], 3),
|
|
)
|
|
|
|
def _fake_prepare_latents(
|
|
batch_size,
|
|
num_channels_latents,
|
|
height,
|
|
width,
|
|
dtype,
|
|
device,
|
|
generator,
|
|
latents,
|
|
):
|
|
prepare_latents_call.update(
|
|
{
|
|
"batch_size": batch_size,
|
|
"num_channels_latents": num_channels_latents,
|
|
"height": height,
|
|
"width": width,
|
|
"dtype": dtype,
|
|
"device": device,
|
|
"generator": generator,
|
|
"latents": latents,
|
|
}
|
|
)
|
|
return torch.zeros(batch_size, 1, 1), torch.zeros(1, 3)
|
|
|
|
def _fake_diffuse(
|
|
prompt_embeds,
|
|
pooled_prompt_embeds,
|
|
negative_prompt_embeds,
|
|
negative_pooled_prompt_embeds,
|
|
*args,
|
|
**kwargs,
|
|
):
|
|
diffuse_call.update(
|
|
{
|
|
"prompt_embeds": prompt_embeds,
|
|
"pooled_prompt_embeds": pooled_prompt_embeds,
|
|
"negative_prompt_embeds": negative_prompt_embeds,
|
|
"negative_pooled_prompt_embeds": negative_pooled_prompt_embeds,
|
|
}
|
|
)
|
|
return torch.arange(2, dtype=torch.float32).view(2, 1)
|
|
|
|
pipeline.encode_prompt = _fake_encode_prompt
|
|
pipeline.prepare_latents = _fake_prepare_latents
|
|
pipeline.prepare_timesteps = lambda *args, **kwargs: (torch.tensor([1.0]), 1)
|
|
pipeline.diffuse = _fake_diffuse
|
|
|
|
prompt_embeds_a = torch.zeros(2, 3)
|
|
prompt_embeds_b = torch.ones(2, 3)
|
|
pooled_prompt_embeds_a = torch.full((4,), 2.0)
|
|
pooled_prompt_embeds_b = torch.full((4,), 3.0)
|
|
negative_prompt_embeds_a = torch.full((2, 3), 4.0)
|
|
negative_prompt_embeds_b = torch.full((2, 3), 5.0)
|
|
negative_pooled_prompt_embeds_a = torch.full((4,), 6.0)
|
|
negative_pooled_prompt_embeds_b = torch.full((4,), 7.0)
|
|
latents_a = torch.zeros(1, 1, 1)
|
|
latents_b = torch.ones(1, 1, 1)
|
|
gen_a = torch.Generator(device="cpu").manual_seed(1)
|
|
gen_b = torch.Generator(device="cpu").manual_seed(2)
|
|
|
|
batch = DiffusionRequestBatch(
|
|
requests=[
|
|
SimpleNamespace(
|
|
request_id="flux-prompt-a",
|
|
prompt={
|
|
"prompt": "prompt-a",
|
|
"negative_prompt": "negative-a",
|
|
"prompt_embeds": prompt_embeds_a,
|
|
"pooled_prompt_embeds": pooled_prompt_embeds_a,
|
|
"negative_prompt_embeds": negative_prompt_embeds_a,
|
|
"negative_pooled_prompt_embeds": negative_pooled_prompt_embeds_a,
|
|
},
|
|
sampling_params=_make_flux_sampling(generator=gen_a, latents=latents_a, output_type="latent"),
|
|
),
|
|
SimpleNamespace(
|
|
request_id="flux-prompt-b",
|
|
prompt={
|
|
"prompt": "prompt-b",
|
|
"negative_prompt": "negative-b",
|
|
"additional_information": {
|
|
"prompt_embeds": [prompt_embeds_b],
|
|
"pooled_prompt_embeds": [pooled_prompt_embeds_b],
|
|
"negative_prompt_embeds": [negative_prompt_embeds_b],
|
|
"negative_pooled_prompt_embeds": [negative_pooled_prompt_embeds_b],
|
|
},
|
|
},
|
|
sampling_params=_make_flux_sampling(generator=gen_b, latents=latents_b, output_type="latent"),
|
|
),
|
|
]
|
|
)
|
|
|
|
outputs = pipeline.forward(batch)
|
|
|
|
assert encode_calls[0]["prompt"] is None
|
|
assert encode_calls[0]["prompt_2"] is None
|
|
torch.testing.assert_close(
|
|
encode_calls[0]["prompt_embeds"],
|
|
torch.stack([prompt_embeds_a, prompt_embeds_b], dim=0),
|
|
)
|
|
torch.testing.assert_close(
|
|
encode_calls[0]["pooled_prompt_embeds"],
|
|
torch.stack([pooled_prompt_embeds_a, pooled_prompt_embeds_b], dim=0),
|
|
)
|
|
assert encode_calls[1]["prompt"] is None
|
|
assert encode_calls[1]["prompt_2"] is None
|
|
torch.testing.assert_close(
|
|
encode_calls[1]["prompt_embeds"],
|
|
torch.stack([negative_prompt_embeds_a, negative_prompt_embeds_b], dim=0),
|
|
)
|
|
torch.testing.assert_close(
|
|
encode_calls[1]["pooled_prompt_embeds"],
|
|
torch.stack([negative_pooled_prompt_embeds_a, negative_pooled_prompt_embeds_b], dim=0),
|
|
)
|
|
torch.testing.assert_close(
|
|
diffuse_call["negative_pooled_prompt_embeds"],
|
|
torch.stack([negative_pooled_prompt_embeds_a, negative_pooled_prompt_embeds_b], dim=0),
|
|
)
|
|
assert prepare_latents_call["generator"] == [gen_a, gen_b]
|
|
torch.testing.assert_close(prepare_latents_call["latents"], torch.cat([latents_a, latents_b], dim=0))
|
|
torch.testing.assert_close(outputs[0].output, torch.tensor([[0.0]]))
|
|
torch.testing.assert_close(outputs[1].output, torch.tensor([[1.0]]))
|