Semantic Kernel:OpenAPI的Plugin
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; } }
运行结果如下:
文章来源微信公众号
想要更快更方便的了解相关知识,可以关注微信公众号
****欢迎关注我的asp.net core系统课程****
《asp.net core精要讲解》 https://ke.qq.com/course/265696
《asp.net core 3.0》 https://ke.qq.com/course/437517
《asp.net core项目实战》 https://ke.qq.com/course/291868
《基于.net core微服务》 https://ke.qq.com/course/299524
《asp.net core精要讲解》 https://ke.qq.com/course/265696
《asp.net core 3.0》 https://ke.qq.com/course/437517
《asp.net core项目实战》 https://ke.qq.com/course/291868
《基于.net core微服务》 https://ke.qq.com/course/299524
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!