Skip to content

Commit 15b6023

Browse files
authored
Merge branch 'Azure-Samples:main' into main
2 parents ed34bb5 + ed26ba5 commit 15b6023

File tree

40 files changed

+3315
-73
lines changed

40 files changed

+3315
-73
lines changed

.github/scripts/build_agent_setup_bicep.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import os
12
import sys
23
from pathlib import Path
34
from azure.cli.core import get_default_cli
@@ -26,6 +27,10 @@ def build_bicep_file(bicep_file: Path) -> None:
2627
output_file = bicep_file.with_name("azuredeploy.json")
2728

2829
print(f"🔹 Building Bicep: {bicep_file} -> {output_file}")
30+
os.environ.update({"AZURE_BICEP_USE_BINARY_FROM_PATH": "false", "AZURE_BICEP_CHECK_VERSION": "false"})
31+
32+
# Pin the bicep CLI to minimize pre-commit failures due to modified metadata in files.
33+
run_az_command("bicep", "install", "--version", "v0.33.93")
2934

3035
# Run az bicep build using Azure CLI SDK
3136
run_az_command("bicep", "build", "--file", str(bicep_file), "--outfile", str(output_file))

.pre-commit-config.yaml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,10 @@ repos:
4343
- id: bicep-build
4444
name: Regenerate azuredeploy.json for Agent samples
4545
description: "Automatically build Bicep files into azuredeploy.json before commit"
46-
entry: python .github/scripts/build_agent_setup_bicep.py
4746
types: [text]
4847
files: ^scenarios/Agents/setup/.*\.bicep$
49-
language: python
5048
require_serial: true
5149
pass_filenames: true
52-
additional_dependencies:
53-
- azure-cli
50+
entry: python
51+
language: system
52+
args: ["-m", "tox", "-qqq", "run", "-e", "build-agent-bicep", "--"]

pyproject.toml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,6 @@ extend-select = [
1818
"ANN",
1919
"RUF",
2020
]
21-
ignore = [
22-
"ANN101", # missing-type-self: This can be inferred and will be deprecated by ruff
23-
]
2421

