-
Notifications
You must be signed in to change notification settings - Fork 44
refactor tests and align test results on torch 2.10.0 and cu13 #248
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: v1
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,25 +2,100 @@ | |
|
|
||
| import torch | ||
|
|
||
| from diffsynth_engine.pipelines.qwen_image import QwenImagePipeline | ||
| from diffsynth_engine import DiffSynthEngine | ||
| from diffsynth_engine.configs import QwenImagePipelineConfig | ||
| from diffsynth_engine.utils.download import fetch_model | ||
| from tests.common.test_case import ImageTestCase | ||
|
|
||
|
|
||
| class TestQwenImagePipeline(ImageTestCase): | ||
| @classmethod | ||
| def setUpClass(cls): | ||
| model_path = fetch_model("Qwen/Qwen-Image") | ||
| cls.pipe = QwenImagePipeline.from_pretrained(model_path_or_config=model_path) | ||
| cls.model_path = fetch_model("Qwen/Qwen-Image") | ||
| config = QwenImagePipelineConfig(model_path=cls.model_path) | ||
| cls.engine = DiffSynthEngine.from_pretrained(config) | ||
|
|
||
| @classmethod | ||
| def tearDownClass(cls): | ||
| del cls.pipe | ||
| cls.engine.shutdown() | ||
| del cls.engine | ||
| torch.cuda.empty_cache() | ||
|
|
||
| def test_txt2img(self): | ||
| prompt = "A painting of a cat in a zen garden" | ||
| negative_prompt = "ugly, blurry, low quality" | ||
| output = self.pipe( | ||
| output = self.engine.generate( | ||
| prompt=prompt, | ||
| negative_prompt=negative_prompt, | ||
| true_cfg_scale=4.0, | ||
| width=1328, | ||
| height=1328, | ||
| num_inference_steps=28, | ||
| generator=torch.Generator(device="cpu").manual_seed(42), | ||
| ) | ||
| image = output.images[0] | ||
| self.assertImageEqualAndSaveFailed(image, "qwen_image/qwen_image.png", threshold=0.99) | ||
|
|
||
|
|
||
| class TestQwenImagePipelineParallel(ImageTestCase): | ||
| @classmethod | ||
| def setUpClass(cls): | ||
| model_path = fetch_model("Qwen/Qwen-Image") | ||
| config = QwenImagePipelineConfig( | ||
| model_path=model_path, | ||
| parallelism=2, | ||
| use_cfg_parallel=True, | ||
| sp_ulysses_degree=1, | ||
| sp_ring_degree=1, | ||
| ) | ||
| cls.engine = DiffSynthEngine.from_pretrained(config) | ||
|
|
||
| @classmethod | ||
| def tearDownClass(cls): | ||
| cls.engine.shutdown() | ||
| del cls.engine | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| torch.cuda.empty_cache() | ||
|
|
||
| def test_txt2img_parallel(self): | ||
| prompt = "A painting of a cat in a zen garden" | ||
| negative_prompt = "ugly, blurry, low quality" | ||
| output = self.engine.generate( | ||
| prompt=prompt, | ||
| negative_prompt=negative_prompt, | ||
| true_cfg_scale=4.0, | ||
| width=1328, | ||
| height=1328, | ||
| num_inference_steps=28, | ||
| generator=torch.Generator(device="cpu").manual_seed(42), | ||
| ) | ||
| image = output.images[0] | ||
| self.assertImageEqualAndSaveFailed(image, "qwen_image/qwen_image.png", threshold=0.99) | ||
|
|
||
|
|
||
| class TestQwenImagePipelineFSDP(ImageTestCase): | ||
| @classmethod | ||
| def setUpClass(cls): | ||
| model_path = fetch_model("Qwen/Qwen-Image") | ||
| config = QwenImagePipelineConfig( | ||
| model_path=model_path, | ||
| parallelism=2, | ||
| use_cfg_parallel=True, | ||
| sp_ulysses_degree=1, | ||
| sp_ring_degree=1, | ||
| use_fsdp=True, | ||
| ) | ||
| cls.engine = DiffSynthEngine.from_pretrained(config) | ||
|
|
||
| @classmethod | ||
| def tearDownClass(cls): | ||
| cls.engine.shutdown() | ||
| del cls.engine | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| torch.cuda.empty_cache() | ||
|
|
||
| def test_txt2img_fsdp(self): | ||
| prompt = "A painting of a cat in a zen garden" | ||
| negative_prompt = "ugly, blurry, low quality" | ||
| output = self.engine.generate( | ||
| prompt=prompt, | ||
| negative_prompt=negative_prompt, | ||
| true_cfg_scale=4.0, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,7 +2,8 @@ | |
|
|
||
| import torch | ||
|
|
||
| from diffsynth_engine.pipelines.qwen_image import QwenImageEditPipeline | ||
| from diffsynth_engine import DiffSynthEngine | ||
| from diffsynth_engine.configs import QwenImagePipelineConfig | ||
| from diffsynth_engine.utils.download import fetch_model | ||
| from tests.common.test_case import ImageTestCase | ||
|
|
||
|
|
@@ -11,19 +12,59 @@ class TestQwenImageEditPipeline(ImageTestCase): | |
| @classmethod | ||
| def setUpClass(cls): | ||
| model_path = fetch_model("Qwen/Qwen-Image-Edit") | ||
| cls.pipe = QwenImageEditPipeline.from_pretrained(model_path_or_config=model_path) | ||
| config = QwenImagePipelineConfig(model_path=model_path) | ||
| cls.engine = DiffSynthEngine.from_pretrained(config) | ||
|
|
||
| @classmethod | ||
| def tearDownClass(cls): | ||
| del cls.pipe | ||
| cls.engine.shutdown() | ||
| del cls.engine | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| torch.cuda.empty_cache() | ||
|
|
||
| def test_single_image_edit(self): | ||
| """Test single image editing with Edit pipeline""" | ||
| input_image = self.get_input_image("qwen_image_edit_input.png") | ||
| prompt = "Replace '通义千问' with '呜哩AI'" | ||
| negative_prompt = " " | ||
|
|
||
| output = self.pipe( | ||
| output = self.engine.generate( | ||
| image=input_image, | ||
| prompt=prompt, | ||
| negative_prompt=negative_prompt, | ||
| true_cfg_scale=4.0, | ||
| num_inference_steps=50, | ||
| generator=torch.Generator(device="cpu").manual_seed(42), | ||
| ) | ||
| image = output.images[0] | ||
| self.assertImageEqualAndSaveFailed(image, "qwen_image/qwen_image_edit.png", threshold=0.99) | ||
|
|
||
|
|
||
| class TestQwenImageEditPipelineParallel(ImageTestCase): | ||
| @classmethod | ||
| def setUpClass(cls): | ||
| model_path = fetch_model("Qwen/Qwen-Image-Edit") | ||
| config = QwenImagePipelineConfig( | ||
| model_path=model_path, | ||
| parallelism=2, | ||
| use_cfg_parallel=True, | ||
| sp_ulysses_degree=1, | ||
| sp_ring_degree=1, | ||
| ) | ||
| cls.engine = DiffSynthEngine.from_pretrained(config) | ||
|
|
||
| @classmethod | ||
| def tearDownClass(cls): | ||
| cls.engine.shutdown() | ||
| del cls.engine | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| torch.cuda.empty_cache() | ||
|
|
||
| def test_single_image_edit_parallel(self): | ||
| """Test single image editing with Edit pipeline in parallel mode""" | ||
| input_image = self.get_input_image("qwen_image_edit_input.png") | ||
| prompt = "Replace '通义千问' with '呜哩AI'" | ||
| negative_prompt = " " | ||
|
|
||
| output = self.engine.generate( | ||
| image=input_image, | ||
| prompt=prompt, | ||
| negative_prompt=negative_prompt, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,7 +2,8 @@ | |
|
|
||
| import torch | ||
|
|
||
| from diffsynth_engine.pipelines.qwen_image import QwenImageEditPlusPipeline | ||
| from diffsynth_engine import DiffSynthEngine | ||
| from diffsynth_engine.configs import QwenImagePipelineConfig | ||
| from diffsynth_engine.utils.download import fetch_model | ||
| from tests.common.test_case import ImageTestCase | ||
|
|
||
|
|
@@ -11,19 +12,22 @@ class TestQwenImageEditPlusPipeline(ImageTestCase): | |
| @classmethod | ||
| def setUpClass(cls): | ||
| model_path = fetch_model("Qwen/Qwen-Image-Edit-2509") | ||
| cls.pipe = QwenImageEditPlusPipeline.from_pretrained(model_path_or_config=model_path) | ||
| config = QwenImagePipelineConfig(model_path=model_path) | ||
| cls.engine = DiffSynthEngine.from_pretrained(config) | ||
|
|
||
| @classmethod | ||
| def tearDownClass(cls): | ||
| del cls.pipe | ||
| cls.engine.shutdown() | ||
| del cls.engine | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| torch.cuda.empty_cache() | ||
|
|
||
| def test_single_image_edit(self): | ||
| """Test single image editing with Edit Plus pipeline""" | ||
| input_image = self.get_input_image("qwen_image_edit_input.png") | ||
| prompt = "Replace '通义千问' with '呜哩AI'" | ||
| negative_prompt = " " | ||
|
|
||
| output = self.pipe( | ||
| output = self.engine.generate( | ||
| image=input_image, | ||
| prompt=prompt, | ||
| negative_prompt=negative_prompt, | ||
|
|
@@ -43,7 +47,7 @@ def test_multi_image_edit(self): | |
| prompt = "根据这图1中女性和图2中的男性,生成一组结婚照,并遵循以下描述:新郎穿着红色的中式马褂,新娘穿着精致的秀禾服,头戴金色凤冠。他们并肩站立在古老的朱红色宫墙前,背景是雕花的木窗。光线明亮柔和,构图对称,氛围喜庆而庄重。" | ||
| negative_prompt = " " | ||
|
|
||
| output = self.pipe( | ||
| output = self.engine.generate( | ||
| image=input_images, | ||
| prompt=prompt, | ||
| negative_prompt=negative_prompt, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,7 +2,8 @@ | |
|
|
||
| import torch | ||
|
|
||
| from diffsynth_engine.pipelines.qwen_image import QwenImageEditPlusPipeline | ||
| from diffsynth_engine import DiffSynthEngine | ||
| from diffsynth_engine.configs import QwenImagePipelineConfig | ||
| from diffsynth_engine.utils.download import fetch_model | ||
| from tests.common.test_case import ImageTestCase | ||
|
|
||
|
|
@@ -11,19 +12,22 @@ class TestQwenImageEditPlusPipeline(ImageTestCase): | |
| @classmethod | ||
| def setUpClass(cls): | ||
| model_path = fetch_model("Qwen/Qwen-Image-Edit-2511") | ||
| cls.pipe = QwenImageEditPlusPipeline.from_pretrained(model_path_or_config=model_path) | ||
| config = QwenImagePipelineConfig(model_path=model_path) | ||
| cls.engine = DiffSynthEngine.from_pretrained(config) | ||
|
|
||
| @classmethod | ||
| def tearDownClass(cls): | ||
| del cls.pipe | ||
| cls.engine.shutdown() | ||
| del cls.engine | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| torch.cuda.empty_cache() | ||
|
|
||
| def test_single_image_edit(self): | ||
| """Test single image editing with Edit Plus pipeline""" | ||
| input_image = self.get_input_image("qwen_image_edit_input.png") | ||
| prompt = "Replace '通义千问' with '呜哩AI'" | ||
| negative_prompt = " " | ||
|
|
||
| output = self.pipe( | ||
| output = self.engine.generate( | ||
| image=input_image, | ||
| prompt=prompt, | ||
| negative_prompt=negative_prompt, | ||
|
|
@@ -43,7 +47,7 @@ def test_multi_image_edit(self): | |
| prompt = "根据这图1中女性和图2中的男性,生成一组结婚照,并遵循以下描述:新郎穿着红色的中式马褂,新娘穿着精致的秀禾服,头戴金色凤冠。他们并肩站立在古老的朱红色宫墙前,背景是雕花的木窗。光线明亮柔和,构图对称,氛围喜庆而庄重。" | ||
| negative_prompt = " " | ||
|
|
||
| output = self.pipe( | ||
| output = self.engine.generate( | ||
| image=input_images, | ||
| prompt=prompt, | ||
| negative_prompt=negative_prompt, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,7 +2,8 @@ | |
|
|
||
| import torch | ||
|
|
||
| from diffsynth_engine.pipelines.qwen_image import QwenImageLayeredPipeline | ||
| from diffsynth_engine import DiffSynthEngine | ||
| from diffsynth_engine.configs import QwenImagePipelineConfig | ||
| from diffsynth_engine.utils.download import fetch_model | ||
| from tests.common.test_case import ImageTestCase | ||
|
|
||
|
|
@@ -11,46 +12,39 @@ class TestQwenImageLayeredPipeline(ImageTestCase): | |
| @classmethod | ||
| def setUpClass(cls): | ||
| model_path = fetch_model("Qwen/Qwen-Image-Layered") | ||
| cls.pipe = QwenImageLayeredPipeline.from_pretrained(model_path_or_config=model_path) | ||
| config = QwenImagePipelineConfig(model_path=model_path) | ||
| cls.engine = DiffSynthEngine.from_pretrained(config) | ||
|
|
||
| @classmethod | ||
| def tearDownClass(cls): | ||
| del cls.pipe | ||
| cls.engine.shutdown() | ||
| del cls.engine | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| torch.cuda.empty_cache() | ||
|
|
||
| def test_image_layered(self): | ||
| input_image = self.get_input_image("qwen_image_layered_input.png").convert("RGBA") | ||
| prompt = "" | ||
|
|
||
| output = self.pipe( | ||
| output = self.engine.generate( | ||
| image=input_image, | ||
| prompt=prompt, | ||
| num_inference_steps=50, | ||
| true_cfg_scale=4.0, | ||
| layers=4, | ||
| layers=3, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The number of layers has been reduced from 4 to 3, which is also reflected in the assertion on line 40. Since 4 is the default value for the |
||
| resolution=640, | ||
| cfg_normalize=False, | ||
| use_en_prompt=True, | ||
| generator=torch.Generator(device="cpu").manual_seed(42), | ||
| ) | ||
|
|
||
| images = output.images[0] | ||
| self.assertEqual(len(images), 4) | ||
|
|
||
| # Compare each layer with reference images | ||
| from tests.common.utils import compute_normalized_ssim | ||
|
|
||
| ssim_results = [] | ||
| for i, layer_image in enumerate(images): | ||
| expect_image = self.get_expect_image(f"qwen_image/qwen_image_layered_{i}.png") | ||
| ssim = compute_normalized_ssim(layer_image, expect_image) | ||
| ssim_results.append((i, ssim)) | ||
| print(f"Layer {i} (qwen_image_layered_{i}.png): SSIM = {ssim:.6f}") | ||
| self.assertEqual(len(images), 3) | ||
|
|
||
| for i, layer_image in enumerate(images): | ||
| self.assertImageEqualAndSaveFailed( | ||
| layer_image, | ||
| f"qwen_image/qwen_image_layered_{i}.png", | ||
| threshold=0.98, | ||
| threshold=0.97, | ||
| ) | ||
|
|
||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Explicitly calling
cls.engine.shutdown()before deleting the engine is recommended to ensure that worker processes are terminated immediately and resources (like GPU memory and multiprocessing pipes) are released. Relying solely ondeland garbage collection can be unreliable in some environments, potentially leading to resource leaks or port conflicts in subsequent tests.