本项目包含 MOSS-TTS-Nano 文本转语音模型在华为昇腾 NPU (Ascend 910B4) 上的适配分析、运行指南及验证报告。
| 路径 | 状态 | 说明 |
|---|---|---|
| PyTorch 原生版 + torch_npu | ✅ 支持 | 已端到端验证通过,推荐此路径 |
| ONNX 版 + CANN EP | ❌ 不支持 | CANN 8.5.1 缺少 LayerNorm/Gelu 等算子 |
| ONNX 版 + CPU EP | ⚠️ 可用 | 功能正常,但无法利用 NPU |
| vLLM-Ascend | ❌ 不支持 | TTS 模型不在 vLLM 支持范围内 |
/tmp/MOSS-TTS-Nano/
├── README.md # 本文件
├── MOSS-TTS-Nano-100M-ONNX-Ascend-适配报告.md # 完整技术分析报告
│ └── ONNX 失败根因分析 + PyTorch 成功验证细节
├── MOSS-TTS-Nano-100M-ONNX-Runbook.md # 运行指南
│ └── ONNX CPU EP 用法 + PyTorch NPU 用法
├── test_moss_tts_nano_npu_end2end.py # 端到端功能验证脚本
│ └── TTS Prefill → Decode → Audio Encode → Decode
├── test_torch_npu.py # 基础 PyTorch NPU 功能测试
├── test_torch_npu_full.py # 完整 PyTorch NPU 测试
│ └── 含 TTS generate 与 Audio Tokenizer 独立测试
├── verify_cann_ep.py # ONNX CANN EP 验证脚本
│ └── 验证 8 个子图在 CANN/CPU 上的加载情况
├── verify_moss_tts_nano.py # verify-agent 综合验证脚本
│ └── 部署验证 + 精度对比(NPU vs CPU) + 性能基准
├── validation_report.json # 结构化 JSON 验证报告
└── validation_report.md # 可视化 Markdown 验证报告python -c "
from modelscope import snapshot_download
snapshot_download('openmoss/MOSS-TTS-Nano', cache_dir='./models')
snapshot_download('openmoss/MOSS-Audio-Tokenizer-Nano', cache_dir='./models')
"python test_moss_tts_nano_npu_end2end.pypython verify_moss_tts_nano.py| 组件 | 参数量 | 状态 |
|---|---|---|
TTS 模型 (MossTTSNanoForCausalLM) | 117.3M | ✅ NPU 加载成功 |
Audio Tokenizer (MossAudioTokenizerModel) | 22.0M | ✅ NPU 加载成功 |
| 测试项 | MSE | MaxDiff | 结论 |
|---|---|---|---|
| TTS Prefill | 3.08e-11 | 2.36e-05 | 浮点误差极小 |
| TTS Decode Step | 3.16e-11 | 2.03e-05 | 浮点误差极小 |
| Audio Encode | 0 (100% 匹配) | 0 | 整型输出完全一致 |
| Audio Decode | 8.47e-07 | 5.22e-03 | 相对误差 ~2.9% |
精度结论: NPU 与 CPU 输出差异在可接受范围内,精度验证通过。
| 测试项 | P50 (ms) | P90 (ms) | Mean (ms) |
|---|---|---|---|
| TTS Prefill | 36.3 | 37.3 | 36.5 |
| TTS Decode Step | 36.6 | 36.8 | 36.6 |
| Audio Encode | 52.9 | 53.1 | 52.8 |
| Audio Decode | 34.1 | 34.4 | 34.1 |
Attention 实现切换: 必须将默认的 flash_attention_2 改为 sdpa 或 eager
model = AutoModelForCausalLM.from_pretrained(
"openmoss/MOSS-TTS-Nano",
trust_remote_code=True,
attn_implementation="sdpa",
).to("npu")Audio Tokenizer padding_mask: encode/decode 必须显式传入 padding_mask,否则 NPU 上会报 0-dim tensor 索引错误
padding_mask = torch.ones((1, 48000), dtype=torch.long, device="npu")
enc_out = codec_model.encode(waveform, padding_mask=padding_mask)openmoss/MOSS-TTS-Nano, openmoss/MOSS-Audio-Tokenizer-NanoOpenMOSS-Team/MOSS-TTS-Nano