您的位置:首页 > 技术中心 > 其他 >

Python3.10怎么接入ChatGPT实现逐句回答流式返回

时间:2023-05-19 20:20

引言

善于观察的朋友一定会敏锐地发现ChatGPT网页端是逐句给出问题答案的,同样,ChatGPT后台Api接口请求中,如果将Stream参数设置为True后,Api接口也可以实现和ChatGPT网页端一样的流式返回,进而更快地给到前端用户反馈,同时也可以缓解连接超时的问题。

SSE是一种协议,用于实现单向服务器到客户端的通信。使用SSE,服务器可以向客户端推送实时数据,而无需客户端发出请求。

在HTTP协议的基础上,SSE采用文本格式进行通信(通常是JSON)。通过实例化一个EventSource对象,客户端与服务器建立连接后即可监听来自服务器的事件。通过事件监听,客户端可以随时接收服务器端推送的数据。

ChatGPT的Server-sent events应用

首先打开ChatGPT网页端,随便问一个问题,然后进入网络选单,清空历史请求记录后,进行网络抓包监听:

Python3.10怎么接入ChatGPT实现逐句回答流式返回

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

为什么ChatGPT会选择这种方式和后端Server进行通信?ChatGPT网页端使用Server-sent events通信是因为这种通信方式可以实现服务器向客户端推送数据,而无需客户端不断地向服务器发送请求。这种推送模式可以增强应用程序的性能和响应速度,并减少不必要的网络流量。

与其他实时通信协议(如WebSocket)相比,Server-sent events通信是一种轻量级协议,易于实现和部署。它还有着广泛的浏览器兼容性,并且无需任何特殊的网络配置即可使用。

新的聊天消息将被推送到网页端,以实时显示聊天内容,这是ChatGPT服务器的工作。使用Server-sent events通信,可以轻松地实现这种实时更新功能,并确保网页端与服务器之间的通信效率和稳定性。

Python3.10怎么接入ChatGPT实现逐句回答流式返回

说白了,降低成本,提高效率,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
");                  self.write("data:" + "push data" + "

");                  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:Usersliuyuewwwvideosite> 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方法来监听后端的主动推送:

Python3.10怎么接入ChatGPT实现逐句回答流式返回

可以看到,每隔两秒钟就可以订阅到后端的message事件推送的消息,同时,SSE默认支持断线重连,而全双工的WebSocket协议则需要自己在前端实现,高下立判。

以上就是Python3.10怎么接入ChatGPT实现逐句回答流式返回的详细内容,更多请关注Gxl网其它相关文章!

本类排行

今日推荐

热门手游