🤖 Microsoft Semantic Kernel

插件化AI编排源码深度解析

Kernel/KernelFunction/KernelPlugin/KernelArguments 四大核心
源码级别解析 · .NET SDK v1.x
2026-03-22 | 每日技术深度解读

什么是 Semantic Kernel?

Semantic Kernel 是微软开发的轻量级 AI 编排框架

核心职责:

  • 统一封装 OpenAI、Azure OpenAI、HuggingFace 等 LLM 服务
  • 插件化架构,支持 Function Calling
  • Prompt Template 管理(Handlebars、Liquid)
  • Vector Store 抽象,支持多种向量数据库
  • Filter 管道,支持 AOP 式拦截

设计理念: Skills (Plugin) = Functions + Prompt Templates

核心架构概览

┌─────────────────────────────────────────────────────────────────┐ │ Semantic Kernel 架构 │ ├─────────────────────────────────────────────────────────────────┤ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ │ Kernel │───▶│KernelPlugin │───▶│KernelFunction│ │ │ │ (编排容器) │ │ (插件集合) │ │ (函数单元) │ │ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │ │ │ │ │ │ ▼ ▼ ▼ │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ │ IAIService │ │PromptTemplate│ │FunctionResult│ │ │ │ (LLM服务) │ │ (模板引擎) │ │ (结果封装) │ │ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │ │ │ │ ▼ │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ │ Filters │ │ Memory │ │ Telemetry │ │ │ │ (拦截器) │ │ (向量存储) │ │ (可观测性) │ │ │ └─────────────┘ └─────────────┘ └─────────────┘ │ └─────────────────────────────────────────────────────────────────┘

四大核心概念

概念 职责 类比
Kernel AI 编排容器,管理服务和插件 IoC Container
KernelFunction 可执行的 AI 函数(Native/Prompt) Delegate/Func<T>
KernelPlugin 函数集合,组织相关 Skills Module/Namespace
KernelArguments 参数容器,携带执行上下文 Dictionary + Settings

Kernel 核心类

namespace Microsoft.SemanticKernel;

public sealed class Kernel : IDisposable
{
    // 核心属性
    public KernelPluginCollection Plugins { get; }
    public IServiceProvider Services { get; }
    public ILoggerFactory LoggerFactory { get; }
    public CultureInfo Culture { get; set; }
    
    // 核心方法
    public static Kernel CreateBuilder() => new KernelBuilder();
    
    public FunctionResult Invoke(
        KernelFunction function,
        KernelArguments? arguments = null);
    
    public Task<FunctionResult> InvokeAsync(
        KernelFunction function,
        KernelArguments? arguments = null,
        CancellationToken cancellationToken = default);
    
    public Task<FunctionResult> InvokePromptAsync(
        string promptTemplate,
        KernelArguments? arguments = null,
        CancellationToken cancellationToken = default);
}

Kernel 构造函数

public sealed class Kernel
{
    private readonly IServiceProvider _serviceProvider;
    private readonly KernelPluginCollection _plugins;
    private readonly List<IFunctionInvocationFilter> _functionFilters;
    
    internal Kernel(
        IServiceProvider? serviceProvider = null,
        IReadOnlyKernelPluginCollection? plugins = null)
    {
        this._serviceProvider = serviceProvider ?? EmptyServiceProvider.Instance;
        this._plugins = new KernelPluginCollection(this, plugins);
        this._functionFilters = new List<IFunctionInvocationFilter>();
        
        // 从服务容器获取 Filters
        var filters = this._serviceProvider
            .GetServices<IFunctionInvocationFilter>();
        this._functionFilters.AddRange(filters);
    }
    
    public void Dispose()
    {
        (this._serviceProvider as IDisposable)?.Dispose();
    }
}

Kernel.Builder 构建模式

// 使用 KernelBuilder 构建
var kernel = Kernel.CreateBuilder()
    .AddAzureOpenAIChatCompletion(
        deploymentName: "gpt-4",
        endpoint: "https://xxx.openai.azure.com/",
        apiKey: "...")
    .AddPlugin(new MathPlugin(), "MathPlugin")
    .Build();

// KernelBuilder 实现
public sealed class KernelBuilder : IKernelBuilder
{
    private readonly IServiceCollection _services = new ServiceCollection();
    private readonly List<KernelPlugin> _plugins = new();
    
    public IKernelBuilder AddPlugin(KernelPlugin plugin)
    {
        this._plugins.Add(plugin);
        return this;
    }
    
    public Kernel Build()
    {
        var serviceProvider = this._services.BuildServiceProvider();
        return new Kernel(serviceProvider, this._plugins);
    }
}

KernelPluginCollection 插件集合

public sealed class KernelPluginCollection 
    : ICollection<KernelPlugin>, IReadOnlyKernelPluginCollection
{
    private readonly Kernel _kernel;
    private readonly Dictionary<string, KernelPlugin> _plugins;
    
    public void Add(KernelPlugin plugin)
    {
        Verify.NotNull(plugin);
        VerifyPluginsNotReadOnly();
        
        // 克隆所有函数,绑定到当前 Kernel
        var clonedPlugin = plugin.CloneForKernel(this._kernel);
        this._plugins[clonedPlugin.Name] = clonedPlugin;
    }
    
    public KernelPlugin this[string name] => this._plugins[name];
    
    public bool TryGetPlugin(string name, [NotNullWhen(true)] out KernelPlugin? plugin)
        => this._plugins.TryGetValue(name, out plugin);
    
    public KernelFunction GetFunction(string pluginName, string functionName)
    {
        var plugin = this[pluginName];
        return plugin[functionName];
    }
}

