Skip to content

快速开始

创建插件需要三个步骤:

  • 构建一个 API
  • OpenAPI 规范格式 的 API 文档文件(yaml 或 JSON 格式)
  • 创建一个 JSON manifest 文件,该文件将定义插件的相关元数据 本节其余部分的重点是通过定义 OpenAPI 规范 和 manifest 文件来创建待办事项列表插件。

插件 manifest​

每个插件都需要一个名为 ai-plugin.json 的文件,该文件需要托管在 API 所在的域名下。例如,一家名为 example.com 的公司将通过 https://example.com 访问插件 JSON 文件,因为这是托管其 API 的地方。当您通过 ChatGPT UI 安装插件时,我们会在后台查找 /.well-known/ai-plugin.json文件。如果未找到该文件,则无法安装插件。

插件的最小定义如下所示:

{  "schema_version": "v1",  "name_for_human": "TODO Plugin",  "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:3333/openapi.yaml",    "is_user_authenticated": false  },  "logo_url": "https://vsq7s0-5001.preview.csb.app/logo.png",  "contact_email": "support@example.com",  "legal_info_url": "http://www.example.com/legal"}

如果您想查看插件文件的所有可能选项,可以参考下面的定义。

田类型描述/选项

schema_versionString清单(manifest)架构版本

name_for_modelString模型将用于定位插件的名称

name_for_humanString人类可读的名称,例如公司全名

description_for_modelString更适合模型的描述,例如令牌上下文长度注意事项或关键字用法,以改进插件提示。

description_for_humanString插件的人类可读描述

authManifestAuth身份验证模式

apiObject接口规范

logo_urlString用于获取插件徽标的网址

contact_emailString用于安全/审核联系、支持和停用的电子邮件联系人

legal_info_urlString重定向 URL,以便用户查看插件信息

HttpAuthorizationTypeHttpAuthorizationType“持有者”或“基本”

ManifestAuthTypeManifestAuthType“无”、“user_http”、“service_http”或“oauth”

interface BaseManifestAuthBaseManifestAuth类型:清单(manifest)身份验证类型;说明:字符串;

ManifestNoAuthManifestNoAuth无需身份验证:BaseManifestAuth & { type: 'none', }

ManifestAuthManifestAuthManifestNoAuth, ManifestServiceHttpAuth, ManifestUserHttpAuth, ManifestOAuthAuth

以下是使用不同身份验证方法的示例:

# App-level API keystype ManifestServiceHttpAuth  = BaseManifestAuth & {  type: 'service_http';  authorization_type: HttpAuthorizationType;  verification_tokens: {    [service: string]?: string;  };}# User-level HTTP authenticationtype ManifestUserHttpAuth  = BaseManifestAuth & {  type: 'user_http';  authorization_type: HttpAuthorizationType;}type ManifestOAuthAuth  = BaseManifestAuth & {  type: 'oauth';  # OAuth URL where a user is directed to for the OAuth authentication flow to begin.  client_url: string;  # OAuth scopes required to accomplish operations on the user's behalf.  scope: string;  # Endpoint used to exchange OAuth code with access token.  authorization_url: string;  # When exchanging OAuth code with access token, the expected header 'content-type'. For example: 'content-type: application/json'  authorization_content_type: string;  # When registering the OAuth client ID and secrets, the plugin service will surface a unique token.  verification_tokens: {    [service: string]?: string;  };}

清单(manifest)文件中某些字段的长度也有一些限制,这些限制在未来可能会变化:

  • name_for_human:最多 50 个字符
  • name_for_model:最多 50 个字符
  • description_for_human:最多 120 个字符
  • description_for_model:最多 8000 个字符(会随着时间的推移而减少) 另外,我们对 API 响应正文长度也有 100k 个字符的限制(会随着时间的推移而减少),这个在未来也可能会变。

OpenAPI 定义​

