• Semantic Kernel dotnet 1.0 RC1正式发布 看下都有哪些重大更新
  • 发布于 2个月前
  • 278 热度
    0 评论
  • 秋萧索
  • 0 粉丝 56 篇博客
  •   
Semantic Kernel dotnet 1.0 RC1 发布了,这是正式迈向 1.0 正式版的第一个候选版本。这个版本相对于1.0 Beta 8 变化非常的大。而且可能是因为发布的比较匆忙,Semantic Kernel 开发者的先行者们已经发现多个明显的 Bug。建议大家谨慎升级。

以下是部分我们认为比较重要的变更:

实现自动函数调用
实现自动 OpenAI(其他带函数调用的模型也可以)函数调用。
备注:自动调用行为是根据 autoInvoke 是否为 true 来处理的。通过在 PromptExecutionSettings 基类的字典中设置命名属性,还可以以与服务无关的方式选择加入 FunctionCallBehavior.AutoInvokeKernelFunctions; 如果未来的服务实现具有内置的函数调用概念(其他一些 LLM 也是如此),或者如果想使用嵌入到连接器实现中的规划器来模拟它,那么它们也可以尊从这个逻辑。

代码例子:
Kernel kernel = new KernelBuilder()
    .WithOpenAIChatCompletion("gpt-3.5-turbo-1106", apiKey)
    .ConfigurePlugins(plugins => plugins.AddPluginFromObject<TimePlugin>())
    .Build();
// 堆代码 duidaima.com
OpenAIPromptExecutionSettings settings = new() { FunctionCallBehavior = FunctionCallBehavior.AutoInvokeKernelFunctions };
Console.WriteLine(await kernel.InvokePromptAsync("What is the current time?", settings));
这个部分的功能表现,简直太酷了。这是一个相当大的新变化,连接器可以自行触发功能,使 LLM 成为实际的计划执行者。

FunctionCallBehavior 中有几个选项可用:
1.FunctionCallBehavior.EnableKernelFunctions: 将发送所提供内核中的函数,但如果请求,不会自动调用;
2.FunctionCallBehavior.AutoInvokeKernelFunctions: 将发送所提供内核中的函数,并在请求时自动调用;
3.FunctionCallBehavior.EnableFunctions(functionsList, autoInvoke): 指定的函数将被发送,它们是否会被自动调用取决于 autoInvoke 参数以及它们在提供的内核中是否可用;

4.FunctionCallBehavior.RequireFunction(function, autoInvoke): 指定的函数将作为函数调用请求发送到服务


流式/非流式处理的平等性
ChatCompletion
以前的
public interface IChatCompletion : IAIService
{
    ChatHistory CreateNewChat(string? instructions = null);
    Task<IReadOnlyList<IChatResult>> GetChatCompletionsAsync(ChatHistory chat, ...);
    Task<IReadOnlyList<IChatResult>> GetChatCompletionsAsync(string prompt, ...);
    IAsyncEnumerable<T> GetStreamingContentAsync<T>(ChatHistory chatHistory, ...);
}

public static class ChatCompletionExtensions
{
    public static async Task<string> GenerateMessageAsync(ChatHistory chat, ...);
}
变更为
public interface IChatCompletionService : IAIService
{
    Task<IReadOnlyList<ChatContent>> GetChatContentsAsync(ChatHistory chat, ..> tags)
    IAsyncEnumerable<StreamingChatContent> GetStreamingChatContentsAsync(ChatHistory chatHistory, ...);
}

public static class ChatCompletionServiceExtensions
{
    //                       v Single          vv Standardized Prompt (Parse <message> tags)
    public static async Task<ChatContent> GetChatContentAsync(string prompt, ...);
    //                       v Single
    public static async Task<ChatContent> GetChatContentAsync(ChatHistory chatHistory, ...);

    public static IAsyncEnumerable<StreamingChatContent> GetStreamingChatContentsAsync(string prompt, ...);
}
TextCompletion
以前:
public interface ITextCompletion : IAIService
{
    Task<IReadOnlyList<ITextResult>> GetCompletionsAsync(string prompt, ...);

