Merge branch 'codex/consolidate-1831' into codex/pr-queue-integration

# Conflicts:
#	CHANGELOG.md
This commit is contained in:
Palash Debnath
2026-09-07 11:16:00 +05:30
9 changed files with 75 additions and 6 deletions
+1
View File
@@ -73,6 +73,7 @@ the frozen-backend fallback mirror it for their toolchains.
- Onboarding recognizes locally saved Hugging Face tokens without contacting Hugging Face, and replacing one requires an explicit click (#1852) — thanks @psiberfunk!
- The logs panel no longer reports “All clear” before log retrieval succeeds or while logs contain warnings or errors (#1870) — thanks @motodriver!
- MOSS accelerator routing now matches runtime device selection, including native XPU and registered NPU detection (#1830) — thanks @li-lizhe!
- Confucius accelerator routing matches device selection, and dots.tts keeps safe CPU precision on non-CUDA accelerators (#1831) — thanks @li-lizhe!
## [0.5.2] — 2026-09-02
+3 -3
View File
@@ -62,9 +62,9 @@ class Confucius4Backend(SubprocessBackend):
# Upstream vocoder rate (config target_sample_rate) — confirmed 22 050 Hz by
# a live run (2026-07-02); still re-read from the sidecar's ready/audio frames.
_DEFAULT_SAMPLE_RATE = 22050
# CUDA fast path + CPU fallback, both exercised (CPU end-to-end validated).
# No MPS claim — upstream has no Metal path.
gpu_compat = ("cuda", "cpu")
# Match device propagation into upstream .to(device). XPU/NPU routing is
# contract-tested, not a claim of physical-hardware synthesis validation.
gpu_compat = ("cuda", "rocm", "xpu", "npu", "cpu")
@classmethod
def is_available(cls) -> tuple[bool, str]:
+5 -2
View File
@@ -104,7 +104,7 @@ def _ensure_clone_on_sys_path() -> None:
def _load_model(stdout):
"""Cold-construct the Confucius4 model (CUDA, else CPU — both validated)."""
"""Cold-construct using an available torch accelerator, with CPU fallback."""
global _model
if _model is not None:
return _model
@@ -115,7 +115,10 @@ def _load_model(stdout):
import torch
from confuciustts.cli.inference import ConfuciusTTS # type: ignore[import-not-found]
device = "cuda" if torch.cuda.is_available() else "cpu"
device = torch.accelerator.current_accelerator(check_available=True)
device = device.type if device is not None else "cpu" # 'cuda', 'npu', 'mps', 'xpu', 'cpu'
if device == "mps":
device = "cpu" # MPS was slower than CPU in the existing validation run
_send(stdout, {"op": "progress", "stage": "loading_model", "percent": 50})
_model = ConfuciusTTS(config_path=_config_path(), device=device)
+2
View File
@@ -115,6 +115,8 @@ def _load_runtime(stdout):
from dots_tts.runtime import DotsTtsRuntime # type: ignore[import-not-found]
repo = os.environ.get("OMNIVOICE_DOTS_TTS_MODEL", _DEFAULT_REPO)
# Match DotsTtsRuntime's own CUDA/CPU selection. Its _check_torch_env
# rejects half precision without CUDA, even when an XPU/NPU is available.
default_precision = "bfloat16" if torch.cuda.is_available() else "float32"
precision = os.environ.get("OMNIVOICE_DOTS_TTS_PRECISION", default_precision)
optimize = os.environ.get("OMNIVOICE_DOTS_TTS_OPTIMIZE", "0") == "1"
+8
View File
@@ -88,3 +88,11 @@ sr = model.sample_rate # 22050
-**Sidecar logic unit-tested** (`tests/test_confucius4_sidecar.py`):
language normalization, tensor→PCM (mono/stereo/clip), config-path
resolution, clone sys.path injection, wire framing, synthesize dispatch.
## Accelerator routing
The sidecar passes a runtime-available CUDA/ROCm, XPU, or registered NPU
through upstream's device-aware model loading. The engine venv needs a matching
PyTorch/vendor runtime. XPU/NPU selection is covered by mocked loader and routing
tests; this change does not certify synthesis on physical XPU/NPU hardware.
MPS keeps the existing CPU fallback described in the validation record above.
+5
View File
@@ -115,3 +115,8 @@ dots.tts runs in a dedicated sidecar venv (it pins `transformers==4.57`,
which conflicts with the parent's `transformers>=5.3`). For why that adds
disk and how uv keeps the cost down, see
[Engine venvs & disk usage](disk-usage.md).
The upstream runtime selects CUDA or CPU internally. Automatic precision follows
that selection: bfloat16 on CUDA, float32 otherwise, including XPU/NPU/MPS hosts
where this runtime executes on CPU. `OMNIVOICE_DOTS_TTS_PRECISION` remains an
explicit override.
+1 -1
View File
@@ -19,7 +19,7 @@ def test_registered_in_lazy_registry():
def test_backend_class_metadata():
from engines.confucius4 import Confucius4Backend
assert Confucius4Backend.id == "confucius4-tts"
assert Confucius4Backend.gpu_compat == ("cuda", "cpu") # CPU validated E2E; no MPS claim
assert Confucius4Backend.gpu_compat == ("cuda", "rocm", "xpu", "npu", "cpu")
assert Confucius4Backend.supports_voice_design is False
+26
View File
@@ -181,3 +181,29 @@ def test_synthesize_calls_generate_and_emits_audio(sc, monkeypatch):
def test_synthesize_rejects_empty_text(sc):
with pytest.raises(ValueError, match="text"):
sc._handle_synthesize({"text": ""}, io.BytesIO())
@pytest.mark.parametrize('family', [None, 'cuda', 'xpu', 'npu', 'mps'])
def test_load_model_matches_routing(sc, monkeypatch, family):
import sys
from types import SimpleNamespace
from unittest.mock import Mock
from core.device_caps import HostCaps
from services.engine_routing import resolve_routing
from engines.confucius4 import Confucius4Backend
accelerator = Mock(return_value=SimpleNamespace(type=family) if family else None)
monkeypatch.setitem(sys.modules, 'torch', SimpleNamespace(
accelerator=SimpleNamespace(current_accelerator=accelerator),
))
constructor = Mock()
monkeypatch.setitem(sys.modules, 'confuciustts.cli.inference', SimpleNamespace(ConfuciusTTS=constructor))
monkeypatch.setattr(sc, '_model', None)
monkeypatch.setattr(sc, '_config_path', lambda: 'fixture.yaml')
monkeypatch.setattr(sc, '_ensure_clone_on_sys_path', lambda: None)
sc._load_model(io.BytesIO())
expected = family if family not in (None, 'mps') else 'cpu'
constructor.assert_called_once_with(config_path='fixture.yaml', device=expected)
accelerator.assert_called_once_with(check_available=True)
caps = HostCaps(family=family or 'cpu', available_families=(family, 'cpu') if family else ('cpu',))
assert resolve_routing(Confucius4Backend.gpu_compat, caps)['effective_device'] == expected
@@ -0,0 +1,24 @@
"""DOTS picks CUDA/CPU internally; another accelerator must not imply bf16."""
import io
import sys
from types import SimpleNamespace
from unittest.mock import Mock
import pytest
@pytest.mark.parametrize('family', [None, 'cuda', 'xpu', 'npu', 'mps'])
def test_precision_matches_runtime_device(monkeypatch, family):
from engines.dots_tts import main
accelerator = Mock(return_value=SimpleNamespace(type=family) if family else None)
monkeypatch.setitem(sys.modules, 'torch', SimpleNamespace(
accelerator=SimpleNamespace(current_accelerator=accelerator),
cuda=SimpleNamespace(is_available=lambda: family == 'cuda'),
))
loader = Mock()
monkeypatch.setitem(sys.modules, 'dots_tts.runtime', SimpleNamespace(DotsTtsRuntime=loader))
monkeypatch.setattr(main, '_runtime', None)
monkeypatch.delenv('OMNIVOICE_DOTS_TTS_PRECISION', raising=False)
main._load_runtime(io.BytesIO())
assert loader.from_pretrained.call_args.kwargs['precision'] == ('bfloat16' if family == 'cuda' else 'float32')