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 每次完全相同
目前仅通过了中文的测试,英文仍然存在此问题,我懒得再深究了
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 每次完全相同
目前仅通过了中文的测试,英文仍然存在此问题,我懒得再深究了