Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
c5a297f
OmniRequestOutput inherits RequestOutput
bowieshi Jul 16, 2026
8115a22
fix multi_modal_placeholders
bowieshi Jul 22, 2026
5e8dfa7
fix from_pipeline
bowieshi Jul 22, 2026
bec1fa0
rm dead code(unwrap, copy, property) & fix __init__ monkey patch
bowieshi Jul 27, 2026
e6944f2
fix quant
bowieshi Jul 27, 2026
4d70c3a
fix pre-commit
bowieshi Jul 27, 2026
0a81d2f
[Refactor]: Mammothmoda2-dev use x_to_text.py in examples (#5454)
princepride Jul 27, 2026
3db328b
[BugFix][MiniCPM-o] Restore audio output without async chunk (#5455)
R2-Y Jul 27, 2026
5e1942a
fix pre-commit
bowieshi Jul 27, 2026
d999576
fix pre-commit
bowieshi Jul 27, 2026
3516d63
fix conflict
bowieshi Jul 29, 2026
445435f
Merge branch 'main' into feature/refactor-2
Gaohan123 Jul 29, 2026
61684f7
fix first = outputs[0] & simpleNamespace
bowieshi Jul 30, 2026
63fb08c
fix merge conflict
bowieshi Jul 30, 2026
7c34afa
fix CI
bowieshi Aug 1, 2026
d44804b
Merge branch 'main' into feature/refactor-2
bowieshi Aug 1, 2026
690a648
Merge branch 'main' into feature/refactor-2
bowieshi Aug 5, 2026
3f093ea
OmniRequestOutput inherits RequestOutput
bowieshi Jul 16, 2026
1841934
fix multi_modal_placeholders
bowieshi Jul 22, 2026
e2efc59
fix from_pipeline
bowieshi Jul 22, 2026
4b4a034
rm dead code(unwrap, copy, property) & fix __init__ monkey patch
bowieshi Jul 27, 2026
8b3c51d
fix quant
bowieshi Jul 27, 2026
fdaf8ac
fix pre-commit
bowieshi Jul 27, 2026
35210e3
[BugFix][MiniCPM-o] Restore audio output without async chunk (#5455)
R2-Y Jul 27, 2026
e6e2146
fix pre-commit
bowieshi Jul 27, 2026
3b9fad4
fix pre-commit
bowieshi Jul 27, 2026
e786eb0
fix first = outputs[0] & simpleNamespace
bowieshi Jul 30, 2026
b0151e9
fix CI
bowieshi Aug 1, 2026
7b258be
Merge branch 'main' into feature/refactor-2
hsliuustc0106 Aug 7, 2026
0d7baa3
fix CI error
bowieshi Aug 10, 2026
a7966ee
merge: 解决冲突并合并远程更新
bowieshi Aug 10, 2026
9316f61
fix no found tts2code2wav_token_only
bowieshi Aug 10, 2026
87bbfce
fix test_vae_decode_parallelism
bowieshi Aug 10, 2026
3c17811
fix pre-commit test_minicpmo_4_5_async_chunk.py
bowieshi Aug 10, 2026
932d0f5
Merge branch 'main' into feature/refactor-2
hsliuustc0106 Aug 10, 2026
6392b6b
fix conflic
bowieshi Aug 12, 2026
6ce63b8
Merge branch 'main' into feature/refactor-2
bowieshi Aug 12, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 10 additions & 11 deletions benchmarks/diffusion/quantization_quality.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,6 @@ def _build_omni_kwargs(args, quantization=None):
def _generate_image(omni, args, prompt, seed):
"""Generate a single image and return (PIL.Image, time_seconds, memory_gib)."""
from vllm_omni.inputs.data import OmniDiffusionSamplingParams
from vllm_omni.outputs import OmniRequestOutput
from vllm_omni.platforms import current_omni_platform

generator = torch.Generator(device=current_omni_platform.device_type).manual_seed(seed)
Expand All @@ -176,7 +175,7 @@ def _generate_image(omni, args, prompt, seed):
elapsed = time.perf_counter() - start
peak_mem = torch.accelerator.max_memory_allocated() / (1024**3)

req_out = OmniRequestOutput.unwrap_result(outputs)
req_out = outputs[0] if isinstance(outputs, list) else outputs
if not req_out.images:
raise ValueError("Could not extract image output from result.")
img = req_out.images[0]
Expand Down Expand Up @@ -206,15 +205,15 @@ def _generate_video(omni, args, prompt, seed):
elapsed = time.perf_counter() - start
peak_mem = torch.accelerator.max_memory_allocated() / (1024**3)

first = outputs[0]
if hasattr(first, "request_output") and isinstance(first.request_output, list):
inner = first.request_output[0]
if isinstance(inner, OmniRequestOutput) and hasattr(inner, "images"):
frames = inner.images[0] if inner.images else None
else:
frames = inner
elif hasattr(first, "images") and first.images:
frames = first.images[0]
if isinstance(outputs, list) and isinstance(outputs[0], OmniRequestOutput):
first = outputs[0]
elif isinstance(outputs, OmniRequestOutput):
first = outputs
else:
raise ValueError("Could not extract video frames from output.")

if hasattr(first, "images"):
frames = first.images[0] if first.images else None
else:
raise ValueError("Could not extract video frames from output.")

Expand Down
2 changes: 1 addition & 1 deletion benchmarks/glm_image/vllm-omni/inference.py
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ def benchmark(args: argparse.Namespace) -> None:
output_idx = 0
for stage_outputs in omni.generate(all_prompts, sampling_params_list, py_generator=True):
if stage_outputs.final_output_type == "image":
request_output = stage_outputs.request_output
request_output = stage_outputs
request_id = getattr(request_output, "request_id", "")

images = getattr(request_output, "images", [])
Expand Down
2 changes: 1 addition & 1 deletion examples/offline_inference/aura_omni/end2end.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ def build_sampling_params() -> list[SamplingParams]:


def save_stage_output(stage_outputs, output_dir: str) -> None:
output = stage_outputs.request_output
output = stage_outputs
request_id = output.request_id
if stage_outputs.final_output_type == "text":
text_output = output.outputs[0].text
Expand Down
2 changes: 1 addition & 1 deletion examples/offline_inference/covo_audio/end2end.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ def main(args):
os.makedirs(output_dir, exist_ok=True)

for stage_outputs in omni_outputs:
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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ async def main():
if not outputs:
raise ValueError("No output produced from omni.generate()")

first_out = outputs[0].request_output
first_out = outputs[0]
req_out: OmniRequestOutput = first_out

# Verify trajectory data (from custom pipeline)
Expand Down
2 changes: 1 addition & 1 deletion examples/offline_inference/dynin_omni/end2end.py
Original file line number Diff line number Diff line change
Expand Up @@ -741,7 +741,7 @@ def make_mmu_prompt(

def iter_mm_outputs(outputs: list[Any]):
for omni_out in outputs:
req_out = getattr(omni_out, "request_output", None)
req_out = omni_out
req_list = req_out if isinstance(req_out, list) else [req_out]
for item in req_list:
if item is None:
Expand Down
2 changes: 1 addition & 1 deletion examples/offline_inference/hunyuan_image3/end2end.py
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ def main():
)
img_idx = 0
for req_output in omni_outputs:
ro = getattr(req_output, "request_output", None)
ro = req_output
stage_id = getattr(req_output, "stage_id", None)

# AR stage text — each CompletionOutput.text is already a delta when
Expand Down
2 changes: 1 addition & 1 deletion examples/offline_inference/image_to_image/image_edit.py
Original file line number Diff line number Diff line change
Expand Up @@ -621,7 +621,7 @@ def main():
images = getattr(output, "images", None)
if images:
break
req_out = getattr(output, "request_output", None)
req_out = output
images = getattr(req_out, "images", None) if req_out is not None else None
if images:
break
Expand Down
4 changes: 2 additions & 2 deletions examples/offline_inference/image_to_video/image_to_video.py
Original file line number Diff line number Diff line change
Expand Up @@ -646,8 +646,8 @@ def main():
if frames.multimodal_output and "audio" in frames.multimodal_output:
audio = frames.multimodal_output["audio"]
audio_sample_rate = frames.multimodal_output.get("audio_sample_rate", audio_sample_rate)
if frames.is_pipeline_output and frames.request_output is not None:
inner_output = frames.request_output
if frames.is_pipeline_output and frames is not None:
inner_output = frames
if isinstance(inner_output, OmniRequestOutput):
if inner_output.multimodal_output and "audio" in inner_output.multimodal_output:
audio = inner_output.multimodal_output["audio"]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
"""
Offline inference example: MammothModa2 image summarization (single AR stage).

Example:
uv run python examples/offline_inference/mammothmodal2_preview/run_mammothmoda2_image_summarize.py \
--model path/to/MammothModa2-Preview \
--deploy-config vllm_omni/deploy/mammoth_moda2_ar.yaml \
--image /path/to/input.jpg \
--question "Please summarize the content of this image."
"""

from __future__ import annotations

import argparse
import os

from PIL import Image
from vllm import SamplingParams
from vllm.multimodal.image import convert_image_mode

from vllm_omni import Omni

DEFAULT_SYSTEM = "You are a helpful assistant."
DEFAULT_QUESTION = "Please summarize the content of this image."


def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser(description="MammothModa2 image summarization (offline, AR only).")
parser.add_argument("--model", type=str, required=True, help="Path to model directory or model id.")
parser.add_argument("--deploy-config", type=str, required=True, help="Path to deploy config yaml.")
parser.add_argument("--image", type=str, required=True, help="Path to input image.")
parser.add_argument("--question", type=str, default=DEFAULT_QUESTION, help="Question/instruction for the model.")
parser.add_argument("--system", type=str, default=DEFAULT_SYSTEM, help="System prompt.")
parser.add_argument(
"--max-tokens",
type=int,
default=512,
help="Max new tokens to generate.",
)
parser.add_argument("--temperature", type=float, default=0.2)
parser.add_argument("--top-p", type=float, default=0.9)
parser.add_argument("--seed", type=int, default=42)
parser.add_argument("--trust-remote-code", action="store_true")
parser.add_argument(
"--enable-diffusion-pipeline-profiler",
action="store_true",
help="Enable diffusion pipeline profiler to display stage durations.",
)
return parser.parse_args()


def build_prompt(system: str, question: str) -> str:
return (
f"<|im_start|>system\n{system}<|im_end|>\n"
"<|im_start|>user\n"
"<|vision_start|><|image_pad|><|vision_end|>"
f"{question}<|im_end|>\n"
"<|im_start|>assistant\n"
)


def main() -> None:
args = parse_args()

if not os.path.exists(args.image):
raise FileNotFoundError(f"Image file not found: {args.image}")

pil_image = Image.open(args.image)
image_data = convert_image_mode(pil_image, "RGB")
prompt = build_prompt(args.system, args.question)

omni = Omni(
model=args.model,
deploy_config=args.deploy_config,
trust_remote_code=args.trust_remote_code,
enable_diffusion_pipeline_profiler=args.enable_diffusion_pipeline_profiler,
)
try:
sp = SamplingParams(
temperature=float(args.temperature),
top_p=float(args.top_p),
top_k=-1,
max_tokens=int(args.max_tokens),
seed=int(args.seed),
detokenize=True,
)
# NOTE: omni.generate() returns a Generator[OmniRequestOutput, None, None].
# Consume it inside the try block so the worker isn't closed early.
outputs = list(
omni.generate(
[
{
"prompt": prompt,
"multi_modal_data": {"image": image_data},
"additional_information": {"omni_task": ["chat"]},
}
],
[sp],
)
)
finally:
omni.close()

lines: list[str] = []
for stage_outputs in outputs:
ro = stage_outputs
text = ro.outputs[0].text if getattr(ro, "outputs", None) else str(ro)
lines.append(f"request_id: {getattr(ro, 'request_id', 'unknown')}\n")
lines.append("answer:\n")
lines.append(text.strip() + "\n")
lines.append("\n")

print("\n".join(lines))


if __name__ == "__main__":
main()
2 changes: 1 addition & 1 deletion examples/offline_inference/mimo_audio/end2end.py
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ def main(args):
os.makedirs(output_dir, exist_ok=True)

for stage_outputs in omni_outputs:
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
Expand Down
2 changes: 1 addition & 1 deletion examples/offline_inference/ming_flash_omni/end2end.py
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ def main(args):
omni.start_profile(stages=args.profiler_stages)

for stage_outputs in omni.generate(prompts, sampling_params_list):
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
Expand Down
2 changes: 1 addition & 1 deletion examples/offline_inference/qwen2_5_omni/end2end.py
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,7 @@ def main(args):
total_requests = len(prompts)
processed_count = 0
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
Expand Down
2 changes: 1 addition & 1 deletion examples/offline_inference/qwen3_omni/end2end.py
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,7 @@ def main(args):
print(f"query type: {args.query_type}")

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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ async def run_single_request(
sampling_params_list=sampling_params_list,
output_modalities=output_modalities,
):
output = omni_output.request_output
output = omni_output
if omni_output.final_output_type == "text":
if stage_0_first_output_ts is None:
stage_0_first_output_ts = time.perf_counter()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
from vllm_omni.diffusion.data import DiffusionParallelConfig
from vllm_omni.entrypoints.omni import Omni
from vllm_omni.inputs.data import OmniDiffusionSamplingParams
from vllm_omni.outputs import OmniRequestOutput
from vllm_omni.platforms import current_omni_platform


Expand Down Expand Up @@ -352,8 +351,8 @@ def main():
else:
print("[Profiler] No valid profiling data returned.")

# Extract output from result
output = OmniRequestOutput.unwrap_result(result)
# omni.generate() returns a list for sync calls; unwrap single-result list.
output = result[0] if isinstance(result, list) else result

if not output.images:
raise ValueError("No video frames found in OmniRequestOutput.")
Expand Down
2 changes: 1 addition & 1 deletion examples/offline_inference/step_audio2/end2end.py
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ def _get_request_index(req_id: str, fallback: int) -> int:
# Process outputs from each stage
for stage_idx, stage_outputs in enumerate(omni_outputs):
# request_output may be a single object or a list
raw_output = stage_outputs.request_output
raw_output = stage_outputs
outputs_list = raw_output if isinstance(raw_output, list) else [raw_output]

if stage_outputs.final_output_type == "text":
Expand Down
5 changes: 3 additions & 2 deletions examples/offline_inference/text_to_audio/text_to_audio.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
from vllm_omni.entrypoints.omni import Omni
from vllm_omni.inputs.data import OmniDiffusionSamplingParams
from vllm_omni.model_extras import get_extra_body_params, get_model_class_name
from vllm_omni.outputs import OmniRequestOutput
from vllm_omni.platforms import current_omni_platform

AUDIOX_TASKS = ("t2a", "t2m", "v2a", "v2m", "tv2a", "tv2m")
Expand Down Expand Up @@ -388,9 +389,9 @@ def main():
raise ValueError("No output generated from omni.generate()")

output = outputs[0]
if not hasattr(output, "request_output") or not output.request_output:
if not isinstance(output, OmniRequestOutput) or not output:
raise ValueError("No request_output found in OmniRequestOutput")
request_output = output.request_output
request_output = output
if not hasattr(request_output, "multimodal_output"):
raise ValueError("No multimodal_output found in request_output")

Expand Down
2 changes: 1 addition & 1 deletion examples/offline_inference/text_to_image/gradio_demo.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ def run_inference(
)
images_outputs = []
for output in outputs:
req_out = output.request_output
req_out = 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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -656,7 +656,7 @@ def main():
images = getattr(output, "images", None)
if images:
break
req_out = getattr(output, "request_output", None)
req_out = output
images = getattr(req_out, "images", None) if req_out is not None else None
if images:
break
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ def run_e2e():
print(f"Received {len(outputs)} outputs.")
for i, output in enumerate(outputs):
try:
ro = output.request_output
ro = output
if ro is None:
print("No request_output found.")
continue
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ def main(args):

t_start = time.perf_counter()
for stage_outputs in omni.generate(inputs):
request_output = stage_outputs.request_output
request_output = stage_outputs
if request_output is None or not request_output.outputs:
continue
_save_wav(
Expand Down Expand Up @@ -215,7 +215,7 @@ async def main_streaming(args):
sample_rate = None

async for stage_output in omni.generate(prompt, request_id=request_id):
mm = stage_output.request_output.outputs[0].multimodal_output
mm = stage_output.outputs[0].multimodal_output
if not stage_output.finished:
t_now = time.perf_counter()
sample_rate, n = _collect_audio_chunk(mm, all_audio_chunks, sample_rate)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ def main(args) -> None:
params_list = sampling_params

for stage_outputs in omni.generate(inputs, params_list):
for i, req_output in enumerate(stage_outputs.request_output):
for i, req_output in enumerate(stage_outputs):
for j, out in enumerate(req_output.outputs):
mm = out.multimodal_output
if mm is None:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ def run_e2e():
print(f"Received {len(outputs)} outputs.")
for i, output in enumerate(outputs):
try:
ro = output.request_output
ro = output
if ro is None:
print("No request_output found.")
continue
Expand Down
Loading
Loading