无服务器解决 Chatgpt 被墙问题的一种思路

2023-03-06 06:35:08 +08:00
 LeeeSe

gpt3-5 的强势登场把国内那批老头子们吓坏了,在我刚得知 api 开放的消息的同时也得知它已经被墙掉了。不过好在我有自己的小水管,体验了一会儿发现速度确实快了不少,但也没有那么夸张。

在 V2 上冲浪了一会儿发现一个 V 友的项目 https://chatgpt.ddiu.me/ ,点进去体验了一会儿发现他的怎么快了这么多,简直秒回。后来经过探索得知此项目部署在 Vercel 上,并且 V 友已经开源出来可以自己部署了,我跟着部署了之后速度也是变得飞快。

其实到这里就该止步了,但是我就是有点别扭,不太喜欢把常用的工具放网页上(其实也有一部分原因是功能不够但是我又不会前端后端),于是我就琢磨着用 Rust 写一个本地 GUI 工具,估计也就五六兆大小的 APP 。并且要求这个 app 有这三个特点:

  1. 速度和 Vercel 上部署的一样快
  2. 墙内无需 VPN 也能随意访问
  3. 不需要拥有服务器就能自己部署
  4. 免费稳定(除了 api )

我琢磨了一会儿突然想到,我直接从 Vercel 下手不就得了,完美满足上述条件啊。于是用 python 的 flask 库对 openai api 进行了简单的转发(我是后来才知道那叫 api 转发,有比较好的实现方法)并部署在了 vercel 上。

服务端 app. py

from flask import Flask, request, jsonify
import openai

app = Flask(__name__)
openai.api_key = "sk-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

@app.route('/chat', methods=['POST'])
def chat():
	messages = request.json['messages']
	res = openai.ChatCompletion.create(model="gpt-3.5-turbo",messages=messages)
	return jsonify(res.choices[0])

if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0', port=7248)

客户端 post.py

import requests

url = 'https://chatapi.leeese.cn/chat'
history = [{'role': 'system', 'content': 'You are a helpful assistant.'}]

while True:
	user_input = input('\nUser input: ')

	if not user_input:
		break
	history.append({'role': 'user', 'content': user_input})
	response = requests.post(url, json={'messages': history})
	print("\nGPT Output:" + response.json()['message']['content'])
	history.append(response.json()['message'])

大家可以直接用客户端的代码关了梯子玩一玩多轮对话体验一下速度,这接口我继续开着。

如果你玩了之后发现速度还是没有网页版那么快,那就对了,这也是我发帖的原因。其实速度还差在 openai 接口有个 stream 的参数,参数默认是 False ,即当 gpt 模型得到完整输出后才会一股脑返回给你。而这个参数开启时服务器那边会一个词一个词地给你返回消息(专业名词 server-sent events ),你一边阅读它一边生成,其实两种方法差不多同时得到所有输出,但是第二种方法提前拿到了输出,导致了体验上不小的差距。但是这个参数开启后我并不知道如何修改服务端和客户端的代码以达到实时传输模型输出的效果,就像网页上文字一行一行出现一样。我目前只知道传输过程中涉及了 websockes 协议,我现在的想法是能不能通过这个协议再由 vercel 实时获取并推送到本地。

我不是专业搞这个的,大家看我上边的 hello world 代码也应该看得出来水平,大家就不要专门评论笑话我了😄。 不过我还是很想知道这条路能不能走通走爽,希望各位看官不吝赐教。

1989 次点击
所在节点    分享发现
20 条回复
LeeeSe
2023-03-06 06:38:22 +08:00
大清早发帖没人看,顶一下去睡觉😴
kongkongye
2023-03-06 07:05:14 +08:00
vercel 国内不是不能访问吗?
kingpo
2023-03-06 07:31:37 +08:00
@kongkongye #2 他提供的二级域名不行,自定义域名可以
bigfei
2023-03-06 07:50:20 +08:00
直接 https proxy 即可
psyer
2023-03-06 07:55:43 +08:00
@kongkongye 添加自定义域名,cf 上代理就可以了。
b1ghawk
2023-03-06 07:57:27 +08:00
好的,谢谢
dreasky
2023-03-06 08:48:39 +08:00
vercel.json 可以直接设置反向代理 一行代码都不用写
kongkongye
2023-03-06 08:52:47 +08:00
@psyer cf 全称是?
BearD01001
2023-03-06 09:57:05 +08:00
@kongkongye cloudflare
tool2d
2023-03-06 11:10:47 +08:00
试了一下 stream 参数,并没有用到 websocket 协议。

还是普通的 POST 返回,只是变成了一个字一个字推送发送,就和普通 http 收发大文件一样。

我的 https 数据是:

data: {"choices":[{"delta":{"content":"性"},"index":0,"finish_reason":null}]}
data: {"choices":[{"delta":{"content":"能"},"index":0,"finish_reason":null}]}
data: {"choices":[{"delta":{"content":"。"},"index":0,"finish_reason":null}]}
data: [DONE]
kongkongye
2023-03-06 11:23:44 +08:00
@dreasky vercel 我看了文档,有个致命问题,免费版超时时间 10s ,如果 openai 回复超过 10s 就断了
Skiro
2023-03-06 12:08:38 +08:00
我记得 Vercel 不是禁止这样用吗?
Byzliu
2023-03-06 13:32:15 +08:00
国内反向代理一下 vercel 就好了😁
LeeeSe
2023-03-06 13:36:23 +08:00
@dreasky 还能这么操作吗?我研究一下
LeeeSe
2023-03-06 13:37:10 +08:00
@Skiro 不太清楚,不过自己一个人用的话应该没什么大问题
dreasky
2023-03-06 16:04:06 +08:00
@kongkongye api 启用 stream 参数 基本不可能超过 10s
LeeeSe
2023-03-06 16:14:16 +08:00
根据 @dreasky 提供的信息部署了镜像,实现了 stream 实时解析,速度确实快了不少,而且国内直接访问

chat.py
```
import json
import requests

# 设置请求头
headers = {
'Content-Type': 'application/json',
'Authorization': 'Bearer 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'
}

history = [{'role': 'system', 'content': '你叫大狸,今年 3 岁了,你无所不知,你的爸爸是山崽,妈妈是强崽,你的后腿生病了,走起路来很不稳。你需要以猫咪的口吻风格尽可能简洁地回答问题。'}]

while True:
user_input = input('User: ')
history.append({'role': 'user', 'content': user_input})

payload = {
'model': 'gpt-3.5-turbo',
'stream': True,
'messages': history
}

response = requests.post('https://openai.leeese.cn', headers=headers, json=payload, stream=True)

replies = ''
for line in response.iter_lines():
if line:
if b'content' in line:
reply = json.loads(line[6:])['choices'][0]['delta']['content']
print(reply, end='', flush=True)
replies += reply

history.append({'role': 'assistant', 'content': replies})

```
LeeeSe
2023-03-06 16:30:30 +08:00
呃格式全乱了,方法和代码放在了这里
https://github.com/LeeeSe/openai-api.git
LeeeSe
2023-03-06 16:53:27 +08:00
没想到公开的 key 这么快就挂掉了,大家切成自己的 key 玩吧
cat9life
2023-03-07 08:29:11 +08:00
你这个需求直接用官方 client 是不是更香?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/921423

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX