diff --git a/CHANGELOG.md b/CHANGELOG.md index a5d97473f..b6dca2848 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -93,6 +93,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed +- Fixed an issue that would cause multiple instances of the same class to behave + incorrectly if any of the given constructor arguments defaulted to a mutable + value (e.g. lists, dictionaries, objects). + - Fixed an issue with `CartesiaTTSService` where `TTSTextFrame` messages weren't being emitted when the model was set to `sonic`. This resulted in the assistant context not being updated with assistant messages. diff --git a/src/pipecat/adapters/schemas/tools_schema.py b/src/pipecat/adapters/schemas/tools_schema.py index 5720535c5..2489e0b4d 100644 --- a/src/pipecat/adapters/schemas/tools_schema.py +++ b/src/pipecat/adapters/schemas/tools_schema.py @@ -5,7 +5,7 @@ # from enum import Enum -from typing import Any, Dict, List +from typing import Any, Dict, List, Optional from pipecat.adapters.schemas.function_schema import FunctionSchema @@ -18,7 +18,7 @@ class ToolsSchema: def __init__( self, standard_tools: List[FunctionSchema], - custom_tools: Dict[AdapterType, List[Dict[str, Any]]] = None, + custom_tools: Optional[Dict[AdapterType, List[Dict[str, Any]]]] = None, ) -> None: """ A schema for tools that includes both standardized function schemas diff --git a/src/pipecat/audio/turn/smart_turn/base_smart_turn.py b/src/pipecat/audio/turn/smart_turn/base_smart_turn.py index e7f30246a..1bd187aee 100644 --- a/src/pipecat/audio/turn/smart_turn/base_smart_turn.py +++ b/src/pipecat/audio/turn/smart_turn/base_smart_turn.py @@ -36,10 +36,10 @@ class SmartTurnTimeoutException(Exception): class BaseSmartTurn(BaseTurnAnalyzer): def __init__( - self, *, sample_rate: Optional[int] = None, params: SmartTurnParams = SmartTurnParams() + self, *, sample_rate: Optional[int] = None, params: Optional[SmartTurnParams] = None ): super().__init__(sample_rate=sample_rate) - self._params = params + self._params = params or SmartTurnParams() # Configuration self._stop_ms = self._params.stop_secs * 1000 # silence threshold in ms # Inference state diff --git a/src/pipecat/audio/turn/smart_turn/http_smart_turn.py b/src/pipecat/audio/turn/smart_turn/http_smart_turn.py index 5bd3743ed..bf9f086a3 100644 --- a/src/pipecat/audio/turn/smart_turn/http_smart_turn.py +++ b/src/pipecat/audio/turn/smart_turn/http_smart_turn.py @@ -6,7 +6,7 @@ import asyncio import io -from typing import Any, Dict +from typing import Any, Dict, Optional import aiohttp import numpy as np @@ -21,12 +21,12 @@ class HttpSmartTurnAnalyzer(BaseSmartTurn): *, url: str, aiohttp_session: aiohttp.ClientSession, - headers: Dict[str, str] = {}, + headers: Optional[Dict[str, str]] = None, **kwargs, ): super().__init__(**kwargs) self._url = url - self._headers = headers + self._headers = headers or {} self._aiohttp_session = aiohttp_session def _serialize_array(self, audio_array: np.ndarray) -> bytes: diff --git a/src/pipecat/audio/vad/silero.py b/src/pipecat/audio/vad/silero.py index a5db2a0ae..26d9368a8 100644 --- a/src/pipecat/audio/vad/silero.py +++ b/src/pipecat/audio/vad/silero.py @@ -105,7 +105,7 @@ class SileroOnnxModel: class SileroVADAnalyzer(VADAnalyzer): - def __init__(self, *, sample_rate: Optional[int] = None, params: VADParams = VADParams()): + def __init__(self, *, sample_rate: Optional[int] = None, params: Optional[VADParams] = None): super().__init__(sample_rate=sample_rate, params=params) logger.debug("Loading Silero VAD model...") diff --git a/src/pipecat/audio/vad/vad_analyzer.py b/src/pipecat/audio/vad/vad_analyzer.py index 3ca21a208..915649031 100644 --- a/src/pipecat/audio/vad/vad_analyzer.py +++ b/src/pipecat/audio/vad/vad_analyzer.py @@ -34,10 +34,10 @@ class VADParams(BaseModel): class VADAnalyzer(ABC): - def __init__(self, *, sample_rate: Optional[int] = None, params: VADParams): + def __init__(self, *, sample_rate: Optional[int] = None, params: Optional[VADParams] = None): self._init_sample_rate = sample_rate self._sample_rate = 0 - self._params = params + self._params = params or VADParams() self._num_channels = 1 self._vad_buffer = b"" diff --git a/src/pipecat/pipeline/task.py b/src/pipecat/pipeline/task.py index 2b90d508d..6deee59f8 100644 --- a/src/pipecat/pipeline/task.py +++ b/src/pipecat/pipeline/task.py @@ -188,9 +188,9 @@ class PipelineTask(BaseTask): self, pipeline: BasePipeline, *, - params: PipelineParams = PipelineParams(), - observers: List[BaseObserver] = [], - clock: BaseClock = SystemClock(), + params: Optional[PipelineParams] = None, + observers: Optional[List[BaseObserver]] = None, + clock: Optional[BaseClock] = None, task_manager: Optional[BaseTaskManager] = None, check_dangling_tasks: bool = True, idle_timeout_secs: Optional[float] = 300, @@ -205,8 +205,8 @@ class PipelineTask(BaseTask): ): super().__init__() self._pipeline = pipeline - self._clock = clock - self._params = params + self._clock = clock or SystemClock() + self._params = params or PipelineParams() self._check_dangling_tasks = check_dangling_tasks self._idle_timeout_secs = idle_timeout_secs self._idle_timeout_frames = idle_timeout_frames @@ -224,6 +224,7 @@ class PipelineTask(BaseTask): DeprecationWarning, ) observers = self._params.observers + observers = observers or [] if self._enable_turn_tracking: self._turn_tracking_observer = TurnTrackingObserver() observers = [self._turn_tracking_observer] + list(observers) diff --git a/src/pipecat/pipeline/task_observer.py b/src/pipecat/pipeline/task_observer.py index 252708f8c..127ea3466 100644 --- a/src/pipecat/pipeline/task_observer.py +++ b/src/pipecat/pipeline/task_observer.py @@ -6,7 +6,7 @@ import asyncio import inspect -from typing import List +from typing import List, Optional from attr import dataclass @@ -39,8 +39,10 @@ class TaskObserver(BaseObserver): """ - def __init__(self, *, observers: List[BaseObserver] = [], task_manager: BaseTaskManager): - self._observers = observers + def __init__( + self, *, observers: Optional[List[BaseObserver]] = None, task_manager: BaseTaskManager + ): + self._observers = observers or [] self._task_manager = task_manager self._proxies: List[Proxy] = [] diff --git a/src/pipecat/processors/aggregators/llm_response.py b/src/pipecat/processors/aggregators/llm_response.py index fa163ac0a..55ac0e2d5 100644 --- a/src/pipecat/processors/aggregators/llm_response.py +++ b/src/pipecat/processors/aggregators/llm_response.py @@ -7,7 +7,7 @@ import asyncio from abc import abstractmethod from dataclasses import dataclass -from typing import Dict, List, Literal, Set +from typing import Dict, List, Literal, Optional, Set from loguru import logger @@ -243,11 +243,11 @@ class LLMUserContextAggregator(LLMContextResponseAggregator): self, context: OpenAILLMContext, *, - params: LLMUserAggregatorParams = LLMUserAggregatorParams(), + params: Optional[LLMUserAggregatorParams] = None, **kwargs, ): super().__init__(context=context, role="user", **kwargs) - self._params = params + self._params = params or LLMUserAggregatorParams() if "aggregation_timeout" in kwargs: import warnings @@ -446,11 +446,11 @@ class LLMAssistantContextAggregator(LLMContextResponseAggregator): self, context: OpenAILLMContext, *, - params: LLMAssistantAggregatorParams = LLMAssistantAggregatorParams(), + params: Optional[LLMAssistantAggregatorParams] = None, **kwargs, ): super().__init__(context=context, role="assistant", **kwargs) - self._params = params + self._params = params or LLMAssistantAggregatorParams() if "expect_stripped_words" in kwargs: import warnings @@ -640,9 +640,9 @@ class LLMAssistantContextAggregator(LLMContextResponseAggregator): class LLMUserResponseAggregator(LLMUserContextAggregator): def __init__( self, - messages: List[dict] = [], + messages: Optional[List[dict]] = None, *, - params: LLMUserAggregatorParams = LLMUserAggregatorParams(), + params: Optional[LLMUserAggregatorParams] = None, **kwargs, ): super().__init__(context=OpenAILLMContext(messages), params=params, **kwargs) @@ -662,9 +662,9 @@ class LLMUserResponseAggregator(LLMUserContextAggregator): class LLMAssistantResponseAggregator(LLMAssistantContextAggregator): def __init__( self, - messages: List[dict] = [], + messages: Optional[List[dict]] = None, *, - params: LLMAssistantAggregatorParams = LLMAssistantAggregatorParams(), + params: Optional[LLMAssistantAggregatorParams] = None, **kwargs, ): super().__init__(context=OpenAILLMContext(messages), params=params, **kwargs) diff --git a/src/pipecat/processors/filters/wake_check_filter.py b/src/pipecat/processors/filters/wake_check_filter.py index d15607e7c..d8661eae1 100644 --- a/src/pipecat/processors/filters/wake_check_filter.py +++ b/src/pipecat/processors/filters/wake_check_filter.py @@ -7,6 +7,7 @@ import re import time from enum import Enum +from typing import List from loguru import logger @@ -31,7 +32,7 @@ class WakeCheckFilter(FrameProcessor): self.wake_timer = 0.0 self.accumulator = "" - def __init__(self, wake_phrases: list[str], keepalive_timeout: float = 3): + def __init__(self, wake_phrases: List[str], keepalive_timeout: float = 3): super().__init__() self._participant_states = {} self._keepalive_timeout = keepalive_timeout diff --git a/src/pipecat/processors/filters/wake_notifier_filter.py b/src/pipecat/processors/filters/wake_notifier_filter.py index e2684d8e4..c7e6ed27a 100644 --- a/src/pipecat/processors/filters/wake_notifier_filter.py +++ b/src/pipecat/processors/filters/wake_notifier_filter.py @@ -22,7 +22,7 @@ class WakeNotifierFilter(FrameProcessor): self, notifier: BaseNotifier, *, - types: Tuple[Type[Frame]], + types: Tuple[Type[Frame], ...], filter: Callable[[Frame], Awaitable[bool]], **kwargs, ): diff --git a/src/pipecat/processors/frameworks/rtvi.py b/src/pipecat/processors/frameworks/rtvi.py index c2f7004ba..f759102ae 100644 --- a/src/pipecat/processors/frameworks/rtvi.py +++ b/src/pipecat/processors/frameworks/rtvi.py @@ -437,10 +437,10 @@ class RTVIObserver(BaseObserver): params (RTVIObserverParams): Settings to enable/disable specific messages. """ - def __init__(self, rtvi: "RTVIProcessor", *, params: RTVIObserverParams = RTVIObserverParams()): + def __init__(self, rtvi: "RTVIProcessor", *, params: Optional[RTVIObserverParams] = None): super().__init__() self._rtvi = rtvi - self._params = params + self._params = params or RTVIObserverParams() self._bot_transcription = "" self._frames_seen = set() rtvi.set_errors_enabled(self._params.errors_enabled) @@ -632,12 +632,12 @@ class RTVIProcessor(FrameProcessor): def __init__( self, *, - config: RTVIConfig = RTVIConfig(config=[]), + config: Optional[RTVIConfig] = None, transport: Optional[BaseTransport] = None, **kwargs, ): super().__init__(**kwargs) - self._config = config + self._config = config or RTVIConfig(config=[]) self._bot_ready = False self._client_ready = False diff --git a/src/pipecat/processors/gstreamer/pipeline_source.py b/src/pipecat/processors/gstreamer/pipeline_source.py index 12b9cef67..84b8a050b 100644 --- a/src/pipecat/processors/gstreamer/pipeline_source.py +++ b/src/pipecat/processors/gstreamer/pipeline_source.py @@ -43,10 +43,10 @@ class GStreamerPipelineSource(FrameProcessor): audio_channels: int = 1 clock_sync: bool = True - def __init__(self, *, pipeline: str, out_params: OutputParams = OutputParams(), **kwargs): + def __init__(self, *, pipeline: str, out_params: Optional[OutputParams] = None, **kwargs): super().__init__(**kwargs) - self._out_params = out_params + self._out_params = out_params or GStreamerPipelineSource.OutputParams() self._sample_rate = 0 Gst.init() diff --git a/src/pipecat/processors/idle_frame_processor.py b/src/pipecat/processors/idle_frame_processor.py index ab98df771..36c7e9821 100644 --- a/src/pipecat/processors/idle_frame_processor.py +++ b/src/pipecat/processors/idle_frame_processor.py @@ -5,7 +5,7 @@ # import asyncio -from typing import Awaitable, Callable, List +from typing import Awaitable, Callable, List, Optional from pipecat.frames.frames import Frame, StartFrame from pipecat.processors.frame_processor import FrameDirection, FrameProcessor @@ -22,14 +22,14 @@ class IdleFrameProcessor(FrameProcessor): *, callback: Callable[["IdleFrameProcessor"], Awaitable[None]], timeout: float, - types: List[type] = [], + types: Optional[List[type]] = None, **kwargs, ): super().__init__(**kwargs) self._callback = callback self._timeout = timeout - self._types = types + self._types = types or [] self._idle_task = None async def process_frame(self, frame: Frame, direction: FrameDirection): diff --git a/src/pipecat/processors/logger.py b/src/pipecat/processors/logger.py index 09a2d1674..b773df8c3 100644 --- a/src/pipecat/processors/logger.py +++ b/src/pipecat/processors/logger.py @@ -4,11 +4,17 @@ # SPDX-License-Identifier: BSD 2-Clause License # -from typing import Optional +from typing import Optional, Tuple, Type from loguru import logger -from pipecat.frames.frames import AudioRawFrame, BotSpeakingFrame, Frame, TransportMessageFrame +from pipecat.frames.frames import ( + BotSpeakingFrame, + Frame, + InputAudioRawFrame, + OutputAudioRawFrame, + TransportMessageFrame, +) from pipecat.processors.frame_processor import FrameDirection, FrameProcessor logger = logger.opt(ansi=True) @@ -19,16 +25,17 @@ class FrameLogger(FrameProcessor): self, prefix="Frame", color: Optional[str] = None, - ignored_frame_types: Optional[list] = [ + ignored_frame_types: Tuple[Type[Frame], ...] = ( BotSpeakingFrame, - AudioRawFrame, + InputAudioRawFrame, + OutputAudioRawFrame, TransportMessageFrame, - ], + ), ): super().__init__() self._prefix = prefix self._color = color - self._ignored_frame_types = tuple(ignored_frame_types) if ignored_frame_types else None + self._ignored_frame_types = ignored_frame_types async def process_frame(self, frame: Frame, direction: FrameDirection): await super().process_frame(frame, direction) diff --git a/src/pipecat/serializers/telnyx.py b/src/pipecat/serializers/telnyx.py index 61a89c7f0..6ef9f7c0d 100644 --- a/src/pipecat/serializers/telnyx.py +++ b/src/pipecat/serializers/telnyx.py @@ -79,7 +79,7 @@ class TelnyxFrameSerializer(FrameSerializer): inbound_encoding: str, call_control_id: Optional[str] = None, api_key: Optional[str] = None, - params: InputParams = InputParams(), + params: Optional[InputParams] = None, ): """Initialize the TelnyxFrameSerializer. @@ -92,11 +92,11 @@ class TelnyxFrameSerializer(FrameSerializer): params: Configuration parameters. """ self._stream_id = stream_id - params.outbound_encoding = outbound_encoding - params.inbound_encoding = inbound_encoding self._call_control_id = call_control_id self._api_key = api_key - self._params = params + self._params = params or TelnyxFrameSerializer.InputParams() + self._params.outbound_encoding = outbound_encoding + self._params.inbound_encoding = inbound_encoding self._telnyx_sample_rate = self._params.telnyx_sample_rate self._sample_rate = 0 # Pipeline input rate diff --git a/src/pipecat/serializers/twilio.py b/src/pipecat/serializers/twilio.py index b169955ce..26a3fea5e 100644 --- a/src/pipecat/serializers/twilio.py +++ b/src/pipecat/serializers/twilio.py @@ -69,7 +69,7 @@ class TwilioFrameSerializer(FrameSerializer): call_sid: Optional[str] = None, account_sid: Optional[str] = None, auth_token: Optional[str] = None, - params: InputParams = InputParams(), + params: Optional[InputParams] = None, ): """Initialize the TwilioFrameSerializer. @@ -84,7 +84,7 @@ class TwilioFrameSerializer(FrameSerializer): self._call_sid = call_sid self._account_sid = account_sid self._auth_token = auth_token - self._params = params + self._params = params or TwilioFrameSerializer.InputParams() self._twilio_sample_rate = self._params.twilio_sample_rate self._sample_rate = 0 # Pipeline input rate diff --git a/src/pipecat/services/anthropic/llm.py b/src/pipecat/services/anthropic/llm.py index 43fe5ab6f..5e0ea0ad2 100644 --- a/src/pipecat/services/anthropic/llm.py +++ b/src/pipecat/services/anthropic/llm.py @@ -91,11 +91,12 @@ class AnthropicLLMService(LLMService): *, api_key: str, model: str = "claude-3-7-sonnet-20250219", - params: InputParams = InputParams(), + params: Optional[InputParams] = None, client=None, **kwargs, ): super().__init__(**kwargs) + params = params or AnthropicLLMService.InputParams() self._client = client or AsyncAnthropic( api_key=api_key ) # if the client is provided, use it and remove it, otherwise create a new one diff --git a/src/pipecat/services/assemblyai/stt.py b/src/pipecat/services/assemblyai/stt.py index 2153d969e..41a27fd5b 100644 --- a/src/pipecat/services/assemblyai/stt.py +++ b/src/pipecat/services/assemblyai/stt.py @@ -38,12 +38,13 @@ class AssemblyAISTTService(STTService): *, api_key: str, sample_rate: Optional[int] = None, - encoding: AudioEncoding = AudioEncoding("pcm_s16le"), + encoding: Optional[AudioEncoding] = None, language=Language.EN, # Only English is supported for Realtime **kwargs, ): super().__init__(sample_rate=sample_rate, **kwargs) + encoding = encoding or AudioEncoding("pcm_s16le") aai.settings.api_key = api_key self._transcriber: Optional[aai.RealtimeTranscriber] = None diff --git a/src/pipecat/services/aws/llm.py b/src/pipecat/services/aws/llm.py index f1a24bb18..9ec617678 100644 --- a/src/pipecat/services/aws/llm.py +++ b/src/pipecat/services/aws/llm.py @@ -530,17 +530,19 @@ class AWSBedrockLLMService(LLMService): def __init__( self, *, + model: str, aws_access_key: Optional[str] = None, aws_secret_key: Optional[str] = None, aws_session_token: Optional[str] = None, aws_region: str = "us-east-1", - model: str, - params: InputParams = InputParams(), + params: Optional[InputParams] = None, client_config: Optional[Config] = None, **kwargs, ): super().__init__(**kwargs) + params = params or AWSBedrockLLMService.InputParams() + # Initialize the AWS Bedrock client if not client_config: client_config = Config( diff --git a/src/pipecat/services/aws/tts.py b/src/pipecat/services/aws/tts.py index cba2acc5f..a0719f227 100644 --- a/src/pipecat/services/aws/tts.py +++ b/src/pipecat/services/aws/tts.py @@ -125,11 +125,13 @@ class AWSPollyTTSService(TTSService): region: Optional[str] = None, voice_id: str = "Joanna", sample_rate: Optional[int] = None, - params: InputParams = InputParams(), + params: Optional[InputParams] = None, **kwargs, ): super().__init__(sample_rate=sample_rate, **kwargs) + params = params or AWSPollyTTSService.InputParams() + self._polly_client = boto3.client( "polly", aws_access_key_id=aws_access_key_id, diff --git a/src/pipecat/services/aws_nova_sonic/aws.py b/src/pipecat/services/aws_nova_sonic/aws.py index 0e474fb89..2a342539e 100644 --- a/src/pipecat/services/aws_nova_sonic/aws.py +++ b/src/pipecat/services/aws_nova_sonic/aws.py @@ -142,7 +142,7 @@ class AWSNovaSonicLLMService(LLMService): region: str, model: str = "amazon.nova-sonic-v1:0", voice_id: str = "matthew", # matthew, tiffany, amy - params: Params = Params(), + params: Optional[Params] = None, system_instruction: Optional[str] = None, tools: Optional[ToolsSchema] = None, send_transcription_frames: bool = True, @@ -155,7 +155,7 @@ class AWSNovaSonicLLMService(LLMService): self._model = model self._client: Optional[BedrockRuntimeClient] = None self._voice_id = voice_id - self._params = params + self._params = params or Params() self._system_instruction = system_instruction self._tools = tools self._send_transcription_frames = send_transcription_frames diff --git a/src/pipecat/services/azure/tts.py b/src/pipecat/services/azure/tts.py index 9dde55496..e8be685a6 100644 --- a/src/pipecat/services/azure/tts.py +++ b/src/pipecat/services/azure/tts.py @@ -68,11 +68,13 @@ class AzureBaseTTSService(TTSService): region: str, voice="en-US-SaraNeural", sample_rate: Optional[int] = None, - params: InputParams = InputParams(), + params: Optional[InputParams] = None, **kwargs, ): super().__init__(sample_rate=sample_rate, **kwargs) + params = params or AzureBaseTTSService.InputParams() + self._settings = { "emphasis": params.emphasis, "language": self.language_to_service_language(params.language) diff --git a/src/pipecat/services/cartesia/tts.py b/src/pipecat/services/cartesia/tts.py index 5d37a583f..22493f229 100644 --- a/src/pipecat/services/cartesia/tts.py +++ b/src/pipecat/services/cartesia/tts.py @@ -11,7 +11,7 @@ import warnings from typing import AsyncGenerator, List, Optional, Union from loguru import logger -from pydantic import BaseModel +from pydantic import BaseModel, Field from pipecat.frames.frames import ( CancelFrame, @@ -90,7 +90,7 @@ class CartesiaTTSService(AudioContextWordTTSService): sample_rate: Optional[int] = None, encoding: str = "pcm_s16le", container: str = "raw", - params: InputParams = InputParams(), + params: Optional[InputParams] = None, text_aggregator: Optional[BaseTextAggregator] = None, **kwargs, ): @@ -113,6 +113,8 @@ class CartesiaTTSService(AudioContextWordTTSService): **kwargs, ) + params = params or CartesiaTTSService.InputParams() + self._api_key = api_key self._cartesia_version = cartesia_version self._url = url @@ -317,7 +319,7 @@ class CartesiaHttpTTSService(TTSService): class InputParams(BaseModel): language: Optional[Language] = Language.EN speed: Optional[Union[str, float]] = "" - emotion: Optional[List[str]] = [] + emotion: Optional[List[str]] = Field(default_factory=list) def __init__( self, @@ -330,11 +332,13 @@ class CartesiaHttpTTSService(TTSService): sample_rate: Optional[int] = None, encoding: str = "pcm_s16le", container: str = "raw", - params: InputParams = InputParams(), + params: Optional[InputParams] = None, **kwargs, ): super().__init__(sample_rate=sample_rate, **kwargs) + params = params or CartesiaHttpTTSService.InputParams() + self._api_key = api_key self._base_url = base_url self._cartesia_version = cartesia_version diff --git a/src/pipecat/services/elevenlabs/tts.py b/src/pipecat/services/elevenlabs/tts.py index 5e5a97e75..4b48a3d3d 100644 --- a/src/pipecat/services/elevenlabs/tts.py +++ b/src/pipecat/services/elevenlabs/tts.py @@ -184,7 +184,7 @@ class ElevenLabsTTSService(AudioContextWordTTSService): model: str = "eleven_flash_v2_5", url: str = "wss://api.elevenlabs.io", sample_rate: Optional[int] = None, - params: InputParams = InputParams(), + params: Optional[InputParams] = None, **kwargs, ): # Aggregating sentences still gives cleaner-sounding results and fewer @@ -210,6 +210,8 @@ class ElevenLabsTTSService(AudioContextWordTTSService): **kwargs, ) + params = params or ElevenLabsTTSService.InputParams() + self._api_key = api_key self._url = url self._settings = { @@ -512,7 +514,7 @@ class ElevenLabsHttpTTSService(WordTTSService): model: str = "eleven_flash_v2_5", base_url: str = "https://api.elevenlabs.io", sample_rate: Optional[int] = None, - params: InputParams = InputParams(), + params: Optional[InputParams] = None, **kwargs, ): super().__init__( @@ -523,6 +525,8 @@ class ElevenLabsHttpTTSService(WordTTSService): **kwargs, ) + params = params or ElevenLabsHttpTTSService.InputParams() + self._api_key = api_key self._base_url = base_url self._params = params diff --git a/src/pipecat/services/fal/stt.py b/src/pipecat/services/fal/stt.py index 950d74d06..a019694fd 100644 --- a/src/pipecat/services/fal/stt.py +++ b/src/pipecat/services/fal/stt.py @@ -173,7 +173,7 @@ class FalSTTService(SegmentedSTTService): *, api_key: Optional[str] = None, sample_rate: Optional[int] = None, - params: InputParams = InputParams(), + params: Optional[InputParams] = None, **kwargs, ): super().__init__( @@ -181,6 +181,8 @@ class FalSTTService(SegmentedSTTService): **kwargs, ) + params = params or FalSTTService.InputParams() + if api_key: os.environ["FAL_KEY"] = api_key elif "FAL_KEY" not in os.environ: diff --git a/src/pipecat/services/fish/tts.py b/src/pipecat/services/fish/tts.py index 39c85281a..84e285aee 100644 --- a/src/pipecat/services/fish/tts.py +++ b/src/pipecat/services/fish/tts.py @@ -52,7 +52,7 @@ class FishAudioTTSService(InterruptibleTTSService): model: str, # This is the reference_id output_format: FishAudioOutputFormat = "pcm", sample_rate: Optional[int] = None, - params: InputParams = InputParams(), + params: Optional[InputParams] = None, **kwargs, ): super().__init__( @@ -62,6 +62,8 @@ class FishAudioTTSService(InterruptibleTTSService): **kwargs, ) + params = params or FishAudioTTSService.InputParams() + self._api_key = api_key self._base_url = "wss://api.fish.audio/v1/tts/live" self._websocket = None diff --git a/src/pipecat/services/gemini_multimodal_live/gemini.py b/src/pipecat/services/gemini_multimodal_live/gemini.py index b2614504b..10b284890 100644 --- a/src/pipecat/services/gemini_multimodal_live/gemini.py +++ b/src/pipecat/services/gemini_multimodal_live/gemini.py @@ -341,11 +341,14 @@ class GeminiMultimodalLiveLLMService(LLMService): start_video_paused: bool = False, system_instruction: Optional[str] = None, tools: Optional[Union[List[dict], ToolsSchema]] = None, - params: InputParams = InputParams(), + params: Optional[InputParams] = None, inference_on_context_initialization: bool = True, **kwargs, ): super().__init__(base_url=base_url, **kwargs) + + params = params or InputParams() + self._last_sent_time = 0 self._api_key = api_key self._base_url = base_url diff --git a/src/pipecat/services/gladia/stt.py b/src/pipecat/services/gladia/stt.py index 8208d01e2..33c927158 100644 --- a/src/pipecat/services/gladia/stt.py +++ b/src/pipecat/services/gladia/stt.py @@ -194,7 +194,7 @@ class GladiaSTTService(STTService): confidence: float = 0.5, sample_rate: Optional[int] = None, model: str = "solaria-1", - params: GladiaInputParams = GladiaInputParams(), + params: Optional[GladiaInputParams] = None, **kwargs, ): """Initialize the Gladia STT service. @@ -211,6 +211,8 @@ class GladiaSTTService(STTService): """ super().__init__(sample_rate=sample_rate, **kwargs) + params = params or GladiaInputParams() + # Warn about deprecated language parameter if it's used if params.language is not None: warnings.warn( diff --git a/src/pipecat/services/google/image.py b/src/pipecat/services/google/image.py index 5a73168dc..dc0218b8c 100644 --- a/src/pipecat/services/google/image.py +++ b/src/pipecat/services/google/image.py @@ -10,7 +10,7 @@ import os # Suppress gRPC fork warnings os.environ["GRPC_ENABLE_FORK_SUPPORT"] = "false" -from typing import AsyncGenerator +from typing import AsyncGenerator, Optional from loguru import logger from PIL import Image @@ -32,19 +32,19 @@ class GoogleImageGenService(ImageGenService): class InputParams(BaseModel): number_of_images: int = Field(default=1, ge=1, le=8) model: str = Field(default="imagen-3.0-generate-002") - negative_prompt: str = Field(default=None) + negative_prompt: Optional[str] = Field(default=None) def __init__( self, *, - params: InputParams = InputParams(), api_key: str, + params: Optional[InputParams] = None, **kwargs, ): super().__init__(**kwargs) - self.set_model_name(params.model) - self._params = params + self._params = params or GoogleImageGenService.InputParams() self._client = genai.Client(api_key=api_key) + self.set_model_name(self._params.model) def can_generate_metrics(self) -> bool: return True diff --git a/src/pipecat/services/google/llm.py b/src/pipecat/services/google/llm.py index e5fcf56db..d13dd546d 100644 --- a/src/pipecat/services/google/llm.py +++ b/src/pipecat/services/google/llm.py @@ -467,13 +467,16 @@ class GoogleLLMService(LLMService): *, api_key: str, model: str = "gemini-2.0-flash", - params: InputParams = InputParams(), + params: Optional[InputParams] = None, system_instruction: Optional[str] = None, tools: Optional[List[Dict[str, Any]]] = None, tool_config: Optional[Dict[str, Any]] = None, **kwargs, ): super().__init__(**kwargs) + + params = params or GoogleLLMService.InputParams() + self.set_model_name(model) self._api_key = api_key self._system_instruction = system_instruction diff --git a/src/pipecat/services/google/llm_vertex.py b/src/pipecat/services/google/llm_vertex.py index a2a485ccd..9b0ed6501 100644 --- a/src/pipecat/services/google/llm_vertex.py +++ b/src/pipecat/services/google/llm_vertex.py @@ -52,7 +52,7 @@ class GoogleVertexLLMService(OpenAILLMService): credentials: Optional[str] = None, credentials_path: Optional[str] = None, model: str = "google/gemini-2.0-flash-001", - params: InputParams = OpenAILLMService.InputParams(), + params: Optional[InputParams] = None, **kwargs, ): """Initializes the VertexLLMService. @@ -64,6 +64,7 @@ class GoogleVertexLLMService(OpenAILLMService): params (InputParams): Vertex AI input parameters. **kwargs: Additional arguments for OpenAILLMService. """ + params = params or OpenAILLMService.InputParams() base_url = self._get_base_url(params) self._api_key = self._get_api_token(credentials, credentials_path) diff --git a/src/pipecat/services/google/stt.py b/src/pipecat/services/google/stt.py index d7373aa71..49b8fba6f 100644 --- a/src/pipecat/services/google/stt.py +++ b/src/pipecat/services/google/stt.py @@ -412,7 +412,7 @@ class GoogleSTTService(STTService): credentials_path: Optional[str] = None, location: str = "global", sample_rate: Optional[int] = None, - params: InputParams = InputParams(), + params: Optional[InputParams] = None, **kwargs, ): """Initialize the Google STT service. @@ -431,6 +431,8 @@ class GoogleSTTService(STTService): """ super().__init__(sample_rate=sample_rate, **kwargs) + params = params or GoogleSTTService.InputParams() + self._location = location self._stream = None self._config = None diff --git a/src/pipecat/services/google/tts.py b/src/pipecat/services/google/tts.py index 487aec7a6..9725aa1c3 100644 --- a/src/pipecat/services/google/tts.py +++ b/src/pipecat/services/google/tts.py @@ -219,11 +219,13 @@ class GoogleTTSService(TTSService): credentials_path: Optional[str] = None, voice_id: str = "en-US-Neural2-A", sample_rate: Optional[int] = None, - params: InputParams = InputParams(), + params: Optional[InputParams] = None, **kwargs, ): super().__init__(sample_rate=sample_rate, **kwargs) + params = params or GoogleTTSService.InputParams() + self._settings = { "pitch": params.pitch, "rate": params.rate, diff --git a/src/pipecat/services/groq/tts.py b/src/pipecat/services/groq/tts.py index 828edf72b..6f73b1629 100644 --- a/src/pipecat/services/groq/tts.py +++ b/src/pipecat/services/groq/tts.py @@ -34,7 +34,7 @@ class GroqTTSService(TTSService): *, api_key: str, output_format: str = "wav", - params: InputParams = InputParams(), + params: Optional[InputParams] = None, model_name: str = "playai-tts", voice_id: str = "Celeste-PlayAI", sample_rate: Optional[int] = GROQ_SAMPLE_RATE, @@ -42,12 +42,15 @@ class GroqTTSService(TTSService): ): if sample_rate != self.GROQ_SAMPLE_RATE: logger.warning(f"Groq TTS only supports {self.GROQ_SAMPLE_RATE}Hz sample rate. ") + super().__init__( pause_frame_processing=True, sample_rate=sample_rate, **kwargs, ) + params = params or GroqTTSService.InputParams() + self._api_key = api_key self._model_name = model_name self._output_format = output_format diff --git a/src/pipecat/services/mem0/memory.py b/src/pipecat/services/mem0/memory.py index a5f076b6e..8c93d72c9 100644 --- a/src/pipecat/services/mem0/memory.py +++ b/src/pipecat/services/mem0/memory.py @@ -4,7 +4,7 @@ # SPDX-License-Identifier: BSD 2-Clause License # -from typing import Any, Dict, List +from typing import Any, Dict, List, Optional from loguru import logger from pydantic import BaseModel, Field @@ -49,16 +49,19 @@ class Mem0MemoryService(FrameProcessor): def __init__( self, *, - api_key: str = None, - local_config: Dict[str, Any] = {}, - user_id: str = None, - agent_id: str = None, - run_id: str = None, - params: InputParams = InputParams(), + api_key: Optional[str] = None, + local_config: Optional[Dict[str, Any]] = None, + user_id: Optional[str] = None, + agent_id: Optional[str] = None, + run_id: Optional[str] = None, + params: Optional[InputParams] = None, ): # Important: Call the parent class __init__ first super().__init__() + local_config = local_config or {} + params = params or Mem0MemoryService.InputParams() + if local_config: self.memory_client = Memory.from_config(local_config) else: diff --git a/src/pipecat/services/minimax/tts.py b/src/pipecat/services/minimax/tts.py index 8dcbab66a..932996751 100644 --- a/src/pipecat/services/minimax/tts.py +++ b/src/pipecat/services/minimax/tts.py @@ -114,11 +114,13 @@ class MiniMaxHttpTTSService(TTSService): voice_id: str = "Calm_Woman", aiohttp_session: aiohttp.ClientSession, sample_rate: Optional[int] = None, - params: InputParams = InputParams(), + params: Optional[InputParams] = None, **kwargs, ): super().__init__(sample_rate=sample_rate, **kwargs) + params = params or MiniMaxHttpTTSService.InputParams() + self._api_key = api_key self._group_id = group_id self._base_url = f"https://api.minimaxi.chat/v1/t2a_v2?GroupId={group_id}" diff --git a/src/pipecat/services/neuphonic/tts.py b/src/pipecat/services/neuphonic/tts.py index de12c8231..bfceca50b 100644 --- a/src/pipecat/services/neuphonic/tts.py +++ b/src/pipecat/services/neuphonic/tts.py @@ -80,7 +80,7 @@ class NeuphonicTTSService(InterruptibleTTSService): url: str = "wss://api.neuphonic.com", sample_rate: Optional[int] = 22050, encoding: str = "pcm_linear", - params: InputParams = InputParams(), + params: Optional[InputParams] = None, **kwargs, ): super().__init__( @@ -92,6 +92,8 @@ class NeuphonicTTSService(InterruptibleTTSService): **kwargs, ) + params = params or NeuphonicTTSService.InputParams() + self._api_key = api_key self._url = url self._settings = { @@ -293,11 +295,13 @@ class NeuphonicHttpTTSService(TTSService): url: str = "https://api.neuphonic.com", sample_rate: Optional[int] = 22050, encoding: str = "pcm_linear", - params: InputParams = InputParams(), + params: Optional[InputParams] = None, **kwargs, ): super().__init__(sample_rate=sample_rate, **kwargs) + params = params or NeuphonicHttpTTSService.InputParams() + self._api_key = api_key self._url = url self._settings = { diff --git a/src/pipecat/services/openai/base_llm.py b/src/pipecat/services/openai/base_llm.py index 641c96f5e..e90f87f3c 100644 --- a/src/pipecat/services/openai/base_llm.py +++ b/src/pipecat/services/openai/base_llm.py @@ -77,11 +77,14 @@ class BaseOpenAILLMService(LLMService): base_url=None, organization=None, project=None, - default_headers: Mapping[str, str] | None = None, - params: InputParams = InputParams(), + default_headers: Optional[Mapping[str, str]] = None, + params: Optional[InputParams] = None, **kwargs, ): super().__init__(**kwargs) + + params = params or BaseOpenAILLMService.InputParams() + self._settings = { "frequency_penalty": params.frequency_penalty, "presence_penalty": params.presence_penalty, diff --git a/src/pipecat/services/openai/llm.py b/src/pipecat/services/openai/llm.py index 07b564fe1..44e0a40ce 100644 --- a/src/pipecat/services/openai/llm.py +++ b/src/pipecat/services/openai/llm.py @@ -6,7 +6,7 @@ import json from dataclasses import dataclass -from typing import Any +from typing import Any, Optional from pipecat.frames.frames import ( FunctionCallCancelFrame, @@ -41,7 +41,7 @@ class OpenAILLMService(BaseOpenAILLMService): self, *, model: str = "gpt-4.1", - params: BaseOpenAILLMService.InputParams = BaseOpenAILLMService.InputParams(), + params: Optional[BaseOpenAILLMService.InputParams] = None, **kwargs, ): super().__init__(model=model, params=params, **kwargs) diff --git a/src/pipecat/services/openai_realtime_beta/openai.py b/src/pipecat/services/openai_realtime_beta/openai.py index 0c37f73ce..e705a9b18 100644 --- a/src/pipecat/services/openai_realtime_beta/openai.py +++ b/src/pipecat/services/openai_realtime_beta/openai.py @@ -8,6 +8,7 @@ import base64 import json import time from dataclasses import dataclass +from typing import Optional from loguru import logger @@ -89,17 +90,20 @@ class OpenAIRealtimeBetaLLMService(LLMService): api_key: str, model: str = "gpt-4o-realtime-preview-2024-12-17", base_url: str = "wss://api.openai.com/v1/realtime", - session_properties: events.SessionProperties = events.SessionProperties(), + session_properties: Optional[events.SessionProperties] = None, start_audio_paused: bool = False, send_transcription_frames: bool = True, **kwargs, ): full_url = f"{base_url}?model={model}" super().__init__(base_url=full_url, **kwargs) + self.api_key = api_key self.base_url = full_url - self._session_properties: events.SessionProperties = session_properties + self._session_properties: events.SessionProperties = ( + session_properties or events.SessionProperties() + ) self._audio_input_paused = start_audio_paused self._send_transcription_frames = send_transcription_frames self._websocket = None diff --git a/src/pipecat/services/playht/tts.py b/src/pipecat/services/playht/tts.py index 865b267c9..34fc6c81a 100644 --- a/src/pipecat/services/playht/tts.py +++ b/src/pipecat/services/playht/tts.py @@ -110,7 +110,7 @@ class PlayHTTTSService(InterruptibleTTSService): voice_engine: str = "Play3.0-mini", sample_rate: Optional[int] = None, output_format: str = "wav", - params: InputParams = InputParams(), + params: Optional[InputParams] = None, **kwargs, ): super().__init__( @@ -119,6 +119,8 @@ class PlayHTTTSService(InterruptibleTTSService): **kwargs, ) + params = params or PlayHTTTSService.InputParams() + self._api_key = api_key self._user_id = user_id self._websocket_url = None @@ -328,11 +330,13 @@ class PlayHTHttpTTSService(TTSService): voice_engine: str = "Play3.0-mini", protocol: str = "http", # Options: http, ws sample_rate: Optional[int] = None, - params: InputParams = InputParams(), + params: Optional[InputParams] = None, **kwargs, ): super().__init__(sample_rate=sample_rate, **kwargs) + params = params or PlayHTHttpTTSService.InputParams() + self._user_id = user_id self._api_key = api_key diff --git a/src/pipecat/services/rime/tts.py b/src/pipecat/services/rime/tts.py index 09a633456..b3f46961f 100644 --- a/src/pipecat/services/rime/tts.py +++ b/src/pipecat/services/rime/tts.py @@ -80,7 +80,7 @@ class RimeTTSService(AudioContextWordTTSService): url: str = "wss://users.rime.ai/ws2", model: str = "mistv2", sample_rate: Optional[int] = None, - params: InputParams = InputParams(), + params: Optional[InputParams] = None, text_aggregator: Optional[BaseTextAggregator] = None, **kwargs, ): @@ -105,6 +105,8 @@ class RimeTTSService(AudioContextWordTTSService): **kwargs, ) + params = params or RimeTTSService.InputParams() + # Store service configuration self._api_key = api_key self._url = url @@ -364,11 +366,13 @@ class RimeHttpTTSService(TTSService): aiohttp_session: aiohttp.ClientSession, model: str = "mistv2", sample_rate: Optional[int] = None, - params: InputParams = InputParams(), + params: Optional[InputParams] = None, **kwargs, ): super().__init__(sample_rate=sample_rate, **kwargs) + params = params or RimeHttpTTSService.InputParams() + self._api_key = api_key self._session = aiohttp_session self._base_url = "https://users.rime.ai/v1/rime-tts" diff --git a/src/pipecat/services/riva/stt.py b/src/pipecat/services/riva/stt.py index b70d63e4e..92a3463c3 100644 --- a/src/pipecat/services/riva/stt.py +++ b/src/pipecat/services/riva/stt.py @@ -99,10 +99,13 @@ class RivaSTTService(STTService): "model_name": "parakeet-ctc-1.1b-asr", }, sample_rate: Optional[int] = None, - params: InputParams = InputParams(), + params: Optional[InputParams] = None, **kwargs, ): super().__init__(sample_rate=sample_rate, **kwargs) + + params = params or RivaSTTService.InputParams() + self._api_key = api_key self._profanity_filter = False self._automatic_punctuation = True @@ -322,11 +325,13 @@ class RivaSegmentedSTTService(SegmentedSTTService): "model_name": "canary-1b-asr", }, sample_rate: Optional[int] = None, - params: InputParams = InputParams(), + params: Optional[InputParams] = None, **kwargs, ): super().__init__(sample_rate=sample_rate, **kwargs) + params = params or RivaSegmentedSTTService.InputParams() + # Set model name self.set_model_name(model_function_map.get("model_name")) @@ -533,7 +538,7 @@ class ParakeetSTTService(RivaSTTService): "model_name": "parakeet-ctc-1.1b-asr", }, sample_rate: Optional[int] = None, - params: RivaSTTService.InputParams = RivaSTTService.InputParams(), # Use parent class's type + params: Optional[RivaSTTService.InputParams] = None, # Use parent class's type **kwargs, ): super().__init__( diff --git a/src/pipecat/services/riva/tts.py b/src/pipecat/services/riva/tts.py index a61155685..31850ea17 100644 --- a/src/pipecat/services/riva/tts.py +++ b/src/pipecat/services/riva/tts.py @@ -44,7 +44,7 @@ class RivaTTSService(TTSService): def __init__( self, *, - api_key: str = None, + api_key: str, server: str = "grpc.nvcf.nvidia.com:443", voice_id: str = "Magpie-Multilingual.EN-US.Ray", sample_rate: Optional[int] = None, @@ -52,10 +52,13 @@ class RivaTTSService(TTSService): "function_id": "877104f7-e885-42b9-8de8-f6e4c6303969", "model_name": "magpie-tts-multilingual", }, - params: InputParams = InputParams(), + params: Optional[InputParams] = None, **kwargs, ): super().__init__(sample_rate=sample_rate, **kwargs) + + params = params or RivaTTSService.InputParams() + self._api_key = api_key self._voice_id = voice_id self._language_code = params.language @@ -136,14 +139,10 @@ class RivaTTSService(TTSService): class FastPitchTTSService(RivaTTSService): - class InputParams(BaseModel): - language: Optional[Language] = Language.EN_US - quality: Optional[int] = 20 - def __init__( self, *, - api_key: str = None, + api_key: str, server: str = "grpc.nvcf.nvidia.com:443", voice_id: str = "English-US.Female-1", sample_rate: Optional[int] = None, @@ -151,11 +150,12 @@ class FastPitchTTSService(RivaTTSService): "function_id": "0149dedb-2be8-4195-b9a0-e57e0e14f972", "model_name": "fastpitch-hifigan-tts", }, - params: InputParams = InputParams(), + params: Optional[RivaTTSService.InputParams] = None, **kwargs, ): super().__init__( api_key=api_key, + server=server, voice_id=voice_id, sample_rate=sample_rate, model_function_map=model_function_map, diff --git a/src/pipecat/services/tts_service.py b/src/pipecat/services/tts_service.py index ed37caa01..cb0e2ea45 100644 --- a/src/pipecat/services/tts_service.py +++ b/src/pipecat/services/tts_service.py @@ -64,7 +64,7 @@ class TTSService(AIService): # Text aggregator to aggregate incoming tokens and decide when to push to the TTS. text_aggregator: Optional[BaseTextAggregator] = None, # Text filter executed after text has been aggregated. - text_filters: Sequence[BaseTextFilter] = [], + text_filters: Optional[Sequence[BaseTextFilter]] = None, text_filter: Optional[BaseTextFilter] = None, # Audio transport destination of the generated frames. transport_destination: Optional[str] = None, @@ -83,7 +83,7 @@ class TTSService(AIService): self._voice_id: str = "" self._settings: Dict[str, Any] = {} self._text_aggregator: BaseTextAggregator = text_aggregator or SimpleTextAggregator() - self._text_filters: Sequence[BaseTextFilter] = text_filters + self._text_filters: Sequence[BaseTextFilter] = text_filters or [] self._transport_destination: Optional[str] = transport_destination if text_filter: diff --git a/src/pipecat/tests/utils.py b/src/pipecat/tests/utils.py index 3f5182044..afa5a9949 100644 --- a/src/pipecat/tests/utils.py +++ b/src/pipecat/tests/utils.py @@ -79,10 +79,13 @@ async def run_test( expected_down_frames: Optional[Sequence[type]] = None, expected_up_frames: Optional[Sequence[type]] = None, ignore_start: bool = True, - observers: List[BaseObserver] = [], - start_metadata: Dict[str, Any] = {}, + observers: Optional[List[BaseObserver]] = None, + start_metadata: Optional[Dict[str, Any]] = None, send_end_frame: bool = True, ) -> Tuple[Sequence[Frame], Sequence[Frame]]: + observers = observers or [] + start_metadata = start_metadata or {} + received_up = asyncio.Queue() received_down = asyncio.Queue() source = QueuedFrameProcessor( diff --git a/src/pipecat/transports/network/websocket_client.py b/src/pipecat/transports/network/websocket_client.py index 535a0ab21..693be54c9 100644 --- a/src/pipecat/transports/network/websocket_client.py +++ b/src/pipecat/transports/network/websocket_client.py @@ -250,11 +250,11 @@ class WebsocketClientTransport(BaseTransport): def __init__( self, uri: str, - params: WebsocketClientParams = WebsocketClientParams(), + params: Optional[WebsocketClientParams] = None, ): super().__init__() - self._params = params + self._params = params or WebsocketClientParams() callbacks = WebsocketClientCallbacks( on_connected=self._on_connected, @@ -262,7 +262,7 @@ class WebsocketClientTransport(BaseTransport): on_message=self._on_message, ) - self._session = WebsocketClientSession(uri, params, callbacks, self.name) + self._session = WebsocketClientSession(uri, self._params, callbacks, self.name) self._input: Optional[WebsocketClientInputTransport] = None self._output: Optional[WebsocketClientOutputTransport] = None diff --git a/src/pipecat/transports/services/daily.py b/src/pipecat/transports/services/daily.py index b31396433..095084037 100644 --- a/src/pipecat/transports/services/daily.py +++ b/src/pipecat/transports/services/daily.py @@ -95,7 +95,7 @@ class WebRTCVADAnalyzer(VADAnalyzer): params: VAD configuration parameters (VADParams). """ - def __init__(self, *, sample_rate: Optional[int] = None, params: VADParams = VADParams()): + def __init__(self, *, sample_rate: Optional[int] = None, params: Optional[VADParams] = None): super().__init__(sample_rate=sample_rate, params=params) self._webrtc_vad = Daily.create_native_vad( @@ -1223,7 +1223,7 @@ class DailyTransport(BaseTransport): room_url: str, token: Optional[str], bot_name: str, - params: DailyParams = DailyParams(), + params: Optional[DailyParams] = None, input_name: Optional[str] = None, output_name: Optional[str] = None, ): @@ -1256,9 +1256,11 @@ class DailyTransport(BaseTransport): on_recording_stopped=self._on_recording_stopped, on_recording_error=self._on_recording_error, ) - self._params = params + self._params = params or DailyParams() - self._client = DailyTransportClient(room_url, token, bot_name, params, callbacks, self.name) + self._client = DailyTransportClient( + room_url, token, bot_name, self._params, callbacks, self.name + ) self._input: Optional[DailyInputTransport] = None self._output: Optional[DailyOutputTransport] = None diff --git a/src/pipecat/transports/services/livekit.py b/src/pipecat/transports/services/livekit.py index 4f215d04f..53a9b1789 100644 --- a/src/pipecat/transports/services/livekit.py +++ b/src/pipecat/transports/services/livekit.py @@ -499,7 +499,7 @@ class LiveKitTransport(BaseTransport): url: str, token: str, room_name: str, - params: LiveKitParams = LiveKitParams(), + params: Optional[LiveKitParams] = None, input_name: Optional[str] = None, output_name: Optional[str] = None, ): @@ -515,7 +515,7 @@ class LiveKitTransport(BaseTransport): on_data_received=self._on_data_received, on_first_participant_joined=self._on_first_participant_joined, ) - self._params = params + self._params = params or LiveKitParams() self._client = LiveKitTransportClient( url, token, room_name, self._params, callbacks, self.name diff --git a/src/pipecat/utils/text/markdown_text_filter.py b/src/pipecat/utils/text/markdown_text_filter.py index 3bac0cb95..c5ace159e 100644 --- a/src/pipecat/utils/text/markdown_text_filter.py +++ b/src/pipecat/utils/text/markdown_text_filter.py @@ -26,9 +26,9 @@ class MarkdownTextFilter(BaseTextFilter): filter_code: Optional[bool] = False filter_tables: Optional[bool] = False - def __init__(self, params: InputParams = InputParams(), **kwargs): + def __init__(self, params: Optional[InputParams] = None, **kwargs): super().__init__(**kwargs) - self._settings = params + self._settings = params or MarkdownTextFilter.InputParams() self._in_code_block = False self._in_table = False self._interrupted = False