Skip to content

Commit 54e17f3

Browse files
committed
update
1 parent 80702d2 commit 54e17f3

File tree

5 files changed

+178
-434
lines changed

5 files changed

+178
-434
lines changed
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
name: Fast PR tests for Modular
2+
3+
on:
4+
pull_request:
5+
branches: [main]
6+
paths:
7+
- "src/diffusers/modular_pipelines/**.py"
8+
- "src/diffusers/models/modeling_utils.py"
9+
- "src/diffusers/models/model_loading_utils.py"
10+
- "src/diffusers/pipelines/pipeline_utils.py"
11+
- "src/diffusers/pipeline_loading_utils.py"
12+
- "src/diffusers/loaders/lora_base.py"
13+
- "src/diffusers/loaders/lora_pipeline.py"
14+
- "src/diffusers/loaders/peft.py"
15+
- "tests/modular_pipelines/**.py"
16+
- ".github/**.yml"
17+
- "utils/**.py"
18+
- "setup.py"
19+
push:
20+
branches:
21+
- ci-*
22+
23+
concurrency:
24+
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
25+
cancel-in-progress: true
26+
27+
env:
28+
DIFFUSERS_IS_CI: yes
29+
HF_HUB_ENABLE_HF_TRANSFER: 1
30+
OMP_NUM_THREADS: 4
31+
MKL_NUM_THREADS: 4
32+
PYTEST_TIMEOUT: 60
33+
34+
jobs:
35+
check_code_quality:
36+
runs-on: ubuntu-22.04
37+
steps:
38+
- uses: actions/checkout@v3
39+
- name: Set up Python
40+
uses: actions/setup-python@v4
41+
with:
42+
python-version: "3.10"
43+
- name: Install dependencies
44+
run: |
45+
python -m pip install --upgrade pip
46+
pip install .[quality]
47+
- name: Check quality
48+
run: make quality
49+
- name: Check if failure
50+
if: ${{ failure() }}
51+
run: |
52+
echo "Quality check failed. Please ensure the right dependency versions are installed with 'pip install -e .[quality]' and run 'make style && make quality'" >> $GITHUB_STEP_SUMMARY
53+
54+
check_repository_consistency:
55+
needs: check_code_quality
56+
runs-on: ubuntu-22.04
57+
steps:
58+
- uses: actions/checkout@v3
59+
- name: Set up Python
60+
uses: actions/setup-python@v4
61+
with:
62+
python-version: "3.10"
63+
- name: Install dependencies
64+
run: |
65+
python -m pip install --upgrade pip
66+
pip install .[quality]
67+
- name: Check repo consistency
68+
run: |
69+
python utils/check_copies.py
70+
python utils/check_dummies.py
71+
python utils/check_support_list.py
72+
make deps_table_check_updated
73+
- name: Check if failure
74+
if: ${{ failure() }}
75+
run: |
76+
echo "Repo consistency check failed. Please ensure the right dependency versions are installed with 'pip install -e .[quality]' and run 'make fix-copies'" >> $GITHUB_STEP_SUMMARY
77+
78+
run_fast_tests:
79+
needs: [check_code_quality, check_repository_consistency]
80+
strategy:
81+
fail-fast: false
82+
matrix:
83+
config:
84+
- name: Fast PyTorch Modular Pipeline CPU tests
85+
framework: pytorch_pipelines
86+
runner: aws-highmemory-32-plus
87+
image: diffusers/diffusers-pytorch-cpu
88+
report: torch_cpu_modular_pipelines
89+
90+
name: ${{ matrix.config.name }}
91+
92+
runs-on:
93+
group: ${{ matrix.config.runner }}
94+
95+
container:
96+
image: ${{ matrix.config.image }}
97+
options: --shm-size "16gb" --ipc host -v /mnt/hf_cache:/mnt/cache/
98+
99+
defaults:
100+
run:
101+
shell: bash
102+
103+
steps:
104+
- name: Checkout diffusers
105+
uses: actions/checkout@v3
106+
with:
107+
fetch-depth: 2
108+
109+
- name: Install dependencies
110+
run: |
111+
python -m venv /opt/venv && export PATH="/opt/venv/bin:$PATH"
112+
python -m uv pip install -e [quality,test]
113+
pip uninstall transformers -y && python -m uv pip install -U transformers@git+https://github.com/huggingface/transformers.git --no-deps
114+
pip uninstall accelerate -y && python -m uv pip install -U accelerate@git+https://github.com/huggingface/accelerate.git --no-deps
115+
116+
- name: Environment
117+
run: |
118+
python -m venv /opt/venv && export PATH="/opt/venv/bin:$PATH"
119+
python utils/print_env.py
120+
121+
- name: Run fast PyTorch Pipeline CPU tests
122+
if: ${{ matrix.config.framework == 'pytorch_pipelines' }}
123+
run: |
124+
python -m venv /opt/venv && export PATH="/opt/venv/bin:$PATH"
125+
python -m pytest -n 8 --max-worker-restart=0 --dist=loadfile \
126+
-s -v -k "not Flax and not Onnx" \
127+
--make-reports=tests_${{ matrix.config.report }} \
128+
tests/modular_pipelines
129+
130+
- name: Failure short reports
131+
if: ${{ failure() }}
132+
run: cat reports/tests_${{ matrix.config.report }}_failures_short.txt
133+
134+
- name: Test suite reports artifacts
135+
if: ${{ always() }}
136+
uses: actions/upload-artifact@v4
137+
with:
138+
name: pr_${{ matrix.config.framework }}_${{ matrix.config.report }}_test_reports
139+
path: reports
140+
141+

