当前位置: 首页 > news >正文

LLM流式方案解决方案和客户端解决方案

背景

接上一篇《LLM大模型统一封装接口解决方案》架构确定后,流式方案非常规请求,需要特殊处理。

本解决方案就是针对上一篇中所需要的流式(打字机效果进行编码)

什么是SSE

SSE(Server-Sent Events,服务器发送事件)是一种基于HTTP的服务器到客户端的单向通信技术,用于实现服务器向客户端推送数据的功能。SSE协议标准由HTML5规范定义,并且其定义被包含在HTML Living Standard中。

SSE允许服务器通过HTTP连接向客户端发送数据,而无需客户端发起请求。这使得SSE非常适合于实时通信或推送通知给客户端的应用程序,例如实时股票报价、即时通讯、实时监控等场景。

基本上,SSE由以下要素组成:

  1. 服务器:负责向客户端发送事件流的HTTP服务器。
  2. 客户端:通过浏览器中的EventSource API与服务器建立连接,接收服务器发送的事件。
  3. 事件流(Event Stream):服务器向客户端发送的数据流,格式为纯文本,使用一种特定的格式进行编码,例如MIME类型为"text/event-stream"。

SSE的优点包括简单易用、实现方便、跨浏览器支持良好等。然而,它也有一些限制,例如不能支持双向通信,与WebSocket相比,SSE的实时性稍逊一筹。

Java框架说明

pom 文件引入的核心依赖包

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.0</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>aip.com</groupId><artifactId>aip-com</artifactId><version>0.0.1</version><name>aip-com</name><description>aip com project for Spring Boot</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</artifactId></dependency><dependency><groupId>io.reactivex.rxjava2</groupId><artifactId>rxjava</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

Java后端核心代码

本方法是标准的SSE协议标准

