AI应用的流式输出,都在使用的 SSE 协议实现

自从 ChatGPT 发布后,各类基于 AI 大模型开发出来的应用百花齐放。

比如 AI 智能客服,知识库 各类 AI Agent,有关注这些工具在回复内容的时候,都是一个字一个字显示出来,不像搜索引擎直接返回一个网页的内容。

查看各类开源 AI 应用的源码实现,都是用 SSE 协议实现。

SSE协议简介

SSE(Server-Sent Events)是一种让服务器向浏览器推送信息的技术,基于HTTP协议,利用其长连接特性,在客户端与服务器之间建立持久连接,实现服务器向客户端的实时数据推送。

SSE是HTML5规范的一部分,由服务端与浏览器端的通讯协议和浏览器端的EventSource对象组成。

SSE 的一些关键特性:

  • 单向通信:
    SSE 仅支持服务器向客户端发送数据,客户端不能向服务器发送数据,这与WebSocket 不同,后者是双向通信。
  • 长连接:
    SSE 使用HTTP 长连接,服务器可以持续向客户端发送数据,而不需要客户端频繁地重新建立连接。
  • 自动重连:
    SSE 客户端在连接断开时会自动尝试重新连接,这使得SSE 具有较好的容错性和可靠性。
  • 基于文本:
    SSE 使用文本格式来传输数据,通常是text/event-stream,这使得调试和理解数据更容易。

SSE 的典型应用场景包括:

  • 实时社交媒体更新:
    例如,当有新消息或动态时,服务器可以立即推送给客户端。
  • 股票行情更新:
    股票市场的价格经常变动,SSE 可以让用户实时看到新的股票价格。
  • 体育比分更新:
    赛事比分、统计信息等,可以通过 SSE 在比赛进行时实时更新。
    实时通知:
    例如,当有新的订单、消息等,服务器可以主动通知客户端。
  • IM 即时通讯
    例如,客服 AI 工具

例子

网页前端代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>SSE示例</title>
</head>
<body>
    <div id="result"></div>
    <script>
        // 检查浏览器是否支持EventSource
        if (!!window.EventSource) {
            var sse = new EventSource('sse.php');

            // 监听消息事件
            sse.onmessage = function (event) {
                var resultDiv = document.getElementById('result');
                resultDiv.innerHTML += event.data + '<br>';
            };

            // 监听打开连接事件
            sse.onopen = function (event) {
                console.log('连接已打开');
            };

            // 监听关闭连接事件
            sse.onclose = function (event) {
                console.log('连接已关闭');
            };

            // 监听错误事件
            sse.onerror = function (event) {
                console.error('连接出错');
            };
        } else {
            alert('您的浏览器不支持SSE');
        }
    </script>
</body>
</html>

PHP 后端代码

<?php
// 关闭输出缓冲
ini_set('output_buffering', 'off');
// 清空所有当前激活的输出缓冲区
while (@ob_end_flush()) {}

// 设置HTTP响应头
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
header('Connection: keep-alive');
header('X-Accel-Buffering: no');

// 开启输出缓冲
ob_start();
// 发送消息的循环
while (true) {
    // 生成随机数并发送消息
    $number = rand(1, 10);
    echo "data: $number\n\n";
    // 刷新缓冲区,将内容发送到客户端
    ob_flush();
    flush();
    // 模拟快速响应,暂停1毫秒
    usleep(1000);
}

运行示例

将上述HTML代码保存为一个HTML文件(如index.html),将PHP代码保存为sse.php。

在本地或远程服务器上配置Web服务器环境,确保PHP正常运行。

将这两个文件放置在Web服务器的根目录下。

打开浏览器访问HTML页面,即可看到服务器推送的随机数不断显示在页面上。

PHP实现中的关键点和注意事项

关闭输出缓冲:在PHP中,使用ini_set('output_buffering', 'off')和ob_end_flush()关闭输出缓冲,确保脚本输出立即发送到浏览器。

设置HTTP响应头:设置Content-Type为text/event-stream,Cache-Control为no-cache,Connection为keep-alive,X-Accel-Buffering为no,以确保服务器发送事件的实时性和连接的持久性。

消息格式:每条消息由一行或多行字段组成,字段以行为单位,每行一个字段,字段名和字段值之间以冒号分隔,字段值内容以换行符结束。消息之间以空行分隔。

刷新缓冲区:在发送消息后,使用ob_flush()和flush()刷新缓冲区,使消息立即发送到客户端。

保持连接:使用while (true)循环保持连接的持续性,确保服务器能够持续向客户端推送消息。

跨域问题:如果需要跨域,需在PHP中设置Access-Control-Allow-Origin和Access-Control-Allow-Credentials等头部信息。

结论

通过以上的PHP和HTML实现,可以成功应用SSE协议实现服务器向客户端的实时推送功能。这种技术在实时通知、实时数据更新、日志监控、进度更新等场景中具有广泛的应用价值。

打赏作者

您将是第一位评论人!

提醒
avatar