首页 > 其他分享 >Semantic Kernel入门系列:通过依赖注入管理对象和插件

Semantic Kernel入门系列:通过依赖注入管理对象和插件

时间:2024-06-11 09:11:07浏览次数:23  
标签:Kernel 插件 依赖 Semantic kernel services 注入

前言

本章讲一下在Semantic Kernel中使用DependencyInject(依赖注入),在之前的章节我们都是通过手动创建Kernel对象来完成框架的初始化工作,今天我们用依赖注入的方式来实现。

实战

定义Native Plugins

我们用官网的LightPlugins插件来演示依赖注入在SK中的使用

public class LightPlugin
{
    public bool IsOn { get; set; } = false;

#pragma warning disable CA1024 // Use properties where appropriate
    [KernelFunction]
    [Description("Gets the state of the light.")]
    public string GetState() => IsOn ? "on" : "off";
#pragma warning restore CA1024 // Use properties where appropriate

    [KernelFunction]
    [Description("Changes the state of the light.'")]
    public string ChangeState(bool newState)
    {
        this.IsOn = newState;
        var state = GetState();

        // Print the state to the console
        Console.WriteLine($"[Light is now {state}]");

        return state;
    }
}

这个插件有两个方法一个是获取当前灯的状态,第二个是改变灯的状态

创建kernel对象

在之前我们的演示中都是通过Kernel对象提供的CreateBuilder方法来创建Kernel对象。

    var kernel = Kernel.CreateBuilder().
      AddOpenAIChatCompletion(modelId: config.ModelId, apiKey: config.ApiKey)
        .Build();

在api项目的开发中,依靠依赖注入的方式更容易管理依赖项,以及对象的复用

依赖注入注入Kernel依赖

有两种方式可以用依赖注入创建Kernel对象,第一种是借助于KernelServiceCollectionExtensions累提供的AddKernel扩展方法,第二种就是自己Kernel kernel = new(services.BuildServiceProvider());或者services.AddTransient<Kernel>();

AddKernel源码

    /// </returns>
    /// <remarks>
    /// Both services are registered as transient, as both objects are mutable.
    /// </remarks>
    public static IKernelBuilder AddKernel(this IServiceCollection services)
    {
        Verify.NotNull(services);

        // Register a KernelPluginCollection to be populated with any IKernelPlugins that have been
        // directly registered in DI. It's transient because the Kernel will store the collection
        // directly, and we don't want two Kernel instances to hold on to the same mutable collection.
        services.AddTransient<KernelPluginCollection>();

        // Register the Kernel as transient. It's mutable and expected to be mutated by consumers,
        // such as via adding event handlers, adding plugins, storing state in its Data collection, etc.
        services.AddTransient<Kernel>();

        // Create and return a builder that can be used for adding services and plugins
        // to the IServiceCollection.
        return new KernelBuilder(services);
    }

通过源码我们可以看出来,这两种方式基本上没区别,第二种AddKernel实际上是简化了我们第二种的步骤,我们就用第一种举例演示

