SK的插件,能让AI功能如虎添翼。Plugin能让AI与本地功能和数据互动,使AI与应用的结合,并起到了很好的粘合剂作用。
怎么能让Plugin本身和功能分离呢?调用API是一个很好的办法,比如下面是一个查询订单的功能,是一个mini API项目。
using System.Text.Json.Serialization;var builder = WebApplication.CreateBuilder(args); builder.Services.AddOpenApi(); var app = builder.Build(); app.MapOpenApi(); app.MapGet("/orders", () => {app.Logger.LogInformation("查询orders");var orders = Enumerable.Range(1, 5).Select(index =>new Order(Guid.NewGuid().ToString(),$"Product {index}",index,index * 10)).ToArray();return orders; }) .WithName("orders").WithDescription("获取订单列表"); app.Run();class Order {public Order(string id, string product, int quantity, decimal price){Id = id;Product = product;Quantity = quantity;Price = price;}[JsonPropertyName("编号")]public string Id { get; set; }[JsonPropertyName("产品名称")]public string Product { get; set; }[JsonPropertyName("订单数量")]public int Quantity { get; set; }[JsonPropertyName("订单金额")]public decimal Price { get; set; } }
这个API的OpenAPI的框架是这样的:http://localhost:5000/openapi/v1.json
{"openapi": "3.0.1","info": {"title": "OpenAPIDemoForAI | v1","version": "1.0.0"},"servers": [{"url": "http://localhost:5000"}],"paths": {"/orders": {"get": {"tags": ["OpenAPIDemoForAI"],"description": "获取订单列表","operationId": "orders","responses": {"200": {"description": "OK","content": {"application/json": {"schema": {"type": "array","items": {"$ref": "#/components/schemas/Order"}}}}}}}}},"components": {"schemas": {"Order": {"required": ["编号","产品名称","订单数量","订单金额"],"type": "object","properties": {"编号": {"type": "string"},"产品名称": {"type": "string"},"订单数量": {"type": "integer","format": "int32"},"订单金额": {"type": "number","format": "double"}}}}},"tags": [{"name": "OpenAPIDemoForAI"}] }
现在调用一下接口,查询一下订单:http://localhost:5000/orders
[{"编号": "c82bd2f1-25d1-4a17-bb40-7cfe9fd35f71","产品名称": "Product 1","订单数量": 1,"订单金额": 10},{"编号": "bc6f1eef-4ea9-426c-a446-1cff12d963ac","产品名称": "Product 2","订单数量": 2,"订单金额": 20},{"编号": "b7b27a33-db1f-4c7c-99c6-064d330d8893","产品名称": "Product 3","订单数量": 3,"订单金额": 30},{"编号": "c58f6e36-4363-441d-b54f-50c99970d07a","产品名称": "Product 4","订单数量": 4,"订单金额": 40},{"编号": "2789ac41-0d90-4da8-8041-b2e3cd3f7859","产品名称": "Product 5","订单数量": 5,"订单金额": 50} ]
SK本身是支持把符合OpenAPI(这里不是OpenAI)规范的API导入成为SK的插件的,主要借助OpenApiKernelPluginFactory来完成,具体实现如下:
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.SemanticKernel; using Microsoft.SemanticKernel.ChatCompletion; using Microsoft.SemanticKernel.Connectors.OpenAI; using Microsoft.SemanticKernel.Plugins.OpenApi; using System.IO; using System.Text.Json; #pragma warning disable var apikey = File.ReadAllText("c:/gpt/key.txt"); using HttpClient httpClient = new();var kernelBuilder = Kernel.CreateBuilder(); kernelBuilder.AddOpenAIChatCompletion("gpt-4o", apiKey: apikey); var kernel = kernelBuilder.Build();var pluginArr = new List<PluginSetting> {new PluginSetting{PluginName="OrderService",UriString="http://localhost:5000/openapi/v1.json"} }; foreach (var pluginItem in pluginArr) {var plugin = await OpenApiKernelPluginFactory.CreateFromOpenApiAsync(pluginName: pluginItem.PluginName,uri: new Uri(pluginItem.UriString),executionParameters: new OpenApiFunctionExecutionParameters(httpClient){IgnoreNonCompliantErrors = true,EnableDynamicPayload = true,});kernel.Plugins.Add(plugin); } var chatCompletionService = kernel.GetRequiredService<IChatCompletionService>(); var openAIPromptExecutionSettings = new OpenAIPromptExecutionSettings() {ToolCallBehavior = ToolCallBehavior.AutoInvokeKernelFunctions }; ChatHistory history = []; while (true) {Console.WriteLine("回车开始");Console.ReadLine();Console.WriteLine("用户 > 查询一下订单,然后总汇订单的总金额 ");history.AddUserMessage("总汇一下订单的总金额");var result = await chatCompletionService.GetChatMessageContentAsync(history,executionSettings: openAIPromptExecutionSettings,kernel: kernel);Console.WriteLine("助理 > " + result);history.AddMessage(result.Role, result.Content!); } public class PluginSetting {public string PluginName { get; set; }public string UriString { get; set; } }
运行结果如下:
文章来源微信公众号
想要更快更方便的了解相关知识,可以关注微信公众号