[Bugfix] fix GLM-Image multi-stage online generation fail (#3084)
Signed-off-by: Lancer <maruixiang6688@gmail.com>
This commit is contained in:
1 parent
e8d22d4fa8
commit
0fe76857ac
4 files changed
+194
No files matched your search
@@ -13,16 +13,22 @@ from argparse import Namespace
|
||||
from types import SimpleNamespace
|
||||
|
||||
import pytest
|
||||
from fastapi import FastAPI
|
||||
from fastapi.testclient import TestClient
|
||||
from PIL import Image
|
||||
from pytest_mock import MockerFixture
|
||||
from vllm import SamplingParams
|
||||
from vllm.entrypoints.openai.models.protocol import BaseModelPath
|
||||
|
||||
from vllm_omni.entrypoints.async_omni import AsyncOmni
|
||||
from vllm_omni.entrypoints.openai.api_server import _DiffusionServingModels, router
|
||||
from vllm_omni.entrypoints.openai.image_api_utils import (
|
||||
encode_image_base64,
|
||||
parse_size,
|
||||
)
|
||||
from vllm_omni.entrypoints.openai.serving_chat import OmniOpenAIServingChat
|
||||
from vllm_omni.inputs.data import OmniDiffusionSamplingParams
|
||||
from vllm_omni.model_executor.stage_input_processors.glm_image import compute_max_tokens
|
||||
|
||||
pytestmark = [pytest.mark.core_model, pytest.mark.cpu]
|
||||
|
||||
@@ -569,6 +575,84 @@ def test_multistage_images_async_omni_construction(async_omni_test_client):
|
||||
assert captured[1].guidance_scale == 6.5
|
||||
|
||||
|
||||
def test_generate_images_async_omni_glm_image_sets_stage0_max_tokens():
|
||||
"""GLM-Image multistage requests must compute stage-0 max_tokens from size."""
|
||||
|
||||
class FakeAsyncOmniClass(AsyncOmni):
|
||||
def __init__(self):
|
||||
stage_configs = [
|
||||
SimpleNamespace(stage_type="llm", is_comprehension=True, model_arch="GlmImageForConditionalGeneration"),
|
||||
SimpleNamespace(stage_type="diffusion", is_comprehension=False, model_arch="GlmImagePipeline"),
|
||||
]
|
||||
default_sampling_params_list = [
|
||||
SamplingParams(temperature=0.1, seed=42),
|
||||
OmniDiffusionSamplingParams(height=1024, width=1024),
|
||||
]
|
||||
self.engine = SimpleNamespace(
|
||||
stage_configs=stage_configs,
|
||||
default_sampling_params_list=default_sampling_params_list,
|
||||
)
|
||||
self.default_sampling_params_list = default_sampling_params_list
|
||||
self.captured_sampling_params_list = None
|
||||
self.captured_prompt = None
|
||||
self._images = [Image.new("RGB", (64, 64), color="green")]
|
||||
self.od_config = SimpleNamespace(supports_multimodal_inputs=True)
|
||||
|
||||
async def generate(self, prompt, request_id, sampling_params=None, sampling_params_list=None):
|
||||
self.captured_sampling_params_list = (
|
||||
sampling_params_list if sampling_params_list is not None else [sampling_params]
|
||||
)
|
||||
self.captured_prompt = prompt
|
||||
yield MockGenerationResult([img.copy() for img in self._images])
|
||||
|
||||
def __class_getitem__(cls, item):
|
||||
return cls
|
||||
|
||||
def get_diffusion_od_config(self):
|
||||
return self.od_config
|
||||
|
||||
app = FastAPI()
|
||||
app.include_router(router)
|
||||
engine = FakeAsyncOmniClass()
|
||||
chat_handler = object.__new__(OmniOpenAIServingChat)
|
||||
chat_handler.engine_client = engine
|
||||
chat_handler._diffusion_engine = None
|
||||
app.state.openai_serving_chat = chat_handler
|
||||
app.state.engine_client = engine
|
||||
app.state.stage_configs = [
|
||||
SimpleNamespace(stage_type="llm", model_arch="GlmImageForConditionalGeneration"),
|
||||
SimpleNamespace(stage_type="diffusion", model_arch="GlmImagePipeline"),
|
||||
]
|
||||
app.state.openai_serving_models = _DiffusionServingModels(
|
||||
[BaseModelPath(name="THUDM/GLM-4.5V", model_path="THUDM/GLM-4.5V")]
|
||||
)
|
||||
app.state.args = Namespace(
|
||||
default_sampling_params='{"1": {"num_inference_steps":4, "guidance_scale":7.5, "generator_device":"cpu"}}',
|
||||
max_generated_image_size=1048576,
|
||||
)
|
||||
client = TestClient(app)
|
||||
|
||||
response = client.post(
|
||||
"/v1/images/generations",
|
||||
json={
|
||||
"prompt": "a coral reef",
|
||||
"n": 1,
|
||||
"size": "1024x1024",
|
||||
"seed": 7,
|
||||
},
|
||||
)
|
||||
assert response.status_code == 200
|
||||
|
||||
captured = engine.captured_sampling_params_list
|
||||
assert captured is not None
|
||||
assert len(captured) == 2
|
||||
assert captured[0].max_tokens == compute_max_tokens(1024, 1024, is_i2i=False)
|
||||
assert captured[0].extra_args["target_h"] == 1024
|
||||
assert captured[0].extra_args["target_w"] == 1024
|
||||
assert captured[1].height == 1024
|
||||
assert captured[1].width == 1024
|
||||
|
||||
|
||||
def test_image_edits_async_omni_stage_configs_only(async_omni_stage_configs_only_client):
|
||||
"""Regression: image edits accepts refactored AsyncOmni without stage_list."""
|
||||
img_bytes = make_test_image_bytes((16, 16))
|
||||
|
||||
Reference in new issue
Block a user