nifty-coder/stemsplit-backend
0
1#!/usr/bin/env python32"""3Demonstration of automatic provider switching on quota approach.4 5This script shows how the voice control system automatically switches6between providers when one approaches its quota limits.7"""8 9import asyncio10import logging11import sys12import os13 14# Add the parent directory to the path so we can import voice_control15sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))16 17from voice_control.rate_limiter import RateLimiter18from voice_control.provider_manager import ProviderManager19from voice_control.models import ProviderConfig, ProviderType20 21# Set up logging22logging.basicConfig(level=logging.INFO)23logger = logging.getLogger(__name__)24 25 26async def demo_automatic_switching():27 """Demonstrate automatic provider switching functionality."""28 29 # Initialize components30 rate_limiter = RateLimiter()31 await rate_limiter.initialize()32 33 provider_manager = ProviderManager(rate_limiter=rate_limiter)34 35 try:36 # Configure two providers with different quota limits37 free_provider_config = ProviderConfig(38 name="free_provider",39 provider_type=ProviderType.WEB_SPEECH_API,40 enabled=True,41 priority=1, # Higher priority (lower number)42 free_tier_limits={"audio_minutes_per_day": 10}, # Small limit43 rate_limits={"requests_per_minute": 5},44 supported_formats=["webm", "wav"],45 supported_languages=["en-US"],46 cost_per_minute=0.0, # Free47 api_credentials={"api_key": "free_key"}48 )49 50 paid_provider_config = ProviderConfig(51 name="paid_provider", 52 provider_type=ProviderType.DEEPGRAM,53 enabled=True,54 priority=2, # Lower priority (higher number)55 free_tier_limits={"audio_minutes_per_day": 300}, # Large limit56 rate_limits={"requests_per_minute": 100},57 supported_formats=["webm", "wav", "mp3"],58 supported_languages=["en-US"],59 cost_per_minute=0.05, # Paid60 api_credentials={"api_key": "paid_key"}61 )62 63 # Configure rate limiter64 await rate_limiter.configure_provider(free_provider_config)65 await rate_limiter.configure_provider(paid_provider_config)66 67 logger.info("=== Automatic Provider Switching Demo ===")68 69 # 1. Check initial provider availability70 logger.info("\n1. Initial provider availability:")71 availability = await rate_limiter.get_providers_by_availability(60.0) # 1 minute request72 for provider, available in availability.items():73 logger.info(f" {provider}: {'Available' if available else 'Not Available'}")74 75 # 2. Simulate consuming quota on free provider76 logger.info("\n2. Consuming quota on free provider (9 minutes out of 10)...")77 await rate_limiter.consume_quota("free_provider", 540.0, 1) # 9 minutes78 79 # Check quota status80 quota_status = await rate_limiter.check_quota("free_provider", 120.0) # Check for 2 more minutes81 logger.info(f" Free provider quota: {quota_status.percentage_used:.1%} used")82 logger.info(f" Remaining: {quota_status.remaining:.1f} minutes")83 84 # 3. Check if provider switching is recommended85 logger.info("\n3. Checking if provider switching is recommended...")86 should_switch = await rate_limiter.should_switch_provider("free_provider", 120.0)87 logger.info(f" Should switch from free_provider: {should_switch}")88 89 if should_switch:90 logger.info(" ✓ System recommends switching due to quota approach")91 else:92 logger.info(" ✗ No switching recommended")93 94 # 4. Show provider ordering with quota consideration95 logger.info("\n4. Provider ordering (considering quota status):")96 # This would normally be done internally by the provider manager97 # For demo purposes, we'll show the logic98 99 free_approaching = await rate_limiter.is_provider_approaching_limit("free_provider", 120.0, 0.9)100 paid_approaching = await rate_limiter.is_provider_approaching_limit("paid_provider", 120.0, 0.9)101 102 logger.info(f" free_provider approaching limit (90%): {free_approaching}")103 logger.info(f" paid_provider approaching limit (90%): {paid_approaching}")104 105 if free_approaching and not paid_approaching:106 logger.info(" → paid_provider would be selected first due to better quota availability")107 elif not free_approaching:108 logger.info(" → free_provider would be selected first (normal priority)")109 110 # 5. Show exponential backoff scenario111 logger.info("\n5. Demonstrating exponential backoff...")112 113 # Try to exceed quota to trigger backoff114 try:115 await rate_limiter.consume_quota("free_provider", 120.0, 1) # This should exceed the limit116 except Exception as e:117 logger.info(f" Quota exceeded: {e}")118 119 # Check if backoff affects switching decision120 should_switch_backoff = await rate_limiter.should_switch_provider("free_provider", 60.0)121 logger.info(f" Should switch due to backoff: {should_switch_backoff}")122 123 # 6. Show provider availability after quota exhaustion124 logger.info("\n6. Provider availability after quota exhaustion:")125 availability_after = await rate_limiter.get_providers_by_availability(60.0)126 for provider, available in availability_after.items():127 status = "Available" if available else "Rate Limited"128 logger.info(f" {provider}: {status}")129 130 logger.info("\n=== Demo Complete ===")131 logger.info("The system successfully demonstrates automatic provider switching")132 logger.info("when quota limits are approached, ensuring continuous service availability.")133 134 finally:135 # Cleanup136 await rate_limiter.shutdown()137 await provider_manager.shutdown()138 139 140if __name__ == "__main__":141 asyncio.run(demo_automatic_switching())