本目录实现 MusicCaps 任务:用 Qwen2.5-Omni Thinker(或调试用的极小 GPT2)先做 SFT,再做 GRPO;GRPO 奖励 = aspect 覆盖 + CLAP 音频–文本对齐。
更偏设计的说明见 MUSICCAPS_PIPELINE.md。
- 下文所有命令默认在
musiccaps_pipeline根目录执行(含configs/、musiccaps/、scripts/的那一层)。 - 使用相对路径时,请保持当前工作目录为该根目录,否则请把配置里的
manifest_path、checkpoint_dir改成绝对路径。
cd /path/to/musiccaps_pipeline
python3 -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -U pip
pip install -r requirements.txt注意事项
- Python 版本:建议 3.10+。
- GPU:正式训练 Omni 需要足够显存的 NVIDIA GPU;CPU 仅适合 mock 或极小规模试验。
- 可选安装:
pip install -e .后可在任意目录执行python -m musiccaps,但仍需通过--config指到本目录下的 yaml,或在该目录设置工作目录。
export PYTHONPATH="$(pwd)"注意事项
- 每次新开终端都要重新执行,或把该行写进你的 shell 配置。
- 若已
pip install -e .且只在包内开发,有时仍可保留PYTHONPATH,避免导入到旧副本。
cp configs/default.yaml configs/local.yaml
# 编辑 configs/local.yaml:至少改 manifest_path、model_id、checkpoint_dir 等注意事项
manifest_path:指向你将要生成或已生成的manifest.jsonl(默认示例为./data/musiccaps_manifest.jsonl)。model_id:与 Hugging Face 上 Omni Thinker 权重一致(如Qwen/Qwen2.5-Omni-3B);显存不够时换更小档或先开 mock。debug_use_mock_model: true:不加载 Omni,改用 tiny GPT2 做流程冒烟(不验证真实音频理解)。lora_r: 0:关闭 LoRA 时,本仓库的 adapter 保存/加载路径(SFT→GRPO)不按 LoRA 场景测试;正式用 Omni 建议lora_r > 0。- Hugging Face 下载(含中国大陆):在
import musiccaps之前未设置HF_ENDPOINT时,包内会默认尝试使用镜像https://hf-mirror.com(见musiccaps/hub_mirrors.py)。若要始终走官方:export HF_ENDPOINT=https://huggingface.co。若不想任何默认镜像:export MUSICCAPS_NO_CN_MIRROR=1。 build_manifest/download_musiccaps_wavs:两脚本在运行时会加入仓库根目录并import musiccaps.hub_mirrors,因此同样会应用上述 Hub 镜像逻辑(与训练一致)。
MusicCaps 在 Hub 上提供 YouTube id + 起止秒 等元数据;本流水线还需要本地 约 10 秒 wav 以及由元数据对齐路径生成的 manifest.jsonl。
文件命名(与 scripts/build_manifest.py 一致)
{ytid}_{start_s}_{end_s}.wav
例如 ytid 为 11 位 id、start_s=30、end_s=40,则文件名为:xxxxxxxxxxx_30_40.wav(以你本地实际 ytid 为准)。
若使用仓库脚本,需在仓库根目录执行,并自备 yt-dlp 与系统 ffmpeg(见 scripts/download_musiccaps_wavs.py 顶部说明):
# 可选:中国大陆访问 Hub
# export HF_ENDPOINT=https://hf-mirror.com
python scripts/download_musiccaps_wavs.py \
--out-dir ./wavs \
--cache-dir ./yt_audio_cache试跑可加 --max-clips 5。若 wav 已由其他合规途径准备好,可跳过本小节,只要命名与上表一致即可。
当你已经下载了部分 YouTube 缓存(./yt_audio_cache)但不想继续下载时,可直接基于缓存切片:
python scripts/slice_musiccaps_from_cache.py \
--out-dir ./wavs \
--cache-dir ./yt_audio_cache \
--workers 8 \
--failures-jsonl ./data/slice_from_cache_failures.jsonl说明:
- 此脚本不会调用 yt-dlp,只会用
ffmpeg从现有缓存切片。 missing cache表示该ytid在本地缓存不存在,会被跳过。- 若缓存文件损坏(如
EBML header parsing failed/moov atom not found),该条会记入失败 jsonl,后续可针对性重下。 --workers只影响切片并行度(M 系列 Mac 可先试8)。
把 Hub 元数据与本地 wav 对齐为训练用清单(除非你改用 examples/mock_manifest.jsonl 等自备 manifest):
# 可选:中国大陆访问 Hub
# export HF_ENDPOINT=https://hf-mirror.com
python scripts/build_manifest.py \
--wav-dir ./wavs \
--out-jsonl ./data/musiccaps_manifest.jsonl \
--require-file关于 export PYTHONPATH="$(pwd)":上述两个脚本都会在内部把仓库根目录加入 sys.path,通常不必为它们单独设置 PYTHONPATH。第 1 步的 PYTHONPATH 仍建议保留,供后续 python -m musiccaps... 使用(未 pip install -e . 时)。
然后在 configs/local.yaml 里把 manifest_path 设为该 musiccaps_manifest.jsonl。
如果你当前只有部分 wav,可先生成一个部分清单用于先行训练,例如:
python scripts/build_manifest.py \
--wav-dir ./wavs \
--out-jsonl ./data/musiccaps_manifest_partial.jsonl \
--require-file再把 configs/local.yaml 的 manifest_path 指向 ./data/musiccaps_manifest_partial.jsonl 即可先开跑。
注意事项
- 注意 版权与平台服务条款;MusicCaps 也有数据许可说明,商用前请自行核对。
- 命名必须与
default_wav_name一致,否则build_manifest --require-file会大量跳过。 --require-file:只写入磁盘上真实存在的 wav,避免训练时才报错;首次对齐数据时强烈建议打开。- 若仍希望训练阶段容错跳过缺失音频,可在配置中设
skip_missing_wavs: true(默认false,即缺失即报错)。 - split 字段:脚本会按 HuggingFace 数据集上的 split 名(如
train/test)以及行内split字段(若有)映射到train/valid/test。训练脚本当前只读split=train,请确认 manifest 里训练集行是train。 - 依赖:需要
datasets且能访问 Hub(或镜像)以下载google/MusicCaps元数据。
export PYTHONPATH="$(pwd)"
python -m musiccaps.train_sft --config configs/default.yaml
# 等价:python -m musiccaps sft --config configs/local.yaml注意事项
- 输出位置:默认在
./checkpoints/sft_lora/(由checkpoint_dir+sft_adapter_name决定)。 - 首次拉 Omni:耗时长、占磁盘大;确保磁盘与网络稳定。
transformers版本:需支持你选的Qwen2_5OmniThinkerForConditionalGeneration与Qwen2_5OmniProcessor;版本过旧会报apply_chat_template或参数错误。- batch:
sft_batch_size默认 1,利于 Omni 多模态调试;调大前需确认显存与 processor 是否支持批处理。 - mock 模式:
debug_use_mock_model: true时不检查 wav 是否存在,仅用文本模板训练 tiny GPT2,用于验证 loss 与保存逻辑。
export PYTHONPATH="$(pwd)"
python -m musiccaps.train_grpo --config configs/local.yaml
# 等价:python -m musiccaps grpo --config configs/local.yaml注意事项
grpo_init_adapter:默认sft_lora,即加载./checkpoints/sft_lora(相对checkpoint_dir)。务必先成功跑完 SFT 且该目录存在,否则会报错。grpo_batch_size必须为 1:当前实现按单条样本做组内采样与奖励,若配置成其他值会直接raise。- CLAP 与显存:会额外加载
laion/larger_clap_music。若 OOM,可在配置里设grpo_clap_device: "cpu"(慢但省 GPU),或暂时reward_weight_clap: 0(仅 aspect + KL)。 - mock + CLAP:
debug_use_mock_model: true时默认不加载 CLAP;若你手动把reward_weight_clap调大,仍需要真实 wav 供 CLAP 读音频,否则请保持reward_weight_clap: 0。 - KL:
beta_kl > 0时使用 PEFT 的disable_adapter()对基座算参考 log prob;非 PEFT 模型则 KL 项为 0。
输出位置:默认 ./checkpoints/grpo_lora/。
- 复制
examples/mock_manifest.jsonl或在其基础上改caption/aspects。 - 在配置中设
debug_use_mock_model: true,manifest_path指向该 jsonl。 reward_weight_clap: 0,避免 CLAP 读盘。- 运行第 4、5 步命令。
注意事项
- 这只能验证 代码路径与梯度,不能代表 Omni 在音乐上的真实效果。
| 目的 | 命令 |
|---|---|
| SFT | python -m musiccaps.train_sft --config configs/local.yaml |
| GRPO | python -m musiccaps.train_grpo --config configs/local.yaml |
| 下载并切 wav | python scripts/download_musiccaps_wavs.py --out-dir ./wavs --cache-dir ./yt_audio_cache |
| 仅从缓存切片 | python scripts/slice_musiccaps_from_cache.py --out-dir ./wavs --cache-dir ./yt_audio_cache --workers 8 |
| 生成 manifest | python scripts/build_manifest.py --wav-dir ./wavs --out-jsonl ./data/musiccaps_manifest.jsonl --require-file |
MusicCaps、Qwen、LAION CLAP 等各有许可证;商用与再分发前请分别阅读并遵守。