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();
    }
}
相关推荐
AI科技摆渡2 小时前
GPT-5.2介绍+ 三步对接教程
android·java·gpt
Java编程爱好者2 小时前
做了个Java打包工具,可以双击启动了!
后端
猿与禅2 小时前
Spring Boot 4.0 完整核心特性及实践指南
java·spring boot·后端·spring·重大升级·springboot4.0
平凡运维之路2 小时前
端口转发
后端
运维@小兵2 小时前
Spring-AI系列——Tool Calling获取当前时间
java·后端·spring
认真敲代码的小火龙2 小时前
【JAVA项目】基于JAVA的养老院管理系统
java·开发语言·课程设计
he___H2 小时前
滑动窗口一题
java·数据结构·算法·滑动窗口
扶苏-su2 小时前
Java---事件处理机制
java·开发语言
用户4099322502122 小时前
Vue3数组语法如何高效处理动态类名的复杂组合与条件判断?
前端·ai编程·trae