diff --git a/.github/workflows/python-compatibility.yaml b/.github/workflows/python-compatibility.yaml index 26f58f9dc..d0114f115 100644 --- a/.github/workflows/python-compatibility.yaml +++ b/.github/workflows/python-compatibility.yaml @@ -42,7 +42,7 @@ jobs: - name: Test uv sync with all extras run: | - uv sync --group dev --all-extras --no-extra krisp + uv sync --group dev --all-extras - name: Verify installation run: | diff --git a/README.md b/README.md index ddd4db1dc..9693941f4 100644 --- a/README.md +++ b/README.md @@ -166,7 +166,6 @@ You can get started with Pipecat running on your local machine, then move your a ```bash uv sync --group dev --all-extras \ --no-extra gstreamer \ - --no-extra krisp \ --no-extra local \ ``` diff --git a/changelog/4204.removed.10.md b/changelog/4204.removed.10.md new file mode 100644 index 000000000..a75617e4a --- /dev/null +++ b/changelog/4204.removed.10.md @@ -0,0 +1 @@ +- ⚠️ Removed deprecated `observers` field from `PipelineParams`. Pass observers directly to `PipelineTask` constructor instead. diff --git a/changelog/4204.removed.11.md b/changelog/4204.removed.11.md new file mode 100644 index 000000000..d54a8ce51 --- /dev/null +++ b/changelog/4204.removed.11.md @@ -0,0 +1 @@ +- ⚠️ Removed deprecated `on_pipeline_ended`, `on_pipeline_cancelled`, and `on_pipeline_stopped` events from `PipelineTask`. Use `on_pipeline_finished` instead. diff --git a/changelog/4204.removed.12.md b/changelog/4204.removed.12.md new file mode 100644 index 000000000..d238d0820 --- /dev/null +++ b/changelog/4204.removed.12.md @@ -0,0 +1 @@ +- ⚠️ Removed `AudioBufferProcessor.user_continuous_stream` parameter. Use `user_audio_passthrough` instead. diff --git a/changelog/4204.removed.13.md b/changelog/4204.removed.13.md new file mode 100644 index 000000000..6fe408fba --- /dev/null +++ b/changelog/4204.removed.13.md @@ -0,0 +1 @@ +- ⚠️ Removed deprecated `camera_in_enabled`, `camera_in_is_live`, `camera_in_width`, `camera_in_height`, `camera_out_enabled`, `camera_out_is_live`, `camera_out_width`, `camera_out_height`, and `camera_out_color` transport params. Use the `video_in_*` and `video_out_*` equivalents instead. diff --git a/changelog/4204.removed.14.md b/changelog/4204.removed.14.md new file mode 100644 index 000000000..e69561e30 --- /dev/null +++ b/changelog/4204.removed.14.md @@ -0,0 +1 @@ +- ⚠️ Removed `RTVIObserver.errors_enabled` parameter. diff --git a/changelog/4204.removed.15.md b/changelog/4204.removed.15.md new file mode 100644 index 000000000..1eaf96471 --- /dev/null +++ b/changelog/4204.removed.15.md @@ -0,0 +1 @@ +- ⚠️ Removed deprecated `vad_enabled` and `vad_audio_passthrough` transport params. diff --git a/changelog/4204.removed.16.md b/changelog/4204.removed.16.md new file mode 100644 index 000000000..05668ad6d --- /dev/null +++ b/changelog/4204.removed.16.md @@ -0,0 +1 @@ +- ⚠️ Removed `TTSService.say()`. Push a `TTSSpeakFrame` into the pipeline instead. diff --git a/changelog/4204.removed.17.md b/changelog/4204.removed.17.md new file mode 100644 index 000000000..4edafe2db --- /dev/null +++ b/changelog/4204.removed.17.md @@ -0,0 +1 @@ +- ⚠️ Removed `DailyRunner.configure_with_args()`. Use `PipelineRunner` with `RunnerArguments` instead. diff --git a/changelog/4204.removed.18.md b/changelog/4204.removed.18.md new file mode 100644 index 000000000..d347cebc8 --- /dev/null +++ b/changelog/4204.removed.18.md @@ -0,0 +1 @@ +- ⚠️ Removed deprecated RTVI models, frames, and processor methods including `RTVIConfig`, `RTVIServiceConfig`, `RTVIServiceOptionConfig`, various `RTVI*Data` models, `RTVIActionFrame`, and `RTVIProcessor.handle_function_call`/`handle_function_call_start`. Use the updated RTVI processor API instead. diff --git a/changelog/4204.removed.19.md b/changelog/4204.removed.19.md new file mode 100644 index 000000000..336bdb769 --- /dev/null +++ b/changelog/4204.removed.19.md @@ -0,0 +1 @@ +- ⚠️ Removed `FrameProcessor.wait_for_task()`. Use `create_task()` and manage tasks with the built-in `TaskManager` instead. diff --git a/changelog/4204.removed.2.md b/changelog/4204.removed.2.md new file mode 100644 index 000000000..615bcd4ea --- /dev/null +++ b/changelog/4204.removed.2.md @@ -0,0 +1 @@ +- ⚠️ Removed `KrispFilter`. The `krisp` extra has been removed from `pyproject.toml`. diff --git a/changelog/4204.removed.20.md b/changelog/4204.removed.20.md new file mode 100644 index 000000000..9f9f8921e --- /dev/null +++ b/changelog/4204.removed.20.md @@ -0,0 +1 @@ +- ⚠️ Removed `LLMService.request_image_frame()`. Push a `UserImageRequestFrame` instead. diff --git a/changelog/4204.removed.3.md b/changelog/4204.removed.3.md new file mode 100644 index 000000000..c0f78f7b4 --- /dev/null +++ b/changelog/4204.removed.3.md @@ -0,0 +1 @@ +- ⚠️ Removed `create_default_resampler()` from `pipecat.audio.utils`. diff --git a/changelog/4204.removed.4.md b/changelog/4204.removed.4.md new file mode 100644 index 000000000..a0cc5745d --- /dev/null +++ b/changelog/4204.removed.4.md @@ -0,0 +1 @@ +- ⚠️ Removed `FalSmartTurnAnalyzer` and `LocalSmartTurnAnalyzer`. diff --git a/changelog/4204.removed.5.md b/changelog/4204.removed.5.md new file mode 100644 index 000000000..cbf163d76 --- /dev/null +++ b/changelog/4204.removed.5.md @@ -0,0 +1 @@ +- ⚠️ Removed deprecated transport frames: `TransportMessageFrame`, `TransportMessageUrgentFrame`, `InputTransportMessageUrgentFrame`, `DailyTransportMessageFrame`, and `DailyTransportMessageUrgentFrame`. Use `OutputTransportMessageFrame`, `OutputTransportMessageUrgentFrame`, `InputTransportMessageFrame`, `DailyOutputTransportMessageFrame`, and `DailyOutputTransportMessageUrgentFrame` instead. diff --git a/changelog/4204.removed.6.md b/changelog/4204.removed.6.md new file mode 100644 index 000000000..baf59d50b --- /dev/null +++ b/changelog/4204.removed.6.md @@ -0,0 +1 @@ +- ⚠️ Removed deprecated `KeypadEntryFrame` alias. diff --git a/changelog/4204.removed.7.md b/changelog/4204.removed.7.md new file mode 100644 index 000000000..cae8d29e7 --- /dev/null +++ b/changelog/4204.removed.7.md @@ -0,0 +1 @@ +- ⚠️ Removed deprecated interruption frames: `StartInterruptionFrame` and `BotInterruptionFrame`. Use `InterruptionFrame` and `InterruptionTaskFrame` instead. diff --git a/changelog/4204.removed.8.md b/changelog/4204.removed.8.md new file mode 100644 index 000000000..581b5d089 --- /dev/null +++ b/changelog/4204.removed.8.md @@ -0,0 +1 @@ +- ⚠️ Removed `LLMService.start_callback` parameter. Register an `on_llm_response_start` event handler instead. diff --git a/changelog/4204.removed.9.md b/changelog/4204.removed.9.md new file mode 100644 index 000000000..0ad26ab3f --- /dev/null +++ b/changelog/4204.removed.9.md @@ -0,0 +1 @@ +- ⚠️ Removed single-argument function call support from `LLMService`. Functions must use named parameters instead of a single `arguments` parameter. diff --git a/changelog/4204.removed.md b/changelog/4204.removed.md new file mode 100644 index 000000000..aa6928bf7 --- /dev/null +++ b/changelog/4204.removed.md @@ -0,0 +1 @@ +- ⚠️ Removed `NoisereduceFilter`. Use system-level noise reduction or a service-based alternative instead. diff --git a/examples/foundational/07p-interruptible-krisp.py b/examples/foundational/07p-interruptible-krisp.py deleted file mode 100644 index 90aa076d6..000000000 --- a/examples/foundational/07p-interruptible-krisp.py +++ /dev/null @@ -1,130 +0,0 @@ -# -# Copyright (c) 2024-2026, Daily -# -# SPDX-License-Identifier: BSD 2-Clause License -# - - -import os - -from dotenv import load_dotenv -from loguru import logger - -from pipecat.audio.filters.krisp_filter import KrispFilter -from pipecat.audio.vad.silero import SileroVADAnalyzer -from pipecat.frames.frames import LLMRunFrame -from pipecat.pipeline.pipeline import Pipeline -from pipecat.pipeline.runner import PipelineRunner -from pipecat.pipeline.task import PipelineParams, PipelineTask -from pipecat.processors.aggregators.llm_context import LLMContext -from pipecat.processors.aggregators.llm_response_universal import ( - LLMContextAggregatorPair, - LLMUserAggregatorParams, -) -from pipecat.runner.types import RunnerArguments -from pipecat.runner.utils import create_transport -from pipecat.services.deepgram.stt import DeepgramSTTService -from pipecat.services.deepgram.tts import DeepgramTTSService -from pipecat.services.openai.llm import OpenAILLMService -from pipecat.transports.base_transport import BaseTransport, TransportParams -from pipecat.transports.daily.transport import DailyParams -from pipecat.transports.websocket.fastapi import FastAPIWebsocketParams - -load_dotenv(override=True) - -# We use lambdas to defer transport parameter creation until the transport -# type is selected at runtime. -transport_params = { - "daily": lambda: DailyParams( - audio_in_enabled=True, - audio_out_enabled=True, - audio_in_filter=KrispFilter(), - ), - "twilio": lambda: FastAPIWebsocketParams( - audio_in_enabled=True, - audio_out_enabled=True, - audio_in_filter=KrispFilter(), - ), - "webrtc": lambda: TransportParams( - audio_in_enabled=True, - audio_out_enabled=True, - audio_in_filter=KrispFilter(), - ), -} - - -async def run_bot(transport: BaseTransport, runner_args: RunnerArguments): - logger.info(f"Starting bot") - - stt = DeepgramSTTService(api_key=os.getenv("DEEPGRAM_API_KEY")) - - tts = DeepgramTTSService( - api_key=os.getenv("DEEPGRAM_API_KEY"), - settings=DeepgramTTSService.Settings( - voice="aura-helios-en", - ), - ) - - llm = OpenAILLMService( - api_key=os.getenv("OPENAI_API_KEY"), - settings=OpenAILLMService.Settings( - system_instruction="You are a helpful assistant in a voice conversation. Your responses will be spoken aloud, so avoid emojis, bullet points, or other formatting that can't be spoken. Respond to what the user said in a creative, helpful, and brief way.", - ), - ) - - context = LLMContext() - user_aggregator, assistant_aggregator = LLMContextAggregatorPair( - context, - user_params=LLMUserAggregatorParams(vad_analyzer=SileroVADAnalyzer()), - ) - - pipeline = Pipeline( - [ - transport.input(), # Transport user input - stt, # STT - user_aggregator, # User responses - llm, # LLM - tts, # TTS - transport.output(), # Transport bot output - assistant_aggregator, # Assistant spoken responses - ] - ) - - task = PipelineTask( - pipeline, - params=PipelineParams( - enable_metrics=True, - enable_usage_metrics=True, - ), - idle_timeout_secs=runner_args.pipeline_idle_timeout_secs, - ) - - @transport.event_handler("on_client_connected") - async def on_client_connected(transport, client): - logger.info(f"Client connected") - # Kick off the conversation. - context.add_message( - {"role": "developer", "content": "Please introduce yourself to the user."} - ) - await task.queue_frames([LLMRunFrame()]) - - @transport.event_handler("on_client_disconnected") - async def on_client_disconnected(transport, client): - logger.info(f"Client disconnected") - await task.cancel() - - runner = PipelineRunner(handle_sigint=runner_args.handle_sigint) - - await runner.run(task) - - -async def bot(runner_args: RunnerArguments): - """Main bot entry point compatible with Pipecat Cloud.""" - transport = await create_transport(runner_args, transport_params) - await run_bot(transport, runner_args) - - -if __name__ == "__main__": - from pipecat.runner.run import main - - main() diff --git a/examples/foundational/38-smart-turn-fal.py b/examples/foundational/38-smart-turn-fal.py deleted file mode 100644 index 432bc3844..000000000 --- a/examples/foundational/38-smart-turn-fal.py +++ /dev/null @@ -1,143 +0,0 @@ -# -# Copyright (c) 2024-2026, Daily -# -# SPDX-License-Identifier: BSD 2-Clause License -# - - -import os - -import aiohttp -from dotenv import load_dotenv -from loguru import logger - -from pipecat.audio.turn.smart_turn.fal_smart_turn import FalSmartTurnAnalyzer -from pipecat.audio.vad.silero import SileroVADAnalyzer -from pipecat.frames.frames import LLMRunFrame -from pipecat.pipeline.pipeline import Pipeline -from pipecat.pipeline.runner import PipelineRunner -from pipecat.pipeline.task import PipelineParams, PipelineTask -from pipecat.processors.aggregators.llm_context import LLMContext -from pipecat.processors.aggregators.llm_response_universal import ( - LLMContextAggregatorPair, - LLMUserAggregatorParams, -) -from pipecat.runner.types import RunnerArguments -from pipecat.runner.utils import create_transport -from pipecat.services.cartesia.tts import CartesiaTTSService -from pipecat.services.deepgram.stt import DeepgramSTTService -from pipecat.services.openai.llm import OpenAILLMService -from pipecat.transports.base_transport import BaseTransport, TransportParams -from pipecat.transports.daily.transport import DailyParams -from pipecat.transports.websocket.fastapi import FastAPIWebsocketParams -from pipecat.turns.user_stop import TurnAnalyzerUserTurnStopStrategy -from pipecat.turns.user_turn_strategies import UserTurnStrategies - -load_dotenv(override=True) - - -# We use lambdas to defer transport parameter creation until the transport -# type is selected at runtime. -transport_params = { - "daily": lambda: DailyParams( - audio_in_enabled=True, - audio_out_enabled=True, - ), - "twilio": lambda: FastAPIWebsocketParams( - audio_in_enabled=True, - audio_out_enabled=True, - ), - "webrtc": lambda: TransportParams( - audio_in_enabled=True, - audio_out_enabled=True, - ), -} - - -async def run_bot(transport: BaseTransport, runner_args: RunnerArguments): - logger.info(f"Starting bot") - - stt = DeepgramSTTService(api_key=os.getenv("DEEPGRAM_API_KEY")) - - tts = CartesiaTTSService( - api_key=os.getenv("CARTESIA_API_KEY"), - settings=CartesiaTTSService.Settings( - voice="71a7ad14-091c-4e8e-a314-022ece01c121", # British Reading Lady - ), - ) - - llm = OpenAILLMService( - api_key=os.getenv("OPENAI_API_KEY"), - settings=OpenAILLMService.Settings( - system_instruction="You are a helpful assistant in a voice conversation. Your responses will be spoken aloud, so avoid emojis, bullet points, or other formatting that can't be spoken. Respond to what the user said in a creative, helpful, and brief way.", - ), - ) - - context = LLMContext() - user_aggregator, assistant_aggregator = LLMContextAggregatorPair( - context, - user_params=LLMUserAggregatorParams( - user_turn_strategies=UserTurnStrategies( - stop=[ - TurnAnalyzerUserTurnStopStrategy( - turn_analyzer=FalSmartTurnAnalyzer( - api_key=os.getenv("FAL_SMART_TURN_API_KEY"), - aiohttp_session=aiohttp.ClientSession(), - ) - ) - ] - ), - vad_analyzer=SileroVADAnalyzer(), - ), - ) - - pipeline = Pipeline( - [ - transport.input(), # Transport user input - stt, - user_aggregator, # User responses - llm, # LLM - tts, # TTS - transport.output(), # Transport bot output - assistant_aggregator, # Assistant spoken responses - ] - ) - - task = PipelineTask( - pipeline, - params=PipelineParams( - enable_metrics=True, - enable_usage_metrics=True, - ), - idle_timeout_secs=runner_args.pipeline_idle_timeout_secs, - ) - - @transport.event_handler("on_client_connected") - async def on_client_connected(transport, client): - logger.info(f"Client connected") - # Kick off the conversation. - context.add_message( - {"role": "developer", "content": "Please introduce yourself to the user."} - ) - await task.queue_frames([LLMRunFrame()]) - - @transport.event_handler("on_client_disconnected") - async def on_client_disconnected(transport, client): - logger.info(f"Client disconnected") - await task.cancel() - - runner = PipelineRunner(handle_sigint=runner_args.handle_sigint) - - await runner.run(task) - - -async def bot(runner_args: RunnerArguments): - """Main bot entry point compatible with Pipecat Cloud.""" - transport = await create_transport(runner_args, transport_params) - await run_bot(transport, runner_args) - - -if __name__ == "__main__": - from pipecat.runner.run import main - - main() diff --git a/pyproject.toml b/pyproject.toml index 851c8c709..9eea482eb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -80,7 +80,6 @@ hume = [ "hume>=0.11.2,<1" ] inworld = [] koala = [ "pvkoala~=2.0.3" ] kokoro = [ "kokoro-onnx>=0.5.0,<1", "requests>=2.32.5,<3" ] -krisp = [ "pipecat-ai-krisp~=0.4.0" ] langchain = [ "langchain>=1.2.13,<2", "langchain-community>=0.4.1,<1", "langchain-openai>=1.1.12,<2" ] lemonslice = [ "pipecat-ai[daily]" ] livekit = [ "livekit>=1.0.13,<2", "livekit-api>=1.0.5,<2", "tenacity>=8.2.3,<10.0.0", "pyjwt>=2.12.0,<3" ] @@ -94,7 +93,6 @@ mlx-whisper = [ "mlx-whisper~=0.4.2" ] moondream = [ "accelerate~=1.10.0", "einops~=0.8.0", "pyvips[binary]~=3.0.0", "timm~=1.0.13", "transformers>=4.48.0,<6" ] nebius = [] neuphonic = [ "pipecat-ai[websockets-base]" ] -noisereduce = [ "noisereduce~=3.0.3" ] novita = [] nvidia = [ "nvidia-riva-client>=2.25.1,<3" ] openai = [ "pipecat-ai[websockets-base]" ] diff --git a/src/pipecat/audio/filters/krisp_filter.py b/src/pipecat/audio/filters/krisp_filter.py deleted file mode 100644 index 58c4a2835..000000000 --- a/src/pipecat/audio/filters/krisp_filter.py +++ /dev/null @@ -1,162 +0,0 @@ -# -# Copyright (c) 2024-2026, Daily -# -# SPDX-License-Identifier: BSD 2-Clause License -# - -"""Krisp noise reduction audio filter for Pipecat. - -This module provides an audio filter implementation using Krisp's noise -reduction technology to suppress background noise in audio streams. -""" - -import os - -import numpy as np -from loguru import logger - -from pipecat.audio.filters.base_audio_filter import BaseAudioFilter -from pipecat.frames.frames import FilterControlFrame, FilterEnableFrame - -try: - from pipecat_ai_krisp.audio.krisp_processor import KrispAudioProcessor -except ModuleNotFoundError as e: - logger.error(f"Exception: {e}") - logger.error("In order to use the Krisp filter, you need to `pip install pipecat-ai[krisp]`.") - raise Exception(f"Missing module: {e}") - - -class KrispProcessorManager: - """Singleton manager for KrispAudioProcessor instances. - - Ensures that only one KrispAudioProcessor instance exists for the entire - program. - """ - - _krisp_instance = None - - @classmethod - def get_processor(cls, sample_rate: int, sample_type: str, channels: int, model_path: str): - """Get or create a KrispAudioProcessor instance. - - Args: - sample_rate: Audio sample rate in Hz. - sample_type: Audio sample type (e.g., "PCM_16"). - channels: Number of audio channels. - model_path: Path to the Krisp model file. - - Returns: - Shared KrispAudioProcessor instance. - """ - if cls._krisp_instance is None: - cls._krisp_instance = KrispAudioProcessor( - sample_rate, sample_type, channels, model_path - ) - return cls._krisp_instance - - -class KrispFilter(BaseAudioFilter): - """Audio filter using Krisp noise reduction technology. - - Provides real-time noise reduction for audio streams using Krisp's - proprietary noise suppression algorithms. Requires a Krisp model file - for operation. - - .. deprecated:: 0.0.94 - The KrispFilter is deprecated and will be removed in a future version. - Use KrispVivaFilter instead. - """ - - def __init__( - self, sample_type: str = "PCM_16", channels: int = 1, model_path: str = None - ) -> None: - """Initialize the Krisp noise reduction filter. - - Args: - sample_type: The audio sample format. Defaults to "PCM_16". - channels: Number of audio channels. Defaults to 1. - model_path: Path to the Krisp model file. If None, uses KRISP_MODEL_PATH - environment variable. - - Raises: - ValueError: If model_path is not provided and KRISP_MODEL_PATH is not set. - """ - super().__init__() - - import warnings - - with warnings.catch_warnings(): - warnings.simplefilter("always") - warnings.warn( - "KrispFilter is deprecated and will be removed in a future version. " - "Use KrispVivaFilter instead.", - DeprecationWarning, - stacklevel=2, - ) - - # Set model path, checking environment if not specified - self._model_path = model_path or os.getenv("KRISP_MODEL_PATH") - if not self._model_path: - logger.error( - "Model path for KrispAudioProcessor is not provided and KRISP_MODEL_PATH is not set." - ) - raise ValueError("Model path for KrispAudioProcessor must be provided.") - - self._sample_type = sample_type - self._channels = channels - self._sample_rate = 0 - self._filtering = True - self._krisp_processor = None - - async def start(self, sample_rate: int): - """Initialize the Krisp processor with the transport's sample rate. - - Args: - sample_rate: The sample rate of the input transport in Hz. - """ - self._sample_rate = sample_rate - self._krisp_processor = KrispProcessorManager.get_processor( - self._sample_rate, self._sample_type, self._channels, self._model_path - ) - - async def stop(self): - """Clean up the Krisp processor when stopping.""" - self._krisp_processor = None - - async def process_frame(self, frame: FilterControlFrame): - """Process control frames to enable/disable filtering. - - Args: - frame: The control frame containing filter commands. - """ - if isinstance(frame, FilterEnableFrame): - self._filtering = frame.enable - - async def filter(self, audio: bytes) -> bytes: - """Apply Krisp noise reduction to audio data. - - Converts audio to float32, applies Krisp noise reduction processing, - and returns the filtered audio clipped to int16 range. - - Args: - audio: Raw audio data as bytes to be filtered. - - Returns: - Noise-reduced audio data as bytes. - """ - if not self._filtering: - return audio - - data = np.frombuffer(audio, dtype=np.int16) - - # Add a small epsilon to avoid division by zero. - epsilon = 1e-10 - data = data.astype(np.float32) + epsilon - - # Process the audio chunk to reduce noise - reduced_noise = self._krisp_processor.process(data) - - # Clip and set processed audio back to frame - audio = np.clip(reduced_noise, -32768, 32767).astype(np.int16).tobytes() - - return audio diff --git a/src/pipecat/audio/filters/noisereduce_filter.py b/src/pipecat/audio/filters/noisereduce_filter.py deleted file mode 100644 index 377a45ff3..000000000 --- a/src/pipecat/audio/filters/noisereduce_filter.py +++ /dev/null @@ -1,104 +0,0 @@ -# -# Copyright (c) 2024-2026, Daily -# -# SPDX-License-Identifier: BSD 2-Clause License -# - -"""Noisereduce audio filter for Pipecat. - -This module provides an audio filter implementation using the noisereduce -library to reduce background noise in audio streams through spectral -gating algorithms. -""" - -import numpy as np -from loguru import logger - -from pipecat.audio.filters.base_audio_filter import BaseAudioFilter -from pipecat.frames.frames import FilterControlFrame, FilterEnableFrame - -try: - import noisereduce as nr -except ModuleNotFoundError as e: - logger.error(f"Exception: {e}") - logger.error( - "In order to use the noisereduce filter, you need to `pip install pipecat-ai[noisereduce]`." - ) - raise Exception(f"Missing module: {e}") - - -class NoisereduceFilter(BaseAudioFilter): - """Audio filter using the noisereduce library for noise suppression. - - Applies spectral gating noise reduction algorithms to suppress background - noise in audio streams. Uses the noisereduce library's default noise - reduction parameters. - - .. deprecated:: 0.0.85 - `NoisereduceFilter` is deprecated and will be removed in a future version. - We recommend using other real-time audio filters like `KrispFilter` or `AICFilter`. - """ - - def __init__(self) -> None: - """Initialize the noisereduce filter.""" - self._filtering = True - self._sample_rate = 0 - - import warnings - - with warnings.catch_warnings(): - warnings.simplefilter("always") - warnings.warn( - "`NoisereduceFilter` is deprecated. " - "Use other real-time audio filters like `KrispFilter` or `AICFilter`.", - DeprecationWarning, - stacklevel=2, - ) - - async def start(self, sample_rate: int): - """Initialize the filter with the transport's sample rate. - - Args: - sample_rate: The sample rate of the input transport in Hz. - """ - self._sample_rate = sample_rate - - async def stop(self): - """Clean up the filter when stopping.""" - pass - - async def process_frame(self, frame: FilterControlFrame): - """Process control frames to enable/disable filtering. - - Args: - frame: The control frame containing filter commands. - """ - if isinstance(frame, FilterEnableFrame): - self._filtering = frame.enable - - async def filter(self, audio: bytes) -> bytes: - """Apply noise reduction to audio data using spectral gating. - - Converts audio to float32, applies noisereduce processing, and returns - the filtered audio clipped to int16 range. - - Args: - audio: Raw audio data as bytes to be filtered. - - Returns: - Noise-reduced audio data as bytes. - """ - if not self._filtering: - return audio - - data = np.frombuffer(audio, dtype=np.int16) - - # Add a small epsilon to avoid division by zero. - epsilon = 1e-10 - data = data.astype(np.float32) + epsilon - - # Noise reduction - reduced_noise = nr.reduce_noise(y=data, sr=self._sample_rate) - audio = np.clip(reduced_noise, -32768, 32767).astype(np.int16).tobytes() - - return audio diff --git a/src/pipecat/audio/turn/smart_turn/fal_smart_turn.py b/src/pipecat/audio/turn/smart_turn/fal_smart_turn.py deleted file mode 100644 index 231ce8901..000000000 --- a/src/pipecat/audio/turn/smart_turn/fal_smart_turn.py +++ /dev/null @@ -1,64 +0,0 @@ -# -# Copyright (c) 2024-2026, Daily -# -# SPDX-License-Identifier: BSD 2-Clause License -# - -"""Fal.ai smart turn analyzer implementation. - -This module provides a smart turn analyzer that uses Fal.ai's hosted smart-turn model -for end-of-turn detection in conversations. - -Note: To learn more about the smart-turn model, visit: - - https://fal.ai/models/fal-ai/smart-turn/playground - - https://github.com/pipecat-ai/smart-turn -""" - -import warnings -from typing import Optional - -import aiohttp - -from pipecat.audio.turn.smart_turn.http_smart_turn import HttpSmartTurnAnalyzer - - -class FalSmartTurnAnalyzer(HttpSmartTurnAnalyzer): - """Smart turn analyzer using Fal.ai's hosted smart-turn model. - - Extends HttpSmartTurnAnalyzer to provide integration with Fal.ai's - smart turn detection API endpoint with proper authentication. - - .. deprecated:: 0.98.0 - FalSmartTurnAnalyzer is deprecated and will be removed in a future version. - Use LocalSmartTurnAnalyzerV3 instead. - """ - - def __init__( - self, - *, - aiohttp_session: aiohttp.ClientSession, - url: str = "https://fal.run/fal-ai/smart-turn/raw", - api_key: Optional[str] = None, - **kwargs, - ): - """Initialize the Fal.ai smart turn analyzer. - - Args: - aiohttp_session: HTTP client session for making API requests. - url: Fal.ai API endpoint URL for smart turn detection. - api_key: API key for authenticating with Fal.ai service. - **kwargs: Additional arguments passed to parent HttpSmartTurnAnalyzer. - """ - headers = {} - if api_key: - headers = {"Authorization": f"Key {api_key}"} - super().__init__(url=url, aiohttp_session=aiohttp_session, headers=headers, **kwargs) - - with warnings.catch_warnings(): - warnings.simplefilter("always") - warnings.warn( - "FalSmartTurnAnalyzer is deprecated and will be removed in a future version. " - "Use LocalSmartTurnAnalyzerV3 instead.", - DeprecationWarning, - stacklevel=2, - ) diff --git a/src/pipecat/audio/turn/smart_turn/local_smart_turn.py b/src/pipecat/audio/turn/smart_turn/local_smart_turn.py deleted file mode 100644 index 791b63af1..000000000 --- a/src/pipecat/audio/turn/smart_turn/local_smart_turn.py +++ /dev/null @@ -1,107 +0,0 @@ -# -# Copyright (c) 2024-2026, Daily -# -# SPDX-License-Identifier: BSD 2-Clause License -# - -"""Local PyTorch smart turn analyzer for on-device ML inference. - -This module provides a smart turn analyzer that uses PyTorch models for -local end-of-turn detection without requiring network connectivity. -""" - -import warnings -from typing import Any, Dict - -import numpy as np -from loguru import logger - -from pipecat.audio.turn.smart_turn.base_smart_turn import BaseSmartTurn - -try: - import torch - from transformers import AutoFeatureExtractor, Wav2Vec2BertForSequenceClassification -except ModuleNotFoundError as e: - logger.error(f"Exception: {e}") - logger.error( - "In order to use the LocalSmartTurnAnalyzer, you need to `pip install pipecat-ai[local-smart-turn]`." - ) - raise Exception(f"Missing module: {e}") - - -class LocalSmartTurnAnalyzer(BaseSmartTurn): - """Local smart turn analyzer using PyTorch models. - - Provides end-of-turn detection using locally-stored PyTorch models, - enabling offline operation without network dependencies. Uses - Wav2Vec2-BERT architecture for audio sequence classification. - - .. deprecated:: 0.0.98 - LocalSmartTurnAnalyzer is deprecated and will be removed in a future version. - Use LocalSmartTurnAnalyzerV3 instead. - """ - - def __init__(self, *, smart_turn_model_path: str, **kwargs): - """Initialize the local PyTorch smart turn analyzer. - - Args: - smart_turn_model_path: Path to directory containing the PyTorch model - and feature extractor files. If empty, uses default HuggingFace model. - **kwargs: Additional arguments passed to BaseSmartTurn. - """ - super().__init__(**kwargs) - - with warnings.catch_warnings(): - warnings.simplefilter("always") - warnings.warn( - "LocalSmartTurnAnalyzer is deprecated and will be removed in a future version. " - "Use LocalSmartTurnAnalyzerV3 instead.", - DeprecationWarning, - stacklevel=2, - ) - - if not smart_turn_model_path: - # Define the path to the pretrained model on Hugging Face - smart_turn_model_path = "pipecat-ai/smart-turn" - - logger.debug("Loading Local Smart Turn model...") - # Load the pretrained model for sequence classification - self._turn_model = Wav2Vec2BertForSequenceClassification.from_pretrained( - smart_turn_model_path - ) - # Load the corresponding feature extractor for preprocessing audio - self._turn_processor = AutoFeatureExtractor.from_pretrained(smart_turn_model_path) - # Set device to GPU if available, else CPU - self._device = torch.device("cuda" if torch.cuda.is_available() else "cpu") - # Move model to selected device and set it to evaluation mode - self._turn_model = self._turn_model.to(self._device) - self._turn_model.eval() - logger.debug("Loaded Local Smart Turn") - - def _predict_endpoint(self, audio_array: np.ndarray) -> Dict[str, Any]: - """Predict end-of-turn using local PyTorch model.""" - inputs = self._turn_processor( - audio_array, - sampling_rate=16000, - padding="max_length", - truncation=True, - max_length=800, # Maximum length as specified in training - return_attention_mask=True, - return_tensors="pt", - ) - - # Move input tensors to the same device as the model - inputs = {k: v.to(self._device) for k, v in inputs.items()} - - # Disable gradient calculation for inference - with torch.no_grad(): - outputs = self._turn_model(**inputs) - logits = outputs.logits - probabilities = torch.nn.functional.softmax(logits, dim=1) - completion_prob = probabilities[0, 1].item() # Probability of class 1 (Complete) - prediction = 1 if completion_prob > 0.5 else 0 - - return { - "prediction": prediction, - "probability": completion_prob, - } diff --git a/src/pipecat/audio/utils.py b/src/pipecat/audio/utils.py index 65f451675..c05e3254b 100644 --- a/src/pipecat/audio/utils.py +++ b/src/pipecat/audio/utils.py @@ -25,34 +25,6 @@ from pipecat.audio.resamplers.soxr_stream_resampler import SOXRStreamAudioResamp SPEAKING_THRESHOLD = 20 -def create_default_resampler(**kwargs) -> BaseAudioResampler: - """Create a default audio resampler instance. - - .. deprecated:: 0.0.74 - This function is deprecated and will be removed in a future version. - Use `create_stream_resampler` for real-time processing scenarios or - `create_file_resampler` for batch processing of complete audio files. - - Args: - **kwargs: Additional keyword arguments passed to the resampler constructor. - - Returns: - A configured SOXRAudioResampler instance. - """ - import warnings - - with warnings.catch_warnings(): - warnings.simplefilter("always") - warnings.warn( - "`create_default_resampler` is deprecated. " - "Use `create_stream_resampler` for real-time processing scenarios or " - "`create_file_resampler` for batch processing of complete audio files.", - DeprecationWarning, - stacklevel=2, - ) - return SOXRAudioResampler(**kwargs) - - def create_file_resampler(**kwargs) -> BaseAudioResampler: """Create an audio resampler instance for batch processing of complete audio files. diff --git a/src/pipecat/frames/frames.py b/src/pipecat/frames/frames.py index 7107cfd97..29369f03a 100644 --- a/src/pipecat/frames/frames.py +++ b/src/pipecat/frames/frames.py @@ -28,7 +28,7 @@ from typing import ( ) from pipecat.adapters.schemas.tools_schema import ToolsSchema -from pipecat.audio.dtmf.types import KeypadEntry as NewKeypadEntry +from pipecat.audio.dtmf.types import KeypadEntry from pipecat.audio.interruptions.base_interruption_strategy import BaseInterruptionStrategy from pipecat.audio.turn.base_turn_analyzer import BaseTurnParams from pipecat.audio.vad.vad_analyzer import VADParams @@ -46,62 +46,6 @@ if TYPE_CHECKING: from pipecat.utils.tracing.tracing_context import TracingContext -class DeprecatedKeypadEntry: - """DTMF keypad entries for phone system integration. - - .. deprecated:: 0.0.82 - This class is deprecated and will be removed in a future version. - Instead, use `audio.dtmf.types.KeypadEntry`. - - Parameters: - ONE: Number key 1. - TWO: Number key 2. - THREE: Number key 3. - FOUR: Number key 4. - FIVE: Number key 5. - SIX: Number key 6. - SEVEN: Number key 7. - EIGHT: Number key 8. - NINE: Number key 9. - ZERO: Number key 0. - POUND: Pound/hash key (#). - STAR: Star/asterisk key (*). - """ - - _enum = NewKeypadEntry - - @classmethod - def _warn(cls): - import warnings - - with warnings.catch_warnings(): - warnings.simplefilter("always") - warnings.warn( - "`pipecat.frames.frames.KeypadEntry` is deprecated and will be removed in a future version. " - "Use `pipecat.audio.dtmf.types.KeypadEntry` instead.", - DeprecationWarning, - stacklevel=2, - ) - - def __call__(self, *args: Any, **kwargs: Any) -> Any: - """Allow the instance to be called as a function.""" - self._warn() - return self._enum(*args, **kwargs) - - def __getattr__(self, name): - """Retrieve an attribute from the underlying enum.""" - self._warn() - return getattr(self._enum, name) - - def __getitem__(self, name): - """Retrieve an item from the underlying enum.""" - self._warn() - return self._enum[name] - - -KeypadEntry = DeprecatedKeypadEntry() - - def format_pts(pts: Optional[int]): """Format presentation timestamp (PTS) in nanoseconds to a human-readable string. @@ -963,32 +907,6 @@ class OutputTransportMessageFrame(DataFrame): return f"{self.name}(message: {self.message})" -@dataclass -class TransportMessageFrame(OutputTransportMessageFrame): - """Frame containing transport-specific message data. - - .. deprecated:: 0.0.87 - This frame is deprecated and will be removed in a future version. - Instead, use `OutputTransportMessageFrame`. - - Parameters: - message: The transport message payload. - """ - - def __post_init__(self): - super().__post_init__() - import warnings - - with warnings.catch_warnings(): - warnings.simplefilter("always") - warnings.warn( - "TransportMessageFrame is deprecated and will be removed in a future version. " - "Instead, use OutputTransportMessageFrame.", - DeprecationWarning, - stacklevel=2, - ) - - @dataclass class DTMFFrame: """Base class for DTMF (Dual-Tone Multi-Frequency) keypad frames. @@ -997,7 +915,7 @@ class DTMFFrame: button: The DTMF keypad entry that was pressed. """ - button: NewKeypadEntry + button: KeypadEntry @dataclass @@ -1154,34 +1072,6 @@ class InterruptionFrame(SystemFrame): pass -@dataclass -class StartInterruptionFrame(InterruptionFrame): - """Frame indicating user started speaking (interruption detected). - - .. deprecated:: 0.0.85 - This frame is deprecated and will be removed in a future version. - Instead, use `InterruptionFrame`. - - Emitted by the BaseInputTransport to indicate that a user has started - speaking (i.e. is interrupting). This is similar to - UserStartedSpeakingFrame except that it should be pushed concurrently - with other frames (so the order is not guaranteed). - """ - - def __post_init__(self): - super().__post_init__() - import warnings - - with warnings.catch_warnings(): - warnings.simplefilter("always") - warnings.warn( - "StartInterruptionFrame is deprecated and will be removed in a future version. " - "Instead, use InterruptionFrame.", - DeprecationWarning, - stacklevel=2, - ) - - @dataclass class UserStartedSpeakingFrame(SystemFrame): """Frame indicating that the user turn has started. @@ -1449,32 +1339,6 @@ class InputTransportMessageFrame(SystemFrame): return f"{self.name}(message: {self.message})" -@dataclass -class InputTransportMessageUrgentFrame(InputTransportMessageFrame): - """Frame for transport messages received from external sources. - - .. deprecated:: 0.0.87 - This frame is deprecated and will be removed in a future version. - Instead, use `InputTransportMessageFrame`. - - Parameters: - message: The urgent transport message payload. - """ - - def __post_init__(self): - super().__post_init__() - import warnings - - with warnings.catch_warnings(): - warnings.simplefilter("always") - warnings.warn( - "InputTransportMessageUrgentFrame is deprecated and will be removed in a future version. " - "Instead, use InputTransportMessageFrame.", - DeprecationWarning, - stacklevel=2, - ) - - @dataclass class OutputTransportMessageUrgentFrame(SystemFrame): """Frame for urgent transport messages that need to be sent immediately. @@ -1489,32 +1353,6 @@ class OutputTransportMessageUrgentFrame(SystemFrame): return f"{self.name}(message: {self.message})" -@dataclass -class TransportMessageUrgentFrame(OutputTransportMessageUrgentFrame): - """Frame for urgent transport messages that need to be sent immediately. - - .. deprecated:: 0.0.87 - This frame is deprecated and will be removed in a future version. - Instead, use `OutputTransportMessageUrgentFrame`. - - Parameters: - message: The urgent transport message payload. - """ - - def __post_init__(self): - super().__post_init__() - import warnings - - with warnings.catch_warnings(): - warnings.simplefilter("always") - warnings.warn( - "TransportMessageUrgentFrame is deprecated and will be removed in a future version. " - "Instead, use OutputTransportMessageFrame.", - DeprecationWarning, - stacklevel=2, - ) - - @dataclass class UserImageRequestFrame(SystemFrame): """Frame requesting an image from a specific user. @@ -1840,34 +1678,6 @@ class InterruptionTaskFrame(TaskSystemFrame): pass -@dataclass -class BotInterruptionFrame(InterruptionTaskFrame): - """Frame indicating the bot should be interrupted. - - .. deprecated:: 0.0.85 - This frame is deprecated and will be removed in a future version. - Instead, use `InterruptionTaskFrame`. - - Emitted when the bot should be interrupted. This will mainly cause the - same actions as if the user interrupted except that the - UserStartedSpeakingFrame and UserStoppedSpeakingFrame won't be generated. - This frame should be pushed upstream. - """ - - def __post_init__(self): - super().__post_init__() - import warnings - - with warnings.catch_warnings(): - warnings.simplefilter("always") - warnings.warn( - "BotInterruptionFrame is deprecated and will be removed in a future version. " - "Instead, use InterruptionTaskFrame.", - DeprecationWarning, - stacklevel=2, - ) - - # # Control frames # diff --git a/src/pipecat/pipeline/llm_switcher.py b/src/pipecat/pipeline/llm_switcher.py index cfee6b2b0..d65d50d08 100644 --- a/src/pipecat/pipeline/llm_switcher.py +++ b/src/pipecat/pipeline/llm_switcher.py @@ -77,7 +77,6 @@ class LLMSwitcher(ServiceSwitcher[StrategyType]): self, function_name: Optional[str], handler: Any, - start_callback=None, *, cancel_on_interruption: bool = True, timeout_secs: Optional[float] = None, @@ -89,12 +88,6 @@ class LLMSwitcher(ServiceSwitcher[StrategyType]): all function calls with a catch-all handler. handler: The function handler. Should accept a single FunctionCallParams parameter. - start_callback: Legacy callback function (deprecated). Put initialization - code at the top of your handler instead. - - .. deprecated:: 0.0.59 - The `start_callback` parameter is deprecated and will be removed in a future version. - cancel_on_interruption: Whether to cancel this function call when an interruption occurs. Defaults to True. timeout_secs: Optional timeout in seconds for the function call. @@ -103,7 +96,6 @@ class LLMSwitcher(ServiceSwitcher[StrategyType]): llm.register_function( function_name=function_name, handler=handler, - start_callback=start_callback, cancel_on_interruption=cancel_on_interruption, timeout_secs=timeout_secs, ) diff --git a/src/pipecat/pipeline/task.py b/src/pipecat/pipeline/task.py index 4b471c08e..d33fcbd2c 100644 --- a/src/pipecat/pipeline/task.py +++ b/src/pipecat/pipeline/task.py @@ -130,11 +130,6 @@ class PipelineParams(BaseModel): .. deprecated:: 0.0.99 Use `LLMUserAggregator`'s new `user_turn_strategies` parameter instead. - observers: [deprecated] Use `observers` arg in `PipelineTask` class. - - .. deprecated:: 0.0.58 - Use the `observers` argument in the `PipelineTask` class instead. - report_only_initial_ttfb: Whether to report only initial time to first byte. send_initial_empty_metrics: Whether to send initial empty metrics. start_metadata: Additional metadata for pipeline start. @@ -151,7 +146,6 @@ class PipelineParams(BaseModel): heartbeats_period_secs: float = HEARTBEAT_SECS heartbeats_monitor_secs: float = HEARTBEAT_MONITOR_SECS interruption_strategies: List[BaseInterruptionStrategy] = Field(default_factory=list) - observers: List[BaseObserver] = Field(default_factory=list) report_only_initial_ttfb: bool = False send_initial_empty_metrics: bool = True start_metadata: Dict[str, Any] = Field(default_factory=dict) @@ -171,21 +165,6 @@ class PipelineTask(BasePipelineTask): - on_frame_reached_downstream: Called when downstream frames reach the sink - on_idle_timeout: Called when pipeline is idle beyond timeout threshold - on_pipeline_started: Called when pipeline starts with StartFrame - - on_pipeline_stopped: [deprecated] Called when pipeline stops with StopFrame - - .. deprecated:: 0.0.86 - Use `on_pipeline_finished` instead. - - - on_pipeline_ended: [deprecated] Called when pipeline ends with EndFrame - - .. deprecated:: 0.0.86 - Use `on_pipeline_finished` instead. - - - on_pipeline_cancelled: [deprecated] Called when pipeline is cancelled with CancelFrame - - .. deprecated:: 0.0.86 - Use `on_pipeline_finished` instead. - - on_pipeline_finished: Called after the pipeline has reached any terminal state. This includes: @@ -280,16 +259,6 @@ class PipelineTask(BasePipelineTask): self._enable_tracing = enable_tracing and is_tracing_available() self._enable_turn_tracking = enable_turn_tracking self._idle_timeout_secs = idle_timeout_secs - if self._params.observers: - import warnings - - with warnings.catch_warnings(): - warnings.simplefilter("always") - warnings.warn( - "Field 'observers' is deprecated, use the 'observers' parameter instead.", - DeprecationWarning, - ) - observers = self._params.observers observers = observers or [] self._turn_tracking_observer: Optional[TurnTrackingObserver] = None self._user_bot_latency_observer: Optional[UserBotLatencyObserver] = None @@ -416,9 +385,6 @@ class PipelineTask(BasePipelineTask): self._register_event_handler("on_frame_reached_downstream") self._register_event_handler("on_idle_timeout") self._register_event_handler("on_pipeline_started") - self._register_event_handler("on_pipeline_stopped") - self._register_event_handler("on_pipeline_ended") - self._register_event_handler("on_pipeline_cancelled") self._register_event_handler("on_pipeline_finished") self._register_event_handler("on_pipeline_error") @@ -489,27 +455,6 @@ class PipelineTask(BasePipelineTask): """ return tuple(self._reached_downstream_types) - def event_handler(self, event_name: str): - """Decorator for registering event handlers. - - Args: - event_name: The name of the event to handle. - - Returns: - The decorator function that registers the handler. - """ - if event_name in ["on_pipeline_stopped", "on_pipeline_ended", "on_pipeline_cancelled"]: - import warnings - - with warnings.catch_warnings(): - warnings.simplefilter("always") - warnings.warn( - f"Event '{event_name}' is deprecated, use 'on_pipeline_finished' instead.", - DeprecationWarning, - ) - - return super().event_handler(event_name) - def add_observer(self, observer: BaseObserver): """Add an observer to monitor pipeline execution. @@ -764,7 +709,6 @@ class PipelineTask(BasePipelineTask): f"{self}: timeout waiting for {frame} to reach the end of the pipeline (being blocked somewhere?)." ) finally: - await self._call_event_handler("on_pipeline_cancelled", frame) await self._call_event_handler("on_pipeline_finished", frame) logger.debug(f"{self}: Closing. Waiting for {frame} to reach the end of the pipeline...") @@ -926,11 +870,9 @@ class PipelineTask(BasePipelineTask): self._pipeline_start_event.set() elif isinstance(frame, EndFrame): - await self._call_event_handler("on_pipeline_ended", frame) await self._call_event_handler("on_pipeline_finished", frame) self._pipeline_end_event.set() elif isinstance(frame, StopFrame): - await self._call_event_handler("on_pipeline_stopped", frame) await self._call_event_handler("on_pipeline_finished", frame) self._pipeline_end_event.set() elif isinstance(frame, CancelFrame): diff --git a/src/pipecat/processors/audio/audio_buffer_processor.py b/src/pipecat/processors/audio/audio_buffer_processor.py index 3181b6e73..62d707fb8 100644 --- a/src/pipecat/processors/audio/audio_buffer_processor.py +++ b/src/pipecat/processors/audio/audio_buffer_processor.py @@ -60,7 +60,6 @@ class AudioBufferProcessor(FrameProcessor): sample_rate: Optional[int] = None, num_channels: int = 1, buffer_size: int = 0, - user_continuous_stream: Optional[bool] = None, enable_turn_audio: bool = False, **kwargs, ): @@ -70,12 +69,6 @@ class AudioBufferProcessor(FrameProcessor): sample_rate: Desired output sample rate. If None, uses source rate. num_channels: Number of channels (1 for mono, 2 for stereo). Defaults to 1. buffer_size: Size of buffer before triggering events. 0 for no buffering. - user_continuous_stream: Controls whether user audio is treated as a continuous - stream for buffering purposes. - - .. deprecated:: 0.0.72 - This parameter no longer has any effect and will be removed in a future version. - enable_turn_audio: Whether turn audio event handlers should be triggered. **kwargs: Additional arguments passed to parent class. """ @@ -87,16 +80,6 @@ class AudioBufferProcessor(FrameProcessor): self._buffer_size = buffer_size self._enable_turn_audio = enable_turn_audio - if user_continuous_stream is not None: - import warnings - - with warnings.catch_warnings(): - warnings.simplefilter("always") - warnings.warn( - "Parameter `user_continuous_stream` is deprecated.", - DeprecationWarning, - ) - self._user_audio_buffer = bytearray() self._bot_audio_buffer = bytearray() diff --git a/src/pipecat/processors/frame_processor.py b/src/pipecat/processors/frame_processor.py index f3d9fbdea..8efb1353d 100644 --- a/src/pipecat/processors/frame_processor.py +++ b/src/pipecat/processors/frame_processor.py @@ -527,33 +527,6 @@ class FrameProcessor(BaseObject): """ await self.task_manager.cancel_task(task, timeout) - async def wait_for_task(self, task: asyncio.Task, timeout: Optional[float] = None): - """Wait for a task to complete. - - .. deprecated:: 0.0.81 - This function is deprecated, use `await task` or - `await asyncio.wait_for(task, timeout)` instead. - - Args: - task: The task to wait for. - timeout: Optional timeout for waiting. - """ - import warnings - - with warnings.catch_warnings(): - warnings.simplefilter("always") - warnings.warn( - "`FrameProcessor.wait_for_task()` is deprecated. " - "Use `await task` or `await asyncio.wait_for(task, timeout)` instead.", - DeprecationWarning, - stacklevel=2, - ) - - if timeout: - await asyncio.wait_for(task, timeout) - else: - await task - async def setup(self, setup: FrameProcessorSetup): """Set up the processor with required components. diff --git a/src/pipecat/processors/frameworks/rtvi/__init__.py b/src/pipecat/processors/frameworks/rtvi/__init__.py index eed90ed09..6c5225906 100644 --- a/src/pipecat/processors/frameworks/rtvi/__init__.py +++ b/src/pipecat/processors/frameworks/rtvi/__init__.py @@ -7,33 +7,10 @@ """RTVI (Real-Time Voice Interface) protocol implementation for Pipecat.""" from pipecat.processors.frameworks.rtvi.frames import ( - RTVIActionFrame, RTVIClientMessageFrame, RTVIServerMessageFrame, RTVIServerResponseFrame, ) -from pipecat.processors.frameworks.rtvi.models_deprecated import ( - ActionResult, - RTVIAction, - RTVIActionArgument, - RTVIActionArgumentData, - RTVIActionResponse, - RTVIActionResponseData, - RTVIActionRun, - RTVIActionRunArgument, - RTVIBotReadyDataDeprecated, - RTVIConfig, - RTVIConfigResponse, - RTVIDescribeActions, - RTVIDescribeActionsData, - RTVIDescribeConfig, - RTVIDescribeConfigData, - RTVIService, - RTVIServiceConfig, - RTVIServiceOption, - RTVIServiceOptionConfig, - RTVIUpdateConfig, -) from pipecat.processors.frameworks.rtvi.observer import ( RTVIFunctionCallReportLevel, RTVIObserver, @@ -42,32 +19,11 @@ from pipecat.processors.frameworks.rtvi.observer import ( from pipecat.processors.frameworks.rtvi.processor import RTVIProcessor __all__ = [ - "ActionResult", - "RTVIAction", - "RTVIActionArgument", - "RTVIActionArgumentData", - "RTVIActionFrame", - "RTVIActionResponse", - "RTVIActionResponseData", - "RTVIActionRun", - "RTVIActionRunArgument", - "RTVIBotReadyDataDeprecated", "RTVIClientMessageFrame", - "RTVIConfig", - "RTVIConfigResponse", - "RTVIDescribeActions", - "RTVIDescribeActionsData", - "RTVIDescribeConfig", - "RTVIDescribeConfigData", "RTVIFunctionCallReportLevel", "RTVIObserver", "RTVIObserverParams", "RTVIProcessor", "RTVIServerMessageFrame", "RTVIServerResponseFrame", - "RTVIService", - "RTVIServiceConfig", - "RTVIServiceOption", - "RTVIServiceOptionConfig", - "RTVIUpdateConfig", ] diff --git a/src/pipecat/processors/frameworks/rtvi/frames.py b/src/pipecat/processors/frameworks/rtvi/frames.py index 6a771f7e4..f4d38ed7e 100644 --- a/src/pipecat/processors/frameworks/rtvi/frames.py +++ b/src/pipecat/processors/frameworks/rtvi/frames.py @@ -12,23 +12,6 @@ from typing import Any, Optional from pipecat.frames.frames import DataFrame, SystemFrame -@dataclass -class RTVIActionFrame(DataFrame): - """Frame containing an RTVI action to execute. - - Parameters: - rtvi_action_run: The action to execute. - message_id: Optional message ID for response correlation. - - .. deprecated:: 0.0.75 - Actions have been removed as part of the RTVI protocol 1.0.0. - Use custom client and server messages instead. - """ - - rtvi_action_run: Any - message_id: Optional[str] = None - - @dataclass class RTVIServerMessageFrame(SystemFrame): """A frame for sending server messages to the client. diff --git a/src/pipecat/processors/frameworks/rtvi/models.py b/src/pipecat/processors/frameworks/rtvi/models.py index 7a9d4e633..9e54dd227 100644 --- a/src/pipecat/processors/frameworks/rtvi/models.py +++ b/src/pipecat/processors/frameworks/rtvi/models.py @@ -229,34 +229,6 @@ class SendTextData(BaseModel): options: Optional[SendTextOptions] = None -class AppendToContextData(BaseModel): - """Data format for appending messages to the context. - - Contains the role, content, and whether to run the message immediately. - - .. deprecated:: 0.0.85 - The RTVI message, append-to-context, has been deprecated. Use send-text - or custom client and server messages instead. - """ - - role: Literal["user", "assistant"] | str - content: Any - run_immediately: bool = False - - -class AppendToContext(BaseModel): - """RTVI message format to append content to the LLM context. - - .. deprecated:: 0.0.85 - The RTVI message, append-to-context, has been deprecated. Use send-text - or custom client and server messages instead. - """ - - label: MessageLiteral = MESSAGE_LABEL - type: Literal["append-to-context"] = "append-to-context" - data: AppendToContextData - - class LLMFunctionCallStartMessageData(BaseModel): """Data for LLM function call start notification. diff --git a/src/pipecat/processors/frameworks/rtvi/models_deprecated.py b/src/pipecat/processors/frameworks/rtvi/models_deprecated.py deleted file mode 100644 index 07c998f6f..000000000 --- a/src/pipecat/processors/frameworks/rtvi/models_deprecated.py +++ /dev/null @@ -1,330 +0,0 @@ -# -# Copyright (c) 2024-2026, Daily -# -# SPDX-License-Identifier: BSD 2-Clause License -# - -"""RTVI pre-1.0 protocol models (deprecated). - -All classes here are kept for backward compatibility only. Pipeline configuration -and the actions API were removed in RTVI protocol 1.0.0. Use custom client and -server messages instead. -""" - -from typing import ( - Any, - Awaitable, - Callable, - Dict, - List, - Literal, - Optional, - Union, -) - -from pydantic import BaseModel, Field, PrivateAttr - -import pipecat.processors.frameworks.rtvi.models as RTVI - -ActionResult = Union[bool, int, float, str, list, dict] - - -class RTVIServiceOption(BaseModel): - """Configuration option for an RTVI service. - - Defines a configurable option that can be set for an RTVI service, - including its name, type, and handler function. - - .. deprecated:: 0.0.75 - Pipeline Configuration has been removed as part of the RTVI protocol 1.0.0. - Use custom client and server messages instead. - """ - - name: str - type: Literal["bool", "number", "string", "array", "object"] - handler: Callable[..., Awaitable[None]] = Field(exclude=True) - - -class RTVIService(BaseModel): - """An RTVI service definition. - - Represents a service that can be configured and used within the RTVI protocol, - containing a name and list of configurable options. - - .. deprecated:: 0.0.75 - Pipeline Configuration has been removed as part of the RTVI protocol 1.0.0. - Use custom client and server messages instead. - """ - - name: str - options: List[RTVIServiceOption] - _options_dict: Dict[str, RTVIServiceOption] = PrivateAttr(default={}) - - def model_post_init(self, __context: Any) -> None: - """Initialize the options dictionary after model creation.""" - self._options_dict = {} - for option in self.options: - self._options_dict[option.name] = option - return super().model_post_init(__context) - - -class RTVIActionArgumentData(BaseModel): - """Data for an RTVI action argument. - - Contains the name and value of an argument passed to an RTVI action. - - .. deprecated:: 0.0.75 - Actions have been removed as part of the RTVI protocol 1.0.0. - Use custom client and server messages instead. - """ - - name: str - value: Any - - -class RTVIActionArgument(BaseModel): - """Definition of an RTVI action argument. - - Specifies the name and expected type of an argument for an RTVI action. - - .. deprecated:: 0.0.75 - Actions have been removed as part of the RTVI protocol 1.0.0. - Use custom client and server messages instead. - """ - - name: str - type: Literal["bool", "number", "string", "array", "object"] - - -class RTVIAction(BaseModel): - """An RTVI action definition. - - Represents an action that can be executed within the RTVI protocol, - including its service, name, arguments, and handler function. - - .. deprecated:: 0.0.75 - Actions have been removed as part of the RTVI protocol 1.0.0. - Use custom client and server messages instead. - """ - - service: str - action: str - arguments: List[RTVIActionArgument] = Field(default_factory=list) - result: Literal["bool", "number", "string", "array", "object"] - handler: Callable[..., Awaitable[ActionResult]] = Field(exclude=True) - _arguments_dict: Dict[str, RTVIActionArgument] = PrivateAttr(default={}) - - def model_post_init(self, __context: Any) -> None: - """Initialize the arguments dictionary after model creation.""" - self._arguments_dict = {} - for arg in self.arguments: - self._arguments_dict[arg.name] = arg - return super().model_post_init(__context) - - -class RTVIServiceOptionConfig(BaseModel): - """Configuration value for an RTVI service option. - - Contains the name and value to set for a specific service option. - - .. deprecated:: 0.0.75 - Pipeline Configuration has been removed as part of the RTVI protocol 1.0.0. - Use custom client and server messages instead. - """ - - name: str - value: Any - - -class RTVIServiceConfig(BaseModel): - """Configuration for an RTVI service. - - Contains the service name and list of option configurations to apply. - - .. deprecated:: 0.0.75 - Pipeline Configuration has been removed as part of the RTVI protocol 1.0.0. - Use custom client and server messages instead. - """ - - service: str - options: List[RTVIServiceOptionConfig] - - -class RTVIConfig(BaseModel): - """Complete RTVI configuration. - - Contains the full configuration for all RTVI services. - - .. deprecated:: 0.0.75 - Pipeline Configuration has been removed as part of the RTVI protocol 1.0.0. - Use custom client and server messages instead. - """ - - config: List[RTVIServiceConfig] - - -# -# Client -> Pipecat messages. -# - - -class RTVIUpdateConfig(BaseModel): - """Request to update RTVI configuration. - - Contains new configuration settings and whether to interrupt the bot. - - .. deprecated:: 0.0.75 - Pipeline Configuration has been removed as part of the RTVI protocol 1.0.0. - Use custom client and server messages instead. - """ - - config: List[RTVIServiceConfig] - interrupt: bool = False - - -class RTVIActionRunArgument(BaseModel): - """Argument for running an RTVI action. - - Contains the name and value of an argument to pass to an action. - - .. deprecated:: 0.0.75 - Actions have been removed as part of the RTVI protocol 1.0.0. - Use custom client and server messages instead. - """ - - name: str - value: Any - - -class RTVIActionRun(BaseModel): - """Request to run an RTVI action. - - Contains the service, action name, and optional arguments. - - .. deprecated:: 0.0.75 - Actions have been removed as part of the RTVI protocol 1.0.0. - Use custom client and server messages instead. - """ - - service: str - action: str - arguments: Optional[List[RTVIActionRunArgument]] = None - - -# -# Pipecat -> Client responses and messages. -# - - -class RTVIBotReadyDataDeprecated(RTVI.BotReadyData): - """Data for bot ready notification. - - Contains protocol version and initial configuration. - """ - - # The config field is deprecated and will not be included if - # the client's rtvi version is 1.0.0 or higher. - config: Optional[List[RTVIServiceConfig]] = None - - -class RTVIDescribeConfigData(BaseModel): - """Data for describing available RTVI configuration. - - Contains the list of available services and their options. - - .. deprecated:: 0.0.75 - Pipeline Configuration has been removed as part of the RTVI protocol 1.0.0. - Use custom client and server messages instead. - """ - - config: List[RTVIService] - - -class RTVIDescribeConfig(BaseModel): - """Message describing available RTVI configuration. - - Sent in response to a describe-config request. - - .. deprecated:: 0.0.75 - Pipeline Configuration has been removed as part of the RTVI protocol 1.0.0. - Use custom client and server messages instead. - """ - - label: RTVI.MessageLiteral = RTVI.MESSAGE_LABEL - type: Literal["config-available"] = "config-available" - id: str - data: RTVIDescribeConfigData - - -class RTVIDescribeActionsData(BaseModel): - """Data for describing available RTVI actions. - - Contains the list of available actions that can be executed. - - .. deprecated:: 0.0.75 - Actions have been removed as part of the RTVI protocol 1.0.0. - Use custom client and server messages instead. - """ - - actions: List[RTVIAction] - - -class RTVIDescribeActions(BaseModel): - """Message describing available RTVI actions. - - Sent in response to a describe-actions request. - - .. deprecated:: 0.0.75 - Actions have been removed as part of the RTVI protocol 1.0.0. - Use custom client and server messages instead. - """ - - label: RTVI.MessageLiteral = RTVI.MESSAGE_LABEL - type: Literal["actions-available"] = "actions-available" - id: str - data: RTVIDescribeActionsData - - -class RTVIConfigResponse(BaseModel): - """Response containing current RTVI configuration. - - Sent in response to a get-config request. - - .. deprecated:: 0.0.75 - Pipeline Configuration has been removed as part of the RTVI protocol 1.0.0. - Use custom client and server messages instead. - """ - - label: RTVI.MessageLiteral = RTVI.MESSAGE_LABEL - type: Literal["config"] = "config" - id: str - data: RTVIConfig - - -class RTVIActionResponseData(BaseModel): - """Data for an RTVI action response. - - Contains the result of executing an action. - - .. deprecated:: 0.0.75 - Actions have been removed as part of the RTVI protocol 1.0.0. - Use custom client and server messages instead. - """ - - result: ActionResult - - -class RTVIActionResponse(BaseModel): - """Response to an RTVI action execution. - - Sent after successfully executing an action. - - .. deprecated:: 0.0.75 - Actions have been removed as part of the RTVI protocol 1.0.0. - Use custom client and server messages instead. - """ - - label: RTVI.MessageLiteral = RTVI.MESSAGE_LABEL - type: Literal["action-response"] = "action-response" - id: str - data: RTVIActionResponseData diff --git a/src/pipecat/processors/frameworks/rtvi/observer.py b/src/pipecat/processors/frameworks/rtvi/observer.py index 7383fe811..7944dd3eb 100644 --- a/src/pipecat/processors/frameworks/rtvi/observer.py +++ b/src/pipecat/processors/frameworks/rtvi/observer.py @@ -94,9 +94,6 @@ class RTVIFunctionCallReportLevel(str, Enum): class RTVIObserverParams: """Parameters for configuring RTVI Observer behavior. - .. deprecated:: 0.0.87 - Parameter `errors_enabled` is deprecated. Error messages are always enabled. - Parameters: bot_output_enabled: Indicates if bot output messages should be sent. bot_llm_enabled: Indicates if the bot's LLM messages should be sent. @@ -109,7 +106,6 @@ class RTVIObserverParams: user_audio_level_enabled: Indicates if user's audio level messages should be sent. metrics_enabled: Indicates if metrics messages should be sent. system_logs_enabled: Indicates if system logs should be sent. - errors_enabled: [Deprecated] Indicates if errors messages should be sent. ignored_sources: List of frame processors whose frames should be silently ignored by this observer. Useful for suppressing RTVI messages from secondary pipeline branches (e.g. a silent evaluation LLM) that should not be visible to clients. @@ -153,7 +149,6 @@ class RTVIObserverParams: user_audio_level_enabled: bool = False metrics_enabled: bool = True system_logs_enabled: bool = False - errors_enabled: Optional[bool] = None ignored_sources: List[FrameProcessor] = field(default_factory=list) skip_aggregator_types: Optional[List[AggregationType | str]] = None bot_output_transforms: Optional[ @@ -214,16 +209,6 @@ class RTVIObserver(BaseObserver): if self._params.system_logs_enabled: self._system_logger_id = logger.add(self._logger_sink) - if self._params.errors_enabled is not None: - import warnings - - with warnings.catch_warnings(): - warnings.simplefilter("always") - warnings.warn( - "Parameter `errors_enabled` is deprecated. Error messages are always enabled.", - DeprecationWarning, - ) - self._aggregation_transforms: List[ Tuple[AggregationType | str, Callable[[str, AggregationType | str], Awaitable[str]]] ] = self._params.bot_output_transforms or [] diff --git a/src/pipecat/processors/frameworks/rtvi/processor.py b/src/pipecat/processors/frameworks/rtvi/processor.py index b750bd70b..69a863594 100644 --- a/src/pipecat/processors/frameworks/rtvi/processor.py +++ b/src/pipecat/processors/frameworks/rtvi/processor.py @@ -8,7 +8,7 @@ import asyncio import base64 -from typing import Any, Dict, Mapping, Optional +from typing import Any, Mapping, Optional from loguru import logger from pydantic import BaseModel, ValidationError @@ -31,24 +31,7 @@ from pipecat.frames.frames import ( SystemFrame, ) from pipecat.processors.frame_processor import FrameDirection, FrameProcessor -from pipecat.processors.frameworks.rtvi.frames import RTVIActionFrame, RTVIClientMessageFrame -from pipecat.processors.frameworks.rtvi.models_deprecated import ( - RTVIAction, - RTVIActionResponse, - RTVIActionResponseData, - RTVIActionRun, - RTVIBotReadyDataDeprecated, - RTVIConfig, - RTVIConfigResponse, - RTVIDescribeActions, - RTVIDescribeActionsData, - RTVIDescribeConfig, - RTVIDescribeConfigData, - RTVIService, - RTVIServiceConfig, - RTVIServiceOptionConfig, - RTVIUpdateConfig, -) +from pipecat.processors.frameworks.rtvi.frames import RTVIClientMessageFrame from pipecat.processors.frameworks.rtvi.observer import RTVIObserver, RTVIObserverParams from pipecat.services.llm_service import ( FunctionCallParams, # TODO(aleix): we shouldn't import `services` from `processors` @@ -68,7 +51,6 @@ class RTVIProcessor(FrameProcessor): def __init__( self, *, - config: Optional[RTVIConfig] = None, transport: Optional[BaseTransport] = None, **kwargs, ): @@ -80,7 +62,6 @@ class RTVIProcessor(FrameProcessor): **kwargs: Additional arguments passed to parent class. """ super().__init__(**kwargs) - self._config = config or RTVIConfig(config=[]) self._bot_ready = False self._client_ready = False @@ -90,12 +71,6 @@ class RTVIProcessor(FrameProcessor): self._client_version = [0, 3, 0] self._llm_skip_tts: bool = False # Keep in sync with llm_service.py's configuration. - self._registered_actions: Dict[str, RTVIAction] = {} - self._registered_services: Dict[str, RTVIService] = {} - - # A task to process incoming action frames. - self._action_task: Optional[asyncio.Task] = None - # A task to process incoming transport messages. self._message_task: Optional[asyncio.Task] = None @@ -111,41 +86,6 @@ class RTVIProcessor(FrameProcessor): self._input_transport = input_transport self._input_transport.enable_audio_in_stream_on_start(False) - def register_action(self, action: RTVIAction): - """Register an action that can be executed via RTVI. - - Args: - action: The action to register. - """ - import warnings - - with warnings.catch_warnings(): - warnings.simplefilter("always") - warnings.warn( - "The actions API is deprecated, use server and client messages instead.", - DeprecationWarning, - ) - - id = self._action_id(action.service, action.action) - self._registered_actions[id] = action - - def register_service(self, service: RTVIService): - """Register a service that can be configured via RTVI. - - Args: - service: The service to register. - """ - import warnings - - with warnings.catch_warnings(): - warnings.simplefilter("always") - warnings.warn( - "The actions API is deprecated, use server and client messages instead.", - DeprecationWarning, - ) - - self._registered_services[service.name] = service - def create_rtvi_observer(self, *, params: Optional[RTVIObserverParams] = None, **kwargs): """Creates a new RTVI Observer. @@ -171,11 +111,6 @@ class RTVIProcessor(FrameProcessor): If left as None, the Pipecat library and version will be used. """ self._bot_ready = True - # Only call the (deprecated) _update_config method if the we're using a - # config (which is deprecated). Otherwise we'd always print an - # unnecessary deprecation warning. - if self._config.config: - await self._update_config(self._config, False) await self._send_bot_ready(about=about) async def interrupt_bot(self): @@ -281,8 +216,6 @@ class RTVIProcessor(FrameProcessor): await self.push_frame(frame, direction) await self._stop(frame) # Data frames - elif isinstance(frame, RTVIActionFrame): - await self._action_queue.put(frame) elif isinstance(frame, LLMConfigureOutputFrame): self._llm_skip_tts = frame.skip_tts await self.push_frame(frame, direction) @@ -292,9 +225,6 @@ class RTVIProcessor(FrameProcessor): async def _start(self, frame: StartFrame): """Start the RTVI processor tasks.""" - if not self._action_task: - self._action_queue = asyncio.Queue() - self._action_task = self.create_task(self._action_task_handler()) if not self._message_task: self._message_queue = asyncio.Queue() self._message_task = self.create_task(self._message_task_handler()) @@ -310,21 +240,10 @@ class RTVIProcessor(FrameProcessor): async def _cancel_tasks(self): """Cancel all running tasks.""" - if self._action_task: - await self.cancel_task(self._action_task) - self._action_task = None - if self._message_task: await self.cancel_task(self._message_task) self._message_task = None - async def _action_task_handler(self): - """Handle incoming action frames.""" - while True: - frame = await self._action_queue.get() - await self._handle_action(frame.message_id, frame.rtvi_action_run) - self._action_queue.task_done() - async def _message_task_handler(self): """Handle incoming transport messages.""" while True: @@ -359,36 +278,17 @@ class RTVIProcessor(FrameProcessor): data = None pass await self._handle_client_ready(message.id, data) - case "describe-actions": - await self._handle_describe_actions(message.id) - case "describe-config": - await self._handle_describe_config(message.id) - case "get-config": - await self._handle_get_config(message.id) - case "update-config": - update_config = RTVIUpdateConfig.model_validate(message.data) - await self._handle_update_config(message.id, update_config) case "disconnect-bot": await self.push_frame(EndTaskFrame(), FrameDirection.UPSTREAM) case "client-message": data = RTVI.RawClientMessageData.model_validate(message.data) await self._handle_client_message(message.id, data) - case "action": - action = RTVIActionRun.model_validate(message.data) - action_frame = RTVIActionFrame(message_id=message.id, rtvi_action_run=action) - await self._action_queue.put(action_frame) case "llm-function-call-result": data = RTVI.LLMFunctionCallResultData.model_validate(message.data) await self._handle_function_call_result(data) case "send-text": data = RTVI.SendTextData.model_validate(message.data) await self._handle_send_text(data) - case "append-to-context": - logger.warning( - f"The append-to-context message is deprecated, use send-text instead." - ) - data = RTVI.AppendToContextData.model_validate(message.data) - await self._handle_update_context(data) case "raw-audio" | "raw-audio-batch": await self._handle_audio_buffer(message.data) @@ -441,100 +341,6 @@ class RTVIProcessor(FrameProcessor): # Handle missing keys, decoding errors, and invalid types logger.error(f"Error processing audio buffer: {e}") - async def _handle_describe_config(self, request_id: str): - """Handle a describe-config request.""" - import warnings - - with warnings.catch_warnings(): - warnings.simplefilter("always") - warnings.warn( - "Configuration helpers are deprecated. If your application needs this behavior, use custom server and client messages.", - DeprecationWarning, - ) - - services = list(self._registered_services.values()) - message = RTVIDescribeConfig(id=request_id, data=RTVIDescribeConfigData(config=services)) - await self.push_transport_message(message) - - async def _handle_describe_actions(self, request_id: str): - """Handle a describe-actions request.""" - import warnings - - with warnings.catch_warnings(): - warnings.simplefilter("always") - warnings.warn( - "The Actions API is deprecated, use custom server and client messages instead.", - DeprecationWarning, - ) - - actions = list(self._registered_actions.values()) - message = RTVIDescribeActions(id=request_id, data=RTVIDescribeActionsData(actions=actions)) - await self.push_transport_message(message) - - async def _handle_get_config(self, request_id: str): - """Handle a get-config request.""" - import warnings - - with warnings.catch_warnings(): - warnings.simplefilter("always") - warnings.warn( - "Configuration helpers are deprecated. If your application needs this behavior, use custom server and client messages.", - DeprecationWarning, - ) - - message = RTVIConfigResponse(id=request_id, data=self._config) - await self.push_transport_message(message) - - def _update_config_option(self, service: str, config: RTVIServiceOptionConfig): - """Update a specific configuration option.""" - for service_config in self._config.config: - if service_config.service == service: - for option_config in service_config.options: - if option_config.name == config.name: - option_config.value = config.value - return - # If we couldn't find a value for this config, we simply need to - # add it. - service_config.options.append(config) - - async def _update_service_config(self, config: RTVIServiceConfig): - """Update configuration for a specific service.""" - import warnings - - with warnings.catch_warnings(): - warnings.simplefilter("always") - warnings.warn( - "Configuration helpers are deprecated. If your application needs this behavior, use custom server and client messages.", - DeprecationWarning, - ) - - service = self._registered_services[config.service] - for option in config.options: - handler = service._options_dict[option.name].handler - await handler(self, service.name, option) - self._update_config_option(service.name, option) - - async def _update_config(self, data: RTVIConfig, interrupt: bool): - """Update the RTVI configuration.""" - import warnings - - with warnings.catch_warnings(): - warnings.simplefilter("always") - warnings.warn( - "Configuration helpers are deprecated. If your application needs this behavior, use custom server and client messages.", - DeprecationWarning, - ) - - if interrupt: - await self.interrupt_bot() - for service_config in data.config: - await self._update_service_config(service_config) - - async def _handle_update_config(self, request_id: str, data: RTVIUpdateConfig): - """Handle an update-config request.""" - await self._update_config(RTVIConfig(config=data.config), data.interrupt) - await self._handle_get_config(request_id) - async def _handle_send_text(self, data: RTVI.SendTextData): """Handle a send-text message from the client.""" opts = data.options if data.options is not None else RTVI.SendTextOptions() @@ -555,15 +361,6 @@ class RTVIProcessor(FrameProcessor): output_frame = LLMConfigureOutputFrame(skip_tts=cur_llm_skip_tts) await self.push_frame(output_frame) - async def _handle_update_context(self, data: RTVI.AppendToContextData): - if data.run_immediately: - await self.interrupt_bot() - frame = LLMMessagesAppendFrame( - messages=[{"role": data.role, "content": data.content}], - run_llm=data.run_immediately, - ) - await self.push_frame(frame) - async def _handle_client_message(self, msg_id: str, data: RTVI.RawClientMessageData): """Handle a client message frame.""" # Create a RTVIClientMessageFrame to push the message @@ -588,24 +385,6 @@ class RTVIProcessor(FrameProcessor): ) await self.push_frame(frame) - async def _handle_action(self, request_id: Optional[str], data: RTVIActionRun): - """Handle an action execution request.""" - action_id = self._action_id(data.service, data.action) - if action_id not in self._registered_actions: - await self._send_error_response(request_id, f"Action {action_id} not registered") - return - action = self._registered_actions[action_id] - arguments = {} - if data.arguments: - for arg in data.arguments: - arguments[arg.name] = arg.value - result = await action.handler(self, action.service, arguments) - # Only send a response if request_id is present. Things that don't care about - # action responses (such as webhooks) don't set a request_id - if request_id: - message = RTVIActionResponse(id=request_id, data=RTVIActionResponseData(result=result)) - await self.push_transport_message(message) - async def _send_bot_ready(self, about: Mapping[str, Any] = None): """Send the bot-ready message to the client. @@ -615,19 +394,10 @@ class RTVIProcessor(FrameProcessor): """ if not about: about = {"library": "pipecat-ai", "library_version": f"{pipecat_version()}"} - if self._client_version and self._client_version[0] < 1: - config = self._config.config - message = RTVI.BotReady( - id=self._client_ready_id, - data=RTVIBotReadyDataDeprecated( - version=RTVI.PROTOCOL_VERSION, about=about, config=config - ), - ) - else: - message = RTVI.BotReady( - id=self._client_ready_id, - data=RTVI.BotReadyData(version=RTVI.PROTOCOL_VERSION, about=about), - ) + message = RTVI.BotReady( + id=self._client_ready_id, + data=RTVI.BotReadyData(version=RTVI.PROTOCOL_VERSION, about=about), + ) await self.push_transport_message(message) async def _send_server_message(self, message: RTVI.ServerMessage | RTVI.ServerResponse): diff --git a/src/pipecat/runner/daily.py b/src/pipecat/runner/daily.py index a60b84a6a..082d7271c 100644 --- a/src/pipecat/runner/daily.py +++ b/src/pipecat/runner/daily.py @@ -275,32 +275,3 @@ async def configure( error_msg = f"Error creating Daily room: {e}" logger.error(error_msg) raise - - -# Keep this for backwards compatibility, but mark as deprecated -async def configure_with_args(aiohttp_session: aiohttp.ClientSession, parser=None): - """Configure Daily room with command-line argument parsing. - - .. deprecated:: 0.0.78 - This function is deprecated. Use configure() instead which uses - environment variables only. - - Args: - aiohttp_session: HTTP session for making API requests. - parser: Ignored. Kept for backwards compatibility. - - Returns: - Tuple containing room URL, authentication token, and None (for args). - """ - import warnings - - with warnings.catch_warnings(): - warnings.simplefilter("always") - warnings.warn( - "configure_with_args is deprecated. Use configure() instead.", - DeprecationWarning, - stacklevel=2, - ) - - room_url, token = await configure(aiohttp_session) - return (room_url, token, None) diff --git a/src/pipecat/services/llm_service.py b/src/pipecat/services/llm_service.py index a479fcfc6..e7aaa7687 100644 --- a/src/pipecat/services/llm_service.py +++ b/src/pipecat/services/llm_service.py @@ -46,7 +46,6 @@ from pipecat.frames.frames import ( LLMTextFrame, LLMUpdateSettingsFrame, StartFrame, - UserImageRequestFrame, ) from pipecat.processors.aggregators.llm_context import ( LLMContext, @@ -127,7 +126,6 @@ class FunctionCallRegistryItem: function_name: Optional[str] handler: FunctionCallHandler | "DirectFunctionWrapper" cancel_on_interruption: bool - handler_deprecated: bool timeout_secs: Optional[float] = None @@ -213,7 +211,6 @@ class LLMService(UserTurnCompletionLLMServiceMixin, AIService): self._function_call_timeout_secs = function_call_timeout_secs self._filter_incomplete_user_turns: bool = False self._base_system_instruction: Optional[str] = None - self._start_callbacks = {} self._adapter = self.adapter_class() self._functions: Dict[Optional[str], FunctionCallRegistryItem] = {} self._function_call_tasks: Dict[Optional[asyncio.Task], FunctionCallRunnerItem] = {} @@ -574,7 +571,6 @@ class LLMService(UserTurnCompletionLLMServiceMixin, AIService): self, function_name: Optional[str], handler: Any, - start_callback=None, *, cancel_on_interruption: bool = True, timeout_secs: Optional[float] = None, @@ -586,49 +582,21 @@ class LLMService(UserTurnCompletionLLMServiceMixin, AIService): all function calls with a catch-all handler. handler: The function handler. Should accept a single FunctionCallParams parameter. - start_callback: Legacy callback function (deprecated). Put initialization - code at the top of your handler instead. - - .. deprecated:: 0.0.59 - The `start_callback` parameter is deprecated and will be removed in a future version. - cancel_on_interruption: Whether to cancel this function call when an interruption occurs. Defaults to True. timeout_secs: Optional per-tool timeout in seconds. Overrides the global ``function_call_timeout_secs`` for this specific function. Defaults to None, which uses the global timeout. """ - signature = inspect.signature(handler) - handler_deprecated = len(signature.parameters) > 1 - if handler_deprecated: - with warnings.catch_warnings(): - warnings.simplefilter("always") - warnings.warn( - "Function calls with parameters `(function_name, tool_call_id, arguments, llm, context, result_callback)` are deprecated, use a single `FunctionCallParams` parameter instead.", - DeprecationWarning, - ) - # Registering a function with the function_name set to None will run # that handler for all functions self._functions[function_name] = FunctionCallRegistryItem( function_name=function_name, handler=handler, cancel_on_interruption=cancel_on_interruption, - handler_deprecated=handler_deprecated, timeout_secs=timeout_secs, ) - # Start callbacks are now deprecated. - if start_callback: - with warnings.catch_warnings(): - warnings.simplefilter("always") - warnings.warn( - "Parameter 'start_callback' is deprecated, just put your code on top of the actual function call instead.", - DeprecationWarning, - ) - - self._start_callbacks[function_name] = start_callback - def register_direct_function( self, handler: DirectFunction, @@ -655,7 +623,6 @@ class LLMService(UserTurnCompletionLLMServiceMixin, AIService): function_name=wrapper.name, handler=wrapper, cancel_on_interruption=cancel_on_interruption, - handler_deprecated=False, timeout_secs=timeout_secs, ) @@ -666,8 +633,6 @@ class LLMService(UserTurnCompletionLLMServiceMixin, AIService): function_name: The name of the function handler to remove. """ del self._functions[function_name] - if function_name in self._start_callbacks: - del self._start_callbacks[function_name] def unregister_direct_function(self, handler: Any): """Remove a registered direct function handler. @@ -736,56 +701,6 @@ class LLMService(UserTurnCompletionLLMServiceMixin, AIService): else: await self._run_sequential_function_calls(runner_items) - async def request_image_frame( - self, - user_id: str, - *, - function_name: Optional[str] = None, - tool_call_id: Optional[str] = None, - text_content: Optional[str] = None, - video_source: Optional[str] = None, - timeout: Optional[float] = 10.0, - ): - """Request an image from a user. - - Pushes a UserImageRequestFrame upstream to request an image from the - specified user. The user image can then be processed by the LLM. - - Use this function from a function call if you want the LLM to process - the image. If you expect the image to be processed by a vision service, - you might want to push a UserImageRequestFrame upstream directly. - - .. deprecated:: 0.0.92 - This method is deprecated, push a `UserImageRequestFrame` instead. - - Args: - user_id: The ID of the user to request an image from. - function_name: Optional function name associated with the request. - tool_call_id: Optional tool call ID associated with the request. - text_content: Optional text content/context for the image request. - video_source: Optional video source identifier. - timeout: Optional timeout for the requested image to be added to the LLM context. - - """ - with warnings.catch_warnings(): - warnings.simplefilter("always") - warnings.warn( - "Method `request_image_frame()` is deprecated, push a `UserImageRequestFrame` instead.", - DeprecationWarning, - ) - await self.push_frame( - UserImageRequestFrame( - user_id=user_id, - text=text_content, - append_to_context=True, - function_name=function_name, - tool_call_id=tool_call_id, - # Deprecated fields below. - context=text_content, - ), - FrameDirection.UPSTREAM, - ) - async def _create_sequential_runner_task(self): if not self._sequential_runner_task: self._sequential_runner_queue = asyncio.Queue() @@ -824,14 +739,6 @@ class LLMService(UserTurnCompletionLLMServiceMixin, AIService): for runner_item in runner_items: await self._sequential_runner_queue.put(runner_item) - async def _call_start_function( - self, context: OpenAILLMContext | LLMContext, function_name: str - ): - if function_name in self._start_callbacks.keys(): - await self._start_callbacks[function_name](function_name, self, context) - elif None in self._start_callbacks.keys(): - return await self._start_callbacks[None](function_name, self, context) - async def _run_function_call(self, runner_item: FunctionCallRunnerItem): if runner_item.function_name in self._functions.keys(): item = self._functions[runner_item.function_name] @@ -844,9 +751,6 @@ class LLMService(UserTurnCompletionLLMServiceMixin, AIService): f"{self} Calling function [{runner_item.function_name}:{runner_item.tool_call_id}] with arguments {runner_item.arguments}" ) - # NOTE(aleix): This needs to be removed after we remove the deprecation. - await self._call_start_function(runner_item.context, runner_item.function_name) - # Broadcast function call in-progress. This frame will let our assistant # context aggregator know that we are in the middle of a function # call. Some contexts/aggregators may not need this. But some definitely @@ -921,25 +825,15 @@ class LLMService(UserTurnCompletionLLMServiceMixin, AIService): ) else: # Handler is a FunctionCallHandler - if item.handler_deprecated: - await item.handler( - runner_item.function_name, - runner_item.tool_call_id, - runner_item.arguments, - self, - runner_item.context, - function_call_result_callback, - ) - else: - params = FunctionCallParams( - function_name=runner_item.function_name, - tool_call_id=runner_item.tool_call_id, - arguments=runner_item.arguments, - llm=self, - context=runner_item.context, - result_callback=function_call_result_callback, - ) - await item.handler(params) + params = FunctionCallParams( + function_name=runner_item.function_name, + tool_call_id=runner_item.tool_call_id, + arguments=runner_item.arguments, + llm=self, + context=runner_item.context, + result_callback=function_call_result_callback, + ) + await item.handler(params) except Exception as e: error_message = f"Error executing function call [{runner_item.function_name}]: {e}" logger.error(f"{self} {error_message}") diff --git a/src/pipecat/services/tts_service.py b/src/pipecat/services/tts_service.py index f33515e68..72830078b 100644 --- a/src/pipecat/services/tts_service.py +++ b/src/pipecat/services/tts_service.py @@ -635,27 +635,6 @@ class TTSService(AIService): return changed - async def say(self, text: str): - """Immediately speak the provided text. - - .. deprecated:: 0.0.79 - Push a `TTSSpeakFrame` instead to ensure frame ordering is maintained. - - Args: - text: The text to speak. - """ - import warnings - - with warnings.catch_warnings(): - warnings.simplefilter("always") - warnings.warn( - "`TTSService.say()` is deprecated. Push a `TTSSpeakFrame` instead.", - DeprecationWarning, - stacklevel=2, - ) - - await self.queue_frame(TTSSpeakFrame(text)) - async def on_turn_context_created(self, context_id: str): """Called when a new turn context ID has been created. diff --git a/src/pipecat/transports/base_input.py b/src/pipecat/transports/base_input.py index bcd457564..d0cd5212c 100644 --- a/src/pipecat/transports/base_input.py +++ b/src/pipecat/transports/base_input.py @@ -93,46 +93,6 @@ class BaseInputTransport(FrameProcessor): # them downstream until we get another `StartFrame`. self._paused = False - if self._params.vad_enabled: - import warnings - - with warnings.catch_warnings(): - warnings.simplefilter("always") - warnings.warn( - "Parameter 'vad_enabled' is deprecated, use 'audio_in_enabled' and 'vad_analyzer' instead.", - DeprecationWarning, - ) - self._params.audio_in_enabled = True - - if self._params.vad_audio_passthrough: - import warnings - - with warnings.catch_warnings(): - warnings.simplefilter("always") - warnings.warn( - "Parameter 'vad_audio_passthrough' is deprecated, audio passthrough is now always enabled. Use 'audio_in_passthrough' to disable.", - DeprecationWarning, - ) - self._params.audio_in_passthrough = True - - if self._params.camera_in_enabled: - import warnings - - with warnings.catch_warnings(): - warnings.simplefilter("always") - warnings.warn( - "Parameters 'camera_*' are deprecated, use 'video_*' instead.", - DeprecationWarning, - ) - self._params.video_in_enabled = self._params.camera_in_enabled - self._params.video_out_enabled = self._params.camera_out_enabled - self._params.video_out_is_live = self._params.camera_out_is_live - self._params.video_out_width = self._params.camera_out_width - self._params.video_out_height = self._params.camera_out_height - self._params.video_out_bitrate = self._params.camera_out_bitrate - self._params.video_out_framerate = self._params.camera_out_framerate - self._params.video_out_color_format = self._params.camera_out_color_format - if self._params.turn_analyzer: import warnings diff --git a/src/pipecat/transports/base_transport.py b/src/pipecat/transports/base_transport.py index 5b6c8673c..3e760cd32 100644 --- a/src/pipecat/transports/base_transport.py +++ b/src/pipecat/transports/base_transport.py @@ -28,54 +28,6 @@ class TransportParams(BaseModel): """Configuration parameters for transport implementations. Parameters: - camera_in_enabled: Enable camera input (deprecated, use video_in_enabled). - - .. deprecated:: 0.0.66 - The `camera_in_enabled` parameter is deprecated, use - `video_in_enabled` instead. - - camera_out_enabled: Enable camera output (deprecated, use video_out_enabled). - - .. deprecated:: 0.0.66 - The `camera_out_enabled` parameter is deprecated, use - `video_out_enabled` instead. - - camera_out_is_live: Enable real-time camera output (deprecated). - - .. deprecated:: 0.0.66 - The `camera_out_is_live` parameter is deprecated, use - `video_out_is_live` instead. - - camera_out_width: Camera output width in pixels (deprecated). - - .. deprecated:: 0.0.66 - The `camera_out_width` parameter is deprecated, use - `video_out_width` instead. - - camera_out_height: Camera output height in pixels (deprecated). - - .. deprecated:: 0.0.66 - The `camera_out_height` parameter is deprecated, use - `video_out_height` instead. - - camera_out_bitrate: Camera output bitrate in bits per second (deprecated). - - .. deprecated:: 0.0.66 - The `camera_out_bitrate` parameter is deprecated, use - `video_out_bitrate` instead. - - camera_out_framerate: Camera output frame rate in FPS (deprecated). - - .. deprecated:: 0.0.66 - The `camera_out_framerate` parameter is deprecated, use - `video_out_framerate` instead. - - camera_out_color_format: Camera output color format string (deprecated). - - .. deprecated:: 0.0.66 - The `camera_out_color_format` parameter is deprecated, use - `video_out_color_format` instead. - audio_out_enabled: Enable audio output streaming. audio_out_sample_rate: Output audio sample rate in Hz. audio_out_channels: Number of output audio channels. @@ -102,18 +54,6 @@ class TransportParams(BaseModel): video_out_color_format: Video output color format string. video_out_codec: Preferred video codec for output (e.g., 'VP8', 'H264', 'H265'). video_out_destinations: List of video output destination identifiers. - vad_enabled: Enable Voice Activity Detection (deprecated). - - .. deprecated:: 0.0.66 - The `vad_enabled` parameter is deprecated, use `audio_in_enabled` - and `TransportParams.vad_analyzer` instead. - - vad_audio_passthrough: Enable VAD audio passthrough (deprecated). - - .. deprecated:: 0.0.66 - The `vad_audio_passthrough` parameter is deprecated, use `audio_in_passthrough` - instead. - vad_analyzer: Voice Activity Detection analyzer instance. .. deprecated:: 0.0.101 @@ -130,14 +70,6 @@ class TransportParams(BaseModel): model_config = ConfigDict(arbitrary_types_allowed=True) - camera_in_enabled: bool = False - camera_out_enabled: bool = False - camera_out_is_live: bool = False - camera_out_width: int = 1024 - camera_out_height: int = 768 - camera_out_bitrate: int = 800000 - camera_out_framerate: int = 30 - camera_out_color_format: str = "RGB" audio_out_enabled: bool = False audio_out_sample_rate: Optional[int] = None audio_out_channels: int = 1 @@ -163,8 +95,6 @@ class TransportParams(BaseModel): video_out_color_format: str = "RGB" video_out_codec: Optional[str] = None video_out_destinations: List[str] = Field(default_factory=list) - vad_enabled: bool = False - vad_audio_passthrough: bool = False vad_analyzer: Optional[VADAnalyzer] = None turn_analyzer: Optional[BaseTurnAnalyzer] = None diff --git a/src/pipecat/transports/daily/transport.py b/src/pipecat/transports/daily/transport.py index 8ef94ae40..6b5f3e909 100644 --- a/src/pipecat/transports/daily/transport.py +++ b/src/pipecat/transports/daily/transport.py @@ -99,58 +99,6 @@ class DailyOutputTransportMessageUrgentFrame(OutputTransportMessageUrgentFrame): participant_id: Optional[str] = None -@dataclass -class DailyTransportMessageFrame(DailyOutputTransportMessageFrame): - """Frame for transport messages in Daily calls. - - .. deprecated:: 0.0.87 - This frame is deprecated and will be removed in a future version. - Instead, use `DailyOutputTransportMessageFrame`. - - Parameters: - participant_id: Optional ID of the participant this message is for/from. - """ - - def __post_init__(self): - super().__post_init__() - import warnings - - with warnings.catch_warnings(): - warnings.simplefilter("always") - warnings.warn( - "DailyTransportMessageFrame is deprecated and will be removed in a future version. " - "Instead, use DailyOutputTransportMessageFrame.", - DeprecationWarning, - stacklevel=2, - ) - - -@dataclass -class DailyTransportMessageUrgentFrame(DailyOutputTransportMessageUrgentFrame): - """Frame for urgent transport messages in Daily calls. - - .. deprecated:: 0.0.87 - This frame is deprecated and will be removed in a future version. - Instead, use `DailyOutputTransportMessageUrgentFrame`. - - Parameters: - participant_id: Optional ID of the participant this message is for/from. - """ - - def __post_init__(self): - super().__post_init__() - import warnings - - with warnings.catch_warnings(): - warnings.simplefilter("always") - warnings.warn( - "DailyTransportMessageUrgentFrame is deprecated and will be removed in a future version. " - "Instead, use DailyOutputTransportMessageUrgentFrame.", - DeprecationWarning, - stacklevel=2, - ) - - @dataclass class DailyInputTransportMessageFrame(InputTransportMessageFrame): """Frame for input urgent transport messages in Daily calls. @@ -162,31 +110,6 @@ class DailyInputTransportMessageFrame(InputTransportMessageFrame): participant_id: Optional[str] = None -class DailyInputTransportMessageUrgentFrame(DailyInputTransportMessageFrame): - """Frame for input urgent transport messages in Daily calls. - - .. deprecated:: 0.0.87 - This frame is deprecated and will be removed in a future version. - Instead, use `DailyInputTransportMessageFrame`. - - Parameters: - participant_id: Optional ID of the participant this message is for/from. - """ - - def __post_init__(self): - super().__post_init__() - import warnings - - with warnings.catch_warnings(): - warnings.simplefilter("always") - warnings.warn( - "DailyInputTransportMessageUrgentFrame is deprecated and will be removed in a future version. " - "Instead, use DailyInputTransportMessageFrame.", - DeprecationWarning, - stacklevel=2, - ) - - @dataclass class DailySIPTransferFrame(DataFrame): """SIP call transfer frame for transport queuing. diff --git a/uv.lock b/uv.lock index 5c3019bbd..83c6423dc 100644 --- a/uv.lock +++ b/uv.lock @@ -2169,7 +2169,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/38/3f/9859f655d11901e7b2996c6e3d33e0caa9a1d4572c3bc61ed0faa64b2f4c/greenlet-3.3.2-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:9bc885b89709d901859cf95179ec9f6bb67a3d2bb1f0e88456461bd4b7f8fd0d", size = 277747, upload-time = "2026-02-20T20:16:21.325Z" }, { url = "https://files.pythonhosted.org/packages/fb/07/cb284a8b5c6498dbd7cba35d31380bb123d7dceaa7907f606c8ff5993cbf/greenlet-3.3.2-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b568183cf65b94919be4438dc28416b234b678c608cafac8874dfeeb2a9bbe13", size = 579202, upload-time = "2026-02-20T20:47:28.955Z" }, { url = "https://files.pythonhosted.org/packages/ed/45/67922992b3a152f726163b19f890a85129a992f39607a2a53155de3448b8/greenlet-3.3.2-cp310-cp310-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:527fec58dc9f90efd594b9b700662ed3fb2493c2122067ac9c740d98080a620e", size = 590620, upload-time = "2026-02-20T20:55:55.581Z" }, - { url = "https://files.pythonhosted.org/packages/03/5f/6e2a7d80c353587751ef3d44bb947f0565ec008a2e0927821c007e96d3a7/greenlet-3.3.2-cp310-cp310-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:508c7f01f1791fbc8e011bd508f6794cb95397fdb198a46cb6635eb5b78d85a7", size = 602132, upload-time = "2026-02-20T21:02:43.261Z" }, { url = "https://files.pythonhosted.org/packages/ad/55/9f1ebb5a825215fadcc0f7d5073f6e79e3007e3282b14b22d6aba7ca6cb8/greenlet-3.3.2-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ad0c8917dd42a819fe77e6bdfcb84e3379c0de956469301d9fd36427a1ca501f", size = 591729, upload-time = "2026-02-20T20:20:58.395Z" }, { url = "https://files.pythonhosted.org/packages/24/b4/21f5455773d37f94b866eb3cf5caed88d6cea6dd2c6e1f9c34f463cba3ec/greenlet-3.3.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:97245cc10e5515dbc8c3104b2928f7f02b6813002770cfaffaf9a6e0fc2b94ef", size = 1551946, upload-time = "2026-02-20T20:49:31.102Z" }, { url = "https://files.pythonhosted.org/packages/00/68/91f061a926abead128fe1a87f0b453ccf07368666bd59ffa46016627a930/greenlet-3.3.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8c1fdd7d1b309ff0da81d60a9688a8bd044ac4e18b250320a96fc68d31c209ca", size = 1618494, upload-time = "2026-02-20T20:21:06.541Z" }, @@ -2177,7 +2176,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f3/47/16400cb42d18d7a6bb46f0626852c1718612e35dcb0dffa16bbaffdf5dd2/greenlet-3.3.2-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:c56692189a7d1c7606cb794be0a8381470d95c57ce5be03fb3d0ef57c7853b86", size = 278890, upload-time = "2026-02-20T20:19:39.263Z" }, { url = "https://files.pythonhosted.org/packages/a3/90/42762b77a5b6aa96cd8c0e80612663d39211e8ae8a6cd47c7f1249a66262/greenlet-3.3.2-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1ebd458fa8285960f382841da585e02201b53a5ec2bac6b156fc623b5ce4499f", size = 581120, upload-time = "2026-02-20T20:47:30.161Z" }, { url = "https://files.pythonhosted.org/packages/bf/6f/f3d64f4fa0a9c7b5c5b3c810ff1df614540d5aa7d519261b53fba55d4df9/greenlet-3.3.2-cp311-cp311-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a443358b33c4ec7b05b79a7c8b466f5d275025e750298be7340f8fc63dff2a55", size = 594363, upload-time = "2026-02-20T20:55:56.965Z" }, - { url = "https://files.pythonhosted.org/packages/9c/8b/1430a04657735a3f23116c2e0d5eb10220928846e4537a938a41b350bed6/greenlet-3.3.2-cp311-cp311-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4375a58e49522698d3e70cc0b801c19433021b5c37686f7ce9c65b0d5c8677d2", size = 605046, upload-time = "2026-02-20T21:02:45.234Z" }, { url = "https://files.pythonhosted.org/packages/72/83/3e06a52aca8128bdd4dcd67e932b809e76a96ab8c232a8b025b2850264c5/greenlet-3.3.2-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8e2cd90d413acbf5e77ae41e5d3c9b3ac1d011a756d7284d7f3f2b806bbd6358", size = 594156, upload-time = "2026-02-20T20:20:59.955Z" }, { url = "https://files.pythonhosted.org/packages/70/79/0de5e62b873e08fe3cef7dbe84e5c4bc0e8ed0c7ff131bccb8405cd107c8/greenlet-3.3.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:442b6057453c8cb29b4fb36a2ac689382fc71112273726e2423f7f17dc73bf99", size = 1554649, upload-time = "2026-02-20T20:49:32.293Z" }, { url = "https://files.pythonhosted.org/packages/5a/00/32d30dee8389dc36d42170a9c66217757289e2afb0de59a3565260f38373/greenlet-3.3.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:45abe8eb6339518180d5a7fa47fa01945414d7cca5ecb745346fc6a87d2750be", size = 1619472, upload-time = "2026-02-20T20:21:07.966Z" }, @@ -2186,7 +2184,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ea/ab/1608e5a7578e62113506740b88066bf09888322a311cff602105e619bd87/greenlet-3.3.2-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:ac8d61d4343b799d1e526db579833d72f23759c71e07181c2d2944e429eb09cd", size = 280358, upload-time = "2026-02-20T20:17:43.971Z" }, { url = "https://files.pythonhosted.org/packages/a5/23/0eae412a4ade4e6623ff7626e38998cb9b11e9ff1ebacaa021e4e108ec15/greenlet-3.3.2-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3ceec72030dae6ac0c8ed7591b96b70410a8be370b6a477b1dbc072856ad02bd", size = 601217, upload-time = "2026-02-20T20:47:31.462Z" }, { url = "https://files.pythonhosted.org/packages/f8/16/5b1678a9c07098ecb9ab2dd159fafaf12e963293e61ee8d10ecb55273e5e/greenlet-3.3.2-cp312-cp312-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a2a5be83a45ce6188c045bcc44b0ee037d6a518978de9a5d97438548b953a1ac", size = 611792, upload-time = "2026-02-20T20:55:58.423Z" }, - { url = "https://files.pythonhosted.org/packages/5c/c5/cc09412a29e43406eba18d61c70baa936e299bc27e074e2be3806ed29098/greenlet-3.3.2-cp312-cp312-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ae9e21c84035c490506c17002f5c8ab25f980205c3e61ddb3a2a2a2e6c411fcb", size = 626250, upload-time = "2026-02-20T21:02:46.596Z" }, { url = "https://files.pythonhosted.org/packages/50/1f/5155f55bd71cabd03765a4aac9ac446be129895271f73872c36ebd4b04b6/greenlet-3.3.2-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:43e99d1749147ac21dde49b99c9abffcbc1e2d55c67501465ef0930d6e78e070", size = 613875, upload-time = "2026-02-20T20:21:01.102Z" }, { url = "https://files.pythonhosted.org/packages/fc/dd/845f249c3fcd69e32df80cdab059b4be8b766ef5830a3d0aa9d6cad55beb/greenlet-3.3.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4c956a19350e2c37f2c48b336a3afb4bff120b36076d9d7fb68cb44e05d95b79", size = 1571467, upload-time = "2026-02-20T20:49:33.495Z" }, { url = "https://files.pythonhosted.org/packages/2a/50/2649fe21fcc2b56659a452868e695634722a6655ba245d9f77f5656010bf/greenlet-3.3.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6c6f8ba97d17a1e7d664151284cb3315fc5f8353e75221ed4324f84eb162b395", size = 1640001, upload-time = "2026-02-20T20:21:09.154Z" }, @@ -2195,7 +2192,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ac/48/f8b875fa7dea7dd9b33245e37f065af59df6a25af2f9561efa8d822fde51/greenlet-3.3.2-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:aa6ac98bdfd716a749b84d4034486863fd81c3abde9aa3cf8eff9127981a4ae4", size = 279120, upload-time = "2026-02-20T20:19:01.9Z" }, { url = "https://files.pythonhosted.org/packages/49/8d/9771d03e7a8b1ee456511961e1b97a6d77ae1dea4a34a5b98eee706689d3/greenlet-3.3.2-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ab0c7e7901a00bc0a7284907273dc165b32e0d109a6713babd04471327ff7986", size = 603238, upload-time = "2026-02-20T20:47:32.873Z" }, { url = "https://files.pythonhosted.org/packages/59/0e/4223c2bbb63cd5c97f28ffb2a8aee71bdfb30b323c35d409450f51b91e3e/greenlet-3.3.2-cp313-cp313-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d248d8c23c67d2291ffd47af766e2a3aa9fa1c6703155c099feb11f526c63a92", size = 614219, upload-time = "2026-02-20T20:55:59.817Z" }, - { url = "https://files.pythonhosted.org/packages/94/2b/4d012a69759ac9d77210b8bfb128bc621125f5b20fc398bce3940d036b1c/greenlet-3.3.2-cp313-cp313-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ccd21bb86944ca9be6d967cf7691e658e43417782bce90b5d2faeda0ff78a7dd", size = 628268, upload-time = "2026-02-20T21:02:48.024Z" }, { url = "https://files.pythonhosted.org/packages/7a/34/259b28ea7a2a0c904b11cd36c79b8cef8019b26ee5dbe24e73b469dea347/greenlet-3.3.2-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b6997d360a4e6a4e936c0f9625b1c20416b8a0ea18a8e19cabbefc712e7397ab", size = 616774, upload-time = "2026-02-20T20:21:02.454Z" }, { url = "https://files.pythonhosted.org/packages/0a/03/996c2d1689d486a6e199cb0f1cf9e4aa940c500e01bdf201299d7d61fa69/greenlet-3.3.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:64970c33a50551c7c50491671265d8954046cb6e8e2999aacdd60e439b70418a", size = 1571277, upload-time = "2026-02-20T20:49:34.795Z" }, { url = "https://files.pythonhosted.org/packages/d9/c4/2570fc07f34a39f2caf0bf9f24b0a1a0a47bc2e8e465b2c2424821389dfc/greenlet-3.3.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1a9172f5bf6bd88e6ba5a84e0a68afeac9dc7b6b412b245dd64f52d83c81e55b", size = 1640455, upload-time = "2026-02-20T20:21:10.261Z" }, @@ -2204,7 +2200,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/3f/ae/8bffcbd373b57a5992cd077cbe8858fff39110480a9d50697091faea6f39/greenlet-3.3.2-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:8d1658d7291f9859beed69a776c10822a0a799bc4bfe1bd4272bb60e62507dab", size = 279650, upload-time = "2026-02-20T20:18:00.783Z" }, { url = "https://files.pythonhosted.org/packages/d1/c0/45f93f348fa49abf32ac8439938726c480bd96b2a3c6f4d949ec0124b69f/greenlet-3.3.2-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:18cb1b7337bca281915b3c5d5ae19f4e76d35e1df80f4ad3c1a7be91fadf1082", size = 650295, upload-time = "2026-02-20T20:47:34.036Z" }, { url = "https://files.pythonhosted.org/packages/b3/de/dd7589b3f2b8372069ab3e4763ea5329940fc7ad9dcd3e272a37516d7c9b/greenlet-3.3.2-cp314-cp314-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c2e47408e8ce1c6f1ceea0dffcdf6ebb85cc09e55c7af407c99f1112016e45e9", size = 662163, upload-time = "2026-02-20T20:56:01.295Z" }, - { url = "https://files.pythonhosted.org/packages/cd/ac/85804f74f1ccea31ba518dcc8ee6f14c79f73fe36fa1beba38930806df09/greenlet-3.3.2-cp314-cp314-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e3cb43ce200f59483eb82949bf1835a99cf43d7571e900d7c8d5c62cdf25d2f9", size = 675371, upload-time = "2026-02-20T21:02:49.664Z" }, { url = "https://files.pythonhosted.org/packages/d2/d8/09bfa816572a4d83bccd6750df1926f79158b1c36c5f73786e26dbe4ee38/greenlet-3.3.2-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:63d10328839d1973e5ba35e98cccbca71b232b14051fd957b6f8b6e8e80d0506", size = 664160, upload-time = "2026-02-20T20:21:04.015Z" }, { url = "https://files.pythonhosted.org/packages/48/cf/56832f0c8255d27f6c35d41b5ec91168d74ec721d85f01a12131eec6b93c/greenlet-3.3.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:8e4ab3cfb02993c8cc248ea73d7dae6cec0253e9afa311c9b37e603ca9fad2ce", size = 1619181, upload-time = "2026-02-20T20:49:36.052Z" }, { url = "https://files.pythonhosted.org/packages/0a/23/b90b60a4aabb4cec0796e55f25ffbfb579a907c3898cd2905c8918acaa16/greenlet-3.3.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:94ad81f0fd3c0c0681a018a976e5c2bd2ca2d9d94895f23e7bb1af4e8af4e2d5", size = 1687713, upload-time = "2026-02-20T20:21:11.684Z" }, @@ -2213,7 +2208,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/98/6d/8f2ef704e614bcf58ed43cfb8d87afa1c285e98194ab2cfad351bf04f81e/greenlet-3.3.2-cp314-cp314t-macosx_11_0_universal2.whl", hash = "sha256:e26e72bec7ab387ac80caa7496e0f908ff954f31065b0ffc1f8ecb1338b11b54", size = 286617, upload-time = "2026-02-20T20:19:29.856Z" }, { url = "https://files.pythonhosted.org/packages/5e/0d/93894161d307c6ea237a43988f27eba0947b360b99ac5239ad3fe09f0b47/greenlet-3.3.2-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8b466dff7a4ffda6ca975979bab80bdadde979e29fc947ac3be4451428d8b0e4", size = 655189, upload-time = "2026-02-20T20:47:35.742Z" }, { url = "https://files.pythonhosted.org/packages/f5/2c/d2d506ebd8abcb57386ec4f7ba20f4030cbe56eae541bc6fd6ef399c0b41/greenlet-3.3.2-cp314-cp314t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b8bddc5b73c9720bea487b3bffdb1840fe4e3656fba3bd40aa1489e9f37877ff", size = 658225, upload-time = "2026-02-20T20:56:02.527Z" }, - { url = "https://files.pythonhosted.org/packages/d1/67/8197b7e7e602150938049d8e7f30de1660cfb87e4c8ee349b42b67bdb2e1/greenlet-3.3.2-cp314-cp314t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:59b3e2c40f6706b05a9cd299c836c6aa2378cabe25d021acd80f13abf81181cf", size = 666581, upload-time = "2026-02-20T21:02:51.526Z" }, { url = "https://files.pythonhosted.org/packages/8e/30/3a09155fbf728673a1dea713572d2d31159f824a37c22da82127056c44e4/greenlet-3.3.2-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b26b0f4428b871a751968285a1ac9648944cea09807177ac639b030bddebcea4", size = 657907, upload-time = "2026-02-20T20:21:05.259Z" }, { url = "https://files.pythonhosted.org/packages/f3/fd/d05a4b7acd0154ed758797f0a43b4c0962a843bedfe980115e842c5b2d08/greenlet-3.3.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:1fb39a11ee2e4d94be9a76671482be9398560955c9e568550de0224e41104727", size = 1618857, upload-time = "2026-02-20T20:49:37.309Z" }, { url = "https://files.pythonhosted.org/packages/6f/e1/50ee92a5db521de8f35075b5eff060dd43d39ebd46c2181a2042f7070385/greenlet-3.3.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:20154044d9085151bc309e7689d6f7ba10027f8f5a8c0676ad398b951913d89e", size = 1680010, upload-time = "2026-02-20T20:21:13.427Z" }, @@ -3882,24 +3876,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl", hash = "sha256:5bb13e3eed2923615535339b3c620e76779af4cb4c6a90deccc9e36b274d3827", size = 23438, upload-time = "2025-12-20T14:08:52.782Z" }, ] -[[package]] -name = "noisereduce" -version = "3.0.3" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "joblib" }, - { name = "matplotlib" }, - { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, - { name = "numpy", version = "2.4.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, - { name = "scipy", version = "1.15.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, - { name = "scipy", version = "1.17.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, - { name = "tqdm" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/11/08/539e3cff148b7f9bde5b4b060451a7445d708fa3fe5d8a2bc0c552976e52/noisereduce-3.0.3.tar.gz", hash = "sha256:ff64a28fb92e3c81f153cf29550e5c2db56b2523afa8f56f5e03c177cc5e918f", size = 20968, upload-time = "2024-10-06T13:43:45.431Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ce/c5/fc00b3e8f86437039fb300ba41d5d683fdf0878d8782e827c2bad074eb59/noisereduce-3.0.3-py3-none-any.whl", hash = "sha256:95cb64cfe29b5fa0311ac764755d2f503ae71571040693577796412be1a54b9d", size = 22142, upload-time = "2024-10-06T13:43:43.886Z" }, -] - [[package]] name = "numba" version = "0.64.0" @@ -4778,9 +4754,6 @@ kokoro = [ { name = "kokoro-onnx" }, { name = "requests" }, ] -krisp = [ - { name = "pipecat-ai-krisp" }, -] langchain = [ { name = "langchain" }, { name = "langchain-community" }, @@ -4826,9 +4799,6 @@ moondream = [ neuphonic = [ { name = "websockets" }, ] -noisereduce = [ - { name = "noisereduce" }, -] nvidia = [ { name = "nvidia-riva-client" }, ] @@ -4977,7 +4947,6 @@ requires-dist = [ { name = "mem0ai", marker = "extra == 'mem0'", specifier = ">=1.0.8,<2" }, { name = "mlx-whisper", marker = "extra == 'mlx-whisper'", specifier = "~=0.4.2" }, { name = "nltk", specifier = ">=3.9.4,<4" }, - { name = "noisereduce", marker = "extra == 'noisereduce'", specifier = "~=3.0.3" }, { name = "numba", specifier = ">=0.61.2,<1" }, { name = "numpy", specifier = ">=1.26.4,<3" }, { name = "nvidia-riva-client", marker = "extra == 'nvidia'", specifier = ">=2.25.1,<3" }, @@ -5012,7 +4981,6 @@ requires-dist = [ { name = "pipecat-ai", extras = ["websockets-base"], marker = "extra == 'soniox'" }, { name = "pipecat-ai", extras = ["websockets-base"], marker = "extra == 'ultravox'" }, { name = "pipecat-ai", extras = ["websockets-base"], marker = "extra == 'websocket'" }, - { name = "pipecat-ai-krisp", marker = "extra == 'krisp'", specifier = "~=0.4.0" }, { name = "pipecat-ai-small-webrtc-prebuilt", marker = "extra == 'runner'", specifier = ">=2.4.0" }, { name = "piper-tts", marker = "extra == 'piper'", specifier = ">=1.3.0,<2" }, { name = "protobuf", specifier = ">=6.31.1,<7" }, @@ -5046,7 +5014,7 @@ requires-dist = [ { name = "wait-for2", marker = "python_full_version < '3.12'", specifier = ">=0.4.1,<1" }, { name = "websockets", marker = "extra == 'websockets-base'", specifier = ">=13.1,<16.0" }, ] -provides-extras = ["aic", "anthropic", "assemblyai", "asyncai", "aws", "aws-nova-sonic", "azure", "cartesia", "camb", "cerebras", "daily", "deepgram", "deepseek", "elevenlabs", "fal", "fireworks", "fish", "gladia", "google", "gradium", "grok", "groq", "gstreamer", "heygen", "hume", "inworld", "koala", "kokoro", "krisp", "langchain", "lemonslice", "livekit", "lmnt", "local", "local-smart-turn", "mcp", "mem0", "mistral", "mlx-whisper", "moondream", "nebius", "neuphonic", "noisereduce", "novita", "nvidia", "openai", "rnnoise", "openrouter", "perplexity", "piper", "qwen", "remote-smart-turn", "resembleai", "rime", "riva", "runner", "sagemaker", "sambanova", "sarvam", "sentry", "silero", "simli", "smallest", "soniox", "soundfile", "speechmatics", "strands", "tavus", "together", "tracing", "ultravox", "webrtc", "websocket", "websockets-base", "whisper", "xai"] +provides-extras = ["aic", "anthropic", "assemblyai", "asyncai", "aws", "aws-nova-sonic", "azure", "cartesia", "camb", "cerebras", "daily", "deepgram", "deepseek", "elevenlabs", "fal", "fireworks", "fish", "gladia", "google", "gradium", "grok", "groq", "gstreamer", "heygen", "hume", "inworld", "koala", "kokoro", "langchain", "lemonslice", "livekit", "lmnt", "local", "local-smart-turn", "mcp", "mem0", "mistral", "mlx-whisper", "moondream", "nebius", "neuphonic", "novita", "nvidia", "openai", "rnnoise", "openrouter", "perplexity", "piper", "qwen", "remote-smart-turn", "resembleai", "rime", "riva", "runner", "sagemaker", "sambanova", "sarvam", "sentry", "silero", "simli", "smallest", "soniox", "soundfile", "speechmatics", "strands", "tavus", "together", "tracing", "ultravox", "webrtc", "websocket", "websockets-base", "whisper", "xai"] [package.metadata.requires-dev] dev = [ @@ -5073,16 +5041,6 @@ docs = [ { name = "toml" }, ] -[[package]] -name = "pipecat-ai-krisp" -version = "0.4.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, - { name = "numpy", version = "2.4.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/1d/37/0f1d11d1dc33234a36de01992a9e5adc3c5e1dce71cc87b2bf909fa2f698/pipecat_ai_krisp-0.4.0.tar.gz", hash = "sha256:4f0e05e218dcf15874957e9851299e219c713a0aa8353d2fd811f1b54001a602", size = 13338, upload-time = "2025-06-09T16:13:08.209Z" } - [[package]] name = "pipecat-ai-small-webrtc-prebuilt" version = "2.4.0"