Kernel.InvokeAsync 核心实现

public async Task<FunctionResult> InvokeAsync(
    KernelFunction function,
    KernelArguments? arguments = null,
    CancellationToken cancellationToken = default)
{
    Verify.NotNull(function);
    
    arguments ??= new KernelArguments();
    
    // 创建 FunctionInvocationContext
    var context = new FunctionInvocationContext(
        this, function, arguments, new FunctionResult(function, this.Culture));
    
    // 执行 Filter 管道
    await this.OnFunctionInvocationAsync(
        function, arguments, context.Result, 
        isStreaming: false,
        async ctx => {
            // 核心执行逻辑
            ctx.Result = await function.InvokeAsync(
                this, ctx.Arguments, cancellationToken);
        },
        cancellationToken);
    
    return context.Result;
}

Kernel.InvokePromptAsync 直接调用 Prompt

public Task<FunctionResult> InvokePromptAsync(
    string promptTemplate,
    KernelArguments? arguments = null,
    CancellationToken cancellationToken = default)
{
    Verify.NotNull(promptTemplate);
    
    // 从 Prompt 模板创建 KernelFunction
    var function = KernelFunctionFactory.CreateFromPrompt(
        promptTemplate,
        promptTemplateFactory: this.PromptTemplateFactory);
    
    // 调用函数
    return this.InvokeAsync(function, arguments, cancellationToken);
}

// 使用示例
var result = await kernel.InvokePromptAsync(
    "Translate this to {{$language}}: {{$text}}",
    new() { ["language"] = "French", ["text"] = "Hello" });
    
Console.WriteLine(result); // "Bonjour"

KernelFunction 抽象类

public abstract class KernelFunction : FullyQualifiedAIFunction
{
    // 核心属性
    public virtual string Name => this.Metadata.Name;
    public virtual string? PluginName => this.Metadata.PluginName;
    public override string Description => this.Metadata.Description;
    public KernelFunctionMetadata Metadata { get; }
    public IReadOnlyDictionary<string, PromptExecutionSettings>? ExecutionSettings { get; }
    
    // 核心方法
    public Task<FunctionResult> InvokeAsync(
        Kernel kernel,
        KernelArguments? arguments = null,
        CancellationToken cancellationToken = default);
    
    public IAsyncEnumerable<StreamingKernelContent> InvokeStreamingAsync(
        Kernel kernel,
        KernelArguments? arguments = null,
        CancellationToken cancellationToken = default);
    
    // 抽象方法
    protected abstract ValueTask<FunctionResult> InvokeCoreAsync(
        Kernel kernel, KernelArguments arguments, CancellationToken cancellationToken);
    
    public abstract KernelFunction Clone(string? pluginName = null);
}

KernelFunction 核心属性详解

protected KernelFunction(
    string name, 
    string? pluginName,
    string description, 
    IReadOnlyList<KernelParameterMetadata> parameters,
    KernelReturnParameterMetadata? returnParameter = null,
    Dictionary<string, PromptExecutionSettings>? executionSettings = null)
    : base(new KernelFunctionMetadata(name)
    {
        PluginName = pluginName,
        Description = description,
        Parameters = KernelVerify.ParametersUniqueness(parameters),
        ReturnParameter = returnParameter ?? KernelReturnParameterMetadata.Empty,
    })
{
    // 构建 JSON Schema(用于 Function Calling)
    this.BuildFunctionSchema();
    
    // 冻结 ExecutionSettings
    if (executionSettings is not null)
    {
        this.ExecutionSettings = executionSettings.ToDictionary(
            entry => entry.Key,
            entry => { var clone = entry.Value.Clone(); clone.Freeze(); return clone; });
    }
}

KernelFunction.InvokeAsync 实现

public async Task<FunctionResult> InvokeAsync(
    Kernel kernel,
    KernelArguments? arguments = null,
    CancellationToken cancellationToken = default)
{
    kernel ??= this.Kernel;
    Verify.NotNull(kernel);
    arguments ??= [];
    
    using var activity = this.StartFunctionActivity(...);
    var logger = kernel.LoggerFactory.CreateLogger<KernelFunction>();
    
    // 调用 Kernel 的 Filter 管道
    var invocationContext = await kernel.OnFunctionInvocationAsync(
        this, arguments, new FunctionResult(this, kernel.Culture),
        isStreaming: false,
        async context => {
            // 核心:调用子类实现
            context.Result = await this.InvokeCoreAsync(
                kernel, context.Arguments, cancellationToken);
        },
        cancellationToken);
    
    return invocationContext.Result;
}

KernelFunction.InvokeStreamingAsync 流式调用

public async IAsyncEnumerable<TResult> InvokeStreamingAsync<TResult>(
    Kernel kernel,
    KernelArguments? arguments = null,
    [EnumeratorCancellation] CancellationToken cancellationToken = default)
{
    kernel ??= this.Kernel;
    Verify.NotNull(kernel);
    arguments ??= [];
    
    var invocationContext = await kernel.OnFunctionInvocationAsync(
        this, arguments, new FunctionResult(this, kernel.Culture),
        isStreaming: true,
        context => {
            // 获取流式枚举器
            var enumerable = this.InvokeStreamingCoreAsync<TResult>(
                kernel, context.Arguments, cancellationToken);
            context.Result = new FunctionResult(this, enumerable, kernel.Culture);
            return Task.CompletedTask;
        },
        cancellationToken);
    
    // 流式返回结果
    var enumerator = invocationContext.Result
        .GetValue<IAsyncEnumerable<TResult>>()!
        .GetAsyncEnumerator(cancellationToken);
    
    await using (enumerator.ConfigureAwait(false))
    {
        while (await enumerator.MoveNextAsync().ConfigureAwait(false))
        {
            yield return enumerator.Current;
        }
    }
}

