From 42f91a905613e7b481489cb6437df87821a81e95 Mon Sep 17 00:00:00 2001 From: zack Date: Sun, 1 Mar 2026 11:44:37 -0500 Subject: [PATCH] Apply ruff formatting fixes --- .../55d-update-settings-assemblyai-stt.py | 4 +- src/pipecat/services/assemblyai/stt.py | 7 +- test_assemblyai_custom.py | 32 ++------ test_assemblyai_interactive.py | 77 +++++++++---------- test_assemblyai_u3pro.py | 17 ++-- 5 files changed, 56 insertions(+), 81 deletions(-) diff --git a/examples/foundational/55d-update-settings-assemblyai-stt.py b/examples/foundational/55d-update-settings-assemblyai-stt.py index b0d676e25..f57865588 100644 --- a/examples/foundational/55d-update-settings-assemblyai-stt.py +++ b/examples/foundational/55d-update-settings-assemblyai-stt.py @@ -102,7 +102,9 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments): @transport.event_handler("on_client_connected") async def on_client_connected(transport, client): logger.info(f"Client connected") - logger.info("Phase 1: No keyterms boosting - try saying 'Xiomara', 'Saoirse', or 'Krzystof'") + logger.info( + "Phase 1: No keyterms boosting - try saying 'Xiomara', 'Saoirse', or 'Krzystof'" + ) messages.append({"role": "system", "content": "Please introduce yourself to the user."}) await task.queue_frames([LLMRunFrame()]) diff --git a/src/pipecat/services/assemblyai/stt.py b/src/pipecat/services/assemblyai/stt.py index 7e2378408..9938afdee 100644 --- a/src/pipecat/services/assemblyai/stt.py +++ b/src/pipecat/services/assemblyai/stt.py @@ -355,13 +355,10 @@ class AssemblyAISTTService(WebsocketSTTService): if hasattr(conn_params, "min_turn_silence"): if ( old_conn_params is None - or conn_params.min_turn_silence - != old_conn_params.min_turn_silence + or conn_params.min_turn_silence != old_conn_params.min_turn_silence ): if conn_params.min_turn_silence is not None: - update_config["min_turn_silence"] = ( - conn_params.min_turn_silence - ) + update_config["min_turn_silence"] = conn_params.min_turn_silence logger.info( f"Updating min_turn_silence to: {conn_params.min_turn_silence}ms" ) diff --git a/test_assemblyai_custom.py b/test_assemblyai_custom.py index c406918c0..e8e0a28d2 100755 --- a/test_assemblyai_custom.py +++ b/test_assemblyai_custom.py @@ -48,11 +48,11 @@ async def main(): logger.remove(0) logger.add(sys.stderr, level=LOG_LEVEL) - logger.info("="*80) + logger.info("=" * 80) logger.info("AssemblyAI u3-rt-pro Custom Test") - logger.info("="*80) + logger.info("=" * 80) logger.info("Starting bot... Speak after you hear the greeting!") - logger.info("="*80) + logger.info("=" * 80) # Create local audio transport transport = LocalAudioTransport( @@ -74,78 +74,63 @@ async def main(): speech_model="u3-rt-pro", # speech_model="universal-streaming-english", # speech_model="universal-streaming-multilingual", - # ==================================================================== # Turn Detection Timing # ==================================================================== - # Minimum silence when confident about end of turn (milliseconds) # Default: 100ms | Higher = more patient | Lower = faster responses # Only used in Pipecat mode (vad_force_turn_endpoint=True) min_turn_silence=100000, # min_turn_silence=200, # min_turn_silence=300, - # Maximum turn silence (milliseconds) # WARNING: In Pipecat mode (vad_force_turn_endpoint=True), this is # automatically set equal to min_turn_silence # to avoid double turn detection. Only used as-is in STT mode. max_turn_silence=500, - # End of turn confidence threshold (0.0 to 1.0) # Higher = requires more confidence before ending turn # end_of_turn_confidence_threshold=0.8, - # ==================================================================== # Prompting & Boosting # ==================================================================== - # Custom Prompt (WARNING: test carefully, default is optimized!) # None = Use AssemblyAI's optimized default (recommended for 88% accuracy) prompt=None, # prompt="Transcribe speech with focus on technical terms.", # prompt="Context: Medical conversation. Transcribe accurately.", - # Keyterms Prompting (boosts recognition for specific words) # NOTE: Cannot use both prompt and keyterms_prompt! keyterms_prompt=None, # keyterms_prompt=["Pipecat", "AssemblyAI", "OpenAI", "Cartesia"], # keyterms_prompt=["Python", "JavaScript", "TypeScript", "API"], - # ==================================================================== # Diarization (Speaker Identification) # ==================================================================== - # Enable speaker labels (identifies different speakers) speaker_labels=None, # None or True # speaker_labels=True, - # ==================================================================== # Audio Configuration # ==================================================================== - # Audio sample rate (Hz) # sample_rate=16000, # sample_rate=8000, - # Audio encoding format # encoding="pcm_s16le", # Default: 16-bit PCM # encoding="pcm_mulaw", # μ-law encoding (telephony) - # ==================================================================== # Other Options # ==================================================================== - # Format transcript turns (applies formatting rules) # format_turns=True, # Default # format_turns=False, - # Language detection (only for universal-streaming-multilingual) # language_detection=True, ) # Log connection parameters for debugging - logger.info("="*80) + logger.info("=" * 80) logger.info("CONNECTION PARAMETERS:") logger.info(f" speech_model: {connection_params.speech_model}") logger.info(f" min_turn_silence: {connection_params.min_turn_silence}") @@ -156,27 +141,26 @@ async def main(): logger.info(f" keyterms_prompt: {connection_params.keyterms_prompt}") logger.info(f" speaker_labels: {connection_params.speaker_labels}") logger.info(f" format_turns: {connection_params.format_turns}") - logger.info(f" end_of_turn_confidence_threshold: {connection_params.end_of_turn_confidence_threshold}") + logger.info( + f" end_of_turn_confidence_threshold: {connection_params.end_of_turn_confidence_threshold}" + ) logger.info(f" language_detection: {connection_params.language_detection}") - logger.info("="*80) + logger.info("=" * 80) # AssemblyAI Speech-to-Text Service stt = AssemblyAISTTService( api_key=os.getenv("ASSEMBLYAI_API_KEY"), connection_params=connection_params, - # Turn Detection Mode # True = Pipecat mode (VAD + Smart Turn controls turns) # False = STT mode (u3-rt-pro model controls turns) vad_force_turn_endpoint=True, - # Speaker Formatting (only used if speaker_labels=True) # None = Just log speaker IDs, don't modify transcript speaker_format=None, # speaker_format="{text}", # speaker_format="{speaker}: {text}", # speaker_format="[{speaker}] {text}", - # Additional available parameters (uncomment to use): # should_interrupt=True, # Only for STT mode ) diff --git a/test_assemblyai_interactive.py b/test_assemblyai_interactive.py index ce468ab3d..c5ec0b429 100755 --- a/test_assemblyai_interactive.py +++ b/test_assemblyai_interactive.py @@ -52,11 +52,11 @@ async def run_bot( test_dynamic_updates: Optional[callable] = None, ): """Run the voice bot with specified configuration.""" - logger.info("="*80) + logger.info("=" * 80) logger.info(f"TEST: {test_name}") - logger.info("="*80) + logger.info("=" * 80) logger.info("Starting bot... Speak into your microphone after you hear the greeting!") - logger.info("="*80) + logger.info("=" * 80) # Create local audio transport transport = LocalAudioTransport( @@ -150,6 +150,7 @@ async def run_bot( # === BASIC CONFIGURATION (1-3) === + async def test_01_basic_100ms(): """Test 1: Basic default configuration (100ms).""" connection_params = AssemblyAIConnectionParams( @@ -179,6 +180,7 @@ async def test_03_custom_500ms(): # === PROMPTING & WARNINGS (4-7) === + async def test_04_max_warning(): """Test 4: max_turn_silence warning (should be overridden).""" logger.warning("āš ļø EXPECT WARNING: max_turn_silence will be overridden") @@ -230,6 +232,7 @@ async def test_07_keyterms_difficult(): # === DIARIZATION (8-9) === + async def test_08_diarization_basic(): """Test 8: Basic diarization (speaker IDs logged).""" connection_params = AssemblyAIConnectionParams( @@ -258,6 +261,7 @@ async def test_09_diarization_xml(): # === DYNAMIC UPDATES - SINGLE PARAMETER (10-13) === + async def test_10_dynamic_keyterms(): """Test 10: Dynamic keyterms update with difficult names.""" connection_params = AssemblyAIConnectionParams( @@ -265,16 +269,16 @@ async def test_10_dynamic_keyterms(): ) async def dynamic_update(task): - logger.info("\n" + "="*80) + logger.info("\n" + "=" * 80) logger.info("PHASE 1: No keyterms boosting") logger.info(" Try saying: Xiomara, Saoirse, Krzystof") logger.info(" (May not transcribe correctly)") - logger.info("="*80) + logger.info("=" * 80) await asyncio.sleep(15) - logger.info("\n" + "="*80) + logger.info("\n" + "=" * 80) logger.info("šŸ”„ UPDATING: Adding keyterms boost") - logger.info("="*80) + logger.info("=" * 80) await task.queue_frame( STTUpdateSettingsFrame( delta=AssemblyAISTTSettings( @@ -284,11 +288,11 @@ async def test_10_dynamic_keyterms(): ) ) ) - logger.info("\n" + "="*80) + logger.info("\n" + "=" * 80) logger.info("PHASE 2: Keyterms NOW boosted") logger.info(" Say the same names again: Xiomara, Saoirse, Krzystof") logger.info(" (Should transcribe better now!)") - logger.info("="*80) + logger.info("=" * 80) logger.info("šŸ”„ This test has 2 phases:") logger.info(" Phase 1 (15s): No boosting - names may be wrong") @@ -308,29 +312,27 @@ async def test_11_dynamic_silence(): ) async def dynamic_update(task): - logger.info("\n" + "="*80) + logger.info("\n" + "=" * 80) logger.info("PHASE 1: Quick responses (100ms silence threshold)") logger.info(" Speak normally - bot responds quickly") - logger.info("="*80) + logger.info("=" * 80) await asyncio.sleep(10) - logger.info("\n" + "="*80) + logger.info("\n" + "=" * 80) logger.info("šŸ”„ UPDATING: Changing silence from 100ms → 3000ms (3 seconds!)") - logger.info("="*80) + logger.info("=" * 80) await task.queue_frame( STTUpdateSettingsFrame( delta=AssemblyAISTTSettings( - connection_params=AssemblyAIConnectionParams( - min_turn_silence=3000 - ) + connection_params=AssemblyAIConnectionParams(min_turn_silence=3000) ) ) ) - logger.info("\n" + "="*80) + logger.info("\n" + "=" * 80) logger.info("PHASE 2: Patient responses (3 second silence threshold)") logger.info(" Bot will wait 3 full seconds before responding") logger.info(" Try pausing mid-sentence - bot should NOT interrupt") - logger.info("="*80) + logger.info("=" * 80) logger.info("šŸ”„ Dramatic change: 100ms → 3000ms after 10 seconds") await run_bot( @@ -347,16 +349,16 @@ async def test_12_dynamic_prompt(): ) async def dynamic_update(task): - logger.info("\n" + "="*80) + logger.info("\n" + "=" * 80) logger.info("PHASE 1: Default prompt (no keyterms)") logger.info(" Try saying: Xiomara, Saoirse, Krzystof") logger.info(" (May not transcribe correctly)") - logger.info("="*80) + logger.info("=" * 80) await asyncio.sleep(15) - logger.info("\n" + "="*80) + logger.info("\n" + "=" * 80) logger.info("šŸ”„ UPDATING: Adding custom prompt with keyterms") - logger.info("="*80) + logger.info("=" * 80) custom_prompt = """Transcribe verbatim. Rules: 1) Always include punctuation in output. 2) Use period/question mark ONLY for complete sentences. @@ -368,17 +370,15 @@ Pay special attention to these names and transcribe them exactly: Xiomara, Saoir await task.queue_frame( STTUpdateSettingsFrame( delta=AssemblyAISTTSettings( - connection_params=AssemblyAIConnectionParams( - prompt=custom_prompt - ) + connection_params=AssemblyAIConnectionParams(prompt=custom_prompt) ) ) ) - logger.info("\n" + "="*80) + logger.info("\n" + "=" * 80) logger.info("PHASE 2: Prompt with keyterms NOW active") logger.info(" Say the same names again: Xiomara, Saoirse, Krzystof") logger.info(" (Should transcribe better now!)") - logger.info("="*80) + logger.info("=" * 80) logger.info("šŸ”„ This test has 2 phases:") logger.info(" Phase 1 (15s): Default prompt - names may be wrong") @@ -403,9 +403,7 @@ async def test_13_dynamic_clear_keyterms(): await task.queue_frame( STTUpdateSettingsFrame( delta=AssemblyAISTTSettings( - connection_params=AssemblyAIConnectionParams( - keyterms_prompt=[] - ) + connection_params=AssemblyAIConnectionParams(keyterms_prompt=[]) ) ) ) @@ -421,6 +419,7 @@ async def test_13_dynamic_clear_keyterms(): # === DYNAMIC UPDATES - MULTIPLE PARAMETERS (14-15) === + async def test_14_multi_param_update(): """Test 14: Update multiple parameters at once.""" connection_params = AssemblyAIConnectionParams( @@ -464,9 +463,7 @@ async def test_15_complex_sequence(): await task.queue_frame( STTUpdateSettingsFrame( delta=AssemblyAISTTSettings( - connection_params=AssemblyAIConnectionParams( - keyterms_prompt=["Pipecat"] - ) + connection_params=AssemblyAIConnectionParams(keyterms_prompt=["Pipecat"]) ) ) ) @@ -476,9 +473,7 @@ async def test_15_complex_sequence(): await task.queue_frame( STTUpdateSettingsFrame( delta=AssemblyAISTTSettings( - connection_params=AssemblyAIConnectionParams( - min_turn_silence=200 - ) + connection_params=AssemblyAIConnectionParams(min_turn_silence=200) ) ) ) @@ -506,6 +501,7 @@ async def test_15_complex_sequence(): # === MODE COMPARISON (16-17) === + async def test_16_pipecat_mode(): """Test 16: Pipecat mode (VAD + Smart Turn controls turns).""" connection_params = AssemblyAIConnectionParams( @@ -538,6 +534,7 @@ async def test_17_stt_mode(): # === STT MODE TIMING EXPERIMENTS (18-20) === + async def test_18_stt_long_max_short_min(): """Test 18: STT mode - Long max_turn_silence + Short min (5000ms + 100ms).""" connection_params = AssemblyAIConnectionParams( @@ -596,6 +593,7 @@ async def test_20_stt_both_short(): # === EDGE CASES (21-23) === + async def test_21_very_long_silence(): """Test 21: Very long silence threshold (STT mode only).""" connection_params = AssemblyAIConnectionParams( @@ -645,9 +643,9 @@ async def test_23_keyterms_plus_diarization(): def show_menu(): """Display the comprehensive test menu.""" - print("\n" + "="*80) + print("\n" + "=" * 80) print("AssemblyAI u3-rt-pro Comprehensive Test Suite") - print("="*80) + print("=" * 80) print("\nšŸ“‹ BASIC CONFIGURATION (1-3)") print(" 1. Basic Default (100ms)") print(" 2. Custom Silence (200ms)") @@ -688,7 +686,7 @@ def show_menu(): print(" 23. Keyterms + Diarization Combined") print("\n 0. Exit") - print("\n" + "="*80) + print("\n" + "=" * 80) async def main(): @@ -735,6 +733,7 @@ async def main(): except Exception as e: logger.error(f"Test failed with error: {e}") import traceback + traceback.print_exc() input("\n\nPress Enter to return to menu...") diff --git a/test_assemblyai_u3pro.py b/test_assemblyai_u3pro.py index ace700753..236ab9b50 100644 --- a/test_assemblyai_u3pro.py +++ b/test_assemblyai_u3pro.py @@ -50,6 +50,7 @@ from pipecat.transports.local.audio import LocalAudioTransport, LocalAudioTransp load_dotenv() + # Test configuration class TestConfig: """Centralized test configuration.""" @@ -205,9 +206,7 @@ async def test_custom_min_silence(): logger.info("TEST 2: Custom min_turn_silence") logger.info("=" * 80) - connection_params = AssemblyAIConnectionParams( - speech_model="u3-rt-pro", min_turn_silence=200 - ) + connection_params = AssemblyAIConnectionParams(speech_model="u3-rt-pro", min_turn_silence=200) task, transport = await create_basic_voice_agent(connection_params) @@ -307,9 +306,7 @@ async def test_diarization_no_format(): logger.info("TEST 10: Diarization Enabled (No Formatting)") logger.info("=" * 80) - connection_params = AssemblyAIConnectionParams( - speech_model="u3-rt-pro", speaker_labels=True - ) + connection_params = AssemblyAIConnectionParams(speech_model="u3-rt-pro", speaker_labels=True) task, transport = await create_basic_voice_agent(connection_params) @@ -327,9 +324,7 @@ async def test_diarization_xml_format(): logger.info("TEST 11: Diarization with XML Formatting") logger.info("=" * 80) - connection_params = AssemblyAIConnectionParams( - speech_model="u3-rt-pro", speaker_labels=True - ) + connection_params = AssemblyAIConnectionParams(speech_model="u3-rt-pro", speaker_labels=True) task, transport = await create_basic_voice_agent( connection_params, speaker_format="<{speaker}>{text}" @@ -516,9 +511,7 @@ def main(): "prompt_keyterms_conflict, keyterms, diarization, diarization_xml, " "dynamic_keyterms, dynamic_silence, multi_param, all)", ) - parser.add_argument( - "--interactive", action="store_true", help="Run in interactive mode" - ) + parser.add_argument("--interactive", action="store_true", help="Run in interactive mode") args = parser.parse_args()