Skip to content
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

.Net: Removing KernelAgent.cs and moving its functionality into Agent.cs #11244

Merged
merged 9 commits into from
Apr 2, 2025
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace Agents;

/// <summary>
/// Demonstrate service selection for <see cref="ChatCompletionAgent"/> through setting service-id
/// on <see cref="KernelAgent.Arguments"/> and also providing override <see cref="KernelArguments"/>
/// on <see cref="Agent.Arguments"/> and also providing override <see cref="KernelArguments"/>
/// when calling <see cref="ChatCompletionAgent.InvokeAsync(ChatHistory, KernelArguments?, Kernel?, CancellationToken)"/>
/// </summary>
public class ChatCompletion_ServiceSelection(ITestOutputHelper output) : BaseAgentsTest(output)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public static IChatHistoryProvider GetHistory(this Kernel kernel) =>
/// <summary>
/// Access an agent as a keyed service.
/// </summary>
public static TAgent GetAgent<TAgent>(this Kernel kernel, string key) where TAgent : KernelAgent =>
public static TAgent GetAgent<TAgent>(this Kernel kernel, string key) where TAgent : Agent =>
kernel.Services.GetRequiredKeyedService<TAgent>(key);

/// <summary>
Expand Down
84 changes: 84 additions & 0 deletions dotnet/src/Agents/Abstractions/Agent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
Expand Down Expand Up @@ -44,6 +45,32 @@ public abstract class Agent
/// </summary>
public ILoggerFactory? LoggerFactory { get; init; }

/// <summary>
/// Gets the arguments for the agent instruction parameters (optional).
/// </summary>
/// <remarks>
/// Also includes <see cref="PromptExecutionSettings"/>.
/// </remarks>
public KernelArguments Arguments { get; init; } = [];

/// <summary>
/// Gets the instructions for the agent (optional).
/// </summary>
public string? Instructions { get; init; }

/// <summary>
/// Gets the <see cref="Kernel"/> containing services, plugins, and filters for use throughout the agent lifetime.
/// </summary>
/// <value>
/// The <see cref="Kernel"/> containing services, plugins, and filters for use throughout the agent lifetime. The default value is an empty Kernel, but that can be overridden.
/// </value>
public Kernel Kernel { get; init; } = new();

/// <summary>
/// Gets or sets a prompt template based on the agent instructions.
/// </summary>
protected IPromptTemplate? Template { get; set; }

/// <summary>
/// Invoke the agent with no message assuming that all required instructions are already provided to the agent or on the thread.
/// </summary>
Expand Down Expand Up @@ -222,6 +249,25 @@ public abstract IAsyncEnumerable<AgentResponseItem<StreamingChatMessageContent>>
/// </summary>
protected virtual ILoggerFactory ActiveLoggerFactory => this.LoggerFactory ?? NullLoggerFactory.Instance;

/// <summary>
/// Formats the system instructions for the agent.
/// </summary>
/// <param name="kernel">The <see cref="Kernel"/> containing services, plugins, and other state for use by the agent.</param>
/// <param name="arguments">Optional arguments to pass to the agents's invocation, including any <see cref="PromptExecutionSettings"/>.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
/// <returns>The formatted system instructions for the agent.</returns>
protected async Task<string?> FormatInstructionsAsync(Kernel kernel, KernelArguments? arguments, CancellationToken cancellationToken)
{
if (this.Template is null)
{
// Use the instructions as-is
return this.Instructions;
}

// Use the provided template as the instructions
return await this.Template.RenderAsync(kernel, arguments, cancellationToken).ConfigureAwait(false);
}

