Skip to content

Inference requires training-only dependencies (pyworld, librosa) due to YAML config referencing dataset.processor #1912

Description

@Iceberg-Yang

Bug 描述

推理(inference)时,AutoModel 加载 CosyVoice-300M-Instruct 模型会因为缺少训练专用依赖 pyworld 而失败,报 ModuleNotFoundError: No module named 'pyworld'。推理代码路径本身不使用 pyworld,但由于推理配置文件 cosyvoice.yaml 引用了 cosyvoice.dataset.processor 模块中的类,导致 HyperPyYAML 在加载配置时触发了不必要的 import 链。

环境信息

  • 模型来源: ModelScope iic/CosyVoice-300M-Instruct(通过 AutoModel(model_dir="iic/CosyVoice-300M-Instruct") 加载)
  • CosyVoice 版本: GitHub main 分支最新代码(clone from https://github.com/FunAudioLLM/CosyVoice)
  • Python 版本: 3.12
  • PyTorch 版本: 2.10.0
  • 运行环境: ModelScope 创空间 xGPU(Linux x86_64, CUDA 12)

复现步骤

  1. 克隆 CosyVoice 仓库:

    git clone --recursive https://github.com/FunAudioLLM/CosyVoice.git
    cd CosyVoice
  2. 仅安装推理必需的依赖(不安装 pyworldlibrosa 等训练专用包):

    pip install torch torchaudio numpy transformers HyperPyYAML onnxruntime-gpu \
      omegaconf einops scipy soundfile inflect regex wetext tqdm tiktoken \
      conformer x-transformers diffusers==0.29.0 lightning
  3. 运行推理加载模型:

    import sys
    sys.path.insert(0, "CosyVoice")
    sys.path.insert(0, "CosyVoice/third_party/Matcha-TTS")
    from cosyvoice.cli.cosyvoice import AutoModel
    cosyvoice = AutoModel(model_dir="iic/CosyVoice-300M-Instruct")
  4. 报错:

    ModuleNotFoundError: No module named 'pyworld'
    

    完整调用链:

    cosyvoice/cli/cosyvoice.py:38  configs = load_hyperpyyaml(f)
    → hyperpyyaml/core.py:471  callable_ = pydoc.locate(callable_string)
    → pydoc.py:488  raise ErrorDuringImport(path, err)
    → cosyvoice/dataset/processor.py:25  import pyworld as pw
    

关于 pyworld 的额外说明

pyworld 是一个 C 扩展包(WORLD 声码器的 Python 封装),安装时需要编译 C 代码。在 Python 3.12 上:

  • 可能因缺少预编译 wheel 而需要从源码编译,存在编译失败风险
  • 编译依赖 Cython 和 numpy C API,增加了环境配置复杂度
  • 对于只需要推理的用户来说,这是一个不必要且较重的依赖

原因分析

cosyvoice.yaml(推理配置文件)中引用了 cosyvoice.dataset.processor 模块中的类路径。当 HyperPyYAML 通过 pydoc.locate() 解析这些类路径时,会触发 cosyvoice.dataset.processor 模块的完整 import。而该模块顶部有:

# cosyvoice/dataset/processor.py
import pyworld as pw      # 仅训练数据预处理需要
import librosa             # 仅训练数据加载需要

这些 import 在推理代码路径中完全不会被调用(推理走的是 cli/cosyvoice.pycli/frontend.pycli/model.pyflow/hifigan/),但因为配置加载机制,它们在模型初始化时就被强制 import 了。

建议修复

方案 A:推理配置与训练配置分离

cosyvoice.yaml 中对 cosyvoice.dataset.processor 类的引用移除或替换为推理专用的实现。推理配置文件不应包含仅在训练/数据预处理阶段使用的模块引用。

方案 B:延迟导入(Lazy Import)

cosyvoice/dataset/processor.py 中将顶层 import 改为函数级延迟导入:

# 改前(顶层 import)
import pyworld as pw
import librosa

# 改后(函数内 import)
def extract_world_features(wav):
    import pyworld as pw
    ...

def load_audio(path):
    import librosa
    ...

这样只有真正调用这些函数时才会触发 import,不影响推理流程。

临时解决方案

目前可通过在 sys.modules 中创建占位模块绕过:

import types
for mod_name in ["pyworld", "librosa"]:
    if mod_name not in sys.modules:
        sys.modules[mod_name] = types.ModuleType(mod_name)

推理功能不受影响,因为 dataset.processor 中的函数在推理路径中不会被调用。

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