refactor(stt): fold no-provider error tail, drop _normalize_local_command_model alias, compact dispatcher call sites

This commit is contained in:
Teknium
2026-09-02 15:59:38 -07:00
parent a4f17d7a4b
commit 5844839639
4 changed files with 20 additions and 56 deletions

View File

@@ -254,17 +254,9 @@ def _convert_caf_to_wav(file_path: str) -> Optional[str]:
# they may wrap local CLIs that want the original bytes.
_CLOUD_TRIM_THRESHOLD_DB_DEFAULT = -40 # audio below this level counts as silence
_CLOUD_TRIM_KEEP_MS_DEFAULT = 300 # how much of each pause survives the trim
_CLOUD_TRIM_MIN_SAVING = 0.10 # use the trimmed file only when >=10% shorter
_CLOUD_TRIM_MIN_RESULT_SECONDS = 0.3 # all-silence guard floor: never upload ~empty audio
# Below this the trim can't pay for itself (several providers bill a 10s
# minimum per request) and the encode would sit on the synchronous voice-note path.
_CLOUD_TRIM_MIN_INPUT_SECONDS = 12.0

View File

@@ -40,14 +40,8 @@ logger = logging.getLogger("tools.transcription_tools")
# The single-env-var HERMES_LOCAL_STT_COMMAND escape hatch stays untouched via
# the built-in ``local_command`` path.
DEFAULT_COMMAND_STT_TIMEOUT_SECONDS = 300
DEFAULT_COMMAND_STT_LANGUAGE = "en"
DEFAULT_COMMAND_STT_OUTPUT_FORMAT = "txt"
COMMAND_STT_OUTPUT_FORMATS = frozenset({"txt", "json", "srt", "vtt"})

View File

@@ -68,9 +68,6 @@ def _normalize_local_model(model_name: Optional[str]) -> str:
return model_name
_normalize_local_command_model = _normalize_local_model
def _try_lazy_install_stt() -> bool:
"""Lazy-install faster-whisper and re-check dynamically so it's usable without a restart."""
try:
@@ -188,11 +185,7 @@ def _load_local_whisper_model(model_name: str, device: str = "auto", compute_typ
# condition_on_previous_text=False so one hallucinated token can't seed a run;
# and the segment confidence gate in _is_hallucinated_segment.
_VAD_MIN_SILENCE_MS_DEFAULT = 500
_NO_SPEECH_PROB_THRESHOLD_DEFAULT = 0.6
_LOGPROB_THRESHOLD_DEFAULT = -1.0
@@ -308,7 +301,7 @@ def _transcribe_local_command(
# Language: hook override > stt.local.language > stt.language > env > "en".
language = language or _resolve_stt_language("local") or DEFAULT_LOCAL_STT_LANGUAGE
normalized_model = _normalize_local_command_model(model_name)
normalized_model = _normalize_local_model(model_name)
try:
with tempfile.TemporaryDirectory(prefix="hermes-local-stt-") as output_dir:

View File

@@ -76,7 +76,6 @@ from tools.transcription_local import ( # noqa: F401 (re-exported; tests patch
_join_confident_segments,
_load_local_whisper_model,
_looks_like_cuda_lib_error,
_normalize_local_command_model,
_normalize_local_model,
_transcribe_local_command,
_try_lazy_install_stt,
@@ -625,10 +624,9 @@ def _transcribe_prepared_audio(
# Convert CAF (iMessage voice notes) to WAV for cloud STT providers.
if Path(file_path).suffix.lower() == ".caf" and provider not in ("local", "local_command"):
converted = _convert_caf_to_wav(file_path)
if not converted:
file_path = _convert_caf_to_wav(file_path)
if not file_path:
return _error_result("CAF audio could not be converted to WAV.")
file_path = converted
# Best-effort pre-upload silence trim for built-in cloud providers.
trim_cleanup_dir: Optional[str] = None
@@ -696,12 +694,9 @@ def _dispatch_stt_provider(
# The hook fires after provider resolution and BEFORE any backend is
# invoked; ``language`` stays None unless a hook overrides it.
model, language, prompt = _apply_pre_transcription_hook(
file_path=file_path,
provider=provider,
model=model,
file_path=file_path, provider=provider, model=model,
language=_get_stt_section(stt_config, provider).get("language"),
prompt=prompt,
source=source,
prompt=prompt, source=source,
)
prompt = _enforce_prompt_length_limit(prompt, provider)
@@ -718,36 +713,28 @@ def _dispatch_stt_provider(
command_provider_config = _resolve_command_stt_provider_config(provider, stt_config)
if command_provider_config is not None:
return _transcribe_command_stt(
file_path,
provider,
command_provider_config,
stt_config,
model_override=model,
language_override=language,
prompt=prompt,
file_path, provider, command_provider_config, stt_config,
model_override=model, language_override=language, prompt=prompt,
)
# Plugin-registered backend. Plugins read per-provider config under
# ``stt.<provider>`` like built-ins; the ``model`` argument overrides it.
plugin_cfg = _get_stt_section(stt_config, provider)
plugin_result = _dispatch_to_plugin_provider(
file_path,
provider,
stt_config,
file_path, provider, stt_config,
model=model or plugin_cfg.get("model"),
language=language or _resolve_stt_language(provider, stt_config),
prompt=prompt,
)
if plugin_result is not None:
return plugin_result
return _no_provider_error(provider, stt_config)
def _no_provider_error(provider: str, stt_config: Dict[str, Any]) -> Dict[str, Any]:
"""Error envelope when nothing claimed *provider*: unregistered name > openai selection reason > generic hint."""
provider_key = str(provider or "").strip().lower()
if (
"provider" in stt_config
and provider_key
and provider_key not in BUILTIN_STT_PROVIDERS
and provider_key != "none"
):
if "provider" in stt_config and provider_key and provider_key not in BUILTIN_STT_PROVIDERS and provider_key != "none":
return _unregistered_stt_provider_error(provider_key)
# An explicit openai selection flattened to "none" carries a
@@ -794,16 +781,14 @@ def transcribe_audio(
return source_error
prepared_path, cleanup_dir, prep_error = _prepare_audio_for_transcription(file_path)
if prep_error:
return prep_error
if prepared_path is None:
return _error_result("Audio preprocessing did not produce a file for transcription.")
if prep_error or prepared_path is None:
return prep_error or _error_result("Audio preprocessing did not produce a file for transcription.")
try:
prepared_error = _validate_audio_file(prepared_path, enforce_size_limit=False)
if prepared_error:
return prepared_error
return _transcribe_prepared_audio(prepared_path, model, source)
return (
_validate_audio_file(prepared_path, enforce_size_limit=False)
or _transcribe_prepared_audio(prepared_path, model, source)
)
finally:
if cleanup_dir:
shutil.rmtree(cleanup_dir, ignore_errors=True)
@@ -828,7 +813,7 @@ def transcribe_audio_local_fallback(
if _HAS_FASTER_WHISPER:
return _transcribe_local(file_path, _normalize_local_model(local_model))
if _has_local_command():
return _transcribe_local_command(file_path, _normalize_local_command_model(local_model))
return _transcribe_local_command(file_path, _normalize_local_model(local_model))
return _error_result("No installed local STT backend is available.", provider="local")