KernelFunctionMetadata 元数据

public sealed class KernelFunctionMetadata : AIFunctionMetadata
{
    public string Name { get; init; }
    public string? PluginName { get; init; }
    public string Description { get; init; }
    public IReadOnlyList<KernelParameterMetadata> Parameters { get; init; }
    public KernelReturnParameterMetadata ReturnParameter { get; init; }
    public ReadOnlyDictionary<string, object?> AdditionalProperties { get; init; }
    
    // 用于 Function Calling 的完整名称
    public string FullyQualifiedName => 
        string.IsNullOrWhiteSpace(this.PluginName) 
            ? this.Name 
            : $"{this.PluginName}.{this.Name}";
    
    // 创建 JSON Schema
    public override JsonElement JsonSchema => this._jsonSchema;
}

KernelPlugin 抽象类

[DebuggerDisplay("Name = {Name}, Functions = {FunctionCount}")]
public abstract class KernelPlugin : IEnumerable<KernelFunction>
{
    public string Name { get; }
    public string Description { get; }
    public abstract int FunctionCount { get; }
    
    protected KernelPlugin(string name, string? description = null)
    {
        KernelVerify.ValidPluginName(name);
        this.Name = name;
        this.Description = !string.IsNullOrWhiteSpace(description) 
            ? description! : "";
    }
    
    // 索引器:通过名称获取函数
    public KernelFunction this[string functionName] =>
        this.TryGetFunction(functionName, out var function) 
            ? function 
            : throw new KeyNotFoundException($"Function not found: {functionName}");
    
    // 抽象方法
    public abstract bool TryGetFunction(
        string name, [NotNullWhen(true)] out KernelFunction? function);
    public abstract IEnumerator<KernelFunction> GetEnumerator();
}

KernelPluginCollection 实现

public sealed class KernelPluginCollection : ICollection<KernelPlugin>
{
    private readonly Kernel _kernel;
    private readonly Dictionary<string, KernelPlugin> _plugins = new();
    
    public int Count => this._plugins.Count;
    public bool IsReadOnly { get; private set; }
    
    public void Add(KernelPlugin plugin)
    {
        Verify.NotNull(plugin);
        if (this._plugins.ContainsKey(plugin.Name))
            throw new ArgumentException($"Plugin already exists: {plugin.Name}");
        
        // 克隆插件,绑定到当前 Kernel
        var cloned = plugin.CloneForKernel(this._kernel);
        this._plugins[cloned.Name] = cloned;
    }
    
    public void Add(string pluginName, IEnumerable<KernelFunction> functions)
    {
        var plugin = KernelPluginFactory.CreateFromFunctions(pluginName, functions);
        this.Add(plugin);
    }
    
    public bool Contains(string pluginName) => this._plugins.ContainsKey(pluginName);
}

DefaultKernelPlugin 默认实现

internal sealed class DefaultKernelPlugin : KernelPlugin
{
    private readonly Dictionary<string, KernelFunction> _functions;
    
    public override int FunctionCount => this._functions.Count;
    
    internal DefaultKernelPlugin(
        string name, 
        string? description, 
        IEnumerable<KernelFunction> functions)
        : base(name, description)
    {
        this._functions = new Dictionary<string, KernelFunction>(
            StringComparer.OrdinalIgnoreCase);
        
        foreach (var function in functions)
        {
            var cloned = function.Clone(this.Name);
            this._functions[cloned.Name] = cloned;
        }
    }
    
    public override bool TryGetFunction(
        string name, [NotNullWhen(true)] out KernelFunction? function)
        => this._functions.TryGetValue(name, out function);
    
    public override IEnumerator<KernelFunction> GetEnumerator()
        => this._functions.Values.GetEnumerator();
}

KernelArguments 参数容器

public sealed class KernelArguments : AIFunctionArguments
{
    private IReadOnlyDictionary<string, PromptExecutionSettings>? _executionSettings;
    
    // 继承自 Dictionary<string, object?>
    public ICollection<string> Names => this.Keys;
    
    public IReadOnlyDictionary<string, PromptExecutionSettings>? ExecutionSettings
    {
        get => this._executionSettings;
        set
        {
            // 验证 ServiceId 与 Key 匹配
            if (value is { Count: > 0 })
            {
                foreach (var kv in value!)
                {
                    if (!string.IsNullOrWhiteSpace(kv.Value.ServiceId) 
                        && kv.Key != kv.Value.ServiceId)
                    {
                        throw new ArgumentException(
                            $"Service id '{kv.Value.ServiceId}' must match key '{kv.Key}'");
                    }
                }
            }
            this._executionSettings = value;
        }
    }
    
    public bool ContainsName(string name)
    {
        Verify.NotNull(name);
        return base.ContainsKey(name);
    }
}

KernelArguments 使用示例

// 创建参数容器
var arguments = new KernelArguments
{
    ["topic"] = "AI",
    ["language"] = "Chinese"
};

// 添加 ExecutionSettings
arguments.ExecutionSettings = new Dictionary<string, PromptExecutionSettings>
{
    ["default"] = new OpenAIPromptExecutionSettings
    {
        MaxTokens = 1000,
        Temperature = 0.7
    }
};

