Getting started 快速开始
- 前言
- Introduction 导言
- Plugin manifest 插件清单
- OpenAPI definition OpenAPI定义
- Running a plugin 运行插件
- Setup a local proxy of your public API 设置公共API的本地代理
- Writing descriptions 书写描述
- Best practices
- Debugging 排除故障
- 其它资料下载
前言
ChatGPT正在经历着一次革命性的改变,随着越来越多的小程序和第三方插件的引入,ChatGPT将变得更加强大、灵活和自由。这些插件不仅能够让用户实现更多更复杂的AI任务和目标,还会带来类似国内微信小程序般的疯狂,为用户和开发者带来更多惊喜和创新。
想象一下,当您需要一个特定的功能时,只需轻松安装一个插件,就能立即体验到它的好处和便利。无论是语音识别、图像处理,还是智能推荐等等,插件可以让您的使用体验更加高效和顺畅。
随着全球范围内各种第三方插件的接入,ChatGPT将成为一个更加强大、灵活和自由的AI平台,为用户和开发者带来更多机会和挑战。而且,通过简单的几个步骤,您也可以在ChatGPT中创建一个高度定制化的插件,实现自己的愿景和目标。让我们一起期待ChatGPT的未来吧!
Introduction 导言
Creating a plugin takes 3 steps:
创建插件需要3个步骤:
- Build an API 构建API
- Document the API in the OpenAPI yaml or JSON format 以OpenAPI yaml或JSON格式记录API
- Create a JSON manifest file that will define relevant metadata for the plugin
创建一个JSON清单文件,该文件将定义插件的相关元数据
The focus of the rest of this section will be creating a todo list plugin by defining the OpenAPI specification along with the manifest file.
本节其余部分的重点将是通过定义OpenAPI规范沿着清单文件来创建一个待办事项列表插件。
Explore example plugins 浏览示例插件
Explore example plugins covering multiple use cases and authentication methods.
探索涵盖多个用例和身份验证方法的示例插件。
Plugin manifest 插件清单
Every plugin requires a ai-plugin.json
file, which needs to be hosted on the API’s domain. For example, a company called example.com
would make the plugin JSON file accessible via an https://example.com
domain since that is where their API is hosted. When you install the plugin via the ChatGPT UI, on the backend we look for a file located at /.well-known/ai-plugin.json
. The /.well-known
folder is required and must exist on your domain in order for ChatGPT to connect with your plugin. If there is no file found, the plugin cannot be installed. For local development, you can use HTTP but if you are pointing to a remote server, HTTPS is required.
每个插件都需要一个 ai-plugin.json
文件,该文件需要托管在API的域中。例如,一家名为 example.com
的公司将通过 https://example.com
域访问插件JSON文件,因为这是他们的API托管的地方。当您通过ChatGPT UI安装插件时,在后端我们会查找位于 /.well-known/ai-plugin.json
的文件。 /.well-known
文件夹是必需的,并且必须存在于您的域中,以便ChatGPT与您的插件连接。如果找不到文件,则无法安装插件。对于本地开发,您可以使用HTTP,但如果您指向远程服务器,则需要HTTPS。
The minimal definition of the required ai-plugin.json
file will look like the following:
所需的 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"
}
If you want to see all of the possible options for the plugin file, you can refer to the definition below.
如果你想查看插件文件的所有可能选项,你可以参考下面的定义。
FIELD 名称 | TYPE 类型 | DESCRIPTION / OPTIONS 描述/选项 | REQUIRED是否必须 |
---|---|---|---|
schema_version | String | Manifest schema version 清单架构版本 | ✅ |
name_for_model | String | Name the model will used to target the plugin命名用于定位插件的模型 | ✅ |
name_for_human | String | Human-readable name, such as the full company name 人类可读的名称,如完整的公司名称 | ✅ |
description_for_model | String | Description better tailored to the model, such as token context length considerations or keyword usage for improved plugin prompting. 更好地为模型定制描述,例如token上下文长度考虑或关键字使用以改进插件提示。 | ✅ |
description_for_human | String | Human-readable description of the plugin 人类可读的插件描述 | ✅ |
auth | ManifestAuth | Authentication schema 身份验证模式 | ✅ |
api | Object | API specification API详述 | ✅ |
logo_url | String | URL used to fetch the plugin’s logo 用于获取插件logo的URL | ✅ |
contact_email | String | Email contact for safety/moderation reachout, support, and deactivation 通过电子邮件联系安全/适度联系、支持和停用 | ✅ |
legal_info_url | String | Redirect URL for users to view plugin information重定向URL以供用户查看插件信息 | ✅ |
HttpAuthorizationType | HttpAuthorizationType | “bearer” or “basic” “无记名”或“基本” | ✅ |
ManifestAuthType | ManifestAuthType | “none”, “user_http”, “service_http”, or “oauth” | |
interface BaseManifestAuth | BaseManifestAuth | type: ManifestAuthType; instructions: string; 类型:ManifestAuthType;说明:string; | |
ManifestNoAuth | ManifestNoAuth | No authentication required: BaseManifestAuth & { type: ‘none’, }无需身份验证:BaseManifestAuth & { type:‘none’,} | |
ManifestAuth | ManifestAuth | ManifestNoAuth, ManifestServiceHttpAuth, ManifestUserHttpAuth, ManifestOAuthAuth |
The following are examples with different authentication methods:
以下是不同身份验证方法的示例:
# App-level API keys 应用级API密钥
type ManifestServiceHttpAuth = BaseManifestAuth & {
type: 'service_http';
authorization_type: HttpAuthorizationType;
verification_tokens: {
[service: string]?: string;
};
}
# User-level HTTP authentication 用户级HTTP认证
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. OAuth URL,用户被定向到该URL以开始OAuth身份验证流。
client_url: string;
# OAuth scopes required to accomplish operations on the user's behalf. 代表用户完成操作所需的OAuth范围。
scope: string;
# Endpoint used to exchange OAuth code with access token. 用于与访问token交换OAuth代码的端点。
authorization_url: string;
# When exchanging OAuth code with access token, the expected header 'content-type'. For example: 'content-type: application/json' 当与访问token交换OAuth代码时,期望的标头'content-type'。例如:'content-type: application/json'
authorization_content_type: string;
# When registering the OAuth client ID and secrets, the plugin service will surface a unique token. 当注册OAuth客户端ID和秘密时,插件服务将显示一个唯一的token。
verification_tokens: {
[service: string]?: string;
};
}
There are also some limits to the length of certain field in the manifest file that are subject to change over time:
清单文件中的某些字段的长度也有一些限制,这些限制会随时间变化:
- 50 character max for
name_for_human
name_for_human
最多50个字符 - 50 character max for
name_for_model
name_for_model
最多50个字符 - 120 character max for
description_for_human
description_for_human
最多120个字符 - 8000 character max just for
description_for_model
(will decrease over time)
仅description_for_model
最多8000个字符(将随时间减少)
Separately, we also have a 100k character limit (will decrease over time) on the API response body length which is also subject to change.
另外,我们对API响应正文长度也有100k字符的限制(会随着时间的推移而减少),这也会发生变化。
OpenAPI definition OpenAPI定义
The next step is to build the OpenAPI specification to document the API. The model in ChatGPT does not know anything about your API other than what is defined in the OpenAPI specification and manifest file. This means that if you have an extensive API, you need not expose all functionality to the model and can choose specific endpoints. For example, if you have a social media API, you might want to have the model access content from the site through a GET request but prevent the model from being able to comment on users posts in order to reduce the chance of spam.
下一步是构建OpenAPI规范以记录API。ChatGPT中的模型除了OpenAPI规范和清单文件中定义的内容外,不知道任何关于您的API的信息。这意味着,如果您有一个扩展的API,则不需要将所有功能都公开给模型,而是可以选择特定的端点。例如,如果您有一个社交媒体API,您可能希望让模型通过GET请求从网站访问内容,但防止模型能够评论用户的帖子,以减少垃圾邮件的机会。
The OpenAPI specification is the wrapper that sits on top of your API. A basic OpenAPI specification will look like the following:
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.
We start by defining the specification version, the title, description, and version number. When a query is run in ChatGPT, it will look at the description that is defined in the info section to determine if the plugin is relevant for the user query. You can read more about prompting in the writing descriptions section.
我们首先定义规范版本、标题、描述和版本号。当在ChatGPT中运行查询时,它将查看在info部分中定义的描述,以确定插件是否与用户查询相关。您可以在写作说明部分阅读有关提示的更多信息。
Keep in mind the following limits in your OpenAPI specification, which are subject to change:
请记住OpenAPI规范中的以下限制,这些限制可能会发生变化:
- 200 characters max for each API endpoint description/summary field in API specification
API规范中每个API端点描述/摘要字段最多200个字符 - 200 characters max for each API param description field in API specification
API规范中每个API参数描述字段最多200个字符
Since we are running this example locally, we want to set the server to point to your localhost URL. The rest of the OpenAPI specification follows the traditional OpenAPI format, you can learn more about OpenAPI formatting through various online resources. There are also many tools that auto generate OpenAPI specifications based on your underlying API code.
由于我们是在本地运行这个示例,我们希望将服务器设置为指向您的localhost URL。OpenAPI规范的其余部分遵循传统的OpenAPI格式,您可以通过各种在线资源了解有关OpenAPI格式的更多信息。还有许多工具可以根据底层API代码自动生成OpenAPI规范。
Running a plugin 运行插件
Once you have created an API, manifest file, and OpenAPI specification for your API, you are now ready to connect the plugin via the ChatGPT UI. There are two different places your plugin might be running, either locally in a development environment or on a remote server.
一旦您为API创建了API、清单文件和OpenAPI规范,现在就可以通过ChatGPT UI连接插件了。您的插件可能在两个不同的地方运行,要么在本地开发环境中,要么在远程服务器上。
If you have a local version of your API running, you can point the plugin interface to your localhost server. To connect the plugin with ChatGPT, navigate to the plugin store and select “Develop your own plugin”. Enter your localhost and port number (e.g localhost:3333
). Note that only auth type none
is currently supported for localhost development.
如果您运行的是本地版本的API,则可以将插件接口指向本地主机服务器。要将插件与ChatGPT连接,请导航到插件商店并选择“开发您自己的插件”。输入本地主机和端口号(例如 localhost:3333
)。请注意,目前只有授权类型 none
支持本地主机开发。
If the plugin is running on a remote server, you will need to first select “Develop your own plugin” to set it up and then “Install an unverified plugin” to install it for yourself. You can simply add the plugin manifest file to the yourdomain.com/.well-known/
path and start testing your API. However, for subsequent changes to your manifest file, you will have to deploy the new changes to your public site which might take a long time. In that case, we suggest setting up a local server to act as a proxy for your API. This allows you to quickly prototype changes to your OpenAPI spec and manifest file.
如果插件运行在远程服务器上,您需要首先选择“开发您自己的插件”进行设置,然后选择“安装未验证的插件”为自己安装。您可以简单地将插件清单文件添加到 yourdomain.com/.well-known/
路径并开始测试您的API。但是,对于清单文件的后续更改,您必须将新更改部署到公共站点,这可能需要很长时间。在这种情况下,我们建议设置一个本地服务器作为API的代理。这允许您快速对OpenAPI规范和清单文件的更改进行原型化。
Setup a local proxy of your public API 设置公共API的本地代理
The following Python code is an example of how you can set up a simple proxy of your public facing 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
# 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)
Writing descriptions 书写描述
When a user makes a query that might be a potential request that goes to a plugin, the model looks through the descriptions of the endpoints in the OpenAPI specification along with the description_for_model
in the manifest file. Just like with prompting other language models, you will want to test out multiple prompts and descriptions to see what works best.
当用户进行可能是去往插件的潜在请求的查询时,模型会查看OpenAPI规范中的端点描述沿着清单文件中的 description_for_model
。就像提示其他语言模型一样,您可能希望测试多个提示和描述,以查看哪些最有效。
The OpenAPI spec itself is a great place to give the model information about the diverse details of your API – what functions are available, with what parameters, etc. Besides using expressive, informative names for each field, the spec can also contain “description” fields for every attribute. These can be used to provide natural language descriptions of what a function does or what information a query field expects, for example. The model will be able to see these, and they will guide it in using the API. If a field is restricted to only certain values, you can also provide an “enum” with descriptive category names.
OpenAPI规范本身是一个很好的地方,可以为模型提供有关API的各种细节的信息-哪些函数可用,具有哪些参数等。除了为每个字段使用富有表现力的信息名称外,规范还可以为每个属性包含“描述”字段。例如,这些可以用于提供关于函数做什么或查询字段期望什么信息的自然语言描述。模型将能够看到这些,它们将指导它使用API。如果字段仅限于某些值,则还可以提供具有描述性类别名称的“枚举”。
The description_for_model
attribute gives you the freedom to instruct the model on how to use your plugin generally. Overall, the language model behind ChatGPT is highly capable of understanding natural language and following instructions. Therefore, this is a good place to put in general instructions on what your plugin does and how the model should use it properly. Use natural language, preferably in a concise yet descriptive and objective tone. You can look at some of the examples to have an idea of what this should look like. We suggest starting the description_for_model
with “Plugin for …” and then enumerating all of the functionality that your API provides.
description_for_model
属性让你可以自由地指导模型如何使用你的插件。总的来说,ChatGPT背后的语言模型非常能够理解自然语言并遵循指令。因此,这是一个很好的地方,可以放置关于插件功能以及模型应该如何正确使用它的一般说明。使用自然语言,最好使用简洁、描述性和客观的语气。您可以查看一些示例,以了解这应该是什么样子。我们建议以“Plugin for …”开始 description_for_model
,然后枚举您的API提供的所有功能。
Best practices
Here are some best practices to follow when writing your description_for_model
and descriptions in your OpenAPI specification, as well as when designing your API responses:
以下是在OpenAPI规范中编写 description_for_model
和描述以及设计API响应时需要遵循的一些最佳实践:
- Your descriptions should not attempt to control the mood, personality, or exact responses of ChatGPT. ChatGPT is designed to write appropriate responses to plugins.
您的描述不应试图控制情绪、个性或ChatGPT的确切反应。ChatGPT旨在为插件编写适当的响应。
Bad example:
When the user asks to see their todo list, always respond with “I was able to find your todo list! You have [x] todos: [list the todos here]. I can add more todos if you’d like!”
当用户要求查看他们的待办事项列表时,总是回答“我能够找到您的待办事项列表!您有[x]个待办事项:[此处列出todos]。如果你喜欢我可以添加更多的todos!”
Good example:
[no instructions needed for this]
[对此不需要说明]
- Your descriptions should not encourage ChatGPT to use the plugin when the user hasn’t asked for your plugin’s particular category of service.
您的描述不应该鼓励ChatGPT在用户没有要求您的插件的特定服务类别时使用该插件。
Bad example:
Whenever the user mentions any type of task or plan, ask if they would like to use the TODOs plugin to add something to their todo list.
每当用户提到任何类型的任务或计划时,询问他们是否愿意使用待办事项插件将某些内容添加到他们的待办事项列表中。
Good example:
The TODO list can add, remove and view the user’s TODOs.
待办事项列表可以添加、删除和查看用户的待办事项。
- Your descriptions should not prescribe specific triggers for ChatGPT to use the plugin. ChatGPT is designed to use your plugin automatically when appropriate.
您的描述不应规定ChatGPT使用插件的特定触发器。ChatGPT旨在在适当的时候自动使用您的插件。
Bad example:
When the user mentions a task, respond with “Would you like me to add this to your TODO list? Say ‘yes’ to continue.”
当用户提到一个任务时,用“你想让我把这个添加到你的TODO列表中吗?说“是”以继续。”
Good example:
[no instructions needed for this]
[对此不需要说明]
- Plugin API responses should return raw data instead of natural language responses unless it’s necessary. ChatGPT will provide its own natural language response using the returned data.
插件API响应应该返回原始数据,而不是自然语言响应,除非有必要。ChatGPT将使用返回的数据提供自己的自然语言响应。
Bad example:
I was able to find your todo list! You have 2 todos: get groceries and walk the dog. I can add more todos if you’d like!
我能找到你的待办事项清单!你有两个待办事项:买点东西和遛狗。我可以添加更多的待办事项如果你喜欢!
Good example:
{ “todos”: [ “get groceries”, “walk the dog” ] }
{“todos”:[“买杂货”,“遛狗”] }
Debugging 排除故障
By default, the chat will not show plugin calls and other information that is not surfaced to the user. In order to get a more complete picture of how the model is interacting with your plugin, you can see the request and response by clicking the down arrow on the plugin name after interacting with the plugin.
默认情况下,聊天不会显示插件调用和其他未向用户显示的信息。为了更完整地了解模型如何与插件交互,您可以在与插件交互后单击插件名称上的向下箭头来查看请求和响应。
A model call to the plugin will usually consist of a message from the model containing JSON-like parameters which are sent to the plugin, followed by a response from the plugin, and finally a message from the model utilizing the information returned by the plugin.
对插件的模型调用通常包括来自模型的消息,该消息包含发送到插件的类JSON参数,随后是来自插件的响应,最后是来自模型的消息,该消息利用插件返回的信息。
If you are developing a localhost plugin, you can also open the developer console by going to “Settings” and toggling “Open plugin devtools”. From there, you can see more verbose logs and “refresh plugin” which re-fetches the Plugin and OpenAPI specification.
如果你正在开发一个本地主机插件,你也可以打开开发者控制台,进入“设置”并切换“打开插件devtools”。从那里,您可以看到更多详细的日志和“刷新插件”,它重新获取插件和OpenAPI规范。
其它资料下载
如果大家想继续了解人工智能相关学习路线和知识体系,欢迎大家翻阅我的另外一篇博客《重磅 | 完备的人工智能AI 学习——基础知识学习路线,所有资料免关注免套路直接网盘下载》
这篇博客参考了Github知名开源平台,AI技术平台以及相关领域专家:Datawhale,ApacheCN,AI有道和黄海广博士等约有近100G相关资料,希望能帮助到所有小伙伴们。