Fork me on GitHub

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; }
}
复制代码

运行结果如下:

  文章来源微信公众号

  想要更快更方便的了解相关知识,可以关注微信公众号 

posted @   桂素伟  阅读(3)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示