NexLM 开源系列】让 AI 聊天更丝滑:WebSocket 实现流式对话!

🌟 在这系列文章中,我们将一起探索如何搭建一个支持大模型集成项目 NexLM 的开发过程,从 架构设计代码实战 ,逐步搭建一个支持 多种大模型(GPT-4、DeepSeek 等)一站式大模型集成与管理平台 ,并集成 认证中心、微服务、流式对话 等核心功能。

系列目录规划:

  1. NexLM:从零开始打造你的专属大模型集成平台
  2. Spring Boot + OpenAI/DeepSeek:如何封装多个大模型 API 调用
  3. 支持流式对话 SSE & WebSocket:让 AI 互动更丝滑
  4. 微服务 + 认证中心:如何保障大模型 API 的安全调用
  5. 缓存与性能优化:提高 LLM API 响应速度
  6. NexLM 开源部署指南(Docker)

第四篇:让 AI 聊天更丝滑:WebSocket 实现流式对话!

在上一章中,我们使用 SSE (Server-Sent Events) 实现了 AI 生成式流式对话 ,但是 SSE 只能 单向推送数据 ,无法支持 用户在对话过程中发送控制指令 (如 停止响应、调整模型、动态修改参数)。

SSE vs WebSocket 对比

对比项 SSE (Server-Sent Events) WebSocket
通信方向 单向 (Server → Client) 双向 (Server ↔ Client)
协议 HTTP/1.1 + EventSource WebSocket 协议
连接方式 基于 HTTP 长连接 需要单独 升级协议
消息格式 纯文本(也支持 JSON) 二进制 / JSON / 文本
断线重连 浏览器自动重连 需要手动实现重连逻辑
服务器推送 天然支持(适合 AI 生成式内容) 需要额外实现
服务器压力 轻量级(基于 HTTP/1.1) 服务器需要维护更多连接
浏览器支持 所有现代浏览器支持 需要 支持 WebSocket
适用场景 AI 流式输出、日志推送、股票行情 实时聊天、双向交互、多人协作

📌 核心区别

  • SSE :适合 服务器推送数据 ,例如 AI 流式回复、日志推送、订阅通知。
  • WebSocket :适合 双向交互 ,例如 聊天、多人协作、在线游戏

本章,我们将升级方案,使用 WebSocket 实现 双向通信,使 AI 对话更智能、更可交互。(上一节回顾)

🌟 为什么要用 WebSocket?

与 SSE 相比,WebSocket 具有以下优点

  1. 支持双向通信 🔄 ------ 客户端可以随时向服务器发送消息,而不仅仅是等待 AI 回复。
  2. 更低的连接开销 🚀 ------ WebSocket 连接后,数据传输比 SSE 高效,适用于高并发场景。
  3. 支持二进制数据 📡 ------ 可以更灵活地发送 JSON、二进制流,适配 AI 复杂交互。
  4. 连接状态可控 🛠 ------ 可以手动 断开连接、重连、主动停止 AI 生成

📌 WebSocket 实现思路

  1. 后端:使用 Spring Boot 搭建 WebSocket 服务器,实现 AI 对话流式返回。

  2. 前端 :用 WebSocket 对接服务器,实现 用户消息发送 & AI 流式回复

  3. 增强功能

    • 支持多轮对话 🗣
    • 支持手动终止 AI 响应
    • 支持 JSON 格式通信 🔄

🚀 后端实现 WebSocket 服务

1️⃣ 引入 WebSocket 依赖

pom.xml 添加 WebSocket 依赖:

xml 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

2️⃣ 创建 WebSocket 服务器

WebSocketChatHandler.java 实现 双向通信逻辑

java 复制代码
@Component
public class WebSocketChatHandler extends TextWebSocketHandler {

    private final DeepSeekClient deepSeekClient;

