From 9a9c8f750327508c44e42bb4627361de5ddee652 Mon Sep 17 00:00:00 2001 From: herotai214 <68222888+herotai214@users.noreply.github.com> Date: Thu, 4 Jun 2026 15:11:17 +0800 Subject: [PATCH] [Test] Add L4 diffusion feature test for GLM-Image (#3451) Signed-off-by: herotai214 --- .buildkite/test-nightly.yml | 39 ++++ .../test_glm_image_expansion.py | 183 ++++++++++++++++++ 2 files changed, 222 insertions(+) create mode 100644 tests/e2e/online_serving/test_glm_image_expansion.py diff --git a/.buildkite/test-nightly.yml b/.buildkite/test-nightly.yml index 28d349b2d..ef99257fb 100644 --- a/.buildkite/test-nightly.yml +++ b/.buildkite/test-nightly.yml @@ -801,6 +801,45 @@ steps: type: DirectoryOrCreate + - label: ":full_moon: Diffusion X2I(&A&T) · GLM-Image Function Test with H100" + timeout_in_minutes: 120 + commands: + - pytest -sv tests/e2e/online_serving/test_glm_image_expansion.py -m "full_model and diffusion and H100" --run-level "full_model" + agents: + queue: "mithril-h100-pool" + plugins: + - kubernetes: + podSpec: + containers: + - image: 936637512419.dkr.ecr.us-west-2.amazonaws.com/vllm-ci-pull-through-cache/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT + resources: + limits: + nvidia.com/gpu: 2 + volumeMounts: + - name: devshm + mountPath: /dev/shm + - name: hf-cache + mountPath: /root/.cache/huggingface + env: + - name: HF_HOME + value: /root/.cache/huggingface + - name: HF_TOKEN + valueFrom: + secretKeyRef: + name: hf-token-secret + key: token + nodeSelector: + node.kubernetes.io/instance-type: gpu-h100-sxm + volumes: + - name: devshm + emptyDir: + medium: Memory + - name: hf-cache + hostPath: + path: /mnt/hf-cache + type: DirectoryOrCreate + + - label: ":full_moon: Diffusion X2I(&A&T) · Function Test with L4" timeout_in_minutes: 60 commands: diff --git a/tests/e2e/online_serving/test_glm_image_expansion.py b/tests/e2e/online_serving/test_glm_image_expansion.py new file mode 100644 index 000000000..d2a08f633 --- /dev/null +++ b/tests/e2e/online_serving/test_glm_image_expansion.py @@ -0,0 +1,183 @@ +""" +Comprehensive tests of diffusion features that are available in online serving mode +and are supported by the following model: +- zai-org/GLM-Image (t2i and i2i) + +Coverage (per mode): +- Baseline +- Cache-DiT +- Tensor-Parallel +- HSDP +- Sequence parallel + +Topology for multi-GPU cases uses runtime deploy YAML (except TP) +so stage-1 parallel fields reach the diffusion worker without relying on CLI + +assert_diffusion_response validates successful generation and the expected resolution. +""" + +import os + +import pytest + +from tests.helpers.mark import hardware_marks +from tests.helpers.media import generate_synthetic_image +from tests.helpers.runtime import ( + OmniServer, + OmniServerParams, + OpenAIClientHandler, + dummy_messages_from_mix_data, +) +from tests.helpers.stage_config import get_deploy_config_path, modify_stage_config + +pytestmark = [pytest.mark.diffusion, pytest.mark.full_model] + +MODEL = os.environ.get("GLM_IMAGE_MODEL_PATH", "zai-org/GLM-Image") + +T2I_PROMPT = "A Vincent van Gogh style impressionist painting." +I2I_PROMPT = "Transform this modern, geometric image into a Vincent van Gogh style impressionist painting." +NEGATIVE_PROMPT = "low quality, blurry, distorted, unnatural colors" + +TWO_CARD_FEATURE_MARKS = hardware_marks(res={"cuda": "H100"}, num_cards=2) + +GLM_DEPLOY = get_deploy_config_path("glm_image.yaml") +GLM_CACHEDIT_DEPLOY = modify_stage_config( + GLM_DEPLOY, + updates={ + "stages": { + 1: {"cache_backend": "cache_dit"}, + }, + }, +) +GLM_TP_2_DEPLOY = modify_stage_config( + GLM_DEPLOY, + updates={ + "stages": { + 0: {"devices": "0", "tensor_parallel_size": 1}, + 1: {"devices": "0,1", "tensor_parallel_size": 2}, + }, + }, +) +GLM_HSDP_2_DEPLOY = modify_stage_config( + GLM_DEPLOY, + updates={ + "stages": { + 0: {"devices": "0"}, + 1: { + "devices": "0,1", + "parallel_config": { + "use_hsdp": True, + "hsdp_shard_size": 2, + }, + }, + }, + }, +) +GLM_SP_2_DEPLOY = modify_stage_config( + GLM_DEPLOY, + updates={ + "stages": { + 0: {"devices": "0"}, + 1: { + "devices": "0,1", + "parallel_config": { + "ulysses_degree": 2, + "ring_degree": 1, + }, + }, + }, + }, +) + + +def _get_diffusion_feature_cases(model: str): + return [ + # Baseline: default deploy (stage 0 -> GPU 0, stage 1 -> GPU 1) + pytest.param( + OmniServerParams( + model=model, + stage_config_path=GLM_DEPLOY, + ), + id="baseline", + marks=TWO_CARD_FEATURE_MARKS, + ), + # Cache-DiT via runtime deploy patch (cache_backend -> engine_extras on stage 1) + pytest.param( + OmniServerParams( + model=model, + stage_config_path=GLM_CACHEDIT_DEPLOY, + ), + id="cachedit", + marks=TWO_CARD_FEATURE_MARKS, + ), + # Tensor-Parallel (2 GPUs on diffusion stage) + pytest.param( + OmniServerParams( + model=model, + stage_config_path=GLM_TP_2_DEPLOY, + ), + id="tensor_parallel_2", + marks=TWO_CARD_FEATURE_MARKS, + ), + # HSDP (2 GPUs on diffusion stage) + pytest.param( + OmniServerParams( + model=model, + stage_config_path=GLM_HSDP_2_DEPLOY, + ), + id="hsdp_2", + marks=TWO_CARD_FEATURE_MARKS, + ), + # Ulysses sequence parallel degree=2 (2 GPUs) + pytest.param( + OmniServerParams( + model=model, + stage_config_path=GLM_SP_2_DEPLOY, + ), + id="sequence_parallel_2", + marks=TWO_CARD_FEATURE_MARKS, + ), + ] + + +MODES = ["t2i", "i2i"] + + +@pytest.mark.parametrize("mode", MODES) +@pytest.mark.parametrize( + "omni_server", + _get_diffusion_feature_cases(MODEL), + indirect=True, +) +def test_glm_image( + omni_server: OmniServer, + mode: str, + openai_client: OpenAIClientHandler, +): + """GLM-Image diffusion feature coverage for t2i and i2i on two H100s.""" + + if mode == "t2i": + messages = dummy_messages_from_mix_data(content_text=T2I_PROMPT) + else: + image_size = 1024 + image_data_url = f"data:image/jpeg;base64,{generate_synthetic_image(image_size, image_size)['base64']}" + messages = dummy_messages_from_mix_data( + image_data_url=image_data_url, + content_text=I2I_PROMPT, + ) + + request_config = { + "model": omni_server.model, + "messages": messages, + "extra_body": { + "height": 1024, + "width": 1024, + "num_inference_steps": 2, + "guidance_scale": 1.5, + "true_cfg_scale": 4.0, + "negative_prompt": NEGATIVE_PROMPT, + "seed": 42, + }, + } + + openai_client.send_diffusion_request(request_config)