Skip to content

.Net: SK integration with MEAI Abstractions #10754

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 54 commits into from
May 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
908333b
.Net: SK integration with MEAI Abstractions (Service Selector + Conte…
RogerBarreto Mar 3, 2025
16187a3
Merge branch 'main' into feature-msextensions-ai
RogerBarreto Mar 3, 2025
409c6e1
Merge branch 'main' into feature-msextensions-ai
RogerBarreto Mar 4, 2025
8476321
Merge branch 'main' into feature-msextensions-ai
RogerBarreto Mar 10, 2025
23b0859
Merge branch 'main' into feature-msextensions-ai
RogerBarreto Mar 12, 2025
af9a595
Merge branch 'main' into feature-msextensions-ai
RogerBarreto Mar 14, 2025
939c268
Merge branch 'main' into feature-msextensions-ai
RogerBarreto Mar 18, 2025
c99328b
Merge branch 'main' of https://github.com/microsoft/semantic-kernel i…
RogerBarreto Mar 19, 2025
dd04727
Adjusting conflicts and adapting to new ChatClient.Messages
RogerBarreto Mar 19, 2025
a773586
Fix warnings
RogerBarreto Mar 19, 2025
a0e2dcd
Merge branch 'main' into feature-msextensions-ai
RogerBarreto Mar 20, 2025
5882adc
Merge branch 'main' into feature-msextensions-ai
RogerBarreto Mar 20, 2025
dfbf238
.Net: MEAI - Add `IChatClient` support for `ChatCompletionAgents` (#1…
RogerBarreto Mar 29, 2025
64d6004
Merge branch 'main' of https://github.com/microsoft/semantic-kernel i…
RogerBarreto Apr 1, 2025
2a82d90
Fix conflict, test passing
RogerBarreto Apr 1, 2025
8bcb334
Fix merge conflicts
RogerBarreto Apr 1, 2025
772a290
Merge branch 'main' into feature-msextensions-ai
RogerBarreto Apr 1, 2025
65f72ad
Fix format
RogerBarreto Apr 1, 2025
f685ac4
Fix format
RogerBarreto Apr 1, 2025
a24ec7a
Merge branch 'main' into feature-msextensions-ai
RogerBarreto Apr 7, 2025
6c42605
Merge branch 'main' into feature-msextensions-ai
RogerBarreto Apr 11, 2025
8f92fac
.Net: AutoFunctionInvocation IChatClient Support (#11536)
RogerBarreto Apr 16, 2025
d0543e9
.Net: main -> feature-msextensions-ai (Conflict fix) (#11610)
RogerBarreto Apr 17, 2025
b948ad0
Merge branch 'main' into feature-msextensions-ai
RogerBarreto Apr 17, 2025
79e618d
Merge branch 'main' into feature-msextensions-ai
RogerBarreto Apr 18, 2025
c21feaf
Merge branch 'main' into feature-msextensions-ai
RogerBarreto Apr 19, 2025
404eb75
Merge branch 'main' into feature-msextensions-ai
RogerBarreto Apr 23, 2025
13dd0d2
Merge branch 'main' into feature-msextensions-ai
RogerBarreto Apr 24, 2025
b62b51b
Remove duplicate reference
RogerBarreto Apr 24, 2025
0f92230
Merge branch 'main' into feature-msextensions-ai
RogerBarreto May 1, 2025
79bcb8d
Merge branch 'main' into feature-msextensions-ai
RogerBarreto May 1, 2025
5079737
Merge branch 'main' into feature-msextensions-ai
RogerBarreto May 2, 2025
baf8250
Merge branch 'main' into feature-msextensions-ai
RogerBarreto May 2, 2025
9381c8d
.Net: Update KernelFunctionInvokingChatClient as a specialization of …
RogerBarreto May 6, 2025
f86c621
Merge branch 'main' into feature-msextensions-ai
RogerBarreto May 6, 2025
8999dbb
Merge branch 'main' into feature-msextensions-ai
RogerBarreto May 9, 2025
3aa6ebc
.Net: KernelFunctions as AIFunctions (#11836)
RogerBarreto May 12, 2025
20400ef
Merge branch 'main' of https://github.com/microsoft/semantic-kernel i…
RogerBarreto May 14, 2025
22d5c3a
.Net: Update to Intermediate KernelFunction Approach (#12055)
RogerBarreto May 15, 2025
0601929
Merge branch 'main' into feature-msextensions-ai
RogerBarreto May 15, 2025
7ba6cdf
Merge branch 'main' into feature-msextensions-ai
RogerBarreto May 16, 2025
52e1e5a
Fix duplicates and AssertStepState error
RogerBarreto May 16, 2025
bf49577
Merge branch 'main' into feature-msextensions-ai
RogerBarreto May 19, 2025
33f4c14
Fix suppressions
RogerBarreto May 19, 2025
fcbe042
.Net: KernelChatOptions + ChatClient Extension methods + Update to Bu…
RogerBarreto May 19, 2025
b80e135
Fix error
RogerBarreto May 19, 2025
04e0a06
Merge branch 'main' into feature-msextensions-ai
RogerBarreto May 19, 2025
bdc4550
Fix IT model
RogerBarreto May 19, 2025
0bdf022
Merge branch 'feature-msextensions-ai' of https://github.com/microsof…
RogerBarreto May 19, 2025
74ce972
Merge branch 'main' of https://github.com/microsoft/semantic-kernel i…
RogerBarreto May 19, 2025
3f6a56c
Fix conflict
RogerBarreto May 19, 2025
7e0ea3c
Suppression adjustment
RogerBarreto May 19, 2025
0b8af0f
Fix obsolete message
RogerBarreto May 19, 2025
50c6675
Merge branch 'main' into feature-msextensions-ai
markwallace-microsoft May 20, 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
3 changes: 0 additions & 3 deletions dotnet/SK-dotnet.sln
Original file line number Diff line number Diff line change
Expand Up @@ -433,8 +433,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OllamaFunctionCalling", "sa
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenAIRealtime", "samples\Demos\OpenAIRealtime\OpenAIRealtime.csproj", "{6154129E-7A35-44A5-998E-B7001B5EDE14}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "CreateChatGpt", "CreateChatGpt", "{02EA681E-C7D8-13C7-8484-4AC65E1B71E8}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "VectorDataIntegrationTests", "VectorDataIntegrationTests", "{4F381919-F1BE-47D8-8558-3187ED04A84F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QdrantIntegrationTests", "src\VectorDataIntegrationTests\QdrantIntegrationTests\QdrantIntegrationTests.csproj", "{27D33AB3-4DFF-48BC-8D76-FB2CDF90B707}"
Expand Down Expand Up @@ -1681,7 +1679,6 @@ Global
{B35B1DEB-04DF-4141-9163-01031B22C5D1} = {0D8C6358-5DAA-4EA6-A924-C268A9A21BC9}
{481A680F-476A-4627-83DE-2F56C484525E} = {5D4C0700-BBB5-418F-A7B2-F392B9A18263}
{6154129E-7A35-44A5-998E-B7001B5EDE14} = {5D4C0700-BBB5-418F-A7B2-F392B9A18263}
{02EA681E-C7D8-13C7-8484-4AC65E1B71E8} = {5D4C0700-BBB5-418F-A7B2-F392B9A18263}
{4F381919-F1BE-47D8-8558-3187ED04A84F} = {831DDCA2-7D2C-4C31-80DB-6BDB3E1F7AE0}
{27D33AB3-4DFF-48BC-8D76-FB2CDF90B707} = {4F381919-F1BE-47D8-8558-3187ED04A84F}
{B29A972F-A774-4140-AECF-6B577C476627} = {4F381919-F1BE-47D8-8558-3187ED04A84F}
Expand Down
125 changes: 117 additions & 8 deletions dotnet/samples/Concepts/Agents/ChatCompletion_FunctionTermination.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,17 @@ namespace Agents;
/// </summary>
public class ChatCompletion_FunctionTermination(ITestOutputHelper output) : BaseAgentsTest(output)
{
[Fact]
public async Task UseAutoFunctionInvocationFilterWithAgentInvocationAsync()
[Theory]
[InlineData(true)]
[InlineData(false)]
public async Task UseAutoFunctionInvocationFilterWithAgentInvocation(bool useChatClient)
{
// Define the agent
ChatCompletionAgent agent =
new()
{
Instructions = "Answer questions about the menu.",
Kernel = CreateKernelWithFilter(),
Kernel = CreateKernelWithFilter(useChatClient),
Arguments = new KernelArguments(new PromptExecutionSettings() { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() }),
};

Expand Down Expand Up @@ -53,15 +55,60 @@ async Task InvokeAgentAsync(string input)
}
}

[Fact]
public async Task UseAutoFunctionInvocationFilterWithStreamingAgentInvocationAsync()
[Theory]
[InlineData(true)]
[InlineData(false)]
public async Task UseAutoFunctionInvocationFilterWithAgentChat(bool useChatClient)
{
// Define the agent
ChatCompletionAgent agent =
new()
{
Instructions = "Answer questions about the menu.",
Kernel = CreateKernelWithFilter(),
Kernel = CreateKernelWithFilter(useChatClient),
Arguments = new KernelArguments(new PromptExecutionSettings() { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() }),
};

KernelPlugin plugin = KernelPluginFactory.CreateFromType<MenuPlugin>();
agent.Kernel.Plugins.Add(plugin);

// Create a chat for agent interaction.
AgentGroupChat chat = new();

// Respond to user input, invoking functions where appropriate.
await InvokeAgentAsync("Hello");
await InvokeAgentAsync("What is the special soup?");
await InvokeAgentAsync("What is the special drink?");
await InvokeAgentAsync("Thank you");

// Display the entire chat history.
WriteChatHistory(await chat.GetChatMessagesAsync().ToArrayAsync());

// Local function to invoke agent and display the conversation messages.
async Task InvokeAgentAsync(string input)
{
ChatMessageContent message = new(AuthorRole.User, input);
chat.AddChatMessage(message);
this.WriteAgentChatMessage(message);

await foreach (ChatMessageContent response in chat.InvokeAsync(agent))
{
this.WriteAgentChatMessage(response);
}
}
}

[Theory]
[InlineData(true)]
[InlineData(false)]
public async Task UseAutoFunctionInvocationFilterWithStreamingAgentInvocation(bool useChatClient)
{
// Define the agent
ChatCompletionAgent agent =
new()
{
Instructions = "Answer questions about the menu.",
Kernel = CreateKernelWithFilter(useChatClient),
Arguments = new KernelArguments(new PromptExecutionSettings() { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() }),
};

Expand Down Expand Up @@ -115,6 +162,61 @@ async Task InvokeAgentAsync(string input)
}
}

[Theory]
[InlineData(true)]
[InlineData(false)]
public async Task UseAutoFunctionInvocationFilterWithStreamingAgentChat(bool useChatClient)
{
// Define the agent
ChatCompletionAgent agent =
new()
{
Instructions = "Answer questions about the menu.",
Kernel = CreateKernelWithFilter(useChatClient),
Arguments = new KernelArguments(new PromptExecutionSettings() { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() }),
};

KernelPlugin plugin = KernelPluginFactory.CreateFromType<MenuPlugin>();
agent.Kernel.Plugins.Add(plugin);

// Create a chat for agent interaction.
AgentGroupChat chat = new();

// Respond to user input, invoking functions where appropriate.
await InvokeAgentAsync("Hello");
await InvokeAgentAsync("What is the special soup?");
await InvokeAgentAsync("What is the special drink?");
await InvokeAgentAsync("Thank you");

// Display the entire chat history.
WriteChatHistory(await chat.GetChatMessagesAsync().ToArrayAsync());

// Local function to invoke agent and display the conversation messages.
async Task InvokeAgentAsync(string input)
{
ChatMessageContent message = new(AuthorRole.User, input);
chat.AddChatMessage(message);
this.WriteAgentChatMessage(message);

bool isFirst = false;
await foreach (StreamingChatMessageContent response in chat.InvokeStreamingAsync(agent))
{
if (string.IsNullOrEmpty(response.Content))
{
continue;
}

if (!isFirst)
{
Console.WriteLine($"\n# {response.Role} - {response.AuthorName ?? "*"}:");
isFirst = true;
}

Console.WriteLine($"\t > streamed: '{response.Content}'");
}
}
}

private void WriteChatHistory(IEnumerable<ChatMessageContent> chat)
{
Console.WriteLine("================================");
Expand All @@ -126,11 +228,18 @@ private void WriteChatHistory(IEnumerable<ChatMessageContent> chat)
}
}

private Kernel CreateKernelWithFilter()
private Kernel CreateKernelWithFilter(bool useChatClient)
{
IKernelBuilder builder = Kernel.CreateBuilder();

base.AddChatCompletionToKernel(builder);
if (useChatClient)
{
base.AddChatClientToKernel(builder);
}
else
{
base.AddChatCompletionToKernel(builder);
}

builder.Services.AddSingleton<IAutoFunctionInvocationFilter>(new AutoInvocationFilter());

Expand Down
36 changes: 25 additions & 11 deletions dotnet/samples/Concepts/Agents/ChatCompletion_HistoryReducer.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// Copyright (c) Microsoft. All rights reserved.

using Microsoft.Extensions.AI;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Agents;
using Microsoft.SemanticKernel.ChatCompletion;
Expand All @@ -19,26 +20,34 @@ public class ChatCompletion_HistoryReducer(ITestOutputHelper output) : BaseTest(
/// Demonstrate the use of <see cref="ChatHistoryTruncationReducer"/> when directly
/// invoking a <see cref="ChatCompletionAgent"/>.
/// </summary>
[Fact]
public async Task TruncatedAgentReductionAsync()
[Theory]
[InlineData(true)]
[InlineData(false)]
public async Task TruncatedAgentReduction(bool useChatClient)
{
// Define the agent
ChatCompletionAgent agent = CreateTruncatingAgent(10, 10);
ChatCompletionAgent agent = CreateTruncatingAgent(10, 10, useChatClient, out var chatClient);

await InvokeAgentAsync(agent, 50);

chatClient?.Dispose();
}

/// <summary>
/// Demonstrate the use of <see cref="ChatHistorySummarizationReducer"/> when directly
/// invoking a <see cref="ChatCompletionAgent"/>.
/// </summary>
[Fact]
public async Task SummarizedAgentReductionAsync()
[Theory]
[InlineData(true)]
[InlineData(false)]
public async Task SummarizedAgentReduction(bool useChatClient)
{
// Define the agent
ChatCompletionAgent agent = CreateSummarizingAgent(10, 10);
ChatCompletionAgent agent = CreateSummarizingAgent(10, 10, useChatClient, out var chatClient);

await InvokeAgentAsync(agent, 50);

chatClient?.Dispose();
}

// Proceed with dialog by directly invoking the agent and explicitly managing the history.
Expand Down Expand Up @@ -79,25 +88,30 @@ private async Task InvokeAgentAsync(ChatCompletionAgent agent, int messageCount)
}
}

private ChatCompletionAgent CreateSummarizingAgent(int reducerMessageCount, int reducerThresholdCount)
private ChatCompletionAgent CreateSummarizingAgent(int reducerMessageCount, int reducerThresholdCount, bool useChatClient, out IChatClient? chatClient)
{
Kernel kernel = this.CreateKernelWithChatCompletion();
Kernel kernel = this.CreateKernelWithChatCompletion(useChatClient, out chatClient);

var service = useChatClient
? kernel.GetRequiredService<IChatClient>().AsChatCompletionService()
: kernel.GetRequiredService<IChatCompletionService>();

return
new()
{
Name = TranslatorName,
Instructions = TranslatorInstructions,
Kernel = kernel,
HistoryReducer = new ChatHistorySummarizationReducer(kernel.GetRequiredService<IChatCompletionService>(), reducerMessageCount, reducerThresholdCount),
HistoryReducer = new ChatHistorySummarizationReducer(service, reducerMessageCount, reducerThresholdCount),
};
}

private ChatCompletionAgent CreateTruncatingAgent(int reducerMessageCount, int reducerThresholdCount) =>
private ChatCompletionAgent CreateTruncatingAgent(int reducerMessageCount, int reducerThresholdCount, bool useChatClient, out IChatClient? chatClient) =>
new()
{
Name = TranslatorName,
Instructions = TranslatorInstructions,
Kernel = this.CreateKernelWithChatCompletion(),
Kernel = this.CreateKernelWithChatCompletion(useChatClient, out chatClient),
HistoryReducer = new ChatHistoryTruncationReducer(reducerMessageCount, reducerThresholdCount),
};
}
10 changes: 7 additions & 3 deletions dotnet/samples/Concepts/Agents/ChatCompletion_Serialization.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,18 @@ public class ChatCompletion_Serialization(ITestOutputHelper output) : BaseAgents
private const string HostName = "Host";
private const string HostInstructions = "Answer questions about the menu.";

[Fact]
public async Task SerializeAndRestoreAgentGroupChatAsync()
[Theory]
[InlineData(true)]
[InlineData(false)]
public async Task SerializeAndRestoreAgentGroupChat(bool useChatClient)
{
// Define the agent
ChatCompletionAgent agent =
new()
{
Instructions = HostInstructions,
Name = HostName,
Kernel = this.CreateKernelWithChatCompletion(),
Kernel = this.CreateKernelWithChatCompletion(useChatClient, out var chatClient),
Arguments = new KernelArguments(new PromptExecutionSettings() { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() }),
};

Expand Down Expand Up @@ -51,6 +53,8 @@ public async Task SerializeAndRestoreAgentGroupChatAsync()
this.WriteAgentChatMessage(content);
}

chatClient?.Dispose();

// Local function to invoke agent and display the conversation messages.
async Task InvokeAgentAsync(AgentGroupChat chat, string input)
{
Expand Down
Loading
Loading