// 在函数中使用
var result = await kernel.InvokeAsync(function, arguments);

// 获取结果
var text = result.GetValue<string>();

// 获取特定类型的设置
var settings = arguments.ExecutionSettings?
    .GetSettings<OpenAIPromptExecutionSettings>();

FunctionResult 结果封装

public sealed class FunctionResult
{
    public KernelFunction Function { get; }
    public object? Value { get; internal set; }
    public CultureInfo Culture { get; }
    
    internal FunctionResult(
        KernelFunction function, 
        object? value = null, 
        CultureInfo? culture = null)
    {
        this.Function = function;
        this.Value = value;
        this.Culture = culture ?? CultureInfo.InvariantCulture;
    }
    
    // 获取类型化值
    public T? GetValue<T>()
    {
        if (this.Value is T typedValue) return typedValue;
        if (this.Value is null) return default;
        
        // 尝试转换
        var converter = TypeDescriptor.GetConverter(typeof(T));
        if (converter.CanConvertFrom(this.Value.GetType()))
            return (T?)converter.ConvertFrom(this.Value);
        
        throw new InvalidCastException(
            $"Cannot cast {this.Value.GetType()} to {typeof(T)}");
    }
    
    public override string ToString() => this.Value?.ToString() ?? string.Empty;
}

IPromptTemplate 接口

namespace Microsoft.SemanticKernel;

public interface IPromptTemplate
{
    /// <summary>
    /// 渲染 Prompt 模板
    /// </summary>
    Task<string> RenderAsync(
        Kernel kernel, 
        KernelArguments? arguments = null, 
        CancellationToken cancellationToken = default);
}

// PromptTemplateConfig 配置
public sealed class PromptTemplateConfig
{
    public string Template { get; set; } = string.Empty;
    public string TemplateFormat { get; set; } = "semantic-kernel";
    public string? Name { get; set; }
    public string? Description { get; set; }
    public List<InputVariable> InputVariables { get; set; } = new();
    public List<PromptExecutionSettings> ExecutionSettings { get; set; } = new();
}

PromptTemplateConfig 配置详解

// 使用 JSON 配置
var config = new PromptTemplateConfig
{
    Name = "Summarize",
    Description = "Summarize the input text",
    Template = """
        Summarize the following text in {{$language}}:
        
        {{$input}}
        
        Summary:
        """,
    InputVariables = new()
    {
        new() { Name = "input", Description = "Text to summarize", IsRequired = true },
        new() { Name = "language", Description = "Output language", Default = "English" }
    },
    ExecutionSettings = new()
    {
        new OpenAIPromptExecutionSettings
        {
            MaxTokens = 500,
            Temperature = 0.3
        }
    }
};

// 从配置创建函数
var function = KernelFunctionFactory.CreateFromPrompt(config);

KernelFunctionFromMethod 原生方法封装

public static class KernelFunctionFactory
{
    public static KernelFunction CreateFromMethod(
        Delegate method,
        string? functionName = null,
        string? description = null,
        IEnumerable<KernelParameterMetadata>? parameters = null,
        KernelReturnParameterMetadata? returnParameter = null)
    {
        return new KernelFunctionFromMethod(
            method, functionName, description, parameters, returnParameter);
    }
}

// 使用示例
[KernelFunction("add")]
[Description("Add two numbers")]
public int Add(
    [Description("First number")] int a,
    [Description("Second number")] int b)
{
    return a + b;
}

var function = KernelFunctionFactory.CreateFromMethod(
    (int a, int b) => a + b,
    functionName: "add",
    description: "Add two numbers");

KernelFunctionFromPrompt Prompt 函数

internal sealed class KernelFunctionFromPrompt : KernelFunction
{
    private readonly IPromptTemplate _promptTemplate;
    private readonly ITextGenerationService? _textGenerationService;
    
    protected override async ValueTask<FunctionResult> InvokeCoreAsync(
        Kernel kernel, 
        KernelArguments arguments, 
        CancellationToken cancellationToken)
    {
        // 1. 渲染 Prompt
        var renderedPrompt = await this._promptTemplate
            .RenderAsync(kernel, arguments, cancellationToken);
        
        // 2. 获取 AI 服务
        var service = this._textGenerationService 
            ?? kernel.GetRequiredService<ITextGenerationService>();
        
        // 3. 获取执行设置
        var settings = arguments.ExecutionSettings?
            .GetSettings<PromptExecutionSettings>() 
            ?? new PromptExecutionSettings();
        
        // 4. 调用 AI
        var response = await service.GetTextContentsAsync(
            renderedPrompt, settings, cancellationToken);
        
        // 5. 返回结果
        return new FunctionResult(this, response.FirstOrDefault()?.Text, kernel.Culture);
    }
}

KernelFunctionAttribute 特性

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public sealed class KernelFunctionAttribute : Attribute
{
    public string? Name { get; }
    public string? Description { get; set; }
    
    public KernelFunctionAttribute(string? name = null)
    {
        this.Name = name;
    }
}

// 使用示例
public class WeatherPlugin
{
    [KernelFunction("get_weather")]
    [Description("Get weather information for a city")]
    public async Task<string> GetWeatherAsync(
        [Description("City name")] string city,
        [Description("Temperature unit (celsius/fahrenheit)")] string unit = "celsius")
    {
        // Implementation
        return $"Weather in {city}: 25°{unit[0].ToString().ToUpper()}";
    }
}

