我们的概念验证的技术探索和能力
OpenAI最近宣布支持ChatGPT的插件。插件是ChatGPT的一个突破性功能,因为它们解决了平台最大的问题之一,即缺乏对互联网的访问和最新的内容。ChatGPT是在2021年的数据集上训练的,不能直接访问互联网。插件为这个限制提供了一个解决方案。像Medium这样的内容平台可以将他们的内容暴露给ChatGPT,根据用户的提示和安装的插件,ChatGPT可以触发你的插件的正确API来检索一段内容并对其进行一些操作。
对Chat GPT的插件支持仍处于私人alpha阶段,我们在Medium获得了早期访问权,所以我们可以探索我们的内容可以被ChatGPT检索的可能性。
我想指出的是,这是一个技术探索,到目前为止,我们还没有发布这个插件的计划。
这篇文章围绕着技术演示方面的事情,我们如何建立它,ChatGPT插件如何工作以及我们的插件能做什么。
🤖 我们的设置
建立一个ChatGPT插件是相当简单的,你需要在你的域名上公开一个.well-known/ai-plugin.json 。它提供了基本信息,以便ChatGPT能够理解你的域名支持插件,并能在安装插件时将适当的描述、图标、链接等链接给终端用户。
{
"schema_version": "v1",
"name_for_human": "Medium plugin",
"name_for_model": "MediumGPTPlugin",
"description_for_human": "Plugin for accessing, browsing and extracting Medium content.",
"description_for_model": "Requests Medium posts, stories, to do manipulation and queries on the content.",
"auth": {
"type": "none"
},
"api": {
"type": "openapi",
"url": "https://medium.com/_/gpt/openapi.yaml",
"is_user_authenticated": false
},
"logo_url": "https://miro.medium.com/v2/1*m-R_BkNf1Qjr1YbyOIJY2w.png",
"contact_email": "support@medium.com",
"legal_info_url": "https://policy.medium.com/medium-terms-of-service-9db0094a1e0f"
}
最重要的部分是你要公开的OpenAPI YAML文件,你可以在上面的代码片段中的url字段看到我们的文件。这是一个规范,将允许ChatGPT理解你的API。它使用OpenAPI规范,你实际上可以在那里开始写你的规范,然后你可以把规范导出到各种语言的服务器接口。那里也有一个linter,所以你可以确保你的API规范是正确的。
在我这边,我实际上是在用Go编写MediumGPT服务(我们Medium的大多数微服务都是用Go编写的),我做了什么来实际编写OpenAPI规范?我把我的Go代码粘贴到ChatGPT中,要求它输出OpenAPI规范。令人惊讶的是,它非常完美,只需做一些修改,基本上就可以了。
你可能会问,为什么我们需要一个新的服务?我们有一个GraphQL的内部API,但ChatGPT并不能真正与GraphQL API对话(也许在未来,一个记录良好的模式听起来非常强大),所以我需要在Go中制作一个中间件,将它的一部分作为标准的REST API公开。
MediumGPT微服务是一个简单的中间件,它可以转换硬编码的GraphQL查询,并将其作为JSON结果在REST API中公开。简单明了,对于概念验证来说足够简单。对我来说也很简单,因为这是我第一次为我们的后端编写Go代码😎。
为了给你一个概念,这里是我们的一个桥接函数,为趋势帖子服务,看起来像:
type Post struct {
ID string json:"id"
Title string json:"title"
// ... More Post object fields
}
func (a *App) Trending(ctx context.Context) ([]*model.Post, error) {
req := graphql.NewRequest( query trending { ... GQL Query } )
var respData struct {
Trending struct {
Posts []*model.Post json:"posts"
} json:"trending"
}
if err := a.client.Run(ctx, req, &respData); err != nil {
return nil, errors.Wrap(err, "fetching trending from rito")
}
return respData.Trending.Posts, nil }
以及这个端点的OpenAPI规范是什么样子的:
openapi: 3.0.3
paths:
/v1/trending:
get:
summary: Get trending stories
description: Returns a list of stories that are currently trending on Medium
operationId: getTrendingStories
responses:
"200":
description: A list of trending stories
content:
application/json:
schema:
type: array
items:
$ref: "#/components/schemas/Story"
components:
schemas:
Story:
type: object
properties:
id:
type: string
description: The unique ID of the story
title:
type: string
description: The title of the story
最重要的部分是你的OpenAPI文档。这是ChatGPT将解析的内容,以了解你的插件能做什么,触发什么API以及什么时候。你的摘要和描述需要简单,OpenAI的文档在其 "编写描述"部分非常清楚。
你可能觉得你需要对你的API提供复杂的描述,包括所有可能的触发等......但这不是ChatGPT所能理解的。描述你的模式对象也很重要,要简单明了地说明每个字段的内容,ChatGPT会完全理解的。
在概念验证中,我们向ChatGPT暴露了4个API
- 获取一个趋势帖子的列表。(包含帖子的标题、副标题、作者信息、链接、主题等......但不包含实际内容)。
- 查询一个特定的帖子以获得其完整的内容(如果不在付费墙后面)。
- 查询一个主题,以获得该主题的趋势和最新的帖子,以及相关主题。
- 使用一个特定的查询来搜索帖子。
一旦所有这些都被建立和部署,这时乐趣才真正开始。
在ChatGPT界面上安装MediumGPT插件
开始吧!
👾 调试该插件
现在,我希望你已经准备好让你的🧠爆炸了!调试这个插件对我来说可能是最棒的部分。为什么?因为我直接在ChatGPT上调试了这个插件。
首先,让我们问问ChatGPT是否理解我们的插件API表面
答案肯定是肯定的,这是我第一次读到它对一些API的理解,并回到文档中对它们进行了一些调整的阶段。重要的是,你要看一下每个API的描述,看看它是否符合你的想法。
我们心目中最重要的问题之一是:"用户是否需要在他们的提示中特别要求中,以便ChatGPT触发我们的插件"
因此,让我们问问ChatGPT
答案是肯定的,也是否定的。现在,我们只能在安装了一个插件后运行ChatGPT。所以无论如何,它很偏向于使用Medium插件。我们可以想象,如果多个平台都暴露了故事/帖子的API,那么在提示中加入Medium将是非常重要的,可以专门针对我们的插件。
例如,我肯定可以通过询问什么是3篇趋势文章来触发它,ChatGPT将触发Medium插件并正确使用趋势API。然后给我答复的前3篇文章。
我们甚至可以在消息的结尾处得到漂亮的小卡片
让我们再做一个测试,看看它是否真的了解我们的API和模式。在帖子模型中,我们有一个属性,isLocked ,它的记录是这样的
isLocked: type: boolean description: Whether the story is locked behind the paywall
让我们尝试一些查询,看看ChatGPT是否理解哪些帖子在付费墙后面,哪些不在付费墙后面。
的确,它是对的!这三个故事不在付费墙后面。
请注意,它并没有触发对我们的插件的调用,因为它的上下文中已经有了之前的响应。
现在,我们知道我们的插件工作正常,ChatGPT理解我们的API,我们可以开始做一些更复杂(和有用)的查询。我还想看看它是否能将查询连在一起形成一个结果。
它成功了!它首先正确地获取了我们的趋势API,然后获取了第一个故事的内容。然后给我一个故事的摘要。
哦,你实际上可以在这里阅读完整的帖子
让我们再深入一点,获取一些相关的帖子,因为我想进一步挖掘这个话题
🤯 它触发了我们的搜索API,有一个不太坏的查询,我们得到一些相关的结果
另一个连锁查询的例子,我要求获得故事主题中的最新帖子,因为我对它感兴趣。当然,它首先获取了主题,然后获取了其中第一篇帖子的内容。
当然,你的问题也可以更自然一些。下面我问的是想得到一般的意见和一个激烈的技术辩论的摘要:SwiftUI VS UIkit。
它成功地提取了我的查询,做了一个搜索查询。
然后去提取一个相关帖子的内容,给我做一个该帖子的摘要,并在底部有一个完整故事的链接。
最后一个例子,我想看看它是否可以对我们的API进行智能处理。你看我们的API有一个漏洞。我们的getTopic调用需要一个话题ID来获取实际的话题数据。所以我问ChatGPT如何能在没有ID的情况下获得话题信息:
它正确地理解到,你必须首先使用搜索API来获取与人工智能相关的故事,然后从那里你可以从帖子的主题对象中获取主题ID,然后在我们的主题API上进行查询。我对它能想出这样的思维链感到有点不可思议。
对于这个插件的实际使用,如果有更多的API暴露在ChatGPT上,其可能性是无限的。我认为它是一种自然的查询语言,用于浏览和操作任何Medium内容(再次,对于不在付费墙后面的内容)。我们还没有到知道这个插件将走向何方的阶段。但是,建立和使用它是一个非常有趣的经历。
我希望你喜欢这篇文章,如果你有任何问题,请随时联系我们。