.NET Core C#系列之 Semantic Kernel Plugin插件教程(数据库)

B站影视 2024-12-08 10:36 2

摘要:首先,需要打开 Visual Studio 2022 并创建一个名为5_1_SKPluginsql的控制台项目。

创建控制台项目

首先,需要打开 Visual Studio 2022 并创建一个名为5_1_SKPluginsql的控制台项目。

接下来,我们将使用SemanticKernel来导入目录中所有的插件。

在项目目录中,创建一个plugins文件夹,并在其中创建BasePlugins文件夹。这个文件夹将用来存放我们系统的基础插件。

在BasePlugins文件夹下,创建一个SQLiteSystem文件夹。这个文件夹将用来存放我们为Sqlite数据库创建的插件。

接着,在SqliteSystem文件夹下创建一个skprompt.txt文件。这个文件是SemanticKernel插件的Prompt文件,它将用来定义插件的AI行为。

# 背景您是SQLite数据库助手,有能力帮助用户执行SQL查询,创建数据库,插入数据,删除数据,更新数据等操作。您需要遵守Sqlite的语法规则,并支持大部分Sqlite的语法。如果用户输入的SQL语句有错误,您需要返回错误信息,其中action为error,sql为错误信息。如果用户需要操作指定表,您需要先查询表的结构,然后再执行用户的操作。查询表则只需要返回表名称。## 用户输入{{$input}}## 输出格式您需要按照定义的格式输出。请注意,输出的格式必须是json,并且无论用户的操作有多少个,都需要是数组格式,即使只有一个操作。输出不要有md格式的标记,比如```json,只需要json的数据。[ { "action": "", // 操作类型,有query, create, insert, delete, update, drop, error,queryTable "sql": "", // 根据用户输入去生成的sql语句 "isResult": bool, // 是否是查询结果 }]接下来,在SqliteSystem文件夹下创建一个config.json文件。这个文件用于配置插件的AI相关参数。文件的内容如下:{ "schema": 1, "type": "completion", "description": "Sqlite数据库助手,用于执行或查询Sqlite数据库", "execution_settings": { "default": { "max_tokens": 1000, "temperature": 0, "response_format": { "type": "json_object" } }, "gpt-3.5-turbo": { "model_id": "gpt-3.5", "max_tokens": 4000, "temperature": 0.1 }, "gpt-4o": { "model_id": "gpt-4o", "max_tokens": 4000, "temperature": 0.5, "response_format": { } } }, "input_variables": [ { "name": "input", "description": "用户输入的需求!", "required": true } ]}

在这个配置文件中:

execution_settings:这是AI的执行参数。default是默认的参数;gpt-3.5-turbo是gpt-3.5模型的参数;gpt-4o模型的参数。input_variables:这是我们的prompt的参数,也是我们的插件需要的参数。name是参数的名称,是参数的描述,required表示参数是否必须。 Exe net8.0 _5_1_SKPluginSQL enable enable Always 在这个项目文件中,我们添加了FreeSql.Provider.Sqlite和Microsoft.SemanticKernelMicrosoft.Semantickernel.Plugins.Core

的NuGet包。