// 导入插件
var plugin = kernel.ImportPluginFromType<WeatherPlugin>("Weather");

KernelParameterMetadata 参数元数据

public sealed class KernelParameterMetadata
{
    public string Name { get; init; }
    public string? Description { get; init; }
    public Type? ParameterType { get; init; }
    public bool IsRequired { get; init; }
    public object? DefaultValue { get; init; }
    public KernelJsonSchema? Schema { get; init; }
    
    // 从 ParameterInfo 创建
    public static KernelParameterMetadata FromParameterInfo(
        ParameterInfo parameter, 
        JsonSerializerOptions? jsonSerializerOptions = null)
    {
        var descriptionAttr = parameter.GetCustomAttribute<DescriptionAttribute>();
        
        return new KernelParameterMetadata(parameter.Name!)
        {
            Description = descriptionAttr?.Description,
            ParameterType = parameter.ParameterType,
            IsRequired = !parameter.HasDefaultValue,
            DefaultValue = parameter.DefaultValue,
            Schema = KernelJsonSchema.Create(parameter.ParameterType, jsonSerializerOptions)
        };
    }
}

KernelReturnParameterMetadata 返回值元数据

public sealed class KernelReturnParameterMetadata
{
    public string? Description { get; init; }
    public Type? ParameterType { get; init; }
    public KernelJsonSchema? Schema { get; init; }
    
    public static KernelReturnParameterMetadata Empty { get; } = new();
    
    // 从 MethodInfo 创建
    public static KernelReturnParameterMetadata FromMethodInfo(
        MethodInfo method, 
        JsonSerializerOptions? jsonSerializerOptions = null)
    {
        var returnAttr = method.ReturnParameter
            .GetCustomAttribute<DescriptionAttribute>();
        
        return new KernelReturnParameterMetadata
        {
            Description = returnAttr?.Description,
            ParameterType = method.ReturnType,
            Schema = KernelJsonSchema.Create(method.ReturnType, jsonSerializerOptions)
        };
    }
}

// 使用示例
[KernelFunction]
[return: Description("The sum of the two numbers")]
public int Add(int a, int b) => a + b;

PromptExecutionSettings 执行设置

public class PromptExecutionSettings
{
    public const string DefaultServiceId = "default";
    
    public string? ServiceId { get; set; }
    public int? MaxTokens { get; set; }
    public double? Temperature { get; set; }
    public double? TopP { get; set; }
    public double? FrequencyPenalty { get; set; }
    public double? PresencePenalty { get; set; }
    public IList<string>? StopSequences { get; set; }
    
    public bool IsFrozen { get; private set; }
    
    public void Freeze() => this.IsFrozen = true;
    
    public virtual PromptExecutionSettings Clone()
    {
        return new PromptExecutionSettings
        {
            ServiceId = this.ServiceId,
            MaxTokens = this.MaxTokens,
            Temperature = this.Temperature,
            TopP = this.TopP,
            // ...
        };
    }
}

// OpenAI 特定设置
public class OpenAIPromptExecutionSettings : PromptExecutionSettings
{
    public string? ChatSystemPrompt { get; set; }
    public bool? Logprobs { get; set; }
    public ToolCallBehavior? ToolCallBehavior { get; set; }
}

AIFunction 集成(Microsoft.Extensions.AI)

public abstract class KernelFunction : FullyQualifiedAIFunction
{
    // 继承自 AIFunction
    public override JsonElement JsonSchema => this._jsonSchema;
    public override MethodInfo? UnderlyingMethod => this._underlyingMethod;
    
    // 转换为 AIFunction
    [Experimental("SKEXP0001")]
    [Obsolete("Use Clone(Kernel) instead")]
    public AIFunction AsAIFunction(Kernel? kernel = null)
    {
        return new KernelAIFunction(this, kernel);
    }
    
    // 内部包装类
    private sealed class KernelAIFunction : AIFunction
    {
        private readonly KernelFunction _kernelFunction;
        private readonly Kernel? _kernel;
        
        protected override async ValueTask<object?> InvokeCoreAsync(
            AIFunctionArguments? arguments, CancellationToken cancellationToken)
        {
            var kernelArgs = new KernelArguments(arguments ?? new());
            var result = await this._kernelFunction
                .InvokeAsync(this._kernel ?? new(), kernelArgs, cancellationToken);
            return result.Value;
        }
    }
}

FunctionInvocationContext 上下文

public sealed class FunctionInvocationContext
{
    public Kernel Kernel { get; }
    public KernelFunction Function { get; }
    public KernelArguments Arguments { get; set; }
    public FunctionResult Result { get; set; }
    public bool IsStreaming { get; }
    public CancellationToken CancellationToken { get; }
    
    internal FunctionInvocationContext(
        Kernel kernel,
        KernelFunction function,
        KernelArguments arguments,
        FunctionResult result,
        bool isStreaming = false,
        CancellationToken cancellationToken = default)
    {
        this.Kernel = kernel;
        this.Function = function;
        this.Arguments = arguments;
        this.Result = result;
        this.IsStreaming = isStreaming;
        this.CancellationToken = cancellationToken;
    }
}

IFunctionInvocationFilter 接口

public interface IFunctionInvocationFilter
{
    Task OnFunctionInvocationAsync(
        FunctionInvocationContext context, 
        Func<FunctionInvocationContext, Task> next);
}

// 实现示例:日志 Filter
public class LoggingFilter : IFunctionInvocationFilter
{
    private readonly ILogger _logger;
    
    public LoggingFilter(ILogger<LoggingFilter> logger)
    {
        this._logger = logger;
    }
    
