checkpointing my wrong work

This commit is contained in:
Ajay Raj 2023-03-18 15:08:07 -07:00
commit f965f32288
6 changed files with 85 additions and 4 deletions

View file

@ -1,6 +1,6 @@
[tool.poetry] [tool.poetry]
name = "vocode" name = "vocode"
version = "0.1.39" version = "0.1.40"
description = "The all-in-one voice SDK" description = "The all-in-one voice SDK"
authors = ["Ajay Raj <ajay@vocode.dev>"] authors = ["Ajay Raj <ajay@vocode.dev>"]
license = "MIT License" license = "MIT License"

View file

@ -5,6 +5,18 @@ from vocode.models.synthesizer import SynthesizerConfig
from vocode.models.transcriber import TranscriberConfig from vocode.models.transcriber import TranscriberConfig
class TwilioConfig(BaseModel):
account_sid: str
auth_token: str
class InternalTwilioConfig(BaseModel):
account_sid: str
api_key: str
api_secret: str
outgoing_application_sid: str
class CallEntity(BaseModel): class CallEntity(BaseModel):
phone_number: str phone_number: str
@ -14,6 +26,7 @@ class CreateInboundCall(BaseModel):
agent_config: AgentConfig agent_config: AgentConfig
synthesizer_config: Optional[SynthesizerConfig] = None synthesizer_config: Optional[SynthesizerConfig] = None
twilio_sid: str twilio_sid: str
twilio_config: Optional[TwilioConfig] = None
class EndOutboundCall(BaseModel): class EndOutboundCall(BaseModel):
@ -27,6 +40,7 @@ class CreateOutboundCall(BaseModel):
agent_config: AgentConfig agent_config: AgentConfig
synthesizer_config: Optional[SynthesizerConfig] = None synthesizer_config: Optional[SynthesizerConfig] = None
conversation_id: Optional[str] = None conversation_id: Optional[str] = None
twilio_config: Optional[TwilioConfig] = None
# TODO add IVR/etc. # TODO add IVR/etc.
@ -39,3 +53,4 @@ class DialIntoZoomCall(BaseModel):
agent_config: AgentConfig agent_config: AgentConfig
synthesizer_config: Optional[SynthesizerConfig] = None synthesizer_config: Optional[SynthesizerConfig] = None
conversation_id: Optional[str] = None conversation_id: Optional[str] = None
twilio_config: Optional[TwilioConfig] = None

View file

@ -3,12 +3,14 @@ from typing import Optional
import requests import requests
import uvicorn import uvicorn
from vocode.models.synthesizer import SynthesizerConfig from vocode.models.synthesizer import SynthesizerConfig
from twilio.jwt.access_token.grants import VoiceGrant
from vocode.models.transcriber import TranscriberConfig from vocode.models.transcriber import TranscriberConfig
from vocode.telephony.utils import create_access_token
from .. import api_key, BASE_URL from .. import api_key, BASE_URL
from ..models.agent import AgentConfig from ..models.agent import AgentConfig
from ..models.telephony import CreateInboundCall from ..models.telephony import CreateInboundCall, InternalTwilioConfig, TwilioConfig
VOCODE_INBOUND_CALL_URL = f"https://{BASE_URL}/create_inbound_call" VOCODE_INBOUND_CALL_URL = f"https://{BASE_URL}/create_inbound_call"
@ -20,6 +22,7 @@ class InboundCallServer:
transcriber_config: Optional[TranscriberConfig] = None, transcriber_config: Optional[TranscriberConfig] = None,
synthesizer_config: Optional[SynthesizerConfig] = None, synthesizer_config: Optional[SynthesizerConfig] = None,
response_on_rate_limit: Optional[str] = None, response_on_rate_limit: Optional[str] = None,
internal_twilio_config: Optional[InternalTwilioConfig] = None,
): ):
self.agent_config = agent_config self.agent_config = agent_config
self.transcriber_config = transcriber_config self.transcriber_config = transcriber_config
@ -30,6 +33,20 @@ class InboundCallServer:
response_on_rate_limit response_on_rate_limit
or "The line is really busy right now, check back later!" or "The line is really busy right now, check back later!"
) )
self.internal_twilio_config = internal_twilio_config
def create_twilio_config(self) -> TwilioConfig:
access_token = create_access_token(self.internal_twilio_config)
access_token.add_grant(
VoiceGrant(
outgoing_application_sid=self.internal_twilio_config.outgoing_application_sid,
incoming_allow=True,
)
)
return TwilioConfig(
account_sid=self.internal_twilio_config.account_sid,
access_token=access_token.to_jwt(),
)
async def handle_call(self, twilio_sid: str = Form(alias="CallSid")): async def handle_call(self, twilio_sid: str = Form(alias="CallSid")):
response = requests.post( response = requests.post(

View file

@ -2,10 +2,20 @@ from typing import Optional
from vocode.models.agent import AgentConfig from vocode.models.agent import AgentConfig
from vocode.models.synthesizer import SynthesizerConfig from vocode.models.synthesizer import SynthesizerConfig
from vocode.models.transcriber import TranscriberConfig from vocode.models.transcriber import TranscriberConfig
from ..models.telephony import CallEntity, CreateOutboundCall, EndOutboundCall from vocode.telephony.utils import create_access_token
from ..models.telephony import (
CallEntity,
CreateOutboundCall,
EndOutboundCall,
InternalTwilioConfig,
TwilioConfig,
)
import requests import requests
from .. import api_key, BASE_URL from .. import api_key, BASE_URL
from twilio.jwt.access_token.grants import VoiceGrant
VOCODE_CREATE_OUTBOUND_CALL_URL = f"https://{BASE_URL}/create_outbound_call" VOCODE_CREATE_OUTBOUND_CALL_URL = f"https://{BASE_URL}/create_outbound_call"
VOCODE_END_OUTBOUND_CALL_URL = f"https://{BASE_URL}/end_outbound_call" VOCODE_END_OUTBOUND_CALL_URL = f"https://{BASE_URL}/end_outbound_call"
@ -19,6 +29,7 @@ class OutboundCall:
transcriber_config: Optional[TranscriberConfig] = None, transcriber_config: Optional[TranscriberConfig] = None,
synthesizer_config: Optional[SynthesizerConfig] = None, synthesizer_config: Optional[SynthesizerConfig] = None,
conversation_id: Optional[str] = None, conversation_id: Optional[str] = None,
internal_twilio_config: Optional[InternalTwilioConfig] = None,
): ):
self.recipient = recipient self.recipient = recipient
self.caller = caller self.caller = caller
@ -26,6 +37,19 @@ class OutboundCall:
self.transcriber_config = transcriber_config self.transcriber_config = transcriber_config
self.synthesizer_config = synthesizer_config self.synthesizer_config = synthesizer_config
self.conversation_id = conversation_id self.conversation_id = conversation_id
self.internal_twilio_config = internal_twilio_config
def create_twilio_config(self) -> TwilioConfig:
access_token = create_access_token(self.internal_twilio_config)
access_token.add_grant(
VoiceGrant(
outgoing_application_sid=self.internal_twilio_config.outgoing_application_sid
)
)
return TwilioConfig(
account_sid=self.internal_twilio_config.account_sid,
access_token=access_token.to_jwt(),
)
def start(self) -> str: def start(self) -> str:
response = requests.post( response = requests.post(
@ -38,6 +62,9 @@ class OutboundCall:
transcriber_config=self.transcriber_config, transcriber_config=self.transcriber_config,
synthesizer_config=self.synthesizer_config, synthesizer_config=self.synthesizer_config,
conversation_id=self.conversation_id, conversation_id=self.conversation_id,
twilio_config=self.create_twilio_config()
if self.internal_twilio_config
else None,
).dict(), ).dict(),
) )
assert response.ok, response.text assert response.ok, response.text