private final ExecutorService executorService = Executors.newFixedThreadPool(5);/*** 会话请求** @return String*/@PostMapping(value = "/completions", consumes = MediaType.APPLICATION_JSON_VALUE)@Operation(summary = "会话请求")public SseEmitter completions(@RequestBody CompletionRequest completionRequest) {response.setContentType(MediaType.TEXT_EVENT_STREAM_VALUE);SseEmitter emitter = new SseEmitter();executorService.execute(() -> {try {for (int i = 0; i < 10; i++) {// 向客户端发送事件emitter.send(SseEmitter.event().name("message").data(JsonHelper.toJSONString(new StreamCompletionResult.Builder().ended(false).message(String.valueOf(i)).build())));Thread.sleep(1000);}emitter.complete();} catch (Exception e) {emitter.completeWithError(e);}});return emitter;/*** 会话请求** @return String*/@GetMapping(value = "/stream")@Operation(summary = "会话请求")public SseEmitter stream() {response.setContentType(MediaType.TEXT_EVENT_STREAM_VALUE);SseEmitter emitter = new SseEmitter();executorService.execute(() -> {try {for (int i = 0; i < 10; i++) {// 向客户端发送事件emitter.send(SseEmitter.event().name("message").data(JsonHelper.toJSONString(new StreamCompletionResult.Builder().ended(false).message(String.valueOf(i)).build())));Thread.sleep(1000);}emitter.complete();} catch (Exception e) {emitter.completeWithError(e);}});return emitter;

Flux 和 Flowable 对比

Flux 和 Flowable 都是响应式编程库中的数据流类型,用于处理异步和基于事件的流式数据。它们分别来自于不同的库,Flux 是 Reactor 库的一部分,而 Flowable 则是 RxJava 库的一部分。以下是它们之间的一些区别:

  1. 库的来源:

    • Flux 来自于 Reactor 库,是 Reactor 的核心组件之一,React的核心模块用于基于反应式流规范处理数据流。
    • Flowable 来自于 RxJava 库,是 RxJava 的核心类之一,RxJava 是 Java 平台的反应式扩展库,用于处理异步和基于事件的编程。
  2. 背压策略:

    • Flux 默认采用背压策略为 BUFFER,可以通过 onBackpressureBuffer、onBackpressureDrop、onBackpressureLatest 等方法来指定不同的背压策略。
    • Flowable 默认也是支持背压的,但是相比 Flux,Flowable 提供了更多的背压策略,如 BUFFER、DROP、LATEST、ERROR、MISSING。
  3. 反应式规范:

    • Flux 遵循 Reactor 库的反应式流规范,使用 Mono 和 Flux 来表示异步流和单个结果。
    • Flowable 遵循 RxJava 库的反应式流规范,使用 Observable 和 Flowable 来表示异步流和单个结果。
  4. 生态系统:

    • Reactor 生态系统主要用于基于 Reactor 的应用程序。
    • RxJava 生态系统则更广泛,它是 ReactiveX 的一部分,支持多种语言和平台,并有许多衍生项目。

总的来说,Flux 和 Flowable 在概念上很相似,都用于处理异步和基于事件的流式数据,但它们来自于不同的库,并且有一些细微的区别,如背压策略和生态系统支持。您可以根据项目需求选择适合的库和数据流类型。

Java后端Flowable方式

本方法是Flowable方式,非标准流式规则

    /*** 会话请求** @return String*/@GetMapping(value = "/stream")@Operation(summary = "会话请求")public Flowable<String> stream() {response.setContentType(MediaType.TEXT_EVENT_STREAM_VALUE);Flowable<String> typingFlow = Flowable.create(emitter -> {executorService.execute(() -> {try {for (int i = 0; i < 10; i++) {emitter.onNext(JsonHelper.toJSONString(new StreamCompletionResult.Builder().ended(false).message(String.valueOf(i)).build()));Thread.sleep(1000);}emitter.onComplete();} catch (Exception e) {}});}, BackpressureStrategy.BUFFER);return typingFlow;}

Java后端Flux方式

本方法是Flux方式,非标准流式规则

    /*** 会话请求** @return String*/@GetMapping(value = "/stream")@Operation(summary = "会话请求")public Flux<String> stream() {response.setContentType(MediaType.TEXT_EVENT_STREAM_VALUE);Flux<String> typingFlow = Flux.create(emitter -> {executorService.execute(() -> {try {for (int i = 0; i < 10; i++) {emitter.next(JsonHelper.toJSONString(new StreamCompletionResult.Builder().ended(false).message(String.valueOf(i)).build()));Thread.sleep(1000);}emitter.complete();} catch (Exception e) {}});}, FluxSink.OverflowStrategy.BUFFER);return typingFlow;}
}

HTML 客户端接收示例程序

function EventSourceGetRequest() SSE 默认方法,只支持GET请求,适合演示用途以及后端包装好服务

function fetchPostRequest() fetch POST 请求实现SSE,支持所有请求(POST,GET等)以及传递参数

sse.html 内容

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>SEE Example</title><script>// SSE 默认方法,只支持GET请求function EventSourceGetRequest() {if(typeof(EventSource)!=="undefined"){var eventSource = new EventSource('http://127.0.0.1:8090/v1/chat/stream');eventSource.onmessage = function(event){document.getElementById('result').insertAdjacentHTML('beforeend', `${event.data}<br/><br/>`);console.log(event)};}else{document.getElementById("result").innerHTML="抱歉,你的浏览器不支持 server-sent 事件...";}}// fetch POST 请求实现SSEfunction fetchPostRequest() {fetch('http://127.0.0.1:8090/v1/chat/completions', {method: 'POST',headers: {'Content-Type': 'application/json'},body: JSON.stringify({}),}).then(response => {// 检查响应是否成功if (!response.ok) {throw new Error('Network response was not ok');}// 返回 ReadableStream 对象return response.body;}).then(stream => {// 创建一个新的文本解码器const decoder = new TextDecoder();// 获取一个 reader 对象const reader = stream.getReader();let chunk = ''// 逐块读取数据function read() {reader.read().then(({ done, value }) => {if (done) {document.getElementById('result').insertAdjacentHTML('beforeend', `${chunk}<hr/>`);console.log('Stream has ended');return;}// 将数据块转换为字符串并显示const tmp = decoder.decode(value, { stream: true });if (tmp.startsWith('event:') && chunk!='') {document.getElementById('result').insertAdjacentHTML('beforeend', `${chunk}<hr/>`);chunk = tmp}else{chunk = chunk + tmp}// 继续读取下一块数据read();});}// 开始读取数据read();}).catch(error => {// 处理错误console.error('There was a problem with the fetch operation:', error);});}// EventSourceGetRequest();fetchPostRequest();</script>
</head>
<body><h1>SEE result</h1><div id="result"></div>
</body>
</html>
  • 标准SSE示例

标准SSE

  • 扩展SSE

在这里插入图片描述

相关文章:

LLM流式方案解决方案和客户端解决方案

背景 接上一篇《LLM大模型统一封装接口解决方案》架构确定后&#xff0c;流式方案非常规请求&#xff0c;需要特殊处理。 本解决方案就是针对上一篇中所需要的流式&#xff08;打字机效果进行编码&#xff09; 什么是SSE SSE&#xff08;Server-Sent Events&#xff0c;服务器发…...

ROS2 高效学习系列

ROS2 高效学习系列 1 说明2 正文 1 说明 2023 年&#xff0c;我们总结输出了 ROS高效入门系列 和 ROS高效进阶系列&#xff0c;系统学习了 ros1 基础知识和 ros 的机器人算法。由于 ros2 的普及&#xff0c;我们将系统学习 ros2 &#xff0c;包括 ros2 基础知识和相关高级组件…...

SpringBoot + MyBatisPlus分页查询

文章目录 1.思路分析2.分页查询后端实现1.com/sun/furn/config/MybatisConfig.java 注入MyBatisPlus分页拦截器2.com/sun/furn/controller/FurnController.java 添加方法3.postman测试 3.分页查询前端实现1.src/views/HomeView.vue 引入分页导航条组件2.src/views/HomeView.vue…...

记使用sjson的一次小事故

1. 前言 之前在设计一个兼容函数的时候&#xff0c;使用了sjson动态设入参数&#xff0c;从而实现一些参数的兼容。大致的逻辑如下所示&#xff1a; // 有一堆不规则的json数据 {"a":"aaa","b":"bbb","any_key1":{"k…...

如何在iOS系统抓取log

前言&#xff1a;因为作者目前工作领域和苹果智能家居有关&#xff0c;然后发现一些bug其实是apple sdk原生code的问题&#xff0c;所以需要给apple提radar单&#xff0c;就需要抓ios端Log充当证据给apple看&#xff0c;其实ios抓log非常简单&#xff0c;大家感兴趣可以学习下哦…...

【嵌入式——QT】Charts常见的图表的绘制

【嵌入式——QT】Charts常见的图表的绘制 柱状图QBarSetQBarSeriesQBarCategoryAxis图示 饼图堆叠柱状图百分比柱状图散点图和光滑曲线图代码示例 柱状图 QBarSet 用于创建柱状图的数据集。 主要函数 setLabel()&#xff1a;设置数据集标签 &#xff1b;setLabelBrush()&am…...

pandas读写excel,csv

1.读excel 1.to_dict() 函数基本语法 DataFrame.to_dict (self, orientdict , into ) --- 官方文档 函数种只需要填写一个参数&#xff1a;orient 即可 &#xff0c;但对于写入orient的不同&#xff0c;字典的构造方式也不同&#xff0c;官网一共给出了6种&#xff0c…...

清华大学突破性研究:GVGEN技术,7秒内从文字到3D高保真生成

引言&#xff1a;3D模型生成的挑战与机遇 随着计算机图形学的发展&#xff0c;3D模型的生成在各个行业中变得越来越重要&#xff0c;包括视频游戏设计、电影制作以及AR/VR技术等。在3D建模的不同方面中&#xff0c;从文本描述生成3D模型成为一个特别有趣的研究领域&#xff0c;…...

软件测试要学习的基础知识——黑盒测试

概述 黑盒测试也叫功能测试&#xff0c;通过测试来检测每个功能是否都能正常使用。在测试中&#xff0c;把程序看作是一个不能打开的黑盒子&#xff0c;在完全不考虑程序内部结构和内部特性的情况下&#xff0c;对程序接口进行测试&#xff0c;只检查程序功能是否按照需求规格…...

如何用Airtest脚本连接无线Android设备?

之前我们已经详细介绍过如何用AirtestIDE无线连接Android设备&#xff0c;它的关键点在于&#xff0c;需要先 adb connect 一次&#xff0c;才能点击 connect 按钮无线连接上该设备&#xff1a; 但是有很多同学&#xff0c;在使用纯Airtest脚本的形式连接无线设备时&#xff0c…...

c语言函数大全(C开头)

c语言函数大全(C开头) There is no nutrition in the blog content. After reading it, you will not only suffer from malnutrition, but also impotence. The blog content is all parallel goods. Those who are worried about being cheated should leave quickly. 函数名…...

初始Redis关联和非关联

基础篇Redis 3.初始Redis 3.1.2.关联和非关联 传统数据库的表与表之间往往存在关联&#xff0c;例如外键&#xff1a; 而非关系型数据库不存在关联关系&#xff0c;要维护关系要么靠代码中的业务逻辑&#xff0c;要么靠数据之间的耦合&#xff1a; {id: 1,name: "张三…...

Redis 更新开源许可证 - 不再支持云供应商提供商业化的 Redis

原文&#xff1a;Rowan Trollope - 2024.03.20 未来的 Redis 版本将继续在 RSALv2 和 SSPLv1 双许可证下提供源代码的免费和宽松使用&#xff1b;这些版本将整合先前仅在 Redis Stack 中可用的高级数据类型和处理引擎。 从今天开始&#xff0c;所有未来的 Redis 版本都将以开…...

生产者Producer往BufferQueue中写数据的过程

In normal operation, the producer calls dequeueBuffer() to get an empty buffer, fills it with data, then calls queueBuffer() to make it available to the consumer 代码如下&#xff1a; // XXX: Tests that fork a process to hold the BufferQueue must run bef…...

使用 Vite 和 Bun 构建前端

虽然 Vite 目前可以与 Bun 配合使用&#xff0c;但它尚未进行大量优化&#xff0c;也未调整以使用 Bun 的打包器、模块解析器或转译器。 Vite 可以与 Bun 完美兼容。从 Vite 的模板开始使用吧。 bun create vite my-app ✔ Select a framework: › React ✔ Select a variant:…...

如何设置IDEA远程连接服务器开发环境并结合cpolar实现ssh远程开发

文章目录 1. 检查Linux SSH服务2. 本地连接测试3. Linux 安装Cpolar4. 创建远程连接公网地址5. 公网远程连接测试6. 固定连接公网地址7. 固定地址连接测试 本文主要介绍如何在IDEA中设置远程连接服务器开发环境&#xff0c;并结合Cpolar内网穿透工具实现无公网远程连接&#xf…...

【项目管理后台】Vue3+Ts+Sass实战框架搭建二

Vue3TsSass搭建 git cz的配置mock 数据配置viteMockServe 建立mock/user.ts文件夹测试一下mock是否配置成功 axios二次封装解决env报错问题&#xff0c;ImportMeta”上不存在属性“env” 统一管理相关接口新建api/index.js 路由的配置建立router/index.ts将路由进行集中封装&am…...

制作一个RISC-V的操作系统六-bootstrap program(risv 引导程序)

文章目录 硬件基本概念qemu-virt地址映射系统引导CSR![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/86461c434e7f4b1b982afba7fad0256c.png)machine模式下的csr对应的csr指令csrrwcsrrs mhartid引导程序做的事情判断当前hart是不是第一个hart初始化栈跳转到c语言的…...

haproxy和keepalived的区别与联系

HAProxy&#xff08;High Availability Proxy&#xff09; 是一个开源的、高效且可靠的解决方案&#xff0c;主要用于负载均衡。它工作在应用层&#xff08;第七层&#xff09;&#xff0c;支持多种协议&#xff0c;如HTTP、HTTPS、FTP等。HAProxy通过健康检查机制持续监控后…...

云效 AppStack + 阿里云 MSE 实现应用服务全链路灰度

作者&#xff1a;周静、吴宇奇、泮圣伟 在应用开发测试验证通过后、进行生产发布前&#xff0c;为了降低新版本发布带来的风险&#xff0c;期望能够先部署到灰度环境&#xff0c;用小部分业务流量进行全链路灰度验证&#xff0c;验证通过后再全量发布生产。本文主要介绍如何通…...

分布式互斥算法

1. 概述&#xff1a;什么是分布式互斥 假设有两个小孩想玩同一个玩具&#xff08;临界资源&#xff09;&#xff0c;但玩具只有一个&#xff0c;必须保证一次只有一个人能够玩。当一个小孩在玩时&#xff0c;另一个小孩只能原地等待&#xff0c;直到玩完才能轮到自己。这就是 …...

C++11新增重要标准(下)

前言 一&#xff0c;forward&#xff08;完美转发&#xff09; 二&#xff0c;可变参数模板 三&#xff0c;emplace系列接口 四&#xff0c;新增类功能 五&#xff0c;default与delete 六&#xff0c;lambda表达式 七&#xff0c;包装器 八&#xff0c;bind 在C11中新增…...

性能剖析:在 ABP 框架中集成 MiniProfiler 实现性能可视化诊断

&#x1f680; 性能剖析&#xff1a;在 ABP 框架中集成 MiniProfiler 实现性能可视化诊断 &#x1f4da; 目录 &#x1f680; 性能剖析&#xff1a;在 ABP 框架中集成 MiniProfiler 实现性能可视化诊断一、为什么选择 MiniProfiler&#xff1f; &#x1f9d0;二、集成 MiniProf…...

计算机网络第2章(下):物理层传输介质与核心设备全面解析

目录 一、传输介质1.1 传输介质的分类1.2 导向型传输介质1.2.1 双绞线&#xff08;Twisted Pair&#xff09;1.2.2 同轴电缆&#xff08;Coaxial Cable&#xff09;1.2.3 光纤&#xff08;Optical Fiber&#xff09;1.2.4 以太网对有线传输介质的命名规则 1.3 非导向型传输介质…...

青少年编程与数学 01-011 系统软件简介 03 NetWare操作系统

青少年编程与数学 01-011 系统软件简介 03 NetWare操作系统 一、历史背景二、核心架构三、关键功能四、管理工具五、客户端支持六、版本演变七、衰落原因八、遗产与影响总结 摘要&#xff1a;NetWare 是早期网络操作系统的巅峰之作&#xff0c;其高性能文件服务、目录管理和容错…...

C++ const 修饰符深入浅出详解

C const 修饰符深入浅出详解 &#x1f4c5; 更新时间&#xff1a;2025年6月6日 &#x1f3f7;️ 标签&#xff1a;C | const关键字 | 常量 | 多文件编程 | 现代C 文章目录 前言&#x1f31f; 一、const 是什么&#xff1f;为什么要用&#xff1f;示例✅ const 的四大好处 &…...

基于Spring Boot的云音乐平台设计与实现

基于Spring Boot的云音乐平台设计与实现——集成协同过滤推荐算法的全栈项目实战 &#x1f4d6; 文章目录 项目概述技术选型与架构设计数据库设计后端核心功能实现推荐算法设计与实现前端交互设计系统优化与性能提升项目部署与测试总结与展望 项目概述 &#x1f3af; 项目背…...

NGINX `ngx_stream_core_module` 模块概览

一、模块定位与功能 通用 TCP/UDP 代理 支持同时处理 TCP 和 UDP 流量&#xff0c;透明转发请求到后端服务器组&#xff08;upstream&#xff09;。可作为四层负载均衡&#xff0c;根据客户端 IP、权重、最少连接等策略将连接分发给后端。 预读&#xff08;preread&#xff09…...

解决微软应用商店 (Microsoft store) 打不开,无网络连接的问题!

很多小伙伴都会遇见微软应用商店 (Microsoft store)打开后出现无网络的问题&#xff0c;一般出现这种问题基本都是因为你的电脑安装了某些银行的网银工具&#xff0c;因为网银工具为了安全会关闭Internet 选项中的最新版本的TLS协议&#xff0c;而微软商店又需要最新的TLS协议才…...

【Fiddler抓取手机数据包】

Fiddler抓取手机数据包的配置方法 确保电脑和手机在同一局域网 电脑和手机需连接同一Wi-Fi网络。可通过电脑命令行输入ipconfig查看电脑的本地IP地址&#xff08;IPv4地址&#xff09;&#xff0c;手机需能ping通该IP。 配置Fiddler允许远程连接 打开Fiddler&#xff0c;进入…...