    public async Task OnFunctionInvocationAsync(
        FunctionInvocationContext context, 
        Func<FunctionInvocationContext, Task> next)
    {
        this._logger.LogInformation(
            "Invoking {Plugin}.{Function}", 
            context.Function.PluginName, context.Function.Name);
        
        await next(context);
        
        this._logger.LogInformation(
            "Result: {Result}", context.Result.ToString());
    }
}

Filter 执行管道

┌─────────────────────────────────────────────────────────────────┐ │ Filter 管道执行流程 │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ Kernel.InvokeAsync(function, arguments) │ │ │ │ │ ▼ │ │ ┌──────────────────────┐ │ │ │ Filter 1 (Logging) │ │ │ │ Pre-Processing │ │ │ └──────────┬───────────┘ │ │ │ next() │ │ ▼ │ │ ┌──────────────────────┐ │ │ │ Filter 2 (Telemetry) │ │ │ │ Pre-Processing │ │ │ └──────────┬───────────┘ │ │ │ next() │ │ ▼ │ │ ┌──────────────────────┐ │ │ │ function.InvokeCoreAsync() │ ◀── 实际执行 │ │ └──────────┬───────────┘ │ │ │ │ │ ▼ │ │ Filter 2 Post-Processing │ │ │ │ │ ▼ │ │ Filter 1 Post-Processing │ │ │ │ │ ▼ │ │ Return Result │ │ │ └─────────────────────────────────────────────────────────────────┘

Kernel.OnFunctionInvocationAsync 实现

internal async Task<FunctionInvocationContext> OnFunctionInvocationAsync(
    KernelFunction function,
    KernelArguments arguments,
    FunctionResult result,
    bool isStreaming,
    Func<FunctionInvocationContext, Task> invokeCore,
    CancellationToken cancellationToken)
{
    var context = new FunctionInvocationContext(
        this, function, arguments, result, isStreaming, cancellationToken);
    
    // 构建 Filter 委托链
    Func<FunctionInvocationContext, Task> pipeline = invokeCore;
    
    foreach (var filter in this._functionFilters.AsEnumerable().Reverse())
    {
        var next = pipeline;
        pipeline = ctx => filter.OnFunctionInvocationAsync(ctx, next);
    }
    
    // 执行管道
    await pipeline(context);
    
    return context;
}

Handlebars PromptTemplate

// 安装 NuGet: Microsoft.SemanticKernel.PromptTemplate.Handlebars

var builder = Kernel.CreateBuilder()
    .AddOpenAIChatCompletion("gpt-4", "api-key");

builder.Services.AddSingleton<IPromptTemplateFactory, HandlebarsPromptTemplateFactory>();

var kernel = builder.Build();

// Handlebars 模板
var template = """
    {{#each messages}}
    {{role}}: {{content}}
    {{/each}}
    
    Assistant:
    """;

var function = KernelFunctionFactory.CreateFromPrompt(
    template, 
    templateFormat: "handlebars");

var result = await kernel.InvokeAsync(function, new()
{
    ["messages"] = new[]
    {
        new { role = "User", content = "Hello" },
        new { role = "Assistant", content = "Hi there!" }
    }
});

Liquid PromptTemplate

// 安装 NuGet: Microsoft.SemanticKernel.PromptTemplate.Liquid

var builder = Kernel.CreateBuilder()
    .AddOpenAIChatCompletion("gpt-4", "api-key");

builder.Services.AddSingleton<IPromptTemplateFactory, LiquidPromptTemplateFactory>();

var kernel = builder.Build();

// Liquid 模板
var template = """
    {% for item in items %}
    - {{ item.name }}: {{ item.value }}
    {% endfor %}
    
    Total: {{ items | size }} items
    """;

var function = KernelFunctionFactory.CreateFromPrompt(
    template, 
    templateFormat: "liquid");

var result = await kernel.InvokeAsync(function, new()
{
    ["items"] = new[]
    {
        new { name = "Apple", value = 10 },
        new { name = "Banana", value = 20 }
    }
});

Semantic Kernel Memory 向量存储

Memory 是 Semantic Kernel 的向量存储抽象层

public interface IVectorStore
{
    IVectorStoreRecordCollection<TKey, TRecord> GetCollection<
        TKey, TRecord>(string name, VectorStoreRecordDefinition? definition = null)
        where TKey : notnull;
    
    Task<bool> CollectionExistsAsync(string name, CancellationToken cancellationToken = default);
    Task CreateCollectionAsync(string name, CancellationToken cancellationToken = default);
    Task DeleteCollectionAsync(string name, CancellationToken cancellationToken = default);
}

// 支持的存储后端
// - Azure AI Search
// - Qdrant
// - Pinecone
// - Chroma
// - Redis
// - In-Memory (开发用)

Text Embedding 生成

public interface ITextEmbeddingGenerationService : IAIService
{
    Task<IReadOnlyList<ReadOnlyMemory<float>>> GenerateEmbeddingsAsync(
        IEnumerable<string> data,
        Kernel? kernel = null,
        CancellationToken cancellationToken = default);
}

// 使用示例
var embeddingService = kernel.GetRequiredService<ITextEmbeddingGenerationService>();

var embeddings = await embeddingService.GenerateEmbeddingsAsync(
    new[] { "Hello world", "Semantic Kernel is great" });

Console.WriteLine($"Embedding dimension: {embeddings[0].Length}");
// 输出: Embedding dimension: 1536 (for text-embedding-ada-002)

