[Bugfix] Stop reading the removed OmniRequestOutput.request_output accessor (#6172)

Signed-off-by: MrlixiangWE <mrdanaer@gmail.com>
This commit is contained in:
MrlixiangWE authored and GitHub committed 2026-08-15 07:07:28 +08:00
1 parent fe54ecc388
commit b95c73742d
12 files changed
+74 -32

No files matched your search

+1 -1
View File
@@ -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}")
```
+2 -3
View File
@@ -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)
)
+2 -3
View File
@@ -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: