SSE在Spring ai alibaba中同时使用Qwen和DeepSeek模型

SSE 定义

  • Server-Sent: 由服务器发送
  • Events: 事件,指服务器主动推给客户端的数据或消息
  • Server-SendEvetns: SSE 服务器发送事件 流式输出

SSE 是一种 基于 HTTP 协议的服务器向客户端单向推送数据的技术,允许服务器主动、持续地向客户端发送文本流数据,而无需客户端反复发起请求(告别传统的 "轮询")。

维度 SSE(Server-Sent Events) WebSocket
通信方向 单向(服务器→客户端) 双向(客户端↔服务器)
底层协议 基于 HTTP/HTTPS,无需升级 需升级 HTTP 协议为 WebSocket 协议
数据类型 仅支持文本(UTF-8) 支持文本 + 二进制
重连机制 客户端内置自动重连 需开发者手动实现重连逻辑
开发成本 极低(HTTP 生态,前端原生 API 支持) 较高(需处理协议升级、心跳保活)
适用场景 服务器单向推送(如实时通知、流式回复) 双向交互(如聊天框、在线游戏)

流失输出定义

流式输出(StreamingOutput) 是一种 逐步返回大模型生成结果的技术,生成一点儿返回一点儿,允许服务器将响应内容分批次实时传输给客户端,而不是全部内容生成完毕后一次性返回。能显著提升用户体验,尤其适用于大模型响应慢的场景(比如长生成文本或者复杂模型推理结果)。

spring ai alibaba两种流式输出

1.ChatModel Stream流式输出

2.ChatClietn Stream流式输出

SSE 后端开发

要求同时存在多种大模型产品在系统里共存使用

新建Module

POM文件

xml 复制代码
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.miao</groupId>
        <artifactId>SpringAIAlibaba-test01</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <artifactId>SAA-04StreamingOutput</artifactId>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--  模型服务灵积  调用alibaba生态的协议 对标openai协议   -->
        <dependency>
            <groupId>com.alibaba.cloud.ai</groupId>
            <artifactId>spring-ai-alibaba-starter-dashscope</artifactId>
            <version>1.0.0.2</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.38</version>
        </dependency>
    </dependencies>
</project>

properties配置

ini 复制代码
server.port=8082

#大模型对话中文UTF8编码处理
server.servlet.encoding.enabled=true
server.servlet.encoding.force=true
server.servlet.encoding.charset=UTF-8

spring.application.name=SAA-03

#spring-ai-alibaba config
#百炼大模型的api-key
spring.ai.dashscope.api-key=${qwen-api-key}
spring.ai.dashscope.url=https://dashscope.aliyuncs.com/compatible-mode/v1
spring.ai.dashscope.model=qwen3-vl-flash

启动类

typescript 复制代码
package com.miao.sse;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SSA04SSEApplication {
    public static void main(String[] args) {
        SpringApplication.run(SSA04SSEApplication.class, args);
    }
}

业务

1.ChatModel实现 2.ChatClietn实现

ChatModel实现Stream流式输出

config 配置qwen和DeepSeek模型
java 复制代码
package com.miao.sse.config;

import com.alibaba.cloud.ai.dashscope.api.DashScopeApi;
import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatModel;
import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatOptions;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SaaLLMConfig {

    private static final String QWEN_MODEL = "qwen3-max";
    private static final String DEEPSEEK_MODEL = "deepseek-v3.1";

    @Value("${spring.ai.dashscope.url")
    private String qwenUrl;

    @Bean(name = "deepseek")
    public ChatModel deepSeek() {
        return DashScopeChatModel.builder()
                .dashScopeApi(DashScopeApi.builder()
                        .apiKey(System.getenv("qwen-api-key"))
                        .build())
                .defaultOptions(DashScopeChatOptions.builder()
                        .withModel(DEEPSEEK_MODEL)
                        .build())
                .build();
    }

    @Bean(name = "qwen")
    public ChatModel qwen() {
        return DashScopeChatModel.builder()
                .dashScopeApi(DashScopeApi.builder()
                        .apiKey(System.getenv("qwen-api-key"))
                        .build())
                .defaultOptions(DashScopeChatOptions.builder().withModel(QWEN_MODEL).build())
                .build();
    }
}
业务实现Controller

ChatModelController

kotlin 复制代码
package com.miao.sse.controller;

import jakarta.annotation.Resource;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;

