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

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions