过去一周,ChatGPT 是机器学习领域最受关注的话题,随着它的热度不断上升,成功出圈引起了人们的广泛关注和讨论。在惊讶于它的性能和能力的同时,很多开发者也纷纷利用 ChatGPT 的技术,开发出各种有意思的应用。比如 《一大波 ChatGPT 开源项目,诞生了》。
ChatGPT 浏览器插件在这波开源项目里跑得最快,应用场景有挑事的意味:把 ChatGPT 放到搜索的场景下去和搜索引擎一较高下。
例如下面两款:
- ChatGPT-Google by ZohaibAhmed
- chat-gpt-google-extension by wong2
ChatGPT-Google 实现思路
项目地址:https://github.com/ZohaibAhmed/ChatGPT-Google
整体构成
从插件的配置清单上可以看出,插件由两部分构成:
- 在页面上运行的 content scripts
- 在后台运行的 background script
后台运行的脚本入口文件为:src/bg/background.js
页面运行的脚本入口文件为:src/inject/inject.js
,除了代码文件,还注入和 UI 相关的样式文件 src/inject/inject.css
。因为功能限制在 google 搜索里生效,所以还限定了注入条件 https://www.google.com/*
后台脚本
从前面的分析可知,后台脚本相关代码在src/background
目录下,只有一个文件 background.js
,内容非常简单。
一句话总结:收到页面发来的消息后,将页面上的插件按钮展示出来,给插件刷存在感,没了,可以直接忽略这部分。
页面交互
界面相关的代码在 src/inject
目录下,内容很简单,一个样式文件和一个脚本文件,其中样式文件还是个空文件,直接忽略,主要看inject.js
,核心代码是红框部分:
代码不多,概括一下执行流程:
- 打开 Google 网页时
inject.js
被注入,页面的代码开始执行 - 执行时向
background.js
发送一个消息,background.js
处理完消息后会执行回调 - 回调里会发起一个轮询任务:每隔 10ms 检查一下这个网页是否加载完毕
- 没加载完毕则继续轮询,加载完毕则取消轮询
- 加载完毕后,从页面上获取用户输入的搜索内容:
document.getElementsByName("q")[0].value;
- 同时往页面上注入一个自定义的框,展示提示 "Generating ChatGPT Response"
document.getElementById("appbar").insertAdjacentHTML('afterend', html);
- 接着就是发起网络请求,从本机的
localhost:5001/chat
端口获取 ChatGPT 生成的结果,将结果替换到页面上 id=GPTCHAT 的 HTML 元素里。
那么这个 localhost:5001/chat
是什么来头?这个就要看作者的另一个项目:chatgpt-api
后端代码
项目地址:https://github.com/ZohaibAhmed/chatgpt-api
这个项目的核心代码只有一个文件 server.py
,按项目作者的话来说,就是提供了一个非官方的 ChatAPI。
代码也很简短:
- 从请求中获取
q
字段的内容,也就是前面传输过来的搜索词 - 使用
send_message
把搜索词发送出去 - 通过
get_last_message
获取最后消息的返回结果 - 把结果作为 response 返回
两个函数的实现如上,这里面的使用到的 box
、PAGE
是什么?代码文件里找一找:
概括起来:使用 playwright 这个浏览器自动化测试框架启动了一个浏览器,而且设为有头模式,即把被控制的浏览器显示出来。
在 server.py 程序启动时 start_browser
,打开 chatgpt 的网页,如果没有登录会提示登录,以登录的话,服务器就跑起来了。
可以看到这里设为非多线程,这是因为 chatgpt 网页限制一次只能进行一个会话,上一个问题没回答完,不能发起下一个问题。
回过头来看 CHAT 接口的代码,总结起来流程就是:
- 程序启动时,新建一个浏览器页面,跳转到 chatgpt 的网页
- 当接收到 chat 请求时,将请求的内容取出来,输入到 chatgpt 网页上的输入框,回车(send_message 函数)
- 查看 chatgpt 页面看页面是否还在加载 chatgpt 返回的结果,如果返回完了,将结果从网页上提取出来,返回
- 以上,就完成 Server 的功能
小结
这个项目本质上是一个披着浏览器插件外皮的 Web 自动化程序。
因为需要利用 playwright 操作目标界面,这部分功能浏览器插件做不了,因此用后端机器实现。
浏览器插件只是作为用户交互的入口代理,从界面上提取输入数据,从后端获取输入并展示出来。
受限于本身 ChatGPT 网页端的限制,只能配合本地搭建服务端使用,通用性不强。
同时由于利用的是 playwright 操作浏览器,性能开销和资源占用都挺大的。
总的来说,这个方案虽然粗暴,但在没有官方 API 的情况时却是蛮实用的,这个思路可以用在很多其他类似的场景上。
chat-gpt-google-extension 实现思路
项目地址:https://github.com/wong2/chat-gpt-google-extension
这个项目在前一个项目的基础上,做了进一步的优化,青出于蓝而胜于蓝:
- 跨平台支持:支持 Chrome、Firefox、Microsoft Edge,同时上架了官方商店
- 更方便易用:不再需要本地搭建服务端,利用浏览器插件本身提供的能力,模拟 chatgpt 网页去 openai 获取数据
- 交互更友好:信息展示在搜索结果列表的右侧,不影响浏览搜索结果,也便于查看 ChatGPT 的输出
TO BE CONTINUE