diff --git a/articles/ai-services/agents/how-to/tools/file-search.md b/articles/ai-services/agents/how-to/tools/file-search.md index c95e3cb942..c42828c689 100644 --- a/articles/ai-services/agents/how-to/tools/file-search.md +++ b/articles/ai-services/agents/how-to/tools/file-search.md @@ -82,110 +82,20 @@ As a fallback, there's a 60-second maximum wait in the run object when the threa ::: zone-end -::: zone pivot="csharp-example" +::: zone pivot="quickstart" -```csharp -using System; -using System.Collections.Generic; -using System.IO; -using System.Threading.Tasks; -using Azure.Core.TestFramework; -using NUnit.Framework; - -namespace Azure.AI.Projects.Tests; +# Quickstart – Upload Local Files w/ file search -public partial class Sample_Agent_FileSearch : SamplesBase -{ - [Test] - public async Task FilesSearchExample() - { - var connectionString = TestEnvironment.AzureAICONNECTIONSTRING; - AgentsClient client = new AgentsClient(connectionString, new DefaultAzureCredential()); - - #region Snippet:UploadAgentFilesToUse - // Upload a file and wait for it to be processed - File.WriteAllText( - path: "sample_file_for_upload.txt", - contents: "The word 'apple' uses the code 442345, while the word 'banana' uses the code 673457."); - Response uploadAgentFileResponse = await client.UploadFileAsync( - filePath: "sample_file_for_upload.txt", - purpose: AgentFilePurpose.Agents); - - AgentFile uploadedAgentFile = uploadAgentFileResponse.Value; - #endregion - - #region Snippet:CreateVectorStore - // Create a vector store with the file and wait for it to be processed. - // 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 - VectorStore vectorStore = await client.CreateVectorStoreAsync( - fileIds: new List { uploadedAgentFile.Id }, - name: "my_vector_store"); - #endregion - - #region Snippet:CreateAgentWithFiles - FileSearchToolResource fileSearchToolResource = new FileSearchToolResource(); - fileSearchToolResource.VectorStoreIds.Add(vectorStore.Id); - - // Create an agent with toolResources and process assistant run - Response agentResponse = await client.CreateAgentAsync( - model: "gpt-4-1106-preview", - name: "SDK Test Agent - Retrieval", - instructions: "You are a helpful agent that can help fetch data from files you know about.", - tools: new List { new FileSearchToolDefinition() }, - toolResources: new ToolResources() { FileSearch = fileSearchToolResource }); - Agent agent = agentResponse.Value; - #endregion - - // Create thread for communication - Response threadResponse = await client.CreateThreadAsync(); - AgentThread thread = threadResponse.Value; - - // Create message to thread - Response messageResponse = await client.CreateMessageAsync( - thread.Id, - MessageRole.User, - "Can you give me the documented codes for 'banana' and 'orange'?"); - ThreadMessage message = messageResponse.Value; - - // Run the agent - Response runResponse = await client.CreateRunAsync(thread, agent); - - do - { - await Task.Delay(TimeSpan.FromMilliseconds(500)); - runResponse = await client.GetRunAsync(thread.Id, runResponse.Value.Id); - } - while (runResponse.Value.Status == RunStatus.Queued - || runResponse.Value.Status == RunStatus.InProgress); +In this example, we’ll use Azure AI Agent Service to create an agent that can help answer questions on information you upload from local files. - Response> afterRunMessagesResponse - = await client.GetMessagesAsync(thread.Id); - IReadOnlyList messages = afterRunMessagesResponse.Value.Data; +## Prerequisites +Complete the [agent setup](../../../quickstart.md). - // Note: messages iterate from newest to oldest, with the messages[0] being the most recent - foreach (ThreadMessage threadMessage in messages) - { - Console.Write($"{threadMessage.CreatedAt:yyyy-MM-dd HH:mm:ss} - {threadMessage.Role,10}: "); - foreach (MessageContent contentItem in threadMessage.ContentItems) - { - if (contentItem is MessageTextContent textItem) - { - Console.Write(textItem.Text); - } - else if (contentItem is MessageImageFileContent imageFileItem) - { - Console.Write($";;;" +// Customer needs to login to Azure subscription via Azure CLI and set the environment variables +var connectionString = TestEnvironment.AzureAICONNECTIONSTRING; +AgentsClient client = new AgentsClient(connectionString, new DefaultAzureCredential()); +``` - # [START upload_file_and_create_agent_with_file_search] - # We will upload the local file to Azure and will use it for vector store creation. - _, asset_uri = project_client.upload_file("./data/product_info_1.md") +--- - # create a vector store with no file and wait for it to be processed - ds = VectorStoreDataSource(asset_identifier=asset_uri, asset_type=VectorStoreDataSourceAssetType.URI_ASSET) - vector_store = project_client.agents.create_vector_store_and_poll(data_sources=[ds], name="sample_vector_store") - print(f"Created vector store, vector store ID: {vector_store.id}") +## Step 2: Upload files and add them to a Vector Store - # create a file search tool - file_search_tool = FileSearchTool(vector_store_ids=[vector_store.id]) +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. - # notices that FileSearchTool as tool and tool_resources must be added or the assistant unable to search the file - agent = project_client.agents.create_agent( - model="gpt-4o-mini", - name="my-assistant", - instructions="You are helpful assistant", - tools=file_search_tool.definitions, - tool_resources=file_search_tool.resources, - ) - # [END upload_file_and_create_agent_with_file_search] - print(f"Created agent, agent ID: {agent.id}") +Vector stores are created using message attachments that have a default expiration policy of seven days after they were last active (defined as the last time the vector store was part of a run). This default exists to help you manage your vector storage costs. You can override these expiration policies at any time. - thread = project_client.agents.create_thread() - print(f"Created thread, thread ID: {thread.id}") +# [Python](#tab/python) - message = project_client.agents.create_message( - thread_id=thread.id, role="user", content="What feature does Smart Eyewear offer?" - ) - print(f"Created message, message ID: {message.id}") +```python +# We will upload the local file to Azure and will use it for vector store creation. +_, asset_uri = project_client.upload_file("./data/product_info_1.md") - run = project_client.agents.create_and_process_run(thread_id=thread.id, assistant_id=agent.id) - print(f"Created run, run ID: {run.id}") +# create a vector store with no file and wait for it to be processed +ds = VectorStoreDataSource(asset_identifier=asset_uri, asset_type=VectorStoreDataSourceAssetType.URI_ASSET) +vector_store = project_client.agents.create_vector_store_and_poll(data_sources=[ds], name="sample_vector_store") +print(f"Created vector store, vector store ID: {vector_store.id}") +``` + +# [C#](#tab/csharp) + +```csharp +// Upload a file and wait for it to be processed +File.WriteAllText( + path: "sample_file_for_upload.txt", + contents: "The word 'apple' uses the code 442345, while the word 'banana' uses the code 673457."); +Response uploadAgentFileResponse = await client.UploadFileAsync( + filePath: "sample_file_for_upload.txt", + purpose: AgentFilePurpose.Agents); + +AgentFile uploadedAgentFile = uploadAgentFileResponse.Value; + +// Create a vector store with the file and wait for it to be processed. +// 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 +VectorStore vectorStore = await client.CreateVectorStoreAsync( + fileIds: new List { uploadedAgentFile.Id }, + name: "my_vector_store"); +``` +--- - project_client.agents.delete_vector_store(vector_store.id) - print("Deleted vector store") +## Step 3: Enable file search - project_client.agents.delete_agent(agent.id) - print("Deleted agent") +To make the files accessible to your agent, create a `FileSearchTool` object with the `vector_store` ID, and attach `tools` and `tool_resources` to the agent. - messages = project_client.agents.list_messages(thread_id=thread.id) - print(f"Messages: {messages}") +# [Python](#tab/python) +```python + +# create a file search tool +file_search_tool = FileSearchTool(vector_store_ids=[vector_store.id]) + +# notices that FileSearchTool as tool and tool_resources must be added or the agent will be unable to search the file +agent = project_client.agents.create_agent( + model="gpt-4o-mini", + name="my-agent", + instructions="You are a helpful agent", + tools=file_search_tool.definitions, + tool_resources=file_search_tool.resources, +) +print(f"Created agent, agent ID: {agent.id}") ``` +# [C#](#tab/csharp) + +```csharp +FileSearchToolResource fileSearchToolResource = new FileSearchToolResource(); +fileSearchToolResource.VectorStoreIds.Add(vectorStore.Id); + +// Create an agent with toolResources and process assistant run +Response agentResponse = await client.CreateAgentAsync( + model: "gpt-4-1106-preview", + name: "SDK Test Agent - Retrieval", + instructions: "You are a helpful agent that can help fetch data from files you know about.", + tools: new List { new FileSearchToolDefinition() }, + toolResources: new ToolResources() { FileSearch = fileSearchToolResource }); +Agent agent = agentResponse.Value; +``` + +--- + +## Step 4: Create a thread + +# [Python](#tab/python) + +```python +thread = project_client.agents.create_thread() +print(f"Created thread, thread ID: {thread.id}") + +message = project_client.agents.create_message( + thread_id=thread.id, role="user", content="What feature does Smart Eyewear offer?" +) +print(f"Created message, message ID: {message.id}") +``` + + + +# [C#](#tab/csharp) + +```csharp +// Create thread for communication +Response threadResponse = await client.CreateThreadAsync(); +AgentThread thread = threadResponse.Value; + +// Create message to thread +Response messageResponse = await client.CreateMessageAsync( + thread.Id, + MessageRole.User, + "Can you give me the documented codes for 'banana' and 'orange'?"); +ThreadMessage message = messageResponse.Value; +``` + +## Step 5: Create a run and check the output +Create a run and observe that the model uses the file search tool to provide a response to the user's question. +# [Python](#tab/python) +```python +run = project_client.agents.create_and_process_run(thread_id=thread.id, assistant_id=agent.id) +print(f"Created run, run ID: {run.id}") + +project_client.agents.delete_vector_store(vector_store.id) +print("Deleted vector store") + +project_client.agents.delete_agent(agent.id) +print("Deleted agent") + +messages = project_client.agents.list_messages(thread_id=thread.id) +print(f"Messages: {messages}") +``` + +# [C#](#tab/csharp) + +```csharp +// Run the agent +Response runResponse = await client.CreateRunAsync(thread, agent); + +do +{ + await Task.Delay(TimeSpan.FromMilliseconds(500)); + runResponse = await client.GetRunAsync(thread.Id, runResponse.Value.Id); +} +while (runResponse.Value.Status == RunStatus.Queued + || runResponse.Value.Status == RunStatus.InProgress); + +Response> afterRunMessagesResponse + = await client.GetMessagesAsync(thread.Id); +IReadOnlyList messages = afterRunMessagesResponse.Value.Data; + +// Note: messages iterate from newest to oldest, with the messages[0] being the most recent +foreach (ThreadMessage threadMessage in messages) +{ + Console.Write($"{threadMessage.CreatedAt:yyyy-MM-dd HH:mm:ss} - {threadMessage.Role,10}: "); + foreach (MessageContent contentItem in threadMessage.ContentItems) + { + if (contentItem is MessageTextContent textItem) + { + Console.Write(textItem.Text); + } + else if (contentItem is MessageImageFileContent imageFileItem) + { + Console.Write($"