Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
298042732c |
No files matched your search
@@ -6,7 +6,6 @@ import pytest
|
||||
from vllm.v1.request import RequestStatus
|
||||
|
||||
import vllm_omni.core.sched.omni_ar_scheduler as scheduler_mod
|
||||
import vllm_omni.model_executor.models.voxcpm2.scheduler as voxcpm2_scheduler_mod
|
||||
from vllm_omni.model_executor.models.voxcpm2.scheduler import VoxCPM2OmniARAsyncScheduler
|
||||
|
||||
pytestmark = [pytest.mark.core_model, pytest.mark.cpu]
|
||||
@@ -52,30 +51,14 @@ class _MockRequest:
|
||||
return RequestStatus.is_finished(self.status)
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def _mock_cuda_graph_platform(monkeypatch) -> None:
|
||||
monkeypatch.setattr(voxcpm2_scheduler_mod.current_omni_platform, "is_cuda", lambda: True)
|
||||
|
||||
|
||||
def _make_scheduler(
|
||||
*,
|
||||
enable_unified_decode_graph: bool | None = True,
|
||||
deterministic_cfm_noise: bool = False,
|
||||
runtime_config_on_model_config: bool = False,
|
||||
) -> VoxCPM2OmniARAsyncScheduler:
|
||||
def _make_scheduler(*, enable_unified_decode_graph: bool = True) -> VoxCPM2OmniARAsyncScheduler:
|
||||
sched = VoxCPM2OmniARAsyncScheduler.__new__(VoxCPM2OmniARAsyncScheduler)
|
||||
hf_config = SimpleNamespace()
|
||||
model_config = SimpleNamespace(hf_config=hf_config)
|
||||
if enable_unified_decode_graph is not None or deterministic_cfm_noise:
|
||||
runtime_config = SimpleNamespace(
|
||||
enable_unified_decode_graph=True if enable_unified_decode_graph is None else enable_unified_decode_graph,
|
||||
deterministic_cfm_noise=deterministic_cfm_noise,
|
||||
runtime_config = SimpleNamespace(enable_unified_decode_graph=enable_unified_decode_graph)
|
||||
sched.vllm_config = SimpleNamespace(
|
||||
model_config=SimpleNamespace(
|
||||
hf_config=SimpleNamespace(voxcpm2_runtime_config=runtime_config),
|
||||
)
|
||||
if runtime_config_on_model_config:
|
||||
model_config.voxcpm2_runtime_config = runtime_config
|
||||
else:
|
||||
hf_config.voxcpm2_runtime_config = runtime_config
|
||||
sched.vllm_config = SimpleNamespace(model_config=model_config)
|
||||
)
|
||||
return sched
|
||||
|
||||
|
||||
@@ -103,39 +86,6 @@ def test_voxcpm2_unified_decode_graph_does_not_defer_when_disabled() -> None:
|
||||
assert not scheduler._should_defer_waiting_for_unified_decode_graph()
|
||||
|
||||
|
||||
def test_voxcpm2_unified_decode_graph_uses_model_runtime_defaults() -> None:
|
||||
scheduler = _make_scheduler(enable_unified_decode_graph=None)
|
||||
scheduler.running = [_MockRequest("decode")]
|
||||
scheduler.waiting = _MockQueue([_MockRequest("prefill", status=RequestStatus.WAITING)])
|
||||
|
||||
assert scheduler._should_defer_waiting_for_unified_decode_graph()
|
||||
|
||||
|
||||
def test_voxcpm2_unified_decode_graph_reads_model_config_runtime_config() -> None:
|
||||
scheduler = _make_scheduler(enable_unified_decode_graph=True, runtime_config_on_model_config=True)
|
||||
scheduler.running = [_MockRequest("decode")]
|
||||
scheduler.waiting = _MockQueue([_MockRequest("prefill", status=RequestStatus.WAITING)])
|
||||
|
||||
assert scheduler._should_defer_waiting_for_unified_decode_graph()
|
||||
|
||||
|
||||
def test_voxcpm2_unified_decode_graph_does_not_defer_with_deterministic_noise() -> None:
|
||||
scheduler = _make_scheduler(deterministic_cfm_noise=True)
|
||||
scheduler.running = [_MockRequest("decode")]
|
||||
scheduler.waiting = _MockQueue([_MockRequest("prefill", status=RequestStatus.WAITING)])
|
||||
|
||||
assert not scheduler._should_defer_waiting_for_unified_decode_graph()
|
||||
|
||||
|
||||
def test_voxcpm2_unified_decode_graph_does_not_defer_without_cuda_graph(monkeypatch) -> None:
|
||||
monkeypatch.setattr(voxcpm2_scheduler_mod.current_omni_platform, "is_cuda", lambda: False)
|
||||
scheduler = _make_scheduler()
|
||||
scheduler.running = [_MockRequest("decode")]
|
||||
scheduler.waiting = _MockQueue([_MockRequest("prefill", status=RequestStatus.WAITING)])
|
||||
|
||||
assert not scheduler._should_defer_waiting_for_unified_decode_graph()
|
||||
|
||||
|
||||
def test_unified_decode_graph_deferral_restores_waiting_queue(monkeypatch) -> None:
|
||||
scheduler = _make_scheduler()
|
||||
scheduler.running = [_MockRequest("decode")]
|
||||
|
||||
@@ -3344,27 +3344,6 @@ class TestTTSAsyncOffloading:
|
||||
qwen3_tts_server._build_tts_params.assert_called_once()
|
||||
qwen3_tts_server._estimate_prompt_len_async.assert_awaited_once()
|
||||
|
||||
def test_prepare_speech_generation_qwen3_default_seed_sets_tts_local_seed(
|
||||
self, qwen3_tts_server, mocker: MockerFixture
|
||||
):
|
||||
"""Deploy default seed should seed Qwen3 TTS residual MTP sampling."""
|
||||
qwen3_tts_server.engine_client.default_sampling_params_list = [
|
||||
SimpleNamespace(max_tokens=2048, seed=42, extra_args=None)
|
||||
]
|
||||
qwen3_tts_server._validate_tts_request = mocker.MagicMock(return_value=None)
|
||||
qwen3_tts_server._build_tts_params = mocker.MagicMock(
|
||||
return_value={"text": ["hello"], "task_type": ["CustomVoice"], "speaker": ["Vivian"]}
|
||||
)
|
||||
qwen3_tts_server._estimate_prompt_len_async = mocker.AsyncMock(return_value=512)
|
||||
request = OpenAICreateSpeechRequest(input="hello")
|
||||
|
||||
asyncio.run(qwen3_tts_server._prepare_speech_generation(request))
|
||||
|
||||
stage0_params = qwen3_tts_server.engine_client.generate.call_args.kwargs["sampling_params_list"][0]
|
||||
assert stage0_params.seed == 42
|
||||
assert stage0_params.extra_args["tts_local_seed"] == 42
|
||||
assert qwen3_tts_server.engine_client.default_sampling_params_list[0].extra_args is None
|
||||
|
||||
def test_prepare_speech_generation_uses_adapter_model_type_label(
|
||||
self,
|
||||
voxtral_server,
|
||||
|
||||
@@ -12,7 +12,6 @@ REPO_ROOT = Path(__file__).resolve().parents[4]
|
||||
RUNNER = REPO_ROOT / "vllm_omni" / "worker" / "gpu_ar_model_runner.py"
|
||||
RUNNER_ASSISTED_METADATA = REPO_ROOT / "vllm_omni" / "worker" / "runner_assisted_metadata.py"
|
||||
TALKER = REPO_ROOT / "vllm_omni" / "model_executor" / "models" / "voxcpm2" / "voxcpm2_talker.py"
|
||||
VOXCPM2_RUNTIME_CONFIG = REPO_ROOT / "vllm_omni" / "model_executor" / "models" / "voxcpm2" / "runtime_config.py"
|
||||
VOXCPM2_PIPELINE = REPO_ROOT / "vllm_omni" / "model_executor" / "models" / "voxcpm2" / "pipeline.py"
|
||||
VOXCPM2_SCHEDULER = REPO_ROOT / "vllm_omni" / "model_executor" / "models" / "voxcpm2" / "scheduler.py"
|
||||
OMNI_AR_SCHEDULER = REPO_ROOT / "vllm_omni" / "core" / "sched" / "omni_ar_scheduler.py"
|
||||
@@ -75,7 +74,6 @@ def test_ar_runner_without_model_hook_stays_on_normal_path():
|
||||
|
||||
def test_voxcpm2_graph_paths_fail_closed_and_preserve_deterministic_noise():
|
||||
source = TALKER.read_text()
|
||||
runtime_config_source = VOXCPM2_RUNTIME_CONFIG.read_text()
|
||||
compact_source = "".join(source.split())
|
||||
|
||||
assert "_voxcpm2_compile_without_inductor_cudagraphs" in source
|
||||
@@ -88,8 +86,8 @@ def test_voxcpm2_graph_paths_fail_closed_and_preserve_deterministic_noise():
|
||||
assert '"triton.cudagraphs": False' in compile_source
|
||||
assert '"triton.cudagraph_trees": False' in compile_source
|
||||
|
||||
assert "self._enable_unified_decode_graph=self._runtime_config.unified_decode_graph_available(" in compact_source
|
||||
assert "andnotself.deterministic_cfm_noise" in "".join(runtime_config_source.split())
|
||||
assert "self._enable_unified_decode_graph=(use_cuda_graph" in compact_source
|
||||
assert "andnotself._deterministic_cfm_noise" in compact_source
|
||||
assert "decode_tail_graph" not in source
|
||||
|
||||
unified_source = source[source.index("def _forward_unified_decode") :]
|
||||
@@ -185,9 +183,7 @@ def test_voxcpm2_scheduler_policy_stays_model_local():
|
||||
assert "def _should_defer_waiting_admission(self) -> bool:" in common_source
|
||||
|
||||
assert "class VoxCPM2OmniARAsyncScheduler(OmniARAsyncScheduler)" in voxcpm2_scheduler_source
|
||||
assert "from .runtime_config import _VoxCPM2RuntimeConfig" in voxcpm2_scheduler_source
|
||||
assert "_VoxCPM2RuntimeConfig.from_vllm_config(self.vllm_config)" in voxcpm2_scheduler_source
|
||||
assert "unified_decode_graph_available(use_cuda_graph=current_omni_platform.is_cuda())" in voxcpm2_scheduler_source
|
||||
assert "voxcpm2_runtime_config" in voxcpm2_scheduler_source
|
||||
assert "_should_defer_waiting_for_unified_decode_graph" in voxcpm2_scheduler_source
|
||||
assert "def schedule(" not in voxcpm2_scheduler_source
|
||||
assert "create_request_queue" not in voxcpm2_scheduler_source
|
||||
|
||||
@@ -60,6 +60,7 @@ stages:
|
||||
temperature: 0.9
|
||||
top_k: 50
|
||||
max_tokens: 4096
|
||||
seed: 42
|
||||
repetition_penalty: 1.05
|
||||
subtalker_sampling_params:
|
||||
do_sample: true
|
||||
@@ -84,6 +85,7 @@ stages:
|
||||
top_p: 1.0
|
||||
top_k: -1
|
||||
max_tokens: 65536
|
||||
seed: 42
|
||||
repetition_penalty: 1.0
|
||||
|
||||
platforms:
|
||||
|
||||
@@ -3687,18 +3687,6 @@ class OmniOpenAIServingSpeech(OpenAIServing, AudioMixin):
|
||||
stage0_params.extra_args = {}
|
||||
stage0_params.extra_args["tts_local_seed"] = request.seed
|
||||
|
||||
if self._tts_model_type == "qwen3_tts" and sampling_params_list:
|
||||
stage0_params = sampling_params_list[0]
|
||||
default_seed = getattr(stage0_params, "seed", None)
|
||||
if default_seed is not None:
|
||||
import copy
|
||||
|
||||
sampling_params_list = copy.deepcopy(sampling_params_list)
|
||||
stage0_params = sampling_params_list[0]
|
||||
if stage0_params.extra_args is None:
|
||||
stage0_params.extra_args = {}
|
||||
stage0_params.extra_args.setdefault("tts_local_seed", int(default_seed))
|
||||
|
||||
generator = self.engine_client.generate(
|
||||
prompt=prompt,
|
||||
request_id=request_id,
|
||||
|
||||
@@ -1,123 +0,0 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import dataclasses
|
||||
from typing import Any
|
||||
|
||||
from vllm.logger import init_logger
|
||||
|
||||
logger = init_logger(__name__)
|
||||
|
||||
|
||||
@dataclasses.dataclass(frozen=True)
|
||||
class _VoxCPM2RuntimeConfig:
|
||||
enable_profiling: bool = False
|
||||
enable_nvtx_profile: bool = False
|
||||
enable_loc_dit_layer_nvtx: bool = False
|
||||
enable_loc_dit_fused_qkv: bool = True
|
||||
enable_loc_dit_fused_mlp: bool = True
|
||||
enable_loc_dit_zero_dt_cache: bool = True
|
||||
enable_loc_dit_fast_rope: bool = False
|
||||
enable_loc_dit_skip_qkv_contig: bool = True
|
||||
enable_loc_dit_reduce_overhead_no_cg: bool = False
|
||||
enable_loc_dit_fullgraph_no_cg: bool = False
|
||||
cfg_cutoff_ratio: float = 1.0
|
||||
decode_graph_capture_policy: str = "all"
|
||||
enable_vae_cuda_graph: bool = False
|
||||
enable_cfm_cuda_graph: bool = False
|
||||
enable_cfm_prealloc_output: bool = False
|
||||
enable_batched_cfm: bool = True
|
||||
deterministic_cfm_noise: bool = False
|
||||
deterministic_cfm_seed: int = 20260601
|
||||
audio_emit_every: int = 1
|
||||
vae_decode_every: int = 3
|
||||
enable_delayed_audio_copy: bool = False
|
||||
delayed_audio_copy_use_events: bool = False
|
||||
coalesce_audio_d2h: bool = True
|
||||
enable_batched_vae_decode: bool = True
|
||||
enable_batched_fsq_fusion: bool = False
|
||||
batched_fsq_fusion_max_batch: int = 32
|
||||
enable_batched_prefill_tail: bool = False
|
||||
enable_unified_decode_graph: bool = True
|
||||
unified_decode_graph_max_batch_size: int = 64
|
||||
|
||||
@classmethod
|
||||
def from_vllm_config(cls, vllm_config: Any) -> _VoxCPM2RuntimeConfig:
|
||||
model_config = vllm_config.model_config
|
||||
raw = getattr(model_config, "voxcpm2_runtime_config", None)
|
||||
if raw is None:
|
||||
raw = getattr(getattr(model_config, "hf_config", None), "voxcpm2_runtime_config", None)
|
||||
if raw is None:
|
||||
return cls()
|
||||
if hasattr(raw, "to_dict"):
|
||||
raw = raw.to_dict()
|
||||
elif not isinstance(raw, dict) and hasattr(raw, "__dict__"):
|
||||
raw = vars(raw)
|
||||
if not isinstance(raw, dict):
|
||||
logger.warning("Ignoring invalid voxcpm2_runtime_config=%r; expected a dict.", raw)
|
||||
return cls()
|
||||
|
||||
fields = {field.name: field for field in dataclasses.fields(cls)}
|
||||
values: dict[str, Any] = {}
|
||||
for key, value in raw.items():
|
||||
if key not in fields:
|
||||
logger.warning("Ignoring unknown VoxCPM2 runtime config key: %s", key)
|
||||
continue
|
||||
default = getattr(cls(), key)
|
||||
values[key] = cls._coerce_value(key, value, default)
|
||||
return cls(**values)._normalized()
|
||||
|
||||
def _normalized(self) -> _VoxCPM2RuntimeConfig:
|
||||
cfg = self
|
||||
if cfg.enable_batched_cfm and cfg.enable_cfm_cuda_graph:
|
||||
logger.warning(
|
||||
"VoxCPM2 batched CFM and CFM CUDA Graph are mutually exclusive; "
|
||||
"disabling CFM CUDA Graph and keeping batched CFM."
|
||||
)
|
||||
cfg = dataclasses.replace(cfg, enable_cfm_cuda_graph=False)
|
||||
if cfg.enable_cfm_prealloc_output and not cfg.enable_cfm_cuda_graph:
|
||||
logger.warning("VoxCPM2 CFM preallocated output requires CFM CUDA Graph; disabling it.")
|
||||
cfg = dataclasses.replace(cfg, enable_cfm_prealloc_output=False)
|
||||
if cfg.delayed_audio_copy_use_events and not cfg.enable_delayed_audio_copy:
|
||||
logger.warning("VoxCPM2 delayed audio copy events require delayed audio copy; disabling event polling.")
|
||||
cfg = dataclasses.replace(cfg, delayed_audio_copy_use_events=False)
|
||||
if cfg.enable_batched_vae_decode and (
|
||||
cfg.enable_delayed_audio_copy or cfg.audio_emit_every > 1 or cfg.enable_vae_cuda_graph
|
||||
):
|
||||
logger.warning(
|
||||
"VoxCPM2 batched VAE decode is incompatible with delayed audio copy, "
|
||||
"audio_emit_every > 1, and VAE CUDA Graph; disabling batched VAE decode."
|
||||
)
|
||||
cfg = dataclasses.replace(cfg, enable_batched_vae_decode=False)
|
||||
if cfg.enable_unified_decode_graph:
|
||||
if cfg.enable_cfm_cuda_graph:
|
||||
logger.info("VoxCPM2 unified decode graph supersedes independent CFM CUDA Graph; disabling it.")
|
||||
cfg = dataclasses.replace(cfg, enable_cfm_cuda_graph=False, enable_cfm_prealloc_output=False)
|
||||
if not cfg.enable_batched_cfm:
|
||||
logger.info("VoxCPM2 unified decode graph requires batched CFM; enabling it.")
|
||||
cfg = dataclasses.replace(cfg, enable_batched_cfm=True)
|
||||
return cfg
|
||||
|
||||
def unified_decode_graph_available(self, *, use_cuda_graph: bool) -> bool:
|
||||
return bool(use_cuda_graph and self.enable_unified_decode_graph and not self.deterministic_cfm_noise)
|
||||
|
||||
@staticmethod
|
||||
def _coerce_value(key: str, value: Any, default: Any) -> Any:
|
||||
if isinstance(default, bool):
|
||||
if isinstance(value, str):
|
||||
return value.strip().lower() in ("1", "true", "yes", "on")
|
||||
return bool(value)
|
||||
if isinstance(default, int) and not isinstance(default, bool):
|
||||
value = int(value)
|
||||
if key in {"audio_emit_every", "vae_decode_every", "batched_fsq_fusion_max_batch"}:
|
||||
return max(1, value)
|
||||
return value
|
||||
if isinstance(default, float):
|
||||
if key == "cfg_cutoff_ratio":
|
||||
return min(1.0, max(0.0, float(value)))
|
||||
return float(value)
|
||||
if isinstance(default, str):
|
||||
return str(value)
|
||||
return value
|
||||
@@ -6,9 +6,6 @@ from __future__ import annotations
|
||||
from vllm.v1.request import RequestStatus
|
||||
|
||||
from vllm_omni.core.sched.omni_ar_scheduler import OmniARAsyncScheduler
|
||||
from vllm_omni.platforms import current_omni_platform
|
||||
|
||||
from .runtime_config import _VoxCPM2RuntimeConfig
|
||||
|
||||
|
||||
class VoxCPM2OmniARAsyncScheduler(OmniARAsyncScheduler):
|
||||
@@ -22,8 +19,11 @@ class VoxCPM2OmniARAsyncScheduler(OmniARAsyncScheduler):
|
||||
"""
|
||||
|
||||
def _unified_decode_graph_enabled(self) -> bool:
|
||||
runtime_config = _VoxCPM2RuntimeConfig.from_vllm_config(self.vllm_config)
|
||||
return runtime_config.unified_decode_graph_available(use_cuda_graph=current_omni_platform.is_cuda())
|
||||
hf_config = getattr(self.vllm_config.model_config, "hf_config", None)
|
||||
runtime_config = getattr(hf_config, "voxcpm2_runtime_config", None)
|
||||
if isinstance(runtime_config, dict):
|
||||
return bool(runtime_config.get("enable_unified_decode_graph", False))
|
||||
return bool(getattr(runtime_config, "enable_unified_decode_graph", False))
|
||||
|
||||
def _should_defer_waiting_for_unified_decode_graph(self) -> bool:
|
||||
if not self._unified_decode_graph_enabled():
|
||||
|
||||
@@ -46,7 +46,6 @@ from vllm_omni.utils.speaker_cache import (
|
||||
from vllm_omni.worker.runner_assisted_metadata import RunnerAssistedFullAttentionMetadataRequest
|
||||
|
||||
from .minicpm4_paged import MiniCPM4PagedForVoxCPM2, MiniCPM4PagedResidualLM
|
||||
from .runtime_config import _VoxCPM2RuntimeConfig
|
||||
from .voxcpm2_import_utils import import_voxcpm2_core
|
||||
|
||||
logger = init_logger(__name__)
|
||||
@@ -105,6 +104,115 @@ class _DecodeResidualMeta(NamedTuple):
|
||||
new_lm_hidden: torch.Tensor
|
||||
|
||||
|
||||
@dataclasses.dataclass(frozen=True)
|
||||
class _VoxCPM2RuntimeConfig:
|
||||
enable_profiling: bool = False
|
||||
enable_nvtx_profile: bool = False
|
||||
enable_loc_dit_layer_nvtx: bool = False
|
||||
enable_loc_dit_fused_qkv: bool = True
|
||||
enable_loc_dit_fused_mlp: bool = True
|
||||
enable_loc_dit_zero_dt_cache: bool = True
|
||||
enable_loc_dit_fast_rope: bool = False
|
||||
enable_loc_dit_skip_qkv_contig: bool = True
|
||||
enable_loc_dit_reduce_overhead_no_cg: bool = False
|
||||
enable_loc_dit_fullgraph_no_cg: bool = False
|
||||
cfg_cutoff_ratio: float = 1.0
|
||||
decode_graph_capture_policy: str = "all"
|
||||
enable_vae_cuda_graph: bool = False
|
||||
enable_cfm_cuda_graph: bool = False
|
||||
enable_cfm_prealloc_output: bool = False
|
||||
enable_batched_cfm: bool = True
|
||||
deterministic_cfm_noise: bool = False
|
||||
deterministic_cfm_seed: int = 20260601
|
||||
audio_emit_every: int = 1
|
||||
vae_decode_every: int = 3
|
||||
enable_delayed_audio_copy: bool = False
|
||||
delayed_audio_copy_use_events: bool = False
|
||||
coalesce_audio_d2h: bool = True
|
||||
enable_batched_vae_decode: bool = True
|
||||
enable_batched_fsq_fusion: bool = False
|
||||
batched_fsq_fusion_max_batch: int = 32
|
||||
enable_batched_prefill_tail: bool = False
|
||||
enable_unified_decode_graph: bool = True
|
||||
unified_decode_graph_max_batch_size: int = 64
|
||||
|
||||
@classmethod
|
||||
def from_vllm_config(cls, vllm_config: VllmConfig) -> _VoxCPM2RuntimeConfig:
|
||||
model_config = vllm_config.model_config
|
||||
raw = getattr(model_config, "voxcpm2_runtime_config", None)
|
||||
if raw is None:
|
||||
raw = getattr(getattr(model_config, "hf_config", None), "voxcpm2_runtime_config", None)
|
||||
if raw is None:
|
||||
return cls()
|
||||
if hasattr(raw, "to_dict"):
|
||||
raw = raw.to_dict()
|
||||
elif not isinstance(raw, dict) and hasattr(raw, "__dict__"):
|
||||
raw = vars(raw)
|
||||
if not isinstance(raw, dict):
|
||||
logger.warning("Ignoring invalid voxcpm2_runtime_config=%r; expected a dict.", raw)
|
||||
return cls()
|
||||
|
||||
fields = {field.name: field for field in dataclasses.fields(cls)}
|
||||
values: dict[str, Any] = {}
|
||||
for key, value in raw.items():
|
||||
if key not in fields:
|
||||
logger.warning("Ignoring unknown VoxCPM2 runtime config key: %s", key)
|
||||
continue
|
||||
default = getattr(cls(), key)
|
||||
values[key] = cls._coerce_value(key, value, default)
|
||||
return cls(**values)._normalized()
|
||||
|
||||
def _normalized(self) -> _VoxCPM2RuntimeConfig:
|
||||
cfg = self
|
||||
if cfg.enable_batched_cfm and cfg.enable_cfm_cuda_graph:
|
||||
logger.warning(
|
||||
"VoxCPM2 batched CFM and CFM CUDA Graph are mutually exclusive; "
|
||||
"disabling CFM CUDA Graph and keeping batched CFM."
|
||||
)
|
||||
cfg = dataclasses.replace(cfg, enable_cfm_cuda_graph=False)
|
||||
if cfg.enable_cfm_prealloc_output and not cfg.enable_cfm_cuda_graph:
|
||||
logger.warning("VoxCPM2 CFM preallocated output requires CFM CUDA Graph; disabling it.")
|
||||
cfg = dataclasses.replace(cfg, enable_cfm_prealloc_output=False)
|
||||
if cfg.delayed_audio_copy_use_events and not cfg.enable_delayed_audio_copy:
|
||||
logger.warning("VoxCPM2 delayed audio copy events require delayed audio copy; disabling event polling.")
|
||||
cfg = dataclasses.replace(cfg, delayed_audio_copy_use_events=False)
|
||||
if cfg.enable_batched_vae_decode and (
|
||||
cfg.enable_delayed_audio_copy or cfg.audio_emit_every > 1 or cfg.enable_vae_cuda_graph
|
||||
):
|
||||
logger.warning(
|
||||
"VoxCPM2 batched VAE decode is incompatible with delayed audio copy, "
|
||||
"audio_emit_every > 1, and VAE CUDA Graph; disabling batched VAE decode."
|
||||
)
|
||||
cfg = dataclasses.replace(cfg, enable_batched_vae_decode=False)
|
||||
if cfg.enable_unified_decode_graph:
|
||||
if cfg.enable_cfm_cuda_graph:
|
||||
logger.info("VoxCPM2 unified decode graph supersedes independent CFM CUDA Graph; disabling it.")
|
||||
cfg = dataclasses.replace(cfg, enable_cfm_cuda_graph=False, enable_cfm_prealloc_output=False)
|
||||
if not cfg.enable_batched_cfm:
|
||||
logger.info("VoxCPM2 unified decode graph requires batched CFM; enabling it.")
|
||||
cfg = dataclasses.replace(cfg, enable_batched_cfm=True)
|
||||
return cfg
|
||||
|
||||
@staticmethod
|
||||
def _coerce_value(key: str, value: Any, default: Any) -> Any:
|
||||
if isinstance(default, bool):
|
||||
if isinstance(value, str):
|
||||
return value.strip().lower() in ("1", "true", "yes", "on")
|
||||
return bool(value)
|
||||
if isinstance(default, int) and not isinstance(default, bool):
|
||||
value = int(value)
|
||||
if key in {"audio_emit_every", "vae_decode_every", "batched_fsq_fusion_max_batch"}:
|
||||
return max(1, value)
|
||||
return value
|
||||
if isinstance(default, float):
|
||||
if key == "cfg_cutoff_ratio":
|
||||
return min(1.0, max(0.0, float(value)))
|
||||
return float(value)
|
||||
if isinstance(default, str):
|
||||
return str(value)
|
||||
return value
|
||||
|
||||
|
||||
def is_cjk_char(c: str) -> bool:
|
||||
"""Check if a character is a CJK ideograph."""
|
||||
cp = ord(c)
|
||||
@@ -920,8 +1028,8 @@ class VoxCPM2TalkerForConditionalGeneration(nn.Module):
|
||||
self._cuda_graph_warmup_steps = 0
|
||||
self._cuda_graph_warmup_threshold = 3
|
||||
self._unified_graphs: dict[int, _CapturedUnifiedDecodeGraph] = {}
|
||||
self._enable_unified_decode_graph = self._runtime_config.unified_decode_graph_available(
|
||||
use_cuda_graph=use_cuda_graph
|
||||
self._enable_unified_decode_graph = (
|
||||
use_cuda_graph and self._runtime_config.enable_unified_decode_graph and not self._deterministic_cfm_noise
|
||||
)
|
||||
self._unified_decode_graph_max_batch_size = self._runtime_config.unified_decode_graph_max_batch_size
|
||||
self._unified_graph_bucket_sizes: frozenset[int] = self._build_unified_graph_bucket_sizes(
|
||||
|
||||
Reference in new issue
Block a user