下一步是使用 OpenAPI 规范 来描述 API 文档。除了 OpenAPI 规范和清单(manifest)文件中定义的内容外,ChatGPT 中的模型对您的 API 一无所知。这意味着,如果您拥有非常多的 API,则无需向模型公开所有 API,只选择开放特定的 API 就行。例如,如果您有一个社交媒体 API,您可能希望模型能通过 GET 请求访问网站内容,但要阻止模型对用户帖子发表评论,以减少垃圾邮件的可能性。

基本的 OpenAPI 规范 如下所示:

openapi: 3.0.1info:  title: TODO Plugin  description: A plugin that allows the user to create and manage a TODO list using ChatGPT.  version: "v1"servers:  - url: http://localhost:3333paths:  /todos:    get:      operationId: getTodos      summary: Get the list of todos      responses:        "200":          description: OK          content:            application/json:              schema:                $ref: "#/components/schemas/getTodosResponse"components:  schemas:    getTodosResponse:      type: object      properties:        todos:          type: array          items:            type: string          description: The list of todos.

我们首先定义规范版本、标题、描述和版本号。在 ChatGPT 中运行查询时,它将查看信息部分中定义的描述,以确定插件是否与用户查询相关。您可以在写作说明部分阅读更多关于提示的信息。

请记住 OpenAPI 规范中的以下限制,这些限制可能会发生变化:

  • API 规范中每个 API Endpoint(指具体的某个 API)节点描述/摘要字段最多 200 个字符
  • API 规范中每个 API 参数描述字段最多 200 个字符 由于我们在本地运行此示例,因此我们希望将服务器设置为指向本地主机 URL。OpenAPI 规范的其余部分遵循传统的 OpenAPI 格式,您可以通过各种在线资源了解有关 OpenAPI 格式的更多信息。还有许多类似 Apifox 这样的工具自动生成 OpenAPI 规范文档。

运行插件​

为您的 API 创建 API、清单(manifest)文件和 OpenAPI 规范后,您现在就可以通过 ChatGPT UI 连接插件了。您的插件可能运行在两个不同的位置,一个是本地开发环境,另一个是远程服务器。

如果您正在运行 API 的本地版本,则可以将插件接口指向该本地设置。要将插件与 ChatGPT 连接,您可以导航到插件市场,然后选择“Install an unverified plugin(安装未经验证的插件)”。

如果插件在远程服务器上运行,则需要首先选择“Develop your own plugin(开发自己的插件)”,然后选择“Install an unverified plugin(安装未经验证的插件)”。您只需将插件清单(manifest)文件添加到 ./well-known 路径并开始测试您的 API。但是,对于清单(manifest)文件的后续更改,您必须将新更改部署到您的公共站点,这可能需要很长时间。在这种情况下,我们建议设置一个本地服务器作为您的 API 的代理。这使您可以快速对 OpenAPI 规范和清单(manifest)文件的更改进行原型设计。

设置公共 API 的本地代理​

以下 Python 代码示例说明了如何设置面向公众的 API 的简单代理。

import requestsimport osimport yamlfrom flask import Flask, jsonify, Response, request, send_from_directoryfrom flask_cors import CORSapp = Flask(__name__)PORT = 3333CORS(app, origins=[f"http://localhost:{PORT}", "https://chat.openai.com"])api_url = 'https://example'@app.route('/.well-known/ai-plugin.json')def serve_manifest():    return send_from_directory(os.path.dirname(__file__), 'ai-plugin.json')@app.route('/openapi.yaml')def serve_openapi_yaml():    with open(os.path.join(os.path.dirname(__file__), 'openapi.yaml'), 'r') as f:        yaml_data = f.read()    yaml_data = yaml.load(yaml_data, Loader=yaml.FullLoader)    return jsonify(yaml_data)@app.route('/openapi.json')def serve_openapi_json():    return send_from_directory(os.path.dirname(__file__), 'openapi.json')@app.route('/<path:path>', methods=['GET', 'POST'])def wrapper(path):    headers = {    'Content-Type': 'application/json',    }    url = f'{api_url}/{path}'    print(f'Forwarding call: {request.method} {path} -> {url}')    if request.method == 'GET':        response = requests.get(url, headers=headers, params=request.args)    elif request.method == 'POST':        print(request.headers)        response = requests.post(url, headers=headers, params=request.args, json=request.json)    else:        raise NotImplementedError(f'Method {request.method} not implemented in wrapper for {path=}')    return response.contentif __name__ == '__main__':    app.run(port=PORT)