// 保存到向量存储
var collection = vectorStore.GetCollection<string, DataModel>("documents");
await collection.UpsertAsync(new DataModel
{
    Id = "doc1",
    Text = "Hello world",
    Vector = embeddings[0]
});

VectorStoreRecordCollection 抽象

public interface IVectorStoreRecordCollection<TKey, TRecord>
    where TKey : notnull
{
    string CollectionName { get; }
    
    Task<TRecord?> GetAsync(TKey key, GetRecordOptions? options = null, CancellationToken cancellationToken = default);
    Task<IReadOnlyList<TRecord?>> GetBatchAsync(IEnumerable<TKey> keys, GetRecordOptions? options = null, CancellationToken cancellationToken = default);
    
    Task UpsertAsync(TRecord record, CancellationToken cancellationToken = default);
    Task UpsertBatchAsync(IEnumerable<TRecord> records, CancellationToken cancellationToken = default);
    
    Task DeleteAsync(TKey key, CancellationToken cancellationToken = default);
    
    Task<VectorSearchResults<TRecord>> VectorizedSearchAsync(
        ReadOnlyMemory<float> vector, 
        VectorSearchOptions? options = null, 
        CancellationToken cancellationToken = default);
}

// 使用示例
var searchResults = await collection.VectorizedSearchAsync(
    queryEmbedding,
    new VectorSearchOptions { Top = 5 });

await foreach (var result in searchResults.Results)
{
    Console.WriteLine($"Score: {result.Score}, Text: {result.Record.Text}");
}

AI Service Provider 模式

// 注册多个 AI 服务
var kernel = Kernel.CreateBuilder()
    .AddOpenAIChatCompletion("gpt-4", "openai-key", serviceId: "openai")
    .AddAzureOpenAIChatCompletion("gpt-4", "endpoint", "azure-key", serviceId: "azure")
    .Build();

// 获取特定服务
var openAIService = kernel.GetRequiredService<IChatCompletionService>("openai");
var azureService = kernel.GetRequiredService<IChatCompletionService>("azure");

// 通过 ExecutionSettings 选择服务
var arguments = new KernelArguments
{
    ExecutionSettings = new Dictionary<string, PromptExecutionSettings>
    {
        ["azure"] = new OpenAIPromptExecutionSettings { MaxTokens = 1000 }
    }
};

// 执行时使用指定服务
var result = await kernel.InvokeAsync(function, arguments);

IChatCompletionService 接口

public interface IChatCompletionService : IAIService
{
    IReadOnlyDictionary<string, object?> Attributes { get; }
    
    Task<IReadOnlyList<ChatMessageContent>> GetChatMessageContentsAsync(
        ChatHistory chatHistory,
        PromptExecutionSettings? executionSettings = null,
        Kernel? kernel = null,
        CancellationToken cancellationToken = default);
    
    IAsyncEnumerable<StreamingChatMessageContent> GetStreamingChatMessageContentsAsync(
        ChatHistory chatHistory,
        PromptExecutionSettings? executionSettings = null,
        Kernel? kernel = null,
        CancellationToken cancellationToken = default);
}

// 使用示例
var chatService = kernel.GetRequiredService<IChatCompletionService>();

var history = new ChatHistory();
history.AddUserMessage("Hello!");

var response = await chatService.GetChatMessageContentsAsync(history);
Console.WriteLine(response[0].Content);

ITextGenerationService 接口

public interface ITextGenerationService : IAIService
{
    IReadOnlyDictionary<string, object?> Attributes { get; }
    
    Task<IReadOnlyList<TextContent>> GetTextContentsAsync(
        string prompt,
        PromptExecutionSettings? executionSettings = null,
        Kernel? kernel = null,
        CancellationToken cancellationToken = default);
    
    IAsyncEnumerable<StreamingTextContent> GetStreamingTextContentsAsync(
        string prompt,
        PromptExecutionSettings? executionSettings = null,
        Kernel? kernel = null,
        CancellationToken cancellationToken = default);
}

// 使用示例
var textService = kernel.GetRequiredService<ITextGenerationService>();

var results = await textService.GetTextContentsAsync(
    "Translate to French: Hello",
    new OpenAIPromptExecutionSettings { MaxTokens = 50 });

Console.WriteLine(results[0].Text); // "Bonjour"

Streaming Content 流式输出

// 流式调用 Chat
var chatService = kernel.GetRequiredService<IChatCompletionService>();

var history = new ChatHistory();
history.AddUserMessage("Tell me a story");

await foreach (var content in chatService.GetStreamingChatMessageContentsAsync(history))
{
    Console.Write(content.Content);
}

// 流式调用 KernelFunction
await foreach (var chunk in kernel.InvokeStreamingAsync<StreamingKernelContent>(function))
{
    Console.Write(chunk);
}

// 带更新的流式调用
var fullContent = new StringBuilder();
await foreach (var update in function.InvokeStreamingAsync<StreamingKernelContent>(kernel))
{
    fullContent.Append(update);
    Console.WriteLine($"Progress: {fullContent.Length} chars");
}

Auto Function Calling 自动调用

// 注册插件
kernel.ImportPluginFromType<WeatherPlugin>("Weather");
kernel.ImportPluginFromType<CalendarPlugin>("Calendar");

// 启用 Auto Function Calling
var settings = new OpenAIPromptExecutionSettings
{
    MaxTokens = 1000,
    ToolCallBehavior = ToolCallBehavior.AutoInvokeKernelFunctions
};

