1、前言
5月13日早上醒来发现ChatGPT官网迎来了一波更新,页面有所调整,而且在settings页面有了关于插件配置的切换。
如图所示OpenAI官网发布,将在下周针对所有ChatGPT Plus用户推出网络浏览和插件权限。我的猜测是一方面最近谷歌AI的发布会可以访问互联网,访问插件等等,如果真如发布会,那比3月份发布时的提升真的太大了,以claude.ai 宣布将文本上下文限制从 9K 扩展到 100K!而且在3月中旬发布ChatGPT-4模型后,新东西出来也比较慢了,种种迹象都在表明OpenAI也面临着一点点的压力。
希望多几家能与OpenAI公司竞争的企业,这样才能促进OpenAI更强劲的爆发。 5月12日拿到了插件开发的权限,当天工作比较忙,就没时间来尝试,于是今天使用了一下。接下来,我会根据我的使用情况来学习一下ChatGPT Plugins官网的插件开发机制。官网的插件我昨天也体验了一番效果还是非常棒的,有兴趣的可以来看看我的体验文章 mp.weixin.qq.com/s/SKycfpMMR… 。
2、ChatGPT Plugins插件
目前看官网的插件如雨后春笋,感觉很快会迎来一波量的变化,昨天上午看还是四十几个,今天看就是54个。下周可能所有Plus用户都可以体验插件,将会对插件迎来一波压力。 看到了自己有了插件的开发权限,于是就顺手来体验一下,看看插件到底是怎么开发出来的呢
OpenAI的插件将ChatGPT连接到第三方应用程序。这些插件使 ChatGPT 能够与开发人员定义的 API 进行交互,从而增强 ChatGPT 的功能并允许它执行广泛的操作,例如:
- 检索实时信息;例如,体育比分、股票价格、最新消息等。
- 检索知识库信息;例如,公司文档、个人笔记等。
- 代表用户执行操作;例如,预订航班、订购食物等。
- 。。。。。。
3、上手调试体验插件
3.1、找到测试项目
首先我直接来到OpenAI的官网 platform.openai.com/docs/plugin… 。 发现demo例子的第一个就是一个最简单的仓库。
看到了 Plugin quickstart,顺手找到了github github.com/openai/plug… 一看是OpenAI官网开源的,啥也不说了,直接git clone开撸代码吧。
3.2、下载运行项目
将项目下载到本地之后,便按照readme进行安装即可
- 3.2.1、首先保证python已经在本机安装
python --version
pip -V
- 3.2.2、 安装依赖
pip install -r requirements.txt
- 3.2.3、运行调试项目
python main.py
- 3.2.4、对接ChatGPT 官网
然后将 localhost:5003 输入到domain中,然后右下角点击。
再点击安装,到Chat便可以选择插件进行聊天使用了
4、尝试使用自己的插件
查看跟插件进行对话是成功的。
再来查看调试日志
通过本地接口也可以获取数据了
基本上已经证明我们的插件调试成功了。
最后突然想到自然语言运用恰当直接操作选择数据接口,有利有弊吧。
5、项目结构解析
如上图所示,我标注箭头的文件大家看了基本都懂,可以忽略了。重要文件就三个
- .wll-known/ai-plugin.json
- openapi.yaml
- main.py
5、1 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:5003/openapi.yaml",
"is_user_authenticated": false
},
"logo_url": "http://localhost:5003/logo.png",
"contact_email": "legal@example.com",
"legal_info_url": "http://example.com/legal"
}
这里最重要的一个配置便是:auth:身份验证架构 ("type": "none") 。
我上面使用的便是没有身份验证的机制,如果我们的插件api接口时面向所有用户开发,需要身份的验证,这里便可以这样设置。如果需要身份验证可以设置为("type": "service_http"),这里就简单一提,留给后面再仔细学习。
5.2、openapi.yaml
openapi: 3.0.1
info:
title: TODO Plugin
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'
servers:
- url: http://localhost:5003
paths:
/todos/{username}:
get:
operationId: getTodos
summary: Get the list of todos
parameters:
- in: path
name: username
schema:
type: string
required: true
description: The name of the user.
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/getTodosResponse'
post:
operationId: addTodo
summary: Add a todo to the list
parameters:
- in: path
name: username
schema:
type: string
required: true
description: The name of the user.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/addTodoRequest'
responses:
"200":
description: OK
delete:
operationId: deleteTodo
summary: Delete a todo from the list
parameters:
- in: path
name: username
schema:
type: string
required: true
description: The name of the user.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/deleteTodoRequest'
responses:
"200":
description: OK
components:
schemas:
getTodosResponse:
type: object
properties:
todos:
type: array
items:
type: string
description: The list of todos.
addTodoRequest:
type: object
required:
- todo
properties:
todo:
type: string
description: The todo to add to the list.
required: true
deleteTodoRequest:
type: object
required:
- todo_idx
properties:
todo_idx:
type: integer
description: The index of the todo to delete.
required: true
简单看到下面这个文件,感觉就是openai定义的一套接口规范,插件的接口需要按照这样的规范来定义。 而且这里的规范,要跟代码里实现的接口要保持一致。下面来看看代码
5.3、main.py
import json
import quart
import quart_cors
from quart import request
app = quart_cors.cors(quart.Quart(__name__), allow_origin="https://chat.openai.com")
# Keep track of todo's. Does not persist if Python session is restarted.
_TODOS = {}
@app.post("/todos/<string:username>")
async def add_todo(username):
request = await quart.request.get_json(force=True)
if username not in _TODOS:
_TODOS[username] = []
_TODOS[username].append(request["todo"])
print(_TODOS)
return quart.Response(response='OK', status=200)
@app.get("/todos/<string:username>")
async def get_todos(username):
print(username)
todos = _TODOS.get(username, [])
print(todos)
return quart.Response(response=json.dumps(_TODOS.get(username, [])), status=200)
@app.delete("/todos/<string:username>")
async def delete_todo(username):
request = await quart.request.get_json(force=True)
todo_idx = request["todo_idx"]
# fail silently, it's a simple plugin
if 0 <= todo_idx < len(_TODOS[username]):
_TODOS[username].pop(todo_idx)
return quart.Response(response='OK', status=200)
@app.get("/logo.png")
async def plugin_logo():
filename = 'logo.png'
return await quart.send_file(filename, mimetype='image/png')
@app.get("/.well-known/ai-plugin.json")
async def plugin_manifest():
host = request.headers['Host']
with open("./.well-known/ai-plugin.json") as f:
text = f.read()
return quart.Response(text, mimetype="text/json")
@app.get("/openapi.yaml")
async def openapi_spec():
host = request.headers['Host']
with open("openapi.yaml") as f:
text = f.read()
return quart.Response(text, mimetype="text/yaml")
def main():
app.run(debug=True, host="localhost", port=5003)
if __name__ == "__main__":
main()
代码实现的思路大致如下:
这段代码是一个基于 Quart 和 Quart-CORS 的简单的 RESTful API 服务器,用于处理待办事项(todo)数据的 CRUD 操作(创建、读取、更新、删除)。Quart 是一个 Python 的异步 web 框架,相当于异步版本的 Flask。Quart-CORS 是一个用于处理跨源资源共享(CORS)的库。
下面是每段代码的简要解释:
-
导入模块:
quart:Quart 框架的主要模块,用于创建和管理 web 应用。quart_cors:用于处理跨域资源共享 (CORS) 的 Quart 扩展。json:用于处理 JSON 数据的 Python 标准库。
-
初始化应用:
app = quart_cors.cors(quart.Quart(__name__), allow_origin="https://chat.openai.com")
这里创建了一个 Quart 应用并允许来自 "chat.openai.com" 的跨源请求。
-
定义一个全局的
_TODOS字典,用于存储各用户的待办事项列表。 -
定义 API 路由:
@app.post("/todos/<string:username>"):添加待办事项。此 API 通过 POST 请求接受新的待办事项,并将其添加到特定用户的待办事项列表中。@app.get("/todos/<string:username>"):获取待办事项。此 API 通过 GET 请求返回特定用户的所有待办事项。@app.delete("/todos/<string:username>"):删除待办事项。此 API 通过 DELETE 请求和待办事项的索引来删除特定用户的一个待办事项。
-
为插件提供的其他路由:
@app.get("/logo.png"):返回一个 logo 文件。@app.get("/.well-known/ai-plugin.json"):返回插件的 manifest 文件。这是一个包含插件元数据的 JSON 文件,如插件名、版本、描述等。@app.get("/openapi.yaml"):返回 OpenAPI 规范文件。OpenAPI 是一个用于描述和文档化 RESTful API 的规范。
-
定义主函数:
- 这个函数会在文件被作为脚本直接运行时启动 Quart 服务器。
总的来说,这段代码为一个基于用户的待办事项应用程序提供了一个 RESTful API。通过这些 API,应用程序可以添加、获取和删除待办事项。
6、总结
通过这个文章相信你对插件的开发应该没那么畏惧了,等待ChatGPT下周的更新所有Plus用户都会开始使用插件了,如果你有什么灵感也可以告诉我,我来实现你心目中的插件,来更好的辅助你完成你手头上需要处理的工作。
通过上面的代码也可以看到,是通过python语言进行实现插件的,但是通过代码实现我发现,通过go语言或者java、.net core、nodejs、php等语言应该都可以实现插件的,不出意外下周开始讨论插件的日子应该到来了,群里的人可能会问处理这个问题可以用那个插件。
更多插件玩法可以参考 github.com/openai/chat…
插件文档地址可以参考 platform.openai.com/docs/plugin…
本文参考的代码仓库是 github.com/openai/plug…
后面我会持续更新我对插件使用的总结。欢迎有兴趣的一起来学习。