关于chatgpt:ChatGPT采用的Serversent-events后端实时推送协议Python310实现基于Tornado61

38次阅读

共计 3477 个字符,预计需要花费 9 分钟才能阅读完成。

长于察看的敌人肯定会敏锐地发现 ChatGPT 网页端是逐句给出问题答案的,同样,ChatGPT 后盾 Api 接口申请中,如果将 Stream 参数设置为 True 后,Api 接口也能够实现和 ChatGPT 网页端一样的流式返回,进而更快地给到前端用户反馈,同时也能够缓解连贯超时的问题。

Server-sent events(SSE)是一种用于实现服务器到客户端的单向通信的协定。应用 SSE,服务器能够向客户端推送实时数据,而无需客户端发出请求。

SSE 建设在 HTTP 协定上,应用基于文本的数据格式(通常是 JSON)进行通信。客户端通过创立一个 EventSource 对象来与服务器建设连贯,而后能够监听服务器发送的事件。服务器端能够随时将事件推送给客户端,客户端通过监听事件来接管这些数据。

ChatGPT 的 Server-sent events 利用

首先关上 ChatGPT 网页端,轻易问一个问题,而后进入网络选单,清空历史申请记录后,进行网络抓包监听:

能够看到,在触发了答复按钮之后,页面会往后端的 backend-api/conversation 对话接口发动申请,但这个接口的通信形式并非传统的 http 接口或者 Websocket 长久化链接协定,而是基于 EventSteam 的事件流一段一段地返回 ChatGPT 后端模型的返回数据。

为什么 ChatGPT 会抉择这种形式和后端 Server 进行通信?ChatGPT 网页端应用 Server-sent events 通信是因为这种通信形式能够实现服务器向客户端推送数据,而无需客户端一直地向服务器发送申请。这种推送模式能够进步应用程序的性能和响应速度,缩小了不必要的网络流量。

与其余实时通信协议(如 WebSocket)相比,Server-sent events 通信是一种轻量级协定,易于实现和部署。此外,它也具备宽泛的浏览器兼容性,并且能够在不须要非凡网络配置的状况下应用。

在 ChatGPT 中,服务器会将新的聊天音讯推送到网页端,以便实时显示新的聊天内容。应用 Server-sent events 通信,能够轻松地实现这种实时更新性能,并确保网页端与服务器之间的通信效率和稳定性。

说白了,降低成本,提高效率,ChatGPT 是一个基于深度学习的大型语言模型,解决自然语言文本须要大量的计算资源和工夫。因而,返回响应的速度必定比一般的读数据库要慢的多,Http 接口显然并不适合,因为 Http 是一次性返回,等待时间过长,而 Websocket 又过重,因为全双工通信并不适宜这种单项对话场景,所谓单项对话场景,就是对话单方并不会并发对话,而是串行的一问一答逻辑,同时长久化链接也会占用服务器资源,要晓得 ChatGPT 简直能够算是日均沉闷用户数寰球最高的 Web 利用了。

效率层面,大型语言模型没方法一下子返回所有计算数据,然而能够通过 Server-sent events 将后面计算出的数据先“推送”到前端,这样用户也不会因为等待时间过长而敞开页面,所以 ChatGPT 的前端观感就是像打字机一样,一段一段的返回答案,这种“边计算边返回”的生成器模式也进步了 ChatGPT 的答复效率。

Python3.10 实现 Server-sent events 利用

这里咱们应用基于 Python3.10 的 Tornado 异步非阻塞框架来实现 Server-sent events 通信。

首先装置 Tornado 框架

pip3 install tornado==6.1

随后编写 sse\_server.py:

import tornado.ioloop  
import tornado.web  
  
  
push_flag = True  
  
from asyncio import sleep  
  
  
class ServerSentEvent(tornado.web.RequestHandler):  
  
    def __init__(self, *args, **kwargs):  
        super(ServerSentEvent, self).__init__(*args, **kwargs)  
        self.set_header('Content-Type', 'text/event-stream')  
        self.set_header('Access-Control-Allow-Origin', "*")  
        self.set_header("Access-Control-Allow-Headers","*")  
        # 申请形式  
        self.set_header("Access-Control-Allow-Methods","*")  
  
    # 断开连接  
    def on_finish(self):  
        print("断开连接")  
        return super().on_finish()  
  
    async def get(self):  
        print("建设链接")  
        while True:  
            if push_flag:  
                print("开始")  
                self.write("event: message\n");  
                self.write("data:" + "push data" + "\n\n");  
                self.flush()  
                await sleep(2)

建设好推送路由类 ServerSentEvent,它继承 Tornado 内置的视图类 tornado.web.RequestHandler,首先利用 super 办法调用父类的初始化办法,设置跨域,如果不应用 super,会将父类同名办法重写,随后建设异步的 get 办法用来链接和推送音讯,这里应用 Python 原生异步的写法,每隔两秒往前端推送一个事件 message, 内容为 push data。

留神,这里只是简略的推送演示,实在场景下如果波及 IO 操作,比方数据库读写或者网络申请之类,还须要独自封装异步办法。

另外这里假设前端 onmessage 处理程序的事件名称为 message。如果想应用其余事件名称,能够应用前端 addEventListener 来订阅事件,最初音讯后必须以两个换行为结尾。

随后编写路由和服务实例:

def make_app():  
    return tornado.web.Application([(r"/sse/data/", ServerSentEvent),  
    ])  
  
if __name__ == "__main__":  
    app = make_app()  
    app.listen(8000)  
    print("sse 服务启动")  
    tornado.ioloop.IOLoop.current().start()

随后在后盾运行命令:

python3 sse_server.py

程序返回:

PS C:\Users\liuyue\www\videosite> python .\sse_server.py  
sse 服务启动 

至此,基于 Tornado 的 Server-sent events 服务就搭建好了。

前端 Vue.js3 链接 Server-sent events 服务

客户端咱们应用目前最风行的 Vue.js3 框架:

sse_init:function(){var push_data = new EventSource("http://localhost:8000/sse/data/")  
        push_data.onopen = function (event) {  
            // open 事件  
            console.log("EventSource 连贯胜利");  
        };  
         
  
        push_data.onmessage = function (event) {  
    try {console.log(event);  
    } catch (error) {console.log('EventSource 完结音讯异样', error);  
    }  
};  
  
  
       push_data.onerror = function (error) {console.log('EventSource 连贯异样', error);  
};  
  
  
      }

这里在前端的初始化办法内建设 EventSource 实例,通过 onmessage 办法来监听后端的被动推送:

能够看到,每隔两秒钟就能够订阅到后端的 message 事件推送的音讯,同时,SSE 默认反对断线重连,而全双工的 WebSocket 协定则须要本人在前端实现,高下立判。

结语

不仅仅能够实现 ChatGPT 的流式返回性能,SSE 在 Web 应用程序中的应用场景十分宽泛,例如实时的新闻推送、实时股票报价、在线游戏等等,比起轮询和长轮询,SSE 更加高效,因为只有在有新数据达到时才会发送;同时 SSE 反对自定义事件和数据,具备更高的灵活性和复用性,为流式数据返回保驾护航,ChatGPT 的最爱,谁不爱?最初奉上我的项目地址,与众乡亲同飨:github.com/zcxey2911/sse\_tornado6\_vuejs3

正文完
 0