    public WebSocketChatHandler(DeepSeekClient deepSeekClient) {
        this.deepSeekClient = deepSeekClient;
    }

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        System.out.println("WebSocket 连接成功:" + session.getId());
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        String userMessage = message.getPayload();
        System.out.println("用户发送消息:" + userMessage);

        try {
            // 调用 AI 大模型接口,并流式返回消息
            deepSeekClient.streamChatWs(userMessage, session);
        } catch (Exception e) {
            session.sendMessage(new TextMessage("AI 服务异常,请稍后重试。"));
            e.printStackTrace();
        }
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) {
        System.out.println("WebSocket 连接关闭:" + session.getId());
    }
}

3️⃣ 配置 WebSocket 路由

WebSocketConfig.java 里开启 WebSocket 并配置路由:

java 复制代码
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {

    @Autowired
    private DeepSeekClient deepSeekClient;

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(new WebSocketChatHandler(deepSeekClient), "/api/ai/chat/websocket").setAllowedOrigins("*");
    }
}

📌 路由说明:

  • WebSocket 连接地址为 ws://localhost:8080/api/ai/chat/websocket
  • 允许 所有前端域名 访问 (setAllowedOrigins("*"))

🚀 前端实现 WebSocket 交互

1️⃣ 创建 WebSocket 连接

javascript 复制代码
<script>
    let ws;
    let isStreaming = false; // 是否正在接收 AI 回复

    function initWebSocket() {
        ws = new WebSocket("ws://localhost:8080/web/api/ai/chat/websocket");

        ws.onopen = function() {
            console.log("WebSocket 连接成功!");
            document.getElementById("stopButton").disabled = false; // 允许停止
        };

        ws.onmessage = function(event) {
            if (!isStreaming) return; // 如果停止了,就不处理新消息
            appendBotMessage(event.data);
        };

        ws.onerror = function(error) {
            console.error("WebSocket 错误: ", error);
        };

        ws.onclose = function() {
            console.log("WebSocket 连接关闭");
            document.getElementById("stopButton").disabled = true; // 禁用停止按钮
        };
    }

    function sendMessage() {
        let input = document.getElementById("userInput");
        let message = input.value.trim();
        if (message === "") return;

        let modelType = document.getElementById("modelType").value;

        appendUserMessage(message);

        // 如果 WebSocket 关闭了,重新连接
        if (!ws || ws.readyState === WebSocket.CLOSED) {
            initWebSocket();
            setTimeout(() => ws.send(JSON.stringify({ modelType: modelType, message: message })), 500);
        } else {
            ws.send(JSON.stringify({ modelType: modelType, message: message }));
        }

        isStreaming = true; // 允许接收 AI 回复
        input.value = "";
        document.getElementById("stopButton").disabled = false; // 启用"停止"按钮
    }

    function stopStreaming() {
        isStreaming = false; // 停止接收数据
        if (ws) {
            ws.close(); // 关闭 WebSocket 连接
        }
        document.getElementById("stopButton").disabled = true; // 禁用"停止"按钮
    }

    function appendUserMessage(text) {
        let chatBox = document.getElementById("chatBox");
        let userMessage = document.createElement("div");
        userMessage.className = "message user-message";
        userMessage.innerText = text;
        chatBox.appendChild(userMessage);
        chatBox.scrollTop = chatBox.scrollHeight;
    }

    function appendBotMessage(text) {
        let chatBox = document.getElementById("chatBox");

        let lastMessage = chatBox.lastElementChild;
        if (lastMessage && lastMessage.classList.contains("bot-message")) {
            lastMessage.innerText += text;
        } else {
            let botMessage = document.createElement("div");
            botMessage.className = "message bot-message";
            botMessage.innerText = text;
            chatBox.appendChild(botMessage);
        }

        chatBox.scrollTop = chatBox.scrollHeight;
    }

    // 初始化 WebSocket 连接
    initWebSocket();
</script>

2️⃣ 添加 HTML 交互界面

新增一个"停止回答"按钮可随时停止。

