V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
LeeeSe
V2EX  ›  分享发现

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

  •  1
     
  •   LeeeSe · 2023-03-06 06:35:08 +08:00 · 2273 次点击
    这是一个创建于 634 天前的主题,其中的信息可能已经有所发展或是发生改变。

    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 代码也应该看得出来水平,大家就不要专门评论笑话我了😄。 不过我还是很想知道这条路能不能走通走爽,希望各位看官不吝赐教。

    第 1 条附言  ·  2023-03-06 16:32:59 +08:00
    代码和方法放在了这里
    https://github.com/LeeeSe/openai-api.git
    20 条回复    2023-03-07 08:29:11 +08:00
    LeeeSe
        1
    LeeeSe  
    OP
       2023-03-06 06:38:22 +08:00   ❤️ 2
    大清早发帖没人看,顶一下去睡觉😴
    kongkongye
        2
    kongkongye  
       2023-03-06 07:05:14 +08:00 via iPhone
    vercel 国内不是不能访问吗?
    kingpo
        3
    kingpo  
       2023-03-06 07:31:37 +08:00   ❤️ 1
    @kongkongye #2 他提供的二级域名不行,自定义域名可以
    bigfei
        4
    bigfei  
       2023-03-06 07:50:20 +08:00 via Android
    直接 https proxy 即可
    psyer
        5
    psyer  
       2023-03-06 07:55:43 +08:00 via Android
    @kongkongye 添加自定义域名,cf 上代理就可以了。
    b1ghawk
        6
    b1ghawk  
       2023-03-06 07:57:27 +08:00 via Android
    好的,谢谢
    dreasky
        7
    dreasky  
       2023-03-06 08:48:39 +08:00
    vercel.json 可以直接设置反向代理 一行代码都不用写
    kongkongye
        8
    kongkongye  
       2023-03-06 08:52:47 +08:00 via iPhone
    @psyer cf 全称是?
    BearD01001
        9
    BearD01001  
       2023-03-06 09:57:05 +08:00 via iPhone
    @kongkongye cloudflare
    tool2d
        10
    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
        11
    kongkongye  
       2023-03-06 11:23:44 +08:00
    @dreasky vercel 我看了文档,有个致命问题,免费版超时时间 10s ,如果 openai 回复超过 10s 就断了
    Skiro
        12
    Skiro  
       2023-03-06 12:08:38 +08:00 via Android   ❤️ 1
    我记得 Vercel 不是禁止这样用吗?
    Byzliu
        13
    Byzliu  
       2023-03-06 13:32:15 +08:00 via Android
    国内反向代理一下 vercel 就好了😁
    LeeeSe
        14
    LeeeSe  
    OP
       2023-03-06 13:36:23 +08:00
    @dreasky 还能这么操作吗?我研究一下
    LeeeSe
        15
    LeeeSe  
    OP
       2023-03-06 13:37:10 +08:00
    @Skiro 不太清楚,不过自己一个人用的话应该没什么大问题
    dreasky
        16
    dreasky  
       2023-03-06 16:04:06 +08:00
    @kongkongye api 启用 stream 参数 基本不可能超过 10s
    LeeeSe
        17
    LeeeSe  
    OP
       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
        18
    LeeeSe  
    OP
       2023-03-06 16:30:30 +08:00
    呃格式全乱了,方法和代码放在了这里
    https://github.com/LeeeSe/openai-api.git
    LeeeSe
        19
    LeeeSe  
    OP
       2023-03-06 16:53:27 +08:00
    没想到公开的 key 这么快就挂掉了,大家切成自己的 key 玩吧
    cat9life
        20
    cat9life  
       2023-03-07 08:29:11 +08:00
    你这个需求直接用官方 client 是不是更香?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3582 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 10:34 · PVG 18:34 · LAX 02:34 · JFK 05:34
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.