diff --git a/dotnet/Directory.Packages.props b/dotnet/Directory.Packages.props index 3117b8da61ad..ff391e724d77 100644 --- a/dotnet/Directory.Packages.props +++ b/dotnet/Directory.Packages.props @@ -17,10 +17,10 @@ + - + - diff --git a/dotnet/nuget.config b/dotnet/nuget.config index 143754718558..7d7626e18f30 100644 --- a/dotnet/nuget.config +++ b/dotnet/nuget.config @@ -3,7 +3,7 @@ - + diff --git a/dotnet/samples/Concepts/Agents/AzureAIAgent_FileManipulation.cs b/dotnet/samples/Concepts/Agents/AzureAIAgent_FileManipulation.cs index 120af824229c..6292339d35e7 100644 --- a/dotnet/samples/Concepts/Agents/AzureAIAgent_FileManipulation.cs +++ b/dotnet/samples/Concepts/Agents/AzureAIAgent_FileManipulation.cs @@ -1,10 +1,9 @@ // Copyright (c) Microsoft. All rights reserved. -using Azure.AI.Projects; +using Azure.AI.Agents.Persistent; using Microsoft.SemanticKernel; using Microsoft.SemanticKernel.Agents.AzureAI; using Microsoft.SemanticKernel.ChatCompletion; using Resources; -using Agent = Azure.AI.Projects.Agent; namespace Agents; @@ -17,10 +16,10 @@ public class AzureAIAgent_FileManipulation(ITestOutputHelper output) : BaseAzure public async Task AnalyzeCSVFileUsingAzureAIAgentAsync() { await using Stream stream = EmbeddedResource.ReadStream("sales.csv")!; - AgentFile fileInfo = await this.AgentsClient.UploadFileAsync(stream, AgentFilePurpose.Agents, "sales.csv"); + PersistentAgentFileInfo fileInfo = await this.Client.Files.UploadFileAsync(stream, PersistentAgentFilePurpose.Agents, "sales.csv"); // Define the agent - Agent definition = await this.AgentsClient.CreateAgentAsync( + PersistentAgent definition = await this.Client.Administration.CreateAgentAsync( TestConfiguration.AzureAI.ChatModelId, tools: [new CodeInterpreterToolDefinition()], toolResources: @@ -31,8 +30,8 @@ public async Task AnalyzeCSVFileUsingAzureAIAgentAsync() FileIds = { fileInfo.Id }, } }); - AzureAIAgent agent = new(definition, this.AgentsClient); - AzureAIAgentThread thread = new(this.AgentsClient); + AzureAIAgent agent = new(definition, this.Client); + AzureAIAgentThread thread = new(this.Client); // Respond to user input try @@ -44,8 +43,8 @@ public async Task AnalyzeCSVFileUsingAzureAIAgentAsync() finally { await thread.DeleteAsync(); - await this.AgentsClient.DeleteAgentAsync(agent.Id); - await this.AgentsClient.DeleteFileAsync(fileInfo.Id); + await this.Client.Administration.DeleteAgentAsync(agent.Id); + await this.Client.Files.DeleteFileAsync(fileInfo.Id); } // Local function to invoke agent and display the conversation messages. diff --git a/dotnet/samples/Concepts/Agents/AzureAIAgent_Streaming.cs b/dotnet/samples/Concepts/Agents/AzureAIAgent_Streaming.cs index d03b223c1cd3..e01e30f663c3 100644 --- a/dotnet/samples/Concepts/Agents/AzureAIAgent_Streaming.cs +++ b/dotnet/samples/Concepts/Agents/AzureAIAgent_Streaming.cs @@ -1,11 +1,10 @@ // Copyright (c) Microsoft. All rights reserved. using System.ComponentModel; -using Azure.AI.Projects; +using Azure.AI.Agents.Persistent; using Microsoft.SemanticKernel; using Microsoft.SemanticKernel.Agents; using Microsoft.SemanticKernel.Agents.AzureAI; using Microsoft.SemanticKernel.ChatCompletion; -using Agent = Azure.AI.Projects.Agent; namespace Agents; @@ -21,23 +20,30 @@ public async Task UseStreamingAgentAsync() const string AgentInstructions = "Repeat the user message in the voice of a pirate and then end with a parrot sound."; // Define the agent - Agent definition = await this.AgentsClient.CreateAgentAsync( + PersistentAgent definition = await this.Client.Administration.CreateAgentAsync( TestConfiguration.AzureAI.ChatModelId, AgentName, null, AgentInstructions); - AzureAIAgent agent = new(definition, this.AgentsClient); + AzureAIAgent agent = new(definition, this.Client); - // Create a thread for the agent conversation. - AzureAIAgentThread agentThread = new(this.AgentsClient, metadata: SampleMetadata); + try + { + // Create a thread for the agent conversation. + AzureAIAgentThread agentThread = new(this.Client, metadata: SampleMetadata); - // Respond to user input - await InvokeAgentAsync(agent, agentThread, "Fortune favors the bold."); - await InvokeAgentAsync(agent, agentThread, "I came, I saw, I conquered."); - await InvokeAgentAsync(agent, agentThread, "Practice makes perfect."); + // Respond to user input + await InvokeAgentAsync(agent, agentThread, "Fortune favors the bold."); + await InvokeAgentAsync(agent, agentThread, "I came, I saw, I conquered."); + await InvokeAgentAsync(agent, agentThread, "Practice makes perfect."); - // Output the entire chat history - await DisplayChatHistoryAsync(agentThread); + // Output the entire chat history + await DisplayChatHistoryAsync(agentThread); + } + finally + { + await this.Client.Administration.DeleteAgentAsync(agent.Id); + } } [Fact] @@ -47,26 +53,34 @@ public async Task UseStreamingAssistantAgentWithPluginAsync() const string AgentInstructions = "Answer questions about the menu."; // Define the agent - Agent definition = await this.AgentsClient.CreateAgentAsync( + PersistentAgent definition = await this.Client.Administration.CreateAgentAsync( TestConfiguration.AzureAI.ChatModelId, AgentName, null, AgentInstructions); - AzureAIAgent agent = new(definition, this.AgentsClient); + AzureAIAgent agent = new(definition, this.Client); // Initialize plugin and add to the agent's Kernel (same as direct Kernel usage). KernelPlugin plugin = KernelPluginFactory.CreateFromType(); agent.Kernel.Plugins.Add(plugin); // Create a thread for the agent conversation. - AzureAIAgentThread agentThread = new(this.AgentsClient, metadata: SampleMetadata); + AzureAIAgentThread agentThread = new(this.Client, metadata: SampleMetadata); - // Respond to user input - await InvokeAgentAsync(agent, agentThread, "What is the special soup and its price?"); - await InvokeAgentAsync(agent, agentThread, "What is the special drink and its price?"); + try + { + // Respond to user input + await InvokeAgentAsync(agent, agentThread, "What is the special soup and its price?"); + await InvokeAgentAsync(agent, agentThread, "What is the special drink and its price?"); - // Output the entire chat history - await DisplayChatHistoryAsync(agentThread); + // Output the entire chat history + await DisplayChatHistoryAsync(agentThread); + } + finally + { + await this.Client.Threads.DeleteThreadAsync(agentThread.Id); + await this.Client.Administration.DeleteAgentAsync(agent.Id); + } } [Fact] @@ -76,23 +90,31 @@ public async Task UseStreamingAssistantWithCodeInterpreterAsync() const string AgentInstructions = "Solve math problems with code."; // Define the agent - Agent definition = await this.AgentsClient.CreateAgentAsync( + PersistentAgent definition = await this.Client.Administration.CreateAgentAsync( TestConfiguration.AzureAI.ChatModelId, AgentName, null, AgentInstructions, [new CodeInterpreterToolDefinition()]); - AzureAIAgent agent = new(definition, this.AgentsClient); + AzureAIAgent agent = new(definition, this.Client); // Create a thread for the agent conversation. - AzureAIAgentThread agentThread = new(this.AgentsClient, metadata: SampleMetadata); + AzureAIAgentThread agentThread = new(this.Client, metadata: SampleMetadata); - // Respond to user input - await InvokeAgentAsync(agent, agentThread, "Is 191 a prime number?"); - await InvokeAgentAsync(agent, agentThread, "Determine the values in the Fibonacci sequence that that are less then the value of 101"); + try + { + // Respond to user input + await InvokeAgentAsync(agent, agentThread, "Is 191 a prime number?"); + await InvokeAgentAsync(agent, agentThread, "Determine the values in the Fibonacci sequence that that are less then the value of 101"); - // Output the entire chat history - await DisplayChatHistoryAsync(agentThread); + // Output the entire chat history + await DisplayChatHistoryAsync(agentThread); + } + finally + { + await this.Client.Threads.DeleteThreadAsync(agentThread.Id); + await this.Client.Administration.DeleteAgentAsync(agent.Id); + } } // Local function to invoke agent and display the conversation messages. diff --git a/dotnet/samples/Demos/ModelContextProtocolClientServer/MCPClient/Samples/AzureAIAgentWithMCPToolsSample.cs b/dotnet/samples/Demos/ModelContextProtocolClientServer/MCPClient/Samples/AzureAIAgentWithMCPToolsSample.cs index 843fa00cba9c..7fd1e1c7fb14 100644 --- a/dotnet/samples/Demos/ModelContextProtocolClientServer/MCPClient/Samples/AzureAIAgentWithMCPToolsSample.cs +++ b/dotnet/samples/Demos/ModelContextProtocolClientServer/MCPClient/Samples/AzureAIAgentWithMCPToolsSample.cs @@ -4,7 +4,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using Azure.AI.Projects; +using Azure.AI.Agents.Persistent; using Azure.Identity; using Microsoft.Extensions.Configuration; using Microsoft.SemanticKernel; @@ -68,7 +68,7 @@ public static async Task RunAsync() await response!.Thread.DeleteAsync(); // Delete the agent after use - await agent.Client.DeleteAgentAsync(agent.Id); + await agent.Client.Administration.DeleteAgentAsync(agent.Id); } /// @@ -86,7 +86,7 @@ private static async Task CreateAzureAIAgentAsync(Kernel kernel, s .AddEnvironmentVariables() .Build(); - if (config["AzureAI:ConnectionString"] is not { } connectionString) + if (config["AzureAI:Endpoint"] is not { } endpoint) { const string Message = "Please provide a valid `AzureAI:ConnectionString` secret to run this sample. See the associated README.md for more details."; Console.Error.WriteLine(Message); @@ -96,11 +96,9 @@ private static async Task CreateAzureAIAgentAsync(Kernel kernel, s string modelId = config["AzureAI:ChatModelId"] ?? "gpt-4o-mini"; // Create the Azure AI Agent - AIProjectClient projectClient = AzureAIAgent.CreateAzureAIClient(connectionString, new AzureCliCredential()); + PersistentAgentsClient agentsClient = AzureAIAgent.CreateAgentsClient(endpoint, new AzureCliCredential()); - AgentsClient agentsClient = projectClient.GetAgentsClient(); - - Azure.AI.Projects.Agent agent = await agentsClient.CreateAgentAsync(modelId, name, null, instructions); + PersistentAgent agent = await agentsClient.Administration.CreateAgentAsync(modelId, name, null, instructions); return new AzureAIAgent(agent, agentsClient) { diff --git a/dotnet/samples/GettingStartedWithAgents/AzureAIAgent/Step01_AzureAIAgent.cs b/dotnet/samples/GettingStartedWithAgents/AzureAIAgent/Step01_AzureAIAgent.cs index 1b3afff46713..e348f065eb13 100644 --- a/dotnet/samples/GettingStartedWithAgents/AzureAIAgent/Step01_AzureAIAgent.cs +++ b/dotnet/samples/GettingStartedWithAgents/AzureAIAgent/Step01_AzureAIAgent.cs @@ -1,4 +1,5 @@ // Copyright (c) Microsoft. All rights reserved. +using Azure.AI.Agents.Persistent; using Microsoft.SemanticKernel; using Microsoft.SemanticKernel.Agents; using Microsoft.SemanticKernel.Agents.AzureAI; @@ -19,11 +20,10 @@ public async Task UseTemplateForAzureAgent() string generateStoryYaml = EmbeddedResource.Read("GenerateStory.yaml"); PromptTemplateConfig templateConfig = KernelFunctionYaml.ToPromptTemplateConfig(generateStoryYaml); // Instructions, Name and Description properties defined via the PromptTemplateConfig. - Azure.AI.Projects.Agent definition = await this.AgentsClient.CreateAgentAsync(TestConfiguration.AzureAI.ChatModelId, templateConfig.Name, templateConfig.Description, templateConfig.Template); - + PersistentAgent definition = await this.Client.Administration.CreateAgentAsync(TestConfiguration.AzureAI.ChatModelId, templateConfig.Name, templateConfig.Description, templateConfig.Template); AzureAIAgent agent = new( definition, - this.AgentsClient, + this.Client, templateFactory: new KernelPromptTemplateFactory(), templateFormat: PromptTemplateConfig.SemanticKernelTemplateFormat) { @@ -35,7 +35,7 @@ public async Task UseTemplateForAzureAgent() }; // Create a thread for the agent conversation. - AgentThread thread = new AzureAIAgentThread(this.AgentsClient, metadata: SampleMetadata); + AgentThread thread = new AzureAIAgentThread(this.Client, metadata: SampleMetadata); try { @@ -53,7 +53,7 @@ await InvokeAgentAsync( finally { await thread.DeleteAsync(); - await this.AgentsClient.DeleteAgentAsync(agent.Id); + await this.Client.Administration.DeleteAgentAsync(agent.Id); } // Local function to invoke agent and display the response. diff --git a/dotnet/samples/GettingStartedWithAgents/AzureAIAgent/Step02_AzureAIAgent_Plugins.cs b/dotnet/samples/GettingStartedWithAgents/AzureAIAgent/Step02_AzureAIAgent_Plugins.cs index 908948650425..666d2a5b650b 100644 --- a/dotnet/samples/GettingStartedWithAgents/AzureAIAgent/Step02_AzureAIAgent_Plugins.cs +++ b/dotnet/samples/GettingStartedWithAgents/AzureAIAgent/Step02_AzureAIAgent_Plugins.cs @@ -1,4 +1,5 @@ // Copyright (c) Microsoft. All rights reserved. +using Azure.AI.Agents.Persistent; using Microsoft.SemanticKernel; using Microsoft.SemanticKernel.Agents; using Microsoft.SemanticKernel.Agents.AzureAI; @@ -23,7 +24,7 @@ public async Task UseAzureAgentWithPlugin() name: "Host"); // Create a thread for the agent conversation. - AgentThread thread = new AzureAIAgentThread(this.AgentsClient, metadata: SampleMetadata); + AgentThread thread = new AzureAIAgentThread(this.Client, metadata: SampleMetadata); // Respond to user input try @@ -36,7 +37,7 @@ public async Task UseAzureAgentWithPlugin() finally { await thread.DeleteAsync(); - await this.AgentsClient.DeleteAgentAsync(agent.Id); + await this.Client.Administration.DeleteAgentAsync(agent.Id); } } @@ -47,7 +48,7 @@ public async Task UseAzureAgentWithPluginEnumParameter() AzureAIAgent agent = await CreateAzureAgentAsync(plugin: KernelPluginFactory.CreateFromType()); // Create a thread for the agent conversation. - AgentThread thread = new AzureAIAgentThread(this.AgentsClient, metadata: SampleMetadata); + AgentThread thread = new AzureAIAgentThread(this.Client, metadata: SampleMetadata); // Respond to user input try @@ -57,20 +58,20 @@ public async Task UseAzureAgentWithPluginEnumParameter() finally { await thread.DeleteAsync(); - await this.AgentsClient.DeleteAgentAsync(agent.Id); + await this.Client.Administration.DeleteAgentAsync(agent.Id); } } private async Task CreateAzureAgentAsync(KernelPlugin plugin, string? instructions = null, string? name = null) { // Define the agent - Azure.AI.Projects.Agent definition = await this.AgentsClient.CreateAgentAsync( + PersistentAgent definition = await this.Client.Administration.CreateAgentAsync( TestConfiguration.AzureAI.ChatModelId, name, null, instructions); - AzureAIAgent agent = new(definition, this.AgentsClient); + AzureAIAgent agent = new(definition, this.Client); // Add to the agent's Kernel if (plugin != null) diff --git a/dotnet/samples/GettingStartedWithAgents/AzureAIAgent/Step03_AzureAIAgent_Chat.cs b/dotnet/samples/GettingStartedWithAgents/AzureAIAgent/Step03_AzureAIAgent_Chat.cs index c54d9cf78829..654ea1d9bfd0 100644 --- a/dotnet/samples/GettingStartedWithAgents/AzureAIAgent/Step03_AzureAIAgent_Chat.cs +++ b/dotnet/samples/GettingStartedWithAgents/AzureAIAgent/Step03_AzureAIAgent_Chat.cs @@ -1,10 +1,10 @@ // Copyright (c) Microsoft. All rights reserved. +using Azure.AI.Agents.Persistent; using Microsoft.SemanticKernel; using Microsoft.SemanticKernel.Agents; using Microsoft.SemanticKernel.Agents.AzureAI; using Microsoft.SemanticKernel.Agents.Chat; using Microsoft.SemanticKernel.ChatCompletion; -using Agent = Azure.AI.Projects.Agent; namespace GettingStarted.AzureAgents; @@ -39,18 +39,18 @@ Consider suggestions when refining an idea. public async Task UseGroupChatWithTwoAgents() { // Define the agents - Agent reviewerModel = await this.AgentsClient.CreateAgentAsync( + PersistentAgent reviewerModel = await this.Client.Administration.CreateAgentAsync( TestConfiguration.AzureAI.ChatModelId, ReviewerName, null, ReviewerInstructions); - AzureAIAgent agentReviewer = new(reviewerModel, this.AgentsClient); - Agent writerModel = await this.AgentsClient.CreateAgentAsync( + AzureAIAgent agentReviewer = new(reviewerModel, this.Client); + PersistentAgent writerModel = await this.Client.Administration.CreateAgentAsync( TestConfiguration.AzureAI.ChatModelId, CopyWriterName, null, CopyWriterInstructions); - AzureAIAgent agentWriter = new(writerModel, this.AgentsClient); + AzureAIAgent agentWriter = new(writerModel, this.Client); // Create a chat for agent interaction. AgentGroupChat chat = @@ -89,6 +89,8 @@ public async Task UseGroupChatWithTwoAgents() finally { await chat.ResetAsync(); + await agentReviewer.Client.Administration.DeleteAgentAsync(agentReviewer.Id); + await agentWriter.Client.Administration.DeleteAgentAsync(agentWriter.Id); } } diff --git a/dotnet/samples/GettingStartedWithAgents/AzureAIAgent/Step04_AzureAIAgent_CodeInterpreter.cs b/dotnet/samples/GettingStartedWithAgents/AzureAIAgent/Step04_AzureAIAgent_CodeInterpreter.cs index 4c36e882d949..ca7558cd6a81 100644 --- a/dotnet/samples/GettingStartedWithAgents/AzureAIAgent/Step04_AzureAIAgent_CodeInterpreter.cs +++ b/dotnet/samples/GettingStartedWithAgents/AzureAIAgent/Step04_AzureAIAgent_CodeInterpreter.cs @@ -1,4 +1,5 @@ // Copyright (c) Microsoft. All rights reserved. +using Azure.AI.Agents.Persistent; using Microsoft.SemanticKernel; using Microsoft.SemanticKernel.Agents; using Microsoft.SemanticKernel.Agents.AzureAI; @@ -15,13 +16,13 @@ public class Step04_AzureAIAgent_CodeInterpreter(ITestOutputHelper output) : Bas public async Task UseCodeInterpreterToolWithAgent() { // Define the agent - Azure.AI.Projects.Agent definition = await this.AgentsClient.CreateAgentAsync( + PersistentAgent definition = await this.Client.Administration.CreateAgentAsync( TestConfiguration.AzureAI.ChatModelId, - tools: [new Azure.AI.Projects.CodeInterpreterToolDefinition()]); - AzureAIAgent agent = new(definition, this.AgentsClient); + tools: [new CodeInterpreterToolDefinition()]); + AzureAIAgent agent = new(definition, this.Client); // Create a thread for the agent conversation. - AgentThread thread = new AzureAIAgentThread(this.AgentsClient, metadata: SampleMetadata); + AgentThread thread = new AzureAIAgentThread(this.Client, metadata: SampleMetadata); // Respond to user input try @@ -31,7 +32,7 @@ public async Task UseCodeInterpreterToolWithAgent() finally { await thread.DeleteAsync(); - await this.AgentsClient.DeleteAgentAsync(agent.Id); + await this.Client.Administration.DeleteAgentAsync(agent.Id); } // Local function to invoke agent and display the conversation messages. diff --git a/dotnet/samples/GettingStartedWithAgents/AzureAIAgent/Step05_AzureAIAgent_FileSearch.cs b/dotnet/samples/GettingStartedWithAgents/AzureAIAgent/Step05_AzureAIAgent_FileSearch.cs index 1716c48d1b6f..9fc515f159af 100644 --- a/dotnet/samples/GettingStartedWithAgents/AzureAIAgent/Step05_AzureAIAgent_FileSearch.cs +++ b/dotnet/samples/GettingStartedWithAgents/AzureAIAgent/Step05_AzureAIAgent_FileSearch.cs @@ -1,5 +1,5 @@ // Copyright (c) Microsoft. All rights reserved. -using Azure.AI.Projects; +using Azure.AI.Agents.Persistent; using Microsoft.SemanticKernel; using Microsoft.SemanticKernel.Agents.AzureAI; using Microsoft.SemanticKernel.ChatCompletion; @@ -18,12 +18,12 @@ public async Task UseFileSearchToolWithAgent() // Define the agent await using Stream stream = EmbeddedResource.ReadStream("employees.pdf")!; - AgentFile fileInfo = await this.AgentsClient.UploadFileAsync(stream, AgentFilePurpose.Agents, "employees.pdf"); - VectorStore fileStore = - await this.AgentsClient.CreateVectorStoreAsync( + PersistentAgentFileInfo fileInfo = await this.Client.Files.UploadFileAsync(stream, PersistentAgentFilePurpose.Agents, "employees.pdf"); + PersistentAgentsVectorStore fileStore = + await this.Client.VectorStores.CreateVectorStoreAsync( [fileInfo.Id], metadata: new Dictionary() { { SampleMetadataKey, bool.TrueString } }); - Agent agentModel = await this.AgentsClient.CreateAgentAsync( + PersistentAgent agentModel = await this.Client.Administration.CreateAgentAsync( TestConfiguration.AzureAI.ChatModelId, tools: [new FileSearchToolDefinition()], toolResources: new() @@ -34,10 +34,10 @@ await this.AgentsClient.CreateVectorStoreAsync( } }, metadata: new Dictionary() { { SampleMetadataKey, bool.TrueString } }); - AzureAIAgent agent = new(agentModel, this.AgentsClient); + AzureAIAgent agent = new(agentModel, this.Client); // Create a thread associated for the agent conversation. - Microsoft.SemanticKernel.Agents.AgentThread thread = new AzureAIAgentThread(this.AgentsClient, metadata: SampleMetadata); + Microsoft.SemanticKernel.Agents.AgentThread thread = new AzureAIAgentThread(this.Client, metadata: SampleMetadata); // Respond to user input try @@ -49,9 +49,9 @@ await this.AgentsClient.CreateVectorStoreAsync( finally { await thread.DeleteAsync(); - await this.AgentsClient.DeleteAgentAsync(agent.Id); - await this.AgentsClient.DeleteVectorStoreAsync(fileStore.Id); - await this.AgentsClient.DeleteFileAsync(fileInfo.Id); + await this.Client.Administration.DeleteAgentAsync(agent.Id); + await this.Client.VectorStores.DeleteVectorStoreAsync(fileStore.Id); + await this.Client.Files.DeleteFileAsync(fileInfo.Id); } // Local function to invoke agent and display the conversation messages. diff --git a/dotnet/samples/GettingStartedWithAgents/AzureAIAgent/Step06_AzureAIAgent_OpenAPI.cs b/dotnet/samples/GettingStartedWithAgents/AzureAIAgent/Step06_AzureAIAgent_OpenAPI.cs index 194ae7b1638d..0514069f3937 100644 --- a/dotnet/samples/GettingStartedWithAgents/AzureAIAgent/Step06_AzureAIAgent_OpenAPI.cs +++ b/dotnet/samples/GettingStartedWithAgents/AzureAIAgent/Step06_AzureAIAgent_OpenAPI.cs @@ -1,5 +1,5 @@ // Copyright (c) Microsoft. All rights reserved. -using Azure.AI.Projects; +using Azure.AI.Agents.Persistent; using Microsoft.SemanticKernel; using Microsoft.SemanticKernel.Agents.AzureAI; using Microsoft.SemanticKernel.ChatCompletion; @@ -24,17 +24,17 @@ public async Task UseOpenAPIToolWithAgent() string apiWeather = EmbeddedResource.Read("weather.json"); // Define the agent - Agent definition = await this.AgentsClient.CreateAgentAsync( + PersistentAgent definition = await this.Client.Administration.CreateAgentAsync( TestConfiguration.AzureAI.ChatModelId, tools: [ new OpenApiToolDefinition("RestCountries", "Retrieve country information", BinaryData.FromString(apiCountries), new OpenApiAnonymousAuthDetails()), new OpenApiToolDefinition("Weather", "Retrieve weather by location", BinaryData.FromString(apiWeather), new OpenApiAnonymousAuthDetails()) ]); - AzureAIAgent agent = new(definition, this.AgentsClient); + AzureAIAgent agent = new(definition, this.Client); // Create a thread for the agent conversation. - Microsoft.SemanticKernel.Agents.AgentThread thread = new AzureAIAgentThread(this.AgentsClient, metadata: SampleMetadata); + Microsoft.SemanticKernel.Agents.AgentThread thread = new AzureAIAgentThread(this.Client, metadata: SampleMetadata); // Respond to user input try @@ -45,7 +45,7 @@ public async Task UseOpenAPIToolWithAgent() finally { await thread.DeleteAsync(); - await this.AgentsClient.DeleteAgentAsync(agent.Id); + await this.Client.Administration.DeleteAgentAsync(agent.Id); } // Local function to invoke agent and display the conversation messages. diff --git a/dotnet/samples/GettingStartedWithAgents/AzureAIAgent/Step07_AzureAIAgent_Functions.cs b/dotnet/samples/GettingStartedWithAgents/AzureAIAgent/Step07_AzureAIAgent_Functions.cs index 6eb018aecbe2..c88da8509695 100644 --- a/dotnet/samples/GettingStartedWithAgents/AzureAIAgent/Step07_AzureAIAgent_Functions.cs +++ b/dotnet/samples/GettingStartedWithAgents/AzureAIAgent/Step07_AzureAIAgent_Functions.cs @@ -1,4 +1,5 @@ // Copyright (c) Microsoft. All rights reserved. +using Azure.AI.Agents.Persistent; using Microsoft.SemanticKernel; using Microsoft.SemanticKernel.Agents; using Microsoft.SemanticKernel.Agents.AzureAI; @@ -27,19 +28,19 @@ public async Task UseSingleAgentWithFunctionTools() KernelPlugin plugin = KernelPluginFactory.CreateFromType(); var tools = plugin.Select(f => f.ToToolDefinition(plugin.Name)); - Azure.AI.Projects.Agent definition = await this.AgentsClient.CreateAgentAsync( + PersistentAgent definition = await this.Client.Administration.CreateAgentAsync( model: TestConfiguration.AzureAI.ChatModelId, name: HostName, description: null, instructions: HostInstructions, tools: tools); - AzureAIAgent agent = new(definition, this.AgentsClient); + AzureAIAgent agent = new(definition, this.Client); // Add plugin to the agent's Kernel (same as direct Kernel usage). agent.Kernel.Plugins.Add(plugin); // Create a thread for the agent conversation. - AgentThread thread = new AzureAIAgentThread(this.AgentsClient, metadata: SampleMetadata); + AgentThread thread = new AzureAIAgentThread(this.Client, metadata: SampleMetadata); // Respond to user input try @@ -52,7 +53,7 @@ public async Task UseSingleAgentWithFunctionTools() finally { await thread.DeleteAsync(); - await this.AgentsClient.DeleteAgentAsync(agent.Id); + await this.Client.Administration.DeleteAgentAsync(agent.Id); } // Local function to invoke agent and display the conversation messages. diff --git a/dotnet/samples/GettingStartedWithAgents/AzureAIAgent/Step08_AzureAIAgent_Declarative.cs b/dotnet/samples/GettingStartedWithAgents/AzureAIAgent/Step08_AzureAIAgent_Declarative.cs index bc0922498775..7a50dcf0475b 100644 --- a/dotnet/samples/GettingStartedWithAgents/AzureAIAgent/Step08_AzureAIAgent_Declarative.cs +++ b/dotnet/samples/GettingStartedWithAgents/AzureAIAgent/Step08_AzureAIAgent_Declarative.cs @@ -1,5 +1,4 @@ // Copyright (c) Microsoft. All rights reserved. -using Azure.AI.Projects; using Azure.Core; using Azure.Identity; using Microsoft.Extensions.DependencyInjection; @@ -8,7 +7,6 @@ using Microsoft.SemanticKernel.Agents.AzureAI; using Microsoft.SemanticKernel.ChatCompletion; using Plugins; -using Agent = Microsoft.SemanticKernel.Agents.Agent; namespace GettingStarted.AzureAgents; @@ -37,6 +35,7 @@ public async Task AzureAIAgentWithConfiguration() AzureAIAgentFactory factory = new(); var builder = Kernel.CreateBuilder(); + builder.Services.AddSingleton(this.Client); builder.Services.AddSingleton(new AzureCliCredential()); var kernel = builder.Build(); @@ -54,6 +53,8 @@ public async Task AzureAIAgentWithKernel() name: MyAgent description: My helpful agent. instructions: You are helpful agent. + model: + id: ${AzureOpenAI:ChatModelId} """; AzureAIAgentFactory factory = new(); @@ -190,9 +191,6 @@ public async Task AzureAIAgentWithFileSearch() """; AzureAIAgentFactory factory = new(); - KernelPlugin plugin = KernelPluginFactory.CreateFromType(); - this._kernel.Plugins.Add(plugin); - var agent = await factory.CreateAgentFromYamlAsync(text, new() { Kernel = this._kernel }, TestConfiguration.ConfigurationRoot); await InvokeAgentAsync(agent!, "What are the key features of the Semantic Kernel?"); @@ -382,7 +380,9 @@ public async Task AzureAIAgentWithTemplate() AzureAIAgentFactory factory = new(); var promptTemplateFactory = new KernelPromptTemplateFactory(); - var agent = await factory.CreateAgentFromYamlAsync(text, new() { Kernel = this._kernel }, TestConfiguration.ConfigurationRoot); + var agent = + await factory.CreateAgentFromYamlAsync(text, new() { Kernel = this._kernel }, TestConfiguration.ConfigurationRoot) ?? + throw new InvalidOperationException("Unable to create agent"); var options = new AgentInvokeOptions() { @@ -404,8 +404,8 @@ public async Task AzureAIAgentWithTemplate() } finally { - var azureaiAgent = agent as AzureAIAgent; - await azureaiAgent!.Client.DeleteAgentAsync(azureaiAgent.Id); + var azureaiAgent = (AzureAIAgent)agent; + await azureaiAgent.Client.Administration.DeleteAgentAsync(azureaiAgent.Id); if (agentThread is not null) { @@ -417,7 +417,7 @@ public async Task AzureAIAgentWithTemplate() public Step08_AzureAIAgent_Declarative(ITestOutputHelper output) : base(output) { var builder = Kernel.CreateBuilder(); - builder.Services.AddSingleton(this.Client); + builder.Services.AddSingleton(this.Client); this._kernel = builder.Build(); } @@ -448,7 +448,7 @@ private async Task InvokeAgentAsync(Agent agent, string input, bool? deleteAgent { var azureaiAgent = agent as AzureAIAgent; Assert.NotNull(azureaiAgent); - await azureaiAgent.Client.DeleteAgentAsync(azureaiAgent.Id); + await azureaiAgent.Client.Administration.DeleteAgentAsync(azureaiAgent.Id); if (agentThread is not null) { diff --git a/dotnet/samples/GettingStartedWithAgents/AzureAIAgent/Step09_AzureAIAgent_BingGrounding.cs b/dotnet/samples/GettingStartedWithAgents/AzureAIAgent/Step09_AzureAIAgent_BingGrounding.cs index 71eaae05575a..acd085d2791d 100644 --- a/dotnet/samples/GettingStartedWithAgents/AzureAIAgent/Step09_AzureAIAgent_BingGrounding.cs +++ b/dotnet/samples/GettingStartedWithAgents/AzureAIAgent/Step09_AzureAIAgent_BingGrounding.cs @@ -1,10 +1,9 @@ // Copyright (c) Microsoft. All rights reserved. -using Azure.AI.Projects; +using Azure.AI.Agents.Persistent; using Microsoft.SemanticKernel; using Microsoft.SemanticKernel.Agents; using Microsoft.SemanticKernel.Agents.AzureAI; using Microsoft.SemanticKernel.ChatCompletion; -using FoundryAgent = Azure.AI.Projects.Agent; namespace GettingStarted.AzureAgents; @@ -17,21 +16,15 @@ public class Step09_AzureAIAgent_BingGrounding(ITestOutputHelper output) : BaseA public async Task UseBingGroundingToolWithAgent() { // Access the BingGrounding connection - ConnectionsClient connectionsClient = this.Client.GetConnectionsClient(); - ConnectionResponse bingConnection = await connectionsClient.GetConnectionAsync(TestConfiguration.AzureAI.BingConnectionId); - - // Define the agent - ToolConnectionList toolConnections = new() - { - ConnectionList = { new ToolConnection(bingConnection.Id) } - }; - FoundryAgent definition = await this.AgentsClient.CreateAgentAsync( + BingGroundingSearchConfiguration bingToolConfiguration = new(TestConfiguration.AzureAI.BingConnectionId); + BingGroundingSearchToolParameters bingToolParameters = new([bingToolConfiguration]); + PersistentAgent definition = await this.Client.Administration.CreateAgentAsync( TestConfiguration.AzureAI.ChatModelId, - tools: [new BingGroundingToolDefinition(toolConnections)]); - AzureAIAgent agent = new(definition, this.AgentsClient); + tools: [new BingGroundingToolDefinition(bingToolParameters)]); + AzureAIAgent agent = new(definition, this.Client); // Create a thread for the agent conversation. - AzureAIAgentThread thread = new(this.AgentsClient, metadata: SampleMetadata); + AzureAIAgentThread thread = new(this.Client, metadata: SampleMetadata); // Respond to user input try @@ -42,7 +35,7 @@ public async Task UseBingGroundingToolWithAgent() finally { await thread.DeleteAsync(); - await this.AgentsClient.DeleteAgentAsync(agent.Id); + await this.Client.Administration.DeleteAgentAsync(agent.Id); } // Local function to invoke agent and display the conversation messages. @@ -62,21 +55,17 @@ async Task InvokeAgentAsync(string input) public async Task UseBingGroundingToolWithStreaming() { // Access the BingGrounding connection - ConnectionsClient connectionClient = this.Client.GetConnectionsClient(); - ConnectionResponse bingConnectionResponse = await connectionClient.GetConnectionAsync(TestConfiguration.AzureAI.BingConnectionId); + BingGroundingSearchConfiguration bingToolConfiguration = new(TestConfiguration.AzureAI.BingConnectionId); + BingGroundingSearchToolParameters bingToolParameters = new([bingToolConfiguration]); // Define the agent - ToolConnectionList toolConnections = new() - { - ConnectionList = { new ToolConnection(bingConnectionResponse.Id) } - }; - FoundryAgent definition = await this.AgentsClient.CreateAgentAsync( + PersistentAgent definition = await this.Client.Administration.CreateAgentAsync( TestConfiguration.AzureAI.ChatModelId, - tools: [new BingGroundingToolDefinition(toolConnections)]); - AzureAIAgent agent = new(definition, this.AgentsClient); + tools: [new BingGroundingToolDefinition(bingToolParameters)]); + AzureAIAgent agent = new(definition, this.Client); // Create a thread for the agent conversation. - AzureAIAgentThread thread = new(this.AgentsClient, metadata: SampleMetadata); + AzureAIAgentThread thread = new(this.Client, metadata: SampleMetadata); // Respond to user input try @@ -96,7 +85,7 @@ public async Task UseBingGroundingToolWithStreaming() finally { await thread.DeleteAsync(); - await this.AgentsClient.DeleteAgentAsync(agent.Id); + await this.Client.Administration.DeleteAgentAsync(agent.Id); } // Local function to invoke agent and display the conversation messages. diff --git a/dotnet/samples/GettingStartedWithAgents/OpenAIAssistant/Step07_Assistant_Declarative.cs b/dotnet/samples/GettingStartedWithAgents/OpenAIAssistant/Step07_Assistant_Declarative.cs index f0d193f300b7..33af88543254 100644 --- a/dotnet/samples/GettingStartedWithAgents/OpenAIAssistant/Step07_Assistant_Declarative.cs +++ b/dotnet/samples/GettingStartedWithAgents/OpenAIAssistant/Step07_Assistant_Declarative.cs @@ -209,8 +209,8 @@ private async Task InvokeAgentAsync(Agent agent, string input, bool deleteAgent { if (deleteAgent) { - var openaiAgent = agent as OpenAIAssistantAgent; - await openaiAgent!.Client.DeleteAssistantAsync(openaiAgent.Id); + var openaiAgent = (OpenAIAssistantAgent)agent; + await openaiAgent.Client.DeleteAssistantAsync(openaiAgent.Id); } if (agentThread is not null) diff --git a/dotnet/samples/GettingStartedWithAgents/Orchestration/Step05_Magentic.cs b/dotnet/samples/GettingStartedWithAgents/Orchestration/Step05_Magentic.cs index eb30e35e04e6..e1d6b542a1c0 100644 --- a/dotnet/samples/GettingStartedWithAgents/Orchestration/Step05_Magentic.cs +++ b/dotnet/samples/GettingStartedWithAgents/Orchestration/Step05_Magentic.cs @@ -1,5 +1,6 @@ // Copyright (c) Microsoft. All rights reserved. +using Azure.AI.Agents.Persistent; using Azure.Identity; using Microsoft.SemanticKernel; using Microsoft.SemanticKernel.Agents; @@ -9,7 +10,6 @@ using Microsoft.SemanticKernel.Agents.Runtime.InProcess; using Microsoft.SemanticKernel.ChatCompletion; using Microsoft.SemanticKernel.Connectors.OpenAI; -using AAIP = Azure.AI.Projects; namespace GettingStarted.Orchestration; @@ -40,15 +40,14 @@ public async Task MagenticTaskAsync() instructions: "You are a Researcher. You find information without additional computation or quantitative analysis.", kernel: researchKernel); - AAIP.AIProjectClient projectClient = AzureAIAgent.CreateAzureAIClient(TestConfiguration.AzureAI.ConnectionString, new AzureCliCredential()); - AAIP.AgentsClient agentsClient = projectClient.GetAgentsClient(); - AAIP.Agent definition = - await agentsClient.CreateAgentAsync( + PersistentAgentsClient agentsClient = AzureAIAgent.CreateAgentsClient(TestConfiguration.AzureAI.Endpoint, new AzureCliCredential()); + PersistentAgent definition = + await agentsClient.Administration.CreateAgentAsync( TestConfiguration.AzureAI.ChatModelId, name: "CoderAgent", description: "Write and executes code to process and analyze data.", instructions: "You solve questions using code. Please provide detailed analysis and computation process.", - tools: [new Azure.AI.Projects.CodeInterpreterToolDefinition()]); + tools: [new CodeInterpreterToolDefinition()]); AzureAIAgent coderAgent = new(definition, agentsClient); // Create a monitor to capturing agent responses (via ResponseCallback) diff --git a/dotnet/samples/GettingStartedWithAgents/Step10_MultiAgent_Declarative.cs b/dotnet/samples/GettingStartedWithAgents/Step10_MultiAgent_Declarative.cs index 03d13cb3c7e0..1b816a8663ea 100644 --- a/dotnet/samples/GettingStartedWithAgents/Step10_MultiAgent_Declarative.cs +++ b/dotnet/samples/GettingStartedWithAgents/Step10_MultiAgent_Declarative.cs @@ -1,7 +1,7 @@ // Copyright (c) Microsoft. All rights reserved. using System.ClientModel; -using Azure.AI.Projects; +using Azure.AI.Agents.Persistent; using Azure.Identity; using Microsoft.Extensions.DependencyInjection; using Microsoft.SemanticKernel; @@ -79,7 +79,7 @@ public async Task AzureAIAgentWithKernel() { var azureaiAgent = agent as AzureAIAgent; Assert.NotNull(azureaiAgent); - await azureaiAgent.Client.DeleteAgentAsync(azureaiAgent.Id); + await azureaiAgent.Client.Administration.DeleteAgentAsync(azureaiAgent.Id); if (agentThread is not null) { @@ -97,19 +97,19 @@ public Step10_MultiAgent_Declarative(ITestOutputHelper output) : base(output) OpenAIAssistantAgent.CreateAzureOpenAIClient(new ApiKeyCredential(this.ApiKey), new Uri(this.Endpoint!)) : OpenAIAssistantAgent.CreateAzureOpenAIClient(new AzureCliCredential(), new Uri(this.Endpoint!)); - var aiProjectClient = AzureAIAgent.CreateAzureAIClient(TestConfiguration.AzureAI.ConnectionString, new AzureCliCredential()); + var agentsClient = AzureAIAgent.CreateAgentsClient(TestConfiguration.AzureAI.Endpoint, new AzureCliCredential()); var builder = Kernel.CreateBuilder(); builder.Services.AddSingleton(openaiClient); - builder.Services.AddSingleton(aiProjectClient); + builder.Services.AddSingleton(agentsClient); AddChatCompletionToKernel(builder); this._kernel = builder.Build(); - this._kernelAgentFactory = new AggregatorKernelAgentFactory( - new ChatCompletionAgentFactory(), - new OpenAIAssistantAgentFactory(), - new AzureAIAgentFactory() - ); + this._kernelAgentFactory = + new AggregatorKernelAgentFactory( + new ChatCompletionAgentFactory(), + new OpenAIAssistantAgentFactory(), + new AzureAIAgentFactory()); } #region private diff --git a/dotnet/src/Agents/AzureAI/Agents.AzureAI.csproj b/dotnet/src/Agents/AzureAI/Agents.AzureAI.csproj index 2b0694f69986..e448a8f4f291 100644 --- a/dotnet/src/Agents/AzureAI/Agents.AzureAI.csproj +++ b/dotnet/src/Agents/AzureAI/Agents.AzureAI.csproj @@ -37,7 +37,7 @@ - + diff --git a/dotnet/src/Agents/AzureAI/AzureAIAgent.ClientFactory.cs b/dotnet/src/Agents/AzureAI/AzureAIAgent.ClientFactory.cs index e3b4e4bfe568..b82b0f0c093a 100644 --- a/dotnet/src/Agents/AzureAI/AzureAIAgent.ClientFactory.cs +++ b/dotnet/src/Agents/AzureAI/AzureAIAgent.ClientFactory.cs @@ -1,6 +1,6 @@ // Copyright (c) Microsoft. All rights reserved. using System.Net.Http; -using Azure.AI.Projects; +using Azure.AI.Agents.Persistent; using Azure.Core; using Azure.Core.Pipeline; using Microsoft.SemanticKernel.Http; @@ -8,32 +8,32 @@ namespace Microsoft.SemanticKernel.Agents.AzureAI; /// -/// Provides an for use by . +/// Provides an for use by . /// public sealed partial class AzureAIAgent : Agent { /// - /// Produces a . + /// Produces a . /// - /// The Azure AI Foundry project connection string, in the form `endpoint;subscription_id;resource_group_name;project_name`. + /// The Azure AI Foundry project endpoint. /// A credential used to authenticate to an Azure Service. /// A custom for HTTP requests. - public static AIProjectClient CreateAzureAIClient( - string connectionString, + public static PersistentAgentsClient CreateAgentsClient( + string endpoint, TokenCredential credential, HttpClient? httpClient = null) { - Verify.NotNullOrWhiteSpace(connectionString, nameof(connectionString)); + Verify.NotNull(endpoint, nameof(endpoint)); Verify.NotNull(credential, nameof(credential)); - AIProjectClientOptions clientOptions = CreateAzureClientOptions(httpClient); + PersistentAgentsAdministrationClientOptions clientOptions = CreateAzureClientOptions(httpClient); - return new AIProjectClient(connectionString, credential, clientOptions); + return new PersistentAgentsClient(endpoint, credential, clientOptions); } - private static AIProjectClientOptions CreateAzureClientOptions(HttpClient? httpClient) + private static PersistentAgentsAdministrationClientOptions CreateAzureClientOptions(HttpClient? httpClient) { - AIProjectClientOptions options = new(); + PersistentAgentsAdministrationClientOptions options = new(); options.AddPolicy(new SemanticKernelHeadersPolicy(), HttpPipelinePosition.PerCall); diff --git a/dotnet/src/Agents/AzureAI/AzureAIAgent.cs b/dotnet/src/Agents/AzureAI/AzureAIAgent.cs index 440dd0c74b65..c02cff51eab4 100644 --- a/dotnet/src/Agents/AzureAI/AzureAIAgent.cs +++ b/dotnet/src/Agents/AzureAI/AzureAIAgent.cs @@ -5,13 +5,12 @@ using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; -using Azure.AI.Projects; +using Azure.AI.Agents.Persistent; using Microsoft.Extensions.Logging; using Microsoft.SemanticKernel.Agents.AzureAI.Internal; using Microsoft.SemanticKernel.Agents.Extensions; using Microsoft.SemanticKernel.ChatCompletion; using Microsoft.SemanticKernel.Diagnostics; -using AAIP = Azure.AI.Projects; namespace Microsoft.SemanticKernel.Agents.AzureAI; @@ -45,7 +44,7 @@ public static class Tools /// /// Gets the assistant definition. /// - public Azure.AI.Projects.Agent Definition { get; private init; } + public PersistentAgent Definition { get; private init; } /// /// Gets the polling behavior for run processing. @@ -56,13 +55,13 @@ public static class Tools /// Initializes a new instance of the class. /// /// The agent model definition. - /// An instance. + /// An instance. /// Optional collection of plugins to add to the kernel. /// An optional factory to produce the for the agent. /// The format of the prompt template used when "templateFactory" parameter is supplied. public AzureAIAgent( - Azure.AI.Projects.Agent model, - AgentsClient client, + PersistentAgent model, + PersistentAgentsClient client, IEnumerable? plugins = null, IPromptTemplateFactory? templateFactory = null, string? templateFormat = null) @@ -95,7 +94,7 @@ public AzureAIAgent( /// /// The associated client. /// - public AgentsClient Client { get; } + public PersistentAgentsClient Client { get; } /// /// Adds a message to the specified thread. @@ -431,7 +430,7 @@ protected override async Task RestoreChannelAsync(string channelSt this.Logger.LogAzureAIAgentRestoringChannel(nameof(RestoreChannelAsync), nameof(AzureAIChannel), threadId); - AAIP.AgentThread thread = await this.Client.GetThreadAsync(threadId, cancellationToken).ConfigureAwait(false); + PersistentAgentThread thread = await this.Client.Threads.GetThreadAsync(threadId, cancellationToken).ConfigureAwait(false); this.Logger.LogAzureAIAgentRestoredChannel(nameof(RestoreChannelAsync), nameof(AzureAIChannel), threadId); diff --git a/dotnet/src/Agents/AzureAI/AzureAIAgentThread.cs b/dotnet/src/Agents/AzureAI/AzureAIAgentThread.cs index 0965819593e6..f111a0ca0515 100644 --- a/dotnet/src/Agents/AzureAI/AzureAIAgentThread.cs +++ b/dotnet/src/Agents/AzureAI/AzureAIAgentThread.cs @@ -7,7 +7,7 @@ using System.Threading; using System.Threading.Tasks; using Azure; -using Azure.AI.Projects; +using Azure.AI.Agents.Persistent; using Microsoft.SemanticKernel.Agents.AzureAI.Internal; namespace Microsoft.SemanticKernel.Agents.AzureAI; @@ -17,7 +17,7 @@ namespace Microsoft.SemanticKernel.Agents.AzureAI; /// public sealed class AzureAIAgentThread : AgentThread { - private readonly AgentsClient _client; + private readonly PersistentAgentsClient _client; private readonly IEnumerable? _messages; private readonly ToolResources? _toolResources; private readonly IReadOnlyDictionary? _metadata; @@ -34,7 +34,7 @@ public sealed class AzureAIAgentThread : AgentThread /// /// Metadata to attach to the underlying thread when it is created.. public AzureAIAgentThread( - AgentsClient client, + PersistentAgentsClient client, IEnumerable? messages = null, ToolResources? toolResources = null, IReadOnlyDictionary? metadata = null) @@ -52,7 +52,7 @@ public AzureAIAgentThread( /// /// The agents client to use for interacting with threads. /// The ID of an existing thread to resume. - public AzureAIAgentThread(AgentsClient client, string id) + public AzureAIAgentThread(PersistentAgentsClient client, string id) { Verify.NotNull(client); Verify.NotNull(id); @@ -78,7 +78,7 @@ public AzureAIAgentThread(AgentsClient client, string id) try { - var agentThreadResponse = await this._client.CreateThreadAsync( + var agentThreadResponse = await this._client.Threads.CreateThreadAsync( this._messages, this._toolResources, this._metadata, @@ -102,7 +102,7 @@ protected override async Task DeleteInternalAsync(CancellationToken cancellation try { - await this._client.DeleteThreadAsync(this.Id, cancellationToken).ConfigureAwait(false); + await this._client.Threads.DeleteThreadAsync(this.Id, cancellationToken).ConfigureAwait(false); } catch (RequestFailedException ex) when (ex.Status == 404) { diff --git a/dotnet/src/Agents/AzureAI/AzureAIChannel.cs b/dotnet/src/Agents/AzureAI/AzureAIChannel.cs index fa5991d4ace8..e1b57d4ad32b 100644 --- a/dotnet/src/Agents/AzureAI/AzureAIChannel.cs +++ b/dotnet/src/Agents/AzureAI/AzureAIChannel.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -using Azure.AI.Projects; +using Azure.AI.Agents.Persistent; using Microsoft.SemanticKernel.Agents.AzureAI.Internal; using Microsoft.SemanticKernel.Agents.Extensions; using Microsoft.SemanticKernel.Diagnostics; @@ -12,7 +12,7 @@ namespace Microsoft.SemanticKernel.Agents.AzureAI; /// /// A specialization for use with . /// -internal sealed class AzureAIChannel(AgentsClient client, string threadId) +internal sealed class AzureAIChannel(PersistentAgentsClient client, string threadId) : AgentChannel { /// @@ -53,7 +53,7 @@ protected override IAsyncEnumerable GetHistoryAsync(Cancella /// protected override Task ResetAsync(CancellationToken cancellationToken = default) { - return client.DeleteThreadAsync(threadId, cancellationToken); + return client.Threads.DeleteThreadAsync(threadId, cancellationToken); } /// diff --git a/dotnet/src/Agents/AzureAI/AzureAIClientProvider.cs b/dotnet/src/Agents/AzureAI/AzureAIClientProvider.cs deleted file mode 100644 index 4d9b55515192..000000000000 --- a/dotnet/src/Agents/AzureAI/AzureAIClientProvider.cs +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. -using System.Collections.Generic; -using System.Linq; -using System.Net.Http; -using Azure.AI.Projects; -using Azure.Core; -using Azure.Core.Pipeline; -using Microsoft.SemanticKernel.Http; - -namespace Microsoft.SemanticKernel.Agents.AzureAI; - -/// -/// Provides an for use by . -/// -public sealed class AzureAIClientProvider -{ - private AgentsClient? _agentsClient; - - /// - /// Gets an active client instance. - /// - public AIProjectClient Client { get; } - - /// - /// Gets an active assistant client instance. - /// - public AgentsClient AgentsClient => this._agentsClient ??= this.Client.GetAgentsClient(); - - /// - /// Configuration keys required for management. - /// - internal IReadOnlyList ConfigurationKeys { get; } - - private AzureAIClientProvider(AIProjectClient client, IEnumerable keys) - { - this.Client = client; - this.ConfigurationKeys = keys.ToArray(); - } - - /// - /// Produces a . - /// - /// The Azure AI Foundry project connection string, in the form `endpoint;subscription_id;resource_group_name;project_name`. - /// A credential used to authenticate to an Azure Service. - /// A custom for HTTP requests. - public static AzureAIClientProvider FromConnectionString( - string connectionString, - TokenCredential credential, - HttpClient? httpClient = null) - { - Verify.NotNullOrWhiteSpace(connectionString, nameof(connectionString)); - Verify.NotNull(credential, nameof(credential)); - - AIProjectClientOptions clientOptions = CreateAzureClientOptions(httpClient); - - return new(new AIProjectClient(connectionString, credential, clientOptions), CreateConfigurationKeys(connectionString, httpClient)); - } - - /// - /// Provides a client instance directly. - /// - public static AzureAIClientProvider FromClient(AIProjectClient client) - { - return new(client, [client.GetType().FullName!, client.GetHashCode().ToString()]); - } - - internal static AIProjectClientOptions CreateAzureClientOptions(HttpClient? httpClient) - { - AIProjectClientOptions options = - new() - { - Diagnostics = { - ApplicationId = HttpHeaderConstant.Values.UserAgent, - } - }; - - options.AddPolicy(new SemanticKernelHeadersPolicy(), HttpPipelinePosition.PerCall); - - if (httpClient is not null) - { - options.Transport = new HttpClientTransport(httpClient); - // Disable retry policy if and only if a custom HttpClient is provided. - options.RetryPolicy = new RetryPolicy(maxRetries: 0); - } - - return options; - } - - private static IEnumerable CreateConfigurationKeys(string connectionString, HttpClient? httpClient) - { - yield return connectionString; - - if (httpClient is not null) - { - if (httpClient.BaseAddress is not null) - { - yield return httpClient.BaseAddress.AbsoluteUri; - } - - foreach (string header in httpClient.DefaultRequestHeaders.SelectMany(h => h.Value)) - { - yield return header; - } - } - } - - private class SemanticKernelHeadersPolicy : HttpPipelineSynchronousPolicy - { - public override void OnSendingRequest(HttpMessage message) - { - message.Request.Headers.Add( - HttpHeaderConstant.Names.SemanticKernelVersion, - HttpHeaderConstant.Values.GetAssemblyVersion(typeof(AzureAIAgent))); - } - } -} diff --git a/dotnet/src/Agents/AzureAI/AzureAIThreadMessageFactory.cs b/dotnet/src/Agents/AzureAI/AzureAIThreadMessageFactory.cs index d37242c522ed..c5199fb146c2 100644 --- a/dotnet/src/Agents/AzureAI/AzureAIThreadMessageFactory.cs +++ b/dotnet/src/Agents/AzureAI/AzureAIThreadMessageFactory.cs @@ -1,6 +1,6 @@ // Copyright (c) Microsoft. All rights reserved. using System.Collections.Generic; -using Azure.AI.Projects; +using Azure.AI.Agents.Persistent; using Microsoft.SemanticKernel.Agents.AzureAI.Internal; namespace Microsoft.SemanticKernel.Agents.AzureAI; diff --git a/dotnet/src/Agents/AzureAI/Definition/AzureAIAgentFactory.cs b/dotnet/src/Agents/AzureAI/Definition/AzureAIAgentFactory.cs index 5bd22137292f..b7e169af2dbb 100644 --- a/dotnet/src/Agents/AzureAI/Definition/AzureAIAgentFactory.cs +++ b/dotnet/src/Agents/AzureAI/Definition/AzureAIAgentFactory.cs @@ -3,7 +3,7 @@ using System.Diagnostics.CodeAnalysis; using System.Threading; using System.Threading.Tasks; -using Azure.AI.Projects; +using Azure.AI.Agents.Persistent; namespace Microsoft.SemanticKernel.Agents.AzureAI; @@ -33,14 +33,13 @@ public AzureAIAgentFactory() if (agentDefinition.Type?.Equals(AzureAIAgentType, System.StringComparison.Ordinal) ?? false) { - var projectClient = agentDefinition.GetAIProjectClient(kernel); + var client = agentDefinition.GetAgentsClient(kernel); - AgentsClient client = projectClient.GetAgentsClient(); - Azure.AI.Projects.Agent agent; + PersistentAgent agent; if (!string.IsNullOrEmpty(agentDefinition.Id)) { // Get an existing agent - agent = await client.GetAgentAsync( + agent = await client.Administration.GetAgentAsync( agentDefinition.Id, cancellationToken: cancellationToken).ConfigureAwait(false); @@ -57,7 +56,7 @@ public AzureAIAgentFactory() Verify.NotNull(agentDefinition.Model); Verify.NotNull(agentDefinition.Model.Id); - agent = await client.CreateAgentAsync( + agent = await client.Administration.CreateAgentAsync( model: agentDefinition.Model.Id, name: agentDefinition.Name, description: agentDefinition.Description, diff --git a/dotnet/src/Agents/AzureAI/Extensions/AgentDefinitionExtensions.cs b/dotnet/src/Agents/AzureAI/Extensions/AgentDefinitionExtensions.cs index 1f11bc5f0260..517266c0fc38 100644 --- a/dotnet/src/Agents/AzureAI/Extensions/AgentDefinitionExtensions.cs +++ b/dotnet/src/Agents/AzureAI/Extensions/AgentDefinitionExtensions.cs @@ -2,7 +2,7 @@ using System; using System.Collections.Generic; using System.Linq; -using Azure.AI.Projects; +using Azure.AI.Agents.Persistent; using Azure.Core; using Microsoft.Extensions.DependencyInjection; using Microsoft.SemanticKernel.Http; @@ -20,24 +20,20 @@ internal static class AgentDefinitionExtensions private const string CodeInterpreterType = "code_interpreter"; private const string FileSearchType = "file_search"; private const string FunctionType = "function"; - private const string MicrosoftFabricType = "fabric_aiskill"; private const string OpenApiType = "openapi"; - private const string SharepointGroundingType = "sharepoint_grounding"; - private static readonly string[] s_validToolTypes = new string[] - { + private static readonly string[] s_validToolTypes = + [ AzureAISearchType, AzureFunctionType, BingGroundingType, CodeInterpreterType, FileSearchType, FunctionType, - MicrosoftFabricType, OpenApiType, - SharepointGroundingType - }; + ]; - private const string ConnectionString = "connection_string"; + private const string Endpoint = "endpoint"; /// /// Return the Azure AI tool definitions which corresponds with the provided . @@ -58,9 +54,7 @@ public static IEnumerable GetAzureToolDefinitions(this AgentDefi CodeInterpreterType => CreateCodeInterpreterToolDefinition(tool), FileSearchType => CreateFileSearchToolDefinition(tool), FunctionType => CreateFunctionToolDefinition(tool), - MicrosoftFabricType => CreateMicrosoftFabricToolDefinition(tool), OpenApiType => CreateOpenApiToolDefinition(tool), - SharepointGroundingType => CreateSharepointGroundingToolDefinition(tool), _ => throw new NotSupportedException($"Unable to create Azure AI tool definition because of unsupported tool type: {tool.Type}, supported tool types are: {string.Join(",", s_validToolTypes)}"), }; }) ?? []; @@ -108,11 +102,11 @@ public static ToolResources GetAzureToolResources(this AgentDefinition agentDefi } /// - /// Return the to be used with the specified . + /// Return the to be used with the specified . /// - /// Agent definition which will be used to provide connection for the . - /// Kernel instance which will be used to resolve a default . - public static AIProjectClient GetAIProjectClient(this AgentDefinition agentDefinition, Kernel kernel) + /// Agent definition which will be used to provide connection for the . + /// Kernel instance which will be used to resolve a default . + public static PersistentAgentsClient GetAgentsClient(this AgentDefinition agentDefinition, Kernel kernel) { Verify.NotNull(agentDefinition); @@ -120,21 +114,20 @@ public static AIProjectClient GetAIProjectClient(this AgentDefinition agentDefin var connection = agentDefinition?.Model?.Connection; if (connection is not null) { - if (connection.ExtensionData.TryGetValue(ConnectionString, out var value) && value is string connectionString) + if (connection.ExtensionData.TryGetValue(Endpoint, out var value) && value is string endpoint) { #pragma warning disable CA2000 // Dispose objects before losing scope, not relevant because the HttpClient is created and may be used elsewhere var httpClient = HttpClientProvider.GetHttpClient(kernel.Services); #pragma warning restore CA2000 // Dispose objects before losing scope - AIProjectClientOptions clientOptions = AzureAIClientProvider.CreateAzureClientOptions(httpClient); var tokenCredential = kernel.Services.GetRequiredService(); - return new(connectionString, tokenCredential, clientOptions); + return AzureAIAgent.CreateAgentsClient(endpoint, tokenCredential, httpClient); } } // Return the client registered on the kernel - var client = kernel.GetAllServices().FirstOrDefault(); - return (AIProjectClient?)client ?? throw new InvalidOperationException("AzureAI project client not found."); + var client = kernel.GetAllServices().FirstOrDefault(); + return (PersistentAgentsClient?)client ?? throw new InvalidOperationException("AzureAI project client not found."); } #region private @@ -184,7 +177,7 @@ public static AIProjectClient GetAIProjectClient(this AgentDefinition agentDefin return null; } - private static AzureAISearchResource? GetAzureAISearchResource(this AgentDefinition agentDefinition) + private static AzureAISearchToolResource? GetAzureAISearchResource(this AgentDefinition agentDefinition) { Verify.NotNull(agentDefinition); @@ -205,7 +198,7 @@ public static AIProjectClient GetAIProjectClient(this AgentDefinition agentDefin string filter = azureAISearch.GetFilter() ?? string.Empty; AzureAISearchQueryType? queryType = azureAISearch.GetAzureAISearchQueryType(); - return new AzureAISearchResource(indexConnectionId, indexName, topK, filter, queryType); + return new AzureAISearchToolResource(indexConnectionId, indexName, topK, filter, queryType); } return null; @@ -237,9 +230,9 @@ private static BingGroundingToolDefinition CreateBingGroundingToolDefinition(Age { Verify.NotNull(tool); - ToolConnectionList bingGrounding = tool.GetToolConnectionList(); + BingGroundingSearchToolParameters bingToolParameters = new(tool.GetToolConnections().Select(connectionId => new BingGroundingSearchConfiguration(connectionId))); - return new BingGroundingToolDefinition(bingGrounding); + return new BingGroundingToolDefinition(bingToolParameters); } private static CodeInterpreterToolDefinition CreateCodeInterpreterToolDefinition(AgentToolDefinition tool) @@ -270,15 +263,6 @@ private static FunctionToolDefinition CreateFunctionToolDefinition(AgentToolDefi return new FunctionToolDefinition(name, description, parameters); } - private static MicrosoftFabricToolDefinition CreateMicrosoftFabricToolDefinition(AgentToolDefinition tool) - { - Verify.NotNull(tool); - - ToolConnectionList fabricAiSkill = tool.GetToolConnectionList(); - - return new MicrosoftFabricToolDefinition(fabricAiSkill); - } - private static OpenApiToolDefinition CreateOpenApiToolDefinition(AgentToolDefinition tool) { Verify.NotNull(tool); @@ -292,14 +276,5 @@ private static OpenApiToolDefinition CreateOpenApiToolDefinition(AgentToolDefini return new OpenApiToolDefinition(name, description, spec, auth); } - - private static SharepointToolDefinition CreateSharepointGroundingToolDefinition(AgentToolDefinition tool) - { - Verify.NotNull(tool); - - ToolConnectionList sharepointGrounding = tool.GetToolConnectionList(); - - return new SharepointToolDefinition(sharepointGrounding); - } #endregion } diff --git a/dotnet/src/Agents/AzureAI/Extensions/AgentRunExtensions.cs b/dotnet/src/Agents/AzureAI/Extensions/AgentRunExtensions.cs index 733494140711..53133baafd07 100644 --- a/dotnet/src/Agents/AzureAI/Extensions/AgentRunExtensions.cs +++ b/dotnet/src/Agents/AzureAI/Extensions/AgentRunExtensions.cs @@ -1,11 +1,11 @@ // Copyright (c) Microsoft. All rights reserved. using System; using System.Collections.Generic; -using System.Linq; using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; -using Azure.AI.Projects; +using Azure; +using Azure.AI.Agents.Persistent; using Microsoft.SemanticKernel.Agents.AzureAI.Internal; namespace Microsoft.SemanticKernel.Agents.AzureAI.Extensions; @@ -19,24 +19,19 @@ namespace Microsoft.SemanticKernel.Agents.AzureAI.Extensions; internal static class AgentRunExtensions { public static async IAsyncEnumerable GetStepsAsync( - this AgentsClient client, - ThreadRun run, - [EnumeratorCancellation] CancellationToken cancellationToken) + this PersistentAgentsClient client, + ThreadRun run, + [EnumeratorCancellation] CancellationToken cancellationToken) { - PageableList? steps = null; - do + AsyncPageable? steps = client.Runs.GetRunStepsAsync(run, cancellationToken: cancellationToken); + await foreach (RunStep step in steps.ConfigureAwait(false)) { - steps = await client.GetRunStepsAsync(run, after: steps?.LastId, cancellationToken: cancellationToken).ConfigureAwait(false); - foreach (RunStep step in steps) - { - yield return step; - } + yield return step; } - while (steps?.HasMore ?? false); } public static async Task CreateAsync( - this AgentsClient client, + this PersistentAgentsClient client, string threadId, AzureAIAgent agent, string? instructions, @@ -44,16 +39,16 @@ public static async Task CreateAsync( AzureAIInvocationOptions? invocationOptions, CancellationToken cancellationToken) { - TruncationObject? truncationStrategy = GetTruncationStrategy(invocationOptions); + Truncation? truncationStrategy = GetTruncationStrategy(invocationOptions); BinaryData? responseFormat = GetResponseFormat(invocationOptions); return - await client.CreateRunAsync( + await client.Runs.CreateRunAsync( threadId, - agent.Definition.Id, + agent.Id, overrideModelName: invocationOptions?.ModelName, overrideInstructions: invocationOptions?.OverrideInstructions ?? instructions, additionalInstructions: invocationOptions?.AdditionalInstructions, - additionalMessages: AgentMessageFactory.GetThreadMessages(invocationOptions?.AdditionalMessages).ToArray(), + additionalMessages: [.. AgentMessageFactory.GetThreadMessages(invocationOptions?.AdditionalMessages)], overrideTools: tools, stream: false, temperature: invocationOptions?.Temperature, @@ -72,11 +67,12 @@ await client.CreateRunAsync( private static BinaryData? GetResponseFormat(AzureAIInvocationOptions? invocationOptions) { return invocationOptions?.EnableJsonResponse == true ? - BinaryData.FromString(ResponseFormat.JsonObject.ToString()) : + //BinaryData.FromString(ResponseFormat.JsonObject.ToString()) : + BinaryData.FromString("// %%% TODO") : null; } - private static TruncationObject? GetTruncationStrategy(AzureAIInvocationOptions? invocationOptions) + private static Truncation? GetTruncationStrategy(AzureAIInvocationOptions? invocationOptions) { return invocationOptions?.TruncationMessageCount == null ? null : @@ -87,7 +83,7 @@ await client.CreateRunAsync( } public static IAsyncEnumerable CreateStreamingAsync( - this AgentsClient client, + this PersistentAgentsClient client, string threadId, AzureAIAgent agent, string? instructions, @@ -95,16 +91,16 @@ public static IAsyncEnumerable CreateStreamingAsync( AzureAIInvocationOptions? invocationOptions, CancellationToken cancellationToken) { - TruncationObject? truncationStrategy = GetTruncationStrategy(invocationOptions); + Truncation? truncationStrategy = GetTruncationStrategy(invocationOptions); BinaryData? responseFormat = GetResponseFormat(invocationOptions); return - client.CreateRunStreamingAsync( + client.Runs.CreateRunStreamingAsync( threadId, - agent.Definition.Id, + agent.Id, overrideModelName: invocationOptions?.ModelName, overrideInstructions: invocationOptions?.OverrideInstructions ?? instructions, additionalInstructions: invocationOptions?.AdditionalInstructions, - additionalMessages: AgentMessageFactory.GetThreadMessages(invocationOptions?.AdditionalMessages).ToArray(), + additionalMessages: [.. AgentMessageFactory.GetThreadMessages(invocationOptions?.AdditionalMessages)], overrideTools: tools, temperature: invocationOptions?.Temperature, topP: invocationOptions?.TopP, diff --git a/dotnet/src/Agents/AzureAI/Extensions/AgentToolDefinitionExtensions.cs b/dotnet/src/Agents/AzureAI/Extensions/AgentToolDefinitionExtensions.cs index e85092fe2470..053c8dc52ffd 100644 --- a/dotnet/src/Agents/AzureAI/Extensions/AgentToolDefinitionExtensions.cs +++ b/dotnet/src/Agents/AzureAI/Extensions/AgentToolDefinitionExtensions.cs @@ -3,7 +3,7 @@ using System; using System.Collections.Generic; using System.Linq; -using Azure.AI.Projects; +using Azure.AI.Agents.Persistent; namespace Microsoft.SemanticKernel.Agents.AzureAI; @@ -75,20 +75,6 @@ internal static FileSearchToolDefinitionDetails GetFileSearchToolDefinitionDetai return details; } - internal static ToolConnectionList GetToolConnectionList(this AgentToolDefinition agentToolDefinition) - { - Verify.NotNull(agentToolDefinition.Options); - - var toolConnections = agentToolDefinition.GetToolConnections(); - - var toolConnectionList = new ToolConnectionList(); - if (toolConnections is not null) - { - toolConnectionList.ConnectionList.AddRange(toolConnections); - } - return toolConnectionList; - } - internal static BinaryData GetSpecification(this AgentToolDefinition agentToolDefinition) { Verify.NotNull(agentToolDefinition.Options); @@ -121,7 +107,7 @@ internal static OpenApiAuthDetails GetOpenApiAuthDetails(this AgentToolDefinitio internal static List? GetVectorStoreIds(this AgentToolDefinition agentToolDefinition) { - return agentToolDefinition.GetOption>("vector_store_ids")?.Select(id => id.ToString()!).ToList(); + return agentToolDefinition.GetOption>("vector_store_ids")?.Select(id => $"{id}").ToList(); } internal static List? GetFileIds(this AgentToolDefinition agentToolDefinition) @@ -236,13 +222,13 @@ private static AzureFunctionBinding GetAzureFunctionBinding(this AgentToolDefini return null; } - private static List GetToolConnections(this AgentToolDefinition agentToolDefinition) + internal static List GetToolConnections(this AgentToolDefinition agentToolDefinition) { Verify.NotNull(agentToolDefinition.Options); - var toolConnections = agentToolDefinition.GetRequiredOption>("tool_connections"); + List toolConnections = agentToolDefinition.GetRequiredOption>("tool_connections"); - return [.. toolConnections.Select(connectionId => new ToolConnection(connectionId.ToString()))]; + return [.. toolConnections.Select(connectionId => $"{connectionId}")]; } private static T GetRequiredOption(this AgentToolDefinition agentToolDefinition, string key) diff --git a/dotnet/src/Agents/AzureAI/Extensions/KernelFunctionExtensions.cs b/dotnet/src/Agents/AzureAI/Extensions/KernelFunctionExtensions.cs index e6b9c722eabb..39ed1b4bac8c 100644 --- a/dotnet/src/Agents/AzureAI/Extensions/KernelFunctionExtensions.cs +++ b/dotnet/src/Agents/AzureAI/Extensions/KernelFunctionExtensions.cs @@ -1,6 +1,6 @@ // Copyright (c) Microsoft. All rights reserved. using System; -using Azure.AI.Projects; +using Azure.AI.Agents.Persistent; namespace Microsoft.SemanticKernel.Agents.AzureAI; diff --git a/dotnet/src/Agents/AzureAI/Internal/AgentMessageFactory.cs b/dotnet/src/Agents/AzureAI/Internal/AgentMessageFactory.cs index 621e364acf6a..7be5906ec5c6 100644 --- a/dotnet/src/Agents/AzureAI/Internal/AgentMessageFactory.cs +++ b/dotnet/src/Agents/AzureAI/Internal/AgentMessageFactory.cs @@ -1,7 +1,7 @@ // Copyright (c) Microsoft. All rights reserved. using System.Collections.Generic; using System.Linq; -using Azure.AI.Projects; +using Azure.AI.Agents.Persistent; using Microsoft.SemanticKernel.ChatCompletion; namespace Microsoft.SemanticKernel.Agents.AzureAI.Internal; @@ -15,7 +15,7 @@ namespace Microsoft.SemanticKernel.Agents.AzureAI.Internal; internal static class AgentMessageFactory { /// - /// Translate metadata from a to be used for a or + /// Translate metadata from a to be used for a or /// . /// /// The message content. @@ -25,7 +25,7 @@ public static Dictionary GetMetadata(ChatMessageContent message) } /// - /// Translate attachments from a to be used for a or + /// Translate attachments from a to be used for a or /// /// The message content. public static IEnumerable GetAttachments(ChatMessageContent message) @@ -35,7 +35,7 @@ public static IEnumerable GetAttachments(ChatMessageContent m .OfType() .Select( fileContent => - new MessageAttachment(fileContent.FileId, GetToolDefinition(fileContent.Tools).ToList())); + new MessageAttachment(fileContent.FileId, [.. GetToolDefinition(fileContent.Tools)])); } /// @@ -58,7 +58,7 @@ public static IEnumerable GetThreadMessages(IEnumerableThe assistant client /// The to monitor for cancellation requests. The default is . /// The thread identifier - public static async Task CreateThreadAsync(AgentsClient client, CancellationToken cancellationToken = default) + public static async Task CreateThreadAsync(PersistentAgentsClient client, CancellationToken cancellationToken = default) { - AAIP.AgentThread thread = await client.CreateThreadAsync(cancellationToken: cancellationToken).ConfigureAwait(false); + PersistentAgentThread thread = await client.Threads.CreateThreadAsync(cancellationToken: cancellationToken).ConfigureAwait(false); return thread.Id; } @@ -59,7 +58,7 @@ public static async Task CreateThreadAsync(AgentsClient client, Cancella /// The message to add /// The to monitor for cancellation requests. The default is . /// if a system message is present, without taking any other action - public static async Task CreateMessageAsync(AgentsClient client, string threadId, ChatMessageContent message, CancellationToken cancellationToken) + public static async Task CreateMessageAsync(PersistentAgentsClient client, string threadId, ChatMessageContent message, CancellationToken cancellationToken) { if (message.Items.Any(i => i is FunctionCallContent)) { @@ -72,7 +71,7 @@ public static async Task CreateMessageAsync(AgentsClient client, string threadId return; } - await client.CreateMessageAsync( + await client.Messages.CreateMessageAsync( threadId, role: message.Role == AuthorRole.User ? MessageRole.User : MessageRole.Agent, content, @@ -89,39 +88,35 @@ await client.CreateMessageAsync( /// The order to return messages in. /// The to monitor for cancellation requests. The default is . /// Asynchronous enumeration of messages. - public static async IAsyncEnumerable GetMessagesAsync(AgentsClient client, string threadId, ListSortOrder? messageOrder, [EnumeratorCancellation] CancellationToken cancellationToken) + public static async IAsyncEnumerable GetMessagesAsync(PersistentAgentsClient client, string threadId, ListSortOrder? messageOrder, [EnumeratorCancellation] CancellationToken cancellationToken) { Dictionary agentNames = []; // Cache agent names by their identifier string? lastId = null; - PageableList? messages = null; - do + AsyncPageable? messages = client.Messages.GetMessagesAsync(threadId, runId: null, limit: null, messageOrder ?? ListSortOrder.Descending, after: lastId, before: null, cancellationToken); + await foreach (PersistentThreadMessage message in messages.ConfigureAwait(false)) { - messages = await client.GetMessagesAsync(threadId, runId: null, limit: null, messageOrder ?? ListSortOrder.Descending, after: lastId, before: null, cancellationToken).ConfigureAwait(false); - foreach (ThreadMessage message in messages) + lastId = message.Id; + string? assistantName = null; + if (!string.IsNullOrWhiteSpace(message.AssistantId) && + !agentNames.TryGetValue(message.AssistantId, out assistantName)) { - lastId = message.Id; - string? assistantName = null; - if (!string.IsNullOrWhiteSpace(message.AssistantId) && - !agentNames.TryGetValue(message.AssistantId, out assistantName)) + PersistentAgent assistant = await client.Administration.GetAgentAsync(message.AssistantId, cancellationToken).ConfigureAwait(false); + if (!string.IsNullOrWhiteSpace(assistant.Name)) { - Azure.AI.Projects.Agent assistant = await client.GetAgentAsync(message.AssistantId, cancellationToken).ConfigureAwait(false); - if (!string.IsNullOrWhiteSpace(assistant.Name)) - { - agentNames.Add(assistant.Id, assistant.Name); - } + agentNames.Add(assistant.Id, assistant.Name); } + } - assistantName ??= message.AssistantId; + assistantName ??= message.AssistantId; - ChatMessageContent content = GenerateMessageContent(assistantName, message); + ChatMessageContent content = GenerateMessageContent(assistantName, message); - if (content.Items.Count > 0) - { - yield return content; - } + if (content.Items.Count > 0) + { + yield return content; } - } while (messages?.HasMore ?? false); + } } /// @@ -140,7 +135,7 @@ public static async IAsyncEnumerable GetMessagesAsync(Agents /// Asynchronous enumeration of messages. public static async IAsyncEnumerable<(bool IsVisible, ChatMessageContent Message)> InvokeAsync( AzureAIAgent agent, - AgentsClient client, + PersistentAgentsClient client, string threadId, AzureAIInvocationOptions? invocationOptions, ILogger logger, @@ -186,7 +181,7 @@ public static async IAsyncEnumerable GetMessagesAsync(Agents throw new KernelException($"Agent Failure - Run terminated: {run.Status} [{run.Id}]: {run.LastError?.Message ?? "Unknown"}"); } - RunStep[] steps = await client.GetStepsAsync(run, cancellationToken).ToArrayAsync(cancellationToken).ConfigureAwait(false); + RunStep[] steps = await client.GetStepsAsync(run, cancellationToken: cancellationToken).ToArrayAsync(cancellationToken).ConfigureAwait(false); // Is tool action required? if (run.Status == RunStatus.RequiresAction) @@ -220,7 +215,7 @@ await functionProcessor.InvokeFunctionCallsAsync( // Process tool output ToolOutput[] toolOutputs = GenerateToolOutputs(functionResults); - await client.SubmitToolOutputsToRunAsync(run, toolOutputs, cancellationToken).ConfigureAwait(false); + await client.Runs.SubmitToolOutputsToRunAsync(run, toolOutputs, cancellationToken).ConfigureAwait(false); } logger.LogAzureAIAgentProcessedRunSteps(nameof(InvokeAsync), functionCalls.Length, run.Id, threadId); @@ -270,7 +265,7 @@ await functionProcessor.InvokeFunctionCallsAsync( { // Retrieve the message RunStepMessageCreationDetails messageDetails = (RunStepMessageCreationDetails)completedStep.StepDetails; - ThreadMessage? message = await RetrieveMessageAsync(client, threadId, messageDetails.MessageCreation.MessageId, agent.PollingOptions.MessageSynchronizationDelay, cancellationToken).ConfigureAwait(false); + PersistentThreadMessage? message = await RetrieveMessageAsync(client, threadId, messageDetails.MessageCreation.MessageId, agent.PollingOptions.MessageSynchronizationDelay, cancellationToken).ConfigureAwait(false); if (message is not null) { @@ -315,7 +310,7 @@ async Task PollRunStatusAsync() try { - run = await client.GetRunAsync(threadId, run.Id, cancellationToken).ConfigureAwait(false); + run = await client.Runs.GetRunAsync(threadId, run.Id, cancellationToken).ConfigureAwait(false); } // The presence of a `Status` code means the server responded with error...always fail in that case catch (ClientResultException clientException) when (clientException.Status <= 0) @@ -371,7 +366,7 @@ async Task PollRunStatusAsync() /// public static async IAsyncEnumerable InvokeStreamingAsync( AzureAIAgent agent, - AgentsClient client, + PersistentAgentsClient client, string threadId, IList? messages, AzureAIInvocationOptions? invocationOptions, @@ -497,7 +492,7 @@ await functionProcessor.InvokeFunctionCallsAsync( // Process tool output ToolOutput[] toolOutputs = GenerateToolOutputs(functionResults); - asyncUpdates = client.SubmitToolOutputsToStreamAsync(run, toolOutputs, cancellationToken); + asyncUpdates = client.Runs.SubmitToolOutputsToStreamAsync(run, toolOutputs, cancellationToken); foreach (RunStep step in activeSteps) { @@ -514,7 +509,7 @@ await functionProcessor.InvokeFunctionCallsAsync( { if (step.StepDetails is RunStepMessageCreationDetails messageDetails) { - ThreadMessage? message = + PersistentThreadMessage? message = await RetrieveMessageAsync( client, threadId, @@ -555,17 +550,17 @@ await RetrieveMessageAsync( logger.LogAzureAIAgentCompletedRun(nameof(InvokeAsync), run?.Id ?? "Failed", threadId); } - private static ChatMessageContent GenerateMessageContent(string? assistantName, ThreadMessage message, RunStep? completedStep = null, ILogger? logger = null) + private static ChatMessageContent GenerateMessageContent(string? assistantName, PersistentThreadMessage message, RunStep? completedStep = null, ILogger? logger = null) { AuthorRole role = new(message.Role.ToString()); Dictionary? metadata = new() { - { nameof(ThreadMessage.CreatedAt), message.CreatedAt }, - { nameof(ThreadMessage.AssistantId), message.AssistantId }, - { nameof(ThreadMessage.ThreadId), message.ThreadId }, - { nameof(ThreadMessage.RunId), message.RunId }, + { nameof(PersistentThreadMessage.CreatedAt), message.CreatedAt }, + { nameof(PersistentThreadMessage.AssistantId), message.AssistantId }, + { nameof(PersistentThreadMessage.ThreadId), message.ThreadId }, + { nameof(PersistentThreadMessage.RunId), message.RunId }, { nameof(MessageContentUpdate.MessageId), message.Id }, }; @@ -696,16 +691,16 @@ private static StreamingChatMessageContent GenerateStreamingMessageContent(strin EndIndex = fileCitationAnnotation.EndIndex, }; } - if (annotation is MessageTextUrlCitationAnnotation urlCitationAnnotation) + if (annotation is MessageTextUriCitationAnnotation urlCitationAnnotation) { return new AnnotationContent( kind: AnnotationKind.UrlCitation, label: annotation.Text, - referenceId: urlCitationAnnotation.UrlCitation.Url) + referenceId: urlCitationAnnotation.UriCitation.Uri) { InnerContent = annotation, - Title = urlCitationAnnotation.UrlCitation.Title, + Title = urlCitationAnnotation.UriCitation.Title, StartIndex = urlCitationAnnotation.StartIndex, EndIndex = urlCitationAnnotation.EndIndex, }; @@ -883,9 +878,9 @@ private static ToolOutput[] GenerateToolOutputs(FunctionResultContent[] function return toolOutputs; } - private static async Task RetrieveMessageAsync(AgentsClient client, string threadId, string messageId, TimeSpan syncDelay, CancellationToken cancellationToken) + private static async Task RetrieveMessageAsync(PersistentAgentsClient client, string threadId, string messageId, TimeSpan syncDelay, CancellationToken cancellationToken) { - ThreadMessage? message = null; + PersistentThreadMessage? message = null; bool retry = false; int count = 0; @@ -893,7 +888,7 @@ private static ToolOutput[] GenerateToolOutputs(FunctionResultContent[] function { try { - message = await client.GetMessageAsync(threadId, messageId, cancellationToken).ConfigureAwait(false); + message = await client.Messages.GetMessageAsync(threadId, messageId, cancellationToken).ConfigureAwait(false); } catch (RequestFailedException exception) { diff --git a/dotnet/src/Agents/AzureAI/Logging/AgentThreadActionsLogMessages.cs b/dotnet/src/Agents/AzureAI/Logging/AgentThreadActionsLogMessages.cs index 27b38bbb7456..0acfc010163a 100644 --- a/dotnet/src/Agents/AzureAI/Logging/AgentThreadActionsLogMessages.cs +++ b/dotnet/src/Agents/AzureAI/Logging/AgentThreadActionsLogMessages.cs @@ -1,7 +1,7 @@ // Copyright (c) Microsoft. All rights reserved. using System; using System.Diagnostics.CodeAnalysis; -using Azure.AI.Projects; +using Azure.AI.Agents.Persistent; using Microsoft.Extensions.Logging; using Microsoft.SemanticKernel.Agents.AzureAI.Internal; diff --git a/dotnet/src/Agents/OpenAI/Extensions/AgentDefinitionExtensions.cs b/dotnet/src/Agents/OpenAI/Extensions/AgentDefinitionExtensions.cs index 88470519ac77..fa62275d0d25 100644 --- a/dotnet/src/Agents/OpenAI/Extensions/AgentDefinitionExtensions.cs +++ b/dotnet/src/Agents/OpenAI/Extensions/AgentDefinitionExtensions.cs @@ -4,7 +4,6 @@ using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; -using Azure.AI.OpenAI; using Azure.Core; using Microsoft.Extensions.DependencyInjection; using Microsoft.SemanticKernel.Http; @@ -140,22 +139,20 @@ public static OpenAIClient GetOpenAIClient(this AgentDefinition agentDefinition, if (connection.Type.Equals(OpenAI, StringComparison.OrdinalIgnoreCase)) { - OpenAIClientOptions clientOptions = OpenAIClientProvider.CreateOpenAIClientOptions(connection.TryGetEndpoint(), httpClient); - return new OpenAIClient(connection.GetApiKeyCredential(), clientOptions); + return OpenAIAssistantAgent.CreateOpenAIClient(connection.GetApiKeyCredential(), connection.TryGetEndpoint(), httpClient); } else if (connection.Type.Equals(AzureOpenAI, StringComparison.OrdinalIgnoreCase)) { var endpoint = connection.TryGetEndpoint(); Verify.NotNull(endpoint, "Endpoint must be specified when using Azure OpenAI."); - AzureOpenAIClientOptions clientOptions = OpenAIClientProvider.CreateAzureClientOptions(httpClient); if (connection.ExtensionData.TryGetValue(ApiKey, out var apiKey) && apiKey is not null) { - return new AzureOpenAIClient(endpoint, connection.GetApiKeyCredential(), clientOptions); + return OpenAIAssistantAgent.CreateAzureOpenAIClient(connection.GetApiKeyCredential(), endpoint, httpClient); } var tokenCredential = kernel.Services.GetRequiredService(); - return new AzureOpenAIClient(endpoint, tokenCredential, clientOptions); + return OpenAIAssistantAgent.CreateAzureOpenAIClient(tokenCredential, endpoint, httpClient); } throw new InvalidOperationException($"Invalid OpenAI client type '{connection.Type}' was specified."); diff --git a/dotnet/src/Agents/OpenAI/OpenAIClientProvider.cs b/dotnet/src/Agents/OpenAI/OpenAIClientProvider.cs index ebb8fcdce542..9c157d9fa125 100644 --- a/dotnet/src/Agents/OpenAI/OpenAIClientProvider.cs +++ b/dotnet/src/Agents/OpenAI/OpenAIClientProvider.cs @@ -19,6 +19,7 @@ namespace Microsoft.SemanticKernel.Agents.OpenAI; /// Provides an for use by . /// [Experimental("SKEXP0110")] +[Obsolete("Use OpenAIAssistantAgent.CreateAzureOpenAIClient(...) or OpenAIAssistantAgent.CreateOpenAIClient(...)")] public sealed class OpenAIClientProvider { /// diff --git a/dotnet/src/Agents/UnitTests/AzureAI/AzureAIClientProviderTests.cs b/dotnet/src/Agents/UnitTests/AzureAI/AzureAIClientProviderTests.cs deleted file mode 100644 index 96ddfb046896..000000000000 --- a/dotnet/src/Agents/UnitTests/AzureAI/AzureAIClientProviderTests.cs +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. -using System; -using System.Net.Http; -using Azure.AI.Projects; -using Azure.Identity; -using Microsoft.SemanticKernel.Agents.AzureAI; -using Moq; -using Xunit; - -namespace SemanticKernel.Agents.UnitTests.AzureAI; - -/// -/// Unit testing of . -/// -public class AzureAIClientProviderTests -{ - /// - /// Verify that provisioning of client for Azure OpenAI. - /// - [Fact] - public void VerifyAzureAIClientProviderDefault() - { - // Act - AzureAIClientProvider provider = AzureAIClientProvider.FromConnectionString("test;test;test;test", new AzureCliCredential()); - - // Assert - Assert.NotNull(provider.Client); - } - - /// - /// Verify that the factory can create a client with http proxy. - /// - [Fact] - public void VerifyAzureAIClientProviderWithHttpClient() - { - // Arrange - using HttpClient httpClient = new() { BaseAddress = new Uri("http://myproxy:9819") }; - - // Act - AzureAIClientProvider provider = AzureAIClientProvider.FromConnectionString("test;test;test;test", new AzureCliCredential(), httpClient); - - // Assert - Assert.NotNull(provider.Client); - - // Arrange - using HttpClient httpClientWithHeaders = new() { BaseAddress = new Uri("http://myproxy:9819") }; - httpClientWithHeaders.DefaultRequestHeaders.Add("X-Test", "Test"); - - // Act - AzureAIClientProvider providerWithHeaders = AzureAIClientProvider.FromConnectionString("test;test;test;test", new AzureCliCredential(), httpClientWithHeaders); - - // Assert - Assert.NotNull(providerWithHeaders.Client); - - Assert.NotEqual(provider.ConfigurationKeys.Count, providerWithHeaders.ConfigurationKeys.Count); - } - - /// - /// Verify that the factory can accept an client that already exists. - /// - [Fact] - public void VerifyAzureAIClientProviderFromClient() - { - // Arrange - Mock mockClient = new(); - AzureAIClientProvider provider = AzureAIClientProvider.FromClient(mockClient.Object); - - // Assert - Assert.NotNull(provider.Client); - Assert.Equal(mockClient.Object, provider.Client); - } -} diff --git a/dotnet/src/Agents/UnitTests/AzureAI/Definition/AzureAIAgentFactoryTests.cs b/dotnet/src/Agents/UnitTests/AzureAI/Definition/AzureAIAgentFactoryTests.cs index c21fbfb03f67..d0aa27fa1d38 100644 --- a/dotnet/src/Agents/UnitTests/AzureAI/Definition/AzureAIAgentFactoryTests.cs +++ b/dotnet/src/Agents/UnitTests/AzureAI/Definition/AzureAIAgentFactoryTests.cs @@ -4,7 +4,7 @@ using System.Net; using System.Net.Http; using System.Threading.Tasks; -using Azure.AI.Projects; +using Azure.AI.Agents.Persistent; using Azure.Core.Pipeline; using Microsoft.Extensions.DependencyInjection; using Microsoft.SemanticKernel; @@ -32,12 +32,14 @@ public AzureAIAgentFactoryTests() this._httpClient = new HttpClient(this._messageHandlerStub, disposeHandler: false); var builder = Kernel.CreateBuilder(); - var client = new AIProjectClient( - "endpoint;subscription_id;resource_group_name;project_name", + var client = new PersistentAgentsClient( + "https://test", new FakeTokenCredential(), - new AIProjectClientOptions() - { Transport = new HttpClientTransport(this._httpClient) }); - builder.Services.AddSingleton(client); + new PersistentAgentsAdministrationClientOptions + { + Transport = new HttpClientTransport(this._httpClient) + }); + builder.Services.AddSingleton(client); this._kernel = builder.Build(); } diff --git a/dotnet/src/Agents/UnitTests/AzureAI/Extensions/KernelFunctionExtensionsTests.cs b/dotnet/src/Agents/UnitTests/AzureAI/Extensions/KernelFunctionExtensionsTests.cs index cb8fe8415b97..298d22eae529 100644 --- a/dotnet/src/Agents/UnitTests/AzureAI/Extensions/KernelFunctionExtensionsTests.cs +++ b/dotnet/src/Agents/UnitTests/AzureAI/Extensions/KernelFunctionExtensionsTests.cs @@ -1,7 +1,7 @@ // Copyright (c) Microsoft. All rights reserved. using System; using System.ComponentModel; -using Azure.AI.Projects; +using Azure.AI.Agents.Persistent; using Microsoft.SemanticKernel; using Microsoft.SemanticKernel.Agents.AzureAI; using Xunit; diff --git a/dotnet/src/Agents/UnitTests/AzureAI/Internal/AgentMessageFactoryTests.cs b/dotnet/src/Agents/UnitTests/AzureAI/Internal/AgentMessageFactoryTests.cs index c42de6fc38a2..99e47fb9f155 100644 --- a/dotnet/src/Agents/UnitTests/AzureAI/Internal/AgentMessageFactoryTests.cs +++ b/dotnet/src/Agents/UnitTests/AzureAI/Internal/AgentMessageFactoryTests.cs @@ -1,7 +1,7 @@ // Copyright (c) Microsoft. All rights reserved. using System; using System.Linq; -using Azure.AI.Projects; +using Azure.AI.Agents.Persistent; using Microsoft.SemanticKernel; using Microsoft.SemanticKernel.Agents.AzureAI.Internal; using Microsoft.SemanticKernel.ChatCompletion; diff --git a/dotnet/src/Agents/UnitTests/OpenAI/Definition/OpenAIAssistantAgentFactoryTests.cs b/dotnet/src/Agents/UnitTests/OpenAI/Definition/OpenAIAssistantAgentFactoryTests.cs index 6dcb0280bec7..72c45009084c 100644 --- a/dotnet/src/Agents/UnitTests/OpenAI/Definition/OpenAIAssistantAgentFactoryTests.cs +++ b/dotnet/src/Agents/UnitTests/OpenAI/Definition/OpenAIAssistantAgentFactoryTests.cs @@ -31,8 +31,7 @@ public OpenAIAssistantAgentFactoryTests() this._messageHandlerStub = new HttpMessageHandlerStub(); this._httpClient = new HttpClient(this._messageHandlerStub, disposeHandler: false); - OpenAIClientOptions clientOptions = OpenAIClientProvider.CreateOpenAIClientOptions(endpoint: null, httpClient: this._httpClient); - OpenAIClient openAIClient = new(new ApiKeyCredential("fakekey"), clientOptions); + OpenAIClient openAIClient = OpenAIAssistantAgent.CreateOpenAIClient(new ApiKeyCredential("fakekey"), httpClient: this._httpClient); var builder = Kernel.CreateBuilder(); builder.Services.AddSingleton(openAIClient); diff --git a/dotnet/src/Agents/UnitTests/OpenAI/Extensions/AssistantClientExtensionsTests.cs b/dotnet/src/Agents/UnitTests/OpenAI/Extensions/AssistantClientExtensionsTests.cs index f1cdd1e429cd..6e87bb686555 100644 --- a/dotnet/src/Agents/UnitTests/OpenAI/Extensions/AssistantClientExtensionsTests.cs +++ b/dotnet/src/Agents/UnitTests/OpenAI/Extensions/AssistantClientExtensionsTests.cs @@ -8,6 +8,7 @@ using Microsoft.SemanticKernel; using Microsoft.SemanticKernel.Agents.OpenAI; using Microsoft.SemanticKernel.ChatCompletion; +using OpenAI; using OpenAI.Assistants; using Xunit; @@ -22,7 +23,7 @@ public sealed class AssistantClientExtensionsTests : IDisposable private readonly HttpMessageHandlerStub _messageHandlerStub; private readonly HttpClient _httpClient; - private readonly OpenAIClientProvider _clientProvider; + private readonly OpenAIClient _client; /// /// Verify the assistant creation with default values. @@ -34,7 +35,7 @@ public async Task VerifyCreateAssistantAsync() this.SetupResponse(HttpStatusCode.OK, OpenAIAssistantResponseContent.AssistantDefinition(ModelValue)); // Act - Assistant definition = await this._clientProvider.AssistantClient.CreateAssistantAsync(modelId: ModelValue); + Assistant definition = await this._client.GetAssistantClient().CreateAssistantAsync(modelId: ModelValue); // Assert Assert.NotNull(definition); @@ -61,7 +62,7 @@ public async Task VerifyCreateAssistantWithIdentityAsync() description: DescriptionValue)); // Act - Assistant definition = await this._clientProvider.AssistantClient.CreateAssistantAsync( + Assistant definition = await this._client.GetAssistantClient().CreateAssistantAsync( modelId: ModelValue, name: NameValue, instructions: InstructionsValue, @@ -99,7 +100,7 @@ public async Task VerifyCreateAssistantWithTemplateAsync() description: DescriptionValue)); // Act - Assistant definition = await this._clientProvider.AssistantClient.CreateAssistantFromTemplateAsync(modelId: ModelValue, templateConfig); + Assistant definition = await this._client.GetAssistantClient().CreateAssistantFromTemplateAsync(modelId: ModelValue, templateConfig); // Assert Assert.NotNull(definition); @@ -120,7 +121,7 @@ public async Task VerifyCreateAssistantWithCodeInterpreterAsync() OpenAIAssistantResponseContent.AssistantDefinition(ModelValue, enableCodeInterpreter: true)); // Act - Assistant definition = await this._clientProvider.AssistantClient.CreateAssistantAsync( + Assistant definition = await this._client.GetAssistantClient().CreateAssistantAsync( modelId: ModelValue, enableCodeInterpreter: true); @@ -143,7 +144,7 @@ public async Task VerifyCreateAssistantWithCodeInterpreterFilesAsync() OpenAIAssistantResponseContent.AssistantDefinition(ModelValue, codeInterpreterFileIds: fileIds)); // Act - Assistant definition = await this._clientProvider.AssistantClient.CreateAssistantAsync( + Assistant definition = await this._client.GetAssistantClient().CreateAssistantAsync( modelId: ModelValue, codeInterpreterFileIds: fileIds); @@ -167,7 +168,7 @@ public async Task VerifyCreateAssistantWithFileSearchAsync() OpenAIAssistantResponseContent.AssistantDefinition(ModelValue, enableFileSearch: true)); // Act - Assistant definition = await this._clientProvider.AssistantClient.CreateAssistantAsync( + Assistant definition = await this._client.GetAssistantClient().CreateAssistantAsync( modelId: ModelValue, enableFileSearch: true); @@ -190,7 +191,7 @@ public async Task VerifyCreateAssistantWithVectorStoreAsync() OpenAIAssistantResponseContent.AssistantDefinition(ModelValue, vectorStoreId: VectorStoreValue)); // Act - Assistant definition = await this._clientProvider.AssistantClient.CreateAssistantAsync( + Assistant definition = await this._client.GetAssistantClient().CreateAssistantAsync( modelId: ModelValue, vectorStoreId: VectorStoreValue); @@ -214,7 +215,7 @@ public async Task VerifyCreateAssistantWithTemperatureAsync() this.SetupResponse(HttpStatusCode.OK, OpenAIAssistantResponseContent.AssistantDefinition("testmodel", temperature: TemperatureValue)); // Act - Assistant definition = await this._clientProvider.AssistantClient.CreateAssistantAsync( + Assistant definition = await this._client.GetAssistantClient().CreateAssistantAsync( modelId: "testmodel", temperature: TemperatureValue); @@ -235,7 +236,7 @@ public async Task VerifyCreateAssistantWithTopPAsync() this.SetupResponse(HttpStatusCode.OK, OpenAIAssistantResponseContent.AssistantDefinition("testmodel", topP: TopPValue)); // Act - Assistant definition = await this._clientProvider.AssistantClient.CreateAssistantAsync( + Assistant definition = await this._client.GetAssistantClient().CreateAssistantAsync( modelId: "testmodel", topP: TopPValue); @@ -261,7 +262,7 @@ public async Task VerifyCreateAssistantWithMetadataAsync() this.SetupResponse(HttpStatusCode.OK, OpenAIAssistantResponseContent.AssistantDefinition("testmodel", metadata: metadata)); // Act - Assistant definition = await this._clientProvider.AssistantClient.CreateAssistantAsync( + Assistant definition = await this._client.GetAssistantClient().CreateAssistantAsync( modelId: "testmodel", metadata: metadata); @@ -280,7 +281,7 @@ public async Task VerifyDeleteAssistantAsync() this.SetupResponse(HttpStatusCode.OK, OpenAIAssistantResponseContent.DeleteAgent); // Act - AssistantDeletionResult result = await this._clientProvider.AssistantClient.DeleteAssistantAsync("testid"); + AssistantDeletionResult result = await this._client.GetAssistantClient().DeleteAssistantAsync("testid"); // Assert Assert.True(result.Deleted); @@ -296,7 +297,7 @@ public async Task VerifyCreateThreadAsync() this.SetupResponse(HttpStatusCode.OK, OpenAIAssistantResponseContent.CreateThread); // Act - string threadId = await this._clientProvider.AssistantClient.CreateThreadAsync(messages: null); + string threadId = await this._client.GetAssistantClient().CreateThreadAsync(messages: null); // Assert Assert.NotNull(threadId); @@ -312,7 +313,7 @@ public async Task VerifyCreateThreadWithMessagesAsync() this.SetupResponse(HttpStatusCode.OK, OpenAIAssistantResponseContent.CreateThread); // Act - string threadId = await this._clientProvider.AssistantClient.CreateThreadAsync(messages: [new ChatMessageContent(AuthorRole.User, "test")]); + string threadId = await this._client.GetAssistantClient().CreateThreadAsync(messages: [new ChatMessageContent(AuthorRole.User, "test")]); // Assert Assert.NotNull(threadId); @@ -329,7 +330,7 @@ public async Task VerifyCreateThreadWithMetadataAsync() Dictionary metadata = new() { { "a", "1" }, { "b", "2" } }; // Act - string threadId = await this._clientProvider.AssistantClient.CreateThreadAsync(metadata: metadata); + string threadId = await this._client.GetAssistantClient().CreateThreadAsync(metadata: metadata); // Assert Assert.NotNull(threadId); @@ -349,7 +350,7 @@ public AssistantClientExtensionsTests() { this._messageHandlerStub = new HttpMessageHandlerStub(); this._httpClient = new HttpClient(this._messageHandlerStub, disposeHandler: false); - this._clientProvider = OpenAIClientProvider.ForOpenAI(apiKey: new ApiKeyCredential("fakekey"), endpoint: null, this._httpClient); + this._client = OpenAIAssistantAgent.CreateOpenAIClient(apiKey: new ApiKeyCredential("fakekey"), endpoint: null, this._httpClient); } private void SetupResponse(HttpStatusCode statusCode, string content) => diff --git a/dotnet/src/Agents/UnitTests/OpenAI/Extensions/OpenAIClientExtensionsTests.cs b/dotnet/src/Agents/UnitTests/OpenAI/Extensions/OpenAIClientExtensionsTests.cs index ce03e8f5843e..92b8279629e6 100644 --- a/dotnet/src/Agents/UnitTests/OpenAI/Extensions/OpenAIClientExtensionsTests.cs +++ b/dotnet/src/Agents/UnitTests/OpenAI/Extensions/OpenAIClientExtensionsTests.cs @@ -8,6 +8,7 @@ using System.Text; using System.Threading.Tasks; using Microsoft.SemanticKernel.Agents.OpenAI; +using OpenAI; using OpenAI.VectorStores; using Xunit; @@ -20,7 +21,7 @@ public sealed class OpenAIClientExtensionsTests : IDisposable { private readonly HttpMessageHandlerStub _messageHandlerStub; private readonly HttpClient _httpClient; - private readonly OpenAIClientProvider _clientProvider; + private readonly OpenAIClient _client; /// /// Verify the default creation of vector-store. @@ -33,7 +34,7 @@ public async Task VerifyCreateDefaultVectorStoreAsync() this.SetupResponse(HttpStatusCode.OK, OpenAIAssistantResponseContent.CreateVectorStore); // Act - string storeId = await this._clientProvider.Client.CreateVectorStoreAsync(fileIds, waitUntilCompleted: false); + string storeId = await this._client.CreateVectorStoreAsync(fileIds, waitUntilCompleted: false); // Assert Assert.NotNull(storeId); @@ -56,7 +57,7 @@ public async Task VerifyCreateVectorStoreAsync() this.SetupResponse(HttpStatusCode.OK, OpenAIAssistantResponseContent.CreateVectorStore); // Act - string storeId = await this._clientProvider.Client.CreateVectorStoreAsync( + string storeId = await this._client.CreateVectorStoreAsync( fileIds, waitUntilCompleted: false, storeName: "test-store", @@ -79,7 +80,7 @@ public async Task VerifyUploadFileAsync() // Act await using MemoryStream stream = new(Encoding.UTF8.GetBytes("test")); - string fileId = await this._clientProvider.Client.UploadAssistantFileAsync(stream, "text.txt"); + string fileId = await this._client.UploadAssistantFileAsync(stream, "text.txt"); // Assert Assert.NotNull(fileId); @@ -95,7 +96,7 @@ public async Task VerifyDeleteFileAsync() this.SetupResponse(HttpStatusCode.OK, OpenAIAssistantResponseContent.DeleteFile); // Act - bool isDeleted = await this._clientProvider.Client.DeleteFileAsync("file-id"); + bool isDeleted = await this._client.DeleteFileAsync("file-id"); // Assert Assert.True(isDeleted); @@ -111,7 +112,7 @@ public async Task VerifyDeleteVectorStoreAsync() this.SetupResponse(HttpStatusCode.OK, OpenAIAssistantResponseContent.DeleteVectorStore); // Act - bool isDeleted = await this._clientProvider.Client.DeleteVectorStoreAsync("store-id"); + bool isDeleted = await this._client.DeleteVectorStoreAsync("store-id"); // Assert Assert.True(isDeleted); @@ -131,7 +132,7 @@ public OpenAIClientExtensionsTests() { this._messageHandlerStub = new HttpMessageHandlerStub(); this._httpClient = new HttpClient(this._messageHandlerStub, disposeHandler: false); - this._clientProvider = OpenAIClientProvider.ForOpenAI(apiKey: new ApiKeyCredential("fakekey"), endpoint: null, this._httpClient); + this._client = OpenAIAssistantAgent.CreateOpenAIClient(apiKey: new ApiKeyCredential("fakekey"), endpoint: null, this._httpClient); } private void SetupResponse(HttpStatusCode statusCode, string content) => diff --git a/dotnet/src/Agents/UnitTests/OpenAI/OpenAIAssistantAgentTests.cs b/dotnet/src/Agents/UnitTests/OpenAI/OpenAIAssistantAgentTests.cs index a5bd93969b41..73b6933c2a47 100644 --- a/dotnet/src/Agents/UnitTests/OpenAI/OpenAIAssistantAgentTests.cs +++ b/dotnet/src/Agents/UnitTests/OpenAI/OpenAIAssistantAgentTests.cs @@ -309,7 +309,7 @@ public async Task VerifyOpenAIAssistantAgentRetrievalAsync() OpenAIAssistantAgent agent = await OpenAIAssistantAgent.RetrieveAsync( - this.CreateTestProvider(), + this.CreateTestClient(), "#id", this._emptyKernel); @@ -330,7 +330,7 @@ public async Task VerifyOpenAIAssistantAgentRetrievalWithFactoryAsync() OpenAIAssistantAgent agent = await OpenAIAssistantAgent.RetrieveAsync( - this.CreateTestProvider(), + this.CreateTestClient(), "#id", this._emptyKernel, [], @@ -748,7 +748,7 @@ public async Task VerifyOpenAIAssistantAgentListDefinitionAsync() // Act var messages = await OpenAIAssistantAgent.ListDefinitionsAsync( - this.CreateTestProvider()).ToArrayAsync(); + this.CreateTestClient()).ToArrayAsync(); // Assert Assert.Equal(7, messages.Length); @@ -761,7 +761,7 @@ await OpenAIAssistantAgent.ListDefinitionsAsync( // Act messages = await OpenAIAssistantAgent.ListDefinitionsAsync( - this.CreateTestProvider()).ToArrayAsync(); + this.CreateTestClient()).ToArrayAsync(); // Assert Assert.Equal(4, messages.Length); } @@ -823,7 +823,7 @@ private async Task VerifyAgentCreationAsync(OpenAIAssistantDefinition definition OpenAIAssistantAgent agent = await OpenAIAssistantAgent.CreateAsync( - this.CreateTestProvider(), + this.CreateTestClient(), definition, this._emptyKernel); @@ -839,7 +839,7 @@ private async Task VerifyAgentTemplateAsync( OpenAIAssistantAgent agent = await OpenAIAssistantAgent.CreateFromTemplateAsync( - this.CreateTestProvider(), + this.CreateTestClient(), capabilities, this._emptyKernel, [], @@ -938,12 +938,12 @@ private Task CreateAgentAsync() return OpenAIAssistantAgent.CreateAsync( - this.CreateTestProvider(), + this.CreateTestClient(), definition, this._emptyKernel); } - private OpenAIClientProvider CreateTestProvider(bool targetAzure = false) + private OpenAIClientProvider CreateTestClient(bool targetAzure = false) => targetAzure ? OpenAIClientProvider.ForAzureOpenAI(apiKey: new ApiKeyCredential("fakekey"), endpoint: new Uri("https://localhost"), this._httpClient) : OpenAIClientProvider.ForOpenAI(apiKey: new ApiKeyCredential("fakekey"), endpoint: null, this._httpClient); diff --git a/dotnet/src/Agents/UnitTests/OpenAI/OpenAIAssistantAgentThreadTests.cs b/dotnet/src/Agents/UnitTests/OpenAI/OpenAIAssistantAgentThreadTests.cs index c7a520ea4295..5b2c5bc18abe 100644 --- a/dotnet/src/Agents/UnitTests/OpenAI/OpenAIAssistantAgentThreadTests.cs +++ b/dotnet/src/Agents/UnitTests/OpenAI/OpenAIAssistantAgentThreadTests.cs @@ -9,6 +9,7 @@ using Microsoft.SemanticKernel.Agents.OpenAI; using Microsoft.SemanticKernel.ChatCompletion; using Moq; +using OpenAI; using OpenAI.Assistants; using Xunit; @@ -75,10 +76,9 @@ public async Task CreateShouldInvokeClientAsync() // Arrange this._messageHandlerStub.SetupResponses(HttpStatusCode.OK, OpenAIAssistantResponseContent.CreateThread); - var provider = this.CreateTestProvider(); - var assistantClient = provider.AssistantClient; + var client = this.CreateTestClient(); - var thread = new OpenAIAssistantAgentThread(assistantClient); + var thread = new OpenAIAssistantAgentThread(client.GetAssistantClient()); // Act await thread.CreateAsync(); @@ -97,10 +97,9 @@ public async Task CreateWithOptionsShouldInvokeClientAsync() // Arrange this._messageHandlerStub.SetupResponses(HttpStatusCode.OK, OpenAIAssistantResponseContent.CreateThread); - var provider = this.CreateTestProvider(); - var assistantClient = provider.AssistantClient; + var client = this.CreateTestClient(); - var thread = new OpenAIAssistantAgentThread(assistantClient, new ThreadCreationOptions()); + var thread = new OpenAIAssistantAgentThread(client.GetAssistantClient(), new ThreadCreationOptions()); // Act await thread.CreateAsync(); @@ -119,10 +118,9 @@ public async Task CreateWithParamsShouldInvokeClientAsync() // Arrange this._messageHandlerStub.SetupResponses(HttpStatusCode.OK, OpenAIAssistantResponseContent.CreateThread); - var provider = this.CreateTestProvider(); - var assistantClient = provider.AssistantClient; + var client = this.CreateTestClient(); - var thread = new OpenAIAssistantAgentThread(assistantClient, [new ChatMessageContent(AuthorRole.User, "Hello")]); + var thread = new OpenAIAssistantAgentThread(client.GetAssistantClient(), [new ChatMessageContent(AuthorRole.User, "Hello")]); // Act await thread.CreateAsync(); @@ -142,10 +140,9 @@ public async Task DeleteShouldInvokeClientAsync() this._messageHandlerStub.SetupResponses(HttpStatusCode.OK, OpenAIAssistantResponseContent.CreateThread); this._messageHandlerStub.SetupResponses(HttpStatusCode.OK, OpenAIAssistantResponseContent.DeleteThread); - var provider = this.CreateTestProvider(); - var assistantClient = provider.AssistantClient; + var client = this.CreateTestClient(); - var thread = new OpenAIAssistantAgentThread(assistantClient); + var thread = new OpenAIAssistantAgentThread(client.GetAssistantClient()); await thread.CreateAsync(); // Act @@ -164,6 +161,6 @@ public void Dispose() GC.SuppressFinalize(this); } - private OpenAIClientProvider CreateTestProvider() - => OpenAIClientProvider.ForOpenAI(apiKey: new ApiKeyCredential("fakekey"), endpoint: null, this._httpClient); + private OpenAIClient CreateTestClient() + => OpenAIAssistantAgent.CreateOpenAIClient(apiKey: new ApiKeyCredential("fakekey"), endpoint: null, this._httpClient); } diff --git a/dotnet/src/Agents/UnitTests/Yaml/AgentYamlTests.cs b/dotnet/src/Agents/UnitTests/Yaml/AgentYamlTests.cs index eff4b579ebf0..e7c23cce73db 100644 --- a/dotnet/src/Agents/UnitTests/Yaml/AgentYamlTests.cs +++ b/dotnet/src/Agents/UnitTests/Yaml/AgentYamlTests.cs @@ -1,11 +1,10 @@ // Copyright (c) Microsoft. All rights reserved. using System; -using System.ClientModel; using System.Net; using System.Net.Http; using System.Threading.Tasks; -using Azure.AI.Projects; +using Azure.AI.Agents.Persistent; using Azure.Core.Pipeline; using Microsoft.Extensions.DependencyInjection; using Microsoft.SemanticKernel; @@ -40,17 +39,18 @@ public AgentYamlTests() var builder = Kernel.CreateBuilder(); // Add OpenAI client - OpenAIClientOptions clientOptions = OpenAIClientProvider.CreateOpenAIClientOptions(endpoint: null, httpClient: this._httpClient); - OpenAIClient openAIClient = new(new ApiKeyCredential("fakekey"), clientOptions); - builder.Services.AddSingleton(openAIClient); + OpenAIClient openAIClient = OpenAIAssistantAgent.CreateOpenAIClient(new System.ClientModel.ApiKeyCredential("fakekey"), httpClient: this._httpClient); + builder.Services.AddSingleton(openAIClient); // Add Azure AI agents client - var client = new AIProjectClient( - "endpoint;subscription_id;resource_group_name;project_name", + var client = new PersistentAgentsClient( + "https://endpoint", new FakeTokenCredential(), - new AIProjectClientOptions() - { Transport = new HttpClientTransport(this._httpClient) }); - builder.Services.AddSingleton(client); + new PersistentAgentsAdministrationClientOptions + { + Transport = new HttpClientTransport(this._httpClient) + }); + builder.Services.AddSingleton(client); this._kernel = builder.Build(); } diff --git a/dotnet/src/Agents/UnitTests/Yaml/AzureAIKernelAgentYamlTests.cs b/dotnet/src/Agents/UnitTests/Yaml/AzureAIKernelAgentYamlTests.cs index dd464faf189d..ea0fef2986c0 100644 --- a/dotnet/src/Agents/UnitTests/Yaml/AzureAIKernelAgentYamlTests.cs +++ b/dotnet/src/Agents/UnitTests/Yaml/AzureAIKernelAgentYamlTests.cs @@ -7,7 +7,7 @@ using System.Text; using System.Text.Json; using System.Threading.Tasks; -using Azure.AI.Projects; +using Azure.AI.Agents.Persistent; using Azure.Core.Pipeline; using Microsoft.Extensions.DependencyInjection; using Microsoft.SemanticKernel; @@ -38,12 +38,14 @@ public AzureAIKernelAgentYamlTests() var builder = Kernel.CreateBuilder(); // Add Azure AI agents client - var client = new AIProjectClient( - "endpoint;subscription_id;resource_group_name;project_name", + var client = new PersistentAgentsClient( + "https://test", new FakeTokenCredential(), - new AIProjectClientOptions() - { Transport = new HttpClientTransport(this._httpClient) }); - builder.Services.AddSingleton(client); + new PersistentAgentsAdministrationClientOptions + { + Transport = new HttpClientTransport(this._httpClient) + }); + builder.Services.AddSingleton(client); this._kernel = builder.Build(); this._kernel.Plugins.Add(KernelPluginFactory.CreateFromType()); @@ -217,42 +219,6 @@ public async Task VerifyRequestIncludesBingGroundingAsync() Assert.Equal("bing_grounding", requestJson.GetProperty("tools")[0].GetProperty("type").GetString()); } - /// - /// Verify the request includes a Microsoft Fabric tool when creating an Azure AI agent. - /// - [Fact] - public async Task VerifyRequestIncludesMicrosoftFabricAsync() - { - // Arrange - const string Text = - """ - type: foundry_agent - name: FoundryAgent - description: AzureAIAgent Description - instructions: AzureAIAgent Instructions - model: - id: gpt-4o-mini - tools: - - type: fabric_aiskill - options: - tool_connections: - - connection_string - """; - AzureAIAgentFactory factory = new(); - this.SetupResponse(HttpStatusCode.OK, AzureAIAgentFactoryTests.AzureAIAgentCreateResponse); - - // Act - var agent = await factory.CreateAgentFromYamlAsync(Text, new() { Kernel = this._kernel }); - - // Assert - Assert.NotNull(agent); - var requestContent = Encoding.UTF8.GetString(this._messageHandlerStub.RequestContent!); - Assert.NotNull(requestContent); - var requestJson = JsonSerializer.Deserialize(requestContent); - Assert.Equal(1, requestJson.GetProperty("tools").GetArrayLength()); - Assert.Equal("fabric_dataagent", requestJson.GetProperty("tools")[0].GetProperty("type").GetString()); - } - /// /// Verify the request includes a Open API tool when creating an Azure AI agent. /// @@ -306,42 +272,6 @@ public async Task VerifyRequestIncludesOpenAPIAsync() Assert.Equal("openapi", requestJson.GetProperty("tools")[2].GetProperty("type").GetString()); } - /// - /// Verify the request includes a Sharepoint tool when creating an Azure AI agent. - /// - [Fact] - public async Task VerifyRequestIncludesSharepointGroundingAsync() - { - // Arrange - const string Text = - """ - type: foundry_agent - name: FoundryAgent - description: AzureAIAgent Description - instructions: AzureAIAgent Instructions - model: - id: gpt-4o-mini - tools: - - type: sharepoint_grounding - options: - tool_connections: - - connection_string - """; - AzureAIAgentFactory factory = new(); - this.SetupResponse(HttpStatusCode.OK, AzureAIAgentFactoryTests.AzureAIAgentCreateResponse); - - // Act - var agent = await factory.CreateAgentFromYamlAsync(Text, new() { Kernel = this._kernel }); - - // Assert - Assert.NotNull(agent); - var requestContent = Encoding.UTF8.GetString(this._messageHandlerStub.RequestContent!); - Assert.NotNull(requestContent); - var requestJson = JsonSerializer.Deserialize(requestContent); - Assert.Equal(1, requestJson.GetProperty("tools").GetArrayLength()); - Assert.Equal("sharepoint_grounding", requestJson.GetProperty("tools")[0].GetProperty("type").GetString()); - } - /// /// Verify the request includes a code interpreter tool and associated resource when creating an Azure AI agent. /// diff --git a/dotnet/src/Experimental/Process.Abstractions/Process.Abstractions.csproj b/dotnet/src/Experimental/Process.Abstractions/Process.Abstractions.csproj index 82ceb5372f15..f4af8d637107 100644 --- a/dotnet/src/Experimental/Process.Abstractions/Process.Abstractions.csproj +++ b/dotnet/src/Experimental/Process.Abstractions/Process.Abstractions.csproj @@ -40,7 +40,6 @@ - diff --git a/dotnet/src/Experimental/Process.LocalRuntime/Process.LocalRuntime.csproj b/dotnet/src/Experimental/Process.LocalRuntime/Process.LocalRuntime.csproj index d5f245549da4..270e25bf7421 100644 --- a/dotnet/src/Experimental/Process.LocalRuntime/Process.LocalRuntime.csproj +++ b/dotnet/src/Experimental/Process.LocalRuntime/Process.LocalRuntime.csproj @@ -41,7 +41,6 @@ - diff --git a/dotnet/src/IntegrationTests/Agents/AzureAIAgentTests.cs b/dotnet/src/IntegrationTests/Agents/AzureAIAgentTests.cs index df336f5f62e2..6fabcf07dbc6 100644 --- a/dotnet/src/IntegrationTests/Agents/AzureAIAgentTests.cs +++ b/dotnet/src/IntegrationTests/Agents/AzureAIAgentTests.cs @@ -1,8 +1,9 @@ // Copyright (c) Microsoft. All rights reserved. +using System; using System.Linq; using System.Threading.Tasks; -using Azure.AI.Projects; +using Azure.AI.Agents.Persistent; using Azure.Identity; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; @@ -21,16 +22,14 @@ public class AzureAIAgentTests { private readonly Kernel _kernel; private readonly AzureAIConfiguration _configuration; - private readonly AIProjectClient _client; - private readonly AgentsClient _agentsClient; + private readonly PersistentAgentsClient _client; public AzureAIAgentTests() { var kernelBuilder = Kernel.CreateBuilder(); this._kernel = kernelBuilder.Build(); this._configuration = this.ReadAzureConfiguration(); - this._client = AzureAIAgent.CreateAzureAIClient(this._configuration.ConnectionString!, new AzureCliCredential()); - this._agentsClient = this._client.GetAgentsClient(); + this._client = AzureAIAgent.CreateAgentsClient(this._configuration.Endpoint, new AzureCliCredential()); } /// @@ -40,14 +39,14 @@ public AzureAIAgentTests() public async Task AzureAIAgentWithThreadCustomOptionsAsync() { var aiAgent = - await this._agentsClient.CreateAgentAsync( + await this._client.Administration.CreateAgentAsync( this._configuration.ChatModelId, name: "HelpfulAssistant", description: "Helpful Assistant", instructions: "You are a helpful assistant."); - var agent = new AzureAIAgent(aiAgent, this._agentsClient) { Kernel = this._kernel }; + var agent = new AzureAIAgent(aiAgent, this._client) { Kernel = this._kernel }; - AzureAIAgentThread agentThread = new(this._agentsClient); + AzureAIAgentThread agentThread = new(this._client); try { @@ -63,7 +62,7 @@ await this._agentsClient.CreateAgentAsync( finally { await agentThread.DeleteAsync(); - await this._agentsClient.DeleteAgentAsync(agent.Id); + await this._client.Administration.DeleteAgentAsync(agent.Id); } } @@ -74,14 +73,14 @@ await this._agentsClient.CreateAgentAsync( public async Task AzureAIAgentWithThreadCustomOptionsStreamingAsync() { var aiAgent = - await this._agentsClient.CreateAgentAsync( + await this._client.Administration.CreateAgentAsync( this._configuration.ChatModelId, name: "HelpfulAssistant", description: "Helpful Assistant", instructions: "You are a helpful assistant."); - var agent = new AzureAIAgent(aiAgent, this._agentsClient) { Kernel = this._kernel }; + var agent = new AzureAIAgent(aiAgent, this._client) { Kernel = this._kernel }; - AzureAIAgentThread agentThread = new(this._agentsClient); + AzureAIAgentThread agentThread = new(this._client); try { @@ -97,7 +96,7 @@ await this._agentsClient.CreateAgentAsync( finally { await agentThread.DeleteAsync(); - await this._agentsClient.DeleteAgentAsync(agent.Id); + await this._client.Administration.DeleteAgentAsync(agent.Id); } } @@ -108,7 +107,7 @@ await this._agentsClient.CreateAgentAsync( public async Task AzureAIAgentDeclarativeAsync() { var builder = Kernel.CreateBuilder(); - builder.Services.AddSingleton(this._client); + builder.Services.AddSingleton(this._client); var kernel = builder.Build(); var text = @@ -125,7 +124,7 @@ public async Task AzureAIAgentDeclarativeAsync() var agent = await factory.CreateAgentFromYamlAsync(text, new() { Kernel = kernel }); Assert.NotNull(agent); - AzureAIAgentThread agentThread = new(this._agentsClient); + AzureAIAgentThread agentThread = new(this._client); try { var response = await agent.InvokeAsync("What is the capital of France?", agentThread).FirstAsync(); @@ -135,7 +134,7 @@ public async Task AzureAIAgentDeclarativeAsync() finally { await agentThread.DeleteAsync(); - await this._agentsClient.DeleteAgentAsync(agent.Id); + await this._client.Administration.DeleteAgentAsync(agent.Id); } } diff --git a/dotnet/src/IntegrationTests/Agents/CommonInterfaceConformance/AzureAIAgentFixture.cs b/dotnet/src/IntegrationTests/Agents/CommonInterfaceConformance/AzureAIAgentFixture.cs index 769e3daec9d7..7c64a525b3fb 100644 --- a/dotnet/src/IntegrationTests/Agents/CommonInterfaceConformance/AzureAIAgentFixture.cs +++ b/dotnet/src/IntegrationTests/Agents/CommonInterfaceConformance/AzureAIAgentFixture.cs @@ -1,7 +1,9 @@ // Copyright (c) Microsoft. All rights reserved. +using System; using System.Threading.Tasks; using Azure; +using Azure.AI.Agents.Persistent; using Azure.Identity; using Microsoft.Extensions.Configuration; using Microsoft.SemanticKernel; @@ -9,7 +11,6 @@ using Microsoft.SemanticKernel.Agents.AzureAI; using Microsoft.SemanticKernel.ChatCompletion; using SemanticKernel.IntegrationTests.TestSettings; -using AAIP = Azure.AI.Projects; namespace SemanticKernel.IntegrationTests.Agents.CommonInterfaceConformance; @@ -22,8 +23,8 @@ public class AzureAIAgentFixture : AgentFixture .AddUserSecrets() .Build(); - private AAIP.AgentsClient? _agentsClient; - private AAIP.Agent? _aiAgent; + private PersistentAgentsClient? _agentsClient; + private PersistentAgent? _aiAgent; private AzureAIAgent? _agent; private AzureAIAgentThread? _thread; private AzureAIAgentThread? _createdThread; @@ -43,7 +44,7 @@ public class AzureAIAgentFixture : AgentFixture public override async Task GetChatHistory() { var chatHistory = new ChatHistory(); - await foreach (var existingMessage in this._thread!.GetMessagesAsync(AAIP.ListSortOrder.Ascending).ConfigureAwait(false)) + await foreach (var existingMessage in this._thread!.GetMessagesAsync(ListSortOrder.Ascending).ConfigureAwait(false)) { chatHistory.Add(existingMessage); } @@ -52,7 +53,7 @@ public override async Task GetChatHistory() public override Task DeleteThread(AgentThread thread) { - return this._agentsClient!.DeleteThreadAsync(thread.Id); + return this._agentsClient!.Threads.DeleteThreadAsync(thread.Id); } public override async Task DisposeAsync() @@ -61,7 +62,7 @@ public override async Task DisposeAsync() { try { - await this._agentsClient!.DeleteThreadAsync(this._thread!.Id); + await this._agentsClient!.Threads.DeleteThreadAsync(this._thread!.Id); } catch (RequestFailedException ex) when (ex.Status == 404) { @@ -70,7 +71,7 @@ public override async Task DisposeAsync() try { - await this._agentsClient!.DeleteThreadAsync(this._createdThread!.Id); + await this._agentsClient!.Threads.DeleteThreadAsync(this._createdThread!.Id); } catch (RequestFailedException ex) when (ex.Status == 404) { @@ -78,23 +79,22 @@ public override async Task DisposeAsync() try { - await this._agentsClient!.DeleteThreadAsync(this._createdServiceFailingAgentThread!.Id); + await this._agentsClient!.Threads.DeleteThreadAsync(this._createdServiceFailingAgentThread!.Id); } catch (RequestFailedException ex) when (ex.Status == 404) { } - await this._agentsClient!.DeleteAgentAsync(this._aiAgent!.Id); + await this._agentsClient!.Administration.DeleteAgentAsync(this._aiAgent!.Id); } public override async Task InitializeAsync() { AzureAIConfiguration configuration = this._configuration.GetSection("AzureAI").Get()!; - var client = AzureAIAgent.CreateAzureAIClient(configuration.ConnectionString!, new AzureCliCredential()); - this._agentsClient = client.GetAgentsClient(); + this._agentsClient = AzureAIAgent.CreateAgentsClient(configuration.Endpoint, new AzureCliCredential()); this._aiAgent = - await this._agentsClient.CreateAgentAsync( + await this._agentsClient.Administration.CreateAgentAsync( configuration.ChatModelId, name: "HelpfulAssistant", description: "Helpful Assistant", @@ -109,10 +109,10 @@ await this._agentsClient.CreateAgentAsync( this._createdThread = new AzureAIAgentThread(this._agentsClient); await this._createdThread.CreateAsync(); - var serviceFailingClient = AzureAIAgent.CreateAzureAIClient("swedencentral.api.azureml.ms;;;", new AzureCliCredential()); - this._serviceFailingAgentThread = new AzureAIAgentThread(serviceFailingClient.GetAgentsClient()); + var serviceFailingClient = AzureAIAgent.CreateAgentsClient("https://invalid", new AzureCliCredential()); + this._serviceFailingAgentThread = new AzureAIAgentThread(serviceFailingClient); - var createdFailingThreadResponse = await this._agentsClient.CreateThreadAsync(); - this._createdServiceFailingAgentThread = new AzureAIAgentThread(serviceFailingClient.GetAgentsClient(), createdFailingThreadResponse.Value.Id); + var createdFailingThreadResponse = await this._agentsClient.Threads.CreateThreadAsync(); + this._createdServiceFailingAgentThread = new AzureAIAgentThread(serviceFailingClient, createdFailingThreadResponse.Value.Id); } } diff --git a/dotnet/src/IntegrationTests/Agents/MixedAgentTests.cs b/dotnet/src/IntegrationTests/Agents/MixedAgentTests.cs index dd39b660966d..7ec24fbecf4e 100644 --- a/dotnet/src/IntegrationTests/Agents/MixedAgentTests.cs +++ b/dotnet/src/IntegrationTests/Agents/MixedAgentTests.cs @@ -12,6 +12,7 @@ using Microsoft.SemanticKernel.Agents.OpenAI; using Microsoft.SemanticKernel.ChatCompletion; using Microsoft.SemanticKernel.Connectors.OpenAI; +using OpenAI; using OpenAI.Assistants; using SemanticKernel.IntegrationTests.TestSettings; using xRetry; @@ -45,7 +46,7 @@ public async Task OpenAIMixedAgentTestAsync(bool useNewFunctionCallingModel) // Arrange, Act & Assert await this.VerifyAgentExecutionAsync( this.CreateChatCompletionKernel(openAISettings), - OpenAIClientProvider.ForOpenAI(new ApiKeyCredential(openAISettings.ApiKey)), + OpenAIAssistantAgent.CreateOpenAIClient(new ApiKeyCredential(openAISettings.ApiKey)), openAISettings.ChatModelId!, useNewFunctionCallingModel); } @@ -65,14 +66,14 @@ public async Task AzureOpenAIMixedAgentAsync(bool useNewFunctionCallingModel) // Arrange, Act & Assert await this.VerifyAgentExecutionAsync( this.CreateChatCompletionKernel(azureOpenAISettings), - OpenAIClientProvider.ForAzureOpenAI(new AzureCliCredential(), new Uri(azureOpenAISettings.Endpoint)), + OpenAIAssistantAgent.CreateAzureOpenAIClient(new AzureCliCredential(), new Uri(azureOpenAISettings.Endpoint)), azureOpenAISettings.ChatDeploymentName!, useNewFunctionCallingModel); } private async Task VerifyAgentExecutionAsync( Kernel chatCompletionKernel, - OpenAIClientProvider clientProvider, + OpenAIClient client, string modelName, bool useNewFunctionCallingModel) { @@ -95,8 +96,9 @@ private async Task VerifyAgentExecutionAsync( chatAgent.Kernel.Plugins.Add(plugin); // Configure assistant agent with the plugin. - Assistant definition = await clientProvider.AssistantClient.CreateAssistantAsync(modelName, instructions: "Answer questions about the menu."); - OpenAIAssistantAgent assistantAgent = new(definition, clientProvider.AssistantClient, [plugin]); + AssistantClient assistantClient = client.GetAssistantClient(); + Assistant definition = await assistantClient.CreateAssistantAsync(modelName, instructions: "Answer questions about the menu."); + OpenAIAssistantAgent assistantAgent = new(definition, assistantClient, [plugin]); // Act & Assert try @@ -107,7 +109,7 @@ private async Task VerifyAgentExecutionAsync( } finally { - await clientProvider.AssistantClient.DeleteAssistantAsync(assistantAgent.Id); + await assistantClient.DeleteAssistantAsync(assistantAgent.Id); } } diff --git a/dotnet/src/IntegrationTests/Agents/OpenAIAssistantAgentTests.cs b/dotnet/src/IntegrationTests/Agents/OpenAIAssistantAgentTests.cs index 35496121715e..7cef37d82cea 100644 --- a/dotnet/src/IntegrationTests/Agents/OpenAIAssistantAgentTests.cs +++ b/dotnet/src/IntegrationTests/Agents/OpenAIAssistantAgentTests.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; +using Azure.AI.OpenAI; using Azure.Core; using Azure.Identity; using Microsoft.Extensions.Configuration; @@ -14,6 +15,7 @@ using Microsoft.SemanticKernel.Agents; using Microsoft.SemanticKernel.Agents.OpenAI; using Microsoft.SemanticKernel.ChatCompletion; +using OpenAI; using OpenAI.Assistants; using OpenAI.Files; using OpenAI.VectorStores; @@ -46,7 +48,7 @@ public async Task OpenAIAssistantAgentTestAsync(string input, string expectedAns Assert.NotNull(openAISettings); await this.ExecuteAgentAsync( - OpenAIClientProvider.ForOpenAI(new ApiKeyCredential(openAISettings.ApiKey)), + OpenAIAssistantAgent.CreateOpenAIClient(new ApiKeyCredential(openAISettings.ApiKey)), openAISettings.ChatModelId!, input, expectedAnswerContains); @@ -63,8 +65,11 @@ public async Task AzureOpenAIAssistantAgentAsync(string input, string expectedAn var azureOpenAIConfiguration = this._configuration.GetSection("AzureOpenAI").Get(); Assert.NotNull(azureOpenAIConfiguration); + OpenAIClient client = CreateClient(azureOpenAIConfiguration); + AssistantClient assistantClient = client.GetAssistantClient(); + await this.ExecuteAgentAsync( - OpenAIClientProvider.ForAzureOpenAI(new AzureCliCredential(), new Uri(azureOpenAIConfiguration.Endpoint)), + CreateClient(azureOpenAIConfiguration), azureOpenAIConfiguration.ChatDeploymentName!, input, expectedAnswerContains); @@ -82,7 +87,7 @@ public async Task OpenAIAssistantAgentStreamingAsync(string input, string expect Assert.NotNull(openAISettings); await this.ExecuteStreamingAgentAsync( - OpenAIClientProvider.ForOpenAI(new ApiKeyCredential(openAISettings.ApiKey)), + OpenAIAssistantAgent.CreateOpenAIClient(new ApiKeyCredential(openAISettings.ApiKey)), openAISettings.ModelId, input, expectedAnswerContains); @@ -99,7 +104,7 @@ public async Task AzureOpenAIAssistantAgentStreamingAsync(string input, string e AzureOpenAIConfiguration azureOpenAIConfiguration = this.ReadAzureConfiguration(); await this.ExecuteStreamingAgentAsync( - CreateClientProvider(azureOpenAIConfiguration), + CreateClient(azureOpenAIConfiguration), azureOpenAIConfiguration.ChatDeploymentName!, input, expectedAnswerContains); @@ -114,11 +119,12 @@ await this.ExecuteStreamingAgentAsync( public async Task AzureOpenAIAssistantAgentFunctionCallResultAsync() { AzureOpenAIConfiguration azureOpenAIConfiguration = this.ReadAzureConfiguration(); - OpenAIClientProvider clientProvider = CreateClientProvider(azureOpenAIConfiguration); - Assistant definition = await clientProvider.AssistantClient.CreateAssistantAsync(azureOpenAIConfiguration.ChatDeploymentName!); - OpenAIAssistantAgent agent = new(definition, clientProvider.AssistantClient); + OpenAIClient client = CreateClient(azureOpenAIConfiguration); + AssistantClient assistantClient = client.GetAssistantClient(); + Assistant definition = await assistantClient.CreateAssistantAsync(azureOpenAIConfiguration.ChatDeploymentName!); + OpenAIAssistantAgent agent = new(definition, assistantClient); - AssistantThread thread = await clientProvider.AssistantClient.CreateThreadAsync(); + AssistantThread thread = await assistantClient.CreateThreadAsync(); ChatMessageContent functionResultMessage = new(AuthorRole.Assistant, [new FunctionResultContent("mock-function", result: "A result value")]); try { @@ -128,8 +134,8 @@ public async Task AzureOpenAIAssistantAgentFunctionCallResultAsync() } finally { - await clientProvider.AssistantClient.DeleteThreadAsync(thread.Id); - await clientProvider.AssistantClient.DeleteAssistantAsync(agent.Id); + await assistantClient.DeleteThreadAsync(thread.Id); + await assistantClient.DeleteAssistantAsync(agent.Id); } } @@ -142,9 +148,10 @@ public async Task AzureOpenAIAssistantAgentFunctionCallResultAsync() public async Task AzureOpenAIAssistantAgentTokensAsync() { AzureOpenAIConfiguration azureOpenAIConfiguration = this.ReadAzureConfiguration(); - OpenAIClientProvider clientProvider = CreateClientProvider(azureOpenAIConfiguration); - Assistant definition = await clientProvider.AssistantClient.CreateAssistantAsync(azureOpenAIConfiguration.ChatDeploymentName!, instructions: "Repeat the user all of the user messages"); - OpenAIAssistantAgent agent = new(definition, clientProvider.AssistantClient) + OpenAIClient client = CreateClient(azureOpenAIConfiguration); + AssistantClient assistantClient = client.GetAssistantClient(); + Assistant definition = await assistantClient.CreateAssistantAsync(azureOpenAIConfiguration.ChatDeploymentName!, instructions: "Repeat the user all of the user messages"); + OpenAIAssistantAgent agent = new(definition, assistantClient) { RunOptions = new() { @@ -152,7 +159,7 @@ public async Task AzureOpenAIAssistantAgentTokensAsync() } }; - AssistantThread thread = await clientProvider.AssistantClient.CreateThreadAsync(); + AssistantThread thread = await assistantClient.CreateThreadAsync(); ChatMessageContent functionResultMessage = new(AuthorRole.User, "A long time ago there lived a king who was famed for his wisdom through all the land. Nothing was hidden from him, and it seemed as if news of the most secret things was brought to him through the air. But he had a strange custom; every day after dinner, when the table was cleared, and no one else was present, a trusty servant had to bring him one more dish. It was covered, however, and even the servant did not know what was in it, neither did anyone know, for the king never took off the cover to eat of it until he was quite alone."); try { @@ -161,8 +168,8 @@ public async Task AzureOpenAIAssistantAgentTokensAsync() } finally { - await clientProvider.AssistantClient.DeleteThreadAsync(thread.Id); - await clientProvider.AssistantClient.DeleteAssistantAsync(agent.Id); + await assistantClient.DeleteThreadAsync(thread.Id); + await assistantClient.DeleteAssistantAsync(agent.Id); } } @@ -173,9 +180,10 @@ public async Task AzureOpenAIAssistantAgentTokensAsync() public async Task AzureOpenAIAssistantAgentWithThreadCustomOptionsAsync() { AzureOpenAIConfiguration azureOpenAIConfiguration = this.ReadAzureConfiguration(); - OpenAIClientProvider clientProvider = CreateClientProvider(azureOpenAIConfiguration); - Assistant definition = await clientProvider.AssistantClient.CreateAssistantAsync(azureOpenAIConfiguration.ChatDeploymentName!); - OpenAIAssistantAgent agent = new(definition, clientProvider.AssistantClient); + OpenAIClient client = CreateClient(azureOpenAIConfiguration); + AssistantClient assistantClient = client.GetAssistantClient(); + Assistant definition = await assistantClient.CreateAssistantAsync(azureOpenAIConfiguration.ChatDeploymentName!); + OpenAIAssistantAgent agent = new(definition, assistantClient); ThreadCreationOptions threadOptions = new() { @@ -185,7 +193,7 @@ public async Task AzureOpenAIAssistantAgentWithThreadCustomOptionsAsync() new ChatMessageContent(AuthorRole.User, "How may I help you?").ToThreadInitializationMessage(), } }; - OpenAIAssistantAgentThread agentThread = new(clientProvider.AssistantClient, threadOptions); + OpenAIAssistantAgentThread agentThread = new(assistantClient, threadOptions); try { @@ -211,7 +219,7 @@ public async Task AzureOpenAIAssistantAgentWithThreadCustomOptionsAsync() finally { await agentThread.DeleteAsync(); - await clientProvider.AssistantClient.DeleteAssistantAsync(agent.Id); + await assistantClient.DeleteAssistantAsync(agent.Id); } } @@ -224,9 +232,10 @@ public async Task AzureOpenAIAssistantAgentWithThreadCustomOptionsAsync() public async Task AzureOpenAIAssistantAgentAdditionalMessagesAsync() { AzureOpenAIConfiguration azureOpenAIConfiguration = this.ReadAzureConfiguration(); - OpenAIClientProvider clientProvider = CreateClientProvider(azureOpenAIConfiguration); - Assistant definition = await clientProvider.AssistantClient.CreateAssistantAsync(azureOpenAIConfiguration.ChatDeploymentName!); - OpenAIAssistantAgent agent = new(definition, clientProvider.AssistantClient); + OpenAIClient client = CreateClient(azureOpenAIConfiguration); + AssistantClient assistantClient = client.GetAssistantClient(); + Assistant definition = await assistantClient.CreateAssistantAsync(azureOpenAIConfiguration.ChatDeploymentName!); + OpenAIAssistantAgent agent = new(definition, assistantClient); ThreadCreationOptions threadOptions = new() { @@ -236,7 +245,7 @@ public async Task AzureOpenAIAssistantAgentAdditionalMessagesAsync() new ChatMessageContent(AuthorRole.User, "How may I help you?").ToThreadInitializationMessage(), } }; - AssistantThread thread = await clientProvider.AssistantClient.CreateThreadAsync(threadOptions); + AssistantThread thread = await assistantClient.CreateThreadAsync(threadOptions); try { var messages = await agent.GetThreadMessagesAsync(thread.Id).ToArrayAsync(); @@ -260,8 +269,8 @@ public async Task AzureOpenAIAssistantAgentAdditionalMessagesAsync() } finally { - await clientProvider.AssistantClient.DeleteThreadAsync(thread.Id); - await clientProvider.AssistantClient.DeleteAssistantAsync(agent.Id); + await assistantClient.DeleteThreadAsync(thread.Id); + await assistantClient.DeleteAssistantAsync(agent.Id); } } @@ -274,17 +283,18 @@ public async Task AzureOpenAIAssistantAgentAdditionalMessagesAsync() public async Task AzureOpenAIAssistantAgentStreamingFileSearchAsync() { AzureOpenAIConfiguration azureOpenAIConfiguration = this.ReadAzureConfiguration(); - OpenAIClientProvider clientProvider = CreateClientProvider(azureOpenAIConfiguration); - Assistant definition = await clientProvider.AssistantClient.CreateAssistantAsync(azureOpenAIConfiguration.ChatDeploymentName!); - OpenAIAssistantAgent agent = new(definition, clientProvider.AssistantClient); + OpenAIClient client = CreateClient(azureOpenAIConfiguration); + AssistantClient assistantClient = client.GetAssistantClient(); + Assistant definition = await assistantClient.CreateAssistantAsync(azureOpenAIConfiguration.ChatDeploymentName!); + OpenAIAssistantAgent agent = new(definition, assistantClient); // Upload file - Using a table of fictional employees. - OpenAIFileClient fileClient = clientProvider.Client.GetOpenAIFileClient(); + OpenAIFileClient fileClient = client.GetOpenAIFileClient(); await using Stream stream = File.OpenRead("TestData/employees.pdf")!; OpenAIFile fileInfo = await fileClient.UploadFileAsync(stream, "employees.pdf", FileUploadPurpose.Assistants); // Create a vector-store - VectorStoreClient vectorStoreClient = clientProvider.Client.GetVectorStoreClient(); + VectorStoreClient vectorStoreClient = client.GetVectorStoreClient(); CreateVectorStoreOperation result = await vectorStoreClient.CreateVectorStoreAsync(waitUntilCompleted: false, new VectorStoreCreationOptions() @@ -292,7 +302,7 @@ await vectorStoreClient.CreateVectorStoreAsync(waitUntilCompleted: false, FileIds = { fileInfo.Id } }); - AssistantThread thread = await clientProvider.AssistantClient.CreateThreadAsync(); + AssistantThread thread = await assistantClient.CreateThreadAsync(); try { await agent.AddChatMessageAsync(thread.Id, new(AuthorRole.User, "Who works in sales?")); @@ -303,8 +313,8 @@ await vectorStoreClient.CreateVectorStoreAsync(waitUntilCompleted: false, } finally { - await clientProvider.AssistantClient.DeleteThreadAsync(thread.Id); - await clientProvider.AssistantClient.DeleteAssistantAsync(agent.Id); + await assistantClient.DeleteThreadAsync(thread.Id); + await assistantClient.DeleteAssistantAsync(agent.Id); await vectorStoreClient.DeleteVectorStoreAsync(result.VectorStoreId); await fileClient.DeleteFileAsync(fileInfo.Id); } @@ -317,11 +327,12 @@ await vectorStoreClient.CreateVectorStoreAsync(waitUntilCompleted: false, public async Task AzureOpenAIAssistantAgentWithThreadCustomOptionsStreamingAsync() { AzureOpenAIConfiguration azureOpenAIConfiguration = this.ReadAzureConfiguration(); - OpenAIClientProvider clientProvider = CreateClientProvider(azureOpenAIConfiguration); - Assistant definition = await clientProvider.AssistantClient.CreateAssistantAsync(azureOpenAIConfiguration.ChatDeploymentName!); - OpenAIAssistantAgent agent = new(definition, clientProvider.AssistantClient); + OpenAIClient client = CreateClient(azureOpenAIConfiguration); + AssistantClient assistantClient = client.GetAssistantClient(); + Assistant definition = await assistantClient.CreateAssistantAsync(azureOpenAIConfiguration.ChatDeploymentName!); + OpenAIAssistantAgent agent = new(definition, assistantClient); - OpenAIAssistantAgentThread agentThread = new(clientProvider.AssistantClient); + OpenAIAssistantAgentThread agentThread = new(assistantClient); try { @@ -342,7 +353,7 @@ public async Task AzureOpenAIAssistantAgentWithThreadCustomOptionsStreamingAsync finally { await agentThread.DeleteAsync(); - await clientProvider.AssistantClient.DeleteAssistantAsync(agent.Id); + await assistantClient.DeleteAssistantAsync(agent.Id); } } @@ -353,7 +364,8 @@ public async Task AzureOpenAIAssistantAgentWithThreadCustomOptionsStreamingAsync public async Task AzureOpenAIAssistantAgentDeclarativeAsync() { AzureOpenAIConfiguration azureOpenAIConfiguration = this.ReadAzureConfiguration(); - OpenAIClientProvider clientProvider = CreateClientProvider(azureOpenAIConfiguration); + OpenAIClient client = CreateClient(azureOpenAIConfiguration); + AssistantClient assistantClient = client.GetAssistantClient(); var text = $""" @@ -376,7 +388,7 @@ public async Task AzureOpenAIAssistantAgentDeclarativeAsync() var agent = await factory.CreateAgentFromYamlAsync(text, new() { Kernel = kernel }); Assert.NotNull(agent); - OpenAIAssistantAgentThread agentThread = new(clientProvider.AssistantClient); + OpenAIAssistantAgentThread agentThread = new(assistantClient); try { RunCreationOptions invocationOptions = new() @@ -394,22 +406,22 @@ public async Task AzureOpenAIAssistantAgentDeclarativeAsync() finally { await agentThread.DeleteAsync(); - await clientProvider.AssistantClient.DeleteAssistantAsync(agent.Id); + await assistantClient.DeleteAssistantAsync(agent.Id); } } private async Task ExecuteAgentAsync( - OpenAIClientProvider clientProvider, + OpenAIClient client, string modelName, string input, string expected) { // Arrange Kernel kernel = new(); - KernelPlugin plugin = KernelPluginFactory.CreateFromType(); - Assistant definition = await clientProvider.AssistantClient.CreateAssistantAsync(modelName, instructions: "Answer questions about the menu."); - OpenAIAssistantAgent agent = new(definition, clientProvider.AssistantClient, [plugin]); + AssistantClient assistantClient = client.GetAssistantClient(); + Assistant definition = await client.GetAssistantClient().CreateAssistantAsync(modelName, instructions: "Answer questions about the menu."); + OpenAIAssistantAgent agent = new(definition, assistantClient, [plugin]); try { @@ -432,12 +444,12 @@ private async Task ExecuteAgentAsync( } finally { - await clientProvider.AssistantClient.DeleteAssistantAsync(agent.Id); + await assistantClient.DeleteAssistantAsync(agent.Id); } } private async Task ExecuteStreamingAgentAsync( - OpenAIClientProvider clientProvider, + OpenAIClient client, string modelName, string input, string expected) @@ -446,8 +458,9 @@ private async Task ExecuteStreamingAgentAsync( Kernel kernel = new(); KernelPlugin plugin = KernelPluginFactory.CreateFromType(); - Assistant definition = await clientProvider.AssistantClient.CreateAssistantAsync(modelName, instructions: "Answer questions about the menu."); - OpenAIAssistantAgent agent = new(definition, clientProvider.AssistantClient, [plugin]); + AssistantClient assistantClient = client.GetAssistantClient(); + Assistant definition = await assistantClient.CreateAssistantAsync(modelName, instructions: "Answer questions about the menu."); + OpenAIAssistantAgent agent = new(definition, assistantClient, [plugin]); AgentGroupChat chat = new(); chat.AddChatMessage(new ChatMessageContent(AuthorRole.User, input)); @@ -489,9 +502,9 @@ private AzureOpenAIConfiguration ReadAzureConfiguration() return azureOpenAIConfiguration; } - private static OpenAIClientProvider CreateClientProvider(AzureOpenAIConfiguration azureOpenAIConfiguration) + private static AzureOpenAIClient CreateClient(AzureOpenAIConfiguration azureOpenAIConfiguration) { - return OpenAIClientProvider.ForAzureOpenAI(new AzureCliCredential(), new Uri(azureOpenAIConfiguration.Endpoint)); + return OpenAIAssistantAgent.CreateAzureOpenAIClient(new AzureCliCredential(), new Uri(azureOpenAIConfiguration.Endpoint)); } public sealed class MenuPlugin diff --git a/dotnet/src/IntegrationTests/TestSettings/AzureAIConfiguration.cs b/dotnet/src/IntegrationTests/TestSettings/AzureAIConfiguration.cs index 0e3993fafc0b..d62372d33df9 100644 --- a/dotnet/src/IntegrationTests/TestSettings/AzureAIConfiguration.cs +++ b/dotnet/src/IntegrationTests/TestSettings/AzureAIConfiguration.cs @@ -6,9 +6,9 @@ namespace SemanticKernel.IntegrationTests.TestSettings; [SuppressMessage("Performance", "CA1812:Internal class that is apparently never instantiated", Justification = "Configuration classes are instantiated through IConfiguration.")] -internal sealed class AzureAIConfiguration(string connectionString, string chatModelId) +internal sealed class AzureAIConfiguration(string endpoint, string chatModelId) { - public string ConnectionString { get; set; } = connectionString; + public string Endpoint { get; set; } = endpoint; public string ChatModelId { get; set; } = chatModelId; } diff --git a/dotnet/src/InternalUtilities/process/Runtime/AgentThreadFactory.cs b/dotnet/src/InternalUtilities/process/Runtime/AgentThreadFactory.cs index 51b616e8ea33..856c233570a0 100644 --- a/dotnet/src/InternalUtilities/process/Runtime/AgentThreadFactory.cs +++ b/dotnet/src/InternalUtilities/process/Runtime/AgentThreadFactory.cs @@ -39,13 +39,13 @@ public static async Task CreateAgentThreadAsync(this KernelProcessA private static async Task CreateAzureAIThreadAsync(string? id, Kernel kernel) { const string ErrorMessage = "The thread could not be created due to an error response from the service."; - var client = kernel.Services.GetService() ?? throw new KernelException("The AzureAI thread type requires an AgentsClient to be registered in the kernel."); + var client = kernel.Services.GetService() ?? throw new KernelException("The AzureAI thread type requires an AgentsClient to be registered in the kernel."); if (string.IsNullOrWhiteSpace(id)) { try { - var threadResponse = await client.CreateThreadAsync().ConfigureAwait(false); + var threadResponse = await client.Threads.CreateThreadAsync().ConfigureAwait(false); id = threadResponse.Value.Id; } catch (RequestFailedException ex) diff --git a/dotnet/src/InternalUtilities/samples/AgentUtilities/BaseAgentsTest.cs b/dotnet/src/InternalUtilities/samples/AgentUtilities/BaseAgentsTest.cs index 1fb10544363f..1d25e5bf54c8 100644 --- a/dotnet/src/InternalUtilities/samples/AgentUtilities/BaseAgentsTest.cs +++ b/dotnet/src/InternalUtilities/samples/AgentUtilities/BaseAgentsTest.cs @@ -2,7 +2,7 @@ using System.Collections.ObjectModel; using System.Diagnostics; -using Azure.AI.Projects; +using Azure.AI.Agents.Persistent; using Microsoft.SemanticKernel; using Microsoft.SemanticKernel.Agents; using Microsoft.SemanticKernel.Agents.OpenAI; diff --git a/dotnet/src/InternalUtilities/samples/AgentUtilities/BaseAzureAgentTest.cs b/dotnet/src/InternalUtilities/samples/AgentUtilities/BaseAzureAgentTest.cs index 08578874ce3e..4bf31af1c249 100644 --- a/dotnet/src/InternalUtilities/samples/AgentUtilities/BaseAzureAgentTest.cs +++ b/dotnet/src/InternalUtilities/samples/AgentUtilities/BaseAzureAgentTest.cs @@ -1,13 +1,10 @@ // Copyright (c) Microsoft. All rights reserved. -using System.ClientModel; using System.Collections.ObjectModel; using System.Diagnostics; -using Azure.AI.Projects; -using Azure.Identity; +using Azure.AI.Agents.Persistent; using Microsoft.SemanticKernel; using Microsoft.SemanticKernel.Agents; -using Microsoft.SemanticKernel.Agents.AzureAI; using Microsoft.SemanticKernel.Agents.OpenAI; using Microsoft.SemanticKernel.ChatCompletion; using OpenAI.Assistants; @@ -41,27 +38,6 @@ public abstract class BaseAzureTest(ITestOutputHelper output) : BaseTest(output, { AssistantSampleMetadataKey, bool.TrueString } }); - /// - /// Provide a according to the configuration settings. - /// - protected AzureAIClientProvider GetAzureProvider() - { - return AzureAIClientProvider.FromConnectionString(TestConfiguration.AzureAI.ConnectionString, new AzureCliCredential()); - } - - /// - /// Provide a according to the configuration settings. - /// - protected OpenAIClientProvider GetClientProvider() - { - return - this.UseOpenAIConfig ? - OpenAIClientProvider.ForOpenAI(new ApiKeyCredential(this.ApiKey ?? throw new ConfigurationNotFoundException("OpenAI:ApiKey"))) : - !string.IsNullOrWhiteSpace(this.ApiKey) ? - OpenAIClientProvider.ForAzureOpenAI(new ApiKeyCredential(this.ApiKey), new Uri(this.Endpoint!)) : - OpenAIClientProvider.ForAzureOpenAI(new AzureCliCredential(), new Uri(this.Endpoint!)); - } - /// /// Common method to write formatted agent chat content to the console. /// diff --git a/dotnet/src/InternalUtilities/samples/AgentUtilities/BaseAzureTest.cs b/dotnet/src/InternalUtilities/samples/AgentUtilities/BaseAzureTest.cs index f27c998f1f65..c2b80ffa3e78 100644 --- a/dotnet/src/InternalUtilities/samples/AgentUtilities/BaseAzureTest.cs +++ b/dotnet/src/InternalUtilities/samples/AgentUtilities/BaseAzureTest.cs @@ -1,7 +1,7 @@ // Copyright (c) Microsoft. All rights reserved. using System.Diagnostics; -using Azure.AI.Projects; +using Azure.AI.Agents.Persistent; using Azure.Identity; using Microsoft.SemanticKernel; using Microsoft.SemanticKernel.Agents; @@ -10,21 +10,14 @@ /// /// Base class for samples that demonstrate the usage of . /// -public abstract class BaseAzureAgentTest : BaseAgentsTest +public abstract class BaseAzureAgentTest : BaseAgentsTest { protected BaseAzureAgentTest(ITestOutputHelper output) : base(output) { - this.Client = AzureAIAgent.CreateAzureAIClient(TestConfiguration.AzureAI.ConnectionString, new AzureCliCredential()); - this.AgentsClient = this.Client.GetAgentsClient(); + this.Client = AzureAIAgent.CreateAgentsClient(TestConfiguration.AzureAI.Endpoint, new AzureCliCredential()); } - /// - protected override AIProjectClient Client { get; } - - /// - /// Gets the . - /// - protected AgentsClient AgentsClient { get; } + protected override PersistentAgentsClient Client { get; } protected async Task DownloadContentAsync(ChatMessageContent message) { @@ -39,8 +32,8 @@ protected async Task DownloadContentAsync(ChatMessageContent message) protected async Task DownloadFileAsync(string fileId, bool launchViewer = false) { - AgentFile fileInfo = this.AgentsClient.GetFile(fileId); - if (fileInfo.Purpose == AgentFilePurpose.AgentsOutput) + PersistentAgentFileInfo fileInfo = this.Client.Files.GetFile(fileId); + if (fileInfo.Purpose == PersistentAgentFilePurpose.AgentsOutput) { string filePath = Path.Combine(Path.GetTempPath(), Path.GetFileName(fileInfo.Filename)); if (launchViewer) @@ -48,7 +41,7 @@ protected async Task DownloadFileAsync(string fileId, bool launchViewer = false) filePath = Path.ChangeExtension(filePath, ".png"); } - BinaryData content = await this.AgentsClient.GetFileContentAsync(fileId); + BinaryData content = await this.Client.Files.GetFileContentAsync(fileId); File.WriteAllBytes(filePath, content.ToArray()); Console.WriteLine($" File #{fileId} saved to: {filePath}"); diff --git a/dotnet/src/InternalUtilities/samples/InternalUtilities/TestConfiguration.cs b/dotnet/src/InternalUtilities/samples/InternalUtilities/TestConfiguration.cs index 697cab7d4147..5387b8f33cb8 100644 --- a/dotnet/src/InternalUtilities/samples/InternalUtilities/TestConfiguration.cs +++ b/dotnet/src/InternalUtilities/samples/InternalUtilities/TestConfiguration.cs @@ -106,9 +106,9 @@ public class OnnxConfig public class AzureAIConfig { - public string WorkflowEndpoint { get; set; } - public string ConnectionString { get; set; } public string ChatModelId { get; set; } + public string Endpoint { get; set; } + public string WorkflowEndpoint { get; set; } public string BingConnectionId { get; set; } public string VectorStoreId { get; set; } public string AgentId { get; set; }