跳到主要内容

快速开始

创建插件需要三个步骤:

  • 构建一个 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 keys
type ManifestServiceHttpAuth = BaseManifestAuth & {
type: 'service_http';
authorization_type: HttpAuthorizationType;
verification_tokens: {
[service: string]?: string;
};
}

# User-level HTTP authentication
type 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.1
info:
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:3333
paths:
/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 requests
import os

import yaml
from flask import Flask, jsonify, Response, request, send_from_directory
from flask_cors import CORS

app = Flask(__name__)

PORT = 3333
CORS(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.content


if __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 响应时要遵循的一些最佳实践:

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

    不好的例子

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

    好例子

    [无需说明]

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

    不好的例子

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

    好例子

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

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

    不好的例子

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

    好例子

    [无需说明]

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

    不好的例子

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

    好例子

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

调试

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

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

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