是我们用于操作Sqlite数据库的NuGet包。是我们的SemanticKernel的NuGet包。Microsoft.SemanticKernel.Plugins.Core是SemanticKernel的提供的一些默认插件的NuGet包。创建OpenAIHttpClientHandler.cspublic class OpenAIHttpClientHandler : HttpClientHandler{ private readonly string _uri; public OpenAIHttpClientHandler(string uri) => _uri = uri.TrimEnd('/'); protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { UriBuilder uriBuilder; if (request.RequestUri?.LocalPath == "/v1/chat/completions") { uriBuilder = new UriBuilder(_uri + "/v1/chat/completions"); request.RequestUri = uriBuilder.Uri; } else if (request.RequestUri?.LocalPath == "/v1/embeddings") { uriBuilder = new UriBuilder(_uri + "/v1/embeddings"); } return await base.SendAsync(request, cancellationToken); }}在目录下,创建FreeSqlPlugin.cspublic sealed class FreeSqlPlugin{ private static readonly IFreeSql FreeSql = new FreeSql.FreeSqlBuilder .UseConnectionString(global::FreeSql.DataType.Sqlite, "Data Source=./sk.db") .UseAutoSyncStructure(true) .Build; [KernelFunction("Execute"),Description("用于执行不需要返回结果的SQL语句,返回是否执行成功,通常用于增删改操作。")] public async Task ExecuteAsync([Description("需要执行的Sqlite的Sql语句")]string sql) { var result = await FreeSql.Ado.ExecuteNonQueryAsync(sql); return result > 0; } [KernelFunction("Query"),Description("用于执行需要返回结果的SQL语句,返回查询结果。")] public async Task> QueryAsync([Description("需要执行的Sqlite的Sql语句")]string sql) { var result = await FreeSql.Ado.QueryAsync(sql); return result; } [KernelFunction("QueryFirst"),Description("用于执行需要返回结果的SQL语句,返回第一行查询结果。")] public async Task QueryFirstAsync([Description("需要执行的Sqlite的Sql语句")]string sql) { var result = await FreeSql.Ado.QuerySingleAsync(sql); return result; } [KernelFunction("QueryFirstOrDefault"),Description("用于执行需要返回结果的SQL语句,返回第一行查询结果,如果没有查询到结果则返回。")] public async Task QueryFirstOrDefaultAsync([Description("需要执行的Sqlite的Sql语句")]string sql) { var result = await FreeSql.Ado.QuerySingleAsync(sql); return result; }}创建SqlAction.cs用于接收SK输出的Sql相关执行数据。public class SqlAction{ public string action { get; set; } public string sql { get; set; } public bool isResult { get; set; }}在Program.csconst string createPrompt = @"# 背景您是一个Sql助手,我会提供很多用于执行Sql的Function,您需要根据需求选择合适的Function来执行Sql语句,返回结果给用户。## 需求操作:{{$action}}Sql语句:{{$sql}}是否存在返回结果:{{$hasResult}}";var kernel = Kernel.CreateBuilder .AddOpenAIChatCompletion( modelId: "gpt-4o", apiKey: "这里填写在https://api.token-ai.cn/创建的令牌", httpClient: new HttpClient(new OpenAIHttpClientHandler("https://api.token-ai.cn/"))) .Build;kernel.Plugins.AddFromType;var pluginsDirectory = Path.Combine(Directory.GetCurrentDirectory, "plugins", "BasePlugins");var basePlugins = kernel .ImportPluginFromPromptDirectory(pluginsDirectory);var chat = kernel.GetRequiredService;while (true){ Console.Write("User=>"); var input = Console.ReadLine; if (input == "exit") { break; } var result = await kernel.InvokeAsync(basePlugins["SqliteSystem"], new KernelArguments { ["input"] = input }); var values = JsonSerializer.Deserialize(result.ToString); foreach (var value in values) { Console.WriteLine($"Action: {value.action} Sql: {value.sql} IsResult: {value.isResult}"); var chatMessageContents = await chat.GetChatMessageContentsAsync(createPrompt .Replace("{{$action}}", value.action) .Replace("{{$sql}}", value.sql) .Replace("{{$isResult}}", value.isResult.ToString), new OpenAIPromptExecutionSettings { ToolCallBehavior = ToolCallBehavior.AutoInvokeKernelFunctions }, kernel); foreach (var chatMessageContent in chatMessageContents) { Console.WriteLine(chatMessageContent.Content); } }}我们定义的这个是我们定义的Prompt,用于处理SK给的相关操作和Sql语句,主要用途是让AI知道执行FreeSqlPlugin插件具体的方法,以及返回的结果,然后总结给用户。

通过

将FreeSqlPlugin插件加载到kernel这一块代码是扫描我们的目录下的BasePlugins文件夹,然后导入文件夹下所有的插件(虽然我们就只有一个插件)。

然后通过下面代码

