Skip to main content

Production-quality async Python SDK for universal voice agent routing with multi-provider support

Project description

EchoRoute - Universal Voice Agent Router

A production-quality async Python SDK for routing voice agent requests across multiple providers with a clean plugin architecture.

🚀 Key Features

  • Universal Interface: Single API for multiple voice providers
  • Plugin Architecture: Providers register themselves using their own APIs
  • Production Ready: Comprehensive error handling, retries, and monitoring
  • Async First: Built with asyncio for high performance
  • Fallback Support: Automatic failover between providers
  • Load Balancing: Distribute requests across available providers
  • Health Monitoring: Real-time provider health checks
  • Extensible: Easy to add new providers

📦 Installation

From PyPI (Recommended)

# Basic installation
pip install echoroute

# With OpenAI support
pip install echoroute[openai]

# With Sarvam AI support
pip install echoroute[sarvam]

# With all providers
pip install echoroute[all]

# For development
pip install echoroute[dev]

From Source

git clone https://github.com/gaurav98095/echoroute.git
cd echoroute
pip install -e .[dev]

🏗️ Architecture

The key architectural principle:

👉 Providers register themselves to the router using their own APIs 👉 After registration, the user interacts with a single common interface 👉 The caller must never care which provider is used

🚀 Quick Start

Basic Usage

import asyncio
from echoroute import (
    VoiceRouter,
    VoiceRequest,
    OpenAIProvider,
    ProviderConfig,
    AudioFormat,
    Language
)

async def main():
    # Create and initialize router
    router = VoiceRouter()
    await router.initialize()

    # Register OpenAI provider
    openai_config = ProviderConfig(
        name="openai",
        api_key="your-openai-api-key"
    )
    openai_provider = OpenAIProvider(openai_config)
    await router.register_provider(openai_provider)

    # Create a voice synthesis request
    request = VoiceRequest(
        text="Hello, world! This is a test of the voice router.",
        language=Language.EN_US,
        output_format=AudioFormat.MP3
    )

    # Process the request - router automatically selects best provider
    response = await router.process_request(request)

    # Access synthesized audio
    audio_data = response.synthesis.audio.data
    with open("output.mp3", "wb") as f:
        f.write(audio_data)

    await router.shutdown()

asyncio.run(main())

Multiple Providers with Fallback

import asyncio
from echoroute import (
    VoiceRouter,
    VoiceRequest,
    OpenAIProvider,
    MockProvider,  # For testing
    ProviderConfig,
    Priority
)

async def main():
    router = VoiceRouter()
    await router.initialize()

    # Register primary provider (OpenAI)
    primary_config = ProviderConfig(
        name="openai-primary",
        api_key="your-openai-key",
        priority=Priority.HIGH
    )
    await router.register_provider(OpenAIProvider(primary_config))

    # Register fallback provider
    fallback_config = ProviderConfig(
        name="fallback",
        priority=Priority.NORMAL
    )
    await router.register_provider(MockProvider(fallback_config))

    # Request will try OpenAI first, fallback to Mock if needed
    request = VoiceRequest(text="Hello with fallback support!")
    response = await router.process_request(request, fallback=True)

    print(f"Processed by: {response.provider_name}")

    await router.shutdown()

asyncio.run(main())

Configuration File

# config.yaml
router:
  max_concurrent_requests: 50
  request_timeout: 30.0
  fallback_enabled: true
  load_balancing: false

providers:
  - name: "openai"
    api_key: "${OPENAI_API_KEY}"
    priority: "high"
    timeout: 30.0
    enabled: true

  - name: "backup"
    priority: "normal"
    enabled: true
    custom_settings:
      simulate_latency: false
from echoroute.utils import ConfigManager

# Load configuration
config_manager = ConfigManager.from_file("config.yaml")
router_config = config_manager.get_router_config()
provider_configs = config_manager.get_provider_configs()

# Create router with config
router = VoiceRouter(router_config)
await router.initialize()

# Register providers from config
for provider_config in provider_configs:
    if provider_config.name == "openai":
        provider = OpenAIProvider(provider_config)
    else:
        provider = MockProvider(provider_config)
    await router.register_provider(provider)

🔌 Creating Custom Providers

from echoroute.core import BaseProvider
from echoroute.types import (
    VoiceRequest,
    VoiceResponse,
    ProviderCapabilities,
    AudioFormat,
    Language
)

class MyCustomProvider(BaseProvider):
    async def initialize(self) -> None:
        # Initialize your provider (API clients, etc.)
        await self._initialize_metadata()

    async def get_capabilities(self) -> ProviderCapabilities:
        return ProviderCapabilities(
            supports_synthesis=True,
            supports_transcription=True,
            supported_languages=[Language.EN_US],
            supported_audio_formats=[AudioFormat.MP3, AudioFormat.WAV]
        )

    async def process_request(self, request: VoiceRequest) -> VoiceResponse:
        # Implement your provider logic here
        response = VoiceResponse(provider_name=self.name, processing_time=0.0)

        if request.text:
            # Synthesize speech
            response.synthesis = await self._synthesize(request.text)

        if request.audio:
            # Transcribe audio
            response.transcription = await self._transcribe(request.audio)

        return response

    async def health_check(self) -> bool:
        # Check if your provider is healthy
        return True

