Skip to content

Commit 9b589f5

Browse files
authored
Add "api-key" HTTP request header when using AzureKeyCredential (Azure#37888)
1 parent b75ca6c commit 9b589f5

File tree

11 files changed

+112
-36
lines changed

11 files changed

+112
-36
lines changed

sdk/ai/azure-ai-inference/CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44

55
### Features Added
66

7-
* Support for tracing. Please find more information in the package [README.md](https://github.com/Azure/azure-sdk-for-python/blob/main/sdk/ai/azure-ai-inference/README.md).
7+
* Support for OpenTelemetry tracing. Please find more information in the package [README.md](https://github.com/Azure/azure-sdk-for-python/blob/main/sdk/ai/azure-ai-inference/README.md).
8+
* When constructing clients using input `credential` of type `AzureKeyCredential`, two HTTP request headers are sent simultaneously for authentication: `Authentication: Beater <key>` and `api-key: <key>` (previously only the first one was sent). This is to support different inference services, removing the need for the application to explicitly specify an additional HTTP request header.
89

910
### Breaking Changes
1011

sdk/ai/azure-ai-inference/README.md

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ Studio.
4141
* An [OpenAI Model from the catalog](https://oai.azure.com/resource/models) deployed through Azure OpenAI Studio.
4242
* The endpoint URL of your model, in the form `https://<your-resouce-name>.openai.azure.com/openai/deployments/<your-deployment-name>`, where `your-resource-name` is your globally unique AOAI resource name, and `your-deployment-name` is your AI Model deployment name.
4343
* Depending on your authentication preference, you either need an API key to authenticate against the service, or Entra ID credentials. The API key is a 32-character string.
44-
* An api-version. Latest preview or GA version listed in the `Data plane - inference` row in [the API Specs table](https://learn.microsoft.com/azure/ai-services/openai/reference#api-specs). At the time of writing, latest GA version was "2024-06-01".
44+
* An api-version. Latest preview or GA version listed in the `Data plane - inference` row in [the API Specs table](https://aka.ms/azsdk/azure-ai-inference/azure-openai-api-versions). At the time of writing, latest GA version was "2024-06-01".
4545

4646
### Install the package
4747

@@ -60,11 +60,9 @@ pip install --upgrade azure-ai-inference
6060
If you want to install Azure AI Inferencing package with support for OpenTelemetry based tracing, use the following command:
6161

6262
```bash
63-
pip install azure-ai-inference[trace]
63+
pip install azure-ai-inference[opentelemetry]
6464
```
6565

66-
67-
6866
## Key concepts
6967

7068
### Create and authenticate a client directly, using API key or GitHub token
@@ -91,9 +89,8 @@ client = ChatCompletionsClient(
9189
# For Azure OpenAI endpoint
9290
client = ChatCompletionsClient(
9391
endpoint=endpoint, # Of the form https://<your-resouce-name>.openai.azure.com/openai/deployments/<your-deployment-name>
94-
credential=AzureKeyCredential(""), # Pass in an empty value.
95-
headers={"api-key": key},
96-
api_version="2024-06-01", # AOAI api-version. Update as needed.
92+
credential=AzureKeyCredential(key),
93+
api_version="2024-06-01", # Azure OpenAI api-version. See https://aka.ms/azsdk/azure-ai-inference/azure-openai-api-versions
9794
)
9895
```
9996

@@ -146,7 +143,7 @@ client = ChatCompletionsClient(
146143
endpoint=endpoint,
147144
credential=DefaultAzureCredential(exclude_interactive_browser_credential=False),
148145
credential_scopes=["https://cognitiveservices.azure.com/.default"],
149-
api_version="2024-06-01", # AOAI api-version. Update as needed.
146+
api_version="2024-06-01", # Azure OpenAI api-version. See https://aka.ms/azsdk/azure-ai-inference/azure-openai-api-versions
150147
)
151148
```
152149

sdk/ai/azure-ai-inference/assets.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
"AssetsRepo": "Azure/azure-sdk-assets",
33
"AssetsRepoPrefixPath": "python",
44
"TagPrefix": "python/ai/azure-ai-inference",
5-
"Tag": "python/ai/azure-ai-inference_19a0adafc6"
5+
"Tag": "python/ai/azure-ai-inference_3934744053"
66
}

sdk/ai/azure-ai-inference/azure/ai/inference/_patch.py

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@
1414
4. Add support for get_model_info, while caching the result (all clients)
1515
5. Add support for chat completion streaming (ChatCompletionsClient client only)
1616
6. Add support for friendly print of result objects (__str__ method) (all clients)
17-
7. Add support for load() method in ImageUrl class (see /models/_patch.py).
17+
7. Add support for load() method in ImageUrl class (see /models/_patch.py)
18+
8. Add support for sending two auth headers for api-key auth (all clients)
1819
1920
"""
2021
import json
@@ -245,8 +246,22 @@ def __init__(
245246
self._model = model
246247
self._model_extras = model_extras
247248

249+
# For Key auth, we need to send these two auth HTTP request headers simultaneously:
250+
# 1. "Authorization: Bearer <key>"
251+
# 2. "api-key: <key>"
252+
# This is because Serverless API, Managed Compute and GitHub endpoints support the first header,
253+
# and Azure OpenAI and the new Unified Inference endpoints support the second header.
254+
# The first header will be taken care of by auto-generated code.
255+
# The second one is added here.
256+
if isinstance(credential, AzureKeyCredential):
257+
headers = kwargs.pop("headers", {})
258+
if "api-key" not in headers:
259+
headers["api-key"] = credential.key
260+
kwargs["headers"] = headers
261+
248262
super().__init__(endpoint, credential, **kwargs)
249263

264+
250265
@overload
251266
def complete(
252267
self,
@@ -724,6 +739,19 @@ def __init__(
724739
self._model = model
725740
self._model_extras = model_extras
726741

742+
# For Key auth, we need to send these two auth HTTP request headers simultaneously:
743+
# 1. "Authorization: Bearer <key>"
744+
# 2. "api-key: <key>"
745+
# This is because Serverless API, Managed Compute and GitHub endpoints support the first header,
746+
# and Azure OpenAI and the new Unified Inference endpoints support the second header.
747+
# The first header will be taken care of by auto-generated code.
748+
# The second one is added here.
749+
if isinstance(credential, AzureKeyCredential):
750+
headers = kwargs.pop("headers", {})
751+
if "api-key" not in headers:
752+
headers["api-key"] = credential.key
753+
kwargs["headers"] = headers
754+
727755
super().__init__(endpoint, credential, **kwargs)
728756

729757
@overload
@@ -1007,6 +1035,19 @@ def __init__(
10071035
self._model = model
10081036
self._model_extras = model_extras
10091037

1038+
# For Key auth, we need to send these two auth HTTP request headers simultaneously:
1039+
# 1. "Authorization: Bearer <key>"
1040+
# 2. "api-key: <key>"
1041+
# This is because Serverless API, Managed Compute and GitHub endpoints support the first header,
1042+
# and Azure OpenAI and the new Unified Inference endpoints support the second header.
1043+
# The first header will be taken care of by auto-generated code.
1044+
# The second one is added here.
1045+
if isinstance(credential, AzureKeyCredential):
1046+
headers = kwargs.pop("headers", {})
1047+
if "api-key" not in headers:
1048+
headers["api-key"] = credential.key
1049+
kwargs["headers"] = headers
1050+
10101051
super().__init__(endpoint, credential, **kwargs)
10111052

10121053
@overload

sdk/ai/azure-ai-inference/azure/ai/inference/aio/_patch.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,19 @@ def __init__(
229229
self._model = model
230230
self._model_extras = model_extras
231231

232+
# For Key auth, we need to send these two auth HTTP request headers simultaneously:
233+
# 1. "Authorization: Bearer <key>"
234+
# 2. "api-key: <key>"
235+
# This is because Serverless API, Managed Compute and GitHub endpoints support the first header,
236+
# and Azure OpenAI and the new Unified Inference endpoints support the second header.
237+
# The first header will be taken care of by auto-generated code.
238+
# The second one is added here.
239+
if isinstance(credential, AzureKeyCredential):
240+
headers = kwargs.pop("headers", {})
241+
if "api-key" not in headers:
242+
headers["api-key"] = credential.key
243+
kwargs["headers"] = headers
244+
232245
super().__init__(endpoint, credential, **kwargs)
233246

234247
@overload
@@ -707,6 +720,19 @@ def __init__(
707720
self._model = model
708721
self._model_extras = model_extras
709722

723+
# For Key auth, we need to send these two auth HTTP request headers simultaneously:
724+
# 1. "Authorization: Bearer <key>"
725+
# 2. "api-key: <key>"
726+
# This is because Serverless API, Managed Compute and GitHub endpoints support the first header,
727+
# and Azure OpenAI and the new Unified Inference endpoints support the second header.
728+
# The first header will be taken care of by auto-generated code.
729+
# The second one is added here.
730+
if isinstance(credential, AzureKeyCredential):
731+
headers = kwargs.pop("headers", {})
732+
if "api-key" not in headers:
733+
headers["api-key"] = credential.key
734+
kwargs["headers"] = headers
735+
710736
super().__init__(endpoint, credential, **kwargs)
711737

712738
@overload
@@ -990,6 +1016,19 @@ def __init__(
9901016
self._model = model
9911017
self._model_extras = model_extras
9921018

1019+
# For Key auth, we need to send these two auth HTTP request headers simultaneously:
1020+
# 1. "Authorization: Bearer <key>"
1021+
# 2. "api-key: <key>"
1022+
# This is because Serverless API, Managed Compute and GitHub endpoints support the first header,
1023+
# and Azure OpenAI and the new Unified Inference endpoints support the second header.
1024+
# The first header will be taken care of by auto-generated code.
1025+
# The second one is added here.
1026+
if isinstance(credential, AzureKeyCredential):
1027+
headers = kwargs.pop("headers", {})
1028+
if "api-key" not in headers:
1029+
headers["api-key"] = credential.key
1030+
kwargs["headers"] = headers
1031+
9931032
super().__init__(endpoint, credential, **kwargs)
9941033

9951034
@overload

sdk/ai/azure-ai-inference/samples/async_samples/sample_chat_completions_streaming_azure_openai_async.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
Entra ID authentication.
1515
2. Update `api_version` (the AOAI REST API version) as needed.
1616
See the "Data plane - inference" row in the table here for latest AOAI api-version:
17-
https://learn.microsoft.com/azure/ai-services/openai/reference#api-specs
17+
https://aka.ms/azsdk/azure-ai-inference/azure-openai-api-versions
1818
3. Set one or two environment variables, depending on your authentication method:
1919
* AZURE_OPENAI_CHAT_ENDPOINT - Your AOAI endpoint URL, with partial path, in the form
2020
https://<your-unique-resouce-name>.openai.azure.com/openai/deployments/<your-deployment-name>
@@ -55,9 +55,8 @@ async def sample_chat_completions_streaming_azure_openai_async():
5555

5656
client = ChatCompletionsClient(
5757
endpoint=endpoint,
58-
credential=AzureKeyCredential(""), # Pass in an empty value.
59-
headers={"api-key": key},
60-
api_version="2024-06-01", # AOAI api-version. Update as needed.
58+
credential=AzureKeyCredential(key),
59+
api_version="2024-06-01", # Azure OpenAI api-version. See https://aka.ms/azsdk/azure-ai-inference/azure-openai-api-versions
6160
)
6261

6362
else: # Entra ID authentication
@@ -67,7 +66,7 @@ async def sample_chat_completions_streaming_azure_openai_async():
6766
endpoint=endpoint,
6867
credential=DefaultAzureCredential(exclude_interactive_browser_credential=False),
6968
credential_scopes=["https://cognitiveservices.azure.com/.default"],
70-
api_version="2024-06-01", # AOAI api-version. Update as needed.
69+
api_version="2024-06-01", # Azure OpenAI api-version. See https://aka.ms/azsdk/azure-ai-inference/azure-openai-api-versions
7170
)
7271

7372
response = await client.complete(

sdk/ai/azure-ai-inference/samples/sample_chat_completions_azure_openai.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
Entra ID authentication.
1515
2. Update `api_version` (the AOAI REST API version) as needed.
1616
See the "Data plane - inference" row in the table here for latest AOAI api-version:
17-
https://learn.microsoft.com/azure/ai-services/openai/reference#api-specs
17+
https://aka.ms/azsdk/azure-ai-inference/azure-openai-api-versions
1818
3. Set one or two environment variables, depending on your authentication method:
1919
* AZURE_OPENAI_CHAT_ENDPOINT - Your AOAI endpoint URL, with partial path, in the form
2020
https://<your-unique-resouce-name>.openai.azure.com/openai/deployments/<your-deployment-name>
@@ -54,9 +54,8 @@ def sample_chat_completions_azure_openai():
5454

5555
client = ChatCompletionsClient(
5656
endpoint=endpoint,
57-
credential=AzureKeyCredential(""), # Pass in an empty value.
58-
headers={"api-key": key},
59-
api_version="2024-06-01", # AOAI api-version. Update as needed.
57+
credential=AzureKeyCredential(key),
58+
api_version="2024-06-01", # Azure OpenAI api-version. See https://aka.ms/azsdk/azure-ai-inference/azure-openai-api-versions
6059
)
6160

6261
else: # Entra ID authentication
@@ -66,7 +65,7 @@ def sample_chat_completions_azure_openai():
6665
endpoint=endpoint,
6766
credential=DefaultAzureCredential(exclude_interactive_browser_credential=False),
6867
credential_scopes=["https://cognitiveservices.azure.com/.default"],
69-
api_version="2024-06-01", # AOAI api-version. Update as needed.
68+
api_version="2024-06-01", # Azure OpenAI api-version. See https://aka.ms/azsdk/azure-ai-inference/azure-openai-api-versions
7069
)
7170

7271
response = client.complete(

sdk/ai/azure-ai-inference/samples/sample_chat_completions_streaming_with_tools.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -112,9 +112,8 @@ def get_flight_info(origin_city: str, destination_city: str):
112112
# Create a chat completion client for Azure OpenAI endpoint
113113
client = ChatCompletionsClient(
114114
endpoint=endpoint,
115-
credential=AzureKeyCredential(""), # Pass in an empty value
116-
headers={"api-key": key},
117-
api_version="2024-06-01", # AOAI api-version. Update as needed.
115+
credential=AzureKeyCredential(key),
116+
api_version="2024-06-01", # Azure OpenAI api-version. See https://aka.ms/azsdk/azure-ai-inference/azure-openai-api-versions
118117
)
119118
else:
120119
# Create a chat completions client for Serverless API endpoint or Managed Compute endpoint

sdk/ai/azure-ai-inference/samples/sample_embeddings_azure_openai.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
Entra ID authentication.
1515
2. Update `api_version` (the AOAI REST API version) as needed.
1616
See the "Data plane - inference" row in the table here for latest AOAI api-version:
17-
https://learn.microsoft.com/azure/ai-services/openai/reference#api-specs
17+
https://aka.ms/azsdk/azure-ai-inference/azure-openai-api-versions
1818
3. Set one or two environment variables, depending on your authentication method:
1919
* AZURE_OPENAI_EMBEDDINGS_ENDPOINT - Your AOAI endpoint URL, with partial path, in the form
2020
https://<your-unique-resouce-name>.openai.azure.com/openai/deployments/<your-deployment-name>
@@ -53,9 +53,8 @@ def sample_embeddings_azure_openai():
5353

5454
client = EmbeddingsClient(
5555
endpoint=endpoint,
56-
credential=AzureKeyCredential(""), # Pass in an empty value.
57-
headers={"api-key": key},
58-
api_version="2024-06-01", # AOAI api-version. Update as needed.
56+
credential=AzureKeyCredential(key),
57+
api_version="2024-06-01", # Azure OpenAI api-version. See https://aka.ms/azsdk/azure-ai-inference/azure-openai-api-versions
5958
)
6059

6160
else: # Entra ID authentication
@@ -65,7 +64,7 @@ def sample_embeddings_azure_openai():
6564
endpoint=endpoint,
6665
credential=DefaultAzureCredential(exclude_interactive_browser_credential=False),
6766
credential_scopes=["https://cognitiveservices.azure.com/.default"],
68-
api_version="2024-06-01", # AOAI api-version. Update as needed.
67+
api_version="2024-06-01", # Azure OpenAI api-version. See https://aka.ms/azsdk/azure-ai-inference/azure-openai-api-versions
6968
)
7069

7170
response = client.embed(input=["first phrase", "second phrase", "third phrase"])

sdk/ai/azure-ai-inference/setup.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
license="MIT License",
3636
author="Microsoft Corporation",
3737
author_email="[email protected]",
38-
url="https://github.com/Azure/azure-sdk-for-python/tree/main/sdk",
38+
url="https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/ai/azure-ai-inference",
3939
keywords="azure, azure sdk",
4040
classifiers=[
4141
"Development Status :: 4 - Beta",
@@ -68,7 +68,7 @@
6868
"typing-extensions>=4.6.0",
6969
],
7070
python_requires=">=3.8",
71-
extras_require={
72-
'trace': ['azure-core-tracing-opentelemetry']
71+
extras_require={
72+
'opentelemetry': ['azure-core-tracing-opentelemetry']
7373
}
7474
)

0 commit comments

Comments
 (0)