/// <summary>
/// Set of keys to establish channel affinity. Minimum expected key-set:
/// <example>
Expand Down Expand Up @@ -336,4 +382,42 @@ protected Task NotifyThreadOfNewMessage(AgentThread thread, ChatMessageContent m
{
return thread.OnNewMessageAsync(message, cancellationToken);
}

/// <summary>
/// Provides a merged instance of <see cref="KernelArguments"/> with precedence for override arguments.
/// </summary>
/// <param name="arguments">The override arguments.</param>
/// <remarks>
/// This merge preserves original <see cref="PromptExecutionSettings"/> and <see cref="KernelArguments"/> parameters.
/// It allows for incremental addition or replacement of specific parameters while also preserving the ability
/// to override the execution settings.
/// </remarks>
protected KernelArguments MergeArguments(KernelArguments? arguments)
{
// Avoid merge when override arguments are not set.
if (arguments == null)
{
return this.Arguments;
}

// Both instances are not null, merge with precedence for override arguments.

// Merge execution settings with precedence for override arguments.
Dictionary<string, PromptExecutionSettings>? settings =
(arguments.ExecutionSettings ?? s_emptySettings)
.Concat(this.Arguments.ExecutionSettings ?? s_emptySettings)
.GroupBy(entry => entry.Key)
.ToDictionary(entry => entry.Key, entry => entry.First().Value);

// Merge parameters with precedence for override arguments.
Dictionary<string, object?>? parameters =
arguments
.Concat(this.Arguments)
.GroupBy(entry => entry.Key)
.ToDictionary(entry => entry.Key, entry => entry.First().Value);

return new KernelArguments(parameters, settings);
}

private static readonly Dictionary<string, PromptExecutionSettings> s_emptySettings = [];
}
100 changes: 0 additions & 100 deletions dotnet/src/Agents/Abstractions/KernelAgent.cs

This file was deleted.

