Skip to content

Commit 975bb9b

Browse files
Python: small code improvements in code of call automation sample (#11477)
### Motivation and Context <!-- Thank you for your contribution to the semantic-kernel repo! Please help reviewers and future users, providing the following information: 1. Why is this change required? 2. What problem does it solve? 3. What scenario does it contribute to? 4. If it fixes an open issue, please link to the issue here. --> cleanup of the call automation sample cleaner code and clearer seperation of debug and info logs. ### Description <!-- Describe your changes, the overall approach, the underlying design. These notes will help understanding how your code works. Thanks! --> ### Contribution Checklist <!-- Before submitting this PR, please make sure: --> - [x] The code builds clean without any errors or warnings - [x] The PR follows the [SK Contribution Guidelines](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md) and the [pre-submission formatting script](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md#development-scripts) raises no violations - [x] All unit tests pass, and I have added new tests where possible - [x] I didn't break anyone 😄
1 parent 3cce24b commit 975bb9b

File tree

1 file changed

+72
-72
lines changed

1 file changed

+72
-72
lines changed

python/samples/demos/call_automation/call_automation.py

Lines changed: 72 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,20 @@
1111
####################################################################
1212
#
1313
# /// script
14-
# requires-python = ">=3.10"
14+
# requires-python = ">=3.12"
1515
# dependencies = [
1616
# "Quart",
1717
# "azure-eventgrid",
1818
# "azure-communication-callautomation==1.4.0b1",
19-
# "semantic-kernel[realtime]",
19+
# "semantic-kernel",
2020
# ]
2121
# ///
22-
2322
import asyncio
2423
import base64
24+
import logging
2525
import os
2626
import uuid
2727
from datetime import datetime
28-
from logging import INFO
2928
from random import randint
3029
from urllib.parse import urlencode, urlparse, urlunparse
3130

@@ -96,6 +95,7 @@ async def goodbye(self):
9695

9796
async def from_realtime_to_acs(audio: ndarray):
9897
"""Function that forwards the audio from the model to the websocket of the ACS client."""
98+
app.logger.debug("Audio received from the model, sending to ACS client")
9999
await websocket.send(
100100
json.dumps({"kind": "AudioData", "audioData": {"data": base64.b64encode(audio.tobytes()).decode("utf-8")}})
101101
)
@@ -129,27 +129,28 @@ async def handle_realtime_messages(client: RealtimeClientBase):
129129
async for event in client.receive(audio_output_callback=from_realtime_to_acs):
130130
match event.service_type:
131131
case ListenEvents.SESSION_CREATED:
132-
print("Session Created Message")
133-
print(f" Session Id: {event.service_event.session.id}")
132+
app.logger.info("Session Created Message")
133+
app.logger.debug(f" Session Id: {event.service_event.session.id}")
134134
case ListenEvents.ERROR:
135-
print(f" Error: {event.service_event.error}")
135+
app.logger.error(f" Error: {event.service_event.error}")
136136
case ListenEvents.INPUT_AUDIO_BUFFER_CLEARED:
137-
print("Input Audio Buffer Cleared Message")
137+
app.logger.info("Input Audio Buffer Cleared Message")
138138
case ListenEvents.INPUT_AUDIO_BUFFER_SPEECH_STARTED:
139-
print(f"Voice activity detection started at {event.service_event.audio_start_ms} [ms]")
139+
app.logger.debug(f"Voice activity detection started at {event.service_event.audio_start_ms} [ms]")
140140
await websocket.send(json.dumps({"Kind": "StopAudio", "AudioData": None, "StopAudio": {}}))
141-
142141
case ListenEvents.CONVERSATION_ITEM_INPUT_AUDIO_TRANSCRIPTION_COMPLETED:
143-
print(f" User:-- {event.service_event.transcript}")
142+
app.logger.info(f" User:-- {event.service_event.transcript}")
144143
case ListenEvents.CONVERSATION_ITEM_INPUT_AUDIO_TRANSCRIPTION_FAILED:
145-
print(f" Error: {event.service_event.error}")
144+
app.logger.error(f" Error: {event.service_event.error}")
146145
case ListenEvents.RESPONSE_DONE:
147-
print("Response Done Message")
148-
print(f" Response Id: {event.service_event.response.id}")
146+
app.logger.info("Response Done Message")
147+
app.logger.debug(f" Response Id: {event.service_event.response.id}")
149148
if event.service_event.response.status_details:
150-
print(f" Status Details: {event.service_event.response.status_details.model_dump_json()}")
149+
app.logger.debug(
150+
f" Status Details: {event.service_event.response.status_details.model_dump_json()}"
151+
)
151152
case ListenEvents.RESPONSE_AUDIO_TRANSCRIPT_DONE:
152-
print(f" AI:-- {event.service_event.transcript}")
153+
app.logger.info(f" AI:-- {event.service_event.transcript}")
153154

154155

155156
# region: Routes
@@ -159,8 +160,6 @@ async def handle_realtime_messages(client: RealtimeClientBase):
159160
@app.websocket("/ws")
160161
async def ws():
161162
app.logger.info("Client connected to WebSocket")
162-
163-
# create the client, using the audio callback
164163
client = AzureRealtimeWebsocket()
165164
settings = AzureRealtimeExecutionSettings(
166165
instructions="""You are a chat bot. Your name is Mosscap and
@@ -189,52 +188,51 @@ async def ws():
189188

190189
@app.route("/api/incomingCall", methods=["POST"])
191190
async def incoming_call_handler() -> Response:
192-
app.logger.info("incoming event data")
193191
for event_dict in await request.json:
194192
event = EventGridEvent.from_dict(event_dict)
195-
app.logger.info("incoming event data --> %s", event.data)
196-
197-
if event.event_type == SystemEventNames.EventGridSubscriptionValidationEventName:
198-
app.logger.info("Validating subscription")
199-
validation_code = event.data["validationCode"]
200-
validation_response = {"validationResponse": validation_code}
201-
return Response(response=json.dumps(validation_response), status=200)
202-
203-
if event.event_type == "Microsoft.Communication.IncomingCall":
204-
app.logger.info("Incoming call received: data=%s", event.data)
205-
caller_id = (
206-
event.data["from"]["phoneNumber"]["value"]
207-
if event.data["from"]["kind"] == "phoneNumber"
208-
else event.data["from"]["rawId"]
209-
)
210-
app.logger.info("incoming call handler caller id: %s", caller_id)
211-
incoming_call_context = event.data["incomingCallContext"]
212-
guid = uuid.uuid4()
213-
query_parameters = urlencode({"callerId": caller_id})
214-
callback_uri = f"{CALLBACK_EVENTS_URI}/{guid}?{query_parameters}"
215-
216-
parsed_url = urlparse(CALLBACK_EVENTS_URI)
217-
websocket_url = urlunparse(("wss", parsed_url.netloc, "/ws", "", "", ""))
218-
219-
app.logger.info("callback url: %s", callback_uri)
220-
app.logger.info("websocket url: %s", websocket_url)
221-
222-
media_streaming_options = MediaStreamingOptions(
223-
transport_url=websocket_url,
224-
transport_type=MediaStreamingTransportType.WEBSOCKET,
225-
content_type=MediaStreamingContentType.AUDIO,
226-
audio_channel_type=MediaStreamingAudioChannelType.MIXED,
227-
start_media_streaming=True,
228-
enable_bidirectional=True,
229-
audio_format=AudioFormat.PCM24_K_MONO,
230-
)
231-
answer_call_result = await acs_client.answer_call(
232-
incoming_call_context=incoming_call_context,
233-
operation_context="incomingCall",
234-
callback_url=callback_uri,
235-
media_streaming=media_streaming_options,
236-
)
237-
app.logger.info("Answered call for connection id: %s", answer_call_result.call_connection_id)
193+
match event.event_type:
194+
case SystemEventNames.EventGridSubscriptionValidationEventName:
195+
app.logger.info("Validating subscription")
196+
validation_code = event.data["validationCode"]
197+
validation_response = {"validationResponse": validation_code}
198+
return Response(response=json.dumps(validation_response), status=200)
199+
case SystemEventNames.AcsIncomingCallEventName:
200+
app.logger.debug("Incoming call received: data=%s", event.data)
201+
caller_id = (
202+
event.data["from"]["phoneNumber"]["value"]
203+
if event.data["from"]["kind"] == "phoneNumber"
204+
else event.data["from"]["rawId"]
205+
)
206+
app.logger.info("incoming call handler caller id: %s", caller_id)
207+
incoming_call_context = event.data["incomingCallContext"]
208+
guid = uuid.uuid4()
209+
query_parameters = urlencode({"callerId": caller_id})
210+
callback_uri = f"{CALLBACK_EVENTS_URI}/{guid}?{query_parameters}"
211+
212+
parsed_url = urlparse(CALLBACK_EVENTS_URI)
213+
websocket_url = urlunparse(("wss", parsed_url.netloc, "/ws", "", "", ""))
214+
215+
app.logger.debug("callback url: %s", callback_uri)
216+
app.logger.debug("websocket url: %s", websocket_url)
217+
218+
answer_call_result = await acs_client.answer_call(
219+
incoming_call_context=incoming_call_context,
220+
operation_context="incomingCall",
221+
callback_url=callback_uri,
222+
media_streaming=MediaStreamingOptions(
223+
transport_url=websocket_url,
224+
transport_type=MediaStreamingTransportType.WEBSOCKET,
225+
content_type=MediaStreamingContentType.AUDIO,
226+
audio_channel_type=MediaStreamingAudioChannelType.MIXED,
227+
start_media_streaming=True,
228+
enable_bidirectional=True,
229+
audio_format=AudioFormat.PCM24_K_MONO,
230+
),
231+
)
232+
app.logger.info(f"Answered call for connection id: {answer_call_result.call_connection_id}")
233+
case _:
234+
app.logger.debug("Event type not handled: %s", event.event_type)
235+
app.logger.debug("Event data: %s", event.data)
238236
return Response(status=200)
239237
return Response(status=200)
240238

@@ -246,7 +244,7 @@ async def callbacks(contextId):
246244
global call_connection_id
247245
event_data = event["data"]
248246
call_connection_id = event_data["callConnectionId"]
249-
app.logger.info(
247+
app.logger.debug(
250248
f"Received Event:-> {event['type']}, Correlation Id:-> {event_data['correlationId']}, CallConnectionId:-> {call_connection_id}" # noqa: E501
251249
)
252250
match event["type"]:
@@ -257,23 +255,25 @@ async def callbacks(contextId):
257255
media_streaming_subscription = call_connection_properties.media_streaming_subscription
258256
app.logger.info(f"MediaStreamingSubscription:--> {media_streaming_subscription}")
259257
app.logger.info(f"Received CallConnected event for connection id: {call_connection_id}")
260-
app.logger.info("CORRELATION ID:--> %s", event_data["correlationId"])
261-
app.logger.info("CALL CONNECTION ID:--> %s", event_data["callConnectionId"])
258+
app.logger.debug("CORRELATION ID:--> %s", event_data["correlationId"])
259+
app.logger.debug("CALL CONNECTION ID:--> %s", event_data["callConnectionId"])
262260
case "Microsoft.Communication.MediaStreamingStarted" | "Microsoft.Communication.MediaStreamingStopped":
263-
app.logger.info(f"Media streaming content type:--> {event_data['mediaStreamingUpdate']['contentType']}")
264-
app.logger.info(
261+
app.logger.debug(
262+
f"Media streaming content type:--> {event_data['mediaStreamingUpdate']['contentType']}"
263+
)
264+
app.logger.debug(
265265
f"Media streaming status:--> {event_data['mediaStreamingUpdate']['mediaStreamingStatus']}"
266266
)
267-
app.logger.info(
267+
app.logger.debug(
268268
f"Media streaming status details:--> {event_data['mediaStreamingUpdate']['mediaStreamingStatusDetails']}" # noqa: E501
269269
)
270270
case "Microsoft.Communication.MediaStreamingFailed":
271-
app.logger.info(
271+
app.logger.warning(
272272
f"Code:->{event_data['resultInformation']['code']}, Subcode:-> {event_data['resultInformation']['subCode']}" # noqa: E501
273273
)
274-
app.logger.info(f"Message:->{event_data['resultInformation']['message']}")
274+
app.logger.warning(f"Message:->{event_data['resultInformation']['message']}")
275275
case "Microsoft.Communication.CallDisconnected":
276-
pass
276+
app.logger.debug(f"Call disconnected for connection id: {call_connection_id}")
277277
return Response(status=200)
278278

279279

@@ -286,5 +286,5 @@ def home():
286286

287287

288288
if __name__ == "__main__":
289-
app.logger.setLevel(INFO)
289+
app.logger.setLevel(logging.INFO)
290290
app.run(port=8080)

0 commit comments

Comments
 (0)