    IAsyncEnumerable<T> GetStreamingContentAsync<T>(string prompt, ...);
}

public static class TextCompletionExtensions
{
    public static async Task<string> CompleteAsync(string text, ...);
    public static IAsyncEnumerable<StreamingContent> GetStreamingContentAsync(string input, ...);
}
变更为:
public interface ITextCompletionService : IAIService
{
    Task<IReadOnlyList<TextContent>> GetTextContentsAsync(string prompt, ...);

    IAsyncEnumerable<StreamingTextContent> GetStreamingTextContentsAsync(string prompt, ...);
}

public static class TextCompletionServiceExtensions
{
    public static async Task<TextContent> GetTextContentAsync(string prompt, ...);
}
函数调用 stepwise planner 改进
1.将 kernel 参数从构造函数移动到 ExecuteAsync 中
2.使用语义函数生成初始计划,并从 YAML 加载提示和设置

3.根据为 planner 指定的最大令牌数检查估计的令牌计数


FunctionCallingStepwisePlannerConfig 增加了几个属性来支持这些改进:
/// <summary>
/// The ratio of tokens to allocate to the completion request. (prompt / (prompt + completion))
/// </summary>
public double MaxTokensRatio { get; set; } = 0.1;

internal int MaxCompletionTokens { get { return (int)(this.MaxTokens * this.MaxTokensRatio); } }

internal int MaxPromptTokens { get { return (int)(this.MaxTokens * (1 - this.MaxTokensRatio)); } }
HandleBars Planer 的遥测支持

重命名
1.Planners.Handlebars 独立包形式存在,在 nuget 上的完整名是 Microsoft.SemanticKernel.Planners.Handlebars
2.将类、方法中的SK前缀改为Kernel,
比如:
SKFunction改为KernelFunction
SKException改为KernelException
ISKPlugin改为IKernelPlugin
等等
3.AIRequestSettings 改名为 PromptExecutionSettings
引入 KernelFunctionArguments 作为 Kernel.InvokeAsync 和 KernelFunction.InvokeAsync 方法的参数。奇葩的是在之后的修改中又将 KernelFunctionArguments 重命名为 KernelArguments 了,以便额外支持 KernelFunctions 以外的其他组件(prompt template、planner 等);也因此相关的一些参数也从 IDictionary<string, string> 类型变更为 KernelArguments。且 KernelArguments 开始支持非字符串参数:
  3.1 InvokeAsync(Kernel kernel, SKContext context, AIRequestSettings? requestSettings, CancellationToken cancellationToken) 变为 InvokeAsync(Kernel kernel, KernelArguments arguments, CancellationToken cancellationToken)
  3.2 InvokeAsync(this Kernel kernel, KernelFunction function, ContextVariables variables, CancellationToken cancellationToken) 变为 InvokeAsync(this Kernel kernel, KernelFunction function, KernelArguments arguments, CancellationToken cancellationToken)
KernelFunction.GetMetadata 从方法变为属性 Function.Metadata

4.重构了 PromptTemplateConfig:
  4.1 requestSettings 重命名为 executionSettings
  4.2 合并了 PromptTemplateConfig 和 PromptFuncitonModel
  4.3 prompt 函数的 config.json 中的 models 改名为 execution_settings

  4.4 KernelFunctionFromPrompt 的 Create 方法增加了 promptTemplateFactory


5.AzureTextCompletion 重名为 AzureOpenAITextCompletion
6.RunStreamingAsync 更名为 InvokeStreamingAsync,并连同 InvokeAsync 一起变为 Kernel 的自有方法,而不再是扩展方法。
7.包 Microsoft.SemanticKernel.TemplateEngine.Handlebars 改名为 Microsoft.SemanticKernel.PromptTemplate.Handlebars
8.将 ModelResult 从 Microsoft.SemanticKernel.Orchestration 移动到 Microsoft.SemanticKernel.AI
9.将 KernelBuilder 的方法重命名为 With 而不是 Configure。为了保持一致性,还将参数的顺序更改为 WithPlugins 优先,以便所有重载都首先具有插件集合,并且将集合的类型更新为类型更强的 KernelPluginCollection 而不是ICollection<IKernelPlugin>
10.命名空间中的 OpenAPI 重命名为 OpenApi
11.IChatCompletion 接口及其所有实现都重命名为具有 Service 后缀
12.ITextCompletion 重命名为 ITextGenerationService
13.ImageGeneration 重命名为 TextToImage