// 自动调用插件函数
var result = await kernel.InvokePromptAsync(
    "What's the weather in Beijing and my next meeting?",
    new KernelArguments(settings));

// 内部流程:
// 1. LLM 返回 tool_calls: ["Weather.get_weather", "Calendar.get_next_meeting"]
// 2. SK 自动调用对应插件
// 3. 将结果发回 LLM
// 4. LLM 生成最终回答

Plugin 导入流程

// 方式1: 从类型导入
kernel.ImportPluginFromType<MyPlugin>("MyPlugin");

// 方式2: 从对象导入
kernel.ImportPluginFromObject(new MyPlugin(), "MyPlugin");

// 方式3: 从方法创建
kernel.ImportPluginFromFunctions("Math", new[]
{
    KernelFunctionFactory.CreateFromMethod((int a, int b) => a + b, "Add"),
    KernelFunctionFactory.CreateFromMethod((int a, int b) => a * b, "Multiply")
});

// 方式4: 从 Prompt 文件导入(YAML)
kernel.ImportPluginFromPromptDirectory("./Plugins/MyPlugin");

// 方式5: 从 OpenAPI 导入
kernel.ImportPluginFromOpenApiAsync("PetStore", "https://petstore.swagger.io/v2/swagger.json");

// 使用导入的插件
var result = await kernel.InvokeAsync(
    kernel.Plugins["MyPlugin"]["MyFunction"],
    new() { ["input"] = "test" });

实战示例:RAG 应用

var kernel = Kernel.CreateBuilder()
    .AddAzureOpenAITextEmbeddingGeneration("text-embedding-ada-002", endpoint, key)
    .AddAzureOpenAIChatCompletion("gpt-4", endpoint, key)
    .Build();

// 导入文档插件
var vectorStore = new InMemoryVectorStore();
var collection = vectorStore.GetCollection<string, Document>("docs");
await collection.CreateCollectionIfNotExistsAsync();

// 创建 RAG 函数
var ragFunction = kernel.CreateFunctionFromPrompt("""
    Use the following context to answer the question.
    
    Context:
    {{#each documents}}
    - {{this}}
    {{/each}}
    
    Question: {{$question}}
    
    Answer:
    """, templateFormat: "handlebars");

// 执行 RAG
var question = "What is Semantic Kernel?";
var embedding = await kernel.InvokeAsync<ReadOnlyMemory<float>>(
    embeddingFunction, new() { ["input"] = question });
var searchResults = await collection.VectorizedSearchAsync(embedding, new() { Top = 5 });

var answer = await kernel.InvokeAsync(ragFunction, new()
{
    ["question"] = question,
    ["documents"] = searchResults.Results.Select(r => r.Record.Content).ToList()
});

最佳实践

✅ 推荐做法

  • 使用 DI 注入 Kernel
  • 为插件函数添加详细 Description
  • 使用 Filter 进行日志和监控
  • 分离 Native 和 Semantic 函数
  • 使用 Template Format 管理复杂 Prompt
  • 启用 Telemetry 可观测性

❌ 避免做法

  • 在循环中频繁创建 Kernel
  • 忽略 Function Calling 错误
  • 硬编码 Prompt 模板
  • 不处理流式调用的取消
  • 混合使用不同版本的 AI 服务
  • 忽略 Token 限制

性能优化策略

// 1. 复用 Kernel 实例
// ❌ 每次请求创建新 Kernel
// ✅ 使用单例 Kernel

// 2. 批量处理
var tasks = inputs.Select(input => 
    kernel.InvokeAsync(function, new() { ["input"] = input }));
var results = await Task.WhenAll(tasks);

// 3. 使用流式输出减少延迟
await foreach (var chunk in kernel.InvokeStreamingAsync(function))
{
    // 立即返回部分结果
    yield return chunk;
}

// 4. 缓存 Embedding
var embeddingCache = new Dictionary<string, ReadOnlyMemory<float>>();

// 5. 禁用不需要的 Filter
var kernel = Kernel.CreateBuilder()
    .ConfigureServices(s => s.RemoveAll<IFunctionInvocationFilter>())
    .Build();

与其他框架对比

框架 语言 特点 适用场景
Semantic Kernel C#/Python/Java 插件化、企业级 .NET 企业应用
LangChain Python/JS 生态丰富、社区大 快速原型
AutoGen Python/.NET 多 Agent 协作 复杂 Agent 系统
CrewAI Python 角色扮演、团队协作 多角色任务
LlamaIndex Python RAG 专用 知识库应用

总结

Semantic Kernel 核心价值

  • 统一 AI 服务抽象,解耦业务与模型
  • 插件化架构,支持 Function Calling
  • Filter 管道,支持 AOP 式扩展
  • Vector Store 抽象,简化 RAG 开发

关键源码文件

  • Kernel.cs - 核心编排容器
  • KernelFunction.cs - 函数抽象基类
  • KernelPlugin.cs - 插件抽象基类
  • KernelArguments.cs - 参数容器
  • FunctionResult.cs - 结果封装

演进方向

Microsoft.Extensions.AI 统一抽象 + 多语言支持

参考资料

  • 源码仓库: github.com/microsoft/semantic-kernel
  • 官方文档: learn.microsoft.com/semantic-kernel
  • 示例代码: github.com/microsoft/semantic-kernel/tree/main/samples
  • .NET API: api.kernel.microsoft.com
  • 社区讨论: github.com/microsoft/semantic-kernel/discussions

感谢阅读!
访问 https://atcfu.com/ai-articles/semantic-kernel/ 回顾本文