@RestController
public class ChatModelController {
    @Resource(name = "qwen")
    private ChatModel qwen;

    @Resource(name = "deepseek")
    private ChatModel deepseek;

    @GetMapping("/qwen")
    public String qwenChat(@RequestParam(name = "msg", defaultValue = "你是谁") String message) {
        return qwen.call(message);
    }

    @GetMapping("/deepseek")
    public Flux<String> deepseekChat(@RequestParam(name = "msg", defaultValue = "你是谁") String message) {
        return deepseek.stream(message);
    }
}

ChatClietn实现Stream流式输出

config 配置deepseek和qwen两个ChatClient
typescript 复制代码
package com.miao.sse.config;

import com.alibaba.cloud.ai.dashscope.api.DashScopeApi;
import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatModel;
import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatOptions;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.chat.prompt.ChatOptions;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SaaLLMConfig {

    private static final String QWEN_MODEL = "qwen3-max";
    private static final String DEEPSEEK_MODEL = "deepseek-v3.1";

    @Value("${spring.ai.dashscope.url")
    private String qwenUrl;

    @Bean(name = "deepseek")
    public ChatModel deepSeek() {
        return DashScopeChatModel.builder()
                .dashScopeApi(DashScopeApi.builder()
                        .apiKey(System.getenv("qwen-api-key"))
                        .build())
                .defaultOptions(DashScopeChatOptions.builder()
                        .withModel(DEEPSEEK_MODEL)
                        .build())
                .build();
    }

    @Bean(name = "qwen")
    public ChatModel qwen() {
        return DashScopeChatModel.builder()
                .dashScopeApi(DashScopeApi.builder()
                        .apiKey(System.getenv("qwen-api-key"))
                        .build())
                .defaultOptions(DashScopeChatOptions.builder().withModel(QWEN_MODEL).build())
                .build();
    }

    @Bean(name = "deepseekChatClient")
    public ChatClient deepSeekChatClient(@Qualifier("deepseek") ChatModel deepseekModel) {
        return ChatClient.builder(deepseekModel)
                .defaultOptions(ChatOptions.builder().model(DEEPSEEK_MODEL).build())
                .build();
    }

    @Bean(name = "qwenChatClient")
    public ChatClient qwenChatClient(@Qualifier("qwen") ChatModel qwenModel) {
        return ChatClient.builder(qwenModel)
                .defaultOptions(ChatOptions.builder().model(QWEN_MODEL).build())
                .build();
    }
}
业务实现 controller
kotlin 复制代码
package com.miao.sse.controller;

import jakarta.annotation.Resource;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;

@RestController
public class ChatClientController {
    @Resource(name = "qwenChatClient")
    private ChatClient qwenClient;

    @Resource(name = "deepseekChatClient")
    private ChatClient deepseekClient;

    @GetMapping("/qwen/client")
    public Flux<String> qwenChat(@RequestParam(name = "msg", defaultValue = "你是谁") String message) {
        return qwenClient.prompt().user(message).stream().content();
    }

    @GetMapping("/deepseek/client")
    public Flux<String> deepseekChat(@RequestParam(name = "msg", defaultValue = "你是谁") String message) {
        return deepseekClient.prompt().user(message).stream().content();
    }
}
相关推荐
泉-java6 分钟前
第56条:为所有导出的API元素编写文档注释 《Effective Java》
java·开发语言
Charlie_lll16 分钟前
力扣解题-移动零
后端·算法·leetcode
zfoo-framework33 分钟前
帧同步和状态同步
java
charlotte1024102436 分钟前
高并发:关于在等待学校教务系统选课时的碎碎念
java·运维·网络
亓才孓41 分钟前
[JDBC]PreparedStatement替代Statement
java·数据库
_F_y1 小时前
C++重点知识总结
java·jvm·c++
打工的小王1 小时前
Spring Boot(三)Spring Boot整合SpringMVC
java·spring boot·后端
毕设源码-赖学姐1 小时前
【开题答辩全过程】以 高校体育场馆管理系统为例,包含答辩的问题和答案
java·spring boot
我真会写代码1 小时前
SSM(指南一)---Maven项目管理从入门到精通|高质量实操指南
java·spring·tomcat·maven·ssm
vx_Biye_Design1 小时前
【关注可免费领取源码】房屋出租系统的设计与实现--毕设附源码40805
java·spring boot·spring·spring cloud·servlet·eclipse·课程设计