Skip to content

Commit c334c85

Browse files
xitzhangXiting Zhangscbedd
authored
[VoiceLive] Fix issue in function calling API (#42910)
* Fix issues in function calling * update changelog * update api docs for ResponseResource.create * update Keyword-only separator for azure.ai.voicelive.ResponseResource.create * update change log * update * update version * update label * fix too long line pylint error * update toml * ensure that we clean up after each venv runs --------- Co-authored-by: Xiting Zhang <[email protected]> Co-authored-by: Scott Beddall <[email protected]>
1 parent 9b29ba1 commit c334c85

File tree

8 files changed

+111
-64
lines changed

8 files changed

+111
-64
lines changed

.github/CODEOWNERS

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -259,8 +259,8 @@
259259
# ServiceLabel: %AI Projects %Service Attention
260260
/sdk/ai/azure-ai-projects/ @dargilco @jhakulin @trangevi @glharper @nick863 @howieleung
261261

262-
# PRLabel: %AI Voice Live
263-
# ServiceLabel: %AI Voice Live %Service Attention
262+
# PRLabel: %Voice Live
263+
# ServiceLabel: %Voice Live %Service Attention
264264
/sdk/ai/azure-ai-voicelive/ @rhurey @xitzhang
265265

266266

sdk/ai/azure-ai-voicelive/CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
# Release History
22

3+
## 1.0.0b2 (Unreleased)
4+
5+
### Features Added
6+
7+
- Async function call
8+
9+
### Bugs Fixed
10+
- Fixed function calling: ensure `FunctionCallOutputItem.output` is properly serialized as a JSON string before sending to the service.
11+
312
## 1.0.0b1 (2025-08-28)
413

514
### Features Added

sdk/ai/azure-ai-voicelive/apiview-properties.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,8 @@
9191
"azure.ai.voicelive.models.ServerEventResponseContentPartDone": "VoiceLive.ServerEventResponseContentPartDone",
9292
"azure.ai.voicelive.models.ServerEventResponseCreated": "VoiceLive.ServerEventResponseCreated",
9393
"azure.ai.voicelive.models.ServerEventResponseDone": "VoiceLive.ServerEventResponseDone",
94+
"azure.ai.voicelive.models.ServerEventResponseFunctionCallArgumentsDelta": "VoiceLive.ServerEventResponseFunctionCallArgumentsDelta",
95+
"azure.ai.voicelive.models.ServerEventResponseFunctionCallArgumentsDone": "VoiceLive.ServerEventResponseFunctionCallArgumentsDone",
9496
"azure.ai.voicelive.models.ServerEventResponseOutputItemAdded": "VoiceLive.ServerEventResponseOutputItemAdded",
9597
"azure.ai.voicelive.models.ServerEventResponseOutputItemDone": "VoiceLive.ServerEventResponseOutputItemDone",
9698
"azure.ai.voicelive.models.ServerEventResponseTextDelta": "VoiceLive.ServerEventResponseTextDelta",

sdk/ai/azure-ai-voicelive/azure/ai/voicelive/_patch.py

Lines changed: 38 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
ClientEventResponseCancel,
3232
ClientEventResponseCreate,
3333
ClientEventSessionUpdate,
34+
ConversationRequestItem,
35+
ResponseCreateParams,
3436
)
3537
from azure.core.credentials import AzureKeyCredential, TokenCredential
3638
from azure.core.exceptions import AzureError
@@ -198,21 +200,33 @@ def __init__(self, connection: "VoiceLiveConnection") -> None:
198200
"""
199201
self._connection = connection
200202

201-
def create(self, *, response: Optional[Mapping[str, Any]] = None, event_id: Optional[str] = None) -> None:
202-
"""Create a new response.
203+
def create(
204+
self,
205+
*,
206+
response: Optional[Union[ResponseCreateParams, Mapping[str, Any]]] = None,
207+
event_id: Optional[str] = None,
208+
additional_instructions: Optional[str] = None,
209+
) -> None:
210+
"""
211+
Create a new response.
203212
204-
:keyword response: Optional mapping of response parameters to send.
205-
:keyword type response: Mapping[str, Any] or None
213+
:keyword response: Optional response parameters to send.
214+
:keyword type response: ~azure.ai.voicelive.models.ResponseCreateParams or Mapping[str, Any] or None
206215
:keyword event_id: Optional ID for the event.
207216
:keyword type event_id: str or None
208-
:return: None
217+
:keyword additional_instructions: Extra system prompt appended to the session's default, for this response only.
218+
:keyword type additional_instructions: str or None
209219
:rtype: None
210220
"""
211-
event = ClientEventResponseCreate()
212-
if response:
213-
event["response"] = dict(response)
214-
if event_id:
215-
event["event_id"] = event_id
221+
if response is not None and not isinstance(response, ResponseCreateParams):
222+
response = ResponseCreateParams(**dict(response))
223+
224+
# Use constructor kwargs (typed) instead of item-assignment
225+
event = ClientEventResponseCreate(
226+
event_id=event_id,
227+
response=response,
228+
additional_instructions=additional_instructions,
229+
)
216230
self._connection.send(event)
217231

