Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
126 commits
Select commit Hold shift + click to select a range
18b5021
auto-gen files
dargilco Mar 26, 2024
b8ea0cd
first pass at writing tests
dargilco Mar 27, 2024
ee78c9c
Re-emit client library with fixed variable name
dargilco Mar 27, 2024
25b5c6b
Fix test
dargilco Mar 27, 2024
5072f00
First test working!
dargilco Mar 28, 2024
62c476a
Re-emit after adding tools. Add async test
dargilco Mar 29, 2024
2bdb446
Add basic samples
dargilco Mar 29, 2024
ad9992c
Ignore spelling errors
dargilco Mar 29, 2024
59bf4f3
fix `tox run -e sphinx` errors
dargilco Mar 29, 2024
1613b37
Merge remote-tracking branch 'origin/main' into dargilco/azure-ai-inf…
dargilco Mar 29, 2024
8d3948c
Update SDK to support embeddings. Add sample. Add root README.md
dargilco Mar 30, 2024
fff460e
Fix typo
dargilco Apr 2, 2024
9d171a7
After re-emit using flat input arguments
dargilco Apr 2, 2024
7efa800
Update README.md code snippets
dargilco Apr 2, 2024
8008505
Merge remote-tracking branch 'origin/main' into dargilco/azure-ai-inf…
dargilco Apr 4, 2024
61b62ac
Re-emit
dargilco Apr 4, 2024
675ba6d
Samples for image generation
dargilco Apr 4, 2024
c5ea2fc
Add dictionary of extra parameters
dargilco Apr 4, 2024
45c7ca1
Re-emit
dargilco Apr 4, 2024
8ee88aa
Example of setting extra parameters
dargilco Apr 4, 2024
bad14c9
Fix README.md title
dargilco Apr 5, 2024
b49acb6
Placeholder patch for streaming chat method
dargilco Apr 5, 2024
708e4c4
Re-emit, to get two new streaming 'Delta' classes
dargilco Apr 5, 2024
da8a678
first go at streaming
dargilco Apr 10, 2024
ed2b227
Latest re-emit, removing 'extra_parameters'
dargilco Apr 10, 2024
0428d95
async streaming support
dargilco Apr 11, 2024
9d98958
A few quality gates fixes
dargilco Apr 11, 2024
37c3599
Use aclose() for async interator
dargilco Apr 11, 2024
58b3669
Update env-variable names
dargilco Apr 11, 2024
0f79e70
First set of updates following SDK review meeting
dargilco Apr 12, 2024
e70da4b
Merge remote-tracking branch 'origin/main' into dargilco/azure-ai-inf…
dargilco Apr 12, 2024
8e274b6
New client names. Other minor model name changes
dargilco Apr 12, 2024
159d82f
Minor fixes to root README.md
dargilco Apr 12, 2024
5326bba
Update tests
dargilco Apr 15, 2024
27b555f
Merge remote-tracking branch 'origin/main' into dargilco/azure-ai-inf…
dargilco Apr 15, 2024
1e42647
Minor test updates
dargilco Apr 16, 2024
65b2bf1
Add assets.json
dargilco Apr 16, 2024
32368f2
Fix test name
dargilco Apr 16, 2024
18d6baa
First round of Pylint fixes
dargilco Apr 16, 2024
1243048
Fix pyright errors
dargilco Apr 16, 2024
3c84d22
Fix all pyright errors
dargilco Apr 16, 2024
c951405
Fix more quality gates
dargilco Apr 17, 2024
e18d79c
Add streaming tests
dargilco Apr 17, 2024
51f30d3
Fix streaming to work with small HTTP buffers (tested down to 64 bytes)
dargilco Apr 18, 2024
2578c8d
Merge remote-tracking branch 'origin/main' into dargilco/azure-ai-inf…
dargilco Apr 18, 2024
3090bae
Update ci.yml
dargilco Apr 18, 2024
84ad0b5
Add samples for chat history, JSON input, IO[bytes] input
dargilco Apr 19, 2024
6b87862
Merge remote-tracking branch 'origin/main' into dargilco/azure-ai-inf…
dargilco May 6, 2024
6aaa1c4
Draft sample for chat completion with tools
dargilco May 8, 2024
11a1c78
Grab latest TypeSpec changes
dargilco May 8, 2024
6a6cbc5
Merge remote-tracking branch 'origin/main' into dargilco/azure-ai-inf…
dargilco May 8, 2024
5864275
Re-emit SDK to pick up TypeSpec tools changes. Fix result.id check to…
dargilco May 8, 2024
9e18146
New test for tool, new recordings
dargilco May 8, 2024
2c97356
use logger for detailed SSE streaming debug spew
dargilco May 9, 2024
37d1e35
Don't build azure-ai-generative and azure-ai-resources packages, as t…
dargilco May 9, 2024
e79c4b5
Split streaming response class to two, one for sync, one for async
dargilco May 9, 2024
06e11f7
Update test timeout. Rename /templates/stages/platform-matrix-ai.json…
dargilco May 9, 2024
610b4eb
Mark azure-ai-generative and azure-ai-resources as in-active
dargilco May 9, 2024
9def3bb
Fix mypy and pylint errors
dargilco May 10, 2024
fb7612b
Sample for getting model info
dargilco May 10, 2024
cd30a48
Remove image generation
dargilco May 10, 2024
a6ae407
Re-emit from TypeSpec without Image Generation
dargilco May 10, 2024
78331f7
Merge remote-tracking branch 'origin/main' into dargilco/azure-ai-inf…
dargilco May 10, 2024
943faa9
Merge remote-tracking branch 'origin/main' into dargilco/azure-ai-inf…
dargilco May 13, 2024
a1ebd6b
Update auth
dargilco May 13, 2024
f0b773c
Add get_model_info tests
dargilco May 14, 2024
e4f3089
Merge remote-tracking branch 'origin/main' into dargilco/azure-ai-inf…
dargilco May 14, 2024
deb3d16
Add sample for ClientGenerator
dargilco May 14, 2024
c6b3bc2
Remove /v1
dargilco May 14, 2024
042c06a
Use new test recording assests without /v1
dargilco May 14, 2024
56450c9
Pick up TypeSpec with /v1 removed from route
dargilco May 14, 2024
a36fbee
Support Image Embeddings and version 2024-05
dargilco May 14, 2024
82168b5
Update test recordings
dargilco May 14, 2024
e788873
Fix quality some quality gates
dargilco May 15, 2024
2c18488
Fix broken link ('link verification check')
dargilco May 15, 2024
2ac893f
Use 'response' instead of 'result' in samples, as this is what I see …
dargilco May 15, 2024
b56ca82
Implement load_client and load_async_client
dargilco May 16, 2024
aafcc37
Make three BaseStreamingChatCompletions variables (constants) private)
dargilco May 16, 2024
b5484ee
sync and async versions of load_client
dargilco May 17, 2024
0a82fe2
Remove wait loop in async samples. Simplify tool sample. Other minor …
dargilco May 17, 2024
3dbca9e
Merge remote-tracking branch 'origin/main' into dargilco/azure-ai-inf…
dargilco May 17, 2024
bf93525
Re-emit with new operator names
dargilco May 17, 2024
ca2f4ff
Minor change to sample
dargilco May 20, 2024
9db8bce
Merge remote-tracking branch 'origin/main' into dargilco/azure-ai-inf…
dargilco May 20, 2024
673f27b
Add support for hyper_parameters
dargilco May 21, 2024
0ed9d7b
Update root README.md
dargilco May 21, 2024
7c5424f
Save work - unknown_params header, hyper_params input, cached model_info
dargilco May 22, 2024
1faf123
Some test changes
dargilco May 22, 2024
71bd71d
Many changes
dargilco May 23, 2024
712dfcc
New test recordings
dargilco May 23, 2024
d6012b7
Minor samples and README.md changes
dargilco May 23, 2024
3f52d6f
Update names of streaming response classes
dargilco May 23, 2024
62c5d8a
Update Entra ID sample, document Entra ID in README, use ttps://ml.az…
dargilco May 23, 2024
8a3a167
use model_extras instead of hyper_params. Update client __str__ to no…
dargilco May 24, 2024
092f91b
Fix all pylint errors. Minor updates to root README.md
dargilco May 28, 2024
8e610c2
Example of JSON messages in the root README.md
dargilco May 28, 2024
6d1e7ce
Merge remote-tracking branch 'origin/main' into dargilco/azure-ai-inf…
dargilco May 28, 2024
a738ff5
Some MyPy fixes. Also fix wrong package name in root README.md
dargilco May 28, 2024
44e94d0
Same work before re-emitting SDK
dargilco May 29, 2024
27ac7b0
Merge remote-tracking branch 'origin/main' into dargilco/azure-ai-inf…
dargilco May 30, 2024
a825db4
Use `embed` instead of `embedding`. Update Entra ID and AOAI samples
dargilco May 30, 2024
c4814d8
Fix some mypy errors. Use different terms for MaaS/MaaP
dargilco May 31, 2024
2df88dc
Re-emit, now with pyproject.toml
dargilco May 31, 2024
89d92d3
Fix/supress mypy & pyright errors
dargilco May 31, 2024
e20d003
Fix missing Etra ID auth in load_client
dargilco May 31, 2024
d7ef3b7
Use vanity link for samples folder
dargilco Jun 3, 2024
63fefdf
Revert "Use vanity link for samples folder"
dargilco Jun 3, 2024
ab6973f
Fix mypy and pyright errors
dargilco Jun 3, 2024
efbcf5c
Update root README.md. Update operator ref doc comments
dargilco Jun 3, 2024
6f69018
Re-emit
dargilco Jun 3, 2024
aed30bf
Fix mypy error in sample
dargilco Jun 3, 2024
c327403
Fix missing ranges in ref-doc comments
dargilco Jun 3, 2024
27f2ed6
Remove unneeded cast
dargilco Jun 3, 2024
2c92e9d
Fix pylint error
dargilco Jun 3, 2024
98cd4fd
Fix typos & method names. Thanks Jarno!
dargilco Jun 4, 2024
a44df4e
Address Johan's code review comments. Thanks Johan!
dargilco Jun 5, 2024
c0958e3
Fix mypy errors
dargilco Jun 5, 2024
2cbb1cf
Minor update to root README.md
dargilco Jun 5, 2024
73c836e
Remove capacity_type
dargilco Jun 6, 2024
0883400
Fix public patched methods not showing up in intellisense, when using…
dargilco Jun 6, 2024
d0930a8
Import 'Self' from Typing package starting from Python 3.11
dargilco Jun 6, 2024
13e8ed6
Fix pylint error, line too long
dargilco Jun 6, 2024
223238c
More AOAI samples. Update package README with regards to AOAI support
dargilco Jun 6, 2024
0d03ad2
Add overloads with `stream: Literal[..]` to fix mypy and pyright erro…
dargilco Jun 6, 2024
8647964
Override all client __init__ methods so you can define and initialize…
dargilco Jun 6, 2024
3715766
Cleanup: delete now unused platform-matrix-ai.json.old
dargilco Jun 7, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
first pass at writing tests
  • Loading branch information
