Skip to content

Commit f8ab7b0

Browse files
setup v0 and v1 tests side-by-side (Azure#32671)
* setup openai tests against v0 and v1 * fixes to get tests working side-by-sie * fix global replace mistake * more tests for different ways to build the client + ad token auth * reorganize client tests * try testing against v1 PoC in CI * update dev reqs * fix attr access for azure in audio * adjust tests to pass for audio/images (for now) * tests for cli and models * testing module client * few fixes to get things working in CI + avoid flaky test where text is empty string * adapt tests to latest changes * get get_bearer_token_provider from azure-identity release * adapt to changes in latest commit * adapt tests to latest commit * point to v1 branch now that azure client merged
1 parent fb7db91 commit f8ab7b0

30 files changed

+4527
-355
lines changed
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
-e ../../../tools/azure-sdk-tools
22
-e ../../../tools/azure-devtools
33
../../identity/azure-identity
4-
../../core/azure-core
54
numpy
6-
git+https://github.com/openai/openai-python@main
5+
aiohttp
6+
requests

sdk/openai/azure-openai/setup.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,7 @@
6262
'azure.openai': ['py.typed'],
6363
},
6464
install_requires=[
65-
"azure-core<2.0.0,>=1.26.0",
66-
"openai<1.0.0,>=0.27.6",
67-
"azure-identity<2.0.0,>=1.12.0"
65+
"azure-identity<2.0.0,>=1.15.0"
6866
],
6967
python_requires=">=3.7",
7068
project_urls={

sdk/openai/azure-openai/tests/conftest.py

Lines changed: 184 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,34 @@
66
# --------------------------------------------------------------------------
77
import os
88
import pytest
9+
import importlib
10+
import contextlib
911
import requests
1012
import aiohttp
1113
import yarl
1214
import functools
1315
import openai
1416
from devtools_testutils.sanitizers import add_header_regex_sanitizer, add_oauth_response_sanitizer
15-
from azure.identity import DefaultAzureCredential
17+
from azure.identity import DefaultAzureCredential, get_bearer_token_provider
18+
from azure.identity.aio import (
19+
DefaultAzureCredential as AsyncDefaultAzureCredential,
20+
get_bearer_token_provider as get_bearer_token_provider_async,
21+
)
1622

23+
# controls whether we run tests against v0 or v1. Options: v0 or v1. Default: v1
24+
ENV_OPENAI_TEST_MODE = "OPENAI_TEST_MODE"
1725

1826
# for pytest.parametrize
1927
ALL = ["azure", "azuread", "openai"]
2028
AZURE = "azure"
2129
OPENAI = "openai"
2230
AZURE_AD = "azuread"
31+
WHISPER_AZURE = "whisper_azure"
32+
WHISPER_AZURE_AD = "whisper_azuread"
33+
WHISPER_ALL = ["whisper_azure", "whisper_azuread", "openai"]
2334

2435
# Environment variable keys
25-
ENV_AZURE_OPENAI_ENDPOINT = "AZURE_OPENAI_ENDPOINT"
36+
ENV_AZURE_OPENAI_ENDPOINT = "AZ_OPENAI_ENDPOINT"
2637
ENV_AZURE_OPENAI_KEY = "AZURE_OPENAI_KEY"
2738
ENV_AZURE_OPENAI_WHISPER_ENDPOINT = "AZURE_OPENAI_WHISPER_ENDPOINT"
2839
ENV_AZURE_OPENAI_WHISPER_KEY = "AZURE_OPENAI_WHISPER_KEY"
@@ -88,22 +99,162 @@ def azure_openai_creds():
8899
"audio_model": ENV_OPENAI_AUDIO_MODEL,
89100
}
90101

102+
# openai>=1.0.0 ---------------------------------------------------------------------------
91103

