diff --git a/sdk/openai/azure-openai/dev_requirements.txt b/sdk/openai/azure-openai/dev_requirements.txt index 751756413f6f..25d2474114e8 100644 --- a/sdk/openai/azure-openai/dev_requirements.txt +++ b/sdk/openai/azure-openai/dev_requirements.txt @@ -1,6 +1,6 @@ -e ../../../tools/azure-sdk-tools ../../identity/azure-identity aiohttp -openai +openai[realtime] pillow pydantic diff --git a/sdk/openai/azure-openai/tests/conftest.py b/sdk/openai/azure-openai/tests/conftest.py index a18032030738..4266744a5eee 100644 --- a/sdk/openai/azure-openai/tests/conftest.py +++ b/sdk/openai/azure-openai/tests/conftest.py @@ -21,7 +21,7 @@ # for pytest.parametrize GA = "2024-10-21" -PREVIEW = "2024-11-01-preview" +PREVIEW = "2024-10-01-preview" LATEST = PREVIEW AZURE = "azure" @@ -40,6 +40,7 @@ ENV_AZURE_OPENAI_KEY = "AZURE_OPENAI_KEY" ENV_AZURE_OPENAI_NORTHCENTRALUS_ENDPOINT = "AZURE_OPENAI_NORTHCENTRALUS_ENDPOINT" ENV_AZURE_OPENAI_SWEDENCENTRAL_ENDPOINT = "AZURE_OPENAI_SWEDENCENTRAL_ENDPOINT" +ENV_AZURE_OPENAI_SWEDENCENTRAL_KEY = "AZURE_OPENAI_SWEDENCENTRAL_KEY" ENV_AZURE_OPENAI_SEARCH_ENDPOINT = "AZURE_OPENAI_SEARCH_ENDPOINT" ENV_AZURE_OPENAI_SEARCH_INDEX = "AZURE_OPENAI_SEARCH_INDEX" @@ -178,6 +179,11 @@ def build_kwargs(args, api_type): return {"model": ENV_AZURE_OPENAI_CHAT_COMPLETIONS_GPT4_NAME} elif api_type == "gpt_4_openai": return {"model": ENV_OPENAI_CHAT_COMPLETIONS_GPT4_MODEL} + if test_feature.startswith("test_realtime"): + if api_type in ["gpt_4_azure"]: + return {"model": "gpt-4o-realtime-preview-1001"} + elif api_type == "gpt_4_openai": + return {"model": "gpt-4o-realtime-preview-2024-10-01"} if test_feature.startswith(("test_module_client", "test_cli")): return {} raise ValueError(f"Test feature: {test_feature} needs to have its kwargs configured.") diff --git a/sdk/openai/azure-openai/tests/test_realtime.py b/sdk/openai/azure-openai/tests/test_realtime.py new file mode 100644 index 000000000000..cbc0c65fab65 --- /dev/null +++ b/sdk/openai/azure-openai/tests/test_realtime.py @@ -0,0 +1,109 @@ +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ + +import os +import pytest +import openai +from devtools_testutils import AzureRecordedTestCase, get_credential +from conftest import ( + ENV_AZURE_OPENAI_SWEDENCENTRAL_ENDPOINT, + ENV_AZURE_OPENAI_SWEDENCENTRAL_KEY, + GPT_4_AZURE, + GPT_4_OPENAI, + configure, + PREVIEW, +) + + +@pytest.mark.live_test_only +class TestRealtime(AzureRecordedTestCase): + + @configure + @pytest.mark.parametrize( + "api_type, api_version", + [(GPT_4_AZURE, PREVIEW), (GPT_4_OPENAI, "v1")], + ) + def test_realtime_text(self, client, api_type, api_version, **kwargs): + with client.beta.realtime.connect( + **kwargs, + ) as connection: + connection.session.update(session={"modalities": ["text"]}) + connection.conversation.item.create( + item={ + "type": "message", + "role": "user", + "content": [{"type": "input_text", "text": "Say hello!"}], + } + ) + connection.response.create() + for event in connection: + if event.type == "response.text.delta": + assert event.delta + elif event.type == "response.text.done": + assert event.text + elif event.type == "response.done": + break + + @configure + @pytest.mark.parametrize( + "api_type, api_version", + [(GPT_4_AZURE, PREVIEW)], + ) + def test_realtime_text_api_key(self, client, api_type, api_version, **kwargs): + client = openai.AzureOpenAI( + azure_endpoint=os.environ[ENV_AZURE_OPENAI_SWEDENCENTRAL_ENDPOINT], + api_key=os.environ[ENV_AZURE_OPENAI_SWEDENCENTRAL_KEY], + api_version=api_version, + ) + with client.beta.realtime.connect( + **kwargs + ) as connection: + connection.session.update(session={"modalities": ["text"]}) + connection.conversation.item.create( + item={ + "type": "message", + "role": "user", + "content": [{"type": "input_text", "text": "Say hello!"}], + } + ) + connection.response.create() + for event in connection: + if event.type == "response.text.delta": + assert event.delta + elif event.type == "response.text.done": + assert event.text + elif event.type == "response.done": + break + + @configure + @pytest.mark.parametrize( + "api_type, api_version", + [(GPT_4_AZURE, PREVIEW)], + ) + def test_realtime_text_ad_token(self, client, api_type, api_version, **kwargs): + client = openai.AzureOpenAI( + azure_endpoint=os.environ[ENV_AZURE_OPENAI_SWEDENCENTRAL_ENDPOINT], + azure_ad_token=get_credential().get_token("https://cognitiveservices.azure.com/.default").token, + api_version=api_version, + ) + with client.beta.realtime.connect( + **kwargs + ) as connection: + connection.session.update(session={"modalities": ["text"]}) + connection.conversation.item.create( + item={ + "type": "message", + "role": "user", + "content": [{"type": "input_text", "text": "Say hello!"}], + } + ) + connection.response.create() + for event in connection: + if event.type == "response.text.delta": + assert event.delta + elif event.type == "response.text.done": + assert event.text + elif event.type == "response.done": + break diff --git a/sdk/openai/azure-openai/tests/test_realtime_async.py b/sdk/openai/azure-openai/tests/test_realtime_async.py new file mode 100644 index 000000000000..dfc613f7f83b --- /dev/null +++ b/sdk/openai/azure-openai/tests/test_realtime_async.py @@ -0,0 +1,114 @@ +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ + +import os +import pytest +import openai +from devtools_testutils import AzureRecordedTestCase, get_credential +from conftest import ( + ENV_AZURE_OPENAI_SWEDENCENTRAL_ENDPOINT, + ENV_AZURE_OPENAI_SWEDENCENTRAL_KEY, + GPT_4_AZURE, + GPT_4_OPENAI, + configure_async, + PREVIEW, +) + + +@pytest.mark.live_test_only +class TestRealtimeAsync(AzureRecordedTestCase): + + @configure_async + @pytest.mark.asyncio + @pytest.mark.parametrize( + "api_type, api_version", + [(GPT_4_AZURE, PREVIEW), (GPT_4_OPENAI, "v1")], + ) + async def test_realtime_text(self, client_async, api_type, api_version, **kwargs): + async with client_async.beta.realtime.connect( + **kwargs, + ) as connection: + await connection.session.update(session={"modalities": ["text"]}) + await connection.conversation.item.create( + item={ + "type": "message", + "role": "user", + "content": [{"type": "input_text", "text": "Say hello!"}], + } + ) + await connection.response.create() + async for event in connection: + if event.type == "response.text.delta": + assert event.delta + elif event.type == "response.text.done": + assert event.text + elif event.type == "response.done": + break + + @configure_async + @pytest.mark.asyncio + @pytest.mark.parametrize( + "api_type, api_version", + [(GPT_4_AZURE, PREVIEW)], + ) + async def test_realtime_text_api_key(self, client_async, api_type, api_version, **kwargs): + client_async = openai.AsyncAzureOpenAI( + azure_endpoint=os.environ[ENV_AZURE_OPENAI_SWEDENCENTRAL_ENDPOINT], + api_key=os.environ[ENV_AZURE_OPENAI_SWEDENCENTRAL_KEY], + api_version=api_version, + ) + async with client_async.beta.realtime.connect( + **kwargs + ) as connection: + await connection.session.update(session={"modalities": ["text"]}) + await connection.conversation.item.create( + item={ + "type": "message", + "role": "user", + "content": [{"type": "input_text", "text": "Say hello!"}], + } + ) + await connection.response.create() + async for event in connection: + if event.type == "response.text.delta": + assert event.delta + elif event.type == "response.text.done": + assert event.text + elif event.type == "response.done": + break + + @configure_async + @pytest.mark.asyncio + @pytest.mark.parametrize( + "api_type, api_version", + [(GPT_4_AZURE, PREVIEW)], + ) + async def test_realtime_text_ad_token(self, client_async, api_type, api_version, **kwargs): + credential = get_credential(is_async=True) + access_token = await credential.get_token("https://cognitiveservices.azure.com/.default") + client_async = openai.AsyncAzureOpenAI( + azure_endpoint=os.environ[ENV_AZURE_OPENAI_SWEDENCENTRAL_ENDPOINT], + azure_ad_token=access_token.token, + api_version=api_version, + ) + async with client_async.beta.realtime.connect( + **kwargs + ) as connection: + await connection.session.update(session={"modalities": ["text"]}) + await connection.conversation.item.create( + item={ + "type": "message", + "role": "user", + "content": [{"type": "input_text", "text": "Say hello!"}], + } + ) + await connection.response.create() + async for event in connection: + if event.type == "response.text.delta": + assert event.delta + elif event.type == "response.text.done": + assert event.text + elif event.type == "response.done": + break diff --git a/sdk/openai/tests.yml b/sdk/openai/tests.yml index 3ffa34c8e481..dd95d954d04f 100644 --- a/sdk/openai/tests.yml +++ b/sdk/openai/tests.yml @@ -17,6 +17,7 @@ extends: AZURE_OPENAI_COMPLETIONS_DEPLOYMENT: $(AOAI-COMPLETIONS-MODEL-DEPLOYMENT) AZURE_OPENAI_NORTHCENTRALUS_ENDPOINT: $(AOAI-ENDPOINT-NORTHCENTRALUS) AZURE_OPENAI_SWEDENCENTRAL_ENDPOINT: $(AOAI-ENDPOINT-SWEDENCENTRAL) + AZURE_OPENAI_SWEDENCENTRAL_KEY: $(AOAI-API-KEY-SWEDENCENTRAL) OPENAI_KEY: $(python-nonazure-openai-key) AZURE_OPENAI_SEARCH_ENDPOINT: $(COGNITIVE-SEARCH-API-ENDPOINT) AZURE_OPENAI_SEARCH_INDEX: $(COGNITIVE-SEARCH-API-INDEX)