2 changes: 1 addition & 1 deletion dotnet/src/Agents/AzureAI/AzureAIAgent.ClientFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace Microsoft.SemanticKernel.Agents.AzureAI;
/// <summary>
/// Provides an <see cref="AIProjectClient"/> for use by <see cref="AzureAIAgent"/>.
/// </summary>
public sealed partial class AzureAIAgent : KernelAgent
public sealed partial class AzureAIAgent : Agent
{
/// <summary>
/// Produces a <see cref="AIProjectClient"/>.
Expand Down
4 changes: 2 additions & 2 deletions dotnet/src/Agents/AzureAI/AzureAIAgent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@
namespace Microsoft.SemanticKernel.Agents.AzureAI;

/// <summary>
/// Provides a specialized <see cref="KernelAgent"/> based on an Azure AI agent.
/// Provides a specialized <see cref="Agent"/> based on an Azure AI agent.
/// </summary>
public sealed partial class AzureAIAgent : KernelAgent
public sealed partial class AzureAIAgent : Agent
{
/// <summary>
/// Provides tool definitions used when associating a file attachment to an input message:
Expand Down
4 changes: 2 additions & 2 deletions dotnet/src/Agents/Bedrock/BedrockAgent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@
namespace Microsoft.SemanticKernel.Agents.Bedrock;

/// <summary>
/// Provides a specialized <see cref="KernelAgent"/> for the Bedrock Agent service.
/// Provides a specialized <see cref="Agent"/> for the Bedrock Agent service.
/// </summary>
public sealed class BedrockAgent : KernelAgent
public sealed class BedrockAgent : Agent
{
/// <summary>
/// The client used to interact with the Bedrock Agent service.
Expand Down
2 changes: 1 addition & 1 deletion dotnet/src/Agents/Core/AgentGroupChat.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public sealed class AgentGroupChat : AgentChat
/// <summary>
/// Add an <see cref="Agent"/> to the chat.
/// </summary>
/// <param name="agent">The <see cref="KernelAgent"/> to add.</param>
/// <param name="agent">The <see cref="Agent"/> to add.</param>
public void AddAgent(Agent agent)
{
if (this._agentIds.Add(agent.Id))
Expand Down
6 changes: 3 additions & 3 deletions dotnet/src/Agents/Core/ChatCompletionAgent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@
namespace Microsoft.SemanticKernel.Agents;

/// <summary>
/// Represents a <see cref="KernelAgent"/> specialization based on <see cref="IChatCompletionService"/>.
/// Represents a <see cref="Agent"/> specialization based on <see cref="IChatCompletionService"/>.
/// </summary>
/// <remarks>
/// NOTE: Enable <see cref="PromptExecutionSettings.FunctionChoiceBehavior"/> for agent plugins
/// (<see cref="KernelAgent.Arguments"/>).
/// (<see cref="Agent.Arguments"/>).
/// </remarks>
public sealed class ChatCompletionAgent : ChatHistoryKernelAgent
public sealed class ChatCompletionAgent : ChatHistoryAgent
{
/// <summary>
/// Initializes a new instance of the <see cref="ChatCompletionAgent"/> class.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@
namespace Microsoft.SemanticKernel.Agents;

/// <summary>
/// Represents a <see cref="KernelAgent"/> specialization bound to a <see cref="ChatHistoryChannel"/>.
/// Represents a <see cref="Agent"/> specialization bound to a <see cref="ChatHistoryChannel"/>.
/// </summary>
/// <remarks>
/// NOTE: Enable <see cref="PromptExecutionSettings.FunctionChoiceBehavior"/> for agent plugins
/// (<see cref="KernelAgent.Arguments"/>).
/// (<see cref="Agent.Arguments"/>).
/// </remarks>
public abstract class ChatHistoryKernelAgent : KernelAgent
public abstract class ChatHistoryAgent : Agent
{
/// <summary>
/// Gets an optional <see cref="IChatHistoryReducer"/> to reduce the history.
Expand Down
6 changes: 3 additions & 3 deletions dotnet/src/Agents/Core/ChatHistoryChannel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
namespace Microsoft.SemanticKernel.Agents;

/// <summary>
/// Represents an <see cref="AgentChannel"/> specialization that acts upon a <see cref="ChatHistoryKernelAgent"/>.
/// Represents an <see cref="AgentChannel"/> specialization that acts upon a <see cref="ChatHistoryAgent"/>.
/// </summary>
[Experimental("SKEXP0110")]
internal sealed class ChatHistoryChannel : AgentChannel
Expand All @@ -35,7 +35,7 @@ internal sealed class ChatHistoryChannel : AgentChannel
Agent agent,
[EnumeratorCancellation] CancellationToken cancellationToken = default)
{
if (agent is not ChatHistoryKernelAgent historyAgent)
if (agent is not ChatHistoryAgent historyAgent)
{
throw new KernelException($"Invalid channel binding for agent: {agent.Id} ({agent.GetType().FullName})");
}
Expand Down Expand Up @@ -95,7 +95,7 @@ bool IsMessageVisible(ChatMessageContent message) =>
/// <inheritdoc/>
protected override async IAsyncEnumerable<StreamingChatMessageContent> InvokeStreamingAsync(Agent agent, IList<ChatMessageContent> messages, [EnumeratorCancellation] CancellationToken cancellationToken = default)
{
if (agent is not ChatHistoryKernelAgent historyAgent)
if (agent is not ChatHistoryAgent historyAgent)
{
throw new KernelException($"Invalid channel binding for agent: {agent.Id} ({agent.GetType().FullName})");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

namespace Microsoft.SemanticKernel.Agents.OpenAI;

public sealed partial class OpenAIAssistantAgent : KernelAgent
public sealed partial class OpenAIAssistantAgent : Agent
{
/// <summary>
/// Specifies a key that avoids an exception from OpenAI Client when a custom endpoint is provided without an API key.
Expand Down
4 changes: 2 additions & 2 deletions dotnet/src/Agents/OpenAI/OpenAIAssistantAgent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@
namespace Microsoft.SemanticKernel.Agents.OpenAI;

/// <summary>
/// Represents a <see cref="KernelAgent"/> specialization based on Open AI Assistant / GPT.
/// Represents a <see cref="Agent"/> specialization based on Open AI Assistant / GPT.
/// </summary>
public sealed partial class OpenAIAssistantAgent : KernelAgent
public sealed partial class OpenAIAssistantAgent : Agent
{
/// <summary>
/// The metadata key that identifies code-interpreter content.
Expand Down
Loading
Loading