转载

OpenAi的聊天插件开始

创建插件需要 3 个步骤:

  1. 构建接口
  2. 以 OpenAPI yaml 或 JSON 格式记录 API
  3. 创建一个 JSON 清单文件,该文件将定义插件的相关元数据

本节其余部分的重点是通过定义 OpenAPI 规范和清单文件来创建待办事项列表插件。

探索示例插件
探索涵盖多个用例和身份验证方法的示例插件。

插件清单

每个插件都需要一个ai-plugin.json文件,该文件需要托管在API的域中。例如,一家名为example.com的公司会通过https://example.com因为这是他们的API所在的域。当您通过ChatGPT UI安装插件时,我们会在后端查找位于/.airknown/ai-plugin.json的文件。/.airnowledge文件夹是必需的,并且必须存在于您的域中,以便ChatGPT与您的插件连接。如果找不到文件,则无法安装插件。对于本地开发,可以使用HTTP,但如果指向远程服务器,则需要HTTPS。

所需文件的最小定义如下所示: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": "http://localhost:3333/logo.png", "contact_email": "support@example.com", "legal_info_url": "http://www.example.com/legal" }

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

类型描述/选项必填
schema_version字符串清单架构版本
name_for_model字符串模型将用于定位插件的名称
name_for_human字符串人类可读的名称,例如公司全名
description_for_model字符串更适合模型的描述,例如令牌上下文长度注意事项或关键字用法,以改进插件提示。
description_for_human字符串插件的人类可读描述
auth清单身份验证身份验证架构
api对象接口规范
logo_url字符串用于获取插件徽标的网址
contact_email字符串用于安全/审核联系、支持和停用的电子邮件联系人
legal_info_url字符串重定向 URL,以便用户查看插件信息
HttpAuthorizationTypeHttpAuthorizationType“持有者”或“基本”
ManifestAuthType清单身份验证类型“无”、“user_http”、“service_http”或“oauth”
interface基本清单身份验证基本清单身份验证类型:清单身份验证类型;说明:字符串;
ManifestNoAuth清单编号身份验证无需身份验证:BaseManifestAuth & { type: 'none', }
ManifestAuth清单身份验证ManifestNoAuth, 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; }; }

清单文件中某些字段的长度也有一些限制,这些限制可能会随着时间的推移而发生变化:

  • 最多 50 个字符name_for_human
  • 最多 50 个字符name_for_model
  • 最多 120 个字符description_for_human
  • 最多 8000 个字符(会随着时间的推移而减少)description_for_model

另外,我们对 API 响应正文长度也有 100k 个字符的限制(会随着时间的推移而减少),这也可能会发生变化。

开放接口定义

下一步是构建 OpenAPI 规范来记录 API。ChatGPT 中的模型除了 OpenAPI 规范和清单文件中定义的内容外,对你的 API 一无所知。这意味着,如果您拥有广泛的 API,则无需向模型公开所有功能,并且可以选择特定的终结点。例如,如果你有一个社交媒体 API,你可能希望模型通过 GET 请求访问站点中的内容,但阻止模型对用户帖子发表评论,以减少垃圾邮件的机会。

OpenAPI 规范是位于 API 之上的包装器。基本的 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 终端节点描述/摘要字段最多 200 个字符
  • API 规范中每个 API 参数描述字段最多 200 个字符

由于我们在本地运行此示例,因此我们希望将服务器设置为指向您的本地主机 URL。OpenAPI 规范的其余部分遵循传统的 OpenAPI 格式,您可以通过各种在线资源了解有关 OpenAPI 格式的更多信息。还有许多工具可以根据您的底层 API 代码自动生成 OpenAPI 规范。

运行插件

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

如果您正在运行 API 的本地版本,则可以将插件接口指向本地主机服务器。要将插件与 ChatGPT 连接,请导航到插件商店并选择“开发您自己的插件”。输入您的本地主机和端口号(例如 )。请注意,本地主机开发目前仅支持身份验证类型。localhost:3333none

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

设置公共 API 的本地代理

The following Python code is an example of how you can set up a simple proxy of your public facing 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 # Note: Setting CORS to allow chat.openapi.com is required for ChatGPT to access your plugin CORS(app, origins=[f"http://localhost:{PORT}", "https://chat.openai.com"]) api_url = 'https://example.com' @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 规范中description_for_model终结点的描述以及清单文件中的描述。就像提示其他语言模型一样,您需要测试多个提示和描述,以查看哪种效果最好。

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

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

最佳实践

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

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

    不好的例子

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

    好例子

    [无需说明]

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

    不好的例子

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

    好例子

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

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

    不好的例子

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

    好例子

    [无需说明]

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

    不好的例子

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

    好例子

    { “待办事项”: [ “买杂货”, “遛狗” ] }

调试

默认情况下,聊天不会显示插件调用和其他未向用户显示的信息。为了更全面地了解模型如何与您的插件交互,您可以在与插件交互后通过单击插件名称上的向下箭头来查看请求和响应。

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

如果您正在开发本地主机插件,您还可以通过转到“设置”并切换“打开插件开发工具”来打开开发人员控制台。从那里,您可以看到更详细的日志和“刷新插件”,它们会重新获取插件和 OpenAPI 规范。