tests/modular_pipelines/stable_diffusion_xl/__init__.py

Whitespace-only changes.

tests/modular_pipelines/stable_diffusion_xl/test_modular_pipeline_stable_diffusion_xl.py

Lines changed: 31 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ def _test_stable_diffusion_xl_euler(self, expected_image_shape, expected_slice,
101101

102102
assert (
103103
np.abs(image_slice.flatten() - expected_slice).max() < expected_max_diff
104-
), f"Image Slice does not match expected slice"
104+
), "Image Slice does not match expected slice"
105105

106106

107107
class SDXLModularIPAdapterTests:
@@ -114,30 +114,20 @@ def test_pipeline_inputs_and_blocks(self):
114114
parameters = blocks.input_names
115115

116116
assert issubclass(self.pipeline_class, ModularIPAdapterMixin)
117-
self.assertIn(
118-
"ip_adapter_image",
119-
parameters,
120-
"`ip_adapter_image` argument must be supported by the `__call__` method",
121-
)
122-
self.assertIn(
123-
"ip_adapter",
124-
blocks.sub_blocks,
125-
"pipeline must contain an IPAdapter block",
126-
)
117+
assert (
118+
"ip_adapter_image" in parameters
119+
), "`ip_adapter_image` argument must be supported by the `__call__` method"
120+
assert "ip_adapter" in blocks.sub_blocks, "pipeline must contain an IPAdapter block"
127121

128122
_ = blocks.sub_blocks.pop("ip_adapter")
129123
parameters = blocks.input_names
130124
intermediate_parameters = blocks.intermediate_input_names
131-
self.assertNotIn(
132-
"ip_adapter_image",
133-
parameters,
134-
"`ip_adapter_image` argument must be removed from the `__call__` method",
135-
)
136-
self.assertNotIn(
137-
"ip_adapter_image_embeds",
138-
intermediate_parameters,
139-
"`ip_adapter_image_embeds` argument must be supported by the `__call__` method",
140-
)
125+
assert (
126+
"ip_adapter_image" not in parameters
127+
), "`ip_adapter_image` argument must be removed from the `__call__` method"
128+
assert (
129+
"ip_adapter_image_embeds" not in intermediate_parameters
130+
), "`ip_adapter_image_embeds` argument must be supported by the `__call__` method"
141131

