由于官方关闭了用到的 API,部分内容已过期
新增了 API 切换支持,可以选择使用 API (API Key)还是 ChatGPT (Access Token)
支持查询当前免费额度
ChatGPT-Swing 是一个非官方的 GUI 程序,利用 Java Swing 技术实现,基于网页版 ChatGPT(3.5),而非公开的 GPT-3 API。利用这个程序,你可以做很多网页版可以做的事(Regenerate response
感觉没必要就没做),包括:
- 账号登录(谷歌账号和微软账号还没测试)
- accessToken 自动刷新(比如明天过期,今天打开程序就会尝试刷新)
- 对话新增与聊天(支持关联上下文)
- 删除单个对话(看请求参数其实是隐藏,但隐藏后你再访问这个 id 就会 404)
- 删除所有对话
- 重命名对话标题
- 消息反馈(点赞或点踩)
- 文本转语音(调用 Free TTS 的在线测试服务,每周对单个 IP 有字数限制,这个网站是支持很多语言的,程序里目前仅支持英语,写死了)
同时免除了烦人的 Cloudflare 验证,挂机后回来随时对话无需刷新网页
缺点就是非官方 API,随时失效,还可能有 Bug
项目依赖
下面是部分截图
登录
程序一开始的设计是直接访问 ChatGPT 服务,这个选项就有用,因为登录的时候会检测当前国家或地区是否支持,登录完成后再调用其他 API 一般就不用了,通常都可以直连,所以这个代理选项只对登录接口有效,并且是本地代理,不是说设置了之后服务器就会用这个代理再去访问 ChatGPT 服务
后来用 Go 测试登录,发现,在我本地相同的网络环境下,如果 Kotlin 这边直接调用 ChatGPT 登录服务,整套流程包括拿 CSRF token 和一些重定向、用户名密码检测、最终拿 accessToken,需要 10 秒左右
神奇的事情发生了,利用 Go 去登录,仅需 5 秒左右,于是干脆起了个 Gin 服务,转发所有请求
这个不是瞎说的,直接登录 ChatGPT 的代码在早期的 commit 里,有兴趣的可以自行 checkout 测试
但这导致了一个问题,如果当前 IP 不在支持范围内,即使登录时开启代理也没用
但是我也没删除,就这样先留着了,因为还有一种潜在的场景就是,在你的本地环境下,确实需要代理才能更快地访问你的自建 API 服务,然后 API 服务将登录接口单独再经一层转发到受支持国家或地区服务器(脑回路比较不寻常就是了)
主界面的组件选择
每次新建的对话,会自动调用接口生成标题,左边是一个树形组件(根节点隐藏了),跟着的节点是每个对话,其中显示的是对话标题。对话下面的是每次问答,其中问的问题会作为对话的子节点加入树中,中间区域则显示 ChatGPT 的响应信息
这部分 UI 经过了重构,一开始打算用 JList
,类似网页版的效果,点击显示所有,然后中间用 JTextArea
直接追加就完了,但是请求和响应颜色一样,看瞎眼
接着中间区域又改成 JTextPane
,以 HTML 的方式显示数据,加一些 css 来修改对话的背景色来区分自己的请求的 ChatGPT 的响应,也不好使,勉强能用
左边后来改成了 JTree
,点击父节点显示整个对话内容,点击子节点就显示本次问答,测试完成差强人意
然后无意中发现了一个好用的库 RSyntaxTextArea
,解决了代码高亮、折叠等问题,除了 's
这个符号偶尔错误解析自动换行,最终的效果就比较理想了,也就是现在的模样
点击父节点显示整个对话内容(关联上下文)
点击子节点显示本次请求响应
代码高亮
RSyntaxTextArea
内建支持列表
父节点右键菜单
- 刷新选中对话内容
- 重命名选中对话
- 删除选中对话
清空所有对话
子节点右键菜单
- 反馈(这里没有加文本反馈,网页版有,并且网页版如果点赞了再点踩是可以的,这里会报错)
文本转语音
选中文本点击 TTS 按钮则可(这个有诸多限制,在文章一开始有写)