撰写说明​

当用户发出可能是对插件的潜在请求的查询时,模型会查看 OpenAPI 规范中 Endpoint(指具体的某个 API)的描述以及清单(manifest)文件中的 description_for_model 。就像提示其他语言模型一样,您需要测试多个提示和描述,看看哪种效果最好。

OpenAPI 规范本身是一个很好的地方,可以为模型提供有关 API 各种细节的信息——可用的功能、参数等。除了为每个字段使用富有表现力、信息丰富的名称外,规范还可以包含“描述”每个属性的字段。例如,这些可用于提供功能的功能或查询字段期望的信息的自然语言描述。该模型将能够看到这些,它们将指导它使用 API。如果一个字段仅限于某些值,您还可以提供一个带有描述性类别名称的“枚举”。

“description_for_model”属性让您可以自由地指导模型一般如何使用您的插件。总体而言,ChatGPT 背后的语言模型能够高度理解自然语言并遵循指令。因此,这是一个很好的地方,可以放置有关插件功能以及模型应如何正确使用它的一般说明。使用自然语言,最好使用简洁但具有描述性和客观性的语气。您可以查看一些示例以了解这应该是什么样子。我们建议 description_for_model 以“Plugin for …”起始 ,然后枚举您的 API 提供的所有功能。

最佳实践​

以下是在 OpenAPI 规范中编写 description_for_model 和描述以及设计 API 响应时要遵循的一些最佳实践:

  • 您的描述不应试图控制 ChatGPT 的情绪、个性或确切反应。ChatGPT 旨在为插件编写适当的响应。

不好的例子:

当用户要求查看他们的待办事项列表时,请始终回复“我能够找到您的待办事项列表!你有 [x] 个待办事项:[在此处列出待办事项]。如果你愿意,我可以添加更多的待办事项!

好例子:

[无需说明]

  • 当用户没有要求您的插件的特定服务类别时,您的描述不应鼓励 ChatGPT 使用该插件。

不好的例子:

每当用户提到任何类型的任务或计划时,询问他们是否要使用 TODOs 插件将某些内容添加到他们的待办事项列表中。

好例子:

TODO 列表可以添加、删除和查看用户的 TODO。

  • 您的描述不应规定 ChatGPT 使用该插件的特定触发器。ChatGPT 旨在在适当的时候自动使用您的插件。

不好的例子:

当用户提到任务时,请回复“您是否希望我将其添加到您的待办事项列表中?说'是'继续。

好例子:

[无需说明]

  • 插件 API 响应应返回原始数据而不是自然语言响应(除非确实有必要)。ChatGPT 将使用返回的数据提供自己的自然语言响应。

不好的例子:

我能够找到你的待办事项清单(manifest)!您有 2 个待办事项:买杂货和遛狗。如果您愿意,我可以添加更多待办事项!

好例子:

{"todos":["买杂货","遛狗"]}

调试​

默认情况下,聊天不会显示插件调用和其他未向用户显示的信息。为了更全面地了解模型如何与您的插件交互,您可以通过单击屏幕左下角的“Debug”按钮打开调试窗口。这将打开到目前为止对话的原始文本,包括插件调用和响应。

对插件的模型调用通常包括来自模型(“助手”)的消息,其中包含发送到插件的类似 JSON 的参数,然后是来自插件(“工具”)的响应,最后是来自利用插件返回的信息的模型。

在某些情况下,例如在插件安装期间,错误可能会出现在浏览器的 javascript 控制台中。