Skip to content

Commit aa2cbd4

Browse files
authored
sample tests recordings (#44303)
code interpreter and file search sample recordings
1 parent 6a79bf9 commit aa2cbd4

12 files changed

+90
-88
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
* Added OpenAPI with Project Connection sample. See `sample_agent_openapi_with_project_connection.py`.
3131
* Added SharePoint grounding tool sample. See `sample_agent_sharepoint.py`.
3232
* Improved MCP client sample showing direct MCP tool invocation. See `samples/mcp_client/sample_mcp_tool_async.py`.
33+
* Samples that download generated files (code interpreter and image generation) now save files to the system temp directory instead of the current working directory. See `sample_agent_code_interpreter.py`, `sample_agent_code_interpreter_async.py`, `sample_agent_image_generation.py`, and `sample_agent_image_generation_async.py`.
3334

3435
## 2.0.0b2 (2025-11-14)
3536

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -269,11 +269,10 @@ After calling `responses.create()`, you can download file using the returned res
269269

270270
```python
271271
image_data = [output.result for output in response.output if output.type == "image_generation_call"]
272-
273272
if image_data and image_data[0]:
274273
print("Downloading generated image...")
275274
filename = "microsoft.png"
276-
file_path = os.path.abspath(filename)
275+
file_path = os.path.join(tempfile.gettempdir(), filename)
277276

278277
with open(file_path, "wb") as f:
279278
f.write(base64.b64decode(image_data[0]))

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_4160165ae8"
5+
"Tag": "python/ai/azure-ai-projects_670570275d"
66
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Force LF line endings for test files to ensure consistent binary representation
2+
# across Windows and Linux platforms.
3+
#
4+
# These files are read and sent as binary REST API request payloads in tests.
5+
# Without consistent line endings, the binary content differs between platforms,
6+
# causing recorded test traffic to be inconsistent and test playback to fail.
7+
#
8+
# By enforcing LF endings, the binary representation remains identical regardless
9+
# of the platform where tests are executed.
10+
11+
*.md text eol=lf
12+
*.csv text eol=lf
13+
*.jsonl text eol=lf

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

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
"""
2525

2626
import os
27-
import httpx
27+
import tempfile
2828
from dotenv import load_dotenv
2929
from azure.identity import DefaultAzureCredential
3030
from azure.ai.projects import AIProjectClient
@@ -84,31 +84,31 @@
8484

8585
# Get the last message which should contain file citations
8686
last_message = response.output[-1] # ResponseOutputMessage
87-
if last_message.type == "message":
88-
# Get the last content item (contains the file annotations)
89-
text_content = last_message.content[-1] # ResponseOutputText
90-
if text_content.type == "output_text":
91-
# Get the last annotation (most recent file)
92-
if text_content.annotations:
93-
file_citation = text_content.annotations[-1] # AnnotationContainerFileCitation
94-
if file_citation.type == "container_file_citation":
95-
file_id = file_citation.file_id
96-
filename = file_citation.filename
97-
container_id = file_citation.container_id
98-
print(f"Found generated file: {filename} (ID: {file_id})")
87+
if (
88+
last_message.type == "message"
89+
and last_message.content
90+
and last_message.content[-1].type == "output_text"
91+
and last_message.content[-1].annotations
92+
):
93+
file_citation = last_message.content[-1].annotations[-1] # AnnotationContainerFileCitation
94+
if file_citation.type == "container_file_citation":
95+
file_id = file_citation.file_id
96+
filename = file_citation.filename
97+
container_id = file_citation.container_id
98+
print(f"Found generated file: {filename} (ID: {file_id})")
99+
100+
print("\nCleaning up...")
101+
project_client.agents.delete_version(agent_name=agent.name, agent_version=agent.version)
102+
print("Agent deleted")
99103

100104
# Download the generated file if available
101105
if file_id and filename:
102106
file_content = openai_client.containers.files.content.retrieve(file_id=file_id, container_id=container_id)
103107
print(f"File ready for download: {filename}")
104-
with open(filename, "wb") as f:
108+
file_path = os.path.join(tempfile.gettempdir(), filename)
109+
with open(file_path, "wb") as f:
105110
f.write(file_content.read())
106-
107111
# Print result (should contain "file")
108-
print(f"==> Result: file, {filename} downloaded successfully.")
112+
print(f"==> Result: file, {file_path} downloaded successfully.")
109113
else:
110114
print("No file generated in response")
111-
112-
print("\nCleaning up...")
113-
project_client.agents.delete_version(agent_name=agent.name, agent_version=agent.version)
114-
print("Agent deleted")

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

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
"""
2525

2626
import os
27+
import tempfile
2728
import asyncio
2829
from dotenv import load_dotenv
2930
from azure.identity.aio import DefaultAzureCredential
@@ -85,37 +86,37 @@ async def main() -> None:
8586

8687
# Get the last message which should contain file citations
8788
last_message = response.output[-1] # ResponseOutputMessage
88-
if last_message.type == "message":
89-
# Get the last content item (contains the file annotations)
90-
text_content = last_message.content[-1] # ResponseOutputText
91-
if text_content.type == "output_text":
92-
# Get the last annotation (most recent file)
93-
if text_content.annotations:
94-
file_citation = text_content.annotations[-1] # AnnotationContainerFileCitation
95-
if file_citation.type == "container_file_citation":
96-
file_id = file_citation.file_id
97-
filename = file_citation.filename
98-
container_id = file_citation.container_id
99-
print(f"Found generated file: {filename} (ID: {file_id})")
89+
if (
90+
last_message.type == "message"
91+
and last_message.content
92+
and last_message.content[-1].type == "output_text"
93+
and last_message.content[-1].annotations
94+
):
95+
file_citation = last_message.content[-1].annotations[-1] # AnnotationContainerFileCitation
96+
if file_citation.type == "container_file_citation":
97+
file_id = file_citation.file_id
98+
filename = file_citation.filename
99+
container_id = file_citation.container_id
100+
print(f"Found generated file: {filename} (ID: {file_id})")
101+
102+
print("\nCleaning up...")
103+
await project_client.agents.delete_version(agent_name=agent.name, agent_version=agent.version)
104+
print("Agent deleted")
100105

101106
# Download the generated file if available
102107
if file_id and filename:
103108
file_content = await openai_client.containers.files.content.retrieve(
104109
file_id=file_id, container_id=container_id
105110
)
106111
print(f"File ready for download: {filename}")
107-
with open(filename, "wb") as f:
112+
file_path = os.path.join(tempfile.gettempdir(), filename)
113+
with open(file_path, "wb") as f:
108114
f.write(file_content.read())
109-
110115
# Print result (should contain "file")
111-
print(f"==> Result: file, {filename} downloaded successfully.")
116+
print(f"==> Result: file, {file_path} downloaded successfully.")
112117
else:
113118
print("No file generated in response")
114119

115-
print("\nCleaning up...")
116-
await project_client.agents.delete_version(agent_name=agent.name, agent_version=agent.version)
117-
print("Agent deleted")
118-
119120
except Exception as e:
120121
print(f"Error occurred: {str(e)}")
121122
raise

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

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040

4141
import base64
4242
import os
43+
import tempfile
4344
from dotenv import load_dotenv
4445

4546
from azure.identity import DefaultAzureCredential
@@ -80,22 +81,20 @@
8081
)
8182
print(f"Response created: {response.id}")
8283

83-
# Save the image to a file
84+
print("\nCleaning up...")
85+
project_client.agents.delete_version(agent_name=agent.name, agent_version=agent.version)
86+
print("Agent deleted")
87+
8488
# [START download_image]
8589
image_data = [output.result for output in response.output if output.type == "image_generation_call"]
86-
8790
if image_data and image_data[0]:
8891
print("Downloading generated image...")
8992
filename = "microsoft.png"
90-
file_path = os.path.abspath(filename)
93+
file_path = os.path.join(tempfile.gettempdir(), filename)
9194

9295
with open(file_path, "wb") as f:
9396
f.write(base64.b64decode(image_data[0]))
94-
# [END download_image]
9597

98+
# [END download_image]
9699
# Print result (should contain "file")
97100
print(f"==> Result: Image downloaded and saved to file: {file_path}")
98-
99-
print("\nCleaning up...")
100-
project_client.agents.delete_version(agent_name=agent.name, agent_version=agent.version)
101-
print("Agent deleted")

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import asyncio
4141
import base64
4242
import os
43+
import tempfile
4344
from dotenv import load_dotenv
4445

4546
from azure.identity.aio import DefaultAzureCredential
@@ -76,24 +77,23 @@ async def main():
7677
)
7778
print(f"Response created: {response.id}")
7879

80+
print("\nCleaning up...")
81+
await project_client.agents.delete_version(agent_name=agent.name, agent_version=agent.version)
82+
print("Agent deleted")
83+
7984
# Save the image to a file
8085
image_data = [output.result for output in response.output if output.type == "image_generation_call"]
81-
8286
if image_data and image_data[0]:
8387
print("Downloading generated image...")
8488
filename = "microsoft.png"
85-
file_path = os.path.abspath(filename)
89+
file_path = os.path.join(tempfile.gettempdir(), filename)
8690

8791
with open(file_path, "wb") as f:
8892
f.write(base64.b64decode(image_data[0]))
8993

9094
# Print result (should contain "file")
9195
print(f"==> Result: Image downloaded and saved to file: {file_path}")
9296

93-
print("\nCleaning up...")
94-
await project_client.agents.delete_version(agent_name=agent.name, agent_version=agent.version)
95-
print("Agent deleted")
96-
9797

9898
if __name__ == "__main__":
9999
asyncio.run(main())

sdk/ai/azure-ai-projects/samples/evaluations/sample_evaluations_score_model_grader_with_image.py

Lines changed: 13 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@
5555
def image_to_data_uri(image_path: str) -> str:
5656
with Image.open(image_path) as img:
5757
buffered = BytesIO()
58-
img.save(buffered, format=img.format or 'PNG')
58+
img.save(buffered, format=img.format or "PNG")
5959
img_str = base64.b64encode(buffered.getvalue()).decode()
6060
mime_type = f"image/{img.format.lower()}" if img.format else "image/png"
6161
return f"data:{mime_type};base64,{img_str}"
@@ -73,14 +73,8 @@ def image_to_data_uri(image_path: str) -> str:
7373
"item_schema": {
7474
"type": "object",
7575
"properties": {
76-
"image_url": {
77-
"type": "string",
78-
"description": "The URL of the image to be evaluated."
79-
},
80-
"caption": {
81-
"type": "string",
82-
"description": "The caption describing the image."
83-
},
76+
"image_url": {"type": "string", "description": "The URL of the image to be evaluated."},
77+
"caption": {"type": "string", "description": "The caption describing the image."},
8478
},
8579
"required": [
8680
"image_url",
@@ -99,22 +93,18 @@ def image_to_data_uri(image_path: str) -> str:
9993
"input": [
10094
{
10195
"role": "system",
102-
"content": "You are an expert grader. Judge how well the model response {{sample.output_text}} describes the image as well as matches the caption {{item.caption}}. Output a score of 1 if it's an excellent match with both. If it's somewhat compatible, output a score around 0.5. Otherwise, give a score of 0."
96+
"content": "You are an expert grader. Judge how well the model response {{sample.output_text}} describes the image as well as matches the caption {{item.caption}}. Output a score of 1 if it's an excellent match with both. If it's somewhat compatible, output a score around 0.5. Otherwise, give a score of 0.",
10397
},
10498
{
10599
"role": "user",
106-
"content":
107-
{
108-
"type": "input_image",
109-
"image_url": "{{item.image_url}}",
110-
"detail": "auto",
111-
}
112-
}
113-
],
114-
"range": [
115-
0.0,
116-
1.0
100+
"content": {
101+
"type": "input_image",
102+
"image_url": "{{item.image_url}}",
103+
"detail": "auto",
104+
},
105+
},
117106
],
107+
"range": [0.0, 1.0],
118108
"pass_threshold": 0.5,
119109
},
120110
]
@@ -163,7 +153,7 @@ def image_to_data_uri(image_path: str) -> str:
163153
type="input_image",
164154
image_url="{{item.image_url}}",
165155
detail="auto",
166-
)
156+
),
167157
),
168158
],
169159
)
@@ -180,7 +170,7 @@ def image_to_data_uri(image_path: str) -> str:
180170
input_messages=input_messages,
181171
sampling_params={
182172
"temperature": 0.8,
183-
}
173+
},
184174
),
185175
)
186176
print(f"Eval Run created (id: {eval_run_object.id}, name: {eval_run_object.name})")

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

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,14 @@
33
# Copyright (c) Microsoft Corporation.
44
# Licensed under the MIT License.
55
# ------------------------------------
6+
7+
# Register MIME types before any other imports to ensure consistent Content-Type detection
8+
# across Windows, macOS, and Linux when uploading files in tests
9+
import mimetypes
10+
11+
mimetypes.add_type("text/csv", ".csv")
12+
mimetypes.add_type("text/markdown", ".md")
13+
614
import os
715
import pytest
816
from dotenv import load_dotenv, find_dotenv
@@ -100,9 +108,6 @@ def sanitize_url_paths():
100108

101109
sanitize_url_paths()
102110

103-
# Normalize Content-Type for CSV files in multipart form-data (varies by OS/Python version)
104-
add_general_string_sanitizer(target="Content-Type: text/csv", value="Content-Type: application/vnd.ms-excel")
105-
106111
# Sanitize API key from service response (this includes Application Insights connection string)
107112
add_body_key_sanitizer(json_path="credentials.key", value="sanitized-api-key")
108113

0 commit comments

Comments
 (0)