Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
43c26ae
Checkpoint
crickman Feb 18, 2025
525b711
Merge branch 'main' into agents-assistant-fixes-and-streamlining
crickman Feb 18, 2025
f969db7
Namespace
crickman Feb 18, 2025
729bd06
Namespace
crickman Feb 18, 2025
aab75b0
Almost
crickman Feb 18, 2025
1e4e4bc
Namespace / header
crickman Feb 18, 2025
fb04c6b
Integration tests
crickman Feb 18, 2025
66d28c0
Namespace
crickman Feb 18, 2025
162132f
Namespace
crickman Feb 18, 2025
5493b1e
Merge branch 'main' into agents-assistant-fixes-and-streamlining
crickman Feb 18, 2025
5025aa2
Coverage
crickman Feb 18, 2025
13d335e
Refine covered surface area
crickman Feb 18, 2025
5484f94
Namespace
crickman Feb 18, 2025
96ee53e
Test cleanup
crickman Feb 18, 2025
0ce3bcd
More coverage
crickman Feb 18, 2025
0a6b891
Exclude streaming
crickman Feb 18, 2025
2177597
Final
crickman Feb 18, 2025
f1274c4
Fix build
crickman Feb 18, 2025
66b95f4
Update constructor
crickman Feb 18, 2025
b42c88f
Merge branch 'main' into agents-assistant-fixes-and-streamlining
crickman Feb 18, 2025
6d6e2ab
Namespace
crickman Feb 18, 2025
f6067c3
Namespace
crickman Feb 18, 2025
787da66
Merge branch 'main' into agents-assistant-fixes-and-streamlining
crickman Feb 18, 2025
527986c
Merge branch 'main' into agents-assistant-fixes-and-streamlining
crickman Feb 19, 2025
773b005
Merge branch 'main' into agents-assistant-fixes-and-streamlining
crickman Feb 19, 2025
8aea63a
Fix integration test
crickman Feb 19, 2025
7180009
Merge branch 'agents-assistant-fixes-and-streamlining' of https://git…
crickman Feb 19, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 7 additions & 49 deletions dotnet/samples/Concepts/Agents/AzureAIAgent_FileManipulation.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// Copyright (c) Microsoft. All rights reserved.
using System.Diagnostics;
using Azure.AI.Projects;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Agents;
Expand All @@ -13,19 +12,16 @@ namespace Agents;
/// <summary>
/// Demonstrate using code-interpreter to manipulate and generate csv files with <see cref="AzureAIAgent"/> .
/// </summary>
public class AzureAIAgent_FileManipulation(ITestOutputHelper output) : BaseAgentsTest(output)
public class AzureAIAgent_FileManipulation(ITestOutputHelper output) : BaseAzureAgentTest(output)
{
[Fact]
public async Task AnalyzeCSVFileUsingAzureAIAgentAsync()
{
AzureAIClientProvider clientProvider = this.GetAzureProvider();
AgentsClient client = clientProvider.Client.GetAgentsClient();

await using Stream stream = EmbeddedResource.ReadStream("sales.csv")!;
AgentFile fileInfo = await client.UploadFileAsync(stream, AgentFilePurpose.Agents, "sales.csv");
AgentFile fileInfo = await this.AgentsClient.UploadFileAsync(stream, AgentFilePurpose.Agents, "sales.csv");

// Define the agent
Agent definition = await client.CreateAgentAsync(
Agent definition = await this.AgentsClient.CreateAgentAsync(
TestConfiguration.AzureAI.ChatModelId,
tools: [new CodeInterpreterToolDefinition()],
toolResources:
Expand All @@ -36,7 +32,7 @@ public async Task AnalyzeCSVFileUsingAzureAIAgentAsync()
FileIds = { fileInfo.Id },
}
});
AzureAIAgent agent = new(definition, clientProvider);
AzureAIAgent agent = new(definition, this.AgentsClient);

// Create a chat for agent interaction.
AgentGroupChat chat = new();
Expand All @@ -50,8 +46,8 @@ public async Task AnalyzeCSVFileUsingAzureAIAgentAsync()
}
finally
{
await client.DeleteAgentAsync(agent.Id);
await client.DeleteFileAsync(fileInfo.Id);
await this.AgentsClient.DeleteAgentAsync(agent.Id);
await this.AgentsClient.DeleteFileAsync(fileInfo.Id);
await chat.ResetAsync();
}

