引言
在当今的AI浪潮中,LLM(大型语言模型)如日中天。而流式输出作为提升用户体验的关键技术,也越来越受到开发者的关注。今天,我们就来深入探讨一下LLM流式输出的原理,并结合具体的代码实现,详细介绍前后端的连接方式。
为什么需要LLM流式输出
在正式介绍代码之前,我们先了解一下为什么需要流式输出。在与LLM交互时,如果等待模型生成完整的回答后再一次性输出,用户可能需要长时间等待,这会极大地影响用户体验。而流式输出则可以边生成边输出,让用户更快地看到响应,就像聊天一样自然流畅。
流式输出不仅能提升用户体验,还与成本有关。因为LLM通常是按token(令牌)计费的,流式输出可以让用户在等待的过程中就开始获取信息,而不需要等到所有token都生成完毕。
前端与后端的职责
在流式输出的实现中,前端和后端都有各自的职责。前端主要负责提供良好的用户体验,尽快返回结果给用户。而后端则负责与LLM交互,生成内容并通过合适的方式推送给前端。
代码实现:前后端流式输出连接方式
后端代码(index.js)
首先,我们来看后端代码,它是基于Node.js和Express框架实现的。以下是具体的代码及注释解释:
// 启动http server
// 引入express框架
// import express from 'express';
// node 最初的commonjs 的模块化方案
const express = require('express');
// console.log(express);
const app = express(); // 后端应用 App
// 路由
app.get('/',(req,res)=>{
// 返回 index.html
// res.send("hello");// str
// response 有请求req 用户, 浏览器(proxy) url localhost:1314 + get path /
// http 足够简单 高并发 用户赶快走 断开联系
// __dirname 项目的根目录
console.log(__dirname);
res.sendFile(__dirname + '/index.html');
})
// 添加一个支持server push 的路由
app.get('/sse',(req,res)=>{
// 支持server push 不断的服务器端推送 少量的
// 设置响应头
res.set({
// steam 文本流, 事件
'Content-Type':'text/event-stream',
'Cache-Control':'no-cache',// 禁止前端使用缓存
'Connection':'keep-alive',// 保持连接
})
res.flushHeaders();
setInterval(()=>{
const message = `Current Time is ${new Date().toLocaleTimeString()}`
// server push
res.write(`data:${message}\n\n`);
},1000)
})
// node 内置模块
const http = require('http').Server(app);// server 基本能力 B/S 架构
// 监听?伺服状态 伺候用户
http.listen(1314,()=>{
console.log('服务器启动成功');
})
代码解释
- 引入Express框架:使用
require('express')引入Express框架,并创建一个Express应用实例app。 - 根路由:当用户访问根路径
/时,服务器会返回index.html文件。 - SSE路由:当用户访问
/sse路径时,服务器会设置响应头,支持服务器端推送(SSE)。Content-Type设置为text/event-stream,表示这是一个事件流;Cache-Control设置为no-cache,禁止前端使用缓存;Connection设置为keep-alive,保持连接。 - 定时推送消息:使用
setInterval函数每隔1秒向客户端推送当前时间。 - 启动服务器:使用
http.listen方法启动服务器,监听端口1314。
前端代码(index.html中的JavaScript部分)
接下来,我们看前端代码,它主要负责与后端建立连接并处理接收到的消息。以下是具体的代码及注释解释:
document.getElementById('streamButton').addEventListener('click', function() {
const outputDiv = document.getElementById('output');
outputDiv.textContent = '连接中...';
// 创建EventSource连接到服务器端的流式接口
// html5 事件流 给他支持SSE 的地址
// SSE Server Sent Events 服务器端推送事件
const eventSource = new EventSource('/sse');
// 接收消息事件
eventSource.onmessage = function(event) {
// 将接收到的内容追加显示
outputDiv.textContent += '\n';
outputDiv.textContent += event.data + '\n';
};
// 错误处理
eventSource.onerror = function(err) {
console.error('EventSource failed:', err);
outputDiv.textContent += '\n\n发生错误,请刷新页面重试。';
eventSource.close();
};
});
代码解释
- 点击事件监听:当用户点击
开始流式输出按钮时,会触发点击事件。 - 显示连接中信息:将输出区域的文本内容设置为
连接中...。 - 创建EventSource连接:使用
EventSource对象创建一个与服务器端/sse路径的连接。 - 接收消息事件:当接收到服务器端推送的消息时,会触发
onmessage事件,将接收到的消息追加到输出区域。 - 错误处理:当连接发生错误时,会触发
onerror事件,在输出区域显示错误信息,并关闭连接。
完成展示:
总结
通过以上的代码实现,我们可以看到,前后端流式输出的连接方式主要是通过服务器端推送(SSE)来实现的。后端设置响应头,支持服务器端推送,前端使用EventSource对象与后端建立连接,接收服务器端推送的消息。这种方式可以让用户更快地看到响应,提升用户体验。
希望本文能帮助你更好地理解LLM流式输出的原理和实现方式。如果你有任何问题或建议,欢迎在评论区留言。
以上就是关于LLM流式输出的详细介绍,希望对你有所帮助!