[Bugfix] Fix MiniCPM-o 4.5 audio placeholder pool step (#5116)
Signed-off-by: a-kaa <siruhe666@gmail.com> Co-authored-by: amy-why-3459 <wuhaiyan17@huawei.com>
This commit is contained in:
1 parent
5d44868e91
commit
0576264dd1
2 files changed
+76
-2
No files matched your search
@@ -0,0 +1,71 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
|
||||
"""Regression tests for MiniCPM-o 4.5 audio placeholder pooling."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import math
|
||||
from types import SimpleNamespace
|
||||
|
||||
import pytest
|
||||
|
||||
from vllm_omni.model_executor.models.minicpmo_4_5.minicpmo_4_5_omni_llm import (
|
||||
MiniCPMO45OmniLLMProcessingInfo,
|
||||
MiniCPMOConfig,
|
||||
)
|
||||
|
||||
pytestmark = [pytest.mark.core_model, pytest.mark.cpu]
|
||||
|
||||
|
||||
class _FakeProcessor:
|
||||
"""Minimal processor surface used by ``get_audio_placeholder``."""
|
||||
|
||||
def __init__(self) -> None:
|
||||
# Reproduce the cached vLLM processor's legacy initial state.
|
||||
self.pool_step = 2
|
||||
self.audio_processor = SimpleNamespace(hop_length=160)
|
||||
self.image_processor = SimpleNamespace(mean=[0.0], std=[1.0])
|
||||
|
||||
def get_audio_placeholder(
|
||||
self,
|
||||
audio_lens: int,
|
||||
chunk_input: bool = True,
|
||||
chunk_length: int = 1,
|
||||
) -> str:
|
||||
del chunk_input, chunk_length
|
||||
feature_lens = math.ceil(audio_lens / self.audio_processor.hop_length)
|
||||
cnn_feature_lens = (feature_lens - 1) // 2 + 1
|
||||
output_lens = (cnn_feature_lens - self.pool_step) // self.pool_step + 1
|
||||
return "<unk>" * output_lens
|
||||
|
||||
|
||||
def _processing_info(pool_step: int, processor: _FakeProcessor) -> MiniCPMO45OmniLLMProcessingInfo:
|
||||
info = object.__new__(MiniCPMO45OmniLLMProcessingInfo)
|
||||
info.ctx = SimpleNamespace(
|
||||
tokenizer=object(),
|
||||
get_hf_config=lambda: SimpleNamespace(audio_pool_step=pool_step),
|
||||
get_hf_processor=lambda **kwargs: processor,
|
||||
)
|
||||
return info
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("configured_pool_step", "expected_placeholders"),
|
||||
[(5, 50), (2, 125)],
|
||||
)
|
||||
def test_audio_placeholders_follow_checkpoint_pool_step(
|
||||
configured_pool_step: int,
|
||||
expected_placeholders: int,
|
||||
) -> None:
|
||||
"""The prompt path must use the same pool step as the audio encoder."""
|
||||
processor = _FakeProcessor()
|
||||
info = _processing_info(configured_pool_step, processor)
|
||||
|
||||
placeholder = info.get_audio_placeholder(5 * 16_000)
|
||||
|
||||
assert processor.pool_step == configured_pool_step
|
||||
assert placeholder.count("<unk>") == expected_placeholders
|
||||
|
||||
|
||||
def test_minicpmo_4_5_pool_step_defaults_to_checkpoint_value() -> None:
|
||||
assert MiniCPMOConfig().audio_pool_step == 5
|
||||
@@ -328,7 +328,7 @@ class MiniCPMOConfig(Qwen2Config):
|
||||
tts_config=None,
|
||||
use_image_id=True,
|
||||
vision_batch_size=16,
|
||||
audio_pool_step=2,
|
||||
audio_pool_step=5,
|
||||
audio_chunk_length=1.0,
|
||||
stream_input=False,
|
||||
init_vision=True,
|
||||
@@ -2839,6 +2839,9 @@ class MiniCPMO45OmniLLMProcessingInfo(BaseProcessingInfo):
|
||||
) -> str:
|
||||
hf_processor = self.get_hf_processor()
|
||||
|
||||
# Keep prompt placeholders aligned with the encoder's checkpoint config.
|
||||
hf_processor.pool_step = self.get_default_audio_pool_step()
|
||||
|
||||
return hf_processor.get_audio_placeholder(
|
||||
audio_lens,
|
||||
chunk_input=chunk_input,
|
||||
@@ -2846,7 +2849,7 @@ class MiniCPMO45OmniLLMProcessingInfo(BaseProcessingInfo):
|
||||
)
|
||||
|
||||
def get_default_audio_pool_step(self) -> int:
|
||||
return getattr(self.get_hf_config(), "audio_pool_step", 2)
|
||||
return getattr(self.get_hf_config(), "audio_pool_step", 5)
|
||||
|
||||
def get_default_audio_sampling_rate(self) -> int:
|
||||
return 16000
|
||||
|
||||
Reference in new issue
Block a user