diff --git a/.buildkite/scripts/run_qwen_offline_example.sh b/.buildkite/scripts/run_qwen_offline_example.sh index cbe5452ac..6e40868eb 100755 --- a/.buildkite/scripts/run_qwen_offline_example.sh +++ b/.buildkite/scripts/run_qwen_offline_example.sh @@ -1,23 +1,36 @@ #!/usr/bin/env bash set -euo pipefail +sudo apt update +sudo apt install ffmpeg -y # Move to repo root (script lives in .buildkite/scripts/) ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" cd "${ROOT_DIR}" -python3 -m pip install --upgrade pip uv -BOOTSTRAP_PY="$(command -v python3)" -UV_BIN=("${BOOTSTRAP_PY}" -m uv) +UV_INSTALL_DIR="${ROOT_DIR}/.local/bin" +case ":${PATH}:" in + *":${UV_INSTALL_DIR}:"*) ;; + *) export PATH="${UV_INSTALL_DIR}:${PATH}" ;; +esac + +if ! command -v uv >/dev/null 2>&1; then + mkdir -p "${UV_INSTALL_DIR}" + curl -LsSf https://astral.sh/uv/install.sh | env UV_INSTALL_DIR="${UV_INSTALL_DIR}" sh +fi + +UV_BIN=(uv) "${UV_BIN[@]}" python install 3.12 "${UV_BIN[@]}" venv --python 3.12 .venv source .venv/bin/activate -"${UV_BIN[@]}" pip install --python .venv/bin/python vllm==0.11.0 --torch-backend=auto -"${UV_BIN[@]}" pip install --python .venv/bin/python -e . +"${UV_BIN[@]}" pip install -e . +"${UV_BIN[@]}" pip install vllm==0.11.0 --torch-backend=auto EXAMPLE_DIR="examples/offline_inference/qwen2_5_omni" cd "${EXAMPLE_DIR}" -bash run_single_prompt.sh +python end2end.py --output-wav output_audio \ + --query-type use_audio_in_video \ + --no-save-results diff --git a/examples/offline_inference/qwen2_5_omni/end2end.py b/examples/offline_inference/qwen2_5_omni/end2end.py index be4e2c1a1..93d29c793 100644 --- a/examples/offline_inference/qwen2_5_omni/end2end.py +++ b/examples/offline_inference/qwen2_5_omni/end2end.py @@ -5,6 +5,7 @@ This example shows how to use vLLM-omni for running offline inference with the correct prompt format on Qwen2.5-Omni """ +import argparse import os from typing import NamedTuple @@ -195,35 +196,43 @@ def main(args): omni_outputs = omni_llm.generate(prompts, sampling_params_list) - # Determine output directory: prefer --output-dir; fallback to --output-wav - output_dir = args.output_dir if getattr(args, "output_dir", None) else args.output_wav - os.makedirs(output_dir, exist_ok=True) + output_dir = None + if args.save_results: + # Determine output directory: prefer --output-dir; fallback to --output-wav + output_dir = args.output_dir if getattr(args, "output_dir", None) else args.output_wav + os.makedirs(output_dir, exist_ok=True) for stage_outputs in omni_outputs: if stage_outputs.final_output_type == "text": for output in stage_outputs.request_output: request_id = int(output.request_id) text_output = output.outputs[0].text - # Save aligned text file per request - prompt_text = prompts[request_id]["prompt"] - out_txt = os.path.join(output_dir, f"{request_id:05d}.txt") - lines = [] - lines.append("Prompt:\n") - lines.append(str(prompt_text) + "\n") - lines.append("vllm_text_output:\n") - lines.append(str(text_output).strip() + "\n") - try: - with open(out_txt, "w", encoding="utf-8") as f: - f.writelines(lines) - except Exception as e: - print(f"[Warn] Failed writing text file {out_txt}: {e}") - print(f"Request ID: {request_id}, Text saved to {out_txt}") + if args.save_results: + # Save aligned text file per request + prompt_text = prompts[request_id]["prompt"] + out_txt = os.path.join(output_dir, f"{request_id:05d}.txt") + lines = [] + lines.append("Prompt:\n") + lines.append(str(prompt_text) + "\n") + lines.append("vllm_text_output:\n") + lines.append(str(text_output).strip() + "\n") + try: + with open(out_txt, "w", encoding="utf-8") as f: + f.writelines(lines) + except Exception as e: + print(f"[Warn] Failed writing text file {out_txt}: {e}") + print(f"Request ID: {request_id}, Text saved to {out_txt}") + else: + print(f"Request ID: {request_id}, Text output:\n{text_output}") elif stage_outputs.final_output_type == "audio": for output in stage_outputs.request_output: request_id = int(output.request_id) audio_tensor = output.multimodal_output["audio"] - output_wav = os.path.join(output_dir, f"output_{output.request_id}.wav") - sf.write(output_wav, audio_tensor.detach().cpu().numpy(), samplerate=24000) - print(f"Request ID: {request_id}, Saved audio to {output_wav}") + if args.save_results: + output_wav = os.path.join(output_dir, f"output_{output.request_id}.wav") + sf.write(output_wav, audio_tensor.detach().cpu().numpy(), samplerate=24000) + print(f"Request ID: {request_id}, Saved audio to {output_wav}") + else: + print(f"Request ID: {request_id}, Received audio output (not saved).") def parse_args(): @@ -266,6 +275,12 @@ def parse_args(): default=65536, help="Threshold for using shared memory in bytes (default: 65536)", ) + parser.add_argument( + "--save-results", + action=argparse.BooleanOptionalAction, + default=True, + help="Save text/audio outputs to files (default: enabled). Use --no-save-results to disable.", + ) parser.add_argument( "--output-wav", default="output_audio",