利用 SSE 实现流式 AI 聊天交互(三)
在 AI 赋能的时代,即时交互式对话体验成为众多应用的核心功能之一。本文将介绍如何使用 流式 SSE (Server-Sent Events) 技术,实现高效的 AI 聊天交互,提供更加丝滑的用户体验。
一、SSE 介绍
SSE (Server-Sent Events) 是一种基于 HTTP 的服务器推送技术,适用于需要实时更新但数据流量较小的场景,例如 AI 对话、股票行情、新闻推送等。它的主要特点包括:
单向通信:服务器可以主动向客户端推送消息,而客户端仅能接收。
轻量级:相比 WebSocket,SSE 使用 HTTP 连接,无需额外协议支持。
自动重连:连接断开时,浏览器会自动尝试重新建立连接。
相比 WebSocket,SSE 更适合 AI 聊天等对实时性要求较高但数据方向单一的场景。
二、实现思路
传统的 AI 聊天一般是用户发送请求后,后端计算完成后一次性返回结果。但对于长文本生成,这种方式可能导致较长的响应延迟。
相比之下,流式响应 (Streaming) 可以让 AI 逐步输出生成内容,从而提升用户体验。
我们的实现基于 Odoo 18 + OpenAI API,通过 SSE (Server-Sent Events) 让前端实时接收 AI 生成的内容,达到流畅的交互效果。
三、后端实现
在 Odoo 的 @http.route 中,我们定义了一个流式接口,负责与 AI 进行通信,并通过 SSE 将生成内容逐步推送到前端。
后端代码:请求 AI 生成内容
@http.route('/ai/stream_chat', type='http', auth='public', cors='*')
def ai_stream_chat(self, **kwargs):
user_id = request.session.uid
user_message = kwargs.get('user_message')
file_content = kwargs.get('file_content', '')
api_url = request.env['ir.config_parameter'].sudo().get_param('ai_chat_url')
api_key = request.env['ir.config_parameter'].sudo().get_param('ai_chat_api_key')
ai_model = request.env['ir.config_parameter'].sudo().get_param('ai_chat_model')
# 初始化 OpenAI 客户端
client = OpenAI(base_url=api_url, api_key=api_key)
messages = [
{"role": "system", "content": "我是一个AI助手,我的名字叫小加!"},
{"role": "user", "content": file_content[:5000]},
{"role": "user", "content": user_message}
]
def event_stream():
try:
completion = client.chat.completions.create(
model=ai_model,
messages=messages,
stream=True,
extra_headers={
"HTTP-Referer": "DeepSeek R1",
"X-Title": "Odoo AIChat"
}
)
response_text = ""
for chunk in completion:
delta = chunk.choices[0].delta
if delta and delta.content:
response_text += delta.content
yield f"data: {chunk.model_dump_json()}\n\n"
yield "data: [DONE]\n\n"
except Exception as e:
yield f"data: {{\"error\": \"{str(e)}\"}}\n\n"
return Response(event_stream(), content_type='text/event-stream')
实现细节:
参数获取:前端传递
user_message和file_content。AI 请求:使用 OpenAI API 发起流式请求。
SSE 事件流:遍历 AI 生成结果并逐步推送。
异常处理:防止请求失败导致 SSE 断开。
四、前端实现
前端使用 EventSource 监听 SSE 事件流,逐步渲染 AI 回复内容。
前端代码:接收 AI 数据并实时渲染
function startAIStream(userMessage, fileContent, base64File, fileName) {
const chatBox = document.getElementById('chat-box');
const botMessageDiv = document.createElement('div');
botMessageDiv.classList.add('message', 'bot');
botMessageDiv.innerHTML = `
<img src="./image/icon1.gif" alt="Bot">
<span id="bot-response">AI 正在思考...</span>
<span id="bot-time" style="font-size: 10px; color: #888; margin-left: 10px;"></span>`;
chatBox.appendChild(botMessageDiv);
chatBox.scrollTop = chatBox.scrollHeight;
const botResponseSpan = botMessageDiv.querySelector("#bot-response");
const botTimeSpan = botMessageDiv.querySelector("#bot-time");
const params = new URLSearchParams({
user_message: userMessage,
file_content: fileContent
});
const eventSource = new EventSource(`/ai/stream_chat?${params.toString()}`);
let fullBotMessage = "";
botResponseSpan.innerText = "";
eventSource.onmessage = function (event) {
if (event.data === "[DONE]") {
eventSource.close();
botTimeSpan.innerText = new Date().toLocaleTimeString();
createHistoryRecord(userMessage, fullBotMessage, base64File, fileName);
return;
}
try {
const jsonData = JSON.parse(event.data);
const deltaContent = jsonData.choices[0]?.delta?.content;
if (deltaContent) {
fullBotMessage += deltaContent;
requestAnimationFrame(() => {
botResponseSpan.innerHTML = marked.parse(fullBotMessage);
chatBox.scrollTop = chatBox.scrollHeight;
});
}
} catch (e) {
console.error("解析数据出错:", e);
}
};
eventSource.onerror = function (err) {
console.error("SSE 连接错误:", err);
eventSource.close();
botResponseSpan.innerText += "\n[连接已断开]";
};
}
五、效果展示
当用户发送消息后,前端立即显示 AI 正在思考...,随后 AI 逐步返回内容,并以 Markdown 解析进行美化。如下图所示:

