ChatGPT Plugin 插件开发:基于 ASP.NET Core Minimal API

科技资讯 投稿 9400 0 评论

ChatGPT Plugin 插件开发:基于 ASP.NET Core Minimal API

前言

这个Todo List插件主要功能是以自然语言的方式向ChatGPT发起指令,ChatGPT将根据合适的时机选择调用此插件。例如:我明天下午3点有一个会议,请帮我记录。此时 ChatGPT将会根据插件的元数据功能描述,然后选择调用插件,将明天下午3点有一个会议通过API记录到待办列表中。

环境准备

在提交申请的时候,最好选择 "I am a developer and want to build a plugin",然后填写较为充分的理由,这样更容易通过一些。

概念说明

    构建服务端 API
  1. 启用 Swagger OpenApi 接口描述
  2. 创建一个插件清单文件,描述插件元数据信息

完成之后,你可以在界面上打开 Plugin Store,然后选择 Develop your own Plugin,填入本地 Api 地址即可。

使用 ASP.NET Core Minimal 开发服务端 API

    编写ai-plugin.json元数据文件
  1. 启用跨域
  2. 启用Swagger,并详细描述接口参数
  3. 编写接口代码

编写 ai-plugin.json元数据文件

每个插件都需要一个 ai-plugin.json 文件,该文件需要托管在API的域中。例如,一家名为 example.com 的公司将通过 https://example.com 域访问插件JSON文件,因为这是他们的API托管的地方。
当通过ChatGPT UI安装插件时,ChatGPT会查找位于 /.well-known/ai-plugin.json 的文件,以便和插件进行连接。如果找不到文件,则无法安装插件。对于本地开发,可以使用HTTP,要指向远程服务器,则需要HTTPS。

{
  "schema_version": "v1",
  "name_for_human": "TODO Plugin (no auth",
  "name_for_model": "todo",
  "description_for_human": "Plugin for managing a TODO list, you can add, remove and view your TODOs.",
  "description_for_model": "Plugin for managing a TODO list, you can add, remove and view your TODOs.",
  "auth": {
    "type": "none"
  },
  "api": {
    "type": "openapi",
    "url": "http://localhost:5000/openapi.yaml",
    "is_user_authenticated": false
  },
  "logo_url": "http://localhost:5000/logo.png",
  "contact_email": "legal@example.com",
  "legal_info_url": "http://example.com/legal"
}

内容很简单,需要说明的有2处。

    api:url 这个是指向 swagger 的 openapi描述文件,需要在服务端暴露出来。
  1. description_for_model 这个是当用户的指令可能有插件的潜在请求查询时,模型会查看该描述,您可能测试多个提示和描述,以查看哪些最有效。

启用跨域

由于是在网页前端调用的本地localhost接口,所以需要接口启用跨域以支持 chat.openai.com 的访问。

builder.Services.AddCors(x => x.AddDefaultPolicy(policyBuilder =>
    policyBuilder.WithOrigins("https://chat.openai.com".AllowAnyHeader(.AllowAnyMethod(;
    
// 省略部分代码

app.UseCors(;

启用Swagger,并详细描述接口参数

ChatGPT需要使用OpenAi V3版本,所以需要确保你引用了最新的 Swashbuckle.AspNetCore NuGet包。

builder.Services.AddSwaggerGen(c =>
{
    c.SwaggerDoc("openapi", new OpenApiInfo
    {
        Description = "A plugin that allows the user to create and manage a TODO list using ChatGPT. If you do not know the user's username, ask them first before making queries to the plugin. Otherwise, use the username \"global\".",
        Version = "v1",
        Title = "TODO Plugin"
    };
    c.AddServer(new OpenApiServer( { Url = "http://localhost:5000" };

    var xmlFilename = $"{Assembly.GetExecutingAssembly(.GetName(.Name}.xml";
    c.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, xmlFilename;
};

//省略部分代码

if (app.Environment.IsDevelopment(
{
    app.UseSwagger(x => x.RouteTemplate = "{documentName}.yaml";
    app.UseSwaggerUI(x =>
    {
        x.RoutePrefix = "";
        x.SwaggerEndpoint("/openapi.yaml", "TODO Plugin";
    };
}

我们配置 RoutePrefix=""以使主页即为swagger默认地址,配置 x.SwaggerEndpoint("/openapi.yaml", "TODO Plugin" 为 OpenAPI文件的访问地址,该地址和 ai-plgion.json中的地址要对应。

API 接口代码


var todos = new Dictionary<string, List<string>>(;

app.MapPost("/todos/{username}", (string username, [FromBody] AddTodoRequest request =>
{
    var todo = request.Todo;
    if (!todos.ContainsKey(username
    {
        todos[username] = new List<string>(;
    }
    todos[username].Add(todo;
    return todo;
}
.Produces<string>(
.WithOpenApi(operation =>
{
    operation.OperationId = "addTodo";
    operation.Summary = "Add a todo to the list";
    var parameter = operation.Parameters[0];
    parameter.Description = "The name of the user.";
    return operation;
};


app.MapGet("/todos/{username}", (string username =>
    Results.Json(todos.TryGetValue(username, out var todo ? todo : Array.Empty<string>(

.Produces<List<string>>(
.WithOpenApi(operation =>
{
    operation.OperationId = "getTodos";
    operation.Summary = "Get the list of todos";

    var parameter = operation.Parameters[0];
    parameter.Description = "The name of the user.";

    operation.Responses["200"].Description = "The list of todos";
    return operation;
};


app.MapDelete("/todos/{username}", (string username, [FromBody] DeleteTodoRequest request =>
{
    var todoIdx = request.TodoIdx;
    if (todos.ContainsKey(username && 0 <= todoIdx && todoIdx < todos[username].Count
    {
        todos[username].RemoveAt(todoIdx;
    }
}
.Produces<List<string>>(
.WithOpenApi(operation =>
{
    operation.OperationId = "getTodos";
    operation.Summary = "Delete a todo from the list";
    operation.Parameters[0].Description = "The name of the user.";
    return operation;
};

app.MapGet("/logo.png", ( => Results.File("logo.png", contentType: "image/png"
    .ExcludeFromDescription(;

app.MapGet("/.well-known/ai-plugin.json", ( => Results.File("ai-plugin.json", contentType: "text/json"
    .ExcludeFromDescription(;

app.Run(;

/// <summary>
/// AddTodoRequest Dto
/// </summary>
/// <param name="Todo">The todo to add to the list.</param>
internal record AddTodoRequest(string Todo;

/// <summary>
/// DeleteTodoRequest Dto
/// </summary>
/// <param name="TodoIdx">The index of the todo to delete.</param>
internal record DeleteTodoRequest(int TodoIdx;

测试插件

总结

完整的代码我已经上传到了Github,大家可自行查看。

如果你觉得本篇文章对您有帮助的话,感谢您的【推荐】。

编程笔记 » ChatGPT Plugin 插件开发:基于 ASP.NET Core Minimal API

赞同 (47) or 分享 (0)
游客 发表我的评论   换个身份
取消评论

表情
(0)个小伙伴在吐槽