92-
def configure_api_type(api_type, whisper=False, **kwargs):
104+
@pytest.fixture
105+
def client(api_type):
106+
if os.getenv(ENV_OPENAI_TEST_MODE, "v1") != "v1":
107+
pytest.skip("Skipping - tests set to run against v1.")
93108
if api_type == "azure":
94-
if whisper:
95-
openai.api_base = os.getenv(ENV_AZURE_OPENAI_WHISPER_ENDPOINT).rstrip("/")
96-
openai.api_key = os.getenv(ENV_AZURE_OPENAI_WHISPER_KEY)
97-
else:
98-
openai.api_base = os.getenv(ENV_AZURE_OPENAI_ENDPOINT).rstrip("/")
99-
openai.api_key = os.getenv(ENV_AZURE_OPENAI_KEY)
109+
client = openai.AzureOpenAI(
110+
azure_endpoint=os.getenv(ENV_AZURE_OPENAI_ENDPOINT),
111+
api_key=os.getenv(ENV_AZURE_OPENAI_KEY),
112+
api_version=ENV_AZURE_OPENAI_API_VERSION,
113+
)
114+
elif api_type == "azuread":
115+
client = openai.AzureOpenAI(
116+
azure_endpoint=os.getenv(ENV_AZURE_OPENAI_ENDPOINT),
117+
azure_ad_token_provider=get_bearer_token_provider(DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default"),
118+
api_version=ENV_AZURE_OPENAI_API_VERSION,
119+
)
120+
elif api_type == "openai":
121+
client = openai.OpenAI(
122+
api_key=os.getenv(ENV_OPENAI_KEY)
123+
)
124+
elif api_type == "whisper_azure":
125+
client = openai.AzureOpenAI(
126+
azure_endpoint=os.getenv(ENV_AZURE_OPENAI_WHISPER_ENDPOINT),
127+
api_key=os.getenv(ENV_AZURE_OPENAI_WHISPER_KEY),
128+
api_version=ENV_AZURE_OPENAI_API_VERSION,
129+
)
130+
elif api_type == "whisper_azuread":
131+
client = openai.AzureOpenAI(
132+
azure_endpoint=os.getenv(ENV_AZURE_OPENAI_WHISPER_ENDPOINT),
133+
azure_ad_token_provider=get_bearer_token_provider(DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default"),
134+
api_version=ENV_AZURE_OPENAI_API_VERSION,
135+
)
136+
137+
return client
138+
139+
140+
@pytest.fixture
141+
def client_async(api_type):
142+
if os.getenv(ENV_OPENAI_TEST_MODE, "v1") != "v1":
143+
pytest.skip("Skipping - tests set to run against v1.")
144+
if api_type == "azure":
145+
client = openai.AsyncAzureOpenAI(
146+
azure_endpoint=os.getenv(ENV_AZURE_OPENAI_ENDPOINT),
147+
api_key=os.getenv(ENV_AZURE_OPENAI_KEY),
148+
api_version=ENV_AZURE_OPENAI_API_VERSION,
149+
)
150+
elif api_type == "azuread":
151+
client = openai.AsyncAzureOpenAI(
152+
azure_endpoint=os.getenv(ENV_AZURE_OPENAI_ENDPOINT),
153+
azure_ad_token_provider=get_bearer_token_provider_async(AsyncDefaultAzureCredential(), "https://cognitiveservices.azure.com/.default"),
154+
api_version=ENV_AZURE_OPENAI_API_VERSION,
155+
)
156+
elif api_type == "openai":
157+
client = openai.AsyncOpenAI(
158+
api_key=os.getenv(ENV_OPENAI_KEY)
159+
)
160+
elif api_type == "whisper_azure":
161+
client = openai.AsyncAzureOpenAI(
162+
azure_endpoint=os.getenv(ENV_AZURE_OPENAI_WHISPER_ENDPOINT),
163+
api_key=os.getenv(ENV_AZURE_OPENAI_WHISPER_KEY),
164+
api_version=ENV_AZURE_OPENAI_API_VERSION,
165+
)
166+
elif api_type == "whisper_azuread":
167+
client = openai.AsyncAzureOpenAI(
168+
azure_endpoint=os.getenv(ENV_AZURE_OPENAI_WHISPER_ENDPOINT),
169+
azure_ad_token_provider=get_bearer_token_provider_async(AsyncDefaultAzureCredential(), "https://cognitiveservices.azure.com/.default"),
170+
api_version=ENV_AZURE_OPENAI_API_VERSION,
171+
)
172+
173+
return client
174+
175+
176+
def build_kwargs(args, api_type):
177+
test_feature = args[0].qualified_test_name
178+
if test_feature.startswith("test_audio"):
179+
if api_type in ["whisper_azure", "whisper_azuread"]:
180+
return {"model": ENV_AZURE_OPENAI_AUDIO_NAME}
181+
elif api_type == "openai":
182+
return {"model": ENV_OPENAI_AUDIO_MODEL}
183+
if test_feature.startswith("test_chat_completions") \
184+
or test_feature.startswith(("test_client", "test_models")):
185+
if api_type in ["azure", "azuread"]:
186+
return {"model": ENV_AZURE_OPENAI_CHAT_COMPLETIONS_NAME}
187+
elif api_type == "openai":
188+
return {"model": ENV_OPENAI_CHAT_COMPLETIONS_MODEL}
189+
if test_feature.startswith("test_completions"):
190+
if api_type in ["azure", "azuread"]:
191+
return {"model": ENV_AZURE_OPENAI_COMPLETIONS_NAME}
192+
elif api_type == "openai":
193+
return {"model": ENV_OPENAI_COMPLETIONS_MODEL}
194+
if test_feature.startswith("test_embeddings"):
195+
if api_type in ["azure", "azuread"]:
196+
return {"model": ENV_AZURE_OPENAI_EMBEDDINGS_NAME}
197+
elif api_type == "openai":
198+
return {"model": ENV_OPENAI_EMBEDDINGS_MODEL}
199+
if test_feature.startswith(("test_dall_e", "test_module_client", "test_cli")):
200+
return {}
201+
raise ValueError(f"Test feature: {test_feature} needs to have its kwargs configured.")
202+
203+
204+
def configure_async(f):
205+
@functools.wraps(f)
206+
async def wrapper(*args, **kwargs):
207+
api_type = kwargs.pop("api_type")
208+
client_async = kwargs.pop("client_async")
209+
azure_openai_creds = kwargs.pop("azure_openai_creds")
210+
kwargs = build_kwargs(args, api_type)
211+
try:
212+
return await f(*args, client_async=client_async, azure_openai_creds=azure_openai_creds, api_type=api_type, **kwargs)
213+
except openai.RateLimitError:
214+
pytest.skip(f"{str(f).split(' ')[1]}[{api_type}]: Skipping - Rate limit reached.")
215+
216+
return wrapper
217+
218+
219+
def configure(f):
220+
@functools.wraps(f)
221+
def wrapper(*args, **kwargs):
222+
api_type = kwargs.pop("api_type")
223+
client = kwargs.pop("client")
224+
azure_openai_creds = kwargs.pop("azure_openai_creds")
225+
kwargs = build_kwargs(args, api_type)
226+
try:
227+
return f(*args, client=client, azure_openai_creds=azure_openai_creds, api_type=api_type, **kwargs)
228+
except openai.RateLimitError:
229+
pytest.skip(f"{str(f).split(' ')[1]}[{api_type}]: Skipping - Rate limit reached.")
230+
231+
return wrapper
232+
233+
234+
235+
@contextlib.contextmanager
236+
def reload():
237+
try:
238+
importlib.reload(openai)
239+
yield
240+
finally:
241+
importlib.reload(openai)
242+
243+
244+
# openai<1.0.0 ---------------------------------------------------------------------------
245+
246+
@pytest.fixture
247+
def set_vars(api_type):
248+
if os.getenv(ENV_OPENAI_TEST_MODE, "v1") != "v0":
249+
pytest.skip("Skipping - tests set to run against v0.")
250+
251+
if api_type == "azure":
252+
openai.api_base = os.getenv(ENV_AZURE_OPENAI_ENDPOINT).rstrip("/")
253+
openai.api_key = os.getenv(ENV_AZURE_OPENAI_KEY)
100254
openai.api_type = "azure"
101255
openai.api_version = ENV_AZURE_OPENAI_API_VERSION
102256
elif api_type == "azuread":
103-
if whisper:
104-
openai.api_base = os.getenv(ENV_AZURE_OPENAI_WHISPER_ENDPOINT).rstrip("/")
105-
else:
106-
openai.api_base = os.getenv(ENV_AZURE_OPENAI_ENDPOINT).rstrip("/")
257+
openai.api_base = os.getenv(ENV_AZURE_OPENAI_ENDPOINT).rstrip("/")
107258
credential = DefaultAzureCredential()
108259
token = credential.get_token("https://cognitiveservices.azure.com/.default")
109260
openai.api_type = "azuread"
@@ -114,30 +265,42 @@ def configure_api_type(api_type, whisper=False, **kwargs):
114265
openai.api_type = "openai"
115266
openai.api_key = os.getenv(ENV_OPENAI_KEY)
116267
openai.api_version = None
268+
elif api_type == "whisper_azure":
269+
openai.api_base = os.getenv(ENV_AZURE_OPENAI_WHISPER_ENDPOINT).rstrip("/")
270+
openai.api_key = os.getenv(ENV_AZURE_OPENAI_WHISPER_KEY)
271+
openai.api_type = "azure"
272+
openai.api_version = ENV_AZURE_OPENAI_API_VERSION
273+
elif api_type == "whisper_azuread":
274+
openai.api_base = os.getenv(ENV_AZURE_OPENAI_WHISPER_ENDPOINT).rstrip("/")
275+
credential = DefaultAzureCredential()
276+
token = credential.get_token("https://cognitiveservices.azure.com/.default")
277+
openai.api_type = "azuread"
278+
openai.api_key = token.token
279+
openai.api_version = ENV_AZURE_OPENAI_API_VERSION
117280

118281

119-
def configure_async(f):
282+
def configure_v0_async(f):
120283
@functools.wraps(f)
121284
async def wrapper(*args, **kwargs):
122285
api_type = kwargs.pop("api_type")
123-
whisper = args[0].qualified_test_name.startswith("test_audio")
124-
configure_api_type(api_type, whisper=whisper, **kwargs)
286+
set_vars = kwargs.pop("set_vars")
287+
azure_openai_creds = kwargs.pop("azure_openai_creds")
125288
try:
126-
return await f(*args, api_type=api_type, **kwargs)
289+
return await f(*args, set_vars=set_vars, azure_openai_creds=azure_openai_creds, api_type=api_type, **kwargs)
127290
except openai.error.RateLimitError:
128291
pytest.skip(f"{str(f).split(' ')[1]}[{api_type}]: Skipping - Rate limit reached.")
129292

130293
return wrapper
131294

132295

133-
def configure(f):
296+
def configure_v0(f):
134297
@functools.wraps(f)
135298
def wrapper(*args, **kwargs):
136299
api_type = kwargs.pop("api_type")
137-
whisper = args[0].qualified_test_name.startswith("test_audio")
138-
configure_api_type(api_type, whisper=whisper, **kwargs)
300+
set_vars = kwargs.pop("set_vars")
301+
azure_openai_creds = kwargs.pop("azure_openai_creds")
139302
try:
140-
return f(*args, api_type=api_type, **kwargs)
303+
return f(*args, set_vars=set_vars, azure_openai_creds=azure_openai_creds, api_type=api_type, **kwargs)
141304
except openai.error.RateLimitError:
142305
pytest.skip(f"{str(f).split(' ')[1]}[{api_type}]: Skipping - Rate limit reached.")
143306

0 commit comments

Comments
 (0)