From 33108f5798a2da3028136cb5af89a7d3d8a74e76 Mon Sep 17 00:00:00 2001 From: Mark Backman Date: Thu, 14 Nov 2024 16:42:01 -0500 Subject: [PATCH] Code review feedback --- CHANGELOG.md | 4 ++-- src/pipecat/frames/frames.py | 2 +- src/pipecat/processors/filters/stt_mute.py | 25 +++++++++++++--------- src/pipecat/services/ai_services.py | 4 ++-- 4 files changed, 20 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c698cb25f..1c1e1cbc0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,10 +14,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added `STTMuteProcessor`, a general-purpose processor that combines STT muting and interruption control. When active, it prevents both transcription and interruptions during bot speech. The processor supports multiple - strategies: `NEVER` (default), `FIRST_SPEECH` (mute only during bot's first + strategies: `FIRST_SPEECH` (mute only during bot's first speech), `ALWAYS` (mute during all bot speech), or `CUSTOM` (using provided callback). -- Added STTMuteFrame, a control frame that enables/disables speech +- Added `STTMuteFrame`, a control frame that enables/disables speech transcription in STT services. ## [0.0.48] - 2024-11-10 "Antonio release" diff --git a/src/pipecat/frames/frames.py b/src/pipecat/frames/frames.py index 77aadb397..e057e97da 100644 --- a/src/pipecat/frames/frames.py +++ b/src/pipecat/frames/frames.py @@ -574,7 +574,7 @@ class TTSUpdateSettingsFrame(ServiceUpdateSettingsFrame): class STTMuteFrame(ControlFrame): """Control frame to mute/unmute the STT service.""" - muted: bool + mute: bool @dataclass diff --git a/src/pipecat/processors/filters/stt_mute.py b/src/pipecat/processors/filters/stt_mute.py index 9b7444eb2..5fae94fb7 100644 --- a/src/pipecat/processors/filters/stt_mute.py +++ b/src/pipecat/processors/filters/stt_mute.py @@ -1,6 +1,12 @@ +# +# Copyright (c) 2024, Daily +# +# SPDX-License-Identifier: BSD 2-Clause License +# + from dataclasses import dataclass from enum import Enum -from typing import Callable, Optional +from typing import Awaitable, Callable, Optional from loguru import logger @@ -17,7 +23,6 @@ from pipecat.services.ai_services import STTService class STTMuteStrategy(Enum): - NEVER = "never" # Never mute FIRST_SPEECH = "first_speech" # Mute only during first bot speech ALWAYS = "always" # Mute during all bot speech CUSTOM = "custom" # Allow custom logic via callback @@ -27,9 +32,9 @@ class STTMuteStrategy(Enum): class STTMuteConfig: """Configuration for STTMuteProcessor""" - strategy: STTMuteStrategy = STTMuteStrategy.NEVER + strategy: STTMuteStrategy # Optional callback for custom muting logic - should_mute_callback: Optional[Callable[["STTMuteProcessor"], bool]] = None + should_mute_callback: Optional[Callable[["STTMuteProcessor"], Awaitable[bool]]] = None class STTMuteProcessor(FrameProcessor): @@ -40,7 +45,7 @@ class STTMuteProcessor(FrameProcessor): are automatically disabled. """ - def __init__(self, stt_service: STTService, config: STTMuteConfig = STTMuteConfig(), **kwargs): + def __init__(self, stt_service: STTService, config: STTMuteConfig, **kwargs): super().__init__(**kwargs) self._stt_service = stt_service self._config = config @@ -56,9 +61,9 @@ class STTMuteProcessor(FrameProcessor): """Handles both STT muting and interruption control.""" if should_mute != self.is_muted: logger.info(f"STT {'muting' if should_mute else 'unmuting'}") - await self.push_frame(STTMuteFrame(muted=should_mute)) + await self.push_frame(STTMuteFrame(mute=should_mute)) - def _should_mute(self) -> bool: + async def _should_mute(self) -> bool: """Determines if STT should be muted based on current state and strategy.""" if not self._bot_is_speaking: return False @@ -71,7 +76,7 @@ class STTMuteProcessor(FrameProcessor): self._first_speech_handled = True return True elif self._config.strategy == STTMuteStrategy.CUSTOM and self._config.should_mute_callback: - return self._config.should_mute_callback(self) + return await self._config.should_mute_callback(self) return False @@ -79,10 +84,10 @@ class STTMuteProcessor(FrameProcessor): # Handle bot speaking state changes if isinstance(frame, BotStartedSpeakingFrame): self._bot_is_speaking = True - await self._handle_mute_state(self._should_mute()) + await self._handle_mute_state(await self._should_mute()) elif isinstance(frame, BotStoppedSpeakingFrame): self._bot_is_speaking = False - await self._handle_mute_state(self._should_mute()) + await self._handle_mute_state(await self._should_mute()) # Handle frame propagation if isinstance(frame, (StartInterruptionFrame, StopInterruptionFrame)): diff --git a/src/pipecat/services/ai_services.py b/src/pipecat/services/ai_services.py index fbb495b47..e0f16e220 100644 --- a/src/pipecat/services/ai_services.py +++ b/src/pipecat/services/ai_services.py @@ -506,8 +506,8 @@ class STTService(AIService): elif isinstance(frame, STTUpdateSettingsFrame): await self._update_settings(frame.settings) elif isinstance(frame, STTMuteFrame): - self._muted = frame.muted - logger.debug(f"STT service {'muted' if frame.muted else 'unmuted'}") + self._muted = frame.mute + logger.debug(f"STT service {'muted' if frame.mute else 'unmuted'}") else: await self.push_frame(frame, direction)