Expand All @@ -65,45 +61,7 @@ async Task InvokeAgentAsync(string input)
await foreach (ChatMessageContent response in chat.InvokeAsync(agent))
{
this.WriteAgentChatMessage(response);
await this.DownloadContentAsync(client, response);
}
}
}

private async Task DownloadContentAsync(AgentsClient client, ChatMessageContent message)
{
foreach (KernelContent item in message.Items)
{
if (item is AnnotationContent annotation)
{
await this.DownloadFileAsync(client, annotation.FileId!);
}
}
}

private async Task DownloadFileAsync(AgentsClient client, string fileId, bool launchViewer = false)
{
AgentFile fileInfo = client.GetFile(fileId);
if (fileInfo.Purpose == AgentFilePurpose.AgentsOutput)
{
string filePath = Path.Combine(Path.GetTempPath(), Path.GetFileName(fileInfo.Filename));
if (launchViewer)
{
filePath = Path.ChangeExtension(filePath, ".png");
}

BinaryData content = await client.GetFileContentAsync(fileId);
File.WriteAllBytes(filePath, content.ToArray());
Console.WriteLine($" File #{fileId} saved to: {filePath}");

if (launchViewer)
{
Process.Start(
new ProcessStartInfo
{
FileName = "cmd.exe",
Arguments = $"/C start {filePath}"
});
await this.DownloadContentAsync(response);
}
}
}
Expand Down
26 changes: 10 additions & 16 deletions dotnet/samples/Concepts/Agents/AzureAIAgent_Streaming.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ namespace Agents;
/// <summary>
/// Demonstrate consuming "streaming" message for <see cref="AzureAIAgent"/>.
/// </summary>
public class AzureAIAgent_Streaming(ITestOutputHelper output) : BaseAgentsTest(output)
public class AzureAIAgent_Streaming(ITestOutputHelper output) : BaseAzureAgentTest(output)
{
[Fact]
public async Task UseStreamingAgentAsync()
Expand All @@ -20,17 +20,15 @@ public async Task UseStreamingAgentAsync()
const string AgentInstructions = "Repeat the user message in the voice of a pirate and then end with a parrot sound.";

// Define the agent
AzureAIClientProvider clientProvider = this.GetAzureProvider();
AgentsClient client = clientProvider.Client.GetAgentsClient();
Agent definition = await client.CreateAgentAsync(
Agent definition = await this.AgentsClient.CreateAgentAsync(
TestConfiguration.AzureAI.ChatModelId,
AgentName,
null,
AgentInstructions);
AzureAIAgent agent = new(definition, clientProvider);
AzureAIAgent agent = new(definition, this.AgentsClient);

// Create a thread for the agent conversation.
AgentThread thread = await client.CreateThreadAsync(metadata: AssistantSampleMetadata);
AgentThread thread = await this.AgentsClient.CreateThreadAsync(metadata: SampleMetadata);

// Respond to user input
await InvokeAgentAsync(agent, thread.Id, "Fortune favors the bold.");
Expand All @@ -48,14 +46,12 @@ public async Task UseStreamingAssistantAgentWithPluginAsync()
const string AgentInstructions = "Answer questions about the menu.";

// Define the agent
AzureAIClientProvider clientProvider = this.GetAzureProvider();
AgentsClient client = clientProvider.Client.GetAgentsClient();
Agent definition = await client.CreateAgentAsync(
Agent definition = await this.AgentsClient.CreateAgentAsync(
TestConfiguration.AzureAI.ChatModelId,
AgentName,
null,
AgentInstructions);
AzureAIAgent agent = new(definition, clientProvider)
AzureAIAgent agent = new(definition, this.AgentsClient)
{
Kernel = new Kernel(),
};
Expand All @@ -65,7 +61,7 @@ public async Task UseStreamingAssistantAgentWithPluginAsync()
agent.Kernel.Plugins.Add(plugin);

// Create a thread for the agent conversation.
AgentThread thread = await client.CreateThreadAsync(metadata: AssistantSampleMetadata);
AgentThread thread = await this.AgentsClient.CreateThreadAsync(metadata: SampleMetadata);

// Respond to user input
await InvokeAgentAsync(agent, thread.Id, "What is the special soup and its price?");
Expand All @@ -82,21 +78,19 @@ public async Task UseStreamingAssistantWithCodeInterpreterAsync()
const string AgentInstructions = "Solve math problems with code.";

// Define the agent
AzureAIClientProvider clientProvider = this.GetAzureProvider();
AgentsClient client = clientProvider.Client.GetAgentsClient();
Agent definition = await client.CreateAgentAsync(
Agent definition = await this.AgentsClient.CreateAgentAsync(
TestConfiguration.AzureAI.ChatModelId,
AgentName,
null,
AgentInstructions,
[new CodeInterpreterToolDefinition()]);
AzureAIAgent agent = new(definition, clientProvider)
AzureAIAgent agent = new(definition, this.AgentsClient)
{
Kernel = new Kernel(),
};

// Create a thread for the agent conversation.
AgentThread thread = await client.CreateThreadAsync(metadata: AssistantSampleMetadata);
AgentThread thread = await this.AgentsClient.CreateThreadAsync(metadata: SampleMetadata);

// Respond to user input
await InvokeAgentAsync(agent, thread.Id, "Is 191 a prime number?");
Expand Down
31 changes: 11 additions & 20 deletions dotnet/samples/Concepts/Agents/DeclarativeAgents.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// Copyright (c) Microsoft. All rights reserved.
using System.Text;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Agents;
using Microsoft.SemanticKernel.ChatCompletion;
Expand All @@ -9,11 +8,13 @@ namespace Agents;

public class DeclarativeAgents(ITestOutputHelper output) : BaseAgentsTest(output)
{
[InlineData("SchedulingAssistant.json", "Read the body of my last five emails, if any contain a meeting request for today, check that it's already on my calendar, if not, call out which email it is.")]
[InlineData(
"SchedulingAssistant.json",
"Read the body of my last five emails, if any contain a meeting request for today, check that it's already on my calendar, if not, call out which email it is.")]
[Theory]
public async Task LoadsAgentFromDeclarativeAgentManifestAsync(string agentFileName, string input)
{
var kernel = CreateKernel();
var kernel = this.CreateKernelWithChatCompletion();
kernel.AutoFunctionInvocationFilters.Add(new ExpectedSchemaFunctionFilter());
var manifestLookupDirectory = Path.Combine(Directory.GetCurrentDirectory(), "..", "..", "..", "Resources", "DeclarativeAgents");
var manifestFilePath = Path.Combine(manifestLookupDirectory, agentFileName);
Expand All @@ -30,9 +31,8 @@ public async Task LoadsAgentFromDeclarativeAgentManifestAsync(string agentFileNa
Assert.NotNull(agent.Instructions);
Assert.NotEmpty(agent.Instructions);

ChatMessageContent message = new(AuthorRole.User, input);
ChatHistory chatHistory = [message];
StringBuilder sb = new();
ChatHistory chatHistory = [new ChatMessageContent(AuthorRole.User, input)];

var kernelArguments = new KernelArguments(new PromptExecutionSettings
{
FunctionChoiceBehavior = FunctionChoiceBehavior.Auto(
Expand All @@ -42,23 +42,14 @@ public async Task LoadsAgentFromDeclarativeAgentManifestAsync(string agentFileNa
}
)
});
await foreach (ChatMessageContent response in agent.InvokeAsync(chatHistory, kernelArguments))
{
chatHistory.Add(response);
sb.Append(response.Content);
}
Assert.NotEmpty(chatHistory.Skip(1));
}
private Kernel CreateKernel()
{
IKernelBuilder builder = Kernel.CreateBuilder();

base.AddChatCompletionToKernel(builder);

return builder.Build();
var responses = await agent.InvokeAsync(chatHistory, kernelArguments).ToArrayAsync();
Assert.NotEmpty(responses);
}

private sealed class ExpectedSchemaFunctionFilter : IAutoFunctionInvocationFilter
{//TODO: this eventually needs to be added to all CAP or DA but we're still discussing where should those facilitators live
{
//TODO: this eventually needs to be added to all CAP or DA but we're still discussing where should those facilitators live
public async Task OnAutoFunctionInvocationAsync(AutoFunctionInvocationContext context, Func<AutoFunctionInvocationContext, Task> next)
{
await next(context);
Expand Down
23 changes: 12 additions & 11 deletions dotnet/samples/Concepts/Agents/MixedChat_Agents.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@
using Microsoft.SemanticKernel.Agents.Chat;
using Microsoft.SemanticKernel.Agents.OpenAI;
using Microsoft.SemanticKernel.ChatCompletion;
using OpenAI.Assistants;

namespace Agents;
/// <summary>
/// Demonstrate that two different agent types are able to participate in the same conversation.
/// In this case a <see cref="ChatCompletionAgent"/> and <see cref="OpenAIAssistantAgent"/> participate.
/// </summary>
public class MixedChat_Agents(ITestOutputHelper output) : BaseAgentsTest(output)
public class MixedChat_Agents(ITestOutputHelper output) : BaseAssistantTest(output)
{
private const string ReviewerName = "ArtDirector";
private const string ReviewerInstructions =
Expand Down Expand Up @@ -44,16 +45,16 @@ public async Task ChatWithOpenAIAssistantAgentAndChatCompletionAgentAsync()
Kernel = this.CreateKernelWithChatCompletion(),
};

OpenAIAssistantAgent agentWriter =
await OpenAIAssistantAgent.CreateAsync(
clientProvider: this.GetClientProvider(),
definition: new OpenAIAssistantDefinition(this.Model)
{
Instructions = CopyWriterInstructions,
Name = CopyWriterName,
Metadata = AssistantSampleMetadata,
},
kernel: new Kernel());
// Define the assistant
Assistant assistant =
await this.AssistantClient.CreateAssistantAsync(
this.Model,
name: CopyWriterName,
instructions: CopyWriterInstructions,
metadata: SampleMetadata);

// Create the agent
OpenAIAssistantAgent agentWriter = new(assistant, this.AssistantClient);

// Create a chat for agent interaction.
AgentGroupChat chat =
Expand Down
43 changes: 17 additions & 26 deletions dotnet/samples/Concepts/Agents/MixedChat_Files.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
using Microsoft.SemanticKernel.Agents;
using Microsoft.SemanticKernel.Agents.OpenAI;
using Microsoft.SemanticKernel.ChatCompletion;
using OpenAI.Files;
using OpenAI.Assistants;
using Resources;

namespace Agents;
Expand All @@ -12,36 +12,27 @@ namespace Agents;
/// Demonstrate <see cref="ChatCompletionAgent"/> agent interacts with
/// <see cref="OpenAIAssistantAgent"/> when it produces file output.
/// </summary>
public class MixedChat_Files(ITestOutputHelper output) : BaseAgentsTest(output)
public class MixedChat_Files(ITestOutputHelper output) : BaseAssistantTest(output)
{
private const string SummaryInstructions = "Summarize the entire conversation for the user in natural language.";

[Fact]
public async Task AnalyzeFileAndGenerateReportAsync()
{
OpenAIClientProvider provider = this.GetClientProvider();

OpenAIFileClient fileClient = provider.Client.GetOpenAIFileClient();

OpenAIFile uploadFile =
await fileClient.UploadFileAsync(
new BinaryData(await EmbeddedResource.ReadAllAsync("30-user-context.txt")),
"30-user-context.txt",
FileUploadPurpose.Assistants);

Console.WriteLine(this.ApiKey);
await using Stream stream = EmbeddedResource.ReadStream("30-user-context.txt")!;
string fileId = await this.Client.UploadAssistantFileAsync(stream, "30-user-context.txt");

// Define the agents
OpenAIAssistantAgent analystAgent =
await OpenAIAssistantAgent.CreateAsync(
provider,
definition: new OpenAIAssistantDefinition(this.Model)
{
EnableCodeInterpreter = true,
CodeInterpreterFileIds = [uploadFile.Id], // Associate uploaded file with assistant code-interpreter
Metadata = AssistantSampleMetadata,
},
kernel: new Kernel());
// Define the assistant
Assistant assistant =
await this.AssistantClient.CreateAssistantAsync(
this.Model,
enableCodeInterpreter: true,
codeInterpreterFileIds: [fileId],
metadata: SampleMetadata);

// Create the agent
OpenAIAssistantAgent analystAgent = new(assistant, this.AssistantClient);

ChatCompletionAgent summaryAgent =
new()
Expand All @@ -66,8 +57,8 @@ Create a tab delimited file report of the ordered (descending) frequency distrib
}
finally
{
await analystAgent.DeleteAsync();
await fileClient.DeleteFileAsync(uploadFile.Id);
await this.AssistantClient.DeleteAssistantAsync(analystAgent.Id);
await this.Client.DeleteFileAsync(fileId);
}

// Local function to invoke agent and display the conversation messages.
Expand All @@ -83,7 +74,7 @@ async Task InvokeAgentAsync(Agent agent, string? input = null)
await foreach (ChatMessageContent response in chat.InvokeAsync(agent))
{
this.WriteAgentChatMessage(response);
await this.DownloadResponseContentAsync(fileClient, response);
await this.DownloadResponseContentAsync(response);
}
}
}
Expand Down
Loading