Signed-off-by: Sysy <1370724210@qq.com> Co-authored-by: Yueqian Lin <70319226+linyueqian@users.noreply.github.com>
203 lines
5.6 KiB
Python
203 lines
5.6 KiB
Python
# SPDX-License-Identifier: Apache-2.0
|
|
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
|
|
|
|
import importlib.util
|
|
from pathlib import Path
|
|
from types import SimpleNamespace
|
|
|
|
import pytest
|
|
|
|
from vllm_omni.model_executor.models.indextts2 import prompt_utils
|
|
from vllm_omni.model_executor.models.indextts2.tokenizer_v2_5 import (
|
|
INDEXTTS25_TOKENIZER_FILE,
|
|
)
|
|
|
|
pytestmark = [pytest.mark.core_model, pytest.mark.cpu]
|
|
|
|
|
|
def _load_indextts2_offline_example():
|
|
example_path = (
|
|
Path(__file__).resolve().parents[4]
|
|
/ "examples"
|
|
/ "offline_inference"
|
|
/ "text_to_speech"
|
|
/ "indextts2"
|
|
/ "end2end.py"
|
|
)
|
|
spec = importlib.util.spec_from_file_location(
|
|
"indextts2_offline_example_test",
|
|
example_path,
|
|
)
|
|
assert spec is not None and spec.loader is not None
|
|
module = importlib.util.module_from_spec(spec)
|
|
spec.loader.exec_module(module)
|
|
return module
|
|
|
|
|
|
def test_offline_main_uses_resolved_stage0_tokenizer_file(monkeypatch, tmp_path):
|
|
monkeypatch.setenv("VLLM_WORKER_MULTIPROC_METHOD", "spawn")
|
|
example = _load_indextts2_offline_example()
|
|
stage0 = SimpleNamespace(engine_args=SimpleNamespace(hf_overrides={"tokenizer_file": "custom-tokenizer.tiktoken"}))
|
|
fake_omni = SimpleNamespace(
|
|
stage_configs=[stage0],
|
|
generate=lambda *args, **kwargs: [],
|
|
)
|
|
captured = {}
|
|
|
|
monkeypatch.setattr(example, "Omni", lambda **kwargs: fake_omni)
|
|
monkeypatch.setattr(example, "SamplingParams", lambda **kwargs: kwargs)
|
|
monkeypatch.setattr(
|
|
example,
|
|
"build_request",
|
|
lambda **kwargs: captured.update(kwargs) or {"additional_information": {}},
|
|
)
|
|
|
|
example.main(
|
|
SimpleNamespace(
|
|
model="/model",
|
|
model_version="2.5",
|
|
deploy_config="/deploy/custom.yaml",
|
|
use_gpt_latent=False,
|
|
stage_init_timeout=300,
|
|
seed=42,
|
|
output_dir=str(tmp_path),
|
|
text="hello",
|
|
ref_audio=None,
|
|
emo_audio=None,
|
|
emo_text=None,
|
|
emo_vector=None,
|
|
emo_alpha=None,
|
|
use_emo_text=False,
|
|
use_random=False,
|
|
lang="en",
|
|
text_normalization=True,
|
|
)
|
|
)
|
|
|
|
assert captured["tokenizer_file"] == "custom-tokenizer.tiktoken"
|
|
|
|
|
|
def test_indextts25_prompt_len_uses_three_conditioning_tokens(monkeypatch):
|
|
captured = {}
|
|
|
|
def fake_prepare(*args, **kwargs):
|
|
captured.update(kwargs)
|
|
return [11, 12, 13, 14], 0
|
|
|
|
monkeypatch.setattr(
|
|
prompt_utils,
|
|
"prepare_indextts25_text",
|
|
fake_prepare,
|
|
)
|
|
|
|
prompt_len = prompt_utils.estimate_indextts2_prefill_prompt_len(
|
|
"/model",
|
|
"hello",
|
|
model_type="indextts2_5",
|
|
lang="en",
|
|
text_normalization=False,
|
|
)
|
|
|
|
# Official prepare_gpt_inputs wraps the language-prefixed tokenizer IDs
|
|
# with start_text=0 and stop_text=1 before appending start_mel.
|
|
assert prompt_len == 3 + (4 + 2) + 1
|
|
assert captured["text_normalization"] is False
|
|
assert captured["tokenizer_file"] == INDEXTTS25_TOKENIZER_FILE
|
|
|
|
|
|
def test_indextts25_prompt_len_uses_custom_tokenizer_file(monkeypatch):
|
|
captured = {}
|
|
|
|
def fake_prepare(*args, **kwargs):
|
|
captured.update(kwargs)
|
|
return [11, 12], 0
|
|
|
|
monkeypatch.setattr(
|
|
prompt_utils,
|
|
"prepare_indextts25_text",
|
|
fake_prepare,
|
|
)
|
|
|
|
prompt_utils.estimate_indextts2_prefill_prompt_len(
|
|
"/model",
|
|
"hello",
|
|
model_type="indextts2_5",
|
|
tokenizer_file="custom-tokenizer.tiktoken",
|
|
)
|
|
|
|
assert captured["tokenizer_file"] == "custom-tokenizer.tiktoken"
|
|
|
|
|
|
def test_indextts25_prompt_len_filters_existing_text_wrapper_ids(monkeypatch):
|
|
monkeypatch.setattr(
|
|
prompt_utils,
|
|
"prepare_indextts25_text",
|
|
lambda *args, **kwargs: ([0, 58838, 1, 42, 0], 0),
|
|
)
|
|
|
|
prompt_len = prompt_utils.estimate_indextts2_prefill_prompt_len(
|
|
"/model",
|
|
"hello",
|
|
model_type="indextts2_5",
|
|
lang="en",
|
|
)
|
|
|
|
assert prompt_len == 3 + (2 + 2) + 1
|
|
|
|
|
|
def test_indextts2_prompt_len_ignores_v25_tokenizer_file(monkeypatch):
|
|
class FakeTokenizer:
|
|
def encode(self, text, *, add_special_tokens):
|
|
assert text == "hello"
|
|
assert add_special_tokens is False
|
|
return [11, 12]
|
|
|
|
def fail_prepare(*args, **kwargs):
|
|
raise AssertionError("IndexTTS 2 must not use the IndexTTS 2.5 tokenizer")
|
|
|
|
monkeypatch.setattr(
|
|
prompt_utils,
|
|
"_get_text_tokenizer",
|
|
lambda model_id_or_path: FakeTokenizer(),
|
|
)
|
|
monkeypatch.setattr(
|
|
prompt_utils,
|
|
"prepare_indextts25_text",
|
|
fail_prepare,
|
|
)
|
|
|
|
prompt_len = prompt_utils.estimate_indextts2_prefill_prompt_len(
|
|
"/model",
|
|
"hello",
|
|
model_type="indextts2",
|
|
tokenizer_file="custom.tiktoken",
|
|
)
|
|
|
|
assert prompt_len == 34 + (2 + 2) + 1
|
|
|
|
|
|
def test_indextts25_prompt_ids_preserve_placeholder_value(monkeypatch):
|
|
captured = {}
|
|
|
|
def fake_estimate(*args, **kwargs):
|
|
captured.update(kwargs)
|
|
return 10
|
|
|
|
monkeypatch.setattr(
|
|
prompt_utils,
|
|
"estimate_indextts2_prefill_prompt_len",
|
|
fake_estimate,
|
|
)
|
|
|
|
prompt_ids = prompt_utils.build_indextts2_prefill_prompt_ids(
|
|
"/model",
|
|
"hello",
|
|
model_type="indextts2_5",
|
|
lang="en",
|
|
tokenizer_file="custom-tokenizer.tiktoken",
|
|
placeholder_token_id=17,
|
|
)
|
|
|
|
assert prompt_ids == [17] * 10
|
|
assert captured["tokenizer_file"] == "custom-tokenizer.tiktoken"
|