ChatGPT Plugin 插件开发:基于 ASP.NET Core Minimal API
前言
这是一篇ChatGPT插件开发教程,描述如何使用 ASP.NET Core Minimal API 开发 ChatGPT 插件,以最简单的 Todo List 指导示例作为入门教程。
这个Todo List插件主要功能是以自然语言的方式向ChatGPT发起指令,ChatGPT将根据合适的时机选择调用此插件。例如:我明天下午3点有一个会议,请帮我记录。此时 ChatGPT将会根据插件的元数据功能描述,然后选择调用插件,将明天下午3点有一个会议通过API记录到待办列表中。
环境准备
首先你需要有一个开通了 Plugins 模块的账号,然后你才能进行调试使用。如果你没有可以在这里申请加入等待列表。说明一下,我是Plus用户,我在提交了申请列表大概过了2-3周左右收到的开通邮件。
在提交申请的时候,最好选择 "I am a developer and want to build a plugin",然后填写较为充分的理由,这样更容易通过一些。
开通完成后,你可以在界面上看到列表中出现 Model 中可以选择 Plugins 选项。

概念说明
整体上,构建 ChatGPT 插件需要3个步骤,
- 构建服务端 API
- 启用 Swagger OpenApi 接口描述
- 创建一个插件清单文件,描述插件元数据信息
完成之后,你可以在界面上打开 Plugin Store,然后选择 Develop your own Plugin,填入本地 Api 地址即可。


使用 ASP.NET Core Minimal 开发服务端 API
为了简单起见,我们的接口不进行授权(No Auth),主要分为几个部分:
- 编写ai-plugin.json元数据文件
- 启用跨域
- 启用Swagger,并详细描述接口参数
- 编写接口代码
编写 ai-plugin.json元数据文件
每个插件都需要一个 ai-plugin.json 文件,该文件需要托管在API的域中。例如,一家名为 example.com 的公司将通过 https://example.com 域访问插件JSON文件,因为这是他们的API托管的地方。
当通过ChatGPT UI安装插件时,ChatGPT会查找位于 /.well-known/ai-plugin.json 的文件,以便和插件进行连接。如果找不到文件,则无法安装插件。对于本地开发,可以使用HTTP,要指向远程服务器,则需要HTTPS。
新建一个 ai-plugin.json 清单文件,填入以下内容:
{
"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描述文件,需要在服务端暴露出来。
- description_for_model 这个是当用户的指令可能有插件的潜在请求查询时,模型会查看该描述,您可能测试多个提示和描述,以查看哪些最有效。
description_for_model 属性让你可以自由地指导模型如何使用你的插件。总的来说,ChatGPT背后的语言模型非常能够理解自然语言并遵循指令。因此,这是一个很好的地方,可以放置关于插件功能以及模型应该如何正确使用它的一般说明。使用自然语言,最好使用简洁、描述性和客观的语气。您可以查看一些示例,以了解这应该是什么样子。我们建议以“Plugin for ...”,然后枚举API提供的所有功能。
启用跨域
由于是在网页前端调用的本地localhost接口,所以需要接口启用跨域以支持 chat.openai.com 的访问。
在 ASP.NET Core启用跨域很简单。
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 接口代码
我们使用 Minimal Api 来构建,代码中需要使用 OpenApi规范对参数进行详细描述,这样ChatGPT才能识别的更加准确。
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);
测试插件

