mirror of
https://github.com/microsoft/semantic-kernel.git
synced 2026-10-12 02:19:06 +00:00
.Net Agents - Update Azure Foundry Agent SDK (#12027)
### Motivation and Context As part of going GA with Foundry Agents, Azure team has split `Azure.AI.Projects` into two packages: `Azure.AI.Projects` & `Azure.AI.Agents.Persistent` In addition, connecting to a foundry project will be based on endpoint/credential and connection-string will not be supported. ### Description - Updated package dependency to include: `Azure.AI.Projects.OneDP` & `Azure.AI.Agents.Persistent` - Updated declarative agents to support `endpoint` instead of `connection-string` - Updated tests and samples - Deprecated `OpenAIClientProvider` - Removed `AzureAIClientProvider`  ### Contribution Checklist <!-- Before submitting this PR, please make sure: --> - [X] The code builds clean without any errors or warnings - [X] The PR follows the [SK Contribution Guidelines](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md) and the [pre-submission formatting script](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md#development-scripts) raises no violations - [X] All unit tests pass, and I have added new tests where possible - [X] I didn't break anyone 😄
This commit is contained in:
@@ -17,10 +17,10 @@
|
||||
<PackageVersion Include="AWSSDK.Extensions.Bedrock.MEAI" Version="4.0.0-preview.16" />
|
||||
<PackageVersion Include="AWSSDK.Extensions.NETCore.Setup" Version="4.0.0" />
|
||||
<PackageVersion Include="AWSSDK.SecurityToken" Version="4.0.0.2" />
|
||||
<PackageVersion Include="Azure.AI.Agents.Persistent" Version="1.0.0" />
|
||||
<PackageVersion Include="Azure.AI.ContentSafety" Version="1.0.0" />
|
||||
<PackageVersion Include="Azure.AI.Inference" Version="1.0.0-beta.2" />
|
||||
<PackageVersion Include="Azure.AI.Inference" Version="1.0.0-beta.5" />
|
||||
<PackageVersion Include="Azure.AI.OpenAI" Version="[2.2.0-beta.4]" />
|
||||
<PackageVersion Include="Azure.AI.Projects" Version="[1.0.0-beta.8]" />
|
||||
<PackageVersion Include="Azure.Identity" Version="1.13.2" />
|
||||
<PackageVersion Include="Azure.Monitor.OpenTelemetry.Exporter" Version="1.3.0" />
|
||||
<PackageVersion Include="Azure.Search.Documents" Version="11.6.0" />
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
|
||||
<packageSources>
|
||||
<clear />
|
||||
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
|
||||
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
|
||||
</packageSources>
|
||||
|
||||
<packageSourceMapping>
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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<MenuPlugin>();
|
||||
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.
|
||||
|
||||
+5
-7
@@ -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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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<WidgetFactory>());
|
||||
|
||||
// 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<AzureAIAgent> 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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+6
-5
@@ -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.
|
||||
|
||||
+10
-10
@@ -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<string, string>() { { 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<string, string>() { { 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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
+5
-4
@@ -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<MenuPlugin>();
|
||||
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.
|
||||
|
||||
+10
-10
@@ -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<TokenCredential>(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<MenuPlugin>();
|
||||
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<AIProjectClient>(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)
|
||||
{
|
||||
|
||||
+15
-26
@@ -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.
|
||||
|
||||
+2
-2
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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>(openaiClient);
|
||||
builder.Services.AddSingleton<AIProjectClient>(aiProjectClient);
|
||||
builder.Services.AddSingleton<PersistentAgentsClient>(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
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Azure.AI.Projects" />
|
||||
<PackageReference Include="Azure.AI.Agents.Persistent" />
|
||||
<PackageReference Include="Azure.Identity" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
/// <summary>
|
||||
/// Provides an <see cref="AIProjectClient"/> for use by <see cref="AzureAIAgent"/>.
|
||||
/// Provides an <see cref="PersistentAgentsClient"/> for use by <see cref="AzureAIAgent"/>.
|
||||
/// </summary>
|
||||
public sealed partial class AzureAIAgent : Agent
|
||||
{
|
||||
/// <summary>
|
||||
/// Produces a <see cref="AIProjectClient"/>.
|
||||
/// Produces a <see cref="PersistentAgentsClient"/>.
|
||||
/// </summary>
|
||||
/// <param name="connectionString">The Azure AI Foundry project connection string, in the form `endpoint;subscription_id;resource_group_name;project_name`.</param>
|
||||
/// <param name="endpoint">The Azure AI Foundry project endpoint.</param>
|
||||
/// <param name="credential"> A credential used to authenticate to an Azure Service.</param>
|
||||
/// <param name="httpClient">A custom <see cref="HttpClient"/> for HTTP requests.</param>
|
||||
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);
|
||||
|
||||
|
||||
@@ -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
|
||||
/// <summary>
|
||||
/// Gets the assistant definition.
|
||||
/// </summary>
|
||||
public Azure.AI.Projects.Agent Definition { get; private init; }
|
||||
public PersistentAgent Definition { get; private init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the polling behavior for run processing.
|
||||
@@ -56,13 +55,13 @@ public sealed partial class AzureAIAgent : Agent
|
||||
/// Initializes a new instance of the <see cref="AzureAIAgent"/> class.
|
||||
/// </summary>
|
||||
/// <param name="model">The agent model definition.</param>
|
||||
/// <param name="client">An <see cref="AgentsClient"/> instance.</param>
|
||||
/// <param name="client">An <see cref="PersistentAgentsClient"/> instance.</param>
|
||||
/// <param name="plugins">Optional collection of plugins to add to the kernel.</param>
|
||||
/// <param name="templateFactory">An optional factory to produce the <see cref="IPromptTemplate"/> for the agent.</param>
|
||||
/// <param name="templateFormat">The format of the prompt template used when "templateFactory" parameter is supplied.</param>
|
||||
public AzureAIAgent(
|
||||
Azure.AI.Projects.Agent model,
|
||||
AgentsClient client,
|
||||
PersistentAgent model,
|
||||
PersistentAgentsClient client,
|
||||
IEnumerable<KernelPlugin>? plugins = null,
|
||||
IPromptTemplateFactory? templateFactory = null,
|
||||
string? templateFormat = null)
|
||||
@@ -95,7 +94,7 @@ public sealed partial class AzureAIAgent : Agent
|
||||
/// <summary>
|
||||
/// The associated client.
|
||||
/// </summary>
|
||||
public AgentsClient Client { get; }
|
||||
public PersistentAgentsClient Client { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
/// </summary>
|
||||
public sealed class AzureAIAgentThread : AgentThread
|
||||
{
|
||||
private readonly AgentsClient _client;
|
||||
private readonly PersistentAgentsClient _client;
|
||||
private readonly IEnumerable<ThreadMessageOptions>? _messages;
|
||||
private readonly ToolResources? _toolResources;
|
||||
private readonly IReadOnlyDictionary<string, string>? _metadata;
|
||||
@@ -34,7 +34,7 @@ public sealed class AzureAIAgentThread : AgentThread
|
||||
/// </param>
|
||||
/// <param name="metadata">Metadata to attach to the underlying thread when it is created..</param>
|
||||
public AzureAIAgentThread(
|
||||
AgentsClient client,
|
||||
PersistentAgentsClient client,
|
||||
IEnumerable<ThreadMessageOptions>? messages = null,
|
||||
ToolResources? toolResources = null,
|
||||
IReadOnlyDictionary<string, string>? metadata = null)
|
||||
@@ -52,7 +52,7 @@ public sealed class AzureAIAgentThread : AgentThread
|
||||
/// </summary>
|
||||
/// <param name="client">The agents client to use for interacting with threads.</param>
|
||||
/// <param name="id">The ID of an existing thread to resume.</param>
|
||||
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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
/// <summary>
|
||||
/// A <see cref="AgentChannel"/> specialization for use with <see cref="AzureAIAgent"/>.
|
||||
/// </summary>
|
||||
internal sealed class AzureAIChannel(AgentsClient client, string threadId)
|
||||
internal sealed class AzureAIChannel(PersistentAgentsClient client, string threadId)
|
||||
: AgentChannel<AzureAIAgent>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
@@ -53,7 +53,7 @@ internal sealed class AzureAIChannel(AgentsClient client, string threadId)
|
||||
/// <inheritdoc/>
|
||||
protected override Task ResetAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
return client.DeleteThreadAsync(threadId, cancellationToken);
|
||||
return client.Threads.DeleteThreadAsync(threadId, cancellationToken);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
|
||||
@@ -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;
|
||||
|
||||
/// <summary>
|
||||
/// Provides an <see cref="AIProjectClient"/> for use by <see cref="AzureAIAgent"/>.
|
||||
/// </summary>
|
||||
public sealed class AzureAIClientProvider
|
||||
{
|
||||
private AgentsClient? _agentsClient;
|
||||
|
||||
/// <summary>
|
||||
/// Gets an active client instance.
|
||||
/// </summary>
|
||||
public AIProjectClient Client { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets an active assistant client instance.
|
||||
/// </summary>
|
||||
public AgentsClient AgentsClient => this._agentsClient ??= this.Client.GetAgentsClient();
|
||||
|
||||
/// <summary>
|
||||
/// Configuration keys required for <see cref="AgentChannel"/> management.
|
||||
/// </summary>
|
||||
internal IReadOnlyList<string> ConfigurationKeys { get; }
|
||||
|
||||
private AzureAIClientProvider(AIProjectClient client, IEnumerable<string> keys)
|
||||
{
|
||||
this.Client = client;
|
||||
this.ConfigurationKeys = keys.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Produces a <see cref="AzureAIClientProvider"/>.
|
||||
/// </summary>
|
||||
/// <param name="connectionString">The Azure AI Foundry project connection string, in the form `endpoint;subscription_id;resource_group_name;project_name`.</param>
|
||||
/// <param name="credential"> A credential used to authenticate to an Azure Service.</param>
|
||||
/// <param name="httpClient">A custom <see cref="HttpClient"/> for HTTP requests.</param>
|
||||
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));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Provides a client instance directly.
|
||||
/// </summary>
|
||||
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<string> 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)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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";
|
||||
|
||||
/// <summary>
|
||||
/// Return the Azure AI tool definitions which corresponds with the provided <see cref="AgentDefinition"/>.
|
||||
@@ -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
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the <see cref="AIProjectClient"/> to be used with the specified <see cref="AgentDefinition"/>.
|
||||
/// Return the <see cref="PersistentAgentsClient"/> to be used with the specified <see cref="AgentDefinition"/>.
|
||||
/// </summary>
|
||||
/// <param name="agentDefinition">Agent definition which will be used to provide connection for the <see cref="AIProjectClient"/>.</param>
|
||||
/// <param name="kernel">Kernel instance which will be used to resolve a default <see cref="AIProjectClient"/>.</param>
|
||||
public static AIProjectClient GetAIProjectClient(this AgentDefinition agentDefinition, Kernel kernel)
|
||||
/// <param name="agentDefinition">Agent definition which will be used to provide connection for the <see cref="PersistentAgentsClient"/>.</param>
|
||||
/// <param name="kernel">Kernel instance which will be used to resolve a default <see cref="PersistentAgentsClient"/>.</param>
|
||||
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<TokenCredential>();
|
||||
return new(connectionString, tokenCredential, clientOptions);
|
||||
return AzureAIAgent.CreateAgentsClient(endpoint, tokenCredential, httpClient);
|
||||
}
|
||||
}
|
||||
|
||||
// Return the client registered on the kernel
|
||||
var client = kernel.GetAllServices<AIProjectClient>().FirstOrDefault();
|
||||
return (AIProjectClient?)client ?? throw new InvalidOperationException("AzureAI project client not found.");
|
||||
var client = kernel.GetAllServices<PersistentAgentsClient>().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
|
||||
}
|
||||
|
||||
@@ -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<RunStep> GetStepsAsync(
|
||||
this AgentsClient client,
|
||||
ThreadRun run,
|
||||
[EnumeratorCancellation] CancellationToken cancellationToken)
|
||||
this PersistentAgentsClient client,
|
||||
ThreadRun run,
|
||||
[EnumeratorCancellation] CancellationToken cancellationToken)
|
||||
{
|
||||
PageableList<RunStep>? steps = null;
|
||||
do
|
||||
AsyncPageable<RunStep>? 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<ThreadRun> 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<StreamingUpdate> 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,
|
||||
|
||||
@@ -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<string>? GetVectorStoreIds(this AgentToolDefinition agentToolDefinition)
|
||||
{
|
||||
return agentToolDefinition.GetOption<List<object>>("vector_store_ids")?.Select(id => id.ToString()!).ToList();
|
||||
return agentToolDefinition.GetOption<List<object>>("vector_store_ids")?.Select(id => $"{id}").ToList();
|
||||
}
|
||||
|
||||
internal static List<string>? GetFileIds(this AgentToolDefinition agentToolDefinition)
|
||||
@@ -236,13 +222,13 @@ internal static class AgentToolDefinitionExtensions
|
||||
return null;
|
||||
}
|
||||
|
||||
private static List<ToolConnection> GetToolConnections(this AgentToolDefinition agentToolDefinition)
|
||||
internal static List<string> GetToolConnections(this AgentToolDefinition agentToolDefinition)
|
||||
{
|
||||
Verify.NotNull(agentToolDefinition.Options);
|
||||
|
||||
var toolConnections = agentToolDefinition.GetRequiredOption<List<object>>("tool_connections");
|
||||
List<object> toolConnections = agentToolDefinition.GetRequiredOption<List<object>>("tool_connections");
|
||||
|
||||
return [.. toolConnections.Select(connectionId => new ToolConnection(connectionId.ToString()))];
|
||||
return [.. toolConnections.Select(connectionId => $"{connectionId}")];
|
||||
}
|
||||
|
||||
private static T GetRequiredOption<T>(this AgentToolDefinition agentToolDefinition, string key)
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// Translate metadata from a <see cref="ChatMessageContent"/> to be used for a <see cref="ThreadMessage"/> or
|
||||
/// Translate metadata from a <see cref="ChatMessageContent"/> to be used for a <see cref="PersistentThreadMessage"/> or
|
||||
/// <see cref="ThreadMessageOptions"/>.
|
||||
/// </summary>
|
||||
/// <param name="message">The message content.</param>
|
||||
@@ -25,7 +25,7 @@ internal static class AgentMessageFactory
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Translate attachments from a <see cref="ChatMessageContent"/> to be used for a <see cref="ThreadMessage"/> or
|
||||
/// Translate attachments from a <see cref="ChatMessageContent"/> to be used for a <see cref="PersistentThreadMessage"/> or
|
||||
/// </summary>
|
||||
/// <param name="message">The message content.</param>
|
||||
public static IEnumerable<MessageAttachment> GetAttachments(ChatMessageContent message)
|
||||
@@ -35,7 +35,7 @@ internal static class AgentMessageFactory
|
||||
.OfType<FileReferenceContent>()
|
||||
.Select(
|
||||
fileContent =>
|
||||
new MessageAttachment(fileContent.FileId, GetToolDefinition(fileContent.Tools).ToList()));
|
||||
new MessageAttachment(fileContent.FileId, [.. GetToolDefinition(fileContent.Tools)]));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
/// <param name="client">The assistant client</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||
/// <returns>The thread identifier</returns>
|
||||
public static async Task<string> CreateThreadAsync(AgentsClient client, CancellationToken cancellationToken = default)
|
||||
public static async Task<string> 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
|
||||
/// <param name="message">The message to add</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||
/// <throws><see cref="KernelException"/> if a system message is present, without taking any other action</throws>
|
||||
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
|
||||
/// <param name="messageOrder">The order to return messages in.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||
/// <returns>Asynchronous enumeration of messages.</returns>
|
||||
public static async IAsyncEnumerable<ChatMessageContent> GetMessagesAsync(AgentsClient client, string threadId, ListSortOrder? messageOrder, [EnumeratorCancellation] CancellationToken cancellationToken)
|
||||
public static async IAsyncEnumerable<ChatMessageContent> GetMessagesAsync(PersistentAgentsClient client, string threadId, ListSortOrder? messageOrder, [EnumeratorCancellation] CancellationToken cancellationToken)
|
||||
{
|
||||
Dictionary<string, string?> agentNames = []; // Cache agent names by their identifier
|
||||
|
||||
string? lastId = null;
|
||||
PageableList<ThreadMessage>? messages = null;
|
||||
do
|
||||
AsyncPageable<PersistentThreadMessage>? 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -140,7 +135,7 @@ internal static class AgentThreadActions
|
||||
/// <returns>Asynchronous enumeration of messages.</returns>
|
||||
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
|
||||
/// </remarks>
|
||||
public static async IAsyncEnumerable<StreamingChatMessageContent> InvokeStreamingAsync(
|
||||
AzureAIAgent agent,
|
||||
AgentsClient client,
|
||||
PersistentAgentsClient client,
|
||||
string threadId,
|
||||
IList<ChatMessageContent>? 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<string, object?>? 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<ThreadMessage?> RetrieveMessageAsync(AgentsClient client, string threadId, string messageId, TimeSpan syncDelay, CancellationToken cancellationToken)
|
||||
private static async Task<PersistentThreadMessage?> 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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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<TokenCredential>();
|
||||
return new AzureOpenAIClient(endpoint, tokenCredential, clientOptions);
|
||||
return OpenAIAssistantAgent.CreateAzureOpenAIClient(tokenCredential, endpoint, httpClient);
|
||||
}
|
||||
|
||||
throw new InvalidOperationException($"Invalid OpenAI client type '{connection.Type}' was specified.");
|
||||
|
||||
@@ -19,6 +19,7 @@ namespace Microsoft.SemanticKernel.Agents.OpenAI;
|
||||
/// Provides an <see cref="OpenAIClient"/> for use by <see cref="OpenAIAssistantAgent"/>.
|
||||
/// </summary>
|
||||
[Experimental("SKEXP0110")]
|
||||
[Obsolete("Use OpenAIAssistantAgent.CreateAzureOpenAIClient(...) or OpenAIAssistantAgent.CreateOpenAIClient(...)")]
|
||||
public sealed class OpenAIClientProvider
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -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;
|
||||
|
||||
/// <summary>
|
||||
/// Unit testing of <see cref="AzureAIClientProvider"/>.
|
||||
/// </summary>
|
||||
public class AzureAIClientProviderTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Verify that provisioning of client for Azure OpenAI.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void VerifyAzureAIClientProviderDefault()
|
||||
{
|
||||
// Act
|
||||
AzureAIClientProvider provider = AzureAIClientProvider.FromConnectionString("test;test;test;test", new AzureCliCredential());
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(provider.Client);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verify that the factory can create a client with http proxy.
|
||||
/// </summary>
|
||||
[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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verify that the factory can accept an client that already exists.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void VerifyAzureAIClientProviderFromClient()
|
||||
{
|
||||
// Arrange
|
||||
Mock<AIProjectClient> mockClient = new();
|
||||
AzureAIClientProvider provider = AzureAIClientProvider.FromClient(mockClient.Object);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(provider.Client);
|
||||
Assert.Equal(mockClient.Object, provider.Client);
|
||||
}
|
||||
}
|
||||
@@ -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<AIProjectClient>(client);
|
||||
new PersistentAgentsAdministrationClientOptions
|
||||
{
|
||||
Transport = new HttpClientTransport(this._httpClient)
|
||||
});
|
||||
builder.Services.AddSingleton(client);
|
||||
this._kernel = builder.Build();
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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>(openAIClient);
|
||||
|
||||
@@ -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;
|
||||
|
||||
/// <summary>
|
||||
/// 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<string, string> 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) =>
|
||||
|
||||
@@ -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;
|
||||
|
||||
/// <summary>
|
||||
/// 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) =>
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 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<AIProjectClient>(client);
|
||||
new PersistentAgentsAdministrationClientOptions
|
||||
{
|
||||
Transport = new HttpClientTransport(this._httpClient)
|
||||
});
|
||||
builder.Services.AddSingleton(client);
|
||||
|
||||
this._kernel = builder.Build();
|
||||
}
|
||||
|
||||
@@ -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<AIProjectClient>(client);
|
||||
new PersistentAgentsAdministrationClientOptions
|
||||
{
|
||||
Transport = new HttpClientTransport(this._httpClient)
|
||||
});
|
||||
builder.Services.AddSingleton(client);
|
||||
|
||||
this._kernel = builder.Build();
|
||||
this._kernel.Plugins.Add(KernelPluginFactory.CreateFromType<WeatherPlugin>());
|
||||
@@ -217,42 +219,6 @@ public class AzureAIKernelAgentYamlTests : IDisposable
|
||||
Assert.Equal("bing_grounding", requestJson.GetProperty("tools")[0].GetProperty("type").GetString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verify the request includes a Microsoft Fabric tool when creating an Azure AI agent.
|
||||
/// </summary>
|
||||
[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<JsonElement>(requestContent);
|
||||
Assert.Equal(1, requestJson.GetProperty("tools").GetArrayLength());
|
||||
Assert.Equal("fabric_dataagent", requestJson.GetProperty("tools")[0].GetProperty("type").GetString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verify the request includes a Open API tool when creating an Azure AI agent.
|
||||
/// </summary>
|
||||
@@ -306,42 +272,6 @@ public class AzureAIKernelAgentYamlTests : IDisposable
|
||||
Assert.Equal("openapi", requestJson.GetProperty("tools")[2].GetProperty("type").GetString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verify the request includes a Sharepoint tool when creating an Azure AI agent.
|
||||
/// </summary>
|
||||
[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<JsonElement>(requestContent);
|
||||
Assert.Equal(1, requestJson.GetProperty("tools").GetArrayLength());
|
||||
Assert.Equal("sharepoint_grounding", requestJson.GetProperty("tools")[0].GetProperty("type").GetString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verify the request includes a code interpreter tool and associated resource when creating an Azure AI agent.
|
||||
/// </summary>
|
||||
|
||||
@@ -40,7 +40,6 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Azure.AI.Projects" />
|
||||
<PackageReference Include="Azure.Identity" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Azure.AI.Projects" />
|
||||
<PackageReference Include="Azure.Identity" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -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<AIProjectClient>(this._client);
|
||||
builder.Services.AddSingleton<PersistentAgentsClient>(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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+16
-16
@@ -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<AzureAIAgentFixture>()
|
||||
.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<ChatHistory> 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<AzureAIConfiguration>()!;
|
||||
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;<subscription_id>;<resource_group_name>;<project_name>", 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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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<AzureOpenAIConfiguration>();
|
||||
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<MenuPlugin>();
|
||||
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<MenuPlugin>();
|
||||
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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -39,13 +39,13 @@ public static class AgentThreadFactory
|
||||
private static async Task<AgentThread> 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<Azure.AI.Projects.AgentsClient>() ?? throw new KernelException("The AzureAI thread type requires an AgentsClient to be registered in the kernel.");
|
||||
var client = kernel.Services.GetService<Azure.AI.Agents.Persistent.PersistentAgentsClient>() ?? 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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 }
|
||||
});
|
||||
|
||||
/// <summary>
|
||||
/// Provide a <see cref="OpenAIClientProvider"/> according to the configuration settings.
|
||||
/// </summary>
|
||||
protected AzureAIClientProvider GetAzureProvider()
|
||||
{
|
||||
return AzureAIClientProvider.FromConnectionString(TestConfiguration.AzureAI.ConnectionString, new AzureCliCredential());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Provide a <see cref="OpenAIClientProvider"/> according to the configuration settings.
|
||||
/// </summary>
|
||||
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!));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Common method to write formatted agent chat content to the console.
|
||||
/// </summary>
|
||||
|
||||
@@ -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;
|
||||
/// <summary>
|
||||
/// Base class for samples that demonstrate the usage of <see cref="AzureAIAgent"/>.
|
||||
/// </summary>
|
||||
public abstract class BaseAzureAgentTest : BaseAgentsTest<AIProjectClient>
|
||||
public abstract class BaseAzureAgentTest : BaseAgentsTest<PersistentAgentsClient>
|
||||
{
|
||||
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());
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override AIProjectClient Client { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="AgentsClient"/>.
|
||||
/// </summary>
|
||||
protected AgentsClient AgentsClient { get; }
|
||||
protected override PersistentAgentsClient Client { get; }
|
||||
|
||||
protected async Task DownloadContentAsync(ChatMessageContent message)
|
||||
{
|
||||
@@ -39,8 +32,8 @@ public abstract class BaseAzureAgentTest : BaseAgentsTest<AIProjectClient>
|
||||
|
||||
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<AIProjectClient>
|
||||
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}");
|
||||
|
||||
|
||||
@@ -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; }
|
||||
|
||||
Reference in New Issue
Block a user