From c50408a808e53f906359f802ad2e99e8949916fd Mon Sep 17 00:00:00 2001 From: "ruirui(rein) yang" <73573651+R2-Y@users.noreply.github.com> Date: Thu, 30 Jul 2026 10:42:42 +0800 Subject: [PATCH] [bugfix][MiniCPM-o]delete duplicate files (#5537) Signed-off-by: R2-Y --- examples/online_serving/minicpmo/README.md | 15 ++-- .../minicpmo/streaming_chat_completion.py | 71 ------------------- recipes/OpenBMB/MiniCPM-o-4_5.md | 14 ++-- .../online_serving/test_minicpmo_streaming.py | 29 -------- 4 files changed, 16 insertions(+), 113 deletions(-) delete mode 100644 examples/online_serving/minicpmo/streaming_chat_completion.py delete mode 100644 tests/examples/online_serving/test_minicpmo_streaming.py diff --git a/examples/online_serving/minicpmo/README.md b/examples/online_serving/minicpmo/README.md index 134ddd62c..bbf43fb4f 100644 --- a/examples/online_serving/minicpmo/README.md +++ b/examples/online_serving/minicpmo/README.md @@ -89,17 +89,18 @@ python openai_chat_completion_client_for_multimodal_generation.py \ --prompt "Briefly introduce yourself." ``` -Streaming text + audio: +Streaming text + audio (use `--stream`): ```bash -python streaming_chat_completion.py \ - --base-url http://localhost:8099/v1 \ - --output minicpmo_stream.wav +python openai_chat_completion_client_for_multimodal_generation.py \ + --query-type text \ + --prompt "Briefly introduce yourself." \ + --port 8099 \ + --stream ``` -The example prints text deltas immediately and joins the independently encoded -24 kHz WAV audio deltas into one valid WAV file. Add `--text-only` to skip -Talker and Code2Wav. +The client prints text deltas as they arrive and saves streamed audio chunks +to WAV files. Shared helpers also work if you pass MiniCPM defaults yourself: diff --git a/examples/online_serving/minicpmo/streaming_chat_completion.py b/examples/online_serving/minicpmo/streaming_chat_completion.py deleted file mode 100644 index b4a4be2f0..000000000 --- a/examples/online_serving/minicpmo/streaming_chat_completion.py +++ /dev/null @@ -1,71 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 -# SPDX-FileCopyrightText: Copyright contributors to the vLLM project -"""Stream MiniCPM-o 4.5 text and audio from /v1/chat/completions.""" - -from __future__ import annotations - -import argparse -import base64 -import io -import wave -from pathlib import Path - -from openai import OpenAI - - -def append_wav_chunk(encoded: str, pcm_parts: list[bytes]) -> tuple[int, int, int]: - """Decode one base64 WAV delta and append its PCM frames.""" - with wave.open(io.BytesIO(base64.b64decode(encoded)), "rb") as wav: - channels = wav.getnchannels() - sample_width = wav.getsampwidth() - sample_rate = wav.getframerate() - pcm_parts.append(wav.readframes(wav.getnframes())) - return channels, sample_width, sample_rate - - -def main() -> None: - parser = argparse.ArgumentParser() - parser.add_argument("--base-url", default="http://localhost:8099/v1") - parser.add_argument("--model", default="openbmb/MiniCPM-o-4_5") - parser.add_argument("--prompt", default="Say hello, then introduce vLLM in one sentence.") - parser.add_argument("--output", type=Path, default=Path("minicpmo_stream.wav")) - parser.add_argument("--text-only", action="store_true") - args = parser.parse_args() - - modalities = ["text"] if args.text_only else ["text", "audio"] - stream = OpenAI(base_url=args.base_url, api_key="EMPTY").chat.completions.create( - model=args.model, - messages=[{"role": "user", "content": args.prompt}], - modalities=modalities, - stream=True, - extra_body={"chat_template_kwargs": {"use_tts_template": not args.text_only}}, - ) - - pcm_parts: list[bytes] = [] - audio_format: tuple[int, int, int] | None = None - for chunk in stream: - for choice in chunk.choices: - content = getattr(choice.delta, "content", None) - if not content: - continue - if getattr(chunk, "modality", None) == "audio": - current_format = append_wav_chunk(content, pcm_parts) - if audio_format is not None and current_format != audio_format: - raise ValueError(f"Audio format changed: {audio_format} -> {current_format}") - audio_format = current_format - elif getattr(chunk, "modality", None) == "text": - print(content, end="", flush=True) - - print() - if pcm_parts and audio_format is not None: - channels, sample_width, sample_rate = audio_format - with wave.open(str(args.output), "wb") as wav: - wav.setnchannels(channels) - wav.setsampwidth(sample_width) - wav.setframerate(sample_rate) - wav.writeframes(b"".join(pcm_parts)) - print(f"Audio saved to {args.output} ({sample_rate} Hz)") - - -if __name__ == "__main__": - main() diff --git a/recipes/OpenBMB/MiniCPM-o-4_5.md b/recipes/OpenBMB/MiniCPM-o-4_5.md index 97b3c6d6d..6bd37e88a 100644 --- a/recipes/OpenBMB/MiniCPM-o-4_5.md +++ b/recipes/OpenBMB/MiniCPM-o-4_5.md @@ -175,16 +175,18 @@ in another choice's `message.audio.data` (24 kHz mono, see Notes). With `modalities: ["text", "audio"]` you typically get two `choices` entries (one text, one audio). -**Streaming text + speech**: +**Streaming text + speech** (use `--stream`): ```bash -python examples/online_serving/minicpmo/streaming_chat_completion.py \ - --base-url http://localhost:8099/v1 \ - --output minicpmo_stream.wav +python examples/online_serving/minicpmo/openai_chat_completion_client_for_multimodal_generation.py \ + --query-type text \ + --prompt "Say hello, then introduce vLLM in one sentence." \ + --port 8099 \ + --stream ``` -The client prints text deltas as they arrive and reconstructs one valid WAV -from the independently encoded audio deltas. +The client prints text deltas as they arrive and saves streamed audio chunks +to WAV files. **Gradio demo (text + image + audio + video UI)**: diff --git a/tests/examples/online_serving/test_minicpmo_streaming.py b/tests/examples/online_serving/test_minicpmo_streaming.py deleted file mode 100644 index 90ba992eb..000000000 --- a/tests/examples/online_serving/test_minicpmo_streaming.py +++ /dev/null @@ -1,29 +0,0 @@ -import base64 -import io -import runpy -import wave -from pathlib import Path - -import pytest - -pytestmark = [pytest.mark.core_model, pytest.mark.cpu] - - -def test_append_wav_chunk_extracts_pcm_frames() -> None: - example = Path(__file__).parents[3] / "examples" / "online_serving" / "minicpmo" / "streaming_chat_completion.py" - append_wav_chunk = runpy.run_path(example)["append_wav_chunk"] - encoded_buffer = io.BytesIO() - with wave.open(encoded_buffer, "wb") as wav: - wav.setnchannels(1) - wav.setsampwidth(2) - wav.setframerate(24000) - wav.writeframes(b"\x01\x02\x03\x04") - - pcm_parts: list[bytes] = [] - audio_format = append_wav_chunk( - base64.b64encode(encoded_buffer.getvalue()).decode(), - pcm_parts, - ) - - assert audio_format == (1, 2, 24000) - assert pcm_parts == [b"\x01\x02\x03\x04"]