From d7cdfbc36b4a7dadf451141f9edc8a381d83da7a Mon Sep 17 00:00:00 2001 From: Teknium <127238744+teknium1@users.noreply.github.com> Date: Wed, 2 Sep 2026 16:12:29 -0700 Subject: [PATCH] refactor(stt): openai-availability reason helper, one-line section banners, docstring compaction --- tools/transcription_audio.py | 9 +++---- tools/transcription_cloud.py | 5 ++-- tools/transcription_command.py | 9 +++---- tools/transcription_local.py | 5 ++-- tools/transcription_tools.py | 46 +++++++++++++++------------------- 5 files changed, 30 insertions(+), 44 deletions(-) diff --git a/tools/transcription_audio.py b/tools/transcription_audio.py index 41fcaef36a..07e45a6734 100644 --- a/tools/transcription_audio.py +++ b/tools/transcription_audio.py @@ -4,9 +4,8 @@ Binary discovery, the shared ffmpeg m4a encode (transcode + silence trim), source/format validation, WeChat .silk decoding, CAF conversion and the best-effort cloud pre-upload silence trim. -Split out of ``tools/transcription_tools.py``; moved names are re-imported -there so ``tools.transcription_tools.`` keeps resolving and patches on the -origin still intercept (origin helpers are imported lazily inside functions). +Split out of ``tools/transcription_tools.py``, which re-imports every name (patch +surface) and is imported lazily here so origin patches still intercept. """ from __future__ import annotations @@ -220,9 +219,7 @@ def _convert_caf_to_wav(file_path: str) -> Optional[str]: return None -# --------------------------------------------------------------------------- -# Cloud pre-upload silence trim -# --------------------------------------------------------------------------- +# ---- Cloud pre-upload silence trim -------------------------------------- # # Local faster-whisper gets Silero VAD; cloud providers get the raw file, so # every second of silence is paid for twice (upload + per-minute billing) and diff --git a/tools/transcription_cloud.py b/tools/transcription_cloud.py index b2b9380ac0..c81f008a6d 100644 --- a/tools/transcription_cloud.py +++ b/tools/transcription_cloud.py @@ -4,9 +4,8 @@ OpenAI-SDK-shaped backends (groq, openai, deepinfra), Mistral Voxtral, the REST multipart backends (xAI, ElevenLabs), and OpenAI audio credential resolution (config > keyless local server > env > managed Nous gateway). -Split out of ``tools/transcription_tools.py``; moved names are re-imported -there so ``tools.transcription_tools.`` keeps resolving and patches on the -origin still intercept (origin helpers are imported lazily inside functions). +Split out of ``tools/transcription_tools.py``, which re-imports every name (patch +surface) and is imported lazily here so origin patches still intercept. """ from __future__ import annotations diff --git a/tools/transcription_command.py b/tools/transcription_command.py index 9b8eccaa3b..82e8da1d57 100644 --- a/tools/transcription_command.py +++ b/tools/transcription_command.py @@ -4,9 +4,8 @@ ``TranscriptionProvider`` dispatch, and the ``pre_transcription`` hook that threads prompt/language/model overrides into every backend. -Split out of ``tools/transcription_tools.py``; moved names are re-imported -there so ``tools.transcription_tools.`` keeps resolving and patches on the -origin still intercept (origin helpers are imported lazily inside functions). +Split out of ``tools/transcription_tools.py``, which re-imports every name (patch +surface) and is imported lazily here so origin patches still intercept. """ from __future__ import annotations @@ -30,9 +29,7 @@ from tools.transcription_common import ( logger = logging.getLogger("tools.transcription_tools") -# --------------------------------------------------------------------------- -# Command-provider registry (``stt.providers.: type: command``) -# --------------------------------------------------------------------------- +# ---- Command-provider registry (``stt.providers.: type: command``) --- # # Mirrors the TTS command-provider registry: same placeholder grammar, # shell-quote-aware rendering and process-tree termination on timeout. diff --git a/tools/transcription_local.py b/tools/transcription_local.py index a4332c1ca3..976fc128da 100644 --- a/tools/transcription_local.py +++ b/tools/transcription_local.py @@ -5,9 +5,8 @@ anti-hallucination transcribe kwargs and segment gate, and the local whisper CLI (``local_command``) provider. The cached-model singleton and its idle-unload watcher stay in ``transcription_tools`` (they own the module state). -Split out of ``tools/transcription_tools.py``; moved names are re-imported -there so ``tools.transcription_tools.`` keeps resolving and patches on the -origin still intercept (origin helpers are imported lazily inside functions). +Split out of ``tools/transcription_tools.py``, which re-imports every name (patch +surface) and is imported lazily here so origin patches still intercept. """ from __future__ import annotations diff --git a/tools/transcription_tools.py b/tools/transcription_tools.py index 5efdf95bc8..94f585bea2 100644 --- a/tools/transcription_tools.py +++ b/tools/transcription_tools.py @@ -127,9 +127,7 @@ _idle_unload_mgmt_lock = threading.Lock() _IDLE_UNLOAD_CHECK_INTERVAL = 30 # seconds between idle checks -# --------------------------------------------------------------------------- -# Config helpers -# --------------------------------------------------------------------------- +# ---- Config helpers ----------------------------------------------------- def _load_stt_config() -> dict: @@ -173,13 +171,17 @@ def _resolve_stt_language( return None -def _has_openai_audio_backend() -> bool: - """Return True when OpenAI audio can use config credentials, env credentials, or the managed gateway.""" +def _openai_audio_unavailable_reason() -> Optional[str]: + """None when OpenAI audio has usable credentials (config, env, or managed gateway); else the reason.""" try: _resolve_openai_audio_client_config() - return True - except ValueError: - return False + return None + except ValueError as exc: + return str(exc) + + +def _has_openai_audio_backend() -> bool: + return _openai_audio_unavailable_reason() is None def _is_local_stt_provider(provider: str, stt_config: Dict[str, Any]) -> bool: @@ -187,9 +189,7 @@ def _is_local_stt_provider(provider: str, stt_config: Dict[str, Any]) -> bool: return (provider or "").lower().strip() in {"local", "local_command"} -# --------------------------------------------------------------------------- -# Provider resolution -# --------------------------------------------------------------------------- +# ---- Provider resolution ------------------------------------------------ def _has_xai_stt_credentials_quietly() -> bool: @@ -223,12 +223,11 @@ def _resolve_explicit_openai() -> str: # Resolve directly rather than via the boolean probe so a managed # openai-audio gateway outage is logged with its real reason, not a # generic "no API key" hint. - try: - _resolve_openai_audio_client_config() + reason = _openai_audio_unavailable_reason() + if reason is None: return "openai" - except ValueError as exc: - logger.warning("STT provider 'openai' configured but unavailable: %s", exc) - return "none" + logger.warning("STT provider 'openai' configured but unavailable: %s", reason) + return "none" def _detect_local_backend() -> Optional[str]: @@ -374,9 +373,7 @@ def _get_provider(stt_config: dict) -> str: return "none" -# --------------------------------------------------------------------------- -# Provider: local (faster-whisper) -# --------------------------------------------------------------------------- +# ---- Provider: local (faster-whisper) ----------------------------------- def _unload_local_model() -> None: @@ -537,9 +534,7 @@ def _transcribe_local( return _error_result(f"Local transcription failed: {e}") -# --------------------------------------------------------------------------- -# Public API -# --------------------------------------------------------------------------- +# ---- Public API --------------------------------------------------------- def _read_block_error(file_path: str) -> Optional[Dict[str, Any]]: @@ -702,10 +697,9 @@ def _no_provider_error(provider: str, stt_config: Dict[str, Any]) -> Dict[str, A # selection-specific reason (e.g. managed openai-audio gateway down); # surface it with its remediation instead of the all-provider hint. if provider_key == "none" and str(stt_config.get("provider") or "") == "openai" and _HAS_OPENAI: - try: - _resolve_openai_audio_client_config() - except ValueError as exc: - return _error_result(str(exc)) + reason = _openai_audio_unavailable_reason() + if reason is not None: + return _error_result(reason) return _error_result( "No STT provider available. Install faster-whisper for free local "