//依赖注入
{
    IServiceCollection services = new ServiceCollection();
    //会话服务注册到IOC容器
    services.AddKernel().AddOpenAIChatCompletion(modelId: config.ModelId, apiKey: config.ApiKey, httpClient: client);
    services.AddSingleton<KernelPlugin>(sp => KernelPluginFactory.CreateFromType<LightPlugin>(serviceProvider: sp));
    var kernel = services.BuildServiceProvider().GetRequiredService<Kernel>();

这就是在依赖注入中注册Kernel对象和插件的步骤,依赖项都会被注册到IServiceCollection

Semantic Kernel使用的服务插件通常作为Singleton单例注册到依赖注入容器中,以便它们可以在各种Kernel之间重用/共享。Kernel通常注册为Transient瞬态,以便每个实例不受处理其他任务的Kernel所做更改的影响。

在项目中使用时,我们可以通过在构造函数中获取Kernel对象的实例,用Kernel对象来获取服务实例

var chatCompletionService = kernel.GetRequiredService<IChatCompletionService>();

IChatCompletionService 实例也可以通过 IServiceProvider 来获取,您可以灵活地使用更适合您要求的方法。

实战

我们用依赖注入跑一下LightPlugin插件

    // Create chat history
    var history = new ChatHistory();

    // Get chat completion service
    var chatCompletionService = kernel.GetRequiredService<IChatCompletionService>();

    // Start the conversation
    Console.Write("User > ");
    string? userInput;
    while ((userInput = Console.ReadLine()) is not null)
    {
        // Add user input
        history.AddUserMessage(userInput);

        // Enable auto function calling
        OpenAIPromptExecutionSettings openAIPromptExecutionSettings = new()
        {
            ToolCallBehavior = ToolCallBehavior.AutoInvokeKernelFunctions
        };

        // Get the response from the AI
        var result = await chatCompletionService.GetChatMessageContentAsync(
            history,
            executionSettings: openAIPromptExecutionSettings,
            kernel: kernel);

        // Print the results
        Console.WriteLine("Assistant > " + result);

        // Add the message from the agent to the chat history
        history.AddMessage(result.Role, result.Content ?? string.Empty);

        // Get user input again
        Console.Write("User > ");
    }

输出:

User > 当前灯光的状态
Assistant > 当前灯光的状态是关闭的。
User > 帮我开个灯
[Light is now on]
Assistant > 已经成功为您点亮了灯。

最后

本文Demo用的大模型月之暗面的moonshot-v1-8k

  "Endpoint": "https://api.moonshot.cn",
  "ModelId": "moonshot-v1-8k",

原则上任何支持OpenAI function calling 格式的都可以使用。

通过本章的学习,我们深入了解了在Semantic Kernel中利用依赖注入的方式来管理Kernel对象和插件,使得项目开发更加灵活和高效。

参考文献

Using Semantic Kernel with Dependency Injection

示例代码

本文源代码

标签:Kernel,插件,依赖,Semantic,kernel,services,注入
From: https://www.cnblogs.com/ruipeng/p/18241147

相关文章

  • 【IDEA 必备插件之一】这样注入 Bean 才爽
    今天我们来介绍一款免费的IDEA生产力插件,它叫BeanAssistant。我们可以在插件市场搜索BeanAssistant来安装它。前言不知道你们在平时的工作场景中是否经常遇到以下的情况。在一个方法中,需要调用某个实例接口的方法。我们经常会先在该类里面先注入这个接口的实例Bean,然后再调......
  • npm发布自己的插件包
    在JavaScript开发领域,npm(NodePackageManager)是不可或缺的包管理和分发工具,它不仅提供了海量的开源库供开发者使用,还允许每个人将自己的代码封装成包分享给全世界。发布一个npm插件包,不仅能提升个人影响力,还能促进技术交流与共享。本文将手把手教你如何发布npm包,同时指出过......
  • 01-前端开发Vscode插件配置
    01自动保存配置02空格渲染方式配置好以后,可以看到代码的空格有几个,以点的方式呈现,1个点表示1个空格03图标插件VSCodeGreatIcons04缩进推荐使用205vscode标记一整块代码文件>>首选项>>设置添加2行代码"editor.bracketPairColorization.enabled":true,"e......
  • cordova-plugin-inappbrowser内置浏览器插件
    一、InAppBrowser(内置浏览器)允许在在单独的窗口中加载网页。例如要向应用用户展示其他网页。当然可以很容易地在应用中加载网页内容并管理,但有时候需要不同的用户体验,InAppBrowser加载网页内容,应用用户可以更方便的直接返回到主应用。二、安装命令:cordovapluginaddcordov......
  • [IDA PRO] RVA 插件
    IDA插件-跳转到偏移量IDA插件-获取偏移量Shift+G跳转到指定RVACtrl+Shift+C(或右键选择)复制当前RVA到剪贴板#------------------------------------------------------------------------------#IDAPlugintojumptoanoffsetfromtheImagebase.#Copythe......
  • 二、插件
    推荐网站:https://vimjc.com大部分插件的介绍和大概设置方法都在这里。一、安装neovim完全体Ubuntu自带的vim在编译时会缺少部分组件,建议从ppa安装完全体的neovim以进行后续的设置。#使用最新版Neovimsudoadd-apt-repositoryppa:neovim-ppa/stable#配套环境p......
  • VSCode超过390万下载的请求插件
    ThunderClient是一款在VSCode(VisualStudioCode)中非常受欢迎的RESTAPI客户端插件,由RangaVadhineni开发,现在已经有超过390万的下载量。它允许开发者直接在编辑器内发送HTTP请求,查看响应。ThunderClient提供了一个直观的界面来构建和测试API,非常适合前后端开发人......
  • 百度网盘下载不限速(6月最新插件)
    【应用名称】百度网盘【应用版本】2024双插件版6月最新【应用大小】220MB【适用平台】win11【应用简介】更新了图文教程百度网盘是国内资源生态最大的在线存储服务提供商,提供免费和收费的文件存储,备份,共享等文件管理等功能.百度网盘客户端的百度网盘电脑版本次依旧......
  • 百度网盘下载不限速,6月最新插件
    【应用名称】百度网盘【应用版本】2024双插件版6月最新【应用大小】220MB【适用平台】win11【应用简介】更新了图文教程百度网盘是国内资源生态最大的在线存储服务提供商,提供免费和收费的文件存储,备份,共享等文件管理等功能.百度网盘客户端的百度网盘电脑版本次依旧......
  • 6月最新百度网盘不限速插件
    【应用名称】百度网盘【应用版本】2024双插件版6月最新【应用大小】220MB【适用平台】win11【应用简介】更新了图文教程百度网盘是国内资源生态最大的在线存储服务提供商,提供免费和收费的文件存储,备份,共享等文件管理等功能.百度网盘客户端的百度网盘电脑版本次依旧......