dargilco committed Mar 27, 2024
commit b8ea0cdd4a88eaa1015be21906e72139ab5374f8
58 changes: 58 additions & 0 deletions sdk/ai/azure-ai-inference/tests/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Azure Image Analysis client library tests for Python

## Running tests locally, on a Windows PC, against the live service

### Prerequisites

See [Prerequisites](https://github.com/Azure/azure-sdk-for-python/blob/main/sdk/vision/azure-ai-vision-imageanalysis/README.md#prerequisites). Create an Azure resource in one of the GPU-supported regions, otherwise some of the tests will fail.

### Setup

* Clone or download this sample repository.
* Open a command prompt window in the folder `sdk\vision\azure-ai-vision-imageanalysis`.
* If you want to run tests against the latest public Image Analysis client library, install it by running:
```bash
pip install azure-ai-vision-imageanalysis
```
* If you want to run tests against a locally built Image Analysis client library:
* First build the wheel:
```bash
pip install wheel
pip install -r dev_requirements.txt
python setup.py bdist_wheel
```
* Then install the resulting local wheel (update version `1.0.0b1` to the current one):
```bash
pip install dist\azure_ai_vision_imageanalysis-1.0.0b1-py3-none-any.whl --user --force-reinstall
```


### Set environment variables

See [Set environment variables](https://github.com/Azure/azure-sdk-for-python/blob/main/sdk/vision/azure-ai-vision-imageanalysis/README.md#set-environment-variables).

In addition, the following environment values **must be** defined, although not used. Assign any value to them:
```
set VISION_TENANT_ID=not-used
set VISION_CLIENT_ID=not-used
set VISION_CLIENT_SECRET=not-used
```

### Configure test proxy

Configure the test proxy to run live service tests without recordings:
```
set AZURE_TEST_RUN_LIVE=true
set AZURE_SKIP_LIVE_RECORDING=true
```

### Run tests

To run all tests, type:
```
pytest
```

### Additional information

See [test documentation](https://github.com/Azure/azure-sdk-for-python/blob/main/doc/dev/tests.md) for additional information, including how to set proxy recordings and run tests using recordings.
12 changes: 12 additions & 0 deletions sdk/ai/azure-ai-inference/tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# ------------------------------------
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
# ------------------------------------

import pytest
from devtools_testutils import test_proxy

# autouse=True will trigger this fixture on each pytest run, even if it's not explicitly used by a test method
@pytest.fixture(scope="session", autouse=True)
def start_proxy(test_proxy):
return
189 changes: 189 additions & 0 deletions sdk/ai/azure-ai-inference/tests/model_inference_test_base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
# ------------------------------------
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
# ------------------------------------
import functools
import logging
import sys
import azure.ai.inference as sdk
import azure.ai.inference as async_sdk

from os import path
from typing import List, Optional, Union
from devtools_testutils import AzureRecordedTestCase, EnvironmentVariableLoader
from azure.core.credentials import AzureKeyCredential
from azure.core.exceptions import AzureError
from azure.core.pipeline import PipelineRequest

# Set to True to enable SDK logging
LOGGING_ENABLED = True

if LOGGING_ENABLED:
# Create a logger for the 'azure' SDK
# See https://docs.python.org/3/library/logging.html
logger = logging.getLogger("azure")
logger.setLevel(logging.INFO) # INFO or DEBUG

# Configure a console output
handler = logging.StreamHandler(stream=sys.stdout)
logger.addHandler(handler)

ServicePreparer = functools.partial(
EnvironmentVariableLoader,
"model",
model_endpoint="https://your-azure-resource-name.your-azure-region.inference.ai.azure.com",
model_key="00000000000000000000000000000000"
)


# The test class name needs to start with "Test" to get collected by pytest
class ModelInferenceTestBase(AzureRecordedTestCase):

client: sdk.ModelClient
async_client: async_sdk.ModelClient
connection_url: str

# Set to True to print out all analysis results
PRINT_CHAT_COMPLETION_RESULTS = True

def _create_client_for_standard_test(self, sync: bool, get_connection_url: bool = False, **kwargs):
endpoint = kwargs.pop("model_endpoint")
key = kwargs.pop("model_key")
self._create_client(endpoint, key, sync, get_connection_url)

def _create_client_for_authentication_failure(self, sync: bool, **kwargs):
endpoint = kwargs.pop("model_endpoint")
key = "00000000000000000000000000000000"
self._create_client(endpoint, key, sync, False)

def _create_client(self, endpoint: str, key: str, sync: bool, get_connection_url: bool):
credential = AzureKeyCredential(key)
if sync:
self.client = sdk.ModelClient(
endpoint=endpoint,
credential=credential,
logging_enable=LOGGING_ENABLED,
raw_request_hook=self._raw_request_check if get_connection_url else None,
)
assert self.client is not None
else:
self.async_client = async_sdk.ModelClient(
endpoint=endpoint,
credential=credential,
logging_enable=LOGGING_ENABLED,
raw_request_hook=self._raw_request_check if get_connection_url else None,
)
assert self.async_client is not None

def _raw_request_check(self, request: PipelineRequest):
self.connection_url = request.http_request.url
print(f"Connection URL: {request.http_request.url}")

def _do_chat_completions(
self,
options: sdk.models.ChatCompletionsOptions,
query_params: Optional[dict] = None,
**kwargs,
):

result = self.client.get_chat_completions(options=options, params=query_params)

# Optional: console printout of all results
if ModelInferenceTestBase.PRINT_CHAT_COMPLETION_RESULTS:
ModelInferenceTestBase._print_chat_completion_results(result)

# Validate all results
ModelInferenceTestBase._validate_chat_completion_results(result)

# Validate that additional query parameters exists in the connection URL, if specify
if query_params is not None:
ModelInferenceTestBase._validate_query_parameters(query_params, self.connection_url)

async def _do_async_chat_completion(
self,
options: sdk.models.ChatCompletionsOptions,
query_params: Optional[dict] = None,
**kwargs,
):

result = await self.async_client.chat_completions(options=options, params=query_params)

# Optional: console printout of all results
if ModelInferenceTestBase.PRINT_CHAT_COMPLETION_RESULTS:
ModelInferenceTestBase._print_chat_completion_results(result)

# Validate all results
ModelInferenceTestBase._validate_chat_completion_results(result)

# Validate that additional query parameters exists in the connection URL, if specify
if query_params is not None:
ModelInferenceTestBase._validate_query_parameters(query_params, self.connection_url)

def _do_chat_completion_with_error(
self,
options: sdk.models.ChatCompletionsOptions,
expected_status_code: int,
expected_message_contains: str,
**kwargs,
):

try:
result = self.client.get_chat_completions(options=options)

except AzureError as e:
print(e)
assert hasattr(e, "status_code")
assert e.status_code == expected_status_code
assert expected_message_contains in e.message
return
assert False # We should not get here

async def _do_async_chat_completion_with_error(
self,
options: sdk.models.ChatCompletionsOptions,
expected_status_code: int,
expected_message_contains: str,
**kwargs,
):

try:
result = await self.async_client.get_chat_completions(options=options)

except AzureError as e:
print(e)
assert hasattr(e, "status_code")
assert e.status_code == expected_status_code
assert expected_message_contains in e.message
return
assert False # We should not get here

@staticmethod
def _validate_query_parameters(query_params: dict, connection_url: str):
assert len(query_params) > 0
query_string = ""
for key, value in query_params.items():
query_string += "&" + key + "=" + value
query_string = "?" + query_string[1:]
assert query_string in connection_url

@staticmethod
def _validate_result(result: sdk.models.ChatCompletions):
assert True

@staticmethod
def _print_analysis_results(result: sdk.models.ChatCompletions):

for choice in result.choices:
print(" choices[0].message.content: {}".format(choice.message.content))
print(" choices[0].message.role: {}".format(choice.message.role))
print(" choices[0].finish_reason: {}".format(choice.finish_reason))
print(" choices[0].index: {}".format(choice.index))

print(" id: {}".format(result.id))
print(" created: {}".format(result.created))
print(" model: {}".format(result.model))
print(" object: {}".format(result.object))
print(" usage.completion_tokens: {}".format(result.usage.completion_tokens))
print(" usage.prompt_tokens: {}".format(result.usage.prompt_tokens))
print(" usage.completion_tokens: {}".format(result.usage.completion_tokens))

Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# ------------------------------------
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
# ------------------------------------
import inspect
import azure.ai.vision.imageanalysis as sdk

from model_inference_test_base import ModelInferenceTestBase, ServicePreparer
from devtools_testutils.aio import recorded_by_proxy_async

# The test class name needs to start with "Test" to get collected by pytest
class TestImageAnalysisAsyncClient(ModelInferenceTestBase):

# **********************************************************************************
#
# HAPPY PATH TESTS
#
# **********************************************************************************

# Test all visual features from a local image, using default settings
@ServicePreparer()
@recorded_by_proxy_async
async def test_async_chat_completion(self, **kwargs):

self._create_client_for_standard_analysis(sync=False, **kwargs)

await self._do_async_chat_completions(
options=[
messages=[
role=sdk.models.ChatRole.USER,
content="How many feet are in a mile?"
]
],
**kwargs
)

await self.async_client.close()

# Test some visual features, one after the other, from image URL, with relevant settings specified
""" @ServicePreparer()
@recorded_by_proxy_async
async def test_analyze_async_single_feature_from_url(self, **kwargs):

self._create_client_for_standard_analysis(sync=False, **kwargs)

await self._do_async_analysis(
image_source=self.IMAGE_URL,
visual_features=[sdk.models.VisualFeatures.DENSE_CAPTIONS],
gender_neutral_caption=True,
**kwargs
)

await self._do_async_analysis(
image_source=self.IMAGE_URL,
visual_features=[sdk.models.VisualFeatures.SMART_CROPS],
smart_crops_aspect_ratios=[0.9, 1.33],
**kwargs
)

await self._do_async_analysis(
image_source=self.IMAGE_URL, visual_features=[sdk.models.VisualFeatures.TAGS], language="en", **kwargs
)

await self._do_async_analysis(
image_source=self.IMAGE_URL, visual_features=[sdk.models.VisualFeatures.PEOPLE], **kwargs
)

await self.async_client.close() """

# **********************************************************************************
#
# ERROR TESTS
#
# **********************************************************************************

""" @ServicePreparer()
@recorded_by_proxy_async
async def test_analyze_async_authentication_failure(self, **kwargs):

self._create_client_for_authentication_failure(sync=False, **kwargs)

await self._do_async_analysis_with_error(
image_source=self.IMAGE_URL,
visual_features=[sdk.models.VisualFeatures.TAGS],
expected_status_code=401,
expected_message_contains="Access denied",
**kwargs
)

await self.async_client.close() """
Loading