2522
[tool.ruff.lint.extend-per-file-ignores]
2623
"*.ipynb" = [
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
#nullable disable
5+
6+
using System;
7+
using System.Collections.Generic;
8+
using System.IO;
9+
using System.Threading.Tasks;
10+
using Azure.Core.TestFramework;
11+
using NUnit.Framework;
12+
13+
namespace Azure.AI.Projects.Tests;
14+
15+
public partial class Sample_Agent_FileSearch : SamplesBase<AIProjectsTestEnvironment>
16+
{
17+
[Test]
18+
public async Task FilesSearchExample()
19+
{
20+
var connectionString = TestEnvironment.AzureAICONNECTIONSTRING;
21+
AgentsClient client = new AgentsClient(connectionString, new DefaultAzureCredential());
22+
23+
#region Snippet:UploadAgentFilesToUse
24+
// Upload a file and wait for it to be processed
25+
File.WriteAllText(
26+
path: "sample_file_for_upload.txt",
27+
contents: "The word 'apple' uses the code 442345, while the word 'banana' uses the code 673457.");
28+
Response<AgentFile> uploadAgentFileResponse = await client.UploadFileAsync(
29+
filePath: "sample_file_for_upload.txt",
30+
purpose: AgentFilePurpose.Agents);
31+
32+
AgentFile uploadedAgentFile = uploadAgentFileResponse.Value;
33+
#endregion
34+
35+
#region Snippet:CreateVectorStore
36+
// Create a vector store with the file and wait for it to be processed.
37+
// If you do not specify a vector store, create_message will create a vector store with a default expiration policy of seven days after they were last active
38+
VectorStore vectorStore = await client.CreateVectorStoreAsync(
39+
fileIds: new List<string> { uploadedAgentFile.Id },
40+
name: "my_vector_store");
41+
#endregion
42+
43+
#region Snippet:CreateAgentWithFiles
44+
FileSearchToolResource fileSearchToolResource = new FileSearchToolResource();
45+
fileSearchToolResource.VectorStoreIds.Add(vectorStore.Id);
46+
47+
// Create an agent with toolResources and process assistant run
48+
Response<Agent> agentResponse = await client.CreateAgentAsync(
49+
model: "gpt-4-1106-preview",
50+
name: "SDK Test Agent - Retrieval",
51+
instructions: "You are a helpful agent that can help fetch data from files you know about.",
52+
tools: new List<ToolDefinition> { new FileSearchToolDefinition() },
53+
toolResources: new ToolResources() { FileSearch = fileSearchToolResource });
54+
Agent agent = agentResponse.Value;
55+
#endregion
56+
57+
// Create thread for communication
58+
Response<AgentThread> threadResponse = await client.CreateThreadAsync();
59+
AgentThread thread = threadResponse.Value;
60+
61+
// Create message to thread
62+
Response<ThreadMessage> messageResponse = await client.CreateMessageAsync(
63+
thread.Id,
64+
MessageRole.User,
65+
"Can you give me the documented codes for 'banana' and 'orange'?");
66+
ThreadMessage message = messageResponse.Value;
67+
68+
// Run the agent
69+
Response<ThreadRun> runResponse = await client.CreateRunAsync(thread, agent);
70+
71+
do
72+
{
73+
await Task.Delay(TimeSpan.FromMilliseconds(500));
74+
runResponse = await client.GetRunAsync(thread.Id, runResponse.Value.Id);
75+
}
76+
while (runResponse.Value.Status == RunStatus.Queued
77+
|| runResponse.Value.Status == RunStatus.InProgress);
78+
79+
Response<PageableList<ThreadMessage>> afterRunMessagesResponse
80+
= await client.GetMessagesAsync(thread.Id);
81+
IReadOnlyList<ThreadMessage> messages = afterRunMessagesResponse.Value.Data;
82+
83+
// Note: messages iterate from newest to oldest, with the messages[0] being the most recent
84+
foreach (ThreadMessage threadMessage in messages)
85+
{
86+
Console.Write($"{threadMessage.CreatedAt:yyyy-MM-dd HH:mm:ss} - {threadMessage.Role,10}: ");
87+
foreach (MessageContent contentItem in threadMessage.ContentItems)
88+
{
89+
if (contentItem is MessageTextContent textItem)
90+
{
91+
Console.Write(textItem.Text);
92+
}
93+
else if (contentItem is MessageImageFileContent imageFileItem)
94+
{
95+
Console.Write($"<image from ID: {imageFileItem.FileId}");
96+
}
97+
Console.WriteLine();
98+
}
99+
}
100+
}
101+
}
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
# ------------------------------------
2+
# Copyright (c) Microsoft Corporation.
3+
# Licensed under the MIT License.
4+
# ------------------------------------
5+
6+
"""
7+
DESCRIPTION:
8+
This sample demonstrates how to use agent operations with file searching from
9+
the Azure Agents service using a synchronous client.
10+
11+
USAGE:
12+
python sample_agents_file_search.py
13+
14+
Before running the sample:
15+
16+
pip install azure-ai-projects azure-identity
17+
18+
Set these environment variables with your own values:
19+
1) PROJECT_CONNECTION_STRING - The project connection string, as found in the overview page of your
20+
Azure AI Foundry project.
21+
2) MODEL_DEPLOYMENT_NAME - The deployment name of the AI model, as found under the "Name" column in
22+
the "Models + endpoints" tab in your Azure AI Foundry project.
23+
"""
24+
25+
import os
26+
from azure.ai.projects import AIProjectClient
27+
from azure.ai.projects.models import (
28+
FileSearchTool,
29+
)
30+
from azure.identity import DefaultAzureCredential
31+
32+
33+
project_client = AIProjectClient.from_connection_string(
34+
credential=DefaultAzureCredential(), conn_str=os.environ["PROJECT_CONNECTION_STRING"]
35+
)
36+
37+
with project_client:
38+
# Upload file and create vector store
39+
# [START upload_file_create_vector_store_and_agent_with_file_search_tool]
40+
file = project_client.agents.upload_file_and_poll(file_path="product_info_1.md", purpose="assistants")
41+
print(f"Uploaded file, file ID: {file.id}")
42+
43+
vector_store = project_client.agents.create_vector_store_and_poll(file_ids=[file.id], name="my_vectorstore")
44+
print(f"Created vector store, vector store ID: {vector_store.id}")
45+
46+
# Create file search tool with resources followed by creating agent
47+
file_search = FileSearchTool(vector_store_ids=[vector_store.id])
48+
49+
agent = project_client.agents.create_agent(
50+
model="gpt-4o-mini",
51+
name="my-assistant",
52+
instructions="Hello, you are helpful assistant and can search information from uploaded files",
53+
tools=file_search.definitions,
54+
tool_resources=file_search.resources,
55+
)
56+
# [END upload_file_create_vector_store_and_agent_with_file_search_tool]
57+
58+
print(f"Created agent, ID: {agent.id}")
59+
60+
# Create thread for communication
61+
thread = project_client.agents.create_thread()
62+
print(f"Created thread, ID: {thread.id}")
63+
64+
# Create message to thread
65+
message = project_client.agents.create_message(
66+
thread_id=thread.id, role="user", content="Hello, what Contoso products do you know?"
67+
)
68+
print(f"Created message, ID: {message.id}")
69+
70+
# Create and process assistant run in thread with tools
71+
run = project_client.agents.create_and_process_run(thread_id=thread.id, agent_id=agent.id)
72+
print(f"Run finished with status: {run.status}")
73+
74+
if run.status == "failed":
75+
# Check if you got "Rate limit is exceeded.", then you want to get more quota
76+
print(f"Run failed: {run.last_error}")
77+
78+
# [START teardown]
79+
# Delete the file when done
80+
project_client.agents.delete_vector_store(vector_store.id)
81+
print("Deleted vector store")
82+
83+
project_client.agents.delete_file(file_id=file.id)
84+
print("Deleted file")
85+
86+
# Delete the agent when done
87+
project_client.agents.delete_agent(agent.id)
88+
print("Deleted agent")
89+
# [END teardown]
90+
91+
# Fetch and log all messages
92+
messages = project_client.agents.list_messages(thread_id=thread.id)
93+
94+
# Print messages from the thread
95+
for text_message in messages.text_messages:
96+
print(text_message)
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# File Search
2+
3+
File Search augments the Agent with knowledge from outside its model, such as proprietary product information or documents provided by your users.
4+
5+
To access your files, the file search tool uses the vector store object. Upload your files and create a vector store to contain them. Once the vector store is created, you should poll its status until all files are out of the in_progress state to ensure that all content has finished processing. The SDK provides helpers for uploading and polling.
6+
7+
### File Sources
8+
- Uploading local files
9+
- [Coming Soon] Azure Blob Storage
10+
11+
### Basic Agent Setup <br>
12+
The File Search tool has the same functionality as AOAI Assistants. Microsoft managed search and storage resources are used.
13+
- Uploaded files get stored in Microsoft managed storage
14+
- A vector store is created using a Microsoft managed search resource
15+
16+
### Standard Agent Setup
17+
The File Search tool uses the Azure AI Search and Azure Blob Storage resources you connected during agent setup.
18+
- Uploaded files get stored in your connected Azure Blob Storage account
19+
- Vector stores get created using your connected Azure AI Seach resource
20+
<br> </br>
21+
22+
For both Agent setups, OpenAI handles the entire ingestion process, including automatically parsing and chunking documents, generating and storing embeddings, and utilizing both vector and keyword searches to retrieve relevant content for user queries.
23+
24+
There is no difference in the code between the two setups; the only variation is in where your files and created vector stores are stored.
25+
26+
## Examples
27+
28+
Run the code samples below and view the output.
29+
30+
>[!NOTE]
31+
> Be sure that you've [installed the SDK](../../quickstart.md#install-the-sdk-package) for your language.
32+
33+
* [Python](./python-file-search.py)
34+
* [C#](./FileSearch.cs)
35+
36+
## Additional samples
37+
38+
* [Python Quart app](https://github.com/Azure-Samples/azureai-assistant-tool/tree/main/samples/FileSearch)
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
# ------------------------------------
2+
# Copyright (c) Microsoft Corporation.
3+
# Licensed under the MIT License.
4+
# ------------------------------------
5+
6+
"""
7+
FILE: sample_agents_basics_async_with_azure_monitor_tracing.py
8+
9+
DESCRIPTION:
10+
This sample demonstrates how to use basic agent operations from
11+
the Azure Agents service using a asynchronous client with Azure Monitor tracing.
12+
View the results in the "Tracing" tab in your Azure AI Studio project page.
13+
14+
USAGE:
15+
python sample_agents_basics_async_with_azure_monitor_tracing.py
16+
17+
Before running the sample:
18+
19+
pip install azure-ai-projects azure-identity opentelemetry-sdk azure-monitor-opentelemetry
20+
21+
Set these environment variables with your own values:
22+
* PROJECT_CONNECTION_STRING - The Azure AI Project connection string, as found in your AI Studio Project.
23+
* AZURE_TRACING_GEN_AI_CONTENT_RECORDING_ENABLED - Optional. Set to `true` to trace the content of chat
24+
messages, which may contain personal data. False by default.
25+
"""
26+
import asyncio
27+
import time
28+
from azure.ai.projects.aio import AIProjectClient
29+
from azure.identity.aio import DefaultAzureCredential
30+
from opentelemetry import trace
31+
import os
32+
from azure.monitor.opentelemetry import configure_azure_monitor
33+
34+
35+
tracer = trace.get_tracer(__name__)
36+
37+
38+
@tracer.start_as_current_span(__file__)
39+
async def main() -> None:
40+
# Create an Azure AI Project Client from a connection string, copied from your AI Studio project.
41+
# At the moment, it should be in the format "<HostName>;<AzureSubscriptionId>;<ResourceGroup>;<HubName>"
42+
# Customer needs to login to Azure subscription via Azure CLI and set the environment variables
43+
44+
project_client = AIProjectClient.from_connection_string(
45+
credential=DefaultAzureCredential(), conn_str=os.environ["PROJECT_CONNECTION_STRING"]
46+
)
47+
48+
# Enable Azure Monitor tracing
49+
application_insights_connection_string = project_client.telemetry.get_connection_string()
50+
if not application_insights_connection_string:
51+
print("Application Insights was not enabled for this project.")
52+
print("Enable it via the 'Tracing' tab in your AI Studio project page.")
53+
exit()
54+
configure_azure_monitor(connection_string=application_insights_connection_string)
55+
56+
async with project_client:
57+
agent = await project_client.agents.create_agent(
58+
model="gpt-4o", name="my-assistant", instructions="You are helpful assistant"
59+
)
60+
print(f"Created agent, agent ID: {agent.id}")
61+
62+
thread = await project_client.agents.create_thread()
63+
print(f"Created thread, thread ID: {thread.id}")
64+
65+
message = await project_client.agents.create_message(
66+
thread_id=thread.id, role="user", content="Hello, tell me a joke"
67+
)
68+
print(f"Created message, message ID: {message.id}")
69+
70+
run = await project_client.agents.create_run(thread_id=thread.id, assistant_id=agent.id)
71+
72+
# poll the run as long as run status is queued or in progress
73+
while run.status in ["queued", "in_progress", "requires_action"]:
74+
# wait for a second
75+
time.sleep(1)
76+
run = await project_client.agents.get_run(thread_id=thread.id, run_id=run.id)
77+
78+
print(f"Run status: {run.status}")
79+
80+
print(f"Run completed with status: {run.status}")
81+
82+
await project_client.agents.delete_agent(agent.id)
83+
print("Deleted agent")
84+
85+
messages = await project_client.agents.list_messages(thread_id=thread.id)
86+
print(f"Messages: {messages}")
87+
88+
89+
if __name__ == "__main__":
90+
asyncio.run(main())

0 commit comments

Comments
 (0)