Skip to content

Commit e549ce0

Browse files
authored
Updates to Agent image generation tool tests (#44267)
1 parent 548e9cb commit e549ce0

File tree

9 files changed

+157
-40
lines changed

9 files changed

+157
-40
lines changed

sdk/ai/azure-ai-projects/.env.template

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,6 @@ AZURE_AI_PROJECTS_TESTS_AI_SEARCH_PROJECT_CONNECTION_ID=
6565
AZURE_AI_PROJECTS_TESTS_AI_SEARCH_INDEX_NAME=
6666
AZURE_AI_PROJECTS_TESTS_MCP_PROJECT_CONNECTION_ID=
6767

68-
# Used in Image generation agent tools tests
69-
AZURE_AI_PROJECTS_TESTS_IMAGE_MODEL_DEPLOYMENT_NAME=
70-
7168
# Used in Fine-tuning tests
7269
AZURE_AI_PROJECTS_TESTS_COMPLETED_OAI_MODEL_SFT_FINE_TUNING_JOB_ID=
7370
AZURE_AI_PROJECTS_TESTS_COMPLETED_OAI_MODEL_RFT_FINE_TUNING_JOB_ID=

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ Generate images based on text prompts with customizable resolution, quality, and
259259
<!-- SNIPPET:sample_agent_image_generation.tool_declaration -->
260260

261261
```python
262-
tool = ImageGenTool(quality="low", size="1024x1024")
262+
tool = ImageGenTool(model="gpt-image-1-mini", quality="low", size="1024x1024") # type: ignore
263263
```
264264

265265
<!-- END SNIPPET -->

sdk/ai/azure-ai-projects/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-projects",
5-
"Tag": "python/ai/azure-ai-projects_9e7a9707f6"
5+
"Tag": "python/ai/azure-ai-projects_3c34f28cdc"
66
}

sdk/ai/azure-ai-projects/samples/agents/tools/sample_agent_image_generation.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,10 @@
3131
used by the agent for understanding and responding to prompts. This is NOT the image generation model.
3232
3333
NOTE:
34-
- Image generation requires a separate "gpt-image-1" deployment which is specified in the
35-
x-ms-oai-image-generation-deployment header when creating the response.
36-
- AZURE_AI_MODEL_DEPLOYMENT_NAME should be set to your chat model (e.g., gpt-4o), NOT "gpt-image-1".
34+
- Image generation requires a separate "gpt-image-1-mini" deployment which is specified when constructing
35+
the `ImageGenTool`, as well as providing it in the `x-ms-oai-image-generation-deployment` header when
36+
calling `.responses.create`.
37+
- AZURE_AI_MODEL_DEPLOYMENT_NAME should be set to your chat model (e.g., gpt-4o), NOT "gpt-image-1-mini".
3738
- The generated image will be saved as "microsoft.png" in the current directory.
3839
"""
3940

@@ -56,7 +57,7 @@
5657
):
5758

5859
# [START tool_declaration]
59-
tool = ImageGenTool(quality="low", size="1024x1024")
60+
tool = ImageGenTool(model="gpt-image-1-mini", quality="low", size="1024x1024") # type: ignore
6061
# [END tool_declaration]
6162

6263
agent = project_client.agents.create_version(
@@ -73,7 +74,7 @@
7374
response = openai_client.responses.create(
7475
input="Generate an image of Microsoft logo.",
7576
extra_headers={
76-
"x-ms-oai-image-generation-deployment": "gpt-image-1"
77+
"x-ms-oai-image-generation-deployment": "gpt-image-1-mini"
7778
}, # this is required at the moment for image generation
7879
extra_body={"agent": {"name": agent.name, "type": "agent_reference"}},
7980
)

sdk/ai/azure-ai-projects/samples/agents/tools/sample_agent_image_generation_async.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,11 @@
3030
the "Models + endpoints" tab in your Microsoft Foundry project.
3131
3232
NOTE:
33-
- Image generation must have "gpt-image-1" deployment specified in the header when creating response at this moment
34-
- The generated image will be saved as "microsoft.png" in the current directory
33+
- Image generation requires a separate "gpt-image-1-mini" deployment which is specified when constructing
34+
the `ImageGenTool`, as well as providing it in the `x-ms-oai-image-generation-deployment` header when
35+
calling `.responses.create`.
36+
- AZURE_AI_MODEL_DEPLOYMENT_NAME should be set to your chat model (e.g., gpt-4o), NOT "gpt-image-1-mini".
37+
- The generated image will be saved as "microsoft.png" in the current directory.
3538
"""
3639

