Support language-specific STT prompts

This commit is contained in:
Magzhan Zhumabayev
2026-05-02 02:27:07 +05:00
parent 2cadbdac8b
commit ce1d4df696
2 changed files with 21 additions and 5 deletions
+3 -1
View File
@@ -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=Здравствуйте! Меня зовут Айнур, я эй-ай-ассистент компании ДиджиОпс. Как я могу к вам обращаться и на каком языке вам удобнее продолжить: на русском или на казахском?
+18 -4
View File
@@ -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