This commit is contained in:
dhruvladia-sarvam
2026-01-30 16:07:52 +05:30
parent 18045582a9
commit 57821cf709

View File

@@ -78,11 +78,13 @@ class SarvamSTTService(STTService):
"""Configuration parameters for Sarvam STT service.
Parameters:
language: Target language for transcription. Required for all models.
Defaults to "unknown" for saarika models and "en-IN" for saaras:v3.
prompt: Optional prompt to guide transcription style/context.
Only applicable to saaras:v3 models. Defaults to None.
mode: Mode of operation for saaras:v3 models. Options: transcribe, translate,
language: Target language for transcription.
- saarika:v2.5: Defaults to "unknown" (auto-detect supported)
- saaras:v2.5: Not used (auto-detects language)
- saaras:v3: Defaults to "en-IN"
prompt: Optional prompt to guide transcription/translation style/context.
Only applicable to saaras models (v2.5 and v3). Defaults to None.
mode: Mode of operation for saaras:v3 models only. Options: transcribe, translate,
verbatim, translit, codemix. Defaults to "transcribe" for saaras:v3.
vad_signals: Enable VAD signals in response. Defaults to None.
high_vad_sensitivity: Enable high VAD (Voice Activity Detection) sensitivity. Defaults to None.
@@ -111,10 +113,13 @@ class SarvamSTTService(STTService):
Args:
api_key: Sarvam API key for authentication.
model: Sarvam model to use for transcription. Allowed: "saarika:v2.5", "saaras:v3".
model: Sarvam model to use for transcription. Allowed values:
- "saarika:v2.5": Standard STT model
- "saaras:v2.5": STT-Translate model (auto-detects language, supports prompts)
- "saaras:v3": Advanced STT model (supports mode and prompts)
sample_rate: Audio sample rate. Defaults to 16000 if not specified.
input_audio_codec: Audio codec/format of the input file. Defaults to "wav".
mode: Mode of operation for saaras:v3 models. Options: transcribe, translate,
mode: Mode of operation for saaras:v3 models only. Options: transcribe, translate,
verbatim, translit, codemix. Defaults to "transcribe" for saaras:v3.
params: Configuration parameters for Sarvam STT service.
**kwargs: Additional arguments passed to the parent STTService.
@@ -125,34 +130,52 @@ class SarvamSTTService(STTService):
params = params.model_copy(update={"mode": mode})
# Validate allowed models
allowed_models = {"saarika:v2.5", "saaras:v3"}
allowed_models = {"saarika:v2.5", "saaras:v3", "saaras:v2.5"}
if model not in allowed_models:
allowed_models_list = ", ".join(sorted(allowed_models))
raise ValueError(f"Unsupported model '{model}'. Allowed values: {allowed_models_list}.")
# Validate that saarika models don't accept prompt parameter
# Validate model-specific parameter restrictions
if "saarika" in model.lower():
# saarika models don't accept prompt or mode
if params.prompt is not None:
raise ValueError(
f"Model '{model}' does not accept prompt parameter. "
"Prompts are only supported for saaras:v3 model."
"Prompts are only supported for saaras models (v2.5 and v3)."
)
if params.mode is not None:
raise ValueError(
f"Model '{model}' does not accept mode parameter. "
"Mode is only supported for saaras:v3 model."
)
elif model.lower() == "saaras:v2.5":
# saaras:v2.5 supports prompt but not mode
if params.mode is not None:
raise ValueError(
f"Model '{model}' does not accept mode parameter. "
"Mode is only supported for saaras:v3 model."
)
if params.language is not None:
raise ValueError(
f"Model '{model}' does not accept language parameter. "
"saaras:v2.5 (STT-Translate) auto-detects language."
)
super().__init__(sample_rate=sample_rate, **kwargs)
self.set_model_name(model)
self._api_key = api_key
self._language_code: Optional[Language] = params.language
# Set language string - both models require language_code
# Set language string based on model type
# - saarika:v2.5: uses language_code or defaults to "unknown"
# - saaras:v2.5: auto-detects language (no language_code needed)
# - saaras:v3: uses language_code or defaults to "en-IN"
if params.language:
self._language_string = language_to_sarvam_language(params.language)
elif "saarika" in model.lower():
self._language_string = "unknown"
elif model.lower() == "saaras:v2.5":
self._language_string = None # STT-Translate auto-detects language
elif model.lower() == "saaras:v3":
self._language_string = "en-IN"
else:
@@ -225,7 +248,17 @@ class SarvamSTTService(STTService):
Args:
language: The language to use for speech recognition.
Raises:
ValueError: If called on saaras:v2.5 model which auto-detects language.
"""
# saaras:v2.5 (STT-Translate) auto-detects language
if self.model_name.lower() == "saaras:v2.5":
raise ValueError(
f"Model '{self.model_name}' does not accept language parameter. "
"saaras:v2.5 (STT-Translate) auto-detects language."
)
logger.info(f"Switching STT language to: [{language}]")
self._language_code = language
self._language_string = language_to_sarvam_language(language)
@@ -233,24 +266,24 @@ class SarvamSTTService(STTService):
await self._connect()
async def set_prompt(self, prompt: Optional[str]):
"""Set the transcription prompt and reconnect.
"""Set the transcription/translation prompt and reconnect.
Args:
prompt: Prompt text to guide transcription style/context.
prompt: Prompt text to guide transcription/translation style/context.
Pass None to clear/disable prompt.
Only applicable to saaras:v3 model.
Only applicable to saaras models (v2.5 and v3).
"""
# saarika models do not accept prompt parameter
if "saarika" in self.model_name.lower():
if prompt is not None:
raise ValueError(
f"Model '{self.model_name}' does not accept prompt parameter. "
"Prompts are only supported for saaras:v3 model."
"Prompts are only supported for saaras models (v2.5 and v3)."
)
# If prompt is None and it's saarika, just silently return (no-op)
return
logger.info("Updating saaras:v3 prompt.")
logger.info(f"Updating {self.model_name} prompt.")
self._prompt = prompt
await self._disconnect()
await self._connect()
@@ -314,8 +347,13 @@ class SarvamSTTService(STTService):
"sample_rate": self.sample_rate,
}
# Both saarika and saaras:v3 use the same speech_to_text_streaming endpoint
await self._socket_client.transcribe(**method_kwargs)
# Use appropriate method based on model type
if self.model_name.lower() == "saaras:v2.5":
# STT-Translate: auto-detects input language and returns translated text
await self._socket_client.translate(**method_kwargs)
else:
# saarika:v2.5 and saaras:v3 use transcribe
await self._socket_client.transcribe(**method_kwargs)
except Exception as e:
yield ErrorFrame(error=f"Error sending audio to Sarvam: {e}", exception=e)
@@ -331,15 +369,18 @@ class SarvamSTTService(STTService):
vad_signals_str = "true" if self._vad_signals else "false"
high_vad_sensitivity_str = "true" if self._high_vad_sensitivity else "false"
# Build connection parameters - both models use speech_to_text_streaming
# Build common connection parameters
connect_kwargs = {
"model": self.model_name,
"language_code": self._language_string, # Required for both models
"vad_signals": vad_signals_str,
"high_vad_sensitivity": high_vad_sensitivity_str,
"sample_rate": str(self.sample_rate),
}
# Add language_code for models that require it (not saaras:v2.5 which auto-detects)
if self._language_string is not None:
connect_kwargs["language_code"] = self._language_string
# Add mode for saaras:v3 only
if self.model_name.lower() == "saaras:v3" and self._mode is not None:
connect_kwargs["mode"] = self._mode
@@ -353,17 +394,25 @@ class SarvamSTTService(STTService):
pass
return connect_fn(**kwargs)
# Both saarika and saaras:v3 use the same speech_to_text_streaming endpoint
self._websocket_context = _connect_with_sdk_headers(
self._sarvam_client.speech_to_text_streaming.connect,
**connect_kwargs,
)
# Choose the appropriate endpoint based on model
if self.model_name.lower() == "saaras:v2.5":
# STT-Translate: auto-detects input language and returns translated text
self._websocket_context = _connect_with_sdk_headers(
self._sarvam_client.speech_to_text_translate_streaming.connect,
**connect_kwargs,
)
else:
# saarika:v2.5 and saaras:v3 use speech_to_text_streaming
self._websocket_context = _connect_with_sdk_headers(
self._sarvam_client.speech_to_text_streaming.connect,
**connect_kwargs,
)
# Enter the async context manager
self._socket_client = await self._websocket_context.__aenter__()
# Set prompt if provided (only for saaras:v3 model, after connection)
if self._prompt is not None and self.model_name.lower() == "saaras:v3":
# Set prompt if provided (only for saaras models, after connection)
if self._prompt is not None and "saaras" in self.model_name.lower():
await self._socket_client.set_prompt(self._prompt)
# Register event handler for incoming messages