3740
import asyncio
@@ -58,7 +61,7 @@ async def main():
5861
definition=PromptAgentDefinition(
5962
model=os.environ["AZURE_AI_MODEL_DEPLOYMENT_NAME"],
6063
instructions="Generate images based on user prompts",
61-
tools=[ImageGenTool(quality="low", size="1024x1024")],
64+
tools=[ImageGenTool(model="gpt-image-1-mini", quality="low", size="1024x1024")], # type: ignore
6265
),
6366
description="Agent for image generation.",
6467
)
@@ -67,7 +70,7 @@ async def main():
6770
response = await openai_client.responses.create(
6871
input="Generate an image of Microsoft logo.",
6972
extra_headers={
70-
"x-ms-oai-image-generation-deployment": "gpt-image-1"
73+
"x-ms-oai-image-generation-deployment": "gpt-image-1-mini"
7174
}, # this is required at the moment for image generation
7275
extra_body={"agent": {"name": agent.name, "type": "agent_reference"}},
7376
)

sdk/ai/azure-ai-projects/tests/agents/test_agents_crud.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313

1414
class TestAgentCrud(TestBase):
1515

16+
# To run this test:
17+
# pytest tests\agents\test_agents_crud.py::TestAgentCrud::test_agents_crud -s
1618
@servicePreparer()
1719
@recorded_by_proxy()
1820
def test_agents_crud(self, **kwargs):

sdk/ai/azure-ai-projects/tests/agents/tools/test_agent_image_generation.py

Lines changed: 18 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,15 @@
99
import base64
1010
import pytest
1111
from test_base import TestBase, servicePreparer
12-
from devtools_testutils import is_live_and_not_recording
12+
from devtools_testutils import recorded_by_proxy, RecordedTransport
1313
from azure.ai.projects.models import PromptAgentDefinition, ImageGenTool
1414
from azure.core.exceptions import ResourceNotFoundError
1515

1616

1717
class TestAgentImageGeneration(TestBase):
1818

1919
@servicePreparer()
20-
@pytest.mark.skipif(
21-
condition=(not is_live_and_not_recording()),
22-
reason="Skipped because we cannot record network calls with OpenAI client",
23-
)
20+
@recorded_by_proxy(RecordedTransport.AZURE_CORE, RecordedTransport.HTTPX)
2421
def test_agent_image_generation(self, **kwargs):
2522
"""
2623
Test agent with Image Generation tool.
@@ -44,57 +41,49 @@ def test_agent_image_generation(self, **kwargs):
4441
DELETE /agents/{agent_name}/versions/{agent_version} project_client.agents.delete_version()
4542
"""
4643

47-
# Get the image model deployment name from environment variable
48-
image_model_deployment = os.environ.get(
49-
"AZURE_AI_PROJECTS_TESTS_IMAGE_MODEL_DEPLOYMENT_NAME", "gpt-image-1-mini"
50-
)
51-
5244
model = self.test_agents_params["model_deployment_name"]
45+
image_model = self.test_agents_tools_params["image_generation_model_deployment_name"]
46+
agent_name = "image-gen-agent"
5347

5448
with (
5549
self.create_client(operation_group="agents", **kwargs) as project_client,
5650
project_client.get_openai_client() as openai_client,
5751
):
5852
# Check if the image model deployment exists in the project
5953
try:
60-
deployment = project_client.deployments.get(image_model_deployment)
54+
deployment = project_client.deployments.get(image_model)
6155
print(f"Image model deployment found: {deployment.name}")
6256
except ResourceNotFoundError:
63-
pytest.skip(f"Image generation model '{image_model_deployment}' not available in this project")
57+
pytest.fail(f"Image generation model '{image_model}' not available in this project")
6458
except Exception as e:
65-
pytest.skip(f"Unable to verify image model deployment: {e}")
59+
pytest.fail(f"Unable to verify image model deployment: {e}")
6660

6761
# Disable retries for faster failure when service returns 500
6862
openai_client.max_retries = 0
6963

7064
# Create agent with image generation tool
7165
agent = project_client.agents.create_version(
72-
agent_name="image-gen-agent",
66+
agent_name=agent_name,
7367
definition=PromptAgentDefinition(
7468
model=model,
7569
instructions="Generate images based on user prompts",
76-
tools=[ImageGenTool(quality="low", size="1024x1024")],
70+
tools=[ImageGenTool(model=image_model, quality="low", size="1024x1024")], # type: ignore
7771
),
7872
description="Agent for testing image generation.",
7973
)
80-
print(f"Agent created (id: {agent.id}, name: {agent.name}, version: {agent.version})")
81-
assert agent.id is not None
82-
assert agent.name == "image-gen-agent"
83-
assert agent.version is not None
74+
self._validate_agent_version(agent, expected_name=agent_name)
8475