总结
以上,就是简单的使用 ASP.NET Core minimal api 开发的一个 Todo List插件,功能比较简单,基本上看下代码就懂了。
完整的代码我已经上传到了Github,大家可自行查看。
https://github.com/yang-xiaodong/chatgpt-aspnetcore-plugin
如果你觉得本篇文章对您有帮助的话,感谢您的【推荐】。
ChatGPT Plugin 插件开发:基于 ASP.NET Core Minimal API的更多相关文章
- ASP.NET Core Web API下事件驱动型架构的实现(一):一个简单的实现
很长一段时间以来,我都在思考如何在ASP.NET Core的框架下,实现一套完整的事件驱动型架构.这个问题看上去有点大,其实主要目标是为了实现一个基于ASP.NET Core的微服务,它能够非常简单地 ...
- 重温.NET下Assembly的加载过程 ASP.NET Core Web API下事件驱动型架构的实现(三):基于RabbitMQ的事件总线
重温.NET下Assembly的加载过程 最近在工作中牵涉到了.NET下的一个古老的问题:Assembly的加载过程.虽然网上有很多文章介绍这部分内容,很多文章也是很久以前就已经出现了,但阅读之后 ...
- ASP.NET Core Web API下事件驱动型架构的实现(三):基于RabbitMQ的事件总线
在上文中,我们讨论了事件处理器中对象生命周期的问题,在进入新的讨论之前,首先让我们总结一下,我们已经实现了哪些内容.下面的类图描述了我们已经实现的组件及其之间的关系,貌似系统已经变得越来越复杂了. 其 ...
- 用VSCode开发一个基于asp.net core 2.0/sql server linux(docker)/ng5/bs4的项目(1)
最近使用vscode比较多. 学习了一下如何在mac上使用vscode开发asp.netcore项目. 这里是我写的关于vscode的一篇文章: https://www.cnblogs.com/cgz ...
- 如何基于asp.net core的Identity框架在mysql上作身份验证处理
首先了解这个概念,我一开始也是理解和掌握基本的概念,再去做程序的开发.Identity框架是微软自己提供,基于.net core平台,可拓展.轻量 级.面向多个数据库的身份验证框架.IdentityS ...
- 基于Asp.Net Core的简单社区项目源代码开源
2019年3月27号 更新版本 本项目基于 ASP.NET CORE 3.0+EF CORE 3.0开发 使用vs2019 +sqlserver 2017(数据库脚本最低支持sql server 20 ...
- AServer - 基于Asp.net core Kestrel的超迷你http服务器
AServer是基于ASP.NET Core Kestrel封装的一个超迷你http服务器.它可以集成进你的Core程序里,用来快速的响应Http请求,而不需要集成整个ASP.NET Core MVC ...
- 基于ASP.NET Core 创建 Web API
使用 Visual Studio 创建项目. 文件->新建->项目,选择创建 ASP.NET Core Web 应用程序. 基于 ASP.NET Core 2.0 ,选择API,身份验证选 ...
- 基于ASP.Net Core开发的一套通用后台框架
基于ASP.Net Core开发一套通用后台框架 写在前面 这是本人在学习的过程中搭建学习的框架,如果对你有所帮助那再好不过.如果您有发现错误,请告知我,我会第一时间修改. 知其然,知其所以然,并非重 ...
- 基于ASP.NET Core 3.0快速搭建Razor Pages Web应用
前言 虽然说学习新的开发框架是一项巨大的投资,但是作为一个开发人员,不断学习新的技术并快速上手是我们应该掌握的技能,甚至是一个.NET Framework开发人员,学习.NET Core 新框架可以更 ...
随机推荐
- JS判断数据类型的4种方法
4种判断方法分别是: typeof instanceof prototype属性 constructor属性 可判断的类型对比如下图: 实践代码如下: 1 // 构造函数名方法 2 function ...
- Graphx二度关系
import org.apache.spark.graphx._import org.apache.spark.rdd.RDDval vertexArray = Array( (1L, (" ...
- python 中倒是什么事可哈希的意思那?
可哈希对象 python中的hashable(可哈希的)是什么意思 2018年12月29日 23:29:36 shangyj17 阅读数:511 不严谨但易懂的解释: 一个对象在其生命周期内,如果 ...
- 关于windows cmd 控制台输出中文
由于中文在window 输出总是优乱码可能性 ,先建cmd.reg 负责下面内容 ,双击运行即可. Windows Registry Editor Version 5.00 [HKEY_CURR ...
- 《MySQL是怎样运行的》第一章小结
- MathJax使用
转载网址: http://t.zoukankan.com/Dean0731-p-12881872.html
- Codeforces Round 857 (Div. 2) A-D
Codeforces Round 857 (Div. 2) A. Likes 求每回合最大的数列:先全使用正数,每个正数对ans++,再全使用负数,每个负数对ans-- 求每回合最小的数列:方法1(模 ...
- linux网络编程中的errno处理
在Linux网络编程中,errno是一个非常重要的变量.它记录了最近发生的系统调用错误代码.在编写网络应用程序时,合理处理errno可以帮助我们更好地了解程序出现的问题并进行调试. 通常,在Linux ...
- Android笔记--图形控制
图形Drawable 形状图形(其定义文件是以shape标签为根节点的XML描述文件,支持四种类型的形状) 具体实现: 在shape标签里面,solid指定填充的颜色,stroke指定边框颜色,cor ...
- Javaweb知识复习--MyBatis+Mapper代理开发
一种持久层框架,主要用于简化JDBC MyBatis应用步骤 1.在数据库里面创建一个表 2.创建模块,导入坐标 就是新建一个Maven项目,在pom.xml里面导入mybatis相应导包依赖代码: ...