Signed-off-by: wangyu <410167048@qq.com> Signed-off-by: [Your Name] [Your Email] Signed-off-by: [Your Name] <your.email@example.com> Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: amy-why-3459 <wuhaiyan17@huawei.com>
141 lines
4.6 KiB
Python
141 lines
4.6 KiB
Python
# SPDX-License-Identifier: Apache-2.0
|
|
# SPDX-FileCopyrightText: Copyright contributors to the vLLM-Omni project
|
|
|
|
"""
|
|
Online serving tests: text-to-image.
|
|
See examples/online_serving/text_to_image/README.md
|
|
|
|
The output materials are organized in a three-level directory structure:
|
|
- Set at init: `self.output_root` for all tests (from env OUTPUT_DIR)
|
|
- Set at `self.run(...)`: `output_subfolder` for a specific example page (e.g., `example_offline_t2i`)
|
|
- Generated by `extract_readme_snippets`: `snippet.test_id` for a specific code block (matching H2 titles, e.g., `basic_usage_001`)
|
|
"""
|
|
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
from tests.examples.helpers import EXAMPLES, OUTPUT_DIR, run_cmd, write_zimage_lora
|
|
from tests.helpers.assertions import assert_image_valid
|
|
from tests.helpers.mark import hardware_marks
|
|
from tests.helpers.runtime import OmniServer, OmniServerParams
|
|
|
|
pytestmark = [pytest.mark.full_model, pytest.mark.example, *hardware_marks(res={"cuda": ["H100", "B200"]})]
|
|
|
|
T2I_ONLINE_CLIENT = EXAMPLES / "online_serving" / "text_to_image" / "openai_chat_client.py"
|
|
EXAMPLE_OUTPUT_SUBFOLDER = "example_online_t2i"
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
def example_output_dir() -> Path:
|
|
d = OUTPUT_DIR / EXAMPLE_OUTPUT_SUBFOLDER
|
|
d.mkdir(parents=True, exist_ok=True)
|
|
return d
|
|
|
|
|
|
# Ensuring two indirect parametrization receive exactly the same parameter list.
|
|
# Then, only one omni_server instance is started for all test functions using this param set.
|
|
# Two additional pre-requisites:
|
|
# - omni_server must (and indeed is) defined as a module-scoped fixture
|
|
# - test functions sharing the same param set must be adjacent to each other
|
|
qwen_image_server_params = [OmniServerParams(model="Qwen/Qwen-Image")]
|
|
z_image_turbo_server_params = [OmniServerParams(model="Tongyi-MAI/Z-Image-Turbo")]
|
|
|
|
|
|
# --- ### Method 1: Using curl ---
|
|
|
|
|
|
@pytest.mark.parametrize("omni_server", qwen_image_server_params, indirect=True)
|
|
def test_api_calls_001(omni_server: OmniServer, example_output_dir: Path):
|
|
url = f"http://{omni_server.host}:{omni_server.port}/v1/chat/completions"
|
|
case_dir = example_output_dir / "api_calls-001"
|
|
case_dir.mkdir(parents=True, exist_ok=True)
|
|
out = case_dir / "api_calls_001.png"
|
|
json_str = """{
|
|
"messages": [
|
|
{"role": "user", "content": "A beautiful landscape painting"}
|
|
],
|
|
"extra_body": {
|
|
"height": 1024,
|
|
"width": 1024,
|
|
"num_inference_steps": 50,
|
|
"true_cfg_scale": 4.0,
|
|
"seed": 42
|
|
}
|
|
}"""
|
|
run_cmd(
|
|
f"curl -s '{url}'"
|
|
" -H 'Content-Type: application/json'"
|
|
f" -d '{json_str}'"
|
|
" | jq -r '.choices[0].message.content[0].image_url.url'"
|
|
f" | cut -d',' -f2- | base64 -d > '{out}'",
|
|
shell=True,
|
|
)
|
|
assert_image_valid(out, width=1024, height=1024)
|
|
|
|
|
|
# --- ### Method 2: Using Python Client ---
|
|
|
|
|
|
@pytest.mark.parametrize("omni_server", qwen_image_server_params, indirect=True)
|
|
def test_api_calls_002(omni_server: OmniServer, example_output_dir: Path):
|
|
case_dir = example_output_dir / "api_calls-002"
|
|
case_dir.mkdir(parents=True, exist_ok=True)
|
|
out = case_dir / "api_calls_002.png"
|
|
run_cmd(
|
|
[
|
|
sys.executable,
|
|
str(T2I_ONLINE_CLIENT),
|
|
"--prompt",
|
|
"A beautiful landscape painting",
|
|
"--output",
|
|
str(out),
|
|
"--server",
|
|
f"http://{omni_server.host}:{omni_server.port}",
|
|
]
|
|
)
|
|
assert_image_valid(out)
|
|
|
|
|
|
@pytest.mark.skip("README section 'Method 3: Using Gradio Demo' is intentionally excluded for examples tests")
|
|
def test_api_calls_003(): ...
|
|
|
|
|
|
# --- ### Using Python Client with LoRA ---
|
|
|
|
|
|
@pytest.mark.parametrize("omni_server", z_image_turbo_server_params, indirect=True)
|
|
def test_lora_001(omni_server: OmniServer, example_output_dir: Path, tmp_path: Path):
|
|
lora_dir = tmp_path / "zimage_lora_a"
|
|
write_zimage_lora(lora_dir, v_scale=8.0)
|
|
case_dir = example_output_dir / "lora-001"
|
|
case_dir.mkdir(parents=True, exist_ok=True)
|
|
out = case_dir / "lora_001.png"
|
|
run_cmd(
|
|
[
|
|
sys.executable,
|
|
str(T2I_ONLINE_CLIENT),
|
|
"--prompt",
|
|
"A piece of cheesecake",
|
|
"--lora-path",
|
|
str(lora_dir),
|
|
"--lora-name",
|
|
"a",
|
|
"--lora-scale",
|
|
"1.0",
|
|
"--output",
|
|
str(out),
|
|
"--server",
|
|
f"http://{omni_server.host}:{omni_server.port}",
|
|
]
|
|
)
|
|
assert_image_valid(out)
|
|
|
|
|
|
# --- ### Using curl with LoRA (Images API) ---
|
|
|
|
|
|
@pytest.mark.skip(reason="Covered by tests/diffusion/lora/test_images_generations_lora.py")
|
|
def test_lora_002(): ...
|