142132
def _get_dummy_image_embeds(self, cross_attention_dim: int = 32):
143133
return torch.randn((1, 1, cross_attention_dim), device=torch_device)
@@ -213,14 +203,10 @@ def test_ip_adapter(self, expected_max_diff: float = 1e-4, expected_pipe_slice=N
213203
max_diff_without_adapter_scale = np.abs(output_without_adapter_scale - output_without_adapter).max()
214204
max_diff_with_adapter_scale = np.abs(output_with_adapter_scale - output_without_adapter).max()
215205

216-
self.assertLess(
217-
max_diff_without_adapter_scale,
218-
expected_max_diff,
219-
"Output without ip-adapter must be same as normal inference",
220-
)
221-
self.assertGreater(
222-
max_diff_with_adapter_scale, 1e-2, "Output with ip-adapter must be different from normal inference"
223-
)
206+
assert (
207+
max_diff_without_adapter_scale < expected_max_diff
208+
), "Output without ip-adapter must be same as normal inference"
209+
assert max_diff_with_adapter_scale > 1e-2, "Output with ip-adapter must be different from normal inference"
224210

225211
# 2. Multi IP-Adapter test cases
226212
adapter_state_dict_1 = create_ip_adapter_state_dict(pipe.unet)
@@ -249,16 +235,12 @@ def test_ip_adapter(self, expected_max_diff: float = 1e-4, expected_pipe_slice=N
249235
output_without_multi_adapter_scale - output_without_adapter
250236
).max()
251237
max_diff_with_multi_adapter_scale = np.abs(output_with_multi_adapter_scale - output_without_adapter).max()
252-
self.assertLess(
253-
max_diff_without_multi_adapter_scale,
254-
expected_max_diff,
255-
"Output without multi-ip-adapter must be same as normal inference",
256-
)
257-
self.assertGreater(
258-
max_diff_with_multi_adapter_scale,
259-
1e-2,
260-
"Output with multi-ip-adapter scale must be different from normal inference",
261-
)
238+
assert (
239+
max_diff_without_multi_adapter_scale < expected_max_diff
240+
), "Output without multi-ip-adapter must be same as normal inference"
241+
assert (
242+
max_diff_with_multi_adapter_scale > 1e-2
243+
), "Output with multi-ip-adapter scale must be different from normal inference"
262244

263245

264246
class SDXLModularControlNetTests:
@@ -270,16 +252,10 @@ def test_pipeline_inputs(self):
270252
blocks = self.pipeline_blocks_class()
271253
parameters = blocks.input_names
272254

273-
self.assertIn(
274-
"control_image",
275-
parameters,
276-
"`control_image` argument must be supported by the `__call__` method",
277-
)
278-
self.assertIn(
279-
"controlnet_conditioning_scale",
280-
parameters,
281-
"`controlnet_conditioning_scale` argument must be supported by the `__call__` method",
282-
)
255+
assert "control_image" in parameters, "`control_image` argument must be supported by the `__call__` method"
256+
assert (
257+
"controlnet_conditioning_scale" in parameters
258+
), "`controlnet_conditioning_scale` argument must be supported by the `__call__` method"
283259

284260
def _modify_inputs_for_controlnet_test(self, inputs: Dict[str, Any]):
285261
controlnet_embedder_scale_factor = 2
@@ -325,14 +301,10 @@ def test_controlnet(self, expected_max_diff: float = 1e-4, expected_pipe_slice=N
325301
max_diff_without_controlnet_scale = np.abs(output_without_controlnet_scale - output_without_controlnet).max()
326302
max_diff_with_controlnet_scale = np.abs(output_with_controlnet_scale - output_without_controlnet).max()
327303

328-
self.assertLess(
329-
max_diff_without_controlnet_scale,
330-
expected_max_diff,
331-
"Output without controlnet must be same as normal inference",
332-
)
333-
self.assertGreater(
334-
max_diff_with_controlnet_scale, 1e-2, "Output with controlnet must be different from normal inference"
335-
)
304+
assert (
305+
max_diff_without_controlnet_scale < expected_max_diff
306+
), "Output without controlnet must be same as normal inference"
307+
assert max_diff_with_controlnet_scale > 1e-2, "Output with controlnet must be different from normal inference"
336308

337309
def test_controlnet_cfg(self):
338310
pipe = self.get_pipeline()
@@ -354,7 +326,7 @@ def test_controlnet_cfg(self):
354326

355327
assert out_cfg.shape == out_no_cfg.shape
356328
max_diff = np.abs(out_cfg - out_no_cfg).max()
357-
self.assertGreater(max_diff, 1e-2)
329+
assert max_diff > 1e-2, "Output with CFG must be different from normal inference"
358330

359331

360332
class SDXLModularGuiderTests:
@@ -378,7 +350,7 @@ def test_guider_cfg(self):
378350

379351
assert out_cfg.shape == out_no_cfg.shape
380352
max_diff = np.abs(out_cfg - out_no_cfg).max()
381-
self.assertGreater(max_diff, 1e-2)
353+
assert max_diff > 1e-2, "Output with CFG must be different from normal inference"
382354

383355

384356
class SDXLModularPipelineFastTests(

tests/modular_pipelines/test_modular_pipelines_common.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22
import unittest
33
from typing import Callable, Union
44

5-
from diffusers.utils.dummy_pt_objects import ModularPipeline, ModularPipelineBlocks
65
import numpy as np
76
import torch
87

98
import diffusers
109
from diffusers.utils import logging
10+
from diffusers.utils.dummy_pt_objects import ModularPipeline, ModularPipelineBlocks
1111
from diffusers.utils.testing_utils import (
1212
backend_empty_cache,
1313
numpy_cosine_similarity_distance,
@@ -142,7 +142,7 @@ def test_pipeline_call_signature(self):
142142
optional_parameters = pipe.default_call_parameters
143143

144144
def _check_for_parameters(parameters, expected_parameters, param_type):
145-
remaining_parameters = set(param for param in parameters if param not in expected_parameters)
145+
remaining_parameters = {param for param in parameters if param not in expected_parameters}
146146
assert (
147147
len(remaining_parameters) == 0
148148
), f"Required {param_type} parameters not present: {remaining_parameters}"
@@ -188,7 +188,7 @@ def test_inference_batch_consistent(self, batch_sizes=[2], batch_generator=True)
188188
output = pipe(**batched_input, output="images")
189189
assert len(output) == batch_size, "Output is different from expected batch size"
190190

191-
def test_batch_inference_identical_to_single(
191+
def test_inference_batch_single_identical(
192192
self,
193193
batch_size=2,
194194
expected_max_diff=1e-4,
@@ -283,16 +283,16 @@ def test_inference_is_not_nan_cpu(self):
283283
pipe.set_progress_bar_config(disable=None)
284284
pipe.to("cpu")
285285

286-
output = pipe(**self.get_dummy_inputs("cpu"), output="np")
286+
output = pipe(**self.get_dummy_inputs("cpu"), output="images")
287287
assert np.isnan(to_np(output)).sum() == 0, "CPU Inference returns NaN"
288288

289289
@require_accelerator
290-
def test_inferece_is_not_nan(self):
290+
def test_inference_is_not_nan(self):
291291
pipe = self.get_pipeline()
292292
pipe.set_progress_bar_config(disable=None)
293293
pipe.to(torch_device)
294294

295-
output = pipe(**self.get_dummy_inputs(torch_device), output="np")
295+
output = pipe(**self.get_dummy_inputs(torch_device), output="images")
296296
assert np.isnan(to_np(output)).sum() == 0, "Accelerator Inference returns NaN"
297297

298298
def test_num_images_per_prompt(self):

0 commit comments

Comments
 (0)