English 简体中文 繁體中文 한국 사람 日本語 Deutsch русский بالعربية TÜRKÇE português คนไทย french
查看: 8|回复: 0

聊聊SpringAI流式输出的底层实现?

[复制链接]
查看: 8|回复: 0

聊聊SpringAI流式输出的底层实现?

[复制链接]
查看: 8|回复: 0

259

主题

0

回帖

787

积分

高级会员

积分
787
acBRy0uWs

259

主题

0

回帖

787

积分

高级会员

积分
787
2025-4-24 05:58:44 | 显示全部楼层 |阅读模式
<div id="container" data-v-1d7a5742="" data-element="root" contentScore="2939">
在 Spring AI 中,流式输出(Streaming Output)是一种逐步返回 AI 模型生成结果的技术,允许服务器将响应内容分批次实时传输给客户端,而不是等待全部内容生成完毕后再一次性返回。
这种机制能显著提升用户体验,尤其适用于大模型响应较慢的场景(如生成长文本或复杂推理结果)。
技术实现

在 Spring AI 中流式输出的实现有以下两种方式:

  • 通过 ChatModel 实现流式输出。
  • 通过 ChatClient 实现流式输出。
ChatModel 流式输出

Spring AI 中的流式输出实现非常简单,使用 ChatModel 中的 stream 即可实现:
@RequestMapping(value = "/streamChat", produces = "text/event-stream")public Flux streamChat(@RequestParam(value = "msg") String msg) {    return chatModel.stream(msg);}

  • 1.
  • 2.
  • 3.
  • 4.





ChatClient 流式输出

ChatClient 流式输出实现也很简单,也是调用 stream().content() 返回 Flux 对象即可:
@RequestMapping("/stream")public Flux stream(String question) {    return chatClient.prompt(question)            .stream()            .content();}

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.





底层实现

那么问题来了流式输出的底层实现究竟是啥呢?
根据以往的经验我们知道,流式输出的实现技术基本有两种:

  • Spring MVC(Servlet)+ SSE 实现流式输出。
  • Spring WebFlux Reactor 模型实现流式输出。
SSE 介绍

SSE(Server-Sent Events)是一种允许服务器向浏览器或其他客户端推送实时更新的技术。它是一种单向通信机制,服务器可以主动向客户端发送数据,而客户端无需频繁轮询服务器请求数据。SSE 是基于 HTTP 协议的,使用标准的 text/event-stream MIME 类型来传输数据。
SSE 主要特点


  • 单向通信:SSE 仅支持服务器到客户端的单向通信,客户端不能向服务器发送消息。如果需要双向通信,可以结合 WebSocket 或其他技术。
  • 基于 HTTP:SSE 使用标准的 HTTP 协议,不需要额外的协议支持,因此兼容性较好。
  • 自动重连:客户端在连接中断后会自动尝试重新连接。
  • 数据格式:SSE 数据以特定的格式发送,每条消息以 data: 开头,以两个换行符 \n\n 结尾。
  • 事件类型:可以为每条消息指定事件类型,客户端可以通过监听特定事件类型来处理不同的消息。
Spring MVC(Spring Web)底层是基于 Servlet 实现的,它是使用 SseEmitter 技术实现 SSE 协议实现流式输出的。
SseEmitter 基本用法

这里提供一个 SseEmitter 的简单使用案例,实现流式输出,让大家更好的理解这个技术点:
import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;import java.io.IOException;@RestControllerpublic class SseDemoController {    @GetMapping(value = "/sse-demo", produces = "text/event-stream")    public SseEmitter streamData() {        // 设置超时时间(单位:毫秒)        SseEmitter emitter = new SseEmitter(30_000L); // 30秒超时        // 异步任务模拟流式输出        new Thread(() -> {            try {                for (int i = 1; i
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

259

主题

0

回帖

787

积分

高级会员

积分
787

QQ|智能设备 | 粤ICP备2024353841号-1

GMT+8, 2025-5-2 16:30 , Processed in 2.164209 second(s), 23 queries .

Powered by 智能设备

©2025