六、项目特点
流式传输:AI 逐步生成内容,提升用户体验。
轻量级实现:基于 SSE,避免复杂的 WebSocket 连接管理。
Markdown 支持:使用
marked.js美化 AI 回复。自动重连:确保长时间使用时连接稳定。
如果你也在开发 AI 聊天功能,不妨尝试这种流式优化方案!
利用 SSE 实现流式 AI 聊天交互(三)的更多相关文章
- Android之利用HTTP网络通信实现与PHP的交互(三)
Android与PHP的交互是通过Http网络编程来实现的,利用php访问数据库,并且操作数据库中的数据,利用php作为接口,使Android连接数据库. 一般情况下,我们使用Json格式进行传输,利 ...
- 流式大数据处理的三种框架:Storm,Spark和Samza
许多分布式计算系统都可以实时或接近实时地处理大数据流.本文将对三种Apache框架分别进行简单介绍,然后尝试快速.高度概述其异同. Apache Storm 在Storm中,先要设计一个用于实时计算的 ...
- [转载]流式大数据处理的三种框架:Storm,Spark和Samza
许多分布式计算系统都可以实时或接近实时地处理大数据流.本文将对三种Apache框架分别进行简单介绍,然后尝试快速.高度概述其异同. Apache Storm 在Storm中,先要设计一个用于实时计算的 ...
- Java8 新特性之流式数据处理
一. 流式处理简介 在我接触到java8流式处理的时候,我的第一感觉是流式处理让集合操作变得简洁了许多,通常我们需要多行代码才能完成的操作,借助于流式处理可以在一行中实现.比如我们希望对一个包含整数的 ...
- Apple公司Darwin流式服务器源代码分析
当前,伴随着Internet的飞速发展,计算机网络已经进入到每一个普通人的家庭.在这个过程中,一个值得我们关注的现象是:Internet中存储和传输内容的构成已经发生了本质的改变,从传统的基于文本或少 ...
- Java8 新特性之流式数据处理(转)
转自:https://www.cnblogs.com/shenlanzhizun/p/6027042.html 一. 流式处理简介 在我接触到java8流式处理的时候,我的第一感觉是流式处理让集合操作 ...
- java1.8新特性之stream流式算法
在Java1.8之前还没有stream流式算法的时候,我们要是在一个放有多个User对象的list集合中,将每个User对象的主键ID取出,组合成一个新的集合,首先想到的肯定是遍历,如下: List& ...
- Java1.8新特性 - Stream流式算法
一. 流式处理简介 在我接触到java8流式数据处理的时候,我的第一感觉是流式处理让集合操作变得简洁了许多,通常我们需要多行代码才能完成的操作,借助于流式处理可以在一行中实现.比如我们希望对一个包 ...
- Java8 中的流式数据处理
java8的流式处理极大了简化我们对于集合.数组等结构的操作,让我们可以以函数式的思想去操作,本篇文章将探讨java8的流式数据处理的基本使用. 一. 流式处理简介 在我接触到java8流式处理的时候 ...
- JDK8新特性(二) 流式编程Stream
流式编程是1.8中的新特性,基于常用的四种函数式接口以及Lambda表达式对集合类数据进行类似流水线一般的操作 流式编程分为大概三个步骤:获取流 → 操作流 → 返回操作结果 流的获取方式 这里先了解 ...
随机推荐
- 2024从国庆到CSP前总结
前言 这是一篇迟来的总结,不过可能也不算太迟. 正文 截至起稿时间(2024.10.23),这个月已经讲了四次课,考了五场试.内容基本全是基于前一段时间的内容进行提升,对我而言很有帮助.我也意识到自己 ...
- win7系统清理C盘空间方法实测
问题描述:win7电脑C盘容易满,采用如下方法清理 方法一:win+r,输入%temp%查看临时文件,手动删除不需要的文件 方法二:减小休眠文件:如果你很少使用休眠模式,可以通过win+r输入cmd命 ...
- 【文献阅读】 PVDF &阻尼&有限元建模
1. 压电Damper原理 Piezoelectric Composite Materials - ScienceDirect 当振动传递到压电材料时,振动能量通过压电效应转化为电能,产生交流电压.所 ...
- https证书中的subject alternative name字段作用及如何生成含该字段的证书
背景 最近,某个运维同事找到我,说测试环境的某个域名(他也在负责维护),假设域名为test.baidu.com,以前呢,证书都是用的生产的证书,最近不让用了.问为啥呢,说不安全,现在在整改了,因为证书 ...
- vue watch监听路由变化
vue watch监听路由变化 // 监听 this.$route.path // watch监听非DOM元素的改变 watch:{ '$route.path':function(to,from){ ...
- Trae 开发工具与使用技巧
大家好,我是 V 哥. 前不久,字节重磅推出 AI 原生 IDE Trae,有了这款工具,程序员的开发效率得到了大大的提升,如何你是程序员,还没有使用起来,那 V 哥建议你即刻起马上安装上,谁用谁知道 ...
- 【Git】基本操作
一.Git 基础 1.Git 介绍 Git 是目前世界上最先进的分布式版本控制系统. 版本控制系统: 设计师在设计的时候做了很多版本 经过了数天去问设计师每个版本都改了些啥,设计师此时可能就说不上来了 ...
- go语言中make和new有什么作用以及区别?
在Go语言中,make 和 new 是两个内置的函数(built-in functions),用于分配内存,但它们之间有显著的区别,主要体现在它们被用于不同类型的对象分配内存. new new关键字用 ...
- 舵机SG90详解
舵机,也叫伺服电机,在嵌入式开发中,舵机作为一种常见的运动控制组件,具有广泛的应用.其中,SG90 舵机以其高效.稳定的性能特点,成为了许多工程师和爱好者的首选,无论是航模.云台.机器人.智能小车中都 ...
- Google发布A2A开源协议:“MCP+A2A”成未来标配?
就在刚刚Google Cloud Next 25大会上,谷歌重磅开源Agent2Agent(A2A)协议,这项被类比为"AI界的HTTP协议"的技术标准,彻底打破了智能体间的信息孤 ...