Skip to content

如果生成的文本较短(1-2个字符),则会直接返回并朗读ref_wav #58

Description

@RScgwj

Python=3.10.9
使用最新版
V2ProPlus自训练模型
详细bug描述:
生成“你好”时有时候会直接返回ref_wav
并不是我的模型的问题,我使用了整合包,同样存在此问题

以下是我自己尝试并借助AI修复的一个方案:
根本原因
First Stage Decoder 内部含有随机采样逻辑(top-k/top-p sampling),导致相同输入下输出不确定。
具体表现:First Stage Decoder 接收 x 和 prompts 后,内部自回归地生成第一个新 token 并 append 到 y 末尾返回。由于采样有随机性,这个 token 有概率直接采样到 1024(stop token)。一旦如此,后续 Stage Decoder 第1步就会立即触发 stop condition,生成长度为0的 semantic tokens,最终传给 vocoder 的是空 tensor,导致 Conv 层报错崩溃。
这不是输入污染、不是 ONNX Session 状态残留、不是 reset_all() 的问题——所有输入每次完全一致,是模型本身的随机性导致的低概率失败。

解决方案
分两层防御,缺一不可。
第一层:First Stage Decoder 输出检测 + 重试
在进入 Stage Decoder 循环前,检测 y 末尾 token,若为 stop token 则重新运行 First Stage Decoder,利用其随机性期望下一次采样到正常 token:

y, y_emb, *present_key_values = first_stage_decoder.run(
None, {"x": x, "prompts": prompts}
)

for retry in range(5):
if y[0, -1] < 1024:
break
logger.warning(f"[t2s_cpu] First Stage Decoder 输出 stop token,重试 {retry+1}/5")
y, y_emb, *present_key_values = first_stage_decoder.run(
None, {"x": x, "prompts": prompts}
)
else:
logger.error("[t2s_cpu] 多次重试仍输出 stop token,放弃")
return np.zeros((1, 1, 0), dtype=np.int64)

y_for_stage = y[:, :y_emb.shape[1]]

第二层:tts() 层的空 tensor 防御
即使第一层失败兜底,防止空 tensor 传入 vocoder 引发 crash:

if semantic_tokens is None:
return None

eos_indices = np.where(semantic_tokens >= 1024)
if len(eos_indices[0]) > 0:
first_eos_index = eos_indices[-1][0]
semantic_tokens = semantic_tokens[..., :first_eos_index]

if semantic_tokens.shape[-1] == 0:
logger.error("[tts] semantic_tokens 为空,跳过本次推理")
return None

附:排查过程中澄清的误解
最初怀疑实际结论ONNX Session 跨推理状态残留ONNX Runtime 每次 run() 完全独立,无状态reset_all() 污染 ssl_contenthash 完全一致,ssl_content 每次相同y/y_emb 长度不对齐导致错误不对齐是现象,真正原因是采样随机性输入数据跨推理被污染prompts hash 每次完全相同
目前仅通过了中文的测试,英文仍然存在此问题,我懒得再深究了

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions