diff --git a/dotnet/Directory.Packages.props b/dotnet/Directory.Packages.props index 3117b8da61..ff391e724d 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 1437547185..7d7626e18f 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 120af82422..6292339d35 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 class AzureAIAgent_FileManipulation(ITestOutputHelper output) : BaseAzure 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 class AzureAIAgent_FileManipulation(ITestOutputHelper output) : BaseAzure 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 d03b223c1c..e01e30f663 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 class AzureAIAgent_Streaming(ITestOutputHelper output) : BaseAzureAgentTe 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 class AzureAIAgent_Streaming(ITestOutputHelper output) : BaseAzureAgentTe 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 class AzureAIAgent_Streaming(ITestOutputHelper output) : BaseAzureAgentTe 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 843fa00cba..7fd1e1c7fb 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; 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 @@ internal sealed class AzureAIAgentWithMCPToolsSample : BaseSample 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 @@ internal sealed class AzureAIAgentWithMCPToolsSample : BaseSample .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 @@ internal sealed class AzureAIAgentWithMCPToolsSample : BaseSample 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 1b3afff467..e348f065eb 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 class Step01_AzureAIAgent(ITestOutputHelper output) : BaseAzureAgentTest( 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 class Step01_AzureAIAgent(ITestOutputHelper output) : BaseAzureAgentTest( }; // 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 @@ public class Step01_AzureAIAgent(ITestOutputHelper output) : BaseAzureAgentTest( 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 9089486504..666d2a5b65 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 class Step02_AzureAIAgent_Plugins(ITestOutputHelper output) : BaseAzureAg 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 class Step02_AzureAIAgent_Plugins(ITestOutputHelper output) : BaseAzureAg finally { await thread.DeleteAsync(); - await this.AgentsClient.DeleteAgentAsync(agent.Id); + await this.Client.Administration.DeleteAgentAsync(agent.Id); } } @@ -47,7 +48,7 @@ public class Step02_AzureAIAgent_Plugins(ITestOutputHelper output) : BaseAzureAg 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 class Step02_AzureAIAgent_Plugins(ITestOutputHelper output) : BaseAzureAg 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 c54d9cf788..654ea1d9bf 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 @@ public class Step03_AzureAIAgent_Chat(ITestOutputHelper output) : BaseAzureAgent 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 class Step03_AzureAIAgent_Chat(ITestOutputHelper output) : BaseAzureAgent 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 4c36e882d9..ca7558cd6a 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 class Step04_AzureAIAgent_CodeInterpreter(ITestOutputHelper output) : Bas 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 1716c48d1b..9fc515f159 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 class Step05_AzureAIAgent_FileSearch(ITestOutputHelper output) : BaseAzur // 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 @@ public class Step05_AzureAIAgent_FileSearch(ITestOutputHelper output) : BaseAzur } }, 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 @@ public class Step05_AzureAIAgent_FileSearch(ITestOutputHelper output) : BaseAzur 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 194ae7b163..0514069f39 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 class Step06_AzureAIAgent_OpenAPI(ITestOutputHelper output) : BaseAzureAg 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 class Step06_AzureAIAgent_OpenAPI(ITestOutputHelper output) : BaseAzureAg 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 6eb018aecb..c88da85096 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 class Step07_AzureAIAgent_Functions(ITestOutputHelper output) : BaseAzure 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 class Step07_AzureAIAgent_Functions(ITestOutputHelper output) : BaseAzure 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 bc09224987..7a50dcf047 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; 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 class Step08_AzureAIAgent_Declarative : BaseAzureAgentTest 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 class Step08_AzureAIAgent_Declarative : BaseAzureAgentTest name: MyAgent description: My helpful agent. instructions: You are helpful agent. + model: + id: ${AzureOpenAI:ChatModelId} """; AzureAIAgentFactory factory = new(); @@ -190,9 +191,6 @@ public class Step08_AzureAIAgent_Declarative : BaseAzureAgentTest """; 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 class Step08_AzureAIAgent_Declarative : BaseAzureAgentTest 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 class Step08_AzureAIAgent_Declarative : BaseAzureAgentTest } 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 class Step08_AzureAIAgent_Declarative : BaseAzureAgentTest 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 @@ public class Step08_AzureAIAgent_Declarative : BaseAzureAgentTest { 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 71eaae0557..acd085d279 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 class Step09_AzureAIAgent_BingGrounding(ITestOutputHelper output) : BaseA 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 @@ public class Step09_AzureAIAgent_BingGrounding(ITestOutputHelper output) : BaseA 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 class Step09_AzureAIAgent_BingGrounding(ITestOutputHelper output) : BaseA 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 f0d193f300..33af885432 100644 --- a/dotnet/samples/GettingStartedWithAgents/OpenAIAssistant/Step07_Assistant_Declarative.cs +++ b/dotnet/samples/GettingStartedWithAgents/OpenAIAssistant/Step07_Assistant_Declarative.cs @@ -209,8 +209,8 @@ public class Step07_Assistant_Declarative : BaseAssistantTest { 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 eb30e35e04..e1d6b542a1 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.Orchestration; 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 class Step05_Magentic(ITestOutputHelper output) : BaseOrchestrationTest(o 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 03d13cb3c7..1b816a8663 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 class Step10_MultiAgent_Declarative : BaseAgentsTest { 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 class Step10_MultiAgent_Declarative : BaseAgentsTest 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 2b0694f699..e448a8f4f2 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 e3b4e4bfe5..b82b0f0c09 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 @@ using Microsoft.SemanticKernel.Http; 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 440dd0c74b..c02cff51ea 100644 --- a/dotnet/src/Agents/AzureAI/AzureAIAgent.cs +++ b/dotnet/src/Agents/AzureAI/AzureAIAgent.cs @@ -5,13 +5,12 @@ using System.Collections.Generic; 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 sealed partial class AzureAIAgent : Agent /// /// 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 sealed partial class AzureAIAgent : Agent /// 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 sealed partial class AzureAIAgent : Agent /// /// The associated client. /// - public AgentsClient Client { get; } + public PersistentAgentsClient Client { get; } /// /// Adds a message to the specified thread. @@ -431,7 +430,7 @@ public sealed partial class AzureAIAgent : Agent 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 0965819593..f111a0ca05 100644 --- a/dotnet/src/Agents/AzureAI/AzureAIAgentThread.cs +++ b/dotnet/src/Agents/AzureAI/AzureAIAgentThread.cs @@ -7,7 +7,7 @@ using System.Runtime.CompilerServices; 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 sealed class AzureAIAgentThread : AgentThread /// /// 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 sealed class AzureAIAgentThread : AgentThread try { - var agentThreadResponse = await this._client.CreateThreadAsync( + var agentThreadResponse = await this._client.Threads.CreateThreadAsync( this._messages, this._toolResources, this._metadata, @@ -102,7 +102,7 @@ public sealed class AzureAIAgentThread : AgentThread 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 fa5991d4ac..e1b57d4ad3 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 @@ internal sealed class AzureAIChannel(AgentsClient client, string threadId) /// 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 4d9b555151..0000000000 --- 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 d37242c522..c5199fb146 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 5bd2213729..b7e169af2d 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 sealed class AzureAIAgentFactory : AgentFactory 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 sealed class AzureAIAgentFactory : AgentFactory 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 1f11bc5f02..517266c0fc 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 @@ internal static class AgentDefinitionExtensions 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 @@ internal static class AgentDefinitionExtensions } /// - /// 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 @@ internal static class AgentDefinitionExtensions 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 @@ internal static class AgentDefinitionExtensions return null; } - private static AzureAISearchResource? GetAzureAISearchResource(this AgentDefinition agentDefinition) + private static AzureAISearchToolResource? GetAzureAISearchResource(this AgentDefinition agentDefinition) { Verify.NotNull(agentDefinition); @@ -205,7 +198,7 @@ internal static class AgentDefinitionExtensions 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 @@ internal static class AgentDefinitionExtensions { 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 @@ internal static class AgentDefinitionExtensions 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 @@ internal static class AgentDefinitionExtensions 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 7334941407..53133baafd 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 @@ internal static class AgentRunExtensions 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 @@ internal static class AgentRunExtensions 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 @@ internal static class AgentRunExtensions } public static IAsyncEnumerable CreateStreamingAsync( - this AgentsClient client, + this PersistentAgentsClient client, string threadId, AzureAIAgent agent, string? instructions, @@ -95,16 +91,16 @@ internal static class AgentRunExtensions 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 e85092fe24..053c8dc52f 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 class AgentToolDefinitionExtensions 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 class AgentToolDefinitionExtensions 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 @@ internal static class AgentToolDefinitionExtensions 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 e6b9c722ea..39ed1b4bac 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 621e364acf..7be5906ec5 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 @@ internal static class AgentMessageFactory } /// - /// 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 @@ internal static class AgentMessageFactory .OfType() .Select( fileContent => - new MessageAttachment(fileContent.FileId, GetToolDefinition(fileContent.Tools).ToList())); + new MessageAttachment(fileContent.FileId, [.. GetToolDefinition(fileContent.Tools)])); } /// @@ -58,7 +58,7 @@ internal static class AgentMessageFactory role: message.Role == AuthorRole.User ? MessageRole.User : MessageRole.Agent, content: message.Content) { - Attachments = GetAttachments(message).ToArray(), + Attachments = [.. GetAttachments(message)], }; if (message.Metadata != null) diff --git a/dotnet/src/Agents/AzureAI/Internal/AgentThreadActions.cs b/dotnet/src/Agents/AzureAI/Internal/AgentThreadActions.cs index 69eb66f482..df41bf1ace 100644 --- a/dotnet/src/Agents/AzureAI/Internal/AgentThreadActions.cs +++ b/dotnet/src/Agents/AzureAI/Internal/AgentThreadActions.cs @@ -9,13 +9,12 @@ using System.Text.Json; using System.Threading; using System.Threading.Tasks; using Azure; -using Azure.AI.Projects; +using Azure.AI.Agents.Persistent; using Microsoft.Extensions.Logging; using Microsoft.SemanticKernel.Agents.AzureAI.Extensions; using Microsoft.SemanticKernel.Agents.Extensions; using Microsoft.SemanticKernel.ChatCompletion; using Microsoft.SemanticKernel.Connectors.FunctionCalling; -using AAIP = Azure.AI.Projects; namespace Microsoft.SemanticKernel.Agents.AzureAI.Internal; @@ -44,9 +43,9 @@ internal static class AgentThreadActions /// The 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 @@ internal static class AgentThreadActions /// 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 @@ internal static class AgentThreadActions return; } - await client.CreateMessageAsync( + await client.Messages.CreateMessageAsync( threadId, role: message.Role == AuthorRole.User ? MessageRole.User : MessageRole.Agent, content, @@ -89,39 +88,35 @@ internal static class AgentThreadActions /// 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); - } - } - - assistantName ??= message.AssistantId; - - ChatMessageContent content = GenerateMessageContent(assistantName, message); - - if (content.Items.Count > 0) - { - yield return content; + agentNames.Add(assistant.Id, assistant.Name); } } - } while (messages?.HasMore ?? false); + + assistantName ??= message.AssistantId; + + ChatMessageContent content = GenerateMessageContent(assistantName, message); + + if (content.Items.Count > 0) + { + yield return content; + } + } } /// @@ -140,7 +135,7 @@ internal static class AgentThreadActions /// 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 @@ internal static class AgentThreadActions 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 @@ internal static class AgentThreadActions // 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 @@ internal static class AgentThreadActions { // 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 @@ internal static class AgentThreadActions 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 @@ internal static class AgentThreadActions /// public static async IAsyncEnumerable InvokeStreamingAsync( AzureAIAgent agent, - AgentsClient client, + PersistentAgentsClient client, string threadId, IList? messages, AzureAIInvocationOptions? invocationOptions, @@ -497,7 +492,7 @@ internal static class AgentThreadActions // 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 @@ internal static class AgentThreadActions { if (step.StepDetails is RunStepMessageCreationDetails messageDetails) { - ThreadMessage? message = + PersistentThreadMessage? message = await RetrieveMessageAsync( client, threadId, @@ -555,17 +550,17 @@ internal static class AgentThreadActions 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 @@ internal static class AgentThreadActions 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 @@ internal static class AgentThreadActions 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 @@ internal static class AgentThreadActions { 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 27b38bbb74..0acfc01016 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 88470519ac..fa62275d0d 100644 --- a/dotnet/src/Agents/OpenAI/Extensions/AgentDefinitionExtensions.cs +++ b/dotnet/src/Agents/OpenAI/Extensions/AgentDefinitionExtensions.cs @@ -4,7 +4,6 @@ using System; 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 @@ internal static class AgentDefinitionExtensions 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 ebb8fcdce5..9c157d9fa1 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 96ddfb0468..0000000000 --- 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 c21fbfb03f..d0aa27fa1d 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; 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 class AzureAIAgentFactoryTests : IDisposable 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 cb8fe8415b..298d22eae5 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 c42de6fc38..99e47fb9f1 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 6dcb0280be..72c4500908 100644 --- a/dotnet/src/Agents/UnitTests/OpenAI/Definition/OpenAIAssistantAgentFactoryTests.cs +++ b/dotnet/src/Agents/UnitTests/OpenAI/Definition/OpenAIAssistantAgentFactoryTests.cs @@ -31,8 +31,7 @@ public class OpenAIAssistantAgentFactoryTests : IDisposable 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 f1cdd1e429..6e87bb6865 100644 --- a/dotnet/src/Agents/UnitTests/OpenAI/Extensions/AssistantClientExtensionsTests.cs +++ b/dotnet/src/Agents/UnitTests/OpenAI/Extensions/AssistantClientExtensionsTests.cs @@ -8,6 +8,7 @@ using System.Threading.Tasks; 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 sealed class AssistantClientExtensionsTests : IDisposable 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 sealed class AssistantClientExtensionsTests : IDisposable 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 sealed class AssistantClientExtensionsTests : IDisposable 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 sealed class AssistantClientExtensionsTests : IDisposable 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 sealed class AssistantClientExtensionsTests : IDisposable 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 sealed class AssistantClientExtensionsTests : IDisposable 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 sealed class AssistantClientExtensionsTests : IDisposable 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 sealed class AssistantClientExtensionsTests : IDisposable 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 sealed class AssistantClientExtensionsTests : IDisposable 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 sealed class AssistantClientExtensionsTests : IDisposable 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 sealed class AssistantClientExtensionsTests : IDisposable 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 sealed class AssistantClientExtensionsTests : IDisposable 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 sealed class AssistantClientExtensionsTests : IDisposable 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 sealed class AssistantClientExtensionsTests : IDisposable 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 sealed class AssistantClientExtensionsTests : IDisposable { 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 ce03e8f584..92b8279629 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.Net.Http; 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 sealed class OpenAIClientExtensionsTests : IDisposable 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 sealed class OpenAIClientExtensionsTests : IDisposable 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 sealed class OpenAIClientExtensionsTests : IDisposable // 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 sealed class OpenAIClientExtensionsTests : IDisposable 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 sealed class OpenAIClientExtensionsTests : IDisposable 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 sealed class OpenAIClientExtensionsTests : IDisposable { 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 a5bd93969b..73b6933c2a 100644 --- a/dotnet/src/Agents/UnitTests/OpenAI/OpenAIAssistantAgentTests.cs +++ b/dotnet/src/Agents/UnitTests/OpenAI/OpenAIAssistantAgentTests.cs @@ -309,7 +309,7 @@ public sealed class OpenAIAssistantAgentTests : IDisposable OpenAIAssistantAgent agent = await OpenAIAssistantAgent.RetrieveAsync( - this.CreateTestProvider(), + this.CreateTestClient(), "#id", this._emptyKernel); @@ -330,7 +330,7 @@ public sealed class OpenAIAssistantAgentTests : IDisposable OpenAIAssistantAgent agent = await OpenAIAssistantAgent.RetrieveAsync( - this.CreateTestProvider(), + this.CreateTestClient(), "#id", this._emptyKernel, [], @@ -748,7 +748,7 @@ public sealed class OpenAIAssistantAgentTests : IDisposable // Act var messages = await OpenAIAssistantAgent.ListDefinitionsAsync( - this.CreateTestProvider()).ToArrayAsync(); + this.CreateTestClient()).ToArrayAsync(); // Assert Assert.Equal(7, messages.Length); @@ -761,7 +761,7 @@ public sealed class OpenAIAssistantAgentTests : IDisposable // Act messages = await OpenAIAssistantAgent.ListDefinitionsAsync( - this.CreateTestProvider()).ToArrayAsync(); + this.CreateTestClient()).ToArrayAsync(); // Assert Assert.Equal(4, messages.Length); } @@ -823,7 +823,7 @@ public sealed class OpenAIAssistantAgentTests : IDisposable OpenAIAssistantAgent agent = await OpenAIAssistantAgent.CreateAsync( - this.CreateTestProvider(), + this.CreateTestClient(), definition, this._emptyKernel); @@ -839,7 +839,7 @@ public sealed class OpenAIAssistantAgentTests : IDisposable OpenAIAssistantAgent agent = await OpenAIAssistantAgent.CreateFromTemplateAsync( - this.CreateTestProvider(), + this.CreateTestClient(), capabilities, this._emptyKernel, [], @@ -938,12 +938,12 @@ public sealed class OpenAIAssistantAgentTests : IDisposable 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 c7a520ea42..5b2c5bc18a 100644 --- a/dotnet/src/Agents/UnitTests/OpenAI/OpenAIAssistantAgentThreadTests.cs +++ b/dotnet/src/Agents/UnitTests/OpenAI/OpenAIAssistantAgentThreadTests.cs @@ -9,6 +9,7 @@ using Microsoft.SemanticKernel; using Microsoft.SemanticKernel.Agents.OpenAI; using Microsoft.SemanticKernel.ChatCompletion; using Moq; +using OpenAI; using OpenAI.Assistants; using Xunit; @@ -75,10 +76,9 @@ public class OpenAIAssistantAgentThreadTests : IDisposable // 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 class OpenAIAssistantAgentThreadTests : IDisposable // 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 class OpenAIAssistantAgentThreadTests : IDisposable // 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 class OpenAIAssistantAgentThreadTests : IDisposable 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 class OpenAIAssistantAgentThreadTests : IDisposable 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 eff4b579eb..e7c23cce73 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 class AgentYamlTests : IDisposable 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 dd464faf18..ea0fef2986 100644 --- a/dotnet/src/Agents/UnitTests/Yaml/AzureAIKernelAgentYamlTests.cs +++ b/dotnet/src/Agents/UnitTests/Yaml/AzureAIKernelAgentYamlTests.cs @@ -7,7 +7,7 @@ using System.Net.Http; 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 class AzureAIKernelAgentYamlTests : IDisposable 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 class AzureAIKernelAgentYamlTests : IDisposable 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 class AzureAIKernelAgentYamlTests : IDisposable 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 82ceb5372f..f4af8d6371 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 d5f245549d..270e25bf74 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 df336f5f62..6fabcf07db 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 class 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 @@ public class AzureAIAgentTests finally { await agentThread.DeleteAsync(); - await this._agentsClient.DeleteAgentAsync(agent.Id); + await this._client.Administration.DeleteAgentAsync(agent.Id); } } @@ -74,14 +73,14 @@ public class AzureAIAgentTests 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 @@ public class AzureAIAgentTests finally { await agentThread.DeleteAsync(); - await this._agentsClient.DeleteAgentAsync(agent.Id); + await this._client.Administration.DeleteAgentAsync(agent.Id); } } @@ -108,7 +107,7 @@ public class AzureAIAgentTests 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 class AzureAIAgentTests 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 class AzureAIAgentTests 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 769e3daec9..7c64a525b3 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; 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 class AzureAIAgentFixture : AgentFixture 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 class AzureAIAgentFixture : AgentFixture { 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 class AzureAIAgentFixture : AgentFixture 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 class AzureAIAgentFixture : AgentFixture 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 @@ public class AzureAIAgentFixture : AgentFixture 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 dd39b66096..7ec24fbecf 100644 --- a/dotnet/src/IntegrationTests/Agents/MixedAgentTests.cs +++ b/dotnet/src/IntegrationTests/Agents/MixedAgentTests.cs @@ -12,6 +12,7 @@ using Microsoft.SemanticKernel.Agents; 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 sealed class MixedAgentTests // 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 sealed class MixedAgentTests // 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 @@ public sealed class MixedAgentTests 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 @@ public sealed class MixedAgentTests } 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 3549612171..7cef37d82c 100644 --- a/dotnet/src/IntegrationTests/Agents/OpenAIAssistantAgentTests.cs +++ b/dotnet/src/IntegrationTests/Agents/OpenAIAssistantAgentTests.cs @@ -6,6 +6,7 @@ using System.IO; 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; 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 sealed class OpenAIAssistantAgentTests 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 sealed class OpenAIAssistantAgentTests 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 sealed class OpenAIAssistantAgentTests 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 sealed class OpenAIAssistantAgentTests AzureOpenAIConfiguration azureOpenAIConfiguration = this.ReadAzureConfiguration(); await this.ExecuteStreamingAgentAsync( - CreateClientProvider(azureOpenAIConfiguration), + CreateClient(azureOpenAIConfiguration), azureOpenAIConfiguration.ChatDeploymentName!, input, expectedAnswerContains); @@ -114,11 +119,12 @@ public sealed class OpenAIAssistantAgentTests 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 sealed class OpenAIAssistantAgentTests } 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 sealed class OpenAIAssistantAgentTests 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 sealed class OpenAIAssistantAgentTests } }; - 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 sealed class OpenAIAssistantAgentTests } 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 sealed class OpenAIAssistantAgentTests 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 sealed class OpenAIAssistantAgentTests 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 sealed class OpenAIAssistantAgentTests finally { await agentThread.DeleteAsync(); - await clientProvider.AssistantClient.DeleteAssistantAsync(agent.Id); + await assistantClient.DeleteAssistantAsync(agent.Id); } } @@ -224,9 +232,10 @@ public sealed class OpenAIAssistantAgentTests 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 sealed class OpenAIAssistantAgentTests 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 sealed class OpenAIAssistantAgentTests } 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 sealed class OpenAIAssistantAgentTests 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 @@ public sealed class OpenAIAssistantAgentTests 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 @@ public sealed class OpenAIAssistantAgentTests } 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 @@ public sealed class OpenAIAssistantAgentTests 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 sealed class OpenAIAssistantAgentTests finally { await agentThread.DeleteAsync(); - await clientProvider.AssistantClient.DeleteAssistantAsync(agent.Id); + await assistantClient.DeleteAssistantAsync(agent.Id); } } @@ -353,7 +364,8 @@ public sealed class OpenAIAssistantAgentTests 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 sealed class OpenAIAssistantAgentTests 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 sealed class OpenAIAssistantAgentTests 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 @@ public sealed class OpenAIAssistantAgentTests } 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 @@ public sealed class OpenAIAssistantAgentTests 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 @@ public sealed class OpenAIAssistantAgentTests 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 0e3993fafc..d62372d33d 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 51b616e8ea..856c233570 100644 --- a/dotnet/src/InternalUtilities/process/Runtime/AgentThreadFactory.cs +++ b/dotnet/src/InternalUtilities/process/Runtime/AgentThreadFactory.cs @@ -39,13 +39,13 @@ public static class AgentThreadFactory 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 1fb1054436..1d25e5bf54 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 08578874ce..4bf31af1c2 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 f27c998f1f..c2b80ffa3e 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 @@ using Microsoft.SemanticKernel.Agents.AzureAI; /// /// 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 @@ public abstract class BaseAzureAgentTest : BaseAgentsTest 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 @@ public abstract class BaseAzureAgentTest : BaseAgentsTest 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 697cab7d41..5387b8f33c 100644 --- a/dotnet/src/InternalUtilities/samples/InternalUtilities/TestConfiguration.cs +++ b/dotnet/src/InternalUtilities/samples/InternalUtilities/TestConfiguration.cs @@ -106,9 +106,9 @@ public sealed class TestConfiguration 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; }