html 复制代码
<div class="chat-container">
    <h1>AI 双向流式聊天</h1>
    <div class="chat-box" id="chatBox"></div>
    <div class="input-area">
        <input type="text" id="userInput" placeholder="请输入问题...">
        <select id="modelType">
            <option value="chatgpt">ChatGPT</option>
            <option value="deepseek">DeepSeek</option>
            <option value="local">本地模型</option>
        </select>
        <button onclick="sendMessage()">发送</button>
        <button id="stopButton" onclick="stopStreaming()" disabled>停止回答</button>
    </div>
</div>

✅ 功能测试&效果展示

  1. 启动 Spring Boot WebSocket 服务

  2. 访问 chat 页面,测试 WebSocket 交互

    • 发送消息
    • AI 回复流式返回
    • 支持手动终止连接(关闭 WebSocket)

📌 进阶优化

支持 AI 生成式内容

  • 可以用 OpenAI API大模型 生成 流式 AI 响应
  • 结合 WebSocket 分块返回,提升体验

支持会话上下文

  • 维护 WebSocket 连接的 Session,实现多轮对话

实现重连机制

  • WebSocket 断开时 自动重连,避免用户体验中断

🎯 总结

方案 SSE (Server-Sent Events) WebSocket
通信方向 单向 (Server → Client) 双向 (Server ↔ Client)
适用场景 AI 生成式流式返回、订阅推送 实时对话、交互式 AI
断线重连 浏览器自动重连 需要手动实现
性能 适合中等并发 高并发更优

🎯 WebSocket 适用于

  • 实时 AI 聊天
  • 流式 AI 交互
  • 多轮会话管理

🎯 下一步优化

  • 结合大模型 API ,让 WebSocket 支持 AI 生成式对话
  • 实现 JSON 通信协议,支持更复杂交互

💡 你已经掌握 SSE + WebSocket 让你的 AI 聊天更智能!后续我们将探索 AI 生成内容的优化技巧!🔥


📢 你对这个项目感兴趣吗?欢迎 Star & 关注! 📌 GitHub 项目地址 🌟 你的支持是我持续创作的动力,欢迎点赞、收藏、分享!

相关推荐
2501_916013745 小时前
日常开发中,iOS 性能调优我们怎么做?
websocket·网络协议·tcp/ip·http·网络安全·https·udp
kkai人工智能9 小时前
DeepSeek的100个应用场景
人工智能·gpt·学习·chatgpt
迅易科技12 小时前
企业智能化第一步:用「Deepseek+自动化」打造企业资源管理的智能中枢
人工智能·知识图谱·deepseek
scimence14 小时前
DeepSeek API接口调用示例(开发语言C#,替换其中key值为自己的key值即可)
开发语言·人工智能·c#·api接口·deepseek
源雀数智14 小时前
源雀SCRM开源·AI企微客服|RAG知识中枢+自训练闭环
java·人工智能·企业微信·流量运营·deepseek
果冻kk15 小时前
【实战教程】零基础搭建DeepSeek大模型聊天系统 - Spring Boot+React完整开发指南
spring boot·后端·react.js·deepseek
聚客AI16 小时前
企业级RAG架构设计:从FAISS索引到HyDE优化的全链路拆解,金融/医疗领域RAG落地案例与避坑指南(附架构图)
人工智能·语言模型·自然语言处理·ai大模型·rag·llamaindex·deepseek
没有梦想的咸鱼185-1037-16631 天前
【大语言模型ChatGPT+Python】近红外光谱数据分析及机器学习与深度学习建模(近红外光谱数据分析、定性/定量分析模型代码自动生成等)
python·深度学习·机器学习·语言模型·chatgpt·数据分析
Jet45051 天前
第100+40步 ChatGPT学习:R语言实现多轮建模
学习·chatgpt·r语言·多轮建模
yibuapi_com1 天前
开源智能体MetaGPT记忆模块解读
python·ai·语言模型·chatgpt·架构·langchain·claude