# Register your custom provider
config = ProviderConfig(name="my-provider", api_key="key")
provider = MyCustomProvider(config)
await router.register_provider(provider)

📊 Monitoring and Health Checks

# Check provider health
health_status = await router.health_check()
print(health_status)  # {"openai": True, "backup": True}

# Get detailed provider status
status = await router.get_provider_status()
for name, details in status.items():
    print(f"{name}: {details['status']}, "
          f"Success Rate: {details['success_rate']:.2%}, "
          f"Latency: {details['latency_ms']:.2f}ms")

🌍 Indian Language Support with Sarvam AI

EchoRoute includes comprehensive support for Indian languages through Sarvam AI:

import asyncio
from echoroute import (
    VoiceRouter,
    VoiceRequest,
    SarvamProvider,
    ProviderConfig,
    Language,
    VoiceModel
)

async def indian_language_example():
    router = VoiceRouter()
    await router.initialize()

    # Register Sarvam AI provider
    sarvam_config = ProviderConfig(
        name="sarvam_ai",
        api_key="your-sarvam-api-key"
    )
    await router.register_provider(SarvamProvider(sarvam_config))

    # Hindi transcription
    hindi_request = VoiceRequest(
        audio=hindi_audio_data,
        language=Language.HI_IN,
        voice_model=VoiceModel.SAARIKA  # Transcription model
    )

    # Auto-detect language and translate to English
    translate_request = VoiceRequest(
        audio=mixed_language_audio,
        language=Language.AUTO,
        voice_model=VoiceModel.SAARAS  # Translation model
    )

    # Generate Hindi speech
    synthesis_request = VoiceRequest(
        text="नमस्ते, यह वीआर राउटर का परीक्षण है।",
        language=Language.HI_IN,
        voice_model=VoiceModel.BULBUL  # TTS model
    )

    await router.shutdown()

Supported Indian Languages

  • Hindi (hi-IN), Gujarati (gu-IN), Bengali (bn-IN)
  • Tamil (ta-IN), Telugu (te-IN), Marathi (mr-IN)
  • Kannada (kn-IN), Malayalam (ml-IN), Punjabi (pa-IN)
  • Odia (or-IN), Assamese (as-IN), Nepali (ne-IN)
  • Urdu (ur-IN), English Indian (en-IN)

Sarvam AI Models

  • SAARIKA: Speech recognition in original language
  • SAARAS: Speech recognition + translation to English
  • BULBUL: Text-to-speech synthesis

🔧 Advanced Configuration

Environment Variables

export ECHOROUTE_MAX_CONCURRENT_REQUESTS=100
export ECHOROUTE_REQUEST_TIMEOUT=45.0
export ECHOROUTE_FALLBACK_ENABLED=true
export ECHOROUTE_LOG_LEVEL=INFO

Retry Configuration

from echoroute.utils import RetryManager

retry_manager = RetryManager(
    max_retries=3,
    base_delay=1.0,
    exponential_base=2.0,
    jitter=True
)

# Providers automatically use retry logic for transient failures

🧪 Testing

Run the test suite:

pytest tests/

Run with coverage:

pytest tests/ --cov=vrouter --cov-report=html

📝 API Reference

Core Classes

  • VoiceRouter: Main router class for managing providers
  • BaseProvider: Abstract base class for implementing providers
  • ProviderRegistry: Manages provider registration and health
  • ConfigManager: Handles configuration loading and management

Data Models

  • VoiceRequest: Input request with text/audio and parameters
  • VoiceResponse: Response with synthesis/transcription results
  • AudioData: Audio data container with format information
  • ProviderConfig: Configuration for individual providers
  • RouterConfig: Configuration for the router itself

Built-in Providers

  • OpenAIProvider: Integration with OpenAI's speech APIs
  • SarvamProvider: Integration with Sarvam AI's Indian language speech APIs
  • MockProvider: Mock provider for testing and development

🤝 Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Add tests
  5. Submit a pull request

📄 License

MIT License - see LICENSE file for details.

🔗 Links

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

echoroute-0.1.0.tar.gz (23.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

echoroute-0.1.0-py3-none-any.whl (25.6 kB view details)

Uploaded Python 3

File details

Details for the file echoroute-0.1.0.tar.gz.

File metadata

  • Download URL: echoroute-0.1.0.tar.gz
  • Upload date:
  • Size: 23.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.19

File hashes

Hashes for echoroute-0.1.0.tar.gz
Algorithm Hash digest
SHA256 9df9f8ad61966edca6a1b91a355cc51ef7c55ce878c444b71318072359227e01
MD5 7e6b81bacb42e549ed7f710b7bb6d811
BLAKE2b-256 f736e0f6cf70d00a557e065491020a350543af099c5cc351791a3b5d53c18a86

See more details on using hashes here.

File details

Details for the file echoroute-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: echoroute-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 25.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.19

File hashes

Hashes for echoroute-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 40ebdae6314f1614df1e28fb52900664f7ec3d261964dcbb322b4c3815f85a65
MD5 c757ff779903c8239c3ca5850b4bcacf
BLAKE2b-256 7361fc808af091aef50a53cf1ae94647afaf75809bcfb98ebdfefa5eb4827f74

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page