218232
def cancel(self, *, response_id: Optional[str] = None, event_id: Optional[str] = None) -> None:
@@ -323,24 +337,31 @@ def __init__(self, connection: "VoiceLiveConnection") -> None:
323337
self._connection = connection
324338

325339
def create(
326-
self, *, item: Mapping[str, Any], previous_item_id: Optional[str] = None, event_id: Optional[str] = None
340+
self,
341+
*,
342+
item: Mapping[str, Any],
343+
previous_item_id: Optional[str] = None,
344+
event_id: Optional[str] = None
327345
) -> None:
328346
"""Create a new conversation item.
329347
330348
:keyword item: The item to create (message, function call, etc.).
331-
:keyword type item: Mapping[str, Any]
349+
:keyword ConversationRequestItem | Mapping[str, Any] item: The item to create (message/functions/etc.).
332350
:keyword previous_item_id: Insert after this item, if provided.
333351
:keyword type previous_item_id: str or None
334352
:keyword event_id: Optional ID for the event.
335353
:keyword type event_id: str or None
336354
:return: None
337355
:rtype: None
338356
"""
339-
event = ClientEventConversationItemCreate({"item": dict(item)})
340-
if previous_item_id:
341-
event["previous_item_id"] = previous_item_id
342-
if event_id:
343-
event["event_id"] = event_id
357+
if not isinstance(item, ConversationRequestItem):
358+
item = ConversationRequestItem(**dict(item))
359+
360+
event = ClientEventConversationItemCreate(
361+
event_id=event_id,
362+
previous_item_id=previous_item_id,
363+
item=item,
364+
)
344365
self._connection.send(event)
345366

346367
def delete(self, *, item_id: str, event_id: Optional[str] = None) -> None:

sdk/ai/azure-ai-voicelive/azure/ai/voicelive/_version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@
66
# Changes may cause incorrect behavior and will be lost if the code is regenerated.
77
# --------------------------------------------------------------------------
88

9-
VERSION = "1.0.0b1"
9+
VERSION = "1.0.0b2"

