[Bugfix] Stop reading the removed OmniRequestOutput.request_output accessor (#6172)
Signed-off-by: MrlixiangWE <mrdanaer@gmail.com>
This commit is contained in:
1 parent
fe54ecc388
commit
b95c73742d
12 files changed
+74
-32
No files matched your search
@@ -101,7 +101,7 @@ outputs = omni.generate(
|
||||
)
|
||||
|
||||
# Access custom trajectory data
|
||||
output = outputs[0].request_output
|
||||
output = outputs[0]
|
||||
print(f"Trajectory timesteps shape: {output.metrics['trajectory_timesteps'].shape}")
|
||||
print(f"Trajectory latents shape: {output.latents.shape}")
|
||||
```
|
||||
|
||||
@@ -47,7 +47,7 @@ if __name__ == "__main__":
|
||||
omni = Omni(model="Tongyi-MAI/Z-Image-Turbo")
|
||||
prompt = "a cup of coffee on the table"
|
||||
outputs = omni.generate(prompt)
|
||||
images = outputs[0].request_output.images
|
||||
images = outputs[0].images
|
||||
images[0].save("coffee.png")
|
||||
```
|
||||
|
||||
@@ -75,8 +75,7 @@ if __name__ == "__main__":
|
||||
]
|
||||
omni_outputs = omni.generate(prompts)
|
||||
for i_prompt, prompt_output in enumerate(omni_outputs):
|
||||
this_request_output = prompt_output.request_output
|
||||
this_images = this_request_output.images
|
||||
this_images = prompt_output.images
|
||||
for i_image, image in enumerate(this_images):
|
||||
image.save(f"p{i_prompt}-img{i_image}.jpg")
|
||||
print("saved to", f"p{i_prompt}-img{i_image}.jpg")
|
||||
|
||||
@@ -43,7 +43,7 @@ if __name__ == "__main__":
|
||||
),
|
||||
],
|
||||
)
|
||||
outputs[0].request_output.images[0].save("output.png")
|
||||
outputs[0].images[0].save("output.png")
|
||||
```
|
||||
|
||||
## Image-to-Image (Image Editing)
|
||||
@@ -72,7 +72,7 @@ if __name__ == "__main__":
|
||||
),
|
||||
],
|
||||
)
|
||||
outputs[0].request_output.images[0].save("output.png")
|
||||
outputs[0].images[0].save("output.png")
|
||||
```
|
||||
|
||||
## Generation Parameters
|
||||
|
||||
@@ -55,7 +55,7 @@ if __name__ == "__main__":
|
||||
omni = Omni(model="Qwen/Qwen-Image")
|
||||
prompt = "a cup of coffee on the table"
|
||||
outputs = omni.generate(prompt)
|
||||
images = outputs[0].request_output.images
|
||||
images = outputs[0].images
|
||||
images[0].save("coffee.png")
|
||||
```
|
||||
|
||||
@@ -179,7 +179,7 @@ if __name__ == "__main__":
|
||||
]
|
||||
outputs = omni.generate(prompts)
|
||||
for i, output in enumerate(outputs):
|
||||
output.request_output.images[0].save(f"{i}.jpg")
|
||||
output.images[0].save(f"{i}.jpg")
|
||||
```
|
||||
|
||||
!!! info
|
||||
@@ -207,7 +207,7 @@ if __name__ == "__main__":
|
||||
}
|
||||
])
|
||||
for i, output in enumerate(outputs):
|
||||
output.request_output.images[0].save(f"{i}.jpg")
|
||||
output.images[0].save(f"{i}.jpg")
|
||||
```
|
||||
|
||||
You can also pass a negative prompt via the CLI argument `--negative-prompt`:
|
||||
|
||||
@@ -96,7 +96,7 @@ if __name__ == "__main__":
|
||||
),
|
||||
)
|
||||
from diffusers.utils import export_to_video
|
||||
frames = outputs[0].request_output.images
|
||||
frames = outputs[0].images
|
||||
export_to_video(frames, "quick_test_i2v.mp4", fps=16)
|
||||
```
|
||||
|
||||
|
||||
@@ -335,7 +335,7 @@ def main(args):
|
||||
print(f"use_tts (tts_bos): {use_tts}")
|
||||
|
||||
for stage_outputs in omni_generator:
|
||||
output = stage_outputs.request_output
|
||||
output = stage_outputs
|
||||
if stage_outputs.final_output_type == "text":
|
||||
request_id = output.request_id
|
||||
text_output = output.outputs[0].text
|
||||
|
||||
@@ -74,7 +74,7 @@ if __name__ == "__main__":
|
||||
omni = Omni(model="Qwen/Qwen-Image")
|
||||
prompt = "a cup of coffee on the table"
|
||||
outputs = omni.generate(prompt)
|
||||
images = outputs[0].request_output.images
|
||||
images = outputs[0].images
|
||||
images[0].save("coffee.png")
|
||||
```
|
||||
|
||||
@@ -265,7 +265,7 @@ if __name__ == "__main__":
|
||||
]
|
||||
outputs = omni.generate(prompts)
|
||||
for i, output in enumerate(outputs):
|
||||
output.request_output.images[0].save(f"{i}.jpg")
|
||||
output.images[0].save(f"{i}.jpg")
|
||||
```
|
||||
|
||||
!!! info
|
||||
@@ -301,7 +301,7 @@ if __name__ == "__main__":
|
||||
}
|
||||
])
|
||||
for i, output in enumerate(outputs):
|
||||
output.request_output.images[0].save(f"{i}.jpg")
|
||||
output.images[0].save(f"{i}.jpg")
|
||||
```
|
||||
|
||||
You can also pass a negative prompt via the CLI argument `--negative-prompt`:
|
||||
|
||||
@@ -53,14 +53,10 @@ def _diff_metrics(a: Image.Image, b: Image.Image) -> tuple[float, float]:
|
||||
def _extract_single_image(outputs) -> Image.Image:
|
||||
first_output = outputs[0]
|
||||
assert first_output.final_output_type == "image"
|
||||
if not hasattr(first_output, "request_output") or not first_output.request_output:
|
||||
raise ValueError("No request_output found in OmniRequestOutput")
|
||||
if not isinstance(first_output, OmniRequestOutput):
|
||||
raise ValueError(f"Expected an OmniRequestOutput, got {type(first_output).__name__}")
|
||||
|
||||
req_out = first_output.request_output
|
||||
if not isinstance(req_out, OmniRequestOutput) or not hasattr(req_out, "images"):
|
||||
raise ValueError("Invalid request_output structure or missing 'images' key")
|
||||
|
||||
images = req_out.images
|
||||
images = first_output.images
|
||||
if images is None or len(images) != 1:
|
||||
raise ValueError(f"Expected 1 image, got {0 if images is None else len(images)}")
|
||||
return images[0]
|
||||
|
||||
@@ -72,8 +72,7 @@ def _to_float_array(data: Any) -> np.ndarray:
|
||||
|
||||
|
||||
def _extract_output_array(output: Any) -> np.ndarray:
|
||||
req_out = output.request_output
|
||||
payload = req_out.images[0]
|
||||
payload = output.images[0]
|
||||
return _to_float_array(payload)
|
||||
|
||||
|
||||
|
||||
@@ -142,12 +142,6 @@ def _generate_joint_output(omni, config: QualityTestConfig):
|
||||
|
||||
first = outputs[0]
|
||||
worker_peak_memory_mb = float(getattr(first, "peak_memory_mb", 0.0) or 0.0)
|
||||
if hasattr(first, "request_output") and isinstance(first.request_output, list):
|
||||
first = first.request_output[0]
|
||||
worker_peak_memory_mb = max(
|
||||
worker_peak_memory_mb,
|
||||
float(getattr(first, "peak_memory_mb", 0.0) or 0.0),
|
||||
)
|
||||
if not hasattr(first, "images") or not first.images:
|
||||
raise ValueError("Could not extract video frames from H3 output")
|
||||
frames = first.images[0]
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
|
||||
"""Guard the public accessor that examples and docs use to read omni outputs.
|
||||
|
||||
``OmniRequestOutput`` used to hold a nested ``RequestOutput`` in a
|
||||
``request_output`` field. Since #5146 it *inherits* ``RequestOutput``, so the
|
||||
generation content lives on the object itself and the nested field is gone.
|
||||
|
||||
Call sites that kept the old accessor only fail once a real model runs, which
|
||||
means a GPU nightly job is the first thing to notice. These checks pin both
|
||||
halves of the contract on CPU instead: the field is really gone, and no doc,
|
||||
example, test or tool still reaches for it.
|
||||
"""
|
||||
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from vllm_omni.outputs import OmniRequestOutput
|
||||
|
||||
pytestmark = [pytest.mark.core_model, pytest.mark.cpu]
|
||||
|
||||
|
||||
ROOT_DIR = Path(__file__).parents[2]
|
||||
SCANNED_DIRS = ("docs", "examples", "tests", "tools")
|
||||
SCANNED_SUFFIXES = (".py", ".md")
|
||||
|
||||
# ``.request_outputs`` (plural, an OutputProcessor batch) is a different and
|
||||
# still-valid attribute, so require a non-identifier character after the name.
|
||||
NESTED_ACCESSOR = re.compile(r"\.request_output(?![\w])")
|
||||
|
||||
|
||||
def _iter_scanned_files():
|
||||
for directory in SCANNED_DIRS:
|
||||
for path in sorted((ROOT_DIR / directory).rglob("*")):
|
||||
if path.suffix in SCANNED_SUFFIXES and path.resolve() != Path(__file__).resolve():
|
||||
yield path
|
||||
|
||||
|
||||
def test_omni_request_output_has_no_nested_request_output():
|
||||
assert not hasattr(OmniRequestOutput(request_id="req-accessor"), "request_output")
|
||||
|
||||
|
||||
def test_no_source_reads_the_nested_request_output():
|
||||
offenders = []
|
||||
for path in _iter_scanned_files():
|
||||
for lineno, line in enumerate(path.read_text(encoding="utf-8").splitlines(), start=1):
|
||||
if NESTED_ACCESSOR.search(line):
|
||||
offenders.append(f"{path.relative_to(ROOT_DIR)}:{lineno}: {line.strip()}")
|
||||
|
||||
assert not offenders, (
|
||||
"OmniRequestOutput no longer nests a RequestOutput; read the content off the "
|
||||
"output itself (e.g. `outputs[0].images`) instead of `.request_output`:\n" + "\n".join(offenders)
|
||||
)
|
||||
@@ -159,11 +159,10 @@ def _run_once(model: str, yaml_path: str, *, async_mode: bool) -> list[dict]:
|
||||
wav: bytes = b""
|
||||
# Batch size 1: submit a single prompt so scheduling is deterministic.
|
||||
for step in omni.generate([_text_prompt(question)], _sampling_params(), py_generator=False):
|
||||
out = step.request_output
|
||||
if step.final_output_type == "text":
|
||||
text = out.outputs[0].text # exact text, no strip -> truly bit-identical
|
||||
text = step.outputs[0].text # exact text, no strip -> truly bit-identical
|
||||
elif step.final_output_type == "audio":
|
||||
wav = _audio_bytes(out.outputs[0].multimodal_output["audio"])
|
||||
wav = _audio_bytes(step.outputs[0].multimodal_output["audio"])
|
||||
if text is None:
|
||||
raise RuntimeError(f"prompt_id={prompt_id} async={async_mode}: produced no text output")
|
||||
if not wav:
|
||||
|
||||
Reference in new issue
Block a user