diff options
Diffstat (limited to 'app/backends/qwen.py')
| -rw-r--r-- | app/backends/qwen.py | 43 |
1 files changed, 25 insertions, 18 deletions
diff --git a/app/backends/qwen.py b/app/backends/qwen.py index 3309c69..b2a1df4 100644 --- a/app/backends/qwen.py +++ b/app/backends/qwen.py @@ -4,8 +4,9 @@ qwen-tts is a pip package providing the ``qwen-tts-demo`` server, which hosts ONE Qwen3-TTS model per process — CustomVoice (built-in speakers), Base (voice cloning) or VoiceDesign (described voice). This module sets it up -end-to-end: pip-install the package into the managed venv. There are no -questions to ask — the port and which model to run live in +end-to-end: pip-install the package into its own managed venv +(``app/envs/qwen`` — the app venv and the faster backend's never receive +it). There are no questions to ask — the port and which model to run live in ``app/converter/config.py`` (the model is chosen per run on the hub's Generate-audiobooks screen), and only one server runs at a time. @@ -46,6 +47,9 @@ from converter.clients import QWEN3_TTS_SPEAKERS from ui import taskview, tui QWEN_PIP_PKG = "qwen-tts" +# The dedicated venv qwen-tts is installed into (never the app env or the +# faster backend's). +QWEN_ENV = envs.QWEN_ENV_DIR DEFAULT_PORT = 7860 # The models a single demo server can host, by config.QWEN_MODEL name. @@ -161,9 +165,9 @@ def delete_model_weights(models: Optional[List[str]] = None) -> int: def _is_installed() -> bool: - if envs.env_script("qwen-tts-demo").is_file(): + if envs.env_script("qwen-tts-demo", QWEN_ENV).is_file(): return True - return envs.module_available("qwen_tts") + return envs.module_available("qwen_tts", QWEN_ENV) def _config_port(url: str, fallback: int) -> int: @@ -218,7 +222,8 @@ def _execute_steps(settings: dict) -> List[taskview.TaskStep]: return steps def install(emit, cancel): - rc = common.pip_install([QWEN_PIP_PKG], emit=emit, cancel=cancel) + rc = common.pip_install([QWEN_PIP_PKG], emit=emit, cancel=cancel, + env_dir=QWEN_ENV) if rc != 0: print(f"[WARNING] pip install failed (exit {rc}); install " f"{QWEN_PIP_PKG} manually") @@ -268,7 +273,7 @@ def _collect_from_flags(args: argparse.Namespace, def build_parser() -> argparse.ArgumentParser: parser = argparse.ArgumentParser( description="Set up the Qwen3-TTS demo backend: pip install " - "qwen-tts into the managed venv.") + "qwen-tts into its managed venv (app/envs/qwen).") parser.add_argument("--skip-install", action="store_true", help="Do not pip install qwen-tts") return parser @@ -279,7 +284,7 @@ def _build_spec(model: str) -> ServerSpec: url = config.QWEN_API_URL return ServerSpec( "qwen", url, - [str(envs.env_script("qwen-tts-demo")), MODEL_REPOS[model], + [str(envs.env_script("qwen-tts-demo", QWEN_ENV)), MODEL_REPOS[model], "--ip", "127.0.0.1", "--port", str(_config_port(url, DEFAULT_PORT))], identity=desired_identity(model)) @@ -363,9 +368,9 @@ def _detect_remote(managed: bool = False): def _hf_download_prefix() -> Optional[List[str]]: - """The venv's hf CLI argv prefix (None when neither script is present).""" + """The qwen env's hf CLI argv prefix (None when neither script is present).""" for name in ("hf", "huggingface-cli"): - candidate = envs.env_script(name) + candidate = envs.env_script(name, QWEN_ENV) if candidate.is_file(): return [str(candidate)] return None @@ -381,7 +386,7 @@ def install_model(model: str, *, emit=None, cancel=None) -> int: """ prefix = _hf_download_prefix() if prefix is None: - print("[ERROR] No hf CLI found in the managed venv; pip install " + print("[ERROR] No hf CLI found in the qwen venv; pip install " f"{QWEN_PIP_PKG} first") return 1 repo = MODEL_REPOS[model] @@ -415,12 +420,14 @@ def uninstall(*, emit=None, cancel=None) -> int: then delete every downloaded model. qwen-tts is a pip package (``qwen_tts`` + the ``qwen-tts-demo`` script) - installed into the managed venv, so uninstalling it removes the backend. - Any server this tool started is stopped first (best-effort). The three - models' weight snapshots — multi-GB directories lazily fetched into the - HuggingFace cache (~/.cache/huggingface/hub) — are deleted too, matching - the hub's confirmation dialog; only those three directories are removed, - never the shared cache itself. + installed into its own managed venv (``app/envs/qwen``, QWEN_ENV), so + uninstalling it removes the backend — the app venv and the faster + backend's env are never touched. Any server this tool started is stopped + first (best-effort). The three models' weight snapshots — multi-GB + directories lazily fetched into the HuggingFace cache + (~/.cache/huggingface/hub) — are deleted too, matching the hub's + confirmation dialog; only those three directories are removed, never the + shared cache itself. With EMIT given (the in-TUI task view) pip runs piped, streaming into EMIT, so its output never touches the terminal behind curses. CANCEL is @@ -436,10 +443,10 @@ def uninstall(*, emit=None, cancel=None) -> int: servers.stop("qwen") if common.cancel_requested(cancel): return 130 - rc = common.pip_uninstall([QWEN_PIP_PKG], emit=emit) + rc = common.pip_uninstall([QWEN_PIP_PKG], emit=emit, env_dir=QWEN_ENV) if rc != 0: print(f"[WARNING] pip uninstall failed (exit {rc}); remove " - f"{QWEN_PIP_PKG} from the managed venv manually") + f"{QWEN_PIP_PKG} from {QWEN_ENV} manually") else: print(f"[OK] {QWEN_PIP_PKG} removed.") # Weights go even when the pip step failed: the package can be |
