Skip to content

提案:为 Twinkle 新增 TTS 训练支持(多码本 Preprocessor + Loss) #279

Open

Description

@Wallbreazzz

背景

Twinkle 现在支持文本 LLM 和多模态,但没有 TTS 训练支持(cookbook 里没 TTS 示例,模型支持表也没列 TTS 变体)。我想给它加上 TTS 的 LoRA SFT 能力,先发个方案对一下,如果没问题我会按工作项实现并提交PR。

目标

让 Twinkle 能跑这两类 TTS 模型的 LoRA SFT:

  1. 多码本 AR-LM(如 Qwen3-TTS-12Hz-1.7B-Base):输入"文本+参考音频",输出"目标音频的多码本 token"
  2. 非 AR 局部 Transformer(如 MOSS-TTS-Local-Transformer-v1.5)

两类架构不同,但 LoRA 都挂在 q/k/v 这些线性层,组件能复用。

设计

仿 cookbook/mm/fsdp2.py 里 LatexOCRProcessor 的范式(自定义 Preprocessor 子类 + Trajectory/Message),加两个组件:

TTSMultiCodebookProcessor(Preprocessor 子类)

把 manifest 里的多码本 audio_codes 组织成训练样本:

  • 文本 + 参考音频部分:label 置 -100(不学)
  • 目标音频部分:保留多码本 label(学)
  • 输出形如 Trajectory(messages=[Message(role='user', content=text, audio=ref_codes), Message(role='assistant', audio_codes=target_codes)])

TTSMultiCodebookLoss(Loss 子类)

多码本 next-token 交叉熵:每个位置对每个码本算 CE 再求和,只在 label != -100 的位置算。多码本 loss 的写法参考 OpenMOSS 官方 MOSS-TTS 仓库 community/norwegian-lora/train_lora.py。

工作项拆解

  • W1 调研多码本 token 在序列里怎么组织(多头输出 / flatten / 残差量化),看 Qwen3-TTS 官方 tokenizer 代码确认。这决定 Preprocessor 的 encode 逻辑。
  • W2 设计 TTSMultiCodebookProcessor 接口:仿 LatexOCRProcessor,定 preprocess(row) -> Trajectory 的字段(Message 要不要加 audio_codes 字段、参考音频怎么放)。
  • W3 实现 TTSMultiCodebookProcessor + 单测:用极小 manifest 跑通 encode,断言 input_ids/labels 的 shape 和 -100 位置正确。
  • W4 设计+实现 TTSMultiCodebookLoss:多码本 CE,仿现成 causal_lm 的接口风格,加 task='multi_codebook_lm'。
  • W5 加 cookbook 示例 cookbook/tts/qwen3_tts_lora.py:单卡 + LoRA + bf16,仿 cookbook/transformers/fsdp2.py 结构。
  • W6 MOSS-TTS-Local-Transformer 适配:非 AR 局部 Transformer 训练格式不同,可能要再写个 Preprocessor 变体(W1-W5 跑通后再碰)。
  • W7 文档:README 教程表加 TTS 行、docs 加一节"TTS 训练"。

不在范围内

  • vocoder / codec 本身训练(冻结用官方训好的)
  • 全量 SFT(先做 LoRA,全量以后再说)

想确认的几点

  1. Message 类要不要扩展支持 audio_codes 字段?还是复用现成的 images 之类?
  2. 多码本 loss 是写个新 Loss 类,还是给现成 CE 加个 multi-codebook 模式?
  3. task='multi_codebook_lm' 这个 task 名合不合适?要不要走现成 task 机制?
  4. cookbook 放 cookbook/tts/ 还是 cookbook/transformers/ 下?

硬件

我在昇腾 NPU 单卡上做(bf16 LoRA),但组件本身不绑死硬件,CUDA 也能跑。