12
vocode/telephony/utils.py Normal file
View file

@ -0,0 +1,12 @@
from twilio.jwt.access_token import AccessToken
from vocode.models.telephony import InternalTwilioConfig
def create_access_token(twilio_config: InternalTwilioConfig):
return AccessToken(
twilio_config.account_sid,
twilio_config.api_key,
twilio_config.api_secret,
identity="user",
)

View file

@ -3,7 +3,12 @@ from vocode.models.agent import AgentConfig
from vocode.models.synthesizer import SynthesizerConfig from vocode.models.synthesizer import SynthesizerConfig
from vocode.models.transcriber import TranscriberConfig from vocode.models.transcriber import TranscriberConfig
from vocode.telephony.outbound_call import OutboundCall from vocode.telephony.outbound_call import OutboundCall
from ..models.telephony import CallEntity, DialIntoZoomCall from ..models.telephony import (
CallEntity,
DialIntoZoomCall,
InternalTwilioConfig,
TwilioConfig,
)
import requests import requests
from .. import api_key, BASE_URL from .. import api_key, BASE_URL
@ -21,6 +26,7 @@ class ZoomDialIn(OutboundCall):
transcriber_config: Optional[TranscriberConfig] = None, transcriber_config: Optional[TranscriberConfig] = None,
synthesizer_config: Optional[SynthesizerConfig] = None, synthesizer_config: Optional[SynthesizerConfig] = None,
conversation_id: Optional[str] = None, conversation_id: Optional[str] = None,
internal_twilio_config: Optional[InternalTwilioConfig] = None,
): ):
super().__init__( super().__init__(
recipient=recipient, recipient=recipient,
@ -29,6 +35,7 @@ class ZoomDialIn(OutboundCall):
transcriber_config=transcriber_config, transcriber_config=transcriber_config,
synthesizer_config=synthesizer_config, synthesizer_config=synthesizer_config,
conversation_id=conversation_id, conversation_id=conversation_id,
internal_twilio_config=internal_twilio_config,
) )
self.zoom_meeting_id = zoom_meeting_id self.zoom_meeting_id = zoom_meeting_id
self.zoom_meeting_password = zoom_meeting_password self.zoom_meeting_password = zoom_meeting_password
@ -46,6 +53,9 @@ class ZoomDialIn(OutboundCall):
transcriber_config=self.transcriber_config, transcriber_config=self.transcriber_config,
synthesizer_config=self.synthesizer_config, synthesizer_config=self.synthesizer_config,
conversation_id=self.conversation_id, conversation_id=self.conversation_id,
twilio_config=self.create_twilio_config()
if self.internal_twilio_config
else None,
).dict(), ).dict(),
) )
assert response.ok, response.text assert response.ok, response.text