我和 GPT-4 一起开发了一个 chrome 插件,可以批量删除 chatGPT 网页版上的对话,废话少说,先看效果:

视频号地址(手机上可以用微信扫码):

背景

作为一名后端工程师,基本没写过啥前端代码。但是自己独立写一个有 UI 界面的作品出来给用户使用,一直是个梦想。无奈动手写的成本太高,也尝试过学习前端语言,但是时间精力问题,一直也没成功。

最近,我在社交媒体上看到很多人借助 chatGPT 实现了自己的 chrome 插件,甚至是开发了自己的 APP,不少都上架了应用商店了。这就又让我眼馋和心动了,也想开始开发一个插件。

另一方面,我在使用 chatGPT 网页版的过程中,会收集一些好用的 prompt,比如“翻译大师”、“变量名取名大师”……但是啊,平时经常会发起一些临时性的对话,就是随便问一些东西。问完之后,就要删掉,以便控制对话数量不要膨胀太快。

问题是,现在想要删除 chatGPT 页面上的对话,还挺麻烦。得先点击相应的对话,进入到对话详情页,弹出删除图标,点击删除图标,再点击确定,最后才能删除。所以,想要一次删除多个对话就很繁琐。

还有一个可能需要用到批量删除对话的场景是:多人合用一个账号,删除对话是刚需,批量删除能节省很多时间。

基于以上的原因,我便开始愉快地和 GPT-4 结队编程,一起开发起批量删除 chatGPT 对话插件。

过程梳理

尝试梳理一下全过程,由于是第一次开发 Chrome Web Store 插件,并且以前从来没有写过前端代码,所以前后花了挺长时间。

原始总共有 3 个对话,本文会将其中的主要节点和对话展示出来,更详细地可以看原对话:

Bulk Delete ChatGPT(1) Bulk Delete ChatGPT(2) Bulk Delete ChatGPT(3)

尝试调用接口失败

在向 GPT-4 提问之前,我用 google 浏览器的 inspect 功能看了下 chatGPT 对话页面的接口调用情况。关于删除一个对话的过程如下:

用户手动点击某个对话,页面会调用一个接口,拿到这个对话的属性,核心的数据就是 Coversation ID。

响应为:

响应里面包含了所有的对话信息。

如果点击删除按钮,再点确定,页面会调一个 PATCH 方法,执行删除:

我一看,这不是挺简单嘛!

接着用 inspect 查看对话对应的 html 元素:

傻眼了,chatGPT 做了混淆,所以没办法知道某个对话的 Conversation ID。

但是别慌,这不是还能拿到标题嘛!刷新页面就会有另一个接口来获取所有的对话数据:

每次拿 20 条对话,对话的 Title 和 Conversation ID 有对应关系:

利用这个对应关系,应该可以根据对话的 Title 拿到对话的 Conversation ID,进而调用接口删除对话。

所以,我开始向 GPT-4 提出了我的需求:

GPT-4 马上给出了回答:

20230430231303

注:为了行文简洁,我删除了部分代码。

这个回答非常全面,一个 chrome 插件的基本文件都有了,像模像样。

我按照 GPT-4 的回答,还别说,真地就开发出来了一个插件。并且加载插件之后,还真就出现了两个按钮。但是问题是按钮上的文字是乱码,按钮也没反应:

20230430215308

按照回答进行修改之后,按钮上的文字正常了,但是点击按钮还是没有响应。

又经过两轮问答,按钮终于有了响应,可以正常在每个对话前加上复选框,但是点击复选框之后,复选框就消失了。

又尝试了两轮修改,可以出现复选框了。我把修改后的代码反馈给 GPT-4,以便让它能跟踪到我的最新进展。顺便一说,在和 GPT-4 结队编程的过程中,我经常这样做。

然后 GPT-4 也记得它的任务,马上就要进行下一步了:

20230430220227

照做后,“复选框没法选中,点击复选框之后会进入鼠标所在的那个对话”。GPT-4 马上意识到:

这是因为点击复选框时,点击事件冒泡到了对话元素,导致进入对话。要解决这个问题,我们需要阻止点击复选框时的事件冒泡。

它又给出了新的 js 代码。我照做后,无法删除对话。因为 GPT-4 前面告诉我的只是修改哪些地方,它默认我使用的都是它给我的代码,但“微调”一下太正常不过了。为了让他更清楚当前的状况,我把当前 js 代码全部复制过来,让它看应该怎么办。

GPT-4 接下来又给了一些修改,但是都不 work。我观察到应该是 Conversation ID 不对。

20230430220820

它构造映射方式是手动调用前面提到过的 conversations 接口。不太行,调用这个接口还得传入 token,这个我还不知道怎么处理。

能不能直接拿页面获取好了的结果。所以我又提出了新的想法:

20230430221110

又经过了多轮的对话,GPT-4 无法搞定构造映射这个需求。我在经过了一番折腾之后,也没耐心了,直接想要 reset 掉构造映射这一轮的对话,于是我又把当前的代码抛了出来:

20230430221438

GPT-4 这时提出换一种方法:

20230430224621

不过最终这个尝试并没有成功。

接下来,这个事情就搁置了几天,暂时不知道该怎么推进了。

模拟手动点击

有一天,我突然想到可以换一种思路,直接模拟页面上的按钮点击。虽然这个方法看起来比较笨,但是实现起来比较简单,也更安全。

毕竟直接调 chatGPT 的 API 接口,万一官方不允许这样做,把账号封了就不好了。

20230430221931

这次就比较顺利了。

