Skip to content

Commit b4456aa

Browse files
authoredMar 6, 2025
Python: restructured the client classes, agent verbs (microsoft#10834)
### 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. --> Added some extra ways to provide functions to the models, and allow more things to be set in the client constructor, rather then the __call__ that get's called by the async context manager. ### Description <!-- Describe your changes, the overall approach, the underlying design. These notes will help understanding how your code works. Thanks! --> - This also splits the backend classes into a new file called _open_ai_realtime.py keeping only the public classes available in the open_ai_realtime.py file. - Adds additional ways of setting up - Adds usage of model_extra to set things up in the constructor ### 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 191f595 commit b4456aa

14 files changed

+1018
-941
lines changed
 

‎python/samples/concepts/realtime/README.md

+5-5
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ To run these samples, you will need to have the following setup:
1111
- pyaudio
1212
- sounddevice
1313
- pydub
14-
e.g. pip install pyaudio sounddevice pydub semantic_kernel[realtime]
14+
e.g. pip install pyaudio sounddevice pydub semantic-kernel[realtime]
1515

1616
The samples all run as python scripts, that can either be started directly or through your IDE.
1717

@@ -41,10 +41,10 @@ The following two samples use function calling with the following functions:
4141

4242
A line is logged whenever one of these functions is called.
4343

44-
### [Chat with function calling Websocket](./realtime_chat_with_function_calling_websocket.py)
44+
### [Chat with function calling Websocket](./realtime_agent_with_function_calling_websocket.py)
4545

46-
This sample uses the websocket api with Azure OpenAI to run the interaction with the voice model, but now with function calling.
46+
This sample uses the websocket api with Azure OpenAI to run a voice agent, capable of taking actions on your behalf.
4747

48-
### [Chat with function calling WebRTC](./realtime_chat_with_function_calling_webrtc.py)
48+
### [Chat with function calling WebRTC](./realtime_agent_with_function_calling_webrtc.py)
4949

50-
This sample uses the WebRTC api with OpenAI to run the interaction with the voice model, but now with function calling.
50+
This sample uses the WebRTC api with OpenAI to run a voice agent, capable of taking actions on your behalf.

‎python/samples/concepts/realtime/realtime_chat_with_function_calling_webrtc.py ‎python/samples/concepts/realtime/realtime_agent_with_function_calling_webrtc.py

+31-33
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,14 @@
66
from random import randint
77

88
from samples.concepts.realtime.utils import AudioPlayerWebRTC, AudioRecorderWebRTC, check_audio_devices
9-
from semantic_kernel import Kernel
109
from semantic_kernel.connectors.ai import FunctionChoiceBehavior
1110
from semantic_kernel.connectors.ai.open_ai import (
1211
ListenEvents,
1312
OpenAIRealtimeExecutionSettings,
1413
OpenAIRealtimeWebRTC,
1514
TurnDetection,
1615
)
17-
from semantic_kernel.contents import ChatHistory
18-
from semantic_kernel.contents.realtime_events import RealtimeTextEvent
16+
from semantic_kernel.contents import ChatHistory, RealtimeTextEvent
1917
from semantic_kernel.functions import kernel_function
2018

2119
logging.basicConfig(level=logging.WARNING)
@@ -26,13 +24,13 @@
2624

2725
"""
2826
This simple sample demonstrates how to use the OpenAI Realtime API to create
29-
a chat bot that can listen and respond directly through audio.
27+
a agent that can listen and respond directly through audio.
3028
It requires installing:
3129
- semantic-kernel[realtime]
3230
- pyaudio
3331
- sounddevice
3432
- pydub
35-
e.g. pip install pyaudio sounddevice pydub semantic_kernel[realtime]
33+
e.g. pip install pyaudio sounddevice pydub semantic-kernel[realtime]
3634
3735
For more details of the exact setup, see the README.md in the realtime folder.
3836
"""
@@ -46,41 +44,42 @@
4644
check_audio_devices()
4745

4846

49-
@kernel_function
50-
def get_weather(location: str) -> str:
51-
"""Get the weather for a location."""
52-
weather_conditions = ("sunny", "hot", "cloudy", "raining", "freezing", "snowing")
53-
weather = weather_conditions[randint(0, len(weather_conditions) - 1)] # nosec
54-
logger.info(f"@ Getting weather for {location}: {weather}")
55-
return f"The weather in {location} is {weather}."
47+
class Helpers:
48+
"""A set of helper functions for the Realtime Agent."""
5649

50+
@kernel_function
51+
def get_weather(self, location: str) -> str:
52+
"""Get the weather for a location."""
53+
weather_conditions = ("sunny", "hot", "cloudy", "raining", "freezing", "snowing")
54+
weather = weather_conditions[randint(0, len(weather_conditions) - 1)] # nosec
55+
logger.info(f"@ Getting weather for {location}: {weather}")
56+
return f"The weather in {location} is {weather}."
5757

58-
@kernel_function
59-
def get_date_time() -> str:
60-
"""Get the current date and time."""
61-
logger.info("@ Getting current datetime")
62-
return f"The current date and time is {datetime.now().isoformat()}."
58+
@kernel_function
59+
def get_date_time(self) -> str:
60+
"""Get the current date and time."""
61+
logger.info("@ Getting current datetime")
62+
return f"The current date and time is {datetime.now().isoformat()}."
6363

64-
65-
@kernel_function
66-
def goodbye():
67-
"""When the user is done, say goodbye and then call this function."""
68-
logger.info("@ Goodbye has been called!")
69-
raise KeyboardInterrupt
64+
@kernel_function
65+
def goodbye(self):
66+
"""When the user is done, say goodbye and then call this function."""
67+
logger.info("@ Goodbye has been called!")
68+
raise KeyboardInterrupt
7069

7170

7271
async def main() -> None:
7372
print_transcript = True
74-
# create the Kernel and add a simple function for function calling.
75-
kernel = Kernel()
76-
kernel.add_functions(plugin_name="helpers", functions=[goodbye, get_weather, get_date_time])
77-
7873
# create the audio player and audio track
79-
# both take a device_id parameter, which is the index of the device to use, if None the default device is used
74+
# both take a device_id parameter, which is the index of the device to use,
75+
# if None the default device will be used
8076
audio_player = AudioPlayerWebRTC()
81-
# create the realtime client and optionally add the audio output function, this is optional
77+
78+
# create the realtime agent and optionally add the audio output function, this is optional
8279
# and can also be passed in the receive method
83-
realtime_client = OpenAIRealtimeWebRTC(audio_track=AudioRecorderWebRTC())
80+
# You can also pass in kernel, plugins, chat_history or settings here.
81+
# For WebRTC the audio_track is required
82+
realtime_agent = OpenAIRealtimeWebRTC(audio_track=AudioRecorderWebRTC(), plugins=[Helpers()])
8483

8584
# Create the settings for the session
8685
# The realtime api, does not use a system message, but takes instructions as a parameter for a session
@@ -111,14 +110,13 @@ async def main() -> None:
111110
# the context manager calls the create_session method on the client and starts listening to the audio stream
112111
async with (
113112
audio_player,
114-
realtime_client(
113+
realtime_agent(
115114
settings=settings,
116115
chat_history=chat_history,
117-
kernel=kernel,
118116
create_response=True,
119117
),
120118
):
121-
async for event in realtime_client.receive(audio_output_callback=audio_player.client_callback):
119+
async for event in realtime_agent.receive(audio_output_callback=audio_player.client_callback):
122120
match event:
123121
case RealtimeTextEvent():
124122
if print_transcript:

‎python/samples/concepts/realtime/realtime_chat_with_function_calling_websocket.py ‎python/samples/concepts/realtime/realtime_agent_with_function_calling_websocket.py

+14-14
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@
1414
ListenEvents,
1515
TurnDetection,
1616
)
17-
from semantic_kernel.contents import ChatHistory
18-
from semantic_kernel.contents.realtime_events import RealtimeTextEvent
17+
from semantic_kernel.contents import ChatHistory, RealtimeTextEvent
1918
from semantic_kernel.functions import kernel_function
2019

2120
logger = logging.getLogger(__name__)
@@ -29,7 +28,7 @@
2928
- pyaudio
3029
- sounddevice
3130
- pydub
32-
e.g. pip install pyaudio sounddevice pydub semantic_kernel[realtime]
31+
e.g. pip install pyaudio sounddevice pydub semantic-kernel[realtime]
3332
3433
For more details of the exact setup, see the README.md in the realtime folder.
3534
"""
@@ -60,20 +59,21 @@ def goodbye():
6059

6160
async def main() -> None:
6261
print_transcript = True
63-
# create the Kernel and add a simple function for function calling.
62+
# create a Kernel and add a simple function for function calling.
6463
kernel = Kernel()
6564
kernel.add_functions(plugin_name="helpers", functions=[goodbye, get_weather, get_date_time])
6665

67-
# create the realtime client, in this the Azure Websocket client, there are also OpenAI Websocket and WebRTC clients
68-
# See 02b-chat_with_function_calling_webrtc.py for an example of the WebRTC client
69-
realtime_client = AzureRealtimeWebsocket()
66+
# create the realtime agent, in this using Azure OpenAI through Websockets,
67+
# there are also OpenAI Websocket and WebRTC clients
68+
# See realtime_agent_with_function_calling_webrtc.py for an example of the WebRTC client
69+
realtime_agent = AzureRealtimeWebsocket()
7070
# create the audio player and audio track
7171
# both take a device_id parameter, which is the index of the device to use, if None the default device is used
7272
audio_player = AudioPlayerWebsocket()
73-
audio_recorder = AudioRecorderWebsocket(realtime_client=realtime_client)
73+
audio_recorder = AudioRecorderWebsocket(realtime_client=realtime_agent)
7474

7575
# Create the settings for the session
76-
# The realtime api, does not use a system message, but takes instructions as a parameter for a session
76+
# The realtime api, does not use a system message, but, like agents, takes instructions as a parameter for a session
7777
# Another important setting is to tune the server_vad turn detection
7878
# if this is turned off (by setting turn_detection=None), you will have to send
7979
# the "input_audio_buffer.commit" and "response.create" event to the realtime api
@@ -102,20 +102,20 @@ async def main() -> None:
102102
"I can tell you what the weather is or the time."
103103
)
104104

105-
# the context manager calls the create_session method on the client and starts listening to the audio stream
105+
# the context manager calls the create_session method on the agent and starts listening to the audio stream
106106
async with (
107107
audio_player,
108108
audio_recorder,
109-
realtime_client(
109+
realtime_agent(
110110
settings=settings,
111111
chat_history=chat_history,
112112
kernel=kernel,
113113
create_response=True,
114114
),
115115
):
116-
# the audio_output_callback can be added here or in the client constructor
116+
# the audio_output_callback can be added here or in the constructor
117117
# using this gives the smoothest experience
118-
async for event in realtime_client.receive(audio_output_callback=audio_player.client_callback):
118+
async for event in realtime_agent.receive(audio_output_callback=audio_player.client_callback):
119119
match event:
120120
case RealtimeTextEvent():
121121
if print_transcript:
@@ -133,7 +133,7 @@ async def main() -> None:
133133

134134
if __name__ == "__main__":
135135
print(
136-
"Instructions: The model will start speaking immediately,"
136+
"Instructions: The agent will start speaking immediately,"
137137
"this can be turned off by removing `create_response=True` above."
138138
"The model will detect when you stop and automatically generate a response. "
139139
"Press ctrl + c to stop the program."

‎python/samples/concepts/realtime/simple_realtime_chat_webrtc.py

+6-7
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
- pyaudio
2525
- sounddevice
2626
- pydub
27-
e.g. pip install pyaudio sounddevice pydub semantic_kernel[realtime]
27+
e.g. pip install pyaudio sounddevice pydub semantic-kernel[realtime]
2828
2929
For more details of the exact setup, see the README.md in the realtime folder.
3030
"""
@@ -42,8 +42,6 @@ async def main() -> None:
4242
# create the realtime client and optionally add the audio output function, this is optional
4343
# you can define the protocol to use, either "websocket" or "webrtc"
4444
# they will behave the same way, even though the underlying protocol is quite different
45-
realtime_client = OpenAIRealtimeWebRTC(audio_track=AudioRecorderWebRTC())
46-
# Create the settings for the session
4745
settings = OpenAIRealtimeExecutionSettings(
4846
instructions="""
4947
You are a chat bot. Your name is Mosscap and
@@ -58,9 +56,11 @@ async def main() -> None:
5856
# for more details.
5957
voice="alloy",
6058
)
59+
realtime_client = OpenAIRealtimeWebRTC(audio_track=AudioRecorderWebRTC(), settings=settings)
60+
# Create the settings for the session
6161
audio_player = AudioPlayerWebRTC()
6262
# the context manager calls the create_session method on the client and starts listening to the audio stream
63-
async with audio_player, realtime_client(settings=settings, create_response=True):
63+
async with audio_player, realtime_client:
6464
async for event in realtime_client.receive(audio_output_callback=audio_player.client_callback):
6565
match event.event_type:
6666
case "text":
@@ -76,9 +76,8 @@ async def main() -> None:
7676

7777
if __name__ == "__main__":
7878
print(
79-
"Instructions: The model will start speaking immediately,"
80-
"this can be turned off by removing `create_response=True` above."
81-
"The model will detect when you stop and automatically generate a response. "
79+
"Instructions: start speaking. "
80+
"The model will detect when you stop and automatically start responding. "
8281
"Press ctrl + c to stop the program."
8382
)
8483
asyncio.run(main())

‎python/samples/concepts/realtime/simple_realtime_chat_websocket.py

+8-9
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
- pyaudio
2626
- sounddevice
2727
- pydub
28-
e.g. pip install pyaudio sounddevice pydub semantic_kernel[realtime]
28+
e.g. pip install pyaudio sounddevice pydub semantic-kernel[realtime]
2929
3030
For more details of the exact setup, see the README.md in the realtime folder.
3131
"""
@@ -43,10 +43,6 @@ async def main() -> None:
4343
# create the realtime client and optionally add the audio output function, this is optional
4444
# you can define the protocol to use, either "websocket" or "webrtc"
4545
# they will behave the same way, even though the underlying protocol is quite different
46-
realtime_client = AzureRealtimeWebsocket()
47-
audio_player = AudioPlayerWebsocket()
48-
audio_recorder = AudioRecorderWebsocket(realtime_client=realtime_client)
49-
# Create the settings for the session
5046
settings = AzureRealtimeExecutionSettings(
5147
instructions="""
5248
You are a chat bot. Your name is Mosscap and
@@ -61,8 +57,12 @@ async def main() -> None:
6157
# for more details.
6258
voice="shimmer",
6359
)
60+
realtime_client = AzureRealtimeWebsocket(settings=settings)
61+
audio_player = AudioPlayerWebsocket()
62+
audio_recorder = AudioRecorderWebsocket(realtime_client=realtime_client)
63+
# Create the settings for the session
6464
# the context manager calls the create_session method on the client and starts listening to the audio stream
65-
async with audio_player, audio_recorder, realtime_client(settings=settings, create_response=True):
65+
async with audio_player, audio_recorder, realtime_client:
6666
async for event in realtime_client.receive():
6767
match event:
6868
# this can be used as an alternative to the callback function used in other samples,
@@ -82,9 +82,8 @@ async def main() -> None:
8282

8383
if __name__ == "__main__":
8484
print(
85-
"Instructions: The model will start speaking immediately,"
86-
"this can be turned off by removing `create_response=True` above."
87-
"The model will detect when you stop and automatically generate a response. "
85+
"Instructions: Start speaking. "
86+
"The model will detect when you stop and automatically start responding. "
8887
"Press ctrl + c to stop the program."
8988
)
9089
asyncio.run(main())

‎python/samples/concepts/realtime/utils.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,7 @@
1616
from sounddevice import InputStream, OutputStream
1717

1818
from semantic_kernel.connectors.ai.realtime_client_base import RealtimeClientBase
19-
from semantic_kernel.contents import AudioContent
20-
from semantic_kernel.contents.realtime_events import RealtimeAudioEvent
19+
from semantic_kernel.contents import AudioContent, RealtimeAudioEvent
2120

2221
logger = logging.getLogger(__name__)
2322

‎python/samples/demos/call_automation/call_automation.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@
4646
from semantic_kernel.connectors.ai.open_ai import (
4747
AzureRealtimeExecutionSettings,
4848
AzureRealtimeWebsocket,
49-
ListenEvents,
5049
)
50+
from semantic_kernel.connectors.ai.open_ai.services._open_ai_realtime import ListenEvents
5151
from semantic_kernel.connectors.ai.realtime_client_base import RealtimeClientBase
5252
from semantic_kernel.contents import AudioContent, RealtimeAudioEvent
5353
from semantic_kernel.functions import kernel_function

‎python/semantic_kernel/connectors/ai/open_ai/__init__.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
from semantic_kernel.connectors.ai.open_ai.prompt_execution_settings.open_ai_text_to_image_execution_settings import (
3535
OpenAITextToImageExecutionSettings,
3636
)
37+
from semantic_kernel.connectors.ai.open_ai.services._open_ai_realtime import ListenEvents, SendEvents
3738
from semantic_kernel.connectors.ai.open_ai.services.azure_audio_to_text import AzureAudioToText
3839
from semantic_kernel.connectors.ai.open_ai.services.azure_chat_completion import AzureChatCompletion
3940
from semantic_kernel.connectors.ai.open_ai.services.azure_realtime import AzureRealtimeWebsocket
@@ -44,10 +45,8 @@
4445
from semantic_kernel.connectors.ai.open_ai.services.open_ai_audio_to_text import OpenAIAudioToText
4546
from semantic_kernel.connectors.ai.open_ai.services.open_ai_chat_completion import OpenAIChatCompletion
4647
from semantic_kernel.connectors.ai.open_ai.services.open_ai_realtime import (
47-
ListenEvents,
4848
OpenAIRealtimeWebRTC,
4949
OpenAIRealtimeWebsocket,
50-
SendEvents,
5150
)
5251
from semantic_kernel.connectors.ai.open_ai.services.open_ai_text_completion import OpenAITextCompletion
5352
from semantic_kernel.connectors.ai.open_ai.services.open_ai_text_embedding import OpenAITextEmbedding

‎python/semantic_kernel/connectors/ai/open_ai/services/_open_ai_realtime.py

+899
Large diffs are not rendered by default.

‎python/semantic_kernel/connectors/ai/open_ai/services/azure_realtime.py

+8-1
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@
1717
from semantic_kernel.connectors.ai.open_ai.prompt_execution_settings.open_ai_realtime_execution_settings import (
1818
AzureRealtimeExecutionSettings,
1919
)
20+
from semantic_kernel.connectors.ai.open_ai.services._open_ai_realtime import OpenAIRealtimeWebsocketBase
2021
from semantic_kernel.connectors.ai.open_ai.services.azure_config_base import AzureOpenAIConfigBase
2122
from semantic_kernel.connectors.ai.open_ai.services.open_ai_model_types import OpenAIModelTypes
22-
from semantic_kernel.connectors.ai.open_ai.services.open_ai_realtime import OpenAIRealtimeWebsocketBase
2323
from semantic_kernel.connectors.ai.open_ai.settings.azure_open_ai_settings import AzureOpenAISettings
2424
from semantic_kernel.connectors.ai.prompt_execution_settings import PromptExecutionSettings
2525
from semantic_kernel.exceptions.service_exceptions import ServiceInitializationError
@@ -79,6 +79,13 @@ def __init__(
7979
environment variables. (Optional)
8080
env_file_encoding: The encoding of the environment settings file. (Optional)
8181
kwargs: Additional arguments.
82+
kwargs: Additional arguments.
83+
This can include:
84+
kernel (Kernel): the kernel to use for function calls
85+
plugins (list[object] or dict[str, object]): the plugins to use for function calls
86+
settings (OpenAIRealtimeExecutionSettings): the settings to use for the session
87+
chat_history (ChatHistory): the chat history to use for the session
88+
Otherwise they can also be passed to the context manager.
8289
"""
8390
try:
8491
azure_openai_settings = AzureOpenAISettings.create(

‎python/semantic_kernel/connectors/ai/open_ai/services/open_ai_realtime.py

+27-858
Large diffs are not rendered by default.

‎python/semantic_kernel/connectors/ai/realtime_client_base.py

+8-2
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,14 @@
1111
from typing_extensions import Self # pragma: no cover
1212

1313
from numpy import ndarray
14-
from pydantic import PrivateAttr
14+
from pydantic import ConfigDict, PrivateAttr
1515

1616
from semantic_kernel.connectors.ai.function_call_choice_configuration import FunctionCallChoiceConfiguration
1717
from semantic_kernel.connectors.ai.function_choice_behavior import FunctionChoiceType
1818
from semantic_kernel.connectors.ai.prompt_execution_settings import PromptExecutionSettings
1919
from semantic_kernel.contents.chat_history import ChatHistory
2020
from semantic_kernel.contents.realtime_events import RealtimeEvents
21+
from semantic_kernel.kernel import Kernel
2122
from semantic_kernel.services.ai_service_client_base import AIServiceClientBase
2223
from semantic_kernel.utils.feature_stage_decorator import experimental
2324

@@ -26,10 +27,15 @@
2627
class RealtimeClientBase(AIServiceClientBase, ABC):
2728
"""Base class for a realtime client."""
2829

30+
model_config = ConfigDict(
31+
extra="allow", populate_by_name=True, arbitrary_types_allowed=True, validate_assignment=True
32+
)
33+
2934
SUPPORTS_FUNCTION_CALLING: ClassVar[bool] = False
3035
audio_output_callback: Callable[[ndarray], Coroutine[Any, Any, None]] | None = None
3136
_chat_history: ChatHistory | None = PrivateAttr(default=None)
3237
_settings: PromptExecutionSettings | None = PrivateAttr(default=None)
38+
_kernel: Kernel | None = PrivateAttr(default=None)
3339
_create_kwargs: dict[str, Any] | None = PrivateAttr(default=None)
3440

3541
@abstractmethod
@@ -136,7 +142,7 @@ def __call__(
136142
Args:
137143
chat_history: Chat history.
138144
settings: Prompt execution settings.
139-
kwargs: Additional arguments, can include `kernel` or specific settings for the service.
145+
kwargs: Additional arguments, can include `kernel` or `plugins` or specific settings for the service.
140146
Check the update_session method for the specific service for more details.
141147
"""
142148
self._chat_history = chat_history

‎python/semantic_kernel/services/ai_service_client_base.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Copyright (c) Microsoft. All rights reserved.
22

33
from abc import ABC
4-
from typing import TYPE_CHECKING, Annotated
4+
from typing import TYPE_CHECKING, Annotated, Any
55

66
from pydantic.types import StringConstraints
77

@@ -25,7 +25,7 @@ class AIServiceClientBase(KernelBaseModel, ABC):
2525
ai_model_id: Annotated[str, StringConstraints(strip_whitespace=True, min_length=1)]
2626
service_id: str = ""
2727

28-
def model_post_init(self, __context: object | None = None):
28+
def model_post_init(self, __context: Any):
2929
"""Update the service_id if it is not set."""
3030
if not self.service_id:
3131
self.service_id = self.ai_model_id

‎python/tests/unit/connectors/ai/open_ai/services/test_openai_realtime.py

+7-5
Original file line numberDiff line numberDiff line change
@@ -47,14 +47,16 @@
4747
from semantic_kernel.connectors.ai.open_ai.prompt_execution_settings.open_ai_realtime_execution_settings import (
4848
OpenAIRealtimeExecutionSettings,
4949
)
50-
from semantic_kernel.connectors.ai.open_ai.services.open_ai_realtime import (
50+
from semantic_kernel.connectors.ai.open_ai.services._open_ai_realtime import (
5151
ListenEvents,
52-
OpenAIRealtimeWebRTC,
53-
OpenAIRealtimeWebsocket,
5452
SendEvents,
5553
_create_openai_realtime_client_event,
5654
update_settings_from_function_call_configuration,
5755
)
56+
from semantic_kernel.connectors.ai.open_ai.services.open_ai_realtime import (
57+
OpenAIRealtimeWebRTC,
58+
OpenAIRealtimeWebsocket,
59+
)
5860
from semantic_kernel.connectors.ai.prompt_execution_settings import PromptExecutionSettings
5961
from semantic_kernel.contents.audio_content import AudioContent
6062
from semantic_kernel.contents.chat_history import ChatHistory
@@ -451,7 +453,7 @@ async def test_update_session(OpenAIWebsocket, kernel):
451453
# images are not supported, so ignored
452454
assert len(mock_send.await_args_list) == 6
453455
assert OpenAIWebsocket._current_settings == settings
454-
assert OpenAIWebsocket.kernel == kernel
456+
assert OpenAIWebsocket._kernel == kernel
455457

456458

457459
async def test_parse_function_call_arguments_done(OpenAIWebsocket, kernel):
@@ -473,7 +475,7 @@ async def test_parse_function_call_arguments_done(OpenAIWebsocket, kernel):
473475
OpenAIWebsocket._call_id_to_function_map["call_id"] = "plugin_name-function_name"
474476
func = kernel_function(name="function_name", description="function_description")(lambda x: x)
475477
kernel.add_function(plugin_name="plugin_name", function_name="function_name", function=func)
476-
OpenAIWebsocket.kernel = kernel
478+
OpenAIWebsocket._kernel = kernel
477479
iter = 0
478480
with patch.object(OpenAIWebsocket, "_send") as mock_send:
479481
async for event in OpenAIWebsocket._parse_function_call_arguments_done(event):

0 commit comments

Comments
 (0)
Please sign in to comment.