8576
# Request image generation
8677
print("\nAsking agent to generate an image of a simple geometric shape...")
8778

8879
response = openai_client.responses.create(
8980
input="Generate an image of a blue circle on a white background.",
90-
extra_headers={
91-
"x-ms-oai-image-generation-deployment": image_model_deployment
92-
}, # Required for image generation
81+
extra_headers={"x-ms-oai-image-generation-deployment": image_model}, # Required for image generation
9382
extra_body={"agent": {"name": agent.name, "type": "agent_reference"}},
9483
)
9584

9685
print(f"Response created (id: {response.id})")
97-
assert response.id is not None
86+
assert response.id
9887
assert response.output is not None
9988
assert len(response.output) > 0
10089

@@ -127,6 +116,12 @@ def test_agent_image_generation(self, **kwargs):
127116

128117
print("\n✓ Agent successfully generated and returned a valid image")
129118

119+
# Save the image to a file in the .assets directory (which is .gitignored)
120+
os.makedirs(".assets", exist_ok=True)
121+
with open(".assets/generated_image_sync.png", "wb") as f:
122+
f.write(image_bytes)
123+
print("✓ Image saved to .assets/generated_image_sync.png")
124+
130125
# Teardown
131126
project_client.agents.delete_version(agent_name=agent.name, agent_version=agent.version)
132127
print("Agent deleted")
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
# pylint: disable=too-many-lines,line-too-long,useless-suppression
2+
# ------------------------------------
3+
# Copyright (c) Microsoft Corporation.
4+
# Licensed under the MIT License.
5+
# ------------------------------------
6+
# cSpell:disable
7+
8+
import os
9+
import base64
10+
import pytest
11+
from test_base import TestBase, servicePreparer
12+
from devtools_testutils.aio import recorded_by_proxy_async
13+
from devtools_testutils import RecordedTransport
14+
from azure.ai.projects.models import PromptAgentDefinition, ImageGenTool
15+
from azure.core.exceptions import ResourceNotFoundError
16+
17+
18+
class TestAgentImageGenerationAsync(TestBase):
19+
20+
@servicePreparer()
21+
@recorded_by_proxy_async(RecordedTransport.AZURE_CORE, RecordedTransport.HTTPX)
22+
async def test_agent_image_generation_async(self, **kwargs):
23+
24+
model = self.test_agents_params["model_deployment_name"]
25+
image_model = self.test_agents_tools_params["image_generation_model_deployment_name"]
26+
agent_name = "image-gen-agent"
27+
28+
async with (
29+
self.create_async_client(operation_group="agents", **kwargs) as project_client,
30+
project_client.get_openai_client() as openai_client,
31+
):
32+
# Check if the image model deployment exists in the project
33+
try:
34+
deployment = await project_client.deployments.get(image_model)
35+
print(f"Image model deployment found: {deployment.name}")
36+
except ResourceNotFoundError:
37+
pytest.fail(f"Image generation model '{image_model}' not available in this project")
38+
except Exception as e:
39+
pytest.fail(f"Unable to verify image model deployment: {e}")
40+
41+
# Disable retries for faster failure when service returns 500
42+
openai_client.max_retries = 0
43+
44+
# Create agent with image generation tool
45+
agent = await project_client.agents.create_version(
46+
agent_name=agent_name,
47+
definition=PromptAgentDefinition(
48+
model=model,
49+
instructions="Generate images based on user prompts",
50+
tools=[ImageGenTool(model=image_model, quality="low", size="1024x1024")], # type: ignore
51+
),
52+
description="Agent for testing image generation.",
53+
)
54+
print(f"Agent created (id: {agent.id}, name: {agent.name}, version: {agent.version})")
55+
self._validate_agent_version(agent, expected_name=agent_name)
56+
57+
# Request image generation
58+
print("\nAsking agent to generate an image of a simple geometric shape...")
59+
60+
response = await openai_client.responses.create(
61+
input="Generate an image of a blue circle on a white background.",
62+
extra_headers={"x-ms-oai-image-generation-deployment": image_model}, # Required for image generation
63+
extra_body={"agent": {"name": agent.name, "type": "agent_reference"}},
64+
)
65+
66+
print(f"Response created (id: {response.id})")
67+
assert response.id
68+
assert response.output is not None
69+
assert len(response.output) > 0
70+
71+
# Extract image data from response
72+
image_data = [output.result for output in response.output if output.type == "image_generation_call"]
73+
74+
# Verify image was generated
75+
assert len(image_data) > 0, "Expected at least one image to be generated"
76+
assert image_data[0], "Expected image data to be non-empty"
77+
78+
print(f"✓ Image data received ({len(image_data[0])} base64 characters)")
79+
80+
# Decode the base64 image
81+
image_bytes = b""
82+
try:
83+
image_bytes = base64.b64decode(image_data[0])
84+
assert len(image_bytes) > 0, "Decoded image should have content"
85+
print(f"✓ Image decoded successfully ({len(image_bytes)} bytes)")
86+
except Exception as e:
87+
pytest.fail(f"Failed to decode base64 image data: {e}")
88+
89+
# Verify it's a PNG image (check magic bytes)
90+
# PNG files start with: 89 50 4E 47 (‰PNG)
91+
assert image_bytes[:4] == b"\x89PNG", "Image does not appear to be a valid PNG"
92+
print("✓ Image is a valid PNG")
93+
94+
# Verify reasonable image size (should be > 1KB for a 1024x1024 image)
95+
assert len(image_bytes) > 1024, f"Image seems too small ({len(image_bytes)} bytes)"
96+
print(f"✓ Image size is reasonable ({len(image_bytes):,} bytes)")
97+
98+
print("\n✓ Agent successfully generated and returned a valid image")
99+
100+
# Save the image to a file in the .assets directory (which is .gitignored)
101+
os.makedirs(".assets", exist_ok=True)
102+
with open(".assets/generated_image_async.png", "wb") as f:
103+
f.write(image_bytes)
104+
print("✓ Image saved to .assets/generated_image_async.png")
105+
106+
# Teardown
107+
await project_client.agents.delete_version(agent_name=agent.name, agent_version=agent.version)
108+
print("Agent deleted")