我们解析用户的输入,然后调用basePlugins中的SqliteSystem插件,然后将返回的结果解析成SqlAction对象。下面我们主要对SqliteSystemPrompt# 背景您是Sqlite数据库助手,有能力帮助用户执行SQL查询,创建数据库,插入数据,删除数据,更新数据等操作。您需要遵守Sqlite的语法规则,并支持大部分Sqlite的语法。如果用户输入的SQL语句有错误,您需要返回错误信息,其中action为error,sql为错误信息。如果用户需要操作指定表,您需要先查询表的结构,然后再执行用户的操作。查询表则只需要返回表名称。在这个Prompt中,我们定义了插件的背景,用户输入,输出格式。我们可以理解Prompt是我们定义的AI的行为,这样AI则会按照我们的定义来执行。背景是我们对于AI的角色进行定义,尽量让他做更专业的事情,防止做出乎我们意料的行为。用户输入在这里我们使用到{{$input}}变量,用于提供给SK插入用户输入的信息。输出格式通过上面一套很严格的Prompt我们就可以得到我们想要的结果。User=>创建username表,字段 id name username password age,插入十条数据,然后查询username表的所有数据。Action: create Sql: CREATE TABLE username (id INTEGER, name TEXT, username TEXT, password TEXT, age INTEGER) IsResult: False表格 "username" 创建成功。Action: insert Sql: INSERT INTO username (id, name, username, password, age) VALUES (1, 'Alice', 'alice123', 'password123', 25) IsResult: False操作已成功执行,数据已插入。Action: insert Sql: INSERT INTO username (id, name, username, password, age) VALUES (2, 'Bob', 'bob456', 'password456', 30) IsResult: False操作成功执行,数据已插入。Action: insert Sql: INSERT INTO username (id, name, username, password, age) VALUES (3, 'Charlie', 'charlie789', 'password789', 35) IsResult: False操作执行成功,新数据已插入。Action: insert Sql: INSERT INTO username (id, name, username, password, age) VALUES (4, 'David', 'david101112', 'password101112', 40) IsResult: False操作已成功执行。Action: insert Sql: INSERT INTO username (id, name, username, password, age) VALUES (5, 'Eve', 'eve131415', 'password131415', 45) IsResult: FalseSQL语句已成功执行,数据已插入数据库中。根据您的要求,已经成功执行了插入数据的操作。Action: insert Sql: INSERT INTO username (id, name, username, password, age) VALUES (6, 'Frank', 'frank161718', 'password161718', 50) IsResult: False已成功执行插入操作。Action: insert Sql: INSERT INTO username (id, name, username, password, age) VALUES (7, 'Grace', 'grace192021', 'password192021', 55) IsResult: False操作已成功执行,没有返回结果。Action: insert Sql: INSERT INTO username (id, name, username, password, age) VALUES (8, 'Helen', 'helen222324', 'password222324', 60) IsResult: FalseSql语句执行成功,数据已插入。Action: insert Sql: INSERT INTO username (id, name, username, password, age) VALUES (9, 'Ivy', 'ivy252627', 'password252627', 65) IsResult: False操作已成功执行。操作已成功执行。Action: insert Sql: INSERT INTO username (id, name, username, password, age) VALUES (10, 'Jack', 'jack282930', 'password282930', 70) IsResult: FalseSQL语句已成功执行,并插入了数据。Action: query Sql: SELECT * FROM username IsResult: True查询结果如下:1. ID: 1, Name: Alice, Username: alice123, Password: password123, Age: 252. ID: 2, Name: Bob, Username: bob456, Password: password456, Age: 303. ID: 3, Name: Charlie, Username: charlie789, Password: password789, Age: 354. ID: 4, Name: David, Username: david101112, Password: password101112, Age: 405. ID: 5, Name: Eve, Username: eve131415, Password: password131415, Age: 456. ID: 6, Name: Frank, Username: frank161718, Password: password161718, Age: 507. ID: 7, Name: Grace, Username: grace192021, Password: password192021, Age: 558. ID: 8, Name: Helen, Username: helen222324, Password: password222324, Age: 609. ID: 9, Name: Ivy, Username: ivy252627, Password: password252627, Age: 6510. ID: 10, Name: Jack, Username: jack282930, Password: password282930, Age: 70

我们输入

创建username表,字段 id name username password age,插入十条数据,然后查询username表的所有数据。

然后AI帮我们生成了SQL语句,并执行了这些SQL语句,然后返回了结果。他分了很多步骤,每一步都有对应的SQL语句和执行结果。第一步是创建表,第二步是插入数据,第三步是查询数据。然后我们可以看到AI返回了我们查询的数据。

然后我们打开sk.db文件,我们可以看到数据库中已经有了username表,并且插入了十条数据。通过上面案例我们实现了通过与AI对话来执行SQL语句,这样我们可以通过AI来执行一些复杂的SQL语句,而不需要我们自己去写,其实还可以继续完善更多功能 直接让AI帮我们画echarts本文主要介绍了如何通过与AI对话来执行SQL语句。首先,需要创建一个名为5_1_SKPluginSQL的控制台项目,然后使用SemanticKernel来导入目录中所有的插件。接着,创建一个plugins文件夹,并在其中创建BasePlugins文件夹,用来存放系统的基础插件。在BasePlugins文件夹下,创建一个SqliteSystem文件夹,用来存放为Sqlite数据库创建的插件。然后,在SqliteSystem文件夹下创建一个skprompt.txt文件,该文件是SemanticKernel插件的Prompt文件,用来定义插件的AI行为。然后,安装和的NuGet包。创建和,分别用于处理HTTP请求和提供给SK执行SQL语句的插件。创建SqlAction.cs在Program.cs中,定义了Prompt,用于处理SK给的相关操作和Sql语句,主要用途是让AI知道执行FreeSqlPlugin插件具体的方法,以及返回的结果,然后总结给用户。然后通过运行项目,我们可以看到AI帮我们生成了SQL语句,并执行了这些SQL语句,然后返回了结果。

下一篇,我们讲解Semantic Kernel Plugin插件联网。

来源:opendotnet

相关推荐