有两个重要的称呼正式变更了
1.正式将 Semantic Function 改称为 Prompt Function。

2.正式将 Native Function 改称为 Method Function。


其他
.AIServices 将必须使用模型 ID 进行配置
.修复了发出多个函数调用导致 OpenAI 返回 500 内部服务器错误的问题
.更改事件处理程序取消的方式,并简化了 FunctionResult,开发者可以通过检查可为空字典来检查是否有元数据。
.将 ExperimentalAttribute 添加到 Semantic Kernel 的 .NET SDK 中的包和类,以标记Semantic Kernel v1.0.0 中尚未准备好的内容。
.Chat Completion API 的标准化提示输入支持(例如<message>)
.提取了一个 TypeConverterFactory 实用工具类,统一为 FunctionResult 和 KernelFunctionFromMethod 提供相同的类型转换功能。
.移除了 KernelNameAttribute,并为 KernelFunctionAttribute 增加了一个 Name 属性。原来需要在一个方法上加 [KernelName("email_addresses")] 和 [KernelFunction] 的合并为一个 [KernelFunction("email_addresses")] 即可
.恢复了 ChatHistory  流式消息输入的支持
.修复 OpenAI JSON manifest 解析问题(下划线小写)
.增加了一个用于使用 System.Text.Json 的序列化方法序列化自定义类型的 ADR。旨在简化自定义类型的使用,允许开发者使用任何可以通过System.Text.Json进行序列化的类型。在 JSON 可序列化类型上进行标准化是必要的,以便使用 JSON 模式在 Planner 的函数手册中描述函数。使用 JSON 模式来描述函数的输入和输出类型将允许 Planner 验证函数的使用是否正确。
.清理了旧的流式处理 API
.删除了 SKContext 类
.新的 Planner 不再以来 Planner Core,以便可以独立发布
.Assistant Experimental 功能做了更新
.清理一些扩展方法类
.除了 Microsoft.SemanticKernel.Connectors.Memory.Postgres.PostgresMemoryEntry 以外所有其他 record 都改回了 class


有时开发者希望对可变数据或行为数据进行建模,这些数据具有复杂或自定义逻辑,用于更改其状态、验证其不变量或与其他对象交互。此类数据的示例包括 UI 控件、服务、存储库、工厂等。在这些情况下,类可以为数据及其行为的实现和封装提供更大的灵活性和控制。也希望避免创建和复制 record 实例的潜在性能开销,尤其是当它们具有许多或大型属性时,或者如果它们经常更新或传递。


record 在后台作为引用类型实现,因此它们仍然会产生内存分配和垃圾回收的成本,并且在与表达式或解构一起使用时,它们还可能生成比类更多的中间对象和副本。此外,record 使用反射来实现其某些方法,例如 ToString 和 equality,这也可能会影响性能。亦或希望依赖基于类的语义的现有代码或框架进行互操作,例如序列化、反射、数据绑定、依赖关系注入等。其中一些方案可能不完全兼容或支持 record,或者可能需要额外的配置或自定义才能按预期工作。例如,某些库可能不容易序列化或反序列化记录,或者可能不支持某些数据绑定功能,如更改通知或验证。


结语
Semantic Kernel dotnet 的这个版本变更很大,也存在一些比较明显的 bug,在跟最新的 .NET 8 兼容上也存在一些潜在的问题,预计官方在本周内会发布一个新的修正版。建议大家先不要着急升级到这个版本,等待下个更稳定的版本发布后再跟进升级。当然了尝鲜研究者除外啊
用户评论