diff --git a/studio/backend/core/inference/providers.py b/studio/backend/core/inference/providers.py index 7ff800e7e9..9ec1db3e6d 100644 --- a/studio/backend/core/inference/providers.py +++ b/studio/backend/core/inference/providers.py @@ -75,11 +75,15 @@ PROVIDER_REGISTRY: dict[str, dict[str, Any]] = { r"transcribe|translate|instruct|sora)\b" # OpenAI realtime/audio variants that don't support chat # streaming. Studio always sends `stream: true`, and OpenAI - # marks `gpt-realtime*` and `gpt-audio-mini` as Streaming: - # Not supported (Realtime API only); surfacing them in the - # picker would 4xx at request time. `gpt-audio` and - # `gpt-4o-realtime-preview` still stream and are kept. + # marks the full Realtime family as Streaming: Not supported + # (Realtime API only, WebRTC/WebSocket transport): `gpt-realtime`, + # `gpt-realtime-mini`, `gpt-4o-realtime-preview*` and + # `gpt-4o-mini-realtime-preview*`, plus `gpt-audio-mini`. + # Selecting them from the picker would 4xx at request time. + # `gpt-audio` and `gpt-4o-audio-preview` are kept -- they + # stream over Chat Completions / Responses. r"|^gpt-realtime(?:$|-)" + r"|^gpt-4o(?:-mini)?-realtime\b" r"|^gpt-audio-mini\b" # Legacy completion bases -- ^-anchored to avoid false # positives on hypothetical future chat ids containing diff --git a/studio/backend/tests/test_provider_registry_filters.py b/studio/backend/tests/test_provider_registry_filters.py index 3aa9b23b2e..e061fffac9 100644 --- a/studio/backend/tests/test_provider_registry_filters.py +++ b/studio/backend/tests/test_provider_registry_filters.py @@ -77,23 +77,28 @@ def test_openai_keeps_every_known_chat_family(): def test_openai_audio_and_realtime_families_split_on_streaming_support(): # Pin the chat/non-chat split: Studio always sends `stream: true`, - # so the picker keeps gpt-audio* (chat streams over /v1/chat/ - # completions) and gpt-4o-realtime-preview (chat streams via the - # /v1/responses adapter), but drops the new gpt-realtime* family - # and gpt-audio-mini, which OpenAI's model cards mark Streaming: - # Not supported (Realtime API / WebSocket only). + # so the picker keeps the audio chat families (gpt-audio* without + # -mini, plus gpt-4o-audio-preview*) which stream over + # /v1/chat/completions and /v1/responses, but drops the entire + # Realtime family (gpt-realtime*, gpt-4o-realtime-preview*, + # gpt-4o-mini-realtime-preview*) and gpt-audio-mini, which OpenAI's + # model cards mark Streaming: Not supported (Realtime API only, + # WebRTC/WebSocket transport). kept = _apply( "openai", [ "gpt-audio", "gpt-audio-1.5", - "gpt-4o-realtime-preview", + "gpt-4o-audio-preview", + "gpt-4o-audio-preview-2024-12-17", ], ) assert kept == [ "gpt-audio", "gpt-audio-1.5", - "gpt-4o-realtime-preview", + "gpt-4o-audio-preview", + # Dated audio-preview snapshot is dropped by the date-suffix rule; + # the canonical id above survives. ], kept dropped = _apply( @@ -104,6 +109,8 @@ def test_openai_audio_and_realtime_families_split_on_streaming_support(): "gpt-realtime-mini", "gpt-realtime-1.5", "gpt-realtime-2", + "gpt-4o-realtime-preview", + "gpt-4o-mini-realtime-preview", "gpt-4o-transcribe", "gpt-4o-mini-transcribe", ], @@ -114,9 +121,9 @@ def test_openai_audio_and_realtime_families_split_on_streaming_support(): def test_openai_drops_non_chat_ids(): noise = [ # Embeddings / TTS / image / moderation / whisper / etc. - # gpt-audio (no -mini) and gpt-4o-realtime-preview are - # intentionally OMITTED from this list -- they DO stream chat. - # See test_openai_audio_and_realtime_families_split_on_streaming_support. + # gpt-audio (no -mini) and gpt-4o-audio-preview are intentionally + # OMITTED from this list -- they DO stream chat. See + # test_openai_audio_and_realtime_families_split_on_streaming_support. "text-embedding-3-small", "text-embedding-3-large", "text-embedding-ada-002", @@ -166,8 +173,9 @@ def test_openai_realtime_translate_variants_are_dropped_but_parent_chat_family_s """gpt-audio is chat-capable (streams over /v1/chat/completions) and stays, but the audio-translation variants share the chat picker's transport and would 4xx, so they must be filtered. The - new gpt-realtime* family and gpt-audio-mini are Realtime-only and - are dropped by a sibling assertion.""" + full Realtime family (gpt-realtime*, gpt-4o*-realtime-preview*) + plus gpt-audio-mini are Realtime-only and dropped by a sibling + assertion.""" kept = _apply("openai", ["gpt-audio"]) assert kept == ["gpt-audio"], kept