Visitar URL original
fix: lazily import onnxruntime for the 25Hz tokenizer by Destination2020 · Pull Request #356 · QwenLM/Qwen3-TTS · GitHub
Skip to content

fix: lazily import onnxruntime for the 25Hz tokenizer - #356

Open
Destination2020 wants to merge 1 commit into
QwenLM:mainfrom
Destination2020:fix/lazy-load-onnxruntime
Open

Destination2020 wants to merge 1 commit into
QwenLM:mainfrom
Destination2020:fix/lazy-load-onnxruntime

Conversation

@Destination2020

Copy link
Copy Markdown

Summary

  • Move the onnxruntime import from module scope into XVectorExtractor.__init__.
  • Preserve TokenizerV1/25Hz support and the existing ONNX Runtime dependency.
  • Add regression coverage for both the 12Hz import path and the 25Hz on-demand path.

Problem

qwen_tts imports both tokenizer implementations. Consequently, importing Qwen3-TTS for a released 12Hz model also imports tokenizer_25hz/vq/speech_vq.py and loads the ONNX Runtime native library, even though the 12Hz tokenizer never uses it.

On an affected Ray/SGLang worker, the following initialization order reproduced the failure:

import faulthandler
import sys

import qwen_tts
assert "onnxruntime" in sys.modules  # before this change
faulthandler.enable()

The last call raised:

OSError: [Errno 12] Cannot allocate memory

Ray workers hit the same error in ray._private.worker.connect() at faulthandler.enable(all_threads=False), then failed to register with the raylet. This later surfaced as secondary Ray connection/worker errors.

Observed environment:

  • Python 3.12.3
  • qwen-tts 0.1.1
  • onnxruntime 1.28.0
  • Ray 2.55.1 / SGLang 0.5.16
  • Intel Xeon Platinum 8480+ (Sapphire Rapids with AMX enabled)
  • Linux 5.10 vendor kernel

This change is intentionally not gated on a Linux kernel version. Whether the native initialization conflict is observable depends on CPU features, Python and ONNX Runtime builds, and initialization order; < 5.14 is therefore not a reliable applicability boundary. Avoiding an unused native import benefits every 12Hz import path.

The underlying alternate-signal-stack/AMX class of issue is discussed in python/cpython#91124 and python/cpython#31789. This PR does not claim to fix that platform-level issue; it prevents the 12Hz path from loading a native runtime it does not need.

Unlike #109, this keeps TokenizerV1/25Hz available. When XVectorExtractor is actually initialized, it imports and uses ONNX Runtime exactly as before.

Validation

python tests/test_lazy_onnxruntime.py -v
Ran 2 tests in 12.751s
OK

The tests verify that:

  1. Importing Qwen3TTSTokenizer and Qwen3TTSTokenizerV2Model does not load onnxruntime.
  2. Initializing the 25Hz XVectorExtractor loads ONNX Runtime on demand and creates the CPU inference session.

Additional validation on the affected host:

  • import qwen_tts; faulthandler.enable() succeeds with ONNX Runtime still unloaded.
  • A Qwen3-TTS-12Hz-1.7B-CustomVoice OmniFlow/Ray/SGLang smoke benchmark completed 1/1 request successfully.

ONNX Runtime is only needed by the CAMPPlus x-vector extractor, but the module-level import loads its native runtime for 12Hz users as well. Import it when XVectorExtractor is initialized and cover both the 12Hz import path and the 25Hz on-demand path.
Copilot AI lite review requested due to automatic review settings August 11, 2026 08:04

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants