-
Notifications
You must be signed in to change notification settings - Fork 3.2k
[VoiceLive]Add NoTurnDetection to disable turn detection #44610
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
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR adds the NoTurnDetection feature to allow manual turn-taking control in VoiceLive conversations, along with significant improvements to serialization safety and model handling.
Changes:
- Added
NoTurnDetectionclass andTurnDetectionType.NONEenum to support client-managed conversation flow without automatic turn detection - Replaced unsafe
eval()usage with explicit type checking in serialization/deserialization for improved security - Enhanced model serialization with support for delimited string arrays (pipe, space, comma, newline formats)
- Fixed mutable type deserialization to properly track changes in model objects
- Updated package to beta status with updated azure-core dependency
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| sdk/ai/azure-ai-voicelive/azure/ai/voicelive/models/_models.py | Added NoTurnDetection class and updated TurnDetection base class documentation to include the new subclass |
| sdk/ai/azure-ai-voicelive/azure/ai/voicelive/models/_enums.py | Added TurnDetectionType.NONE enum value for no turn detection mode |
| sdk/ai/azure-ai-voicelive/azure/ai/voicelive/models/init.py | Exported NoTurnDetection class in public API |
| sdk/ai/azure-ai-voicelive/tests/test_live_realtime_service.py | Updated test to use NoTurnDetection() instead of dictionary-based turn detection configuration |
| sdk/ai/azure-ai-voicelive/samples/async_mcp_sample.py | Code formatting improvements (whitespace, line breaks) |
| sdk/ai/azure-ai-voicelive/pyproject.toml | Updated development status to Beta and increased azure-core minimum version to 1.36.0 |
| sdk/ai/azure-ai-voicelive/azure/ai/voicelive/_version.py | Updated version to 1.2.0b3 |
| sdk/ai/azure-ai-voicelive/azure/ai/voicelive/_utils/serialization.py | Replaced eval() with explicit type checking for security and added error handling |
| sdk/ai/azure-ai-voicelive/azure/ai/voicelive/_utils/model_base.py | Added array encoding support and improved mutable type deserialization caching |
| sdk/ai/azure-ai-voicelive/apiview-properties.json | Added NoTurnDetection to API view mappings |
| sdk/ai/azure-ai-voicelive/CHANGELOG.md | Updated changelog for 1.2.0b3 release with feature descriptions and bug fixes |
| _ARRAY_ENCODE_MAPPING = { | ||
| "pipeDelimited": "|", | ||
| "spaceDelimited": " ", | ||
| "commaDelimited": ",", | ||
| "newlineDelimited": "\n", | ||
| } | ||
|
|
||
|
|
||
| def _deserialize_array_encoded(delimit: str, attr): | ||
| if isinstance(attr, str): | ||
| if attr == "": | ||
| return [] | ||
| return attr.split(delimit) | ||
| return attr | ||
|
|
Copilot
AI
Jan 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new array encoding/decoding functionality (lines 174-188, 330-334, 532-534, 819-829) lacks test coverage. Since the repository has comprehensive test coverage for serialization (test_unit_serialization.py), tests should be added for the new delimited array formats (pipe, space, comma, newline) to ensure proper encoding and decoding.
| def __getitem__(self, key: str) -> typing.Any: | ||
| # If this key has been deserialized (for mutable types), we need to handle serialization | ||
| if hasattr(self, "_attr_to_rest_field"): | ||
| cache_attr = f"_deserialized_{key}" | ||
| if hasattr(self, cache_attr): | ||
| rf = _get_rest_field(getattr(self, "_attr_to_rest_field"), key) | ||
| if rf: | ||
| value = self._data.get(key) | ||
| if isinstance(value, (dict, list, set)): | ||
| # For mutable types, serialize and return | ||
| # But also update _data with serialized form and clear flag | ||
| # so mutations via this returned value affect _data | ||
| serialized = _serialize(value, rf._format) | ||
| # If serialized form is same type (no transformation needed), | ||
| # return _data directly so mutations work | ||
| if isinstance(serialized, type(value)) and serialized == value: | ||
| return self._data.get(key) | ||
| # Otherwise return serialized copy and clear flag | ||
| try: | ||
| object.__delattr__(self, cache_attr) | ||
| except AttributeError: | ||
| pass | ||
| # Store serialized form back | ||
| self._data[key] = serialized | ||
| return serialized | ||
| return self._data.__getitem__(key) | ||
|
|
||
| def __setitem__(self, key: str, value: typing.Any) -> None: | ||
| # Clear any cached deserialized value when setting through dictionary access | ||
| cache_attr = f"_deserialized_{key}" | ||
| try: | ||
| object.__delattr__(self, cache_attr) | ||
| except AttributeError: | ||
| pass | ||
| self._data.__setitem__(key, value) |
Copilot
AI
Jan 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new mutable type deserialization caching mechanism (lines 372-406, 1073-1106) lacks test coverage. Since the repository has comprehensive test coverage for deserialization functionality, tests should be added to verify that mutations to deserialized mutable types (dict, list, set) are properly tracked and reflected in the model's _data.
| if data_type == "int": | ||
| return int(data) | ||
| if data_type == "float": | ||
| return float(data) | ||
| if data_type == "bool": | ||
| return bool(data) | ||
| raise TypeError("Unknown basic data type: {}".format(data_type)) |
Copilot
AI
Jan 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The replacement of eval() with explicit type checking (lines 831-837) lacks test coverage for the new error path. Since the repository has comprehensive test coverage for serialization, add tests to verify that calling serialize_basic with unsupported data types (not str, int, float, bool) raises a TypeError with an appropriate error message.
| if data_type == "int": | ||
| return int(attr) | ||
| if data_type == "float": | ||
| return float(attr) | ||
| raise TypeError("Unknown basic data type: {}".format(data_type)) |
Copilot
AI
Jan 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The replacement of eval() with explicit type checking (lines 1793-1797) lacks test coverage for the new error path. Since the repository has comprehensive test coverage for deserialization, add tests to verify that calling deserialize_basic with unsupported data types (not str, int, float, bool) raises a TypeError with an appropriate error message.
| ): | ||
| # encoded string may be deserialized to sequence | ||
| return deserializer(obj) | ||
| except: # pylint: disable=bare-except |
Copilot
AI
Jan 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bare except clause catches all exceptions without discrimination, which can hide unexpected errors and make debugging difficult. Replace with specific exception types (e.g., AttributeError, TypeError) that might be raised when checking the deserializer structure.
| except: # pylint: disable=bare-except | |
| except (AttributeError, TypeError, IndexError): |
| """No turn detection - client manages turn taking. | ||
| :ivar type: Required. | ||
| :vartype type: str or ~azure.ai.voicelive.models.NONE |
Copilot
AI
Jan 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The documentation reference uses "~azure.ai.voicelive.models.NONE" which appears to be incorrect. It should reference the TurnDetectionType.NONE enum value properly, similar to how other models reference their types (e.g., using "str or ~azure.ai.voicelive.models.TurnDetectionType").
| :vartype type: str or ~azure.ai.voicelive.models.NONE | |
| :vartype type: str or ~azure.ai.voicelive.models.TurnDetectionType |
API Change CheckAPIView identified API level changes in this PR and created the following API reviews |
Description
Please add an informative description that covers that changes made by the pull request and link all relevant issues.
If an SDK is being regenerated based on a new API spec, a link to the pull request containing these API spec changes should be included above.
All SDK Contribution checklist:
General Guidelines and Best Practices
Testing Guidelines