Skip to content

[Bug] Continuation + Clone sometimes repeats the reference transcript instead of the target text on MOSS-TTS-v1.5 #156

@hewkick

Description

@hewkick

我在测试 MOSS-TTS v1.5 的日语 Continuation + Clone 模式时,遇到了一个与文本控制相关的问题。

在使用 Continuation + Clone 模式时,模型有时不会生成我提供的目标文本,而是直接复读参考音频中的文本,或者使用参考文本中的部分内容替换目标文本。不过,在单独使用 Clone 模式时,我没有观察到这个问题。

我理解 Continuation 模式本身会把 prefix audio 以及对应的文本作为上下文,因此它可能更偏向“续写”而不是普通的短句音色克隆。

想问下,Continuation + Clone 模式是否本来就不太适合“参考音频内容和目标文本没有上下文关系,只想进行短句音色克隆”的场景?

感谢你们的回答!也期待看到 MOSS-TTS 之后更优秀的版本。


举例

以下是一个例子。

参考文本和参考音频的内容是:

ずっとあなたの耳元で囁いてきたんです。やっと思い出してくれた。

目标文本是:

私は人の世の各地へと溶け込んで、魔女因子を振りまいてきました。

在 Continuation + Clone 模式下,我有时会观察到以下几类输出错误:

  1. 直接复读参考文本,或复读参考文本的一部分。
    例如,最终输出类似于:

    ずっとあなたの耳元で囁いてきたんです
    
  2. 使用参考文本中的词替换目标文本中的词。
    例如,参考文本中的 あなた 可能会替换目标文本开头的 私は,最终输出类似于:

    あなた人の世の各地へと溶け込んで……
    
  3. 先生成一部分参考文本,然后才开始生成目标文本。
    例如,最终输出类似于:

    ずっとあなたの耳元で囁いて私は人の世の各地へと溶け込んで、魔女因子を振りまいてきました。
    

使用代码

from pathlib import Path
import importlib.util
import torch
import torchaudio
from transformers import AutoModel, AutoProcessor
# Disable the broken cuDNN SDPA backend
torch.backends.cuda.enable_cudnn_sdp(False)
# Keep these enabled as fallbacks
torch.backends.cuda.enable_flash_sdp(True)
torch.backends.cuda.enable_mem_efficient_sdp(True)
torch.backends.cuda.enable_math_sdp(True)


pretrained_model_name_or_path = "moss-tts-v1_5"
device = "cuda" if torch.cuda.is_available() else "cpu"
dtype = torch.bfloat16 if device == "cuda" else torch.float32

def resolve_attn_implementation() -> str:
    # Prefer FlashAttention 2 when package + device conditions are met.
    if (
        device == "cuda"
        and importlib.util.find_spec("flash_attn") is not None
        and dtype in {torch.float16, torch.bfloat16}
    ):
        major, _ = torch.cuda.get_device_capability()
        if major >= 8:
            return "flash_attention_2"

    # CUDA fallback: use PyTorch SDPA kernels.
    if device == "cuda":
        return "sdpa"

    # CPU fallback.
    return "eager"


attn_implementation = resolve_attn_implementation()
print(f"[INFO] Using attn_implementation={attn_implementation}")

processor = AutoProcessor.from_pretrained(
    pretrained_model_name_or_path,
    trust_remote_code=True
)
processor.audio_tokenizer = processor.audio_tokenizer.to(device)

text_2 = "私は人の世の各地へと溶け込んで、魔女因子を振りまいてきました。"
ref_text_2 = "ずっとあなたの耳元で囁いてきたんです。やっと思い出してくれた。"
# Use audio from ./assets/audio to avoid downloading from the cloud.
ref_audio_2 = "test/yuki/ref_audio.ogg"

conversations = [
    # Continuation with voice cloning
    [
        processor.build_user_message(text=ref_text_2 + text_2, reference=[ref_audio_2], language="ja"),
        processor.build_assistant_message(audio_codes_list=[ref_audio_2])
    ],
]

model = AutoModel.from_pretrained(
    pretrained_model_name_or_path,
    trust_remote_code=True,
    attn_implementation=attn_implementation,
    torch_dtype=dtype,
).to(device)
model.eval()

batch_size = 1

save_dir = Path("inference_root")
save_dir.mkdir(exist_ok=True, parents=True)
sample_idx = 0
with torch.no_grad():
    for start in range(0, len(conversations), batch_size):
        batch_conversations = conversations[start : start + batch_size]
        batch = processor(batch_conversations, mode="continuation")
        input_ids = batch["input_ids"].to(device)
        attention_mask = batch["attention_mask"].to(device)

        outputs = model.generate(
            input_ids=input_ids,
            attention_mask=attention_mask,
            max_new_tokens=4096,
        )

        for message in processor.decode(outputs):
            audio = message.audio_codes_list[0]
            out_path = save_dir / f"sample{sample_idx}.wav"
            sample_idx += 1
            torchaudio.save(out_path, audio.unsqueeze(0), processor.model_config.sampling_rate)

谢谢!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions