diff --git a/wavefront/server/apps/call_processing/call_processing/services/language_detection_tool.py b/wavefront/server/apps/call_processing/call_processing/services/language_detection_tool.py index 41ac2087..e8e0dd09 100644 --- a/wavefront/server/apps/call_processing/call_processing/services/language_detection_tool.py +++ b/wavefront/server/apps/call_processing/call_processing/services/language_detection_tool.py @@ -6,9 +6,10 @@ from typing import Dict, Any, List, Callable from pipecat.services.llm_service import FunctionCallParams -from pipecat.frames.frames import LLMMessagesUpdateFrame from call_processing.log.logger import logger from call_processing.constants.language_config import LANGUAGE_INSTRUCTIONS +from call_processing.services.tts_service import TTSServiceFactory +from call_processing.services.stt_service import STTServiceFactory class LanguageDetectionToolFactory: @@ -17,8 +18,9 @@ class LanguageDetectionToolFactory: @staticmethod def create_language_detection_tool( task_container: Dict[str, Any], - language_switcher: Any, - stt_language_switcher: Any, + tts_provider: str, + stt_provider: str, + tts_voice_ids: Dict[str, str], context_container: Dict[str, Any], supported_languages: List[str], default_language: str, @@ -30,8 +32,9 @@ def create_language_detection_tool( Args: task_container: Dictionary containing PipelineTask (populated after task creation) Format: {'task': PipelineTask | None} - language_switcher: LanguageSwitcher instance that manages TTS routing - stt_language_switcher: STTLanguageSwitcher instance that manages STT routing + tts_provider: TTS provider name (e.g. 'elevenlabs', 'azure') + stt_provider: STT provider name (e.g. 'deepgram', 'azure') + tts_voice_ids: Dict mapping language code -> voice ID for TTS context_container: Dictionary containing LLMContext (populated after context creation) Format: {'context': LLMContext | None} supported_languages: List of supported language codes @@ -123,15 +126,35 @@ async def detect_and_switch_language(params: FunctionCallParams): # Perform language switch try: - # Update TTS language switcher state - language_switcher.set_language(target_language) - - # Update STT language switcher state - stt_language_switcher.set_language(target_language) - - logger.info( - f'Switched TTS and STT language from {current_language} to {target_language}' + # Queue TTS settings update (voice + language) + tts_frame = TTSServiceFactory.create_language_update_frame( + tts_provider, + target_language, + tts_voice_ids.get(target_language), ) + tts_frame_queued = False + if tts_frame: + await task.queue_frame(tts_frame) + tts_frame_queued = True + + # Queue STT settings update (language) + stt_frame = STTServiceFactory.create_language_update_frame( + stt_provider, target_language + ) + stt_frame_queued = False + if stt_frame: + await task.queue_frame(stt_frame) + stt_frame_queued = True + + log_msg = ( + f'Language update {current_language} -> {target_language}: ' + f'TTS={"queued" if tts_frame_queued else "skipped"}, ' + f'STT={"queued" if stt_frame_queued else "skipped"}' + ) + if tts_frame_queued or stt_frame_queued: + logger.info(log_msg) + else: + logger.error(log_msg) # Update system prompt with language instruction language_instruction = LANGUAGE_INSTRUCTIONS.get( @@ -151,17 +174,16 @@ async def detect_and_switch_language(params: FunctionCallParams): # Append new language instruction to clean base prompt updated_content = f'{language_instruction}\n\n{base_prompt}' - updated_system_message = { - 'role': 'system', - 'content': updated_content, - } - # Update context + # Mutate the system message in-place on the context object so + # the full conversation history (including the current tool + # call + result being appended by pipecat) is preserved. + # Using LLMMessagesUpdateFrame would snapshot messages BEFORE + # pipecat appends the tool result, stripping it from context + # and causing a second spurious tool call on LLM continuation. current_messages = context.get_messages() - new_messages = [updated_system_message] + current_messages[1:] - await task.queue_frame( - LLMMessagesUpdateFrame(new_messages, run_llm=False) - ) + current_messages[0] = {'role': 'system', 'content': updated_content} + context.set_messages(current_messages) logger.info( f'Updated system prompt with {target_language} instruction' diff --git a/wavefront/server/apps/call_processing/call_processing/services/pipecat_service.py b/wavefront/server/apps/call_processing/call_processing/services/pipecat_service.py index a6319f86..9338d957 100644 --- a/wavefront/server/apps/call_processing/call_processing/services/pipecat_service.py +++ b/wavefront/server/apps/call_processing/call_processing/services/pipecat_service.py @@ -25,7 +25,6 @@ CancelFrame, EndFrame, ErrorFrame, - Frame, StopFrame, TTSSpeakFrame, BotSpeakingFrame, @@ -33,7 +32,6 @@ UserSpeakingFrame, UserStartedSpeakingFrame, ) -from pipecat.pipeline.parallel_pipeline import ParallelPipeline from pipecat.pipeline.pipeline import Pipeline from pipecat.pipeline.runner import PipelineRunner from pipecat.pipeline.task import PipelineParams, PipelineTask @@ -44,10 +42,6 @@ LLMUserAggregatorParams, UserTurnStoppedMessage, ) -from pipecat.processors.filters.function_filter import FunctionFilter -from pipecat.processors.transcript_processor import ( - TranscriptProcessor, -) # from pipecat.pipeline.service_switcher import ( # ServiceSwitcher, @@ -101,103 +95,6 @@ ) -class STTLanguageSwitcher(ParallelPipeline): - """ - ParallelPipeline that routes STT to different language-specific services - based on current language state. Same pattern as LanguageSwitcher for TTS. - """ - - def __init__( - self, - stt_services: Dict[str, Any], - supported_languages: List[str], - default_language: str, - ): - self._current_language = default_language - self._stt_services = stt_services - self._supported_languages = supported_languages - - # Build parallel routes: one per language - routes = [] - for lang_code in supported_languages: - filter_func = self._create_language_filter(lang_code) - stt_service = stt_services[lang_code] - routes.append( - [FunctionFilter(filter_func, filter_system_frames=True), stt_service] - ) - - super().__init__(*routes) - - def _create_language_filter(self, lang_code: str): - """Create filter function for specific language""" - - async def language_filter(_: Frame) -> bool: - return self._current_language == lang_code - - return language_filter - - @property - def current_language(self): - return self._current_language - - def set_language(self, language_code: str): - """Update current language (called by language detection tool)""" - if language_code in self._supported_languages: - self._current_language = language_code - logger.info(f'STTLanguageSwitcher: Language set to {language_code}') - else: - logger.warning(f'STTLanguageSwitcher: Invalid language {language_code}') - - -class LanguageSwitcher(ParallelPipeline): - """ - ParallelPipeline that routes TTS to different language-specific services - based on current language state. - """ - - def __init__( - self, - tts_services: Dict[str, Any], - supported_languages: List[str], - default_language: str, - ): - self._current_language = default_language - self._tts_services = tts_services - self._supported_languages = supported_languages - - # Build parallel routes: one per language - # Each route: [FunctionFilter, TTS service] - routes = [] - for lang_code in supported_languages: - filter_func = self._create_language_filter(lang_code) - tts_service = tts_services[lang_code] - routes.append( - [FunctionFilter(filter_func, filter_system_frames=True), tts_service] - ) - - super().__init__(*routes) - - def _create_language_filter(self, lang_code: str): - """Create filter function for specific language""" - - async def language_filter(_: Frame) -> bool: - return self._current_language == lang_code - - return language_filter - - @property - def current_language(self): - return self._current_language - - def set_language(self, language_code: str): - """Update current language (called by language detection tool)""" - if language_code in self._supported_languages: - self._current_language = language_code - logger.info(f'LanguageSwitcher: Language set to {language_code}') - else: - logger.warning(f'LanguageSwitcher: Invalid language {language_code}') - - class PipecatService: """Service for creating and running Pipecat pipelines""" @@ -275,74 +172,28 @@ async def run_conversation( 'parameters': stt_parameters or {}, } - # Create TTS services (one per language for multi-language mode) - tts_services = {} - if is_multi_language: logger.info( - f'Multi-language mode enabled for languages: {supported_languages}' + f'Multi-language mode enabled for languages: {supported_languages}. ' + f'Creating single TTS/STT service with default language: {default_language}' ) - # Create TTS services for each supported language - for lang_code in supported_languages: - # Get voice ID for this language - voice_id_for_lang = tts_voice_ids_dict.get(lang_code) - if not voice_id_for_lang: - logger.warning( - f'No voice ID for language {lang_code}, using default' - ) - voice_id_for_lang = default_voice_id - - # Deep clone config to avoid mutating original - tts_config_lang = deepcopy(tts_config_with_params) - - # Update language parameters - if 'parameters' not in tts_config_lang: - tts_config_lang['parameters'] = {} - tts_config_lang['parameters']['language'] = lang_code - tts_config_lang['voice_id'] = voice_id_for_lang - - # Create TTS service - tts_services[lang_code] = TTSServiceFactory.create_tts_service( - tts_config_lang - ) - logger.info( - f'Created TTS service for language: {lang_code} ' - f'with voice: {voice_id_for_lang}' - ) - - # Create per-language STT services (same pattern as TTS) - stt_services = {} - for lang_code in supported_languages: - stt_config_lang = deepcopy(stt_config_with_params) - if 'parameters' not in stt_config_lang: - stt_config_lang['parameters'] = {} - stt_config_lang['parameters']['language'] = lang_code - - stt_services[lang_code] = STTServiceFactory.create_stt_service( - stt_config_lang - ) - logger.info(f'Created STT service for language: {lang_code}') - - # Create STTLanguageSwitcher for STT routing - stt = STTLanguageSwitcher( - stt_services=stt_services, - supported_languages=supported_languages, - default_language=default_language, - ) - logger.info( - f'Initialized STTLanguageSwitcher with default language: {default_language}' + # Create a single TTS service with the default language; language switches + # are handled at runtime via TTSUpdateSettingsFrame / STTUpdateSettingsFrame + tts_config_lang = deepcopy(tts_config_with_params) + if 'parameters' not in tts_config_lang: + tts_config_lang['parameters'] = {} + tts_config_lang['parameters']['language'] = default_language + tts_config_lang['voice_id'] = tts_voice_ids_dict.get( + default_language, default_voice_id ) + tts = TTSServiceFactory.create_tts_service(tts_config_lang) - # Create LanguageSwitcher for TTS routing - tts = LanguageSwitcher( - tts_services=tts_services, - supported_languages=supported_languages, - default_language=default_language, - ) - logger.info( - f'Initialized LanguageSwitcher with default language: {default_language}' - ) + stt_config_lang = deepcopy(stt_config_with_params) + if 'parameters' not in stt_config_lang: + stt_config_lang['parameters'] = {} + stt_config_lang['parameters']['language'] = default_language + stt = STTServiceFactory.create_stt_service(stt_config_lang) else: logger.info('Single language mode - no language detection needed') @@ -414,8 +265,7 @@ async def run_conversation( { 'role': 'system', 'content': system_content, - }, - {'role': 'assistant', 'content': agent_config['welcome_message']}, + } ] # Load and register tools for this agent @@ -459,8 +309,9 @@ async def run_conversation( language_detection_func = ( LanguageDetectionToolFactory.create_language_detection_tool( task_container=task_container, - language_switcher=tts, # Pass the TTS LanguageSwitcher instance - stt_language_switcher=stt, # Pass the STT LanguageSwitcher instance + tts_provider=tts_config['provider'], + stt_provider=stt_config['provider'], + tts_voice_ids=tts_voice_ids_dict, context_container=context_container, supported_languages=supported_languages, default_language=default_language, @@ -570,9 +421,6 @@ async def run_conversation( ), ) - # Create transcript processor for language detection - transcript = TranscriptProcessor() - # --- Call evaluation: transcript log and stats --- transcript_log: List[Dict[str, Any]] = [] call_evaluation_tasks: List[asyncio.Task] = [] @@ -624,13 +472,11 @@ async def on_assistant_turn_stopped( # Build pipeline components list pipeline_components = [ transport.input(), # Audio input from Twilio - stt, # Speech-to-Text (ServiceSwitcher for multi-lang, direct for single) - transcript.user(), # Transcript processor for user messages + stt, # Speech-to-Text context_aggregator.user(), # Add user message to context llm, # LLM processing - tts, # Text-to-Speech (ServiceSwitcher for multi-lang, direct for single) + tts, # Text-to-Speech transport.output(), # Audio output to Twilio - transcript.assistant(), # Transcript processor for assistant messages context_aggregator.assistant(), # Add assistant response to context ] @@ -734,7 +580,9 @@ async def on_pipeline_finished(task, frame): @transport.event_handler('on_client_connected') async def on_client_connected(transport, client): logger.info(f"Client connected for agent: {agent_config['name']}") - await task.queue_frame(TTSSpeakFrame(agent_config['welcome_message'])) + await task.queue_frame( + TTSSpeakFrame(agent_config['welcome_message'], append_to_context=True) + ) @transport.event_handler('on_client_disconnected') async def on_client_disconnected(transport, client): diff --git a/wavefront/server/apps/call_processing/call_processing/services/stt_service.py b/wavefront/server/apps/call_processing/call_processing/services/stt_service.py index 65255e6a..0b209a29 100644 --- a/wavefront/server/apps/call_processing/call_processing/services/stt_service.py +++ b/wavefront/server/apps/call_processing/call_processing/services/stt_service.py @@ -7,18 +7,20 @@ from typing import Dict, Any from call_processing.log.logger import logger -# Pipecat STT services -from pipecat.services.deepgram.stt import DeepgramSTTService -from pipecat.services.sarvam.stt import SarvamSTTService -from pipecat.services.elevenlabs.stt import ElevenLabsRealtimeSTTService +# Pipecat STT services and their Settings classes +from pipecat.services.deepgram.stt import DeepgramSTTService, DeepgramSTTSettings +from pipecat.services.sarvam.stt import SarvamSTTService, SarvamSTTSettings +from pipecat.services.elevenlabs.stt import ( + ElevenLabsRealtimeSTTService, + ElevenLabsRealtimeSTTSettings, +) +from pipecat.services.azure.stt import AzureSTTService, AzureSTTSettings # Pipecat language enum from pipecat.transcriptions.language import Language -# Deepgram options -from deepgram import LiveOptions - -from pipecat.services.azure.stt import AzureSTTService +# Frames +from pipecat.frames.frames import STTUpdateSettingsFrame class STTServiceFactory: @@ -71,50 +73,39 @@ def create_stt_service(stt_config: Dict[str, Any]): @staticmethod def _create_deepgram_stt(api_key: str, parameters: Dict[str, Any]): """Create Deepgram STT service""" - # Build LiveOptions from the parameters dict - options_dict = {} + # Runtime-updatable settings + settings_kwargs: Dict[str, Any] = { + 'model': parameters.get('model', 'nova-2'), + 'interim_results': parameters.get('interim_results', True), + } - # Add parameters from config - if 'model' in parameters: - options_dict['model'] = parameters['model'] if 'language' in parameters: - options_dict['language'] = parameters['language'] - if 'interim_results' in parameters: - options_dict['interim_results'] = parameters['interim_results'] - if 'encoding' in parameters: - options_dict['encoding'] = parameters['encoding'] - if 'sample_rate' in parameters: - options_dict['sample_rate'] = parameters['sample_rate'] - # if 'endpointing' in parameters: # using pipecat VAD + smart turn detection - # options_dict['endpointing'] = parameters['endpointing'] - if 'channels' in parameters: - options_dict['channels'] = parameters['channels'] + settings_kwargs['language'] = parameters['language'] if 'smart_format' in parameters: - options_dict['smart_format'] = parameters['smart_format'] + settings_kwargs['smart_format'] = parameters['smart_format'] if 'punctuate' in parameters: - options_dict['punctuate'] = parameters['punctuate'] + settings_kwargs['punctuate'] = parameters['punctuate'] if 'profanity_filter' in parameters: - options_dict['profanity_filter'] = parameters['profanity_filter'] - # if 'vad_events' in parameters: # depreceated in pipecat 0.99+ - # options_dict['vad_events'] = parameters['vad_events'] - - # Set smart defaults if not provided - options_dict.setdefault( - 'interim_results', True - ) # Always enable for faster feedback - # options_dict.setdefault('endpointing', 300) # 300ms = faster cutoff - options_dict.setdefault('encoding', 'linear16') - options_dict.setdefault('sample_rate', 8000) - options_dict.setdefault('model', 'nova-2') - - # Create LiveOptions object - live_options = LiveOptions(**options_dict) - - logger.info( - f"Deepgram STT config: model={options_dict.get('model', 'default')}" - ) + settings_kwargs['profanity_filter'] = parameters['profanity_filter'] + + # Init-level params (not runtime-updatable) + kwargs: Dict[str, Any] = { + 'api_key': api_key, + 'encoding': parameters.get('encoding', 'linear16'), + } + if 'sample_rate' in parameters: + kwargs['sample_rate'] = parameters['sample_rate'] + else: + kwargs['sample_rate'] = 8000 + if 'channels' in parameters: + kwargs['channels'] = parameters['channels'] + + logger.info(f"Deepgram STT config: model={settings_kwargs['model']}") - return DeepgramSTTService(api_key=api_key, live_options=live_options) + return DeepgramSTTService( + **kwargs, + settings=DeepgramSTTSettings(**settings_kwargs), + ) # Mapping of short language codes to pipecat Language enum for Sarvam SARVAM_LANGUAGE_MAP = { @@ -134,36 +125,31 @@ def _create_deepgram_stt(api_key: str, parameters: Dict[str, Any]): @staticmethod def _create_sarvam_stt(api_key: str, parameters: Dict[str, Any]): """Create Sarvam STT service""" - params_dict = {} + settings_kwargs: Dict[str, Any] = {} - # Map language code to pipecat Language enum if 'language' in parameters and parameters['language']: lang_code = parameters['language'] lang_enum = STTServiceFactory.SARVAM_LANGUAGE_MAP.get(lang_code) if lang_enum: - params_dict['language'] = lang_enum + settings_kwargs['language'] = lang_enum else: logger.warning(f"Unknown Sarvam language '{lang_code}', skipping") if 'vad_signals' in parameters: - params_dict['vad_signals'] = parameters['vad_signals'] + settings_kwargs['vad_signals'] = parameters['vad_signals'] if 'high_vad_sensitivity' in parameters: - params_dict['high_vad_sensitivity'] = parameters['high_vad_sensitivity'] + settings_kwargs['high_vad_sensitivity'] = parameters['high_vad_sensitivity'] model = parameters.get('model', 'saarika:v2.5') sample_rate = parameters.get('sample_rate', 8000) - input_params = ( - SarvamSTTService.InputParams(**params_dict) if params_dict else None - ) - logger.info(f'Sarvam STT config: model={model}, sample_rate={sample_rate}') return SarvamSTTService( api_key=api_key, model=model, sample_rate=sample_rate, - params=input_params, + settings=SarvamSTTSettings(**settings_kwargs) if settings_kwargs else None, ) # Mapping of short language codes to ElevenLabs ISO-639-3 language codes @@ -198,14 +184,13 @@ def _create_sarvam_stt(api_key: str, parameters: Dict[str, Any]): @staticmethod def _create_elevenlabs_stt(api_key: str, parameters: Dict[str, Any]): """Create ElevenLabs Realtime STT service (WebSocket streaming, scribe_v2_realtime)""" - params_dict = {} + settings_kwargs: Dict[str, Any] = {} - # Map language code to ElevenLabs ISO-639-3 code if 'language' in parameters and parameters['language']: lang_code = parameters['language'] - elevenlabs_lang = STTServiceFactory.ELEVENLABS_LANGUAGE_MAP.get(lang_code) - if elevenlabs_lang: - params_dict['language_code'] = elevenlabs_lang + lang_code_iso = STTServiceFactory.ELEVENLABS_LANGUAGE_MAP.get(lang_code) + if lang_code_iso: + settings_kwargs['language'] = lang_code_iso else: logger.warning( f"Unknown ElevenLabs language '{lang_code}', skipping (auto-detect will be used)" @@ -214,19 +199,15 @@ def _create_elevenlabs_stt(api_key: str, parameters: Dict[str, Any]): model = parameters.get('model', 'scribe_v2_realtime') sample_rate = parameters.get('sample_rate', 8000) - input_params = ( - ElevenLabsRealtimeSTTService.InputParams(**params_dict) - if params_dict - else None - ) - logger.info(f'ElevenLabs STT config: model={model}, sample_rate={sample_rate}') return ElevenLabsRealtimeSTTService( api_key=api_key, model=model, sample_rate=sample_rate, - params=input_params, + settings=ElevenLabsRealtimeSTTSettings(**settings_kwargs) + if settings_kwargs + else None, ) @staticmethod @@ -235,7 +216,7 @@ def _create_azure_stt(api_key: str, region: str, parameters: Dict[str, Any]): if not region: raise ValueError("Azure STT requires 'region' to be set in the STT config") - kwargs = { + kwargs: Dict[str, Any] = { 'api_key': api_key, 'region': region, } @@ -250,11 +231,12 @@ def _create_azure_stt(api_key: str, region: str, parameters: Dict[str, Any]): ): kwargs['ttfs_p99_latency'] = parameters['ttfs_p99_latency'] + settings_kwargs: Dict[str, Any] = {} if 'language' in parameters and parameters['language']: lang_code = parameters['language'] lang_enum = STTServiceFactory.AZURE_LANGUAGE_MAP.get(lang_code) if lang_enum: - kwargs['language'] = lang_enum + settings_kwargs['language'] = lang_enum else: logger.warning( f"Unknown Azure language '{lang_code}', using service default" @@ -262,7 +244,41 @@ def _create_azure_stt(api_key: str, region: str, parameters: Dict[str, Any]): logger.info(f'Azure STT config: region={region}') - return AzureSTTService(**kwargs) + return AzureSTTService( + **kwargs, + settings=AzureSTTSettings(**settings_kwargs) if settings_kwargs else None, + ) + + @staticmethod + def create_language_update_frame(provider: str, lang_code: str): + """Create STTUpdateSettingsFrame for a runtime language switch, provider-aware.""" + if provider == 'deepgram': + return STTUpdateSettingsFrame(delta=DeepgramSTTSettings(language=lang_code)) + elif provider == 'azure': + lang_enum = STTServiceFactory.AZURE_LANGUAGE_MAP.get(lang_code) + if not lang_enum: + logger.warning(f"No Azure STT language mapping for '{lang_code}'") + return None + return STTUpdateSettingsFrame(delta=AzureSTTSettings(language=lang_enum)) + elif provider == 'sarvam': + lang_enum = STTServiceFactory.SARVAM_LANGUAGE_MAP.get(lang_code) + if not lang_enum: + logger.warning(f"No Sarvam STT language mapping for '{lang_code}'") + return None + return STTUpdateSettingsFrame(delta=SarvamSTTSettings(language=lang_enum)) + elif provider == 'elevenlabs': + lang_code_iso = STTServiceFactory.ELEVENLABS_LANGUAGE_MAP.get(lang_code) + if not lang_code_iso: + logger.warning(f"No ElevenLabs STT language mapping for '{lang_code}'") + return None + return STTUpdateSettingsFrame( + delta=ElevenLabsRealtimeSTTSettings(language=lang_code_iso) + ) + else: + logger.warning( + f"STT provider '{provider}' does not support runtime language updates" + ) + return None @staticmethod def _create_assemblyai_stt(api_key: str, parameters: Dict[str, Any]): diff --git a/wavefront/server/apps/call_processing/call_processing/services/tts_service.py b/wavefront/server/apps/call_processing/call_processing/services/tts_service.py index b0360373..24d3e806 100644 --- a/wavefront/server/apps/call_processing/call_processing/services/tts_service.py +++ b/wavefront/server/apps/call_processing/call_processing/services/tts_service.py @@ -8,15 +8,17 @@ from call_processing.log.logger import logger # Pipecat TTS services -from pipecat.services.elevenlabs.tts import ElevenLabsTTSService -from pipecat.services.deepgram.tts import DeepgramTTSService -from pipecat.services.cartesia.tts import CartesiaTTSService -from pipecat.services.sarvam.tts import SarvamTTSService +from pipecat.services.elevenlabs.tts import ElevenLabsTTSService, ElevenLabsTTSSettings +from pipecat.services.deepgram.tts import DeepgramTTSService, DeepgramTTSSettings +from pipecat.services.cartesia.tts import CartesiaTTSService, CartesiaTTSSettings +from pipecat.services.sarvam.tts import SarvamTTSService, SarvamTTSSettings +from pipecat.services.azure.tts import AzureTTSService, AzureTTSSettings # Language for params from pipecat.transcriptions.language import Language -from pipecat.services.azure.tts import AzureTTSService +# Frames +from pipecat.frames.frames import TTSUpdateSettingsFrame class TTSServiceFactory: @@ -88,57 +90,49 @@ def create_tts_service(tts_config: Dict[str, Any]): @staticmethod def _create_elevenlabs_tts(api_key: str, voice_id: str, parameters: Dict[str, Any]): """Create ElevenLabs TTS service""" - # Model is a direct parameter, not in InputParams model = parameters.get('model', 'eleven_turbo_v2_5') - # Build InputParams from the parameters dict - params_dict = {} + settings_kwargs: Dict[str, Any] = { + 'voice': voice_id, + 'model': model, + } if 'language' in parameters: - # Convert string to Language enum if needed lang = parameters['language'] if isinstance(lang, str): try: - params_dict['language'] = Language(lang) + settings_kwargs['language'] = Language(lang) except ValueError: logger.warning(f"Unknown language '{lang}', skipping") else: - params_dict['language'] = lang + settings_kwargs['language'] = lang if 'stability' in parameters: - params_dict['stability'] = parameters['stability'] + settings_kwargs['stability'] = parameters['stability'] if 'similarity_boost' in parameters: - params_dict['similarity_boost'] = parameters['similarity_boost'] + settings_kwargs['similarity_boost'] = parameters['similarity_boost'] if 'style' in parameters: - params_dict['style'] = parameters['style'] + settings_kwargs['style'] = parameters['style'] if 'use_speaker_boost' in parameters: - params_dict['use_speaker_boost'] = parameters['use_speaker_boost'] + settings_kwargs['use_speaker_boost'] = parameters['use_speaker_boost'] if 'speed' in parameters: - params_dict['speed'] = parameters['speed'] - - # Create InputParams object (only if we have params) - input_params = ( - ElevenLabsTTSService.InputParams(**params_dict) if params_dict else None - ) + settings_kwargs['speed'] = parameters['speed'] logger.info( f"ElevenLabs TTS config: model={model}, " - f"stability={params_dict.get('stability', 'default')}" + f"stability={settings_kwargs.get('stability', 'default')}" ) return ElevenLabsTTSService( - api_key=api_key, voice_id=voice_id, model=model, params=input_params + api_key=api_key, + settings=ElevenLabsTTSSettings(**settings_kwargs), ) @staticmethod def _create_deepgram_tts(api_key: str, voice_id: str, parameters: Dict[str, Any]): """Create Deepgram TTS service""" - kwargs = { - 'api_key': api_key, - 'voice': voice_id, # voice_id IS the model (e.g., "aura-2-helena-en") - } + kwargs: Dict[str, Any] = {'api_key': api_key} - # Optional parameters if 'base_url' in parameters: kwargs['base_url'] = parameters['base_url'] if 'encoding' in parameters: @@ -147,40 +141,36 @@ def _create_deepgram_tts(api_key: str, voice_id: str, parameters: Dict[str, Any] kwargs['sample_rate'] = parameters['sample_rate'] logger.info(f'Deepgram TTS config: voice={voice_id}') - return DeepgramTTSService(**kwargs) + return DeepgramTTSService( + **kwargs, + settings=DeepgramTTSSettings(voice=voice_id), + ) @staticmethod def _create_cartesia_tts(api_key: str, voice_id: str, parameters: Dict[str, Any]): """Create Cartesia TTS service""" - # Model is a direct parameter model = parameters.get('model', 'sonic-2') - # Build InputParams from the parameters dict - params_dict = {} + settings_kwargs: Dict[str, Any] = { + 'voice': voice_id, + 'model': model, + } if 'language' in parameters: - # Convert string to Language enum if needed lang = parameters['language'] if isinstance(lang, str): try: - params_dict['language'] = Language(lang) + settings_kwargs['language'] = Language(lang) except ValueError: logger.warning(f"Unknown language '{lang}', skipping") else: - params_dict['language'] = lang - - if 'speed' in parameters: - params_dict['speed'] = parameters['speed'] - - # Create InputParams object (only if we have params) - input_params = ( - CartesiaTTSService.InputParams(**params_dict) if params_dict else None - ) + settings_kwargs['language'] = lang logger.info(f'Cartesia TTS config: voice={voice_id}, model={model}') return CartesiaTTSService( - api_key=api_key, voice_id=voice_id, model=model, params=input_params + api_key=api_key, + settings=CartesiaTTSSettings(**settings_kwargs), ) # Mapping of short language codes to pipecat Language enum for Sarvam @@ -202,37 +192,38 @@ def _create_cartesia_tts(api_key: str, voice_id: str, parameters: Dict[str, Any] def _create_sarvam_tts(api_key: str, voice_id: str, parameters: Dict[str, Any]): """Create Sarvam TTS service (WebSocket-based streaming)""" model = parameters.get('model', 'bulbul:v2') + sample_rate = parameters.get('sample_rate') - # Build InputParams from the parameters dict - params_dict = {} + settings_kwargs: Dict[str, Any] = { + 'voice': voice_id, + 'model': model, + } if 'language' in parameters and parameters['language']: lang_code = parameters['language'] lang_enum = TTSServiceFactory.SARVAM_LANGUAGE_MAP.get(lang_code) if lang_enum: - params_dict['language'] = lang_enum + settings_kwargs['language'] = lang_enum else: logger.warning(f"Unknown Sarvam language '{lang_code}', skipping") if 'pitch' in parameters: - params_dict['pitch'] = parameters['pitch'] + settings_kwargs['pitch'] = parameters['pitch'] if 'pace' in parameters: - params_dict['pace'] = parameters['pace'] + settings_kwargs['pace'] = parameters['pace'] if 'loudness' in parameters: - params_dict['loudness'] = parameters['loudness'] + settings_kwargs['loudness'] = parameters['loudness'] if 'enable_preprocessing' in parameters: - params_dict['enable_preprocessing'] = parameters['enable_preprocessing'] + settings_kwargs['enable_preprocessing'] = parameters['enable_preprocessing'] if 'temperature' in parameters: - params_dict['temperature'] = parameters['temperature'] - - input_params = ( - SarvamTTSService.InputParams(**params_dict) if params_dict else None - ) + settings_kwargs['temperature'] = parameters['temperature'] logger.info(f'Sarvam TTS config: voice={voice_id}, model={model}') return SarvamTTSService( - api_key=api_key, voice_id=voice_id, model=model, params=input_params + api_key=api_key, + sample_rate=sample_rate, + settings=SarvamTTSSettings(**settings_kwargs), ) @staticmethod @@ -243,42 +234,100 @@ def _create_azure_tts( if not region: raise ValueError("Azure TTS requires 'region' to be set in the TTS config") - params_dict = {} + settings_kwargs: Dict[str, Any] = {'voice': voice_id} if 'language' in parameters and parameters['language']: lang_code = parameters['language'] lang_enum = TTSServiceFactory.AZURE_LANGUAGE_MAP.get(lang_code) if lang_enum: - params_dict['language'] = lang_enum + settings_kwargs['language'] = lang_enum else: logger.warning( f"Unknown Azure language '{lang_code}', using service default" ) + if 'style' in parameters and parameters['style']: - params_dict['style'] = parameters['style'] + settings_kwargs['style'] = parameters['style'] if 'style_degree' in parameters and parameters['style_degree']: - params_dict['style_degree'] = parameters['style_degree'] + settings_kwargs['style_degree'] = parameters['style_degree'] if 'role' in parameters and parameters['role']: - params_dict['role'] = parameters['role'] + settings_kwargs['role'] = parameters['role'] if 'rate' in parameters and parameters['rate']: - params_dict['rate'] = parameters['rate'] + settings_kwargs['rate'] = parameters['rate'] if 'pitch' in parameters and parameters['pitch']: - params_dict['pitch'] = parameters['pitch'] + settings_kwargs['pitch'] = parameters['pitch'] if 'volume' in parameters and parameters['volume']: - params_dict['volume'] = parameters['volume'] + settings_kwargs['volume'] = parameters['volume'] - kwargs = { + kwargs: Dict[str, Any] = { 'api_key': api_key, 'region': region, - 'voice': voice_id, } - if params_dict: - kwargs['params'] = AzureTTSService.InputParams(**params_dict) - if 'sample_rate' in parameters and parameters['sample_rate']: kwargs['sample_rate'] = parameters['sample_rate'] logger.info(f'Azure TTS config: voice={voice_id}, region={region}') - return AzureTTSService(**kwargs) + return AzureTTSService(**kwargs, settings=AzureTTSSettings(**settings_kwargs)) + + @staticmethod + def create_language_update_frame( + provider: str, lang_code: str, voice_id: str = None + ): + """Create TTSUpdateSettingsFrame for a runtime language+voice switch, provider-aware.""" + if provider == 'elevenlabs': + # Language is implicit from the voice model; only update voice + if not voice_id: + logger.warning( + 'ElevenLabs TTS: no voice_id provided for language update' + ) + return None + return TTSUpdateSettingsFrame(delta=ElevenLabsTTSSettings(voice=voice_id)) + elif provider == 'deepgram': + if not voice_id: + logger.warning('Deepgram TTS: no voice_id provided for language update') + return None + return TTSUpdateSettingsFrame(delta=DeepgramTTSSettings(voice=voice_id)) + elif provider == 'cartesia': + delta_kwargs: Dict[str, Any] = {} + if voice_id: + delta_kwargs['voice'] = voice_id + try: + delta_kwargs['language'] = Language(lang_code) + except ValueError: + logger.warning( + f"Unknown Cartesia language '{lang_code}', skipping language update" + ) + if not delta_kwargs: + return None + return TTSUpdateSettingsFrame(delta=CartesiaTTSSettings(**delta_kwargs)) + elif provider == 'azure': + delta_kwargs = {} + if voice_id: + delta_kwargs['voice'] = voice_id + lang_enum = TTSServiceFactory.AZURE_LANGUAGE_MAP.get(lang_code) + if lang_enum: + delta_kwargs['language'] = lang_enum + else: + logger.warning(f"No Azure TTS language mapping for '{lang_code}'") + if not delta_kwargs: + return None + return TTSUpdateSettingsFrame(delta=AzureTTSSettings(**delta_kwargs)) + elif provider == 'sarvam': + delta_kwargs = {} + if voice_id: + delta_kwargs['voice'] = voice_id + lang_enum = TTSServiceFactory.SARVAM_LANGUAGE_MAP.get(lang_code) + if lang_enum: + delta_kwargs['language'] = lang_enum + else: + logger.warning(f"No Sarvam TTS language mapping for '{lang_code}'") + if not delta_kwargs: + return None + return TTSUpdateSettingsFrame(delta=SarvamTTSSettings(**delta_kwargs)) + else: + logger.warning( + f"TTS provider '{provider}' does not support runtime language updates" + ) + return None diff --git a/wavefront/server/apps/call_processing/pyproject.toml b/wavefront/server/apps/call_processing/pyproject.toml index 8e7f4644..aa4d8c43 100644 --- a/wavefront/server/apps/call_processing/pyproject.toml +++ b/wavefront/server/apps/call_processing/pyproject.toml @@ -21,7 +21,7 @@ dependencies = [ "redis>=5.0.0", "tenacity>=8.0.0", # Pipecat and voice processing - "pipecat-ai[websocket,cartesia,google,silero,deepgram,groq,runner,azure,local-smart-turn-v3,sarvam,tracing]==0.0.103", + "pipecat-ai[websocket,cartesia,google,silero,deepgram,groq,runner,azure,sarvam,tracing]==0.0.106", "opentelemetry-exporter-otlp-proto-grpc>=1.0.0", "opentelemetry-exporter-otlp-proto-http>=1.0.0", # Twilio diff --git a/wavefront/server/uv.lock b/wavefront/server/uv.lock index d295378f..0e7887d8 100644 --- a/wavefront/server/uv.lock +++ b/wavefront/server/uv.lock @@ -65,15 +65,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/b0/5e/80cee674cdbe529ef008721d7eebb50ae5def4314211d82123aa23e828f8/accelerate-0.34.2-py3-none-any.whl", hash = "sha256:d69159e2c4e4a473d14443b27d2d732929254e826b3ab4813b3785b5ac616c7c", size = 324366, upload-time = "2024-09-05T16:45:17.121Z" }, ] -[[package]] -name = "aenum" -version = "3.1.16" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/09/7a/61ed58e8be9e30c3fe518899cc78c284896d246d51381bab59b5db11e1f3/aenum-3.1.16.tar.gz", hash = "sha256:bfaf9589bdb418ee3a986d85750c7318d9d2839c1b1a1d6fe8fc53ec201cf140", size = 137693, upload-time = "2026-01-12T22:34:38.819Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e3/52/6ad8f63ec8da1bf40f96996d25d5b650fdd38f5975f8c813732c47388f18/aenum-3.1.16-py3-none-any.whl", hash = "sha256:9035092855a98e41b66e3d0998bd7b96280e85ceb3a04cc035636138a1943eaf", size = 165627, upload-time = "2025-04-25T03:17:58.89Z" }, -] - [[package]] name = "agents-module" version = "0.1.0" @@ -627,7 +618,7 @@ dependencies = [ { name = "httpx" }, { name = "opentelemetry-exporter-otlp-proto-grpc" }, { name = "opentelemetry-exporter-otlp-proto-http" }, - { name = "pipecat-ai", extra = ["azure", "cartesia", "deepgram", "google", "groq", "local-smart-turn-v3", "runner", "sarvam", "silero", "tracing", "websocket"] }, + { name = "pipecat-ai", extra = ["azure", "cartesia", "deepgram", "google", "groq", "runner", "sarvam", "tracing", "websocket"] }, { name = "pydantic" }, { name = "python-dotenv" }, { name = "python-multipart" }, @@ -644,7 +635,7 @@ requires-dist = [ { name = "httpx", specifier = ">=0.27.0" }, { name = "opentelemetry-exporter-otlp-proto-grpc", specifier = ">=1.0.0" }, { name = "opentelemetry-exporter-otlp-proto-http", specifier = ">=1.0.0" }, - { name = "pipecat-ai", extras = ["websocket", "cartesia", "google", "silero", "deepgram", "groq", "runner", "azure", "local-smart-turn-v3", "sarvam", "tracing"], specifier = "==0.0.103" }, + { name = "pipecat-ai", extras = ["websocket", "cartesia", "google", "silero", "deepgram", "groq", "runner", "azure", "sarvam", "tracing"], specifier = "==0.0.106" }, { name = "pydantic", specifier = ">=2.0.0" }, { name = "python-dotenv", specifier = ">=1.1.0,<2.0.0" }, { name = "python-multipart", specifier = ">=0.0.9" }, @@ -654,27 +645,6 @@ requires-dist = [ { name = "uvicorn", specifier = ">=0.30.5,<1.0.0" }, ] -[[package]] -name = "cartesia" -version = "2.0.17" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "aiohttp" }, - { name = "audioop-lts", marker = "python_full_version >= '3.13' and python_full_version < '4'" }, - { name = "httpx" }, - { name = "httpx-sse" }, - { name = "iterators" }, - { name = "pydantic" }, - { name = "pydantic-core" }, - { name = "pydub" }, - { name = "typing-extensions" }, - { name = "websockets" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/fa/ff/bfd3191a7fdbbb5c4dfe4d34461c6aa0d158a6eea599cb9a5df2c91109fa/cartesia-2.0.17.tar.gz", hash = "sha256:fd7fcdcbb5aac47ff6b35cd48420b4993ef1742aaa71bb7d52b335314045d584", size = 79227, upload-time = "2025-11-13T21:06:45.332Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/52/9c/f7b83329e0567d0ab165abd81405108d146abc9728732c1af3858ee38bfd/cartesia-2.0.17-py3-none-any.whl", hash = "sha256:de8975ced1c5c09f1b51bb87ceea6c1641ba817901cfc73c47fc4e37c6ca351a", size = 153376, upload-time = "2025-11-13T21:06:42.872Z" }, -] - [[package]] name = "certifi" version = "2025.8.3" @@ -977,19 +947,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/94/35/386550fd60316d1e37eccdda609b074113298f23cef5bddb2049823fe666/dacite-1.9.2-py3-none-any.whl", hash = "sha256:053f7c3f5128ca2e9aceb66892b1a3c8936d02c686e707bee96e19deef4bc4a0", size = 16600, upload-time = "2025-02-05T09:27:24.345Z" }, ] -[[package]] -name = "dataclasses-json" -version = "0.6.7" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "marshmallow" }, - { name = "typing-inspect" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/64/a4/f71d9cf3a5ac257c993b5ca3f93df5f7fb395c725e7f1e6479d2514173c3/dataclasses_json-0.6.7.tar.gz", hash = "sha256:b6b3e528266ea45b9535223bc53ca645f5208833c29229e847b3f26a1cc55fc0", size = 32227, upload-time = "2024-06-09T16:20:19.103Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/c3/be/d0d44e092656fe7a06b55e6103cbce807cdbdee17884a5367c68c9860853/dataclasses_json-0.6.7-py3-none-any.whl", hash = "sha256:0dbf33f26c8d5305befd61b39d2b3414e8a407bedc2834dea9b8d642666fb40a", size = 28686, upload-time = "2024-06-09T16:20:16.715Z" }, -] - [[package]] name = "datasource" version = "0.1.0" @@ -1030,21 +987,18 @@ requires-dist = [ [[package]] name = "deepgram-sdk" -version = "4.7.0" +version = "6.0.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "aenum" }, - { name = "aiofiles" }, - { name = "aiohttp" }, - { name = "dataclasses-json" }, - { name = "deprecation" }, { name = "httpx" }, + { name = "pydantic" }, + { name = "pydantic-core" }, { name = "typing-extensions" }, { name = "websockets" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/17/c7/3c5918c2c74e3d56cf3d738aa174bc688c73069dc9682fc1bfaeb2058cc6/deepgram_sdk-4.7.0.tar.gz", hash = "sha256:e371396d8835d449782df472c3bd501f6cad41b3c925f66771933ff3fc4b1a13", size = 100128, upload-time = "2025-07-21T15:43:56.705Z" } +sdist = { url = "https://files.pythonhosted.org/packages/73/46/6dc45de574d766a20853452d7beccf17cb0cfeb685a0f03460f1fe49b48e/deepgram_sdk-6.0.1.tar.gz", hash = "sha256:88558a43d6173a861c8b6d6491b9ee8805679fb09fb81ef51eeb6871dad77767", size = 176743, upload-time = "2026-02-24T13:52:17.163Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/33/63/43a6e46b35eae9739e22b5cace4a22ece76d4aff74b563563b9507411484/deepgram_sdk-4.7.0-py3-none-any.whl", hash = "sha256:1a2a0890aa43cbc510e07b0f911f6841770ca0222e6fcc069bd3e2afcde1c061", size = 157911, upload-time = "2025-07-21T15:43:55.695Z" }, + { url = "https://files.pythonhosted.org/packages/58/a4/53b9075816edc566694aed014d9864febedf232677b74f5d30bdde64b5de/deepgram_sdk-6.0.1-py3-none-any.whl", hash = "sha256:1b33d621b1c0b1d7a6a7b46fdc393aef4212e670521fada99764f5fb3f9d55fd", size = 490751, upload-time = "2026-02-24T13:52:15.998Z" }, ] [[package]] @@ -1066,18 +1020,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/7c/2f/41598584075fef9e2bc33c102ba2e0b91ffb207d914b19402d3abf566de8/dependency_injector-4.48.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:05ff29398e23a08e840c9a89a0b516d988b337a38534d33791857bd1defd2d23", size = 1623553, upload-time = "2025-09-19T10:19:40.947Z" }, ] -[[package]] -name = "deprecation" -version = "2.1.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "packaging" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/5a/d3/8ae2869247df154b64c1884d7346d412fed0c49df84db635aab2d1c40e62/deprecation-2.1.0.tar.gz", hash = "sha256:72b3bde64e5d778694b0cf68178aed03d15e15477116add3fb773e581f9518ff", size = 173788, upload-time = "2020-04-20T14:23:38.738Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/02/c3/253a89ee03fc9b9682f1541728eb66db7db22148cd94f89ab22528cd1e1b/deprecation-2.1.0-py2.py3-none-any.whl", hash = "sha256:a10811591210e1fb0e768a8c25517cabeabcba6f0bf96564f8ff45189f90b14a", size = 11178, upload-time = "2020-04-20T14:23:36.581Z" }, -] - [[package]] name = "distlib" version = "0.4.0" @@ -1609,15 +1551,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/47/71/70db47e4f6ce3e5c37a607355f80da8860a33226be640226ac52cb05ef2e/fsspec-2025.9.0-py3-none-any.whl", hash = "sha256:530dc2a2af60a414a832059574df4a6e10cce927f6f4a78209390fe38955cfb7", size = 199289, upload-time = "2025-09-02T19:10:47.708Z" }, ] -[[package]] -name = "future" -version = "1.0.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a7/b2/4140c69c6a66432916b26158687e821ba631a4c9273c474343badf84d3ba/future-1.0.0.tar.gz", hash = "sha256:bd2968309307861edae1458a4f8a4f3598c03be43b97521076aebf5d94c07b05", size = 1228490, upload-time = "2024-02-21T11:52:38.461Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/da/71/ae30dadffc90b9006d77af76b393cb9dfbfc9629f339fc1574a1c52e6806/future-1.0.0-py3-none-any.whl", hash = "sha256:929292d34f5872e70396626ef385ec22355a1fae8ad29e1a734c3e43f9fbc216", size = 491326, upload-time = "2024-02-21T11:52:35.956Z" }, -] - [[package]] name = "gold-module" version = "0.1.0" @@ -1951,6 +1884,7 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/a4/de/f28ced0a67749cac23fecb02b694f6473f47686dff6afaa211d186e2ef9c/greenlet-3.2.4-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:96378df1de302bc38e99c3a9aa311967b7dc80ced1dcc6f171e99842987882a2", size = 272305, upload-time = "2025-08-07T13:15:41.288Z" }, { url = "https://files.pythonhosted.org/packages/09/16/2c3792cba130000bf2a31c5272999113f4764fd9d874fb257ff588ac779a/greenlet-3.2.4-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:1ee8fae0519a337f2329cb78bd7a8e128ec0f881073d43f023c7b8d4831d5246", size = 632472, upload-time = "2025-08-07T13:42:55.044Z" }, { url = "https://files.pythonhosted.org/packages/ae/8f/95d48d7e3d433e6dae5b1682e4292242a53f22df82e6d3dda81b1701a960/greenlet-3.2.4-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:94abf90142c2a18151632371140b3dba4dee031633fe614cb592dbb6c9e17bc3", size = 644646, upload-time = "2025-08-07T13:45:26.523Z" }, + { url = "https://files.pythonhosted.org/packages/d5/5e/405965351aef8c76b8ef7ad370e5da58d57ef6068df197548b015464001a/greenlet-3.2.4-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:4d1378601b85e2e5171b99be8d2dc85f594c79967599328f95c1dc1a40f1c633", size = 640519, upload-time = "2025-08-07T13:53:13.928Z" }, { url = "https://files.pythonhosted.org/packages/25/5d/382753b52006ce0218297ec1b628e048c4e64b155379331f25a7316eb749/greenlet-3.2.4-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0db5594dce18db94f7d1650d7489909b57afde4c580806b8d9203b6e79cdc079", size = 639707, upload-time = "2025-08-07T13:18:27.146Z" }, { url = "https://files.pythonhosted.org/packages/1f/8e/abdd3f14d735b2929290a018ecf133c901be4874b858dd1c604b9319f064/greenlet-3.2.4-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2523e5246274f54fdadbce8494458a2ebdcdbc7b802318466ac5606d3cded1f8", size = 587684, upload-time = "2025-08-07T13:18:25.164Z" }, { url = "https://files.pythonhosted.org/packages/5d/65/deb2a69c3e5996439b0176f6651e0052542bb6c8f8ec2e3fba97c9768805/greenlet-3.2.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:1987de92fec508535687fb807a5cea1560f6196285a4cde35c100b8cd632cc52", size = 1116647, upload-time = "2025-08-07T13:42:38.655Z" }, @@ -1961,6 +1895,7 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/44/69/9b804adb5fd0671f367781560eb5eb586c4d495277c93bde4307b9e28068/greenlet-3.2.4-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:3b67ca49f54cede0186854a008109d6ee71f66bd57bb36abd6d0a0267b540cdd", size = 274079, upload-time = "2025-08-07T13:15:45.033Z" }, { url = "https://files.pythonhosted.org/packages/46/e9/d2a80c99f19a153eff70bc451ab78615583b8dac0754cfb942223d2c1a0d/greenlet-3.2.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ddf9164e7a5b08e9d22511526865780a576f19ddd00d62f8a665949327fde8bb", size = 640997, upload-time = "2025-08-07T13:42:56.234Z" }, { url = "https://files.pythonhosted.org/packages/3b/16/035dcfcc48715ccd345f3a93183267167cdd162ad123cd93067d86f27ce4/greenlet-3.2.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:f28588772bb5fb869a8eb331374ec06f24a83a9c25bfa1f38b6993afe9c1e968", size = 655185, upload-time = "2025-08-07T13:45:27.624Z" }, + { url = "https://files.pythonhosted.org/packages/31/da/0386695eef69ffae1ad726881571dfe28b41970173947e7c558d9998de0f/greenlet-3.2.4-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:5c9320971821a7cb77cfab8d956fa8e39cd07ca44b6070db358ceb7f8797c8c9", size = 649926, upload-time = "2025-08-07T13:53:15.251Z" }, { url = "https://files.pythonhosted.org/packages/68/88/69bf19fd4dc19981928ceacbc5fd4bb6bc2215d53199e367832e98d1d8fe/greenlet-3.2.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c60a6d84229b271d44b70fb6e5fa23781abb5d742af7b808ae3f6efd7c9c60f6", size = 651839, upload-time = "2025-08-07T13:18:30.281Z" }, { url = "https://files.pythonhosted.org/packages/19/0d/6660d55f7373b2ff8152401a83e02084956da23ae58cddbfb0b330978fe9/greenlet-3.2.4-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3b3812d8d0c9579967815af437d96623f45c0f2ae5f04e366de62a12d83a8fb0", size = 607586, upload-time = "2025-08-07T13:18:28.544Z" }, { url = "https://files.pythonhosted.org/packages/8e/1a/c953fdedd22d81ee4629afbb38d2f9d71e37d23caace44775a3a969147d4/greenlet-3.2.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:abbf57b5a870d30c4675928c37278493044d7c14378350b3aa5d484fa65575f0", size = 1123281, upload-time = "2025-08-07T13:42:39.858Z" }, @@ -1971,6 +1906,7 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/49/e8/58c7f85958bda41dafea50497cbd59738c5c43dbbea5ee83d651234398f4/greenlet-3.2.4-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:1a921e542453fe531144e91e1feedf12e07351b1cf6c9e8a3325ea600a715a31", size = 272814, upload-time = "2025-08-07T13:15:50.011Z" }, { url = "https://files.pythonhosted.org/packages/62/dd/b9f59862e9e257a16e4e610480cfffd29e3fae018a68c2332090b53aac3d/greenlet-3.2.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:cd3c8e693bff0fff6ba55f140bf390fa92c994083f838fece0f63be121334945", size = 641073, upload-time = "2025-08-07T13:42:57.23Z" }, { url = "https://files.pythonhosted.org/packages/f7/0b/bc13f787394920b23073ca3b6c4a7a21396301ed75a655bcb47196b50e6e/greenlet-3.2.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:710638eb93b1fa52823aa91bf75326f9ecdfd5e0466f00789246a5280f4ba0fc", size = 655191, upload-time = "2025-08-07T13:45:29.752Z" }, + { url = "https://files.pythonhosted.org/packages/f2/d6/6adde57d1345a8d0f14d31e4ab9c23cfe8e2cd39c3baf7674b4b0338d266/greenlet-3.2.4-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:c5111ccdc9c88f423426df3fd1811bfc40ed66264d35aa373420a34377efc98a", size = 649516, upload-time = "2025-08-07T13:53:16.314Z" }, { url = "https://files.pythonhosted.org/packages/7f/3b/3a3328a788d4a473889a2d403199932be55b1b0060f4ddd96ee7cdfcad10/greenlet-3.2.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d76383238584e9711e20ebe14db6c88ddcedc1829a9ad31a584389463b5aa504", size = 652169, upload-time = "2025-08-07T13:18:32.861Z" }, { url = "https://files.pythonhosted.org/packages/ee/43/3cecdc0349359e1a527cbf2e3e28e5f8f06d3343aaf82ca13437a9aa290f/greenlet-3.2.4-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:23768528f2911bcd7e475210822ffb5254ed10d71f4028387e5a99b4c6699671", size = 610497, upload-time = "2025-08-07T13:18:31.636Z" }, { url = "https://files.pythonhosted.org/packages/b8/19/06b6cf5d604e2c382a6f31cafafd6f33d5dea706f4db7bdab184bad2b21d/greenlet-3.2.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:00fadb3fedccc447f517ee0d3fd8fe49eae949e1cd0f6a611818f4f6fb7dc83b", size = 1121662, upload-time = "2025-08-07T13:42:41.117Z" }, @@ -1981,6 +1917,7 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/22/5c/85273fd7cc388285632b0498dbbab97596e04b154933dfe0f3e68156c68c/greenlet-3.2.4-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:49a30d5fda2507ae77be16479bdb62a660fa51b1eb4928b524975b3bde77b3c0", size = 273586, upload-time = "2025-08-07T13:16:08.004Z" }, { url = "https://files.pythonhosted.org/packages/d1/75/10aeeaa3da9332c2e761e4c50d4c3556c21113ee3f0afa2cf5769946f7a3/greenlet-3.2.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:299fd615cd8fc86267b47597123e3f43ad79c9d8a22bebdce535e53550763e2f", size = 686346, upload-time = "2025-08-07T13:42:59.944Z" }, { url = "https://files.pythonhosted.org/packages/c0/aa/687d6b12ffb505a4447567d1f3abea23bd20e73a5bed63871178e0831b7a/greenlet-3.2.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:c17b6b34111ea72fc5a4e4beec9711d2226285f0386ea83477cbb97c30a3f3a5", size = 699218, upload-time = "2025-08-07T13:45:30.969Z" }, + { url = "https://files.pythonhosted.org/packages/dc/8b/29aae55436521f1d6f8ff4e12fb676f3400de7fcf27fccd1d4d17fd8fecd/greenlet-3.2.4-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:b4a1870c51720687af7fa3e7cda6d08d801dae660f75a76f3845b642b4da6ee1", size = 694659, upload-time = "2025-08-07T13:53:17.759Z" }, { url = "https://files.pythonhosted.org/packages/92/2e/ea25914b1ebfde93b6fc4ff46d6864564fba59024e928bdc7de475affc25/greenlet-3.2.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:061dc4cf2c34852b052a8620d40f36324554bc192be474b9e9770e8c042fd735", size = 695355, upload-time = "2025-08-07T13:18:34.517Z" }, { url = "https://files.pythonhosted.org/packages/72/60/fc56c62046ec17f6b0d3060564562c64c862948c9d4bc8aa807cf5bd74f4/greenlet-3.2.4-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:44358b9bf66c8576a9f57a590d5f5d6e72fa4228b763d0e43fee6d3b06d3a337", size = 657512, upload-time = "2025-08-07T13:18:33.969Z" }, { url = "https://files.pythonhosted.org/packages/23/6e/74407aed965a4ab6ddd93a7ded3180b730d281c77b765788419484cdfeef/greenlet-3.2.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:2917bdf657f5859fbf3386b12d68ede4cf1f04c90c3a6bc1f013dd68a22e2269", size = 1612508, upload-time = "2025-11-04T12:42:23.427Z" }, @@ -2211,15 +2148,6 @@ http2 = [ { name = "h2" }, ] -[[package]] -name = "httpx-sse" -version = "0.4.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/4c/60/8f4281fa9bbf3c8034fd54c0e7412e66edbab6bc74c4996bd616f8d0406e/httpx-sse-0.4.0.tar.gz", hash = "sha256:1e81a3a3070ce322add1d3529ed42eb5f70817f45ed6ec915ab753f961139721", size = 12624, upload-time = "2023-12-22T08:01:21.083Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e1/9b/a181f281f65d776426002f330c31849b86b31fc9d848db62e16f03ff739f/httpx_sse-0.4.0-py3-none-any.whl", hash = "sha256:f329af6eae57eaa2bdfd962b42524764af68075ea87370a2de920af5341e318f", size = 7819, upload-time = "2023-12-22T08:01:19.89Z" }, -] - [[package]] name = "huggingface-hub" version = "0.35.3" @@ -2434,15 +2362,6 @@ dev = [ { name = "testing-postgresql", specifier = ">=1.3.0,<2.0.0" }, ] -[[package]] -name = "iterators" -version = "0.2.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/02/c4/135b5bdb9f14f728fe1274361b336f77c5f1606af9a5622a765fe75f5fa0/iterators-0.2.0.tar.gz", hash = "sha256:e9927a1ea1ef081830fd1512f3916857c36bd4b37272819a6cd29d0f44431b97", size = 4284, upload-time = "2023-01-23T16:07:02.46Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/bd/a1/9c29772ac9f3bdf9837c92ba5c1fc93f75da14c2e0c3fc41e10485f68feb/iterators-0.2.0-py3-none-any.whl", hash = "sha256:1d7ff03f576c9de0e01bac66209556c066d6b1fc45583a99cfc9f4645be7900e", size = 5022, upload-time = "2023-01-23T16:07:00.352Z" }, -] - [[package]] name = "itsdangerous" version = "2.2.0" @@ -2847,18 +2766,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/70/bc/6f1c2f612465f5fa89b95bead1f44dcb607670fd42891d8fdcd5d039f4f4/markupsafe-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa", size = 14146, upload-time = "2025-09-27T18:37:28.327Z" }, ] -[[package]] -name = "marshmallow" -version = "3.26.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "packaging" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/ab/5e/5e53d26b42ab75491cda89b871dab9e97c840bf12c63ec58a1919710cd06/marshmallow-3.26.1.tar.gz", hash = "sha256:e6d8affb6cb61d39d26402096dc0aee12d5a26d490a121f118d2e81dc0719dc6", size = 221825, upload-time = "2025-02-03T15:32:25.093Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/34/75/51952c7b2d3873b44a0028b1bd26a25078c18f92f256608e8d1dc61b39fd/marshmallow-3.26.1-py3-none-any.whl", hash = "sha256:3350409f20a70a7e4e11a27661187b77cdcaeb20abca41c1454fe33636bea09c", size = 50878, upload-time = "2025-02-03T15:32:22.295Z" }, -] - [[package]] name = "mdurl" version = "0.1.2" @@ -3205,15 +3112,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/fd/69/b547032297c7e63ba2af494edba695d781af8a0c6e89e4d06cf848b21d80/multidict-6.6.4-py3-none-any.whl", hash = "sha256:27d8f8e125c07cb954e54d75d04905a9bba8a439c1d84aca94949d4d03d8601c", size = 12313, upload-time = "2025-08-11T12:08:46.891Z" }, ] -[[package]] -name = "mypy-extensions" -version = "1.1.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a2/6e/371856a3fb9d31ca8dac321cda606860fa4548858c0cc45d9d1d4ca2628b/mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558", size = 6343, upload-time = "2025-04-22T14:54:24.164Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", size = 4963, upload-time = "2025-04-22T14:54:22.983Z" }, -] - [[package]] name = "networkx" version = "3.5" @@ -3225,7 +3123,7 @@ wheels = [ [[package]] name = "nltk" -version = "3.9.2" +version = "3.9.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "click" }, @@ -3233,9 +3131,9 @@ dependencies = [ { name = "regex" }, { name = "tqdm" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/f9/76/3a5e4312c19a028770f86fd7c058cf9f4ec4321c6cf7526bab998a5b683c/nltk-3.9.2.tar.gz", hash = "sha256:0f409e9b069ca4177c1903c3e843eef90c7e92992fa4931ae607da6de49e1419", size = 2887629, upload-time = "2025-10-01T07:19:23.764Z" } +sdist = { url = "https://files.pythonhosted.org/packages/e1/8f/915e1c12df07c70ed779d18ab83d065718a926e70d3ea33eb0cd66ffb7c0/nltk-3.9.3.tar.gz", hash = "sha256:cb5945d6424a98d694c2b9a0264519fab4363711065a46aa0ae7a2195b92e71f", size = 2923673, upload-time = "2026-02-24T12:05:53.833Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/60/90/81ac364ef94209c100e12579629dc92bf7a709a84af32f8c551b02c07e94/nltk-3.9.2-py3-none-any.whl", hash = "sha256:1e209d2b3009110635ed9709a67a1a3e33a10f799490fa71cf4bec218c11c88a", size = 1513404, upload-time = "2025-10-01T07:19:21.648Z" }, + { url = "https://files.pythonhosted.org/packages/c2/7e/9af5a710a1236e4772de8dfcc6af942a561327bb9f42b5b4a24d0cf100fd/nltk-3.9.3-py3-none-any.whl", hash = "sha256:60b3db6e9995b3dd976b1f0fa7dec22069b2677e759c28eb69b62ddd44870522", size = 1525385, upload-time = "2026-02-24T12:05:46.54Z" }, ] [[package]] @@ -3886,7 +3784,7 @@ wheels = [ [[package]] name = "pipecat-ai" -version = "0.0.103" +version = "0.0.106" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "aiofiles" }, @@ -3909,9 +3807,9 @@ dependencies = [ { name = "transformers" }, { name = "wait-for2", marker = "python_full_version < '3.12'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/88/cd/5b5fbbe64edb7825cb5b1604480484dda760cb2d2a6655b9f3e4f33c87b1/pipecat_ai-0.0.103.tar.gz", hash = "sha256:9d08b8032a5a045a69202c83ce643f1ab6108aa6610122f566c152966171ad3c", size = 10974618, upload-time = "2026-02-21T00:44:09.557Z" } +sdist = { url = "https://files.pythonhosted.org/packages/b4/f6/661eb8937171263725136a82a6d2c2c11780ab9010b95d54abd9dec7591f/pipecat_ai-0.0.106.tar.gz", hash = "sha256:4330e7be9f17c07883ce265305e4062bf04c1b4ed4ff89a4e77171b059e3b9fa", size = 11094658, upload-time = "2026-03-19T06:41:01.923Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/20/ef/bd6c2022f16b6453bbe2348b254741ce221bec3e2729aed376503376bf07/pipecat_ai-0.0.103-py3-none-any.whl", hash = "sha256:cd05259cc2772a3fff38233a33f9fafad3a10a8ac1f371094ace97285b7ecc73", size = 10620793, upload-time = "2026-02-21T00:44:07.05Z" }, + { url = "https://files.pythonhosted.org/packages/6b/80/c78c945a352eb74b9ee67ef98bb87ae3f2bb69bc0cd496156e478a68cee1/pipecat_ai-0.0.106-py3-none-any.whl", hash = "sha256:5a3be3102ac65bb77088a612d11610c29d3453bd2b3a13872a5f83bfc1b1885d", size = 10726733, upload-time = "2026-03-19T06:40:59.518Z" }, ] [package.optional-dependencies] @@ -3919,7 +3817,6 @@ azure = [ { name = "azure-cognitiveservices-speech" }, ] cartesia = [ - { name = "cartesia" }, { name = "websockets" }, ] deepgram = [ @@ -3935,10 +3832,6 @@ google = [ groq = [ { name = "groq" }, ] -local-smart-turn-v3 = [ - { name = "onnxruntime" }, - { name = "transformers" }, -] runner = [ { name = "fastapi" }, { name = "pipecat-ai-small-webrtc-prebuilt" }, @@ -3949,9 +3842,6 @@ sarvam = [ { name = "sarvamai" }, { name = "websockets" }, ] -silero = [ - { name = "onnxruntime" }, -] tracing = [ { name = "opentelemetry-api" }, { name = "opentelemetry-instrumentation" }, @@ -3964,14 +3854,14 @@ websocket = [ [[package]] name = "pipecat-ai-small-webrtc-prebuilt" -version = "2.2.0" +version = "2.4.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "fastapi", extra = ["all"] }, ] -sdist = { url = "https://files.pythonhosted.org/packages/9a/9f/b06cc0e2eaeda811959c216dade3ed38c30d20e6327a2b22f80125072c5a/pipecat_ai_small_webrtc_prebuilt-2.2.0.tar.gz", hash = "sha256:5d73fe619225b97e383863a901060d1c986f088f4de004477856b085aaba76c4", size = 466005, upload-time = "2026-02-13T19:28:54.626Z" } +sdist = { url = "https://files.pythonhosted.org/packages/ba/02/1e6e90f084ebb1fc954f37661c4614219e4c9fec3d305c8abe5141707b0c/pipecat_ai_small_webrtc_prebuilt-2.4.0.tar.gz", hash = "sha256:c5eddca4e061afb7c5f98cf52ccb85511978a8c834447f6c6d662029e02950c4", size = 472449, upload-time = "2026-03-13T14:17:08.164Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/26/71/20a015cea25dc57129ed6426fdf37a09aefe37f4dd60e3a42ba2d9e3bd1b/pipecat_ai_small_webrtc_prebuilt-2.2.0-py3-none-any.whl", hash = "sha256:e7917d23f51e5418667541a3e241b2de28a43eea35a5a9486721be3da04e719d", size = 466257, upload-time = "2026-02-13T19:28:53.188Z" }, + { url = "https://files.pythonhosted.org/packages/25/77/8f6f67142a153943fff31530d51dcf7a2374c39dfa9aba6ef163bf0c622f/pipecat_ai_small_webrtc_prebuilt-2.4.0-py3-none-any.whl", hash = "sha256:9e9a3aa24231b1bf4101a6a2b42c4164a186c0c3d3e49bd51f77280eaa402d12", size = 472792, upload-time = "2026-03-13T14:17:06.556Z" }, ] [[package]] @@ -4459,15 +4349,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c1/60/5d4751ba3f4a40a6891f24eec885f51afd78d208498268c734e256fb13c4/pydantic_settings-2.12.0-py3-none-any.whl", hash = "sha256:fddb9fd99a5b18da837b29710391e945b1e30c135477f484084ee513adb93809", size = 51880, upload-time = "2025-11-10T14:25:45.546Z" }, ] -[[package]] -name = "pydub" -version = "0.25.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/fe/9a/e6bca0eed82db26562c73b5076539a4a08d3cffd19c3cc5913a3e61145fd/pydub-0.25.1.tar.gz", hash = "sha256:980a33ce9949cab2a569606b65674d748ecbca4f0796887fd6f46173a7b0d30f", size = 38326, upload-time = "2021-03-10T02:09:54.659Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a6/53/d78dc063216e62fc55f6b2eebb447f6a4b0a59f55c8406376f76bf959b08/pydub-0.25.1-py2.py3-none-any.whl", hash = "sha256:65617e33033874b59d87db603aa1ed450633288aefead953b30bded59cb599a6", size = 32327, upload-time = "2021-03-10T02:09:53.503Z" }, -] - [[package]] name = "pygments" version = "2.19.2" @@ -4493,16 +4374,15 @@ crypto = [ [[package]] name = "pyloudnorm" -version = "0.1.1" +version = "0.2.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "future" }, { name = "numpy" }, { name = "scipy" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/75/b5/39d59c44ecd828fabfdbd796b50a561e6543ca90ef440ab307374f107856/pyloudnorm-0.1.1.tar.gz", hash = "sha256:63cd4e197dea4e7795160ea08ed02d318091bce883e436a6dbc5963326b71e1e", size = 8588, upload-time = "2023-01-05T16:11:28.601Z" } +sdist = { url = "https://files.pythonhosted.org/packages/23/00/f915eaa75326f4209941179c2b93ac477f2040e4aeff5bb21d16eb8058f9/pyloudnorm-0.2.0.tar.gz", hash = "sha256:8bf597658ea4e1975c275adf490f6deb5369ea409f2901f939915efa4b681b16", size = 14037, upload-time = "2026-01-04T11:43:35.265Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/58/f5/6724805521ab4e723a12182f92374031032aff28a8a89dc8505c52b79032/pyloudnorm-0.1.1-py3-none-any.whl", hash = "sha256:d7f12ebdd097a464d87ce2878fc4d942f15f8233e26cc03f33fefa226f869a14", size = 9636, upload-time = "2023-01-05T16:11:27.331Z" }, + { url = "https://files.pythonhosted.org/packages/aa/b6/65a49a05614b2548edbba3aab118f2ebe7441dfd778accdcdce9f6567f20/pyloudnorm-0.2.0-py3-none-any.whl", hash = "sha256:9bb69afb904f59d007a7f9ba3d75d16fb8aeef35c44d6df822a9f192d69cf13f", size = 10879, upload-time = "2026-01-04T11:43:34.534Z" }, ] [[package]] @@ -5071,7 +4951,7 @@ wheels = [ [[package]] name = "sarvamai" -version = "0.1.26a2" +version = "0.1.26" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "httpx" }, @@ -5080,9 +4960,9 @@ dependencies = [ { name = "typing-extensions" }, { name = "websockets" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/7a/6c/80ab26743586532a3e9d68385549b0992e5318b5499db815889c8527cce5/sarvamai-0.1.26a2.tar.gz", hash = "sha256:0cbd1a95d13c1f8f0d1bf8fbeb37e86d3c2dc75a7ac402743bf0e571378f79e4", size = 112445, upload-time = "2026-02-16T13:16:28.392Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d7/31/13f65e8533b667514e1cfe838d12a14494cbc5943fd8f0c101305127459b/sarvamai-0.1.26.tar.gz", hash = "sha256:d51a213c27feb33d65f5b71e4882dcdb873dc5e0d720390b7ba18d1bdeec2471", size = 113050, upload-time = "2026-03-06T16:40:36.647Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/1f/3e/76c8ea81e790a5dab2ec9cd9fdb02cd600f90b1dfd9c895bea2fb5e6aa7f/sarvamai-0.1.26a2-py3-none-any.whl", hash = "sha256:2b0549a18e093ea382725240035a0bea18fff2a0d5207ad6c95ff7189e03264a", size = 227413, upload-time = "2026-02-16T13:16:27.045Z" }, + { url = "https://files.pythonhosted.org/packages/76/c9/c03a807ace9cafbfe26418be995e4959142a55313c9f26564586e111f31d/sarvamai-0.1.26-py3-none-any.whl", hash = "sha256:39e79ba0932f4501a2aa28f84fd2de64d34fc9a7af2b0d4ead1efa617517b3bd", size = 229057, upload-time = "2026-03-06T16:40:35.584Z" }, ] [[package]] @@ -5296,23 +5176,28 @@ wheels = [ [[package]] name = "soxr" -version = "0.5.0.post1" +version = "1.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "numpy" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/02/c0/4429bf9b3be10e749149e286aa5c53775399ec62891c6b970456c6dca325/soxr-0.5.0.post1.tar.gz", hash = "sha256:7092b9f3e8a416044e1fa138c8172520757179763b85dc53aa9504f4813cff73", size = 170853, upload-time = "2024-08-31T03:43:33.058Z" } +sdist = { url = "https://files.pythonhosted.org/packages/42/7e/f4b461944662ad75036df65277d6130f9411002bfb79e9df7dff40a31db9/soxr-1.0.0.tar.gz", hash = "sha256:e07ee6c1d659bc6957034f4800c60cb8b98de798823e34d2a2bba1caa85a4509", size = 171415, upload-time = "2025-09-07T13:22:21.317Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/29/28/dc62dae260a77603e8257e9b79078baa2ca4c0b4edc6f9f82c9113d6ef18/soxr-0.5.0.post1-cp311-cp311-macosx_10_14_x86_64.whl", hash = "sha256:6fb77b626773a966e3d8f6cb24f6f74b5327fa5dc90f1ff492450e9cdc03a378", size = 203648, upload-time = "2024-08-31T03:43:08.339Z" }, - { url = "https://files.pythonhosted.org/packages/0e/48/3e88329a695f6e0e38a3b171fff819d75d7cc055dae1ec5d5074f34d61e3/soxr-0.5.0.post1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:39e0f791ba178d69cd676485dbee37e75a34f20daa478d90341ecb7f6d9d690f", size = 159933, upload-time = "2024-08-31T03:43:10.053Z" }, - { url = "https://files.pythonhosted.org/packages/9c/a5/6b439164be6871520f3d199554568a7656e96a867adbbe5bac179caf5776/soxr-0.5.0.post1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4f0b558f445ba4b64dbcb37b5f803052eee7d93b1dbbbb97b3ec1787cb5a28eb", size = 221010, upload-time = "2024-08-31T03:43:11.839Z" }, - { url = "https://files.pythonhosted.org/packages/9f/e5/400e3bf7f29971abad85cb877e290060e5ec61fccd2fa319e3d85709c1be/soxr-0.5.0.post1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ca6903671808e0a6078b0d146bb7a2952b118dfba44008b2aa60f221938ba829", size = 252471, upload-time = "2024-08-31T03:43:13.347Z" }, - { url = "https://files.pythonhosted.org/packages/86/94/6a7e91bea7e6ca193ee429869b8f18548cd79759e064021ecb5756024c7c/soxr-0.5.0.post1-cp311-cp311-win_amd64.whl", hash = "sha256:c4d8d5283ed6f5efead0df2c05ae82c169cfdfcf5a82999c2d629c78b33775e8", size = 166723, upload-time = "2024-08-31T03:43:15.212Z" }, - { url = "https://files.pythonhosted.org/packages/5d/e3/d422d279e51e6932e7b64f1170a4f61a7ee768e0f84c9233a5b62cd2c832/soxr-0.5.0.post1-cp312-abi3-macosx_10_14_x86_64.whl", hash = "sha256:fef509466c9c25f65eae0ce1e4b9ac9705d22c6038c914160ddaf459589c6e31", size = 199993, upload-time = "2024-08-31T03:43:17.24Z" }, - { url = "https://files.pythonhosted.org/packages/20/f1/88adaca3c52e03bcb66b63d295df2e2d35bf355d19598c6ce84b20be7fca/soxr-0.5.0.post1-cp312-abi3-macosx_11_0_arm64.whl", hash = "sha256:4704ba6b13a3f1e41d12acf192878384c1c31f71ce606829c64abdf64a8d7d32", size = 156373, upload-time = "2024-08-31T03:43:18.633Z" }, - { url = "https://files.pythonhosted.org/packages/b8/38/bad15a9e615215c8219652ca554b601663ac3b7ac82a284aca53ec2ff48c/soxr-0.5.0.post1-cp312-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd052a66471a7335b22a6208601a9d0df7b46b8d087dce4ff6e13eed6a33a2a1", size = 216564, upload-time = "2024-08-31T03:43:20.789Z" }, - { url = "https://files.pythonhosted.org/packages/e1/1a/569ea0420a0c4801c2c8dd40d8d544989522f6014d51def689125f3f2935/soxr-0.5.0.post1-cp312-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a3f16810dd649ab1f433991d2a9661e9e6a116c2b4101039b53b3c3e90a094fc", size = 248455, upload-time = "2024-08-31T03:43:22.165Z" }, - { url = "https://files.pythonhosted.org/packages/bc/10/440f1ba3d4955e0dc740bbe4ce8968c254a3d644d013eb75eea729becdb8/soxr-0.5.0.post1-cp312-abi3-win_amd64.whl", hash = "sha256:b1be9fee90afb38546bdbd7bde714d1d9a8c5a45137f97478a83b65e7f3146f6", size = 164937, upload-time = "2024-08-31T03:43:23.671Z" }, + { url = "https://files.pythonhosted.org/packages/65/ce/a3262bc8733d3a4ce5f660ed88c3d97f4b12658b0909e71334cba1721dcb/soxr-1.0.0-cp311-cp311-macosx_10_14_x86_64.whl", hash = "sha256:28e19d74a5ef45c0d7000f3c70ec1719e89077379df2a1215058914d9603d2d8", size = 206739, upload-time = "2025-09-07T13:21:54.572Z" }, + { url = "https://files.pythonhosted.org/packages/64/dc/e8cbd100b652697cc9865dbed08832e7e135ff533f453eb6db9e6168d153/soxr-1.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f8dc69fc18884e53b72f6141fdf9d80997edbb4fec9dc2942edcb63abbe0d023", size = 165233, upload-time = "2025-09-07T13:21:55.887Z" }, + { url = "https://files.pythonhosted.org/packages/75/12/4b49611c9ba5e9fe6f807d0a83352516808e8e573f8b4e712fc0c17f3363/soxr-1.0.0-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3f15450e6f65f22f02fcd4c5a9219c873b1e583a73e232805ff160c759a6b586", size = 208867, upload-time = "2025-09-07T13:21:57.076Z" }, + { url = "https://files.pythonhosted.org/packages/cc/70/92146ab970a3ef8c43ac160035b1e52fde5417f89adb10572f7e788d9596/soxr-1.0.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1f73f57452f9df37b4de7a4052789fcbd474a5b28f38bba43278ae4b489d4384", size = 242633, upload-time = "2025-09-07T13:21:58.621Z" }, + { url = "https://files.pythonhosted.org/packages/b5/a7/628479336206959463d08260bffed87905e7ba9e3bd83ca6b405a0736e94/soxr-1.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:9f417c3d69236051cf5a1a7bad7c4bff04eb3d8fcaa24ac1cb06e26c8d48d8dc", size = 173814, upload-time = "2025-09-07T13:21:59.798Z" }, + { url = "https://files.pythonhosted.org/packages/c5/c7/f92b81f1a151c13afb114f57799b86da9330bec844ea5a0d3fe6a8732678/soxr-1.0.0-cp312-abi3-macosx_10_14_x86_64.whl", hash = "sha256:abecf4e39017f3fadb5e051637c272ae5778d838e5c3926a35db36a53e3a607f", size = 205508, upload-time = "2025-09-07T13:22:01.252Z" }, + { url = "https://files.pythonhosted.org/packages/ff/1d/c945fea9d83ea1f2be9d116b3674dbaef26ed090374a77c394b31e3b083b/soxr-1.0.0-cp312-abi3-macosx_11_0_arm64.whl", hash = "sha256:e973d487ee46aa8023ca00a139db6e09af053a37a032fe22f9ff0cc2e19c94b4", size = 163568, upload-time = "2025-09-07T13:22:03.558Z" }, + { url = "https://files.pythonhosted.org/packages/b5/80/10640970998a1d2199bef6c4d92205f36968cddaf3e4d0e9fe35ddd405bd/soxr-1.0.0-cp312-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e8ce273cca101aff3d8c387db5a5a41001ba76ef1837883438d3c652507a9ccc", size = 204707, upload-time = "2025-09-07T13:22:05.125Z" }, + { url = "https://files.pythonhosted.org/packages/b1/87/2726603c13c2126cb8ded9e57381b7377f4f0df6ba4408e1af5ddbfdc3dd/soxr-1.0.0-cp312-abi3-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e8f2a69686f2856d37823bbb7b78c3d44904f311fe70ba49b893af11d6b6047b", size = 238032, upload-time = "2025-09-07T13:22:06.428Z" }, + { url = "https://files.pythonhosted.org/packages/ce/04/530252227f4d0721a5524a936336485dfb429bb206a66baf8e470384f4a2/soxr-1.0.0-cp312-abi3-win_amd64.whl", hash = "sha256:2a3b77b115ae7c478eecdbd060ed4f61beda542dfb70639177ac263aceda42a2", size = 172070, upload-time = "2025-09-07T13:22:07.62Z" }, + { url = "https://files.pythonhosted.org/packages/99/77/d3b3c25b4f1b1aa4a73f669355edcaee7a52179d0c50407697200a0e55b9/soxr-1.0.0-cp314-cp314t-macosx_10_14_x86_64.whl", hash = "sha256:392a5c70c04eb939c9c176bd6f654dec9a0eaa9ba33d8f1024ed63cf68cdba0a", size = 209509, upload-time = "2025-09-07T13:22:08.773Z" }, + { url = "https://files.pythonhosted.org/packages/8a/ee/3ca73e18781bb2aff92b809f1c17c356dfb9a1870652004bd432e79afbfa/soxr-1.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:fdc41a1027ba46777186f26a8fba7893be913383414135577522da2fcc684490", size = 167690, upload-time = "2025-09-07T13:22:10.259Z" }, + { url = "https://files.pythonhosted.org/packages/bd/f0/eea8b5f587a2531657dc5081d2543a5a845f271a3bea1c0fdee5cebde021/soxr-1.0.0-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:449acd1dfaf10f0ce6dfd75c7e2ef984890df94008765a6742dafb42061c1a24", size = 209541, upload-time = "2025-09-07T13:22:11.739Z" }, + { url = "https://files.pythonhosted.org/packages/64/59/2430a48c705565eb09e78346950b586f253a11bd5313426ced3ecd9b0feb/soxr-1.0.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:38b35c99e408b8f440c9376a5e1dd48014857cd977c117bdaa4304865ae0edd0", size = 243025, upload-time = "2025-09-07T13:22:12.877Z" }, + { url = "https://files.pythonhosted.org/packages/3c/1b/f84a2570a74094e921bbad5450b2a22a85d58585916e131d9b98029c3e69/soxr-1.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:a39b519acca2364aa726b24a6fd55acf29e4c8909102e0b858c23013c38328e5", size = 184850, upload-time = "2025-09-07T13:22:14.068Z" }, ] [[package]] @@ -5707,19 +5592,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" }, ] -[[package]] -name = "typing-inspect" -version = "0.9.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "mypy-extensions" }, - { name = "typing-extensions" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/dc/74/1789779d91f1961fa9438e9a8710cdae6bd138c80d7303996933d117264a/typing_inspect-0.9.0.tar.gz", hash = "sha256:b23fc42ff6f6ef6954e4852c1fb512cdd18dbea03134f91f856a95ccc9461f78", size = 13825, upload-time = "2023-05-24T20:25:47.612Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/65/f3/107a22063bf27bdccf2024833d3445f4eea42b2e598abfbd46f6a63b6cb0/typing_inspect-0.9.0-py3-none-any.whl", hash = "sha256:9ee6fc59062311ef8547596ab6b955e1b8aa46242d854bfc78f4f6b0eff35f9f", size = 8827, upload-time = "2023-05-24T20:25:45.287Z" }, -] - [[package]] name = "typing-inspection" version = "0.4.1"