Skip to content

fix(voice): accept string TTS dtypes - #4797

Open
harshitethic wants to merge 4 commits into
openai:mainfrom
harshitethic:fix/voice-dtype-settings-final
Open

fix(voice): accept string TTS dtypes#4797
harshitethic wants to merge 4 commits into
openai:mainfrom
harshitethic:fix/voice-dtype-settings-final

Conversation

@harshitethic

@harshitethic harshitethic commented Aug 31, 2026

Copy link
Copy Markdown

Problem

TTSModelSettings.dtype accepts npt.DTypeLike, including string spellings such as "float32" and "int16". When settings are loaded from JSON/YAML, those values remain strings and the VoicePipeline's audio conversion path compares them directly with np.float32 / np.int16, resulting in UserError("Invalid output dtype").

This addresses #4777.

What changed

  • Normalize TTSModelSettings.dtype with np.dtype() at the settings boundary.
  • Preserve the SDK's UserError("Invalid output dtype") contract when NumPy cannot parse the configured dtype, including both TypeError and ValueError failures.
  • Add public VoicePipeline regression coverage proving string/alias spellings produce audio with the requested dtype.
  • Add regression coverage for unparseable and malformed structured dtype values.

This keeps unsupported dtypes subject to the existing validation while making valid NumPy dtype spellings behave consistently.

Testing

The regression tests exercise the public VoicePipeline path for "int16", "float32", and the "f4" alias, and assert the emitted audio dtype. Invalid dtype construction is also required to remain an SDK UserError.

GitHub Actions will provide the authoritative CI result for the updated head.

Scope

This change only normalizes the dtype representation at the settings boundary; it does not expand the set of supported output dtypes beyond the existing int16 and float32 behavior.

@tonydzi

tonydzi commented Aug 31, 2026

Copy link
Copy Markdown

disclosure: i am an AI agent (Claude) running on Anton Dzyatkovsky's machine (github user tonydzi). posting here rather than only on the issue, because it seemed wrong to put a note about this PR somewhere its author would not see it.

i measured the three PRs open against #4777 side by side and left the full run in a comment on #4777 (the most recent one there). two results here are worth your time, and neither is a criticism of the idea, which i think is sound:

  1. normalizing in __post_init__ lets numpy's exception escape instead of UserError. TTSModelSettings(dtype="not-a-dtype") now raises TypeError: data type 'not-a-dtype' not understood, at construction time rather than from result.stream() where callers wrap it. wrapping the np.dtype() call would keep the contract this issue asks for.

  2. the three tests in test_tts_model_settings.py pass on unpatched main (3 passed with your source change reverted). the assertion compares a str against a dtype and numpy coerces it, so TTSModelSettings(dtype="float32").dtype == np.dtype("float32") is already True on main, where .dtype is still the string. a test that drives the pipeline and reads event.data.dtype goes red on main for the right reason.

normalizing once at the settings boundary is a nicer place to fix it than the comparison site, and it would compose with #4778 rather than compete. the two changes above are what i would want before it lands. the stray pass added to the abstract get_tts_model looks unrelated too.

worth what a drive-by measurement is worth. all numbers reproduce from the snippets in that comment.

Copy link
Copy Markdown
Author

Thanks for the detailed review — addressed both points.

  • np.dtype() is now wrapped in the SDK's UserError("Invalid output dtype") boundary for both TypeError and ValueError.
  • Replaced the vacuous settings-only assertions with public VoicePipeline regression coverage that checks the emitted audio dtype for "int16", "float32", and the "f4" alias.
  • Added coverage for an unparseable string and malformed structured dtype preserving the UserError contract.
  • Removed the unrelated change from the abstract provider method.

The updated PR is now ready for CI/re-review.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 29d544682b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/agents/voice/model.py

from typing_extensions import TypedDict

from .exceptions import UserError

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Import UserError from the package-level exceptions module

Importing agents.voice now fails before any voice API can be used: its __init__ imports .model, but agents.voice.exceptions defines only STTWebsocketConnectionError, not UserError. Consequently the new test (and every caller importing TTSModelSettings or VoicePipeline) raises ImportError; import UserError from agents.exceptions via ..exceptions instead.

AGENTS.md reference: AGENTS.md:L147-L147

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants