-
Notifications
You must be signed in to change notification settings - Fork 30
voice agents refactoring #207
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
7a00c1d
c5d0a04
2acffea
98b0597
b460cf2
a27956a
04c9ba7
95e7a11
1e6741f
8d35f5a
0a2e567
b0899d7
c594ff6
bdb3f10
e620845
b5993b9
452755f
365da18
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -16,8 +16,6 @@ | |||||||||
| from pipecat.runner.types import WebSocketRunnerArguments | ||||||||||
| from pipecat.runner.utils import parse_telephony_websocket | ||||||||||
|
|
||||||||||
| # from pipecat.audio.turn.smart_turn.local_smart_turn_v3 import LocalSmartTurnAnalyzerV3 | ||||||||||
| # from pipecat.audio.turn.smart_turn.base_smart_turn import SmartTurnParams | ||||||||||
| from pipecat.serializers.twilio import TwilioFrameSerializer | ||||||||||
| from pipecat.audio.vad.silero import SileroVADAnalyzer | ||||||||||
| from pipecat.audio.vad.vad_analyzer import VADParams | ||||||||||
|
|
@@ -119,6 +117,8 @@ async def inbound_webhook( | |||||||||
|
|
||||||||||
| # Pass parameters to WebSocket stream | ||||||||||
| stream.parameter(name='voice_agent_id', value=agent_id) | ||||||||||
| stream.parameter(name='customer_number', value=From) | ||||||||||
| stream.parameter(name='agent_number', value=To) | ||||||||||
|
|
||||||||||
| connect.append(stream) | ||||||||||
| response.append(connect) | ||||||||||
|
|
@@ -134,13 +134,15 @@ async def inbound_webhook( | |||||||||
|
|
||||||||||
| @webhook_router.post('/twiml') | ||||||||||
| async def twiml_endpoint( | ||||||||||
| From: str = Form(...), | ||||||||||
| To: str = Form(...), | ||||||||||
| voice_agent_id: str = Query(...), | ||||||||||
| welcome_message_audio_url: str = Query(default=''), | ||||||||||
| ): | ||||||||||
| """ | ||||||||||
| Twilio TwiML endpoint | ||||||||||
|
|
||||||||||
| Called by Twilio when call connects (directly or via inbound webhook redirect). | ||||||||||
| Called by Twilio when call connects (directly or via outbound webhook redirect). | ||||||||||
| Returns TwiML XML with WebSocket connection instructions. | ||||||||||
|
|
||||||||||
| Query params: | ||||||||||
|
|
@@ -181,6 +183,8 @@ async def twiml_endpoint( | |||||||||
|
|
||||||||||
| # Pass parameters to WebSocket stream | ||||||||||
| stream.parameter(name='voice_agent_id', value=voice_agent_id) | ||||||||||
| stream.parameter(name='customer_number', value=To) | ||||||||||
| stream.parameter(name='agent_number', value=From) | ||||||||||
|
Comment on lines
+186
to
+187
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Critical: In the
In Twilio webhooks, 🐛 Fix the swapped parameters # Pass parameters to WebSocket stream
stream.parameter(name='voice_agent_id', value=voice_agent_id)
- stream.parameter(name='customer_number', value=To)
- stream.parameter(name='agent_number', value=From)
+ stream.parameter(name='customer_number', value=From)
+ stream.parameter(name='agent_number', value=To)📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is actually an outbound web hook There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
For outbound calls initiated by Twilio:
So the mapping in stream.parameter(name='customer_number', value=To) # Customer is being called
stream.parameter(name='agent_number', value=From) # Agent is the callerThis is the opposite of ✏️ Learnings added
|
||||||||||
|
|
||||||||||
| connect.append(stream) | ||||||||||
| response.append(connect) | ||||||||||
|
|
@@ -223,12 +227,20 @@ async def websocket_endpoint( | |||||||||
| # Extract parameters from stream | ||||||||||
| body_data = call_data.get('body', {}) | ||||||||||
| voice_agent_id = body_data.get('voice_agent_id') | ||||||||||
| customer_number = body_data.get('customer_number') | ||||||||||
| # agent_number = body_data.get('agent_number') | ||||||||||
coderabbitai[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
|
|
||||||||||
| if not voice_agent_id: | ||||||||||
| logger.error('voice_agent_id not found in stream parameters') | ||||||||||
| await websocket.close(code=1008, reason='Missing voice_agent_id') | ||||||||||
| return | ||||||||||
|
|
||||||||||
| if not customer_number: | ||||||||||
| logger.warning( | ||||||||||
| 'customer_number not found in stream parameters, using empty string' | ||||||||||
| ) | ||||||||||
| customer_number = '' | ||||||||||
|
|
||||||||||
| logger.info(f'Voice agent ID: {voice_agent_id}') | ||||||||||
|
|
||||||||||
| # Convert voice_agent_id to UUID | ||||||||||
|
|
@@ -263,13 +275,12 @@ async def websocket_endpoint( | |||||||||
| vad_analyzer=SileroVADAnalyzer( | ||||||||||
| params=VADParams( | ||||||||||
| confidence=0.7, # Default is 0.7, can lower to 0.4-0.5 for faster detection | ||||||||||
| start_secs=0.15, # Default is 0.2, keep it | ||||||||||
| stop_secs=0.8, # KEY: Lower from default 0.8 for faster cutoff (should be 0.2 for smart turn detection) | ||||||||||
| start_secs=0.2, # Default is 0.2, keep it | ||||||||||
| stop_secs=0.2, # KEY: Lower from default 0.8 for faster cutoff (should be 0.2 for smart turn detection) | ||||||||||
| min_volume=0.6, # Default is 0.6, adjust based on your audio quality | ||||||||||
| ), | ||||||||||
| ), # Voice Activity Detection | ||||||||||
| serializer=serializer, | ||||||||||
| # turn_analyzer=LocalSmartTurnAnalyzerV3(params=SmartTurnParams()), | ||||||||||
| ), | ||||||||||
| ) | ||||||||||
|
|
||||||||||
|
|
@@ -282,6 +293,7 @@ async def websocket_endpoint( | |||||||||
| tts_config=configs['tts_config'], | ||||||||||
| stt_config=configs['stt_config'], | ||||||||||
| tools=configs['tools'], | ||||||||||
| customer_number=customer_number, | ||||||||||
| ) | ||||||||||
|
|
||||||||||
| except Exception as e: | ||||||||||
|
|
||||||||||
Uh oh!
There was an error while loading. Please reload this page.