open source
This commit is contained in:
parent
70b6e17c69
commit
a93bfc1ec9
61 changed files with 4013 additions and 126 deletions
143
vocode/streaming/telephony/server/base.py
Normal file
143
vocode/streaming/telephony/server/base.py
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
import logging
|
||||
from typing import Optional
|
||||
from fastapi import APIRouter, Form, Response
|
||||
from pydantic import BaseModel
|
||||
from vocode.streaming.agent.base_agent import BaseAgent
|
||||
from vocode.streaming.models.agent import AgentConfig
|
||||
from vocode.streaming.models.synthesizer import (
|
||||
AzureSynthesizerConfig,
|
||||
SynthesizerConfig,
|
||||
)
|
||||
from vocode.streaming.models.transcriber import (
|
||||
DeepgramTranscriberConfig,
|
||||
PunctuationEndpointingConfig,
|
||||
TranscriberConfig,
|
||||
)
|
||||
from vocode.streaming.synthesizer.base_synthesizer import BaseSynthesizer
|
||||
from vocode.streaming.telephony.config_manager.base_config_manager import (
|
||||
BaseConfigManager,
|
||||
)
|
||||
from vocode.streaming.telephony.constants import (
|
||||
DEFAULT_AUDIO_ENCODING,
|
||||
DEFAULT_CHUNK_SIZE,
|
||||
DEFAULT_SAMPLING_RATE,
|
||||
)
|
||||
|
||||
from vocode.streaming.telephony.server.router.calls import CallsRouter
|
||||
from vocode.streaming.telephony.server.router.twiml import TwiMLRouter
|
||||
from vocode.streaming.models.telephony import (
|
||||
CallConfig,
|
||||
CallEntity,
|
||||
CreateOutboundCall,
|
||||
CreateInboundCall,
|
||||
DialIntoZoomCall,
|
||||
EndOutboundCall,
|
||||
TwilioConfig,
|
||||
)
|
||||
from twilio.rest import Client
|
||||
|
||||
from vocode.streaming.telephony.conversation.call import Call
|
||||
from vocode.streaming.telephony.templates import Templater
|
||||
from vocode.streaming.transcriber.base_transcriber import BaseTranscriber
|
||||
from vocode.streaming.utils import create_conversation_id
|
||||
|
||||
|
||||
class InboundCallConfig(BaseModel):
|
||||
url: str
|
||||
agent_config: AgentConfig
|
||||
twilio_config: TwilioConfig
|
||||
transcriber_config: Optional[TranscriberConfig] = None
|
||||
synthesizer_config: Optional[SynthesizerConfig] = None
|
||||
|
||||
|
||||
class TelephonyServer:
|
||||
def __init__(
|
||||
self,
|
||||
base_url: str,
|
||||
config_manager: BaseConfigManager,
|
||||
inbound_call_configs: list[InboundCallConfig] = [],
|
||||
logger: Optional[logging.Logger] = None,
|
||||
):
|
||||
self.base_url = base_url
|
||||
self.logger = logger or logging.getLogger(__name__)
|
||||
self.router = APIRouter()
|
||||
self.config_manager = config_manager
|
||||
self.templater = Templater()
|
||||
self.router.include_router(
|
||||
CallsRouter(
|
||||
base_url=base_url,
|
||||
templater=self.templater,
|
||||
config_manager=self.config_manager,
|
||||
logger=self.logger,
|
||||
).get_router()
|
||||
)
|
||||
self.router.include_router(
|
||||
TwiMLRouter(
|
||||
base_url=base_url, templater=self.templater, logger=self.logger
|
||||
).get_router()
|
||||
)
|
||||
for config in inbound_call_configs:
|
||||
self.router.add_api_route(
|
||||
config.url,
|
||||
self.create_inbound_route(
|
||||
agent_config=config.agent_config,
|
||||
twilio_config=config.twilio_config,
|
||||
transcriber_config=config.transcriber_config,
|
||||
synthesizer_config=config.synthesizer_config,
|
||||
),
|
||||
methods=["POST"],
|
||||
)
|
||||
logger.info(f"Set up inbound call TwiML at https://{base_url}{config.url}")
|
||||
|
||||
def create_inbound_route(
|
||||
self,
|
||||
agent_config: AgentConfig,
|
||||
twilio_config: TwilioConfig,
|
||||
transcriber_config: Optional[TranscriberConfig] = None,
|
||||
synthesizer_config: Optional[SynthesizerConfig] = None,
|
||||
):
|
||||
def route(twilio_sid: str = Form(alias="CallSid")) -> Response:
|
||||
call_config = CallConfig(
|
||||
transcriber_config=transcriber_config
|
||||
or DeepgramTranscriberConfig(
|
||||
sampling_rate=DEFAULT_SAMPLING_RATE,
|
||||
audio_encoding=DEFAULT_AUDIO_ENCODING,
|
||||
chunk_size=DEFAULT_CHUNK_SIZE,
|
||||
model="voicemail",
|
||||
endpointing_config=PunctuationEndpointingConfig(),
|
||||
),
|
||||
agent_config=agent_config,
|
||||
synthesizer_config=synthesizer_config
|
||||
or AzureSynthesizerConfig(
|
||||
sampling_rate=DEFAULT_SAMPLING_RATE,
|
||||
audio_encoding=DEFAULT_AUDIO_ENCODING,
|
||||
),
|
||||
twilio_config=twilio_config,
|
||||
twilio_sid=twilio_sid,
|
||||
)
|
||||
|
||||
conversation_id = create_conversation_id()
|
||||
self.config_manager.save_config(conversation_id, call_config)
|
||||
return self.templater.get_connection_twiml(
|
||||
base_url=self.base_url, call_id=conversation_id
|
||||
)
|
||||
|
||||
return route
|
||||
|
||||
async def end_outbound_call(self, conversation_id: str):
|
||||
# TODO validation via twilio_client
|
||||
call_config = self.config_manager.get_config(conversation_id)
|
||||
if not call_config:
|
||||
raise ValueError("Call not found")
|
||||
call = Call.from_call_config(
|
||||
self.base_url,
|
||||
call_config,
|
||||
self.config_manager,
|
||||
conversation_id,
|
||||
self.logger,
|
||||
)
|
||||
call.end_twilio_call()
|
||||
return {"id": call.id}
|
||||
|
||||
def get_router(self) -> APIRouter:
|
||||
return self.router
|
||||
Loading…
Add table
Add a link
Reference in a new issue