sdk/ai/azure-ai-projects/tests/test_base.py

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@
6666
azure_ai_projects_tests_ai_search_project_connection_id="/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/sanitized-resource-group/providers/Microsoft.CognitiveServices/accounts/sanitized-account/projects/sanitized-project/connections/sanitized-ai-search-connection",
6767
azure_ai_projects_tests_ai_search_index_name="sanitized-index-name",
6868
azure_ai_projects_tests_mcp_project_connection_id="/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/sanitized-resource-group/providers/Microsoft.CognitiveServices/accounts/sanitized-account/projects/sanitized-project/connections/sanitized-mcp-connection",
69-
azure_ai_projects_tests_image_model_deployment_name="gpt-image-1-mini",
7069
)
7170

7271
# Fine-tuning job type constants
@@ -105,6 +104,10 @@ class TestBase(AzureRecordedTestCase):
105104
"agent_name": "agent-for-python-projects-sdk-testing",
106105
}
107106

107+
test_agents_tools_params = {
108+
"image_generation_model_deployment_name": "gpt-image-1-mini",
109+
}
110+
108111
test_inference_params = {
109112
"connection_name_api_key_auth": "connection1",
110113
"connection_name_entra_id_auth": "connection2",
@@ -386,23 +389,31 @@ def _validate_agent_version(
386389
) -> None:
387390
assert agent is not None
388391
assert isinstance(agent, AgentVersionDetails)
389-
assert agent.id is not None
392+
assert agent.id
390393
if expected_name:
391394
assert agent.name == expected_name
395+
else:
396+
assert agent.name
392397
if expected_version:
393398
assert agent.version == expected_version
399+
else:
400+
assert agent.version
394401
print(f"Agent version validated (id: {agent.id}, name: {agent.name}, version: {agent.version})")
395402

396403
def _validate_agent(
397404
self, agent: AgentDetails, expected_name: Optional[str] = None, expected_latest_version: Optional[str] = None
398405
) -> None:
399406
assert agent is not None
400407
assert isinstance(agent, AgentDetails)
401-
assert agent.id is not None
408+
assert agent.id
402409
if expected_name:
403410
assert agent.name == expected_name
411+
else:
412+
assert agent.name
404413
if expected_latest_version:
405414
assert agent.versions.latest.version == expected_latest_version
415+
else:
416+
assert agent.versions.latest.version
406417
print(f"Agent validated (id: {agent.id}, name: {agent.name}, latest version: {agent.versions.latest.version})")
407418

408419
def _validate_conversation_item(

0 commit comments

Comments
 (0)