Merge pull request #2622 from pipecat-ai/mb/call-data-runner
Add to, from phone info and custom data to the development runner
This commit is contained in:
18
CHANGELOG.md
18
CHANGELOG.md
@@ -39,6 +39,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
Using the universal `LLMContext` and associated `LLMContextAggregatorPair` is
|
Using the universal `LLMContext` and associated `LLMContextAggregatorPair` is
|
||||||
a pre-requisite for using `LLMSwitcher` to switch between LLMs at runtime.
|
a pre-requisite for using `LLMSwitcher` to switch between LLMs at runtime.
|
||||||
|
|
||||||
|
- Added new fields to the development runner's `parse_telephony_websocket`
|
||||||
|
method in support of providing dynamic data to a bot.
|
||||||
|
|
||||||
|
- Twilio: Added a new `body` parameter, which parses the websocket message
|
||||||
|
for `customParameters`. Provide data via the `Parameter` nouns in your
|
||||||
|
TwiML to use this feature.
|
||||||
|
- Telnyx & Exotel: Both providers make the `to` and `from` phone numbers
|
||||||
|
available in the websocket messages. You can now access these numbers as
|
||||||
|
`call_data["to"]` and `call_data["from"]`.
|
||||||
|
|
||||||
|
Note: Each telephony provider offers different features. Refer to the
|
||||||
|
corresponding example in `pipecat-examples` to see how to pass custom data
|
||||||
|
to your bot.
|
||||||
|
|
||||||
|
- Added `body` to the `WebsocketRunnerArguments` as an optional parameter.
|
||||||
|
Custom `body` information can be passed from the server into the bot file via
|
||||||
|
the `bot()` method using this new parameter.
|
||||||
|
|
||||||
- Added video streaming support to `LiveKitTransport`.
|
- Added video streaming support to `LiveKitTransport`.
|
||||||
|
|
||||||
- Added `OpenAIRealtimeLLMService` and `AzureRealtimeLLMService` which provide
|
- Added `OpenAIRealtimeLLMService` and `AzureRealtimeLLMService` which provide
|
||||||
|
|||||||
@@ -51,9 +51,11 @@ class WebSocketRunnerArguments(RunnerArguments):
|
|||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
websocket: WebSocket connection for audio streaming
|
websocket: WebSocket connection for audio streaming
|
||||||
|
body: Additional request data
|
||||||
"""
|
"""
|
||||||
|
|
||||||
websocket: WebSocket
|
websocket: WebSocket
|
||||||
|
body: Optional[Any] = field(default_factory=dict)
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
|
|||||||
@@ -99,16 +99,35 @@ async def parse_telephony_websocket(websocket: WebSocket):
|
|||||||
tuple: (transport_type: str, call_data: dict)
|
tuple: (transport_type: str, call_data: dict)
|
||||||
|
|
||||||
call_data contains provider-specific fields:
|
call_data contains provider-specific fields:
|
||||||
- Twilio: {"stream_id": str, "call_id": str}
|
- Twilio: {
|
||||||
- Telnyx: {"stream_id": str, "call_control_id": str, "outbound_encoding": str}
|
"stream_id": str,
|
||||||
- Plivo: {"stream_id": str, "call_id": str}
|
"call_id": str,
|
||||||
- Exotel: {"stream_id": str, "call_id": str, "account_sid": str}
|
"body": dict
|
||||||
|
}
|
||||||
|
- Telnyx: {
|
||||||
|
"stream_id": str,
|
||||||
|
"call_control_id": str,
|
||||||
|
"outbound_encoding": str,
|
||||||
|
"from": str,
|
||||||
|
"to": str,
|
||||||
|
}
|
||||||
|
- Plivo: {
|
||||||
|
"stream_id": str,
|
||||||
|
"call_id": str,
|
||||||
|
}
|
||||||
|
- Exotel: {
|
||||||
|
"stream_id": str,
|
||||||
|
"call_id": str,
|
||||||
|
"account_sid": str,
|
||||||
|
"from": str,
|
||||||
|
"to": str,
|
||||||
|
}
|
||||||
|
|
||||||
Example usage::
|
Example usage::
|
||||||
|
|
||||||
transport_type, call_data = await parse_telephony_websocket(websocket)
|
transport_type, call_data = await parse_telephony_websocket(websocket)
|
||||||
if transport_type == "telnyx":
|
if transport_type == "twilio":
|
||||||
outbound_encoding = call_data["outbound_encoding"]
|
user_id = call_data["body"]["user_id"]
|
||||||
"""
|
"""
|
||||||
# Read first two messages
|
# Read first two messages
|
||||||
start_data = websocket.iter_text()
|
start_data = websocket.iter_text()
|
||||||
@@ -151,9 +170,12 @@ async def parse_telephony_websocket(websocket: WebSocket):
|
|||||||
# Extract provider-specific data
|
# Extract provider-specific data
|
||||||
if transport_type == "twilio":
|
if transport_type == "twilio":
|
||||||
start_data = call_data_raw.get("start", {})
|
start_data = call_data_raw.get("start", {})
|
||||||
|
body_data = start_data.get("customParameters", {})
|
||||||
call_data = {
|
call_data = {
|
||||||
"stream_id": start_data.get("streamSid"),
|
"stream_id": start_data.get("streamSid"),
|
||||||
"call_id": start_data.get("callSid"),
|
"call_id": start_data.get("callSid"),
|
||||||
|
# All custom parameters
|
||||||
|
"body": body_data,
|
||||||
}
|
}
|
||||||
|
|
||||||
elif transport_type == "telnyx":
|
elif transport_type == "telnyx":
|
||||||
@@ -163,6 +185,8 @@ async def parse_telephony_websocket(websocket: WebSocket):
|
|||||||
"outbound_encoding": call_data_raw.get("start", {})
|
"outbound_encoding": call_data_raw.get("start", {})
|
||||||
.get("media_format", {})
|
.get("media_format", {})
|
||||||
.get("encoding"),
|
.get("encoding"),
|
||||||
|
"from": call_data_raw.get("start", {}).get("from", ""),
|
||||||
|
"to": call_data_raw.get("start", {}).get("to", ""),
|
||||||
}
|
}
|
||||||
|
|
||||||
elif transport_type == "plivo":
|
elif transport_type == "plivo":
|
||||||
@@ -178,6 +202,8 @@ async def parse_telephony_websocket(websocket: WebSocket):
|
|||||||
"stream_id": start_data.get("stream_sid"),
|
"stream_id": start_data.get("stream_sid"),
|
||||||
"call_id": start_data.get("call_sid"),
|
"call_id": start_data.get("call_sid"),
|
||||||
"account_sid": start_data.get("account_sid"),
|
"account_sid": start_data.get("account_sid"),
|
||||||
|
"from": start_data.get("from", ""),
|
||||||
|
"to": start_data.get("to", ""),
|
||||||
}
|
}
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
|||||||
Reference in New Issue
Block a user