Flatten input_params into individual fields on SonioxSTTSettings and GladiaSTTSettings
This makes each service-specific field individually visible to the delta/update mechanism (`apply_update`, `given_fields`) and removes the need for complex sync logic between `input_params` and top-level fields like `model`. - Soniox: replace `input_params: SonioxInputParams` with 8 individual fields, simplify `_update_settings` by removing model sync logic, remove unused `is_given` import - Gladia: replace `input_params: GladiaInputParams` with 11 individual fields, resolve deprecated `language` → `language_config` at init time rather than at `_prepare_settings` time
This commit is contained in:
@@ -32,7 +32,13 @@ from pipecat.frames.frames import (
|
||||
UserStartedSpeakingFrame,
|
||||
UserStoppedSpeakingFrame,
|
||||
)
|
||||
from pipecat.services.gladia.config import GladiaInputParams
|
||||
from pipecat.services.gladia.config import (
|
||||
GladiaInputParams,
|
||||
LanguageConfig,
|
||||
MessagesConfig,
|
||||
PreProcessingConfig,
|
||||
RealtimeProcessingConfig,
|
||||
)
|
||||
from pipecat.services.settings import NOT_GIVEN, STTSettings, _NotGiven
|
||||
from pipecat.services.stt_latency import GLADIA_TTFS_P99
|
||||
from pipecat.services.stt_service import WebsocketSTTService
|
||||
@@ -185,10 +191,36 @@ class GladiaSTTSettings(STTSettings):
|
||||
"""Settings for Gladia STT service.
|
||||
|
||||
Parameters:
|
||||
input_params: Gladia ``GladiaInputParams`` for detailed configuration.
|
||||
encoding: Audio encoding format.
|
||||
bit_depth: Audio bit depth.
|
||||
channels: Number of audio channels.
|
||||
custom_metadata: Additional metadata to include with requests.
|
||||
endpointing: Silence duration in seconds to mark end of speech.
|
||||
maximum_duration_without_endpointing: Maximum utterance duration without silence.
|
||||
language_config: Detailed language configuration.
|
||||
pre_processing: Audio pre-processing options.
|
||||
realtime_processing: Real-time processing features.
|
||||
messages_config: WebSocket message filtering options.
|
||||
enable_vad: Enable VAD to trigger end of utterance detection.
|
||||
"""
|
||||
|
||||
input_params: GladiaInputParams | _NotGiven = field(default_factory=lambda: NOT_GIVEN)
|
||||
encoding: str | None | _NotGiven = field(default_factory=lambda: NOT_GIVEN)
|
||||
bit_depth: int | None | _NotGiven = field(default_factory=lambda: NOT_GIVEN)
|
||||
channels: int | None | _NotGiven = field(default_factory=lambda: NOT_GIVEN)
|
||||
custom_metadata: Dict[str, Any] | None | _NotGiven = field(default_factory=lambda: NOT_GIVEN)
|
||||
endpointing: float | None | _NotGiven = field(default_factory=lambda: NOT_GIVEN)
|
||||
maximum_duration_without_endpointing: int | None | _NotGiven = field(
|
||||
default_factory=lambda: NOT_GIVEN
|
||||
)
|
||||
language_config: LanguageConfig | None | _NotGiven = field(default_factory=lambda: NOT_GIVEN)
|
||||
pre_processing: PreProcessingConfig | None | _NotGiven = field(
|
||||
default_factory=lambda: NOT_GIVEN
|
||||
)
|
||||
realtime_processing: RealtimeProcessingConfig | None | _NotGiven = field(
|
||||
default_factory=lambda: NOT_GIVEN
|
||||
)
|
||||
messages_config: MessagesConfig | None | _NotGiven = field(default_factory=lambda: NOT_GIVEN)
|
||||
enable_vad: bool | None | _NotGiven = field(default_factory=lambda: NOT_GIVEN)
|
||||
|
||||
|
||||
class GladiaSTTService(WebsocketSTTService):
|
||||
@@ -280,7 +312,29 @@ class GladiaSTTService(WebsocketSTTService):
|
||||
self._region = region
|
||||
self._url = url
|
||||
self._receive_task = None
|
||||
self._settings = GladiaSTTSettings(model=model, language=None, input_params=params)
|
||||
|
||||
# Resolve deprecated language → language_config at init time
|
||||
language_config = params.language_config
|
||||
if not language_config and params.language:
|
||||
language_code = self.language_to_service_language(params.language)
|
||||
if language_code:
|
||||
language_config = LanguageConfig(languages=[language_code], code_switching=False)
|
||||
|
||||
self._settings = GladiaSTTSettings(
|
||||
model=model,
|
||||
language=None,
|
||||
encoding=params.encoding,
|
||||
bit_depth=params.bit_depth,
|
||||
channels=params.channels,
|
||||
custom_metadata=params.custom_metadata,
|
||||
endpointing=params.endpointing,
|
||||
maximum_duration_without_endpointing=params.maximum_duration_without_endpointing,
|
||||
language_config=language_config,
|
||||
pre_processing=params.pre_processing,
|
||||
realtime_processing=params.realtime_processing,
|
||||
messages_config=params.messages_config,
|
||||
enable_vad=params.enable_vad,
|
||||
)
|
||||
self._sync_model_name_to_metrics()
|
||||
|
||||
# Session management
|
||||
@@ -321,52 +375,43 @@ class GladiaSTTService(WebsocketSTTService):
|
||||
return language_to_gladia_language(language)
|
||||
|
||||
def _prepare_settings(self) -> Dict[str, Any]:
|
||||
params = self._settings.input_params
|
||||
s = self._settings
|
||||
|
||||
settings = {
|
||||
"encoding": params.encoding or "wav/pcm",
|
||||
"bit_depth": params.bit_depth or 16,
|
||||
"encoding": s.encoding or "wav/pcm",
|
||||
"bit_depth": s.bit_depth or 16,
|
||||
"sample_rate": self.sample_rate,
|
||||
"channels": params.channels or 1,
|
||||
"model": self._settings.model,
|
||||
"channels": s.channels or 1,
|
||||
"model": s.model,
|
||||
}
|
||||
|
||||
# Add custom_metadata if provided
|
||||
settings["custom_metadata"] = dict(params.custom_metadata or {})
|
||||
settings["custom_metadata"] = dict(s.custom_metadata or {})
|
||||
settings["custom_metadata"]["pipecat"] = pipecat_version()
|
||||
|
||||
# Add endpointing parameters if provided
|
||||
if params.endpointing is not None:
|
||||
settings["endpointing"] = params.endpointing
|
||||
if params.maximum_duration_without_endpointing is not None:
|
||||
if s.endpointing is not None:
|
||||
settings["endpointing"] = s.endpointing
|
||||
if s.maximum_duration_without_endpointing is not None:
|
||||
settings["maximum_duration_without_endpointing"] = (
|
||||
params.maximum_duration_without_endpointing
|
||||
s.maximum_duration_without_endpointing
|
||||
)
|
||||
|
||||
# Add language configuration (prioritize language_config over deprecated language)
|
||||
if params.language_config:
|
||||
settings["language_config"] = params.language_config.model_dump(exclude_none=True)
|
||||
elif params.language: # Backward compatibility for deprecated parameter
|
||||
language_code = self.language_to_service_language(params.language)
|
||||
if language_code:
|
||||
settings["language_config"] = {
|
||||
"languages": [language_code],
|
||||
"code_switching": False,
|
||||
}
|
||||
# Add language configuration
|
||||
if s.language_config:
|
||||
settings["language_config"] = s.language_config.model_dump(exclude_none=True)
|
||||
|
||||
# Add pre_processing configuration if provided
|
||||
if params.pre_processing:
|
||||
settings["pre_processing"] = params.pre_processing.model_dump(exclude_none=True)
|
||||
if s.pre_processing:
|
||||
settings["pre_processing"] = s.pre_processing.model_dump(exclude_none=True)
|
||||
|
||||
# Add realtime_processing configuration if provided
|
||||
if params.realtime_processing:
|
||||
settings["realtime_processing"] = params.realtime_processing.model_dump(
|
||||
exclude_none=True
|
||||
)
|
||||
if s.realtime_processing:
|
||||
settings["realtime_processing"] = s.realtime_processing.model_dump(exclude_none=True)
|
||||
|
||||
# Add messages_config if provided
|
||||
if params.messages_config:
|
||||
settings["messages_config"] = params.messages_config.model_dump(exclude_none=True)
|
||||
if s.messages_config:
|
||||
settings["messages_config"] = s.messages_config.model_dump(exclude_none=True)
|
||||
|
||||
return settings
|
||||
|
||||
@@ -562,7 +607,7 @@ class GladiaSTTService(WebsocketSTTService):
|
||||
Broadcasts UserStartedSpeakingFrame and optionally triggers interruption
|
||||
when VAD is enabled.
|
||||
"""
|
||||
if not self._settings.input_params.enable_vad or self._is_speaking:
|
||||
if not self._settings.enable_vad or self._is_speaking:
|
||||
return
|
||||
|
||||
logger.debug(f"{self} User started speaking")
|
||||
@@ -577,7 +622,7 @@ class GladiaSTTService(WebsocketSTTService):
|
||||
|
||||
Broadcasts UserStoppedSpeakingFrame when VAD is enabled.
|
||||
"""
|
||||
if not self._settings.input_params.enable_vad or not self._is_speaking:
|
||||
if not self._settings.enable_vad or not self._is_speaking:
|
||||
return
|
||||
self._is_speaking = False
|
||||
await self.broadcast_frame(UserStoppedSpeakingFrame)
|
||||
|
||||
@@ -24,7 +24,7 @@ from pipecat.frames.frames import (
|
||||
VADUserStoppedSpeakingFrame,
|
||||
)
|
||||
from pipecat.processors.frame_processor import FrameDirection
|
||||
from pipecat.services.settings import NOT_GIVEN, STTSettings, _NotGiven, is_given
|
||||
from pipecat.services.settings import NOT_GIVEN, STTSettings, _NotGiven
|
||||
from pipecat.services.stt_latency import SONIOX_TTFS_P99
|
||||
from pipecat.services.stt_service import WebsocketSTTService
|
||||
from pipecat.transcriptions.language import Language
|
||||
@@ -141,10 +141,28 @@ class SonioxSTTSettings(STTSettings):
|
||||
"""Settings for Soniox STT service.
|
||||
|
||||
Parameters:
|
||||
input_params: Soniox ``SonioxInputParams`` for detailed configuration.
|
||||
audio_format: Audio format to use for transcription.
|
||||
num_channels: Number of channels to use for transcription.
|
||||
language_hints: List of language hints to use for transcription.
|
||||
language_hints_strict: If true, strictly enforce language hints.
|
||||
context: Customization for transcription. String for models with
|
||||
context_version 1 and SonioxContextObject for models with
|
||||
context_version 2.
|
||||
enable_speaker_diarization: Whether to enable speaker diarization.
|
||||
enable_language_identification: Whether to enable language identification.
|
||||
client_reference_id: Client reference ID to use for transcription.
|
||||
"""
|
||||
|
||||
input_params: SonioxInputParams | _NotGiven = field(default_factory=lambda: NOT_GIVEN)
|
||||
audio_format: str | None | _NotGiven = field(default_factory=lambda: NOT_GIVEN)
|
||||
num_channels: int | None | _NotGiven = field(default_factory=lambda: NOT_GIVEN)
|
||||
language_hints: List[Language] | None | _NotGiven = field(default_factory=lambda: NOT_GIVEN)
|
||||
language_hints_strict: bool | None | _NotGiven = field(default_factory=lambda: NOT_GIVEN)
|
||||
context: SonioxContextObject | str | None | _NotGiven = field(default_factory=lambda: NOT_GIVEN)
|
||||
enable_speaker_diarization: bool | None | _NotGiven = field(default_factory=lambda: NOT_GIVEN)
|
||||
enable_language_identification: bool | None | _NotGiven = field(
|
||||
default_factory=lambda: NOT_GIVEN
|
||||
)
|
||||
client_reference_id: str | None | _NotGiven = field(default_factory=lambda: NOT_GIVEN)
|
||||
|
||||
|
||||
class SonioxSTTService(WebsocketSTTService):
|
||||
@@ -199,7 +217,15 @@ class SonioxSTTService(WebsocketSTTService):
|
||||
|
||||
self._settings = SonioxSTTSettings(
|
||||
model=params.model,
|
||||
input_params=params,
|
||||
language=None,
|
||||
audio_format=params.audio_format,
|
||||
num_channels=params.num_channels,
|
||||
language_hints=params.language_hints,
|
||||
language_hints_strict=params.language_hints_strict,
|
||||
context=params.context,
|
||||
enable_speaker_diarization=params.enable_speaker_diarization,
|
||||
enable_language_identification=params.enable_language_identification,
|
||||
client_reference_id=params.client_reference_id,
|
||||
)
|
||||
self._sync_model_name_to_metrics()
|
||||
|
||||
@@ -226,12 +252,7 @@ class SonioxSTTService(WebsocketSTTService):
|
||||
await self._connect()
|
||||
|
||||
async def _update_settings(self, delta: SonioxSTTSettings) -> dict[str, Any]:
|
||||
"""Apply a settings delta, keeping ``input_params`` in sync.
|
||||
|
||||
Top-level ``model`` is the source of truth. When it is given in
|
||||
*delta* its value is propagated into ``input_params``. When only
|
||||
``input_params`` is given, its ``model`` is propagated *up* to the
|
||||
top-level field.
|
||||
"""Apply settings delta.
|
||||
|
||||
Settings are stored but not applied to the active connection.
|
||||
|
||||
@@ -241,22 +262,11 @@ class SonioxSTTService(WebsocketSTTService):
|
||||
Returns:
|
||||
Dict mapping changed field names to their previous values.
|
||||
"""
|
||||
model_given = is_given(getattr(delta, "model", NOT_GIVEN))
|
||||
|
||||
changed = await super()._update_settings(delta)
|
||||
|
||||
if not changed:
|
||||
return changed
|
||||
|
||||
# --- Sync model --------------------------------------------------
|
||||
if model_given:
|
||||
# Top-level model wins → push into input_params.
|
||||
self._settings.input_params.model = self._settings.model
|
||||
elif "input_params" in changed and self._settings.input_params.model is not None:
|
||||
# Only input_params was given → pull model up.
|
||||
self._settings.model = self._settings.input_params.model
|
||||
self._sync_model_name_to_metrics()
|
||||
|
||||
# TODO: someday we could reconnect here to apply updated settings.
|
||||
# Code might look something like the below:
|
||||
# await self._disconnect()
|
||||
@@ -377,26 +387,26 @@ class SonioxSTTService(WebsocketSTTService):
|
||||
# Either one or the other is required.
|
||||
enable_endpoint_detection = not self._vad_force_turn_endpoint
|
||||
|
||||
params = self._settings.input_params
|
||||
s = self._settings
|
||||
|
||||
context = params.context
|
||||
context = s.context
|
||||
if isinstance(context, SonioxContextObject):
|
||||
context = context.model_dump()
|
||||
|
||||
# Send the initial configuration message.
|
||||
config = {
|
||||
"api_key": self._api_key,
|
||||
"model": self._settings.model,
|
||||
"audio_format": params.audio_format,
|
||||
"num_channels": params.num_channels or 1,
|
||||
"model": s.model,
|
||||
"audio_format": s.audio_format,
|
||||
"num_channels": s.num_channels or 1,
|
||||
"enable_endpoint_detection": enable_endpoint_detection,
|
||||
"sample_rate": self.sample_rate,
|
||||
"language_hints": _prepare_language_hints(params.language_hints),
|
||||
"language_hints_strict": params.language_hints_strict,
|
||||
"language_hints": _prepare_language_hints(s.language_hints),
|
||||
"language_hints_strict": s.language_hints_strict,
|
||||
"context": context,
|
||||
"enable_speaker_diarization": params.enable_speaker_diarization,
|
||||
"enable_language_identification": params.enable_language_identification,
|
||||
"client_reference_id": params.client_reference_id,
|
||||
"enable_speaker_diarization": s.enable_speaker_diarization,
|
||||
"enable_language_identification": s.enable_language_identification,
|
||||
"client_reference_id": s.client_reference_id,
|
||||
}
|
||||
|
||||
# Send the configuration message.
|
||||
|
||||
Reference in New Issue
Block a user