Activity

  1. Wallbreazzz commented on Aug 31, 2026

    @Wallbreazzz
    Author

    cc @tastelikefeet @tpx818 could u please review this plan, thx

  2. tastelikefeet commented on Aug 31, 2026

    @tastelikefeet
    Collaborator

    感谢你的代码计划!
    先回复你的 plan
    首先这个实现大致是合理的,有几个点需要注意:

    1. TTSMultiCodebookProcessor:预处理一般与数据集相关,定义的这个数据集可以类似于一个基类,可以让所有类似数据集继承复用
    2. Trajectory 结构中有 user_data 字段,可以将其他字段放在其中
    3. 可以是一个新 loss
    4. 目前的 task 的定义是针对模型结构有修改(例如 embedding、reranker),因此需要额外的 task 提示 forward 的时候进行处理,因此如果只是 loss 不同,可以复用现有 task
    5. cookbook位置这个命题相对随意
    6. 注意多 lora 部分是否可以兼容,毕竟 twinkle 是支持 c/s 模式的
      其次说一下其他相关的问题:
      swift 目前在和 twinkle 进行底层架构融合,可能对你的 plan 有所影响。但我们仍然欢迎你将自己的计划贡献进来,因此就有两个模式:
    7. 等待我们的重构完成(约 9 月末稳定),然后基于我们的代码继续提升
    8. 先行合入 twinkle,我们会基于你的代码和我们的已有代码组合,形成更完善和鲁棒的代码版本

    再次感谢你的 plan!如果代码完成,直接提交 PR 即可。

  3. Wallbreazzz commented on Aug 31, 2026

    @Wallbreazzz
    Author

    感谢 review!确认理解以下几点:

    1. audio_codes 放 Trajectory.user_data(不改 Message),Processor 做成基类让类似 TTS 数据集继承复用
    2. 写新的 TTSMultiCodebookLoss 类
    3. 复用现有 task(causal_lm),不新增 task,loss 差异在 Loss 层处理
    4. cookbook 放 cookbook/tts/

    另外会注意多 LoRA 兼容(c/s 模式下 Processor/Loss 不写死 adapter_name)。

    时机选择:模式2 先行合入,9 月末 swift 融合如有适配再调整。预计近期提 PR。

  4. Wallbreazzz commented on Oct 28, 2026

    @Wallbreazzz
    Author

    方案更新(2026-10-28)

    感谢前面的建议。实际实现和验证后,当前贡献范围收敛为 Qwen3-TTS-12Hz-1.7B-Base 的单昇腾 NPU、bf16、LoRA cookbook,以本条更新为准;原提案中的通用 TTS 抽象和 MOSS 适配不再作为本批交付承诺。

    相对原方案的调整

    • 不扩展 Message,不新增全局 task,也暂不引入通用 TTSMultiCodebookProcessor 基类。当前 cookbook 直接组织显式张量批次,由专用 InputProcessor 与模型桥接处理;没有采用之前设想的 Trajectory.user_data 数据路径。先验证单模型闭环,再根据复用需求讨论通用接口。
    • Qwen3-TTS 的两个预测分支分别处理:Talker 沿时间轴使用其内部 causal shift;残差 Code Predictor 的 logits 对应码本1–15,采用同位CE,不再沿码本轴做一次shift。总损失为Talker loss + 0.3×残差码本loss。此选择有对齐及末头梯度测试,不推断官方预训练权重的训练方式或音质收益。
    • 复用 Twinkle 的训练、优化器及adapter能力,模型桥接留在 cookbook;不修改框架默认依赖。当前有内部optimizer-group/wrapping接口依赖,已在文档中明确,欢迎就集成边界提出建议。
    • 目录为 cookbook/qwen3_tts/。数据准备保留显式train/dev划分、参考来源及内容指纹;支持微批次累积、尾窗口和完整更新边界上的保存/跨进程恢复。dev不参与训练,不把准备了dev manifest描述成已完成质量评估。
    • 验证范围限定为local模式、单卡、一个活动LoRA。此前提到的CUDA、MOSS、多LoRA并发及c/s模式均未完成验证,本批不宣称支持;尤其不会把沿用adapter接口等同于多租户兼容验收。

    按依赖顺序贡献

    1. 数据、音频特征、前向与损失契约:草稿 PR Add Qwen3-TTS data and forward/loss contracts (1/5) #350(替代已关闭的大草稿 Add single-NPU Qwen3-TTS LoRA training cookbook #349)。
    2. Twinkle模型接入及最小LoRA更新/保存重载。
    3. 梯度累积、更新边界checkpoint与恢复。
    4. manifest、离线预编码和训练CLI。

    每层包含对应测试与文档,后续PR在前置PR合入后依次提交,并根据review调整。生成/评估工具作为后续独立贡献;EOS干预仍为实验,不作为默认策略或普遍质量修复。

    当前证据与剩余边界

    • 完整训练集成版本在真实1.7B Base / Ascend 910B上通过40项测试,覆盖参数更新、冻结范围、保存重载和跨进程续训。
    • 拆分后四个累计层分别执行10/17/23/37项CPU检查,每层2项官方包检查在隔离模式下跳过。最终四层Git tree与已验收集成版本完全相同;不声称每个中间层独立跑过NPU。
    • 默认采样生成与评分回读另有21项远端验证,12份底模/adapter输出与先前已试听版本的PCM完全一致。仅说明流程及输出复现,不证明微调后音色更接近目标。
    • 正式数据训练收敛、长时间稳定性及系统性的内容/音色质量评估尚未完成;本批定位为有验证依据的参考实现。

    本条更新不表示RFC已经全部实现,也不请求关闭本issue。后续仍在这里跟踪各层贡献及尚未覆盖的能力。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions