前言
這是一篇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": "[email protected]",
"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
如果你覺得本篇文章對您有幫助的話,感謝您的【推薦】。