AIGC丨ChatGPT的流式输出技术SSE实践!

文摘   2024-10-24 16:54   中国  
当我们在使用ChatGPT,文心一言,kimi,通义千问等工具进行问答时,发现他们的回答不是一次性给出完整答案,而是逐字或逐块地返回答案。
这是因为大语言模型每次生成下一个词语(或Token)时,都会根据前面生成的内容进行推测和计算,它其实并不知道整个句子会是什么样子。如果等待整个回复生成后再输出到网页,会导致用户长时间等待,极大降低用户体验。
相反,通过逐字或逐块地返回回复,可以实现更快的交互响应,模拟自然对话的节奏,让整个交互过程更加符合日常交流的体验。这种可见的生成过程帮助用户理解模型是如何形成回答的,提高对话的透明度和可解释性。
这种方式可以称之为流式输出,流式输出是大模型在交互过程中的一种有效策略,它兼顾了效率和用户体验,同时也增强了模型的互动性和透明度
那么流式输出又是使用什么技术实现的呢?
以通义千问的对话接口为例,其中当stream参数设置为true时,将会流式输出对话的结果。在响应示例里我们可以看到结果并不是一次性给出。
再看到通义千问在线对话工具,响应头的类型是content-type:text/event-stream,这表示响应是文本流输出。
这就涉及到了SSE(Server-SentEvents)技术。


SSE介绍


SSE(Server-Sent Events),服务器发送事件,是一种基于HTTP协议的服务器主动向客户端推送数据的技术,利用HTTP的长连接特性,在客户端与服务器之间建立长连接。
SSE建立了一个从服务器到客户端的单向通道,服务器通过这个通道可以持续地向客户端发送事件流,而无需客户端进行显式的请求。
服务器接收到连接请求后,会设置特定的响应头,如Content-Type: text/event-stream,表示这是一个SSE流。然后,服务器向客户端持续发送以“data:”开头的多行文本数据。

SSE适用场景的特点可以概况为以下几点:

单向通信:服务器只要向客户端推送数据,而不需要接收客户端的数据。

实时数据更新:服务器可以不断地将最新的数据推送给客户端,保持数据的实时性和准确性。

低延迟:服务器需要尽快地将数据推送给客户端,避免数据的延迟和过期。



SSE实践


我们可以使用各种编程语言和技术栈来实现SSE。
通过服务端,实现数据推送;在客户端,实现服务器端推送数据的接收。

以下是使用python来实现服务端javascript实现客户端具体示例:

#服务端

服务端通过sse-starlette第三方库,使用 EventSourceResponse 类创建将发送 SSE 事件的响应。
安装第三方库:sse-starlette
pip install sse-starlette

下面是具体示例:

from fastapi import FastAPI, Requestfrom fastapi.middleware.cors import CORSMiddlewarefrom sse_starlette import EventSourceResponseimport asyncioimport uvicorn
app = FastAPI()
app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], )
async def answer_generator(request: Request): answer = 'SSE是一种基于HTTP协议的服务器主动向客户端推送数据的技术,利用HTTP的长连接特性,在客户端与服务器之间建立长连接。' for i in answer: if await request.is_disconnected(): print("连接已中断") break yield{ 'id':'100001', 'event': 'message', 'retry': 15000, 'data': i } await asyncio.sleep(0.2)

@app.get("/chat")async def chat(request: Request): response = answer_generator(request) return EventSourceResponse(response)

if __name__ == "__main__": uvicorn.run(app, host='0.0.0.0', port=8080)

#客户端

EventSource说明:https://developer.mozilla.org/zh-CN/docs/Web/API/EventSource
EventSource 接口是web与服务器发送事件通信的接口。
一个 EventSource 实例会对 HTTP 服务器开启一个持久化的连接,此连接会一直保持开启直到通过调用 EventSource.close() 关闭。
客户端通过创建一个EventSource实例,从指定的 URL 接收服务器发送事件,然后通过监听事件,获取到服务器发送的数据。

EventSource 可以监听三种类型的事件:message、open 和 error。

  • message 事件:当接收到服务器发送的消息时触发。
  • open 事件:当连接被打开时触发。
  • error 事件:当发生连接错误时触发。
如果使用GET请求,无需安装插件,则可直接通过EventSource对象,连接服务端获得推送的数据。
如果使用POST请求,常用借助第三方库fetchEventSource方法连接服务。
安装fetch-event-source插件
npm install @microsoft/fetch-event-source
下面是使用EventSource的示例:
<!DOCTYPE html>  <html>  <head>      <title>SSE Client</title>  </head>  <body>      <h1>SSE Messages</h1>      <h3 id="messages"></h3>      <script>          // 创建一个新的EventSource对象来连接到SSE服务器          var source = new EventSource('http://127.0.0.1:8080/chat');            // 当接收到消息时,将其添加到页面上          source.onmessage = function(event) {              var data = event.data;              var messages = document.getElementById('messages');              messages.innerHTML += data;        };            // 可选:处理连接打开事件          source.onopen = function(event) {              console.log('SSE connection opened.');          };            // 可选:处理连接错误事件          source.onerror = function(event) {              console.error('SSE error:', event);              source.close(); // 关闭连接          };  </script>  </body>  </html>
终就可以实现像ChatGPT一样的输出效果了
槿墨AI
产品服务

结合大模型通用知识及在交通、社会治理、安全生产、自然资源等行业领域的知识,深入业务场景,精确捕获用户意图,为用户提供智能问答、数据分析、报表生成、工作任务理解与执行等一系列服务

📞若您有相关需求,欢迎点击下方链接与我们沟通洽谈

🗨️也可以在公众号后台给我们留言



 


槿墨AI
开启探索人类未来命运的旅程,拥抱如槿似墨的无限可能。
 最新文章