From ce1d4df6964129894182e161ea2f7ff53fd61a4d Mon Sep 17 00:00:00 2001 From: Magzhan Zhumabayev Date: Sat, 2 May 2026 02:27:07 +0500 Subject: [PATCH] Support language-specific STT prompts --- .env.example | 4 +++- providers/stt_openai.py | 22 ++++++++++++++++++---- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/.env.example b/.env.example index 1b2ec68..d6bf6ed 100644 --- a/.env.example +++ b/.env.example @@ -35,7 +35,9 @@ STT_PROVIDER=openai STT_FALLBACK_PROVIDER=elevenlabs # Empty means auto-detect the first answer, because the greeting asks for name and preferred language. STT_NAME_CAPTURE_LANGUAGE_CODE= -STT_PROMPT=Это русская речь по телефону. Точно распознавай короткие ответы, имена, фамилии, слова благодарности и прощания. Особое внимание именам: Айнур, Айгерим, Алия, Данияр, Азамат, Арман, Мадина, Нурсултан, Руслан, Асель. Если человек представился одним словом, сохраняй его как имя. Номера телефонов записывай цифрами. +STT_PROMPT= +STT_PROMPT_RU=Это русская речь по телефону. Точно распознавай короткие ответы, имена, фамилии, слова благодарности и прощания. Если человек представился одним словом, сохраняй его как имя. Номера телефонов записывай цифрами. +STT_PROMPT_KZ=Бұл қазақ тіліндегі телефон арқылы сөйлесу. Қысқа жауаптарды, есімдерді, тілді таңдауды және қоштасуды дәл таны. Клиент бір сөзбен танысса, оны есім ретінде сақта. Телефон нөмірлерін цифрлармен жаз. TTS_PROVIDER=elevenlabs REALTIME_VOICE_INITIAL_GREETING_RU_TEXT=Здравствуйте! Меня зовут Айнур, я эй-ай-ассистент компании ДиджиОпс. Как я могу к вам обращаться и на каком языке вам удобнее продолжить: на русском или на казахском? diff --git a/providers/stt_openai.py b/providers/stt_openai.py index ad9e3db..9a1e004 100644 --- a/providers/stt_openai.py +++ b/providers/stt_openai.py @@ -92,17 +92,22 @@ class OpenAISTT(BaseSTT): ).strip() or None self._input_sample_rate_hz = max(int(input_sample_rate_hz), 1) self._prompt = str(prompt if prompt is not None else os.getenv("STT_PROMPT", "")).strip() + self._ru_prompt = str(os.getenv("STT_PROMPT_RU", "")).strip() + self._kk_prompt = str(os.getenv("STT_PROMPT_KZ", "") or os.getenv("STT_PROMPT_KK", "")).strip() self._language = str(language if language is not None else os.getenv("OPENAI_STT_LANGUAGE", "")).strip() or None self._timeout_seconds = max(float(timeout_seconds if timeout_seconds is not None else _timeout_seconds()), 1.0) self._max_retries = max(int(max_retries if max_retries is not None else _max_retries()), 0) self._client: Any | None = None self._openai_module: Any | None = None LOGGER.info( - "OpenAI STT config: model=%s input_sample_rate=%s language=%s prompt_configured=%s base_url=%s timeout=%s", + "OpenAI STT config: model=%s input_sample_rate=%s language=%s prompt_configured=%s " + "ru_prompt_configured=%s kk_prompt_configured=%s base_url=%s timeout=%s", self._model, self._input_sample_rate_hz, self._language, bool(self._prompt), + bool(self._ru_prompt), + bool(self._kk_prompt), self._base_url or "default", self._timeout_seconds, ) @@ -122,6 +127,7 @@ class OpenAISTT(BaseSTT): raise RuntimeError("OPENAI_API_KEY is required for OpenAI STT") effective_language = _normalize_openai_language_code(language_code) or self._language + effective_prompt = self._prompt_for_language(effective_language) wav_bytes = _pcm16le_to_wav_bytes(audio_bytes, sample_rate_hz=self._input_sample_rate_hz) audio_file = io.BytesIO(wav_bytes) audio_file.name = "utterance.wav" @@ -134,7 +140,7 @@ class OpenAISTT(BaseSTT): len(wav_bytes), self._input_sample_rate_hz, effective_language, - _preview_text(self._prompt), + _preview_text(effective_prompt), ) request: dict[str, object] = { @@ -142,8 +148,8 @@ class OpenAISTT(BaseSTT): "model": self._model, "response_format": "json", } - if self._prompt: - request["prompt"] = self._prompt + if effective_prompt: + request["prompt"] = effective_prompt if effective_language: request["language"] = effective_language @@ -203,6 +209,14 @@ class OpenAISTT(BaseSTT): self._client = AsyncOpenAI(**client_kwargs) return self._client + def _prompt_for_language(self, language_code: str | None) -> str: + normalized = _normalize_openai_language_code(language_code) + if normalized == "ru": + return self._ru_prompt or self._prompt + if normalized == "kk": + return self._kk_prompt or self._prompt + return self._prompt + async def close(self) -> None: client = self._client self._client = None