过程中遇到的一些问题,GPT-4 马上就能意识到错在哪里,并快速给出方案:

20230430222051

当然,我自己也犯了一些错,我没给全信息,但是 GPT-4 没有任何抱怨:

20230430222246

接下来,又遇到了另一些问题,选中删除按钮、确认按钮并不容易。最终,GPT-4 通过相对位置(第一个是确认,第二个是取消)来选择按钮:

20230430222600

搞定按钮选择问题后,已经可以模拟点击按钮了,但随后出现了一个大问题:

20230430224716

插件只能删一个对话,且删除后,页面会自动刷新,原来的 checkbox 就没了。这时,我提出了新想法:

20230430223036

通过加延时(最终是通过检测页面上是否有复选框元素来判断有没有完成刷新),在页面刷新后,又加上了复选框。但是之前选中的对话也没了:

20230430223300

GPT-4 提出了要将之前选中的对话存起来,尝试了但是没有成功。

现在我们选中对话其实存的是 index,就是对话在左侧页面上的顺序,第一个对话的 index 是 1,第二个对话的 index 就是 2。很遗憾,删除了一个对话后,页面会刷新,所有选中的对话的 index 都会变。所以不能简单地存储 index,还得对 index 进行加减操作,以便在页面刷新后能正确选中上一轮中未被删除的已经选中过的对话。

经过了多次探讨,GPT-4 还是没能解决。不过,它建议加一些调试日志,看一下点击删除后,index 会怎么变化。于是,没学过前端的我,也开始上手调试代码。

最终,我把 GPT-4 用循环实现的逻辑变成了用递归实现,最终比较丝滑地解决了问题。

20230430224146

过程中,也遇到了一些小问题。比如,当我重复点击“添加复选框”的按钮时,它会在对话前添加多个复选框。GPT-4 拿到问题后,很快就给出了解决方案:

这个问题的原因是每次点击 “添加复选框” 按钮时,addCheckboxes 函数都会再次执行,导致每个对话前都添加了新的复选框。为了解决这个问题,我们可以在 addCheckboxes 函数中检查每个对话前是否已经存在复选框,如果不存在,则添加复选框。

这样,通过模拟页面点击来实现批量删除对话的功能就实现了。

美化插件页面

插件基本的功能完成后,就可以用 CSS 代码来美化页面。

20230430224355

当然,我也可以“PUA”它页面不好看,让它重新给代码:

20230430224813

总之就是不断地进行调试,来美化页面效果。

最终的页面效果是这样的,咱也没专业学过设计,所以就凑合看看:

上传代码到 github

至此,插件的功能就完成地差不多了。剩下的工作就是将代码上传到 Github 以及发布到 Chrome Web Store 了。当然,Github 的 README 就不用自己写了。毕竟整个过程 GPT-4 都全程参与,写个说明文档小菜一碟。

20230430225408

确定了 README 的内容后,我还让它给我翻译成英文,同样是简单得要命:

20230507201547

发布插件到 Chrome Web Store

因为我是第一次开发 Chrome Web 插件,具体的步骤还真不知道。这要是在以前,直接就是 google 搜出来一篇靠谱的前人文章,然后照着步骤做。虽然大概率也能达到目的,但是还得自己手动甄别,极有的可能做法是一口气打开 5 篇文章,然后选择其中一篇看起来不错的,照着做。

但现在不一样了,只需用自然语言告诉 GPT-4,它会立即提供完整的步骤,关键是真的有用。很多事情,就是因为更方便了一些,完成他的动力就更强了一些,最终做成的概率就更大了。

我甚至还询问了 GPT-4 对这个扩展的 Logo 有什么建议:

20230430230602

最终在 GPT-4 的帮助下,我成功地发布了插件,现在可以直接安装使用了。

启发

从开始启动开发,到最终上架 Chrome Web Store,花费了不少时间。过程中,我也学会了一些插件开发的技巧,这不,在这之后我又开发了个 chrome 浏览器插件:Xargin Blog Archive,这回就顺畅很多了,当然这是后话。

有几点启发,记录在此,希望能对你有所帮助。

  1. 和 GPT-4 对话可以用自然语言。这和我们用搜索引擎时的体验完全不一样,搜索引擎是关键词匹配,我们说得越多,反而匹配越困难。GPT-4 则不然,我们说的要求越具体,它的理解就可能越对,提供的代码质量就更高。
  2. 可以用两个对话来进行一个任务。一个用 GPT-4,一个用 chatGPT。避免 GPT-4 的额度用完之后,得等待一段时间后才能再次进行对话。注意:如果额度用完之后,还是继续对话,那之后的模型就会变成 chatGPT,额度恢复后无法再次变回 GPT-4。
  3. 当陷入困境后,一定要提供更多信息。如果只是一味地说:不行,这不 work。仅管 GPT-4 会一次次地让你尝试其他方式,但是基本上都不 work。
  4. 及时告诉 GPT-4 阶段进展。有时,我们会对 GPT-4 提供的代码做一些自己的修改,这个时候需要及时和他同步,这样在后续的对话过程中才更能保持“默契”。

最后

本文讲述了我在开发“Bulk Delete ChatGPT”这个插件的全过程,包括背景、实现过程、发布过程等,最后还总结出来几点经验。

总体上,整个开发过程很有意思。GPT-4 能让不会写前端代码的后端工程师动手开发一个纯前端的插件,属实厉害。尽管过程比较曲折,但是有了经验以后,之后再做类似的事情肯定会更高效。最后,希望这篇文章也能给你带来启发。