sdk/ai/azure-ai-voicelive/azure/ai/voicelive/aio/_patch.py

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333
ClientEventResponseCancel,
3434
ClientEventResponseCreate,
3535
ClientEventSessionUpdate,
36+
ConversationRequestItem,
37+
ResponseCreateParams,
3638
)
3739
from azure.core.credentials import AzureKeyCredential, TokenCredential
3840
from azure.core.pipeline import policies
@@ -127,21 +129,34 @@ def __init__(self, connection: "VoiceLiveConnection") -> None:
127129
"""
128130
self._connection = connection
129131

130-
async def create(self, *, response: Optional[Mapping[str, Any]] = None, event_id: Optional[str] = None) -> None:
132+
async def create(
133+
self,
134+
*,
135+
response: Optional[Union[ResponseCreateParams, Mapping[str, Any]]] = None,
136+
event_id: Optional[str] = None,
137+
additional_instructions: Optional[str] = None,
138+
) -> None:
131139
"""Create a response from the model.
132140
133141
This event instructs the server to create a Response (triggering model inference).
134142
When in Server VAD mode, the server may create responses automatically.
135143
136-
:keyword Mapping[str, Any] response: Optional response configuration.
137-
:keyword str event_id: Optional ID for the event.
144+
:keyword response: Optional response configuration to send.
145+
:keyword type response: ~azure.ai.voicelive.models.ResponseCreateParams or Mapping[str, Any] or None
146+
:keyword event_id: Optional ID for the event.
147+
:keyword type event_id: str or None
148+
:keyword additional_instructions: Extra system prompt appended to the session's default, for this response only.
149+
:keyword type additional_instructions: str or None
138150
:rtype: None
139151
"""
140-
event = ClientEventResponseCreate()
141-
if response is not None:
142-
event["response"] = dict(response)
143-
if event_id:
144-
event["event_id"] = event_id
152+
if response is not None and not isinstance(response, ResponseCreateParams):
153+
response = ResponseCreateParams(**dict(response))
154+
155+
event = ClientEventResponseCreate(
156+
event_id=event_id,
157+
response=response,
158+
additional_instructions=additional_instructions,
159+
)
145160

146161
await self._connection.send(event)
147162

@@ -247,20 +262,27 @@ def __init__(self, connection: "VoiceLiveConnection") -> None:
247262
self._connection = connection
248263

249264
async def create(
250-
self, *, item: Mapping[str, Any], previous_item_id: Optional[str] = None, event_id: Optional[str] = None
265+
self,
266+
*,
267+
item: Union[ConversationRequestItem, Mapping[str, Any]],
268+
previous_item_id: Optional[str] = None,
269+
event_id: Optional[str] = None
251270
) -> None:
252271
"""Create a new conversation item.
253272
254-
:keyword Mapping[str, Any] item: The item to create (message/functions/etc.).
273+
:keyword ConversationRequestItem | Mapping[str, Any] item: The item to create (message/functions/etc.).
255274
:keyword str previous_item_id: Optional ID of the item after which to insert this item.
256275
:keyword str event_id: Optional ID for the event.
257276
:rtype: None
258277
"""
259-
event = ClientEventConversationItemCreate({"item": dict(item)})
260-
if previous_item_id:
261-
event["previous_item_id"] = previous_item_id
262-
if event_id:
263-
event["event_id"] = event_id
278+
if not isinstance(item, ConversationRequestItem):
279+
item = ConversationRequestItem(**dict(item))
280+
281+
event = ClientEventConversationItemCreate(
282+
event_id=event_id,
283+
previous_item_id=previous_item_id,
284+
item=item,
285+
)
264286
await self._connection.send(event)
265287

266288
async def delete(self, *, item_id: str, event_id: Optional[str] = None) -> None:

sdk/ai/azure-ai-voicelive/azure/ai/voicelive/models/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@
9595
ServerEventResponseContentPartDone,
9696
ServerEventResponseCreated,
9797
ServerEventResponseDone,
98+
ServerEventResponseFunctionCallArgumentsDelta,
99+
ServerEventResponseFunctionCallArgumentsDone,
98100
ServerEventResponseOutputItemAdded,
99101
ServerEventResponseOutputItemDone,
100102
ServerEventResponseTextDelta,
@@ -225,6 +227,8 @@
225227
"ServerEventResponseContentPartDone",
226228
"ServerEventResponseCreated",
227229
"ServerEventResponseDone",
230+
"ServerEventResponseFunctionCallArgumentsDelta",
231+
"ServerEventResponseFunctionCallArgumentsDone",
228232
"ServerEventResponseOutputItemAdded",
229233
"ServerEventResponseOutputItemDone",
230234
"ServerEventResponseTextDelta",

sdk/ai/azure-ai-voicelive/pyproject.toml

Lines changed: 18 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,34 @@
1-
# --------------------------------------------------------------------------
2-
# Copyright (c) Microsoft Corporation.
3-
# Licensed under the MIT License.
4-
# Code generated by Microsoft (R) Python Code Generator.
5-
# Changes may cause incorrect behavior and will be lost if the code is regenerated.
6-
# --------------------------------------------------------------------------
7-
81
[build-system]
92
requires = ["setuptools>=77.0.3", "wheel"]
103
build-backend = "setuptools.build_meta"
114

125
[project]
136
name = "azure-ai-voicelive"
14-
authors = [
15-
{ name = "Microsoft Corporation", email = "[email protected]" },
16-
]
17-
description = "Microsoft Corporation Azure Ai Voicelive Client Library for Python"
7+
authors = [{ name = "Microsoft Corporation", email = "[email protected]" }]
8+
description = "Microsoft Corporation Azure AI VoiceLive Client Library for Python"
189
license = "MIT"
1910
classifiers = [
20-
"Development Status :: 4 - Beta",
21-
"Programming Language :: Python",
22-
"Programming Language :: Python :: 3 :: Only",
23-
"Programming Language :: Python :: 3",
24-
"Programming Language :: Python :: 3.9",
25-
"Programming Language :: Python :: 3.10",
26-
"Programming Language :: Python :: 3.11",
27-
"Programming Language :: Python :: 3.12",
28-
"Programming Language :: Python :: 3.13",
11+
"Development Status :: 4 - Beta",
12+
"Programming Language :: Python",
13+
"Programming Language :: Python :: 3 :: Only",
14+
"Programming Language :: Python :: 3",
15+
"Programming Language :: Python :: 3.9",
16+
"Programming Language :: Python :: 3.10",
17+
"Programming Language :: Python :: 3.11",
18+
"Programming Language :: Python :: 3.12",
19+
"Programming Language :: Python :: 3.13",
2920
]
3021
requires-python = ">=3.9"
31-
keywords = ["azure", "azure sdk"]
22+
keywords = ["azure", "azure sdk", "voice", "voicelive", "realtime", "websocket", "audio"]
3223

3324
dependencies = [
34-
"isodate>=0.6.1",
35-
"azure-core>=1.35.0",
36-
"typing-extensions>=4.6.0",
37-
]
38-
dynamic = [
39-
"version", "readme"
25+
"isodate>=0.6.1",
26+
"azure-core>=1.35.1", # bump if you rely on 1.35.1
27+
"typing-extensions>=4.6.0; python_version < '3.11'",
4028
]
4129

30+
dynamic = ["version", "readme"]
31+
4232
[project.optional-dependencies]
4333
aiohttp = ["aiohttp>=3.9.0,<4.0.0"]
4434
websockets = ["websockets>=12.0,<14.0"]
@@ -57,15 +47,14 @@ test = [
5747
"azure-identity",
5848
"soundfile",
5949
"pyaudio; platform_python_implementation == 'CPython' and python_version < '3.13'",
60-
# add "isodate" here only if you need a different test pin than runtime
6150
]
6251

6352
[project.urls]
6453
Repository = "https://github.com/Azure/azure-sdk-for-python"
6554

6655
[tool.setuptools.dynamic]
6756
version = { attr = "azure.ai.voicelive._version.VERSION" }
68-
readme = {file = ["README.md", "CHANGELOG.md"], content-type = "text/markdown"}
57+
readme = { file = ["README.md", "CHANGELOG.md"], content-type = "text/markdown" }
6958

7059
[tool.setuptools.packages.find]
7160
include = ["azure.ai.voicelive", "azure.ai.voicelive.*"]

0 commit comments

Comments
 (0)