关于java 调用阿里千问大模型,流式返回,并返回给前端

aaff

FLux曹,找了那么多案例,没一个靠谱的,还得东拼西凑。具体方法类

maven 这两个应该就够用

java 复制代码
   <!--ai调用-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>dashscope-sdk-java</artifactId>
            <version>2.19.4</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>
java 复制代码
  @GetMapping(value = "/aiTestTwo", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<String> simpleStream() throws NoApiKeyException, InputRequiredException {
        // 直接返回一个 Flux,每个元素会立即发送给前端
        Generation gen = new Generation();
        Message systemMsg = Message.builder()
                .role(Role.SYSTEM.getValue())
                .content("You are a helpful assistant.")
                .build();
        Message userMsg = Message.builder()
                .role(Role.USER.getValue())
                .content("你是谁?")
                .build();
        GenerationParam param = GenerationParam.builder()
                // 若没有配置环境变量,请用阿里云百炼API Key将下行替换为:.apiKey("sk-xxx")
                .apiKey(System.getenv("DASHSCOPE_API_KEY"))//DASHSCOPE_API_KEY
                // 模型列表:https://help.aliyun.com/model-studio/getting-started/models
                .model("qwen-plus")
                .messages(Arrays.asList(systemMsg, userMsg))
                .resultFormat(GenerationParam.ResultFormat.MESSAGE)
                .incrementalOutput(true)
                .build();

        Flowable<GenerationResult> flowable  = gen.streamCall(param);
        return Flux.from(flowable)
                .publishOn(Schedulers.boundedElastic())
                .map(result -> result.getOutput().getChoices().get(0).getMessage().getContent())
                .filter(content -> content != null && !content.isEmpty());


    }

或者sse调用

复制代码
@GetMapping(value = "/aiTestTwo", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public SseEmitter simpleStream() throws NoApiKeyException, InputRequiredException {
        SSE sse = new SSE(60000L);
        // 直接返回一个 Flux,每个元素会立即发送给前端
        Generation gen = new Generation();
        Message systemMsg = Message.builder()
                .role(Role.SYSTEM.getValue())
                .content("You are a helpful assistant.")
                .build();
        Message userMsg = Message.builder()
                .role(Role.USER.getValue())
                .content("你是谁?")
                .build();
        GenerationParam param = GenerationParam.builder()
                // 若没有配置环境变量,请用阿里云百炼API Key将下行替换为:.apiKey("sk-xxx")
                .apiKey(System.getenv("DASHSCOPE_API_KEY"))//DASHSCOPE_API_KEY
                // 模型列表:https://help.aliyun.com/model-studio/getting-started/models
                .model("qwen-plus")
                .messages(Arrays.asList(systemMsg, userMsg))
                .resultFormat(GenerationParam.ResultFormat.MESSAGE)
                .incrementalOutput(true)
                .build();

        /*Flowable<GenerationResult> flowable = gen.streamCall(param);*/
        gen.streamCall(param).forEach(result -> {
            System.out.println(result);
            System.out.println(result.getOutput());
            System.out.println(result.getOutput().getChoices());
            System.out.println(result.getOutput().getChoices().get(0));
            System.out.println(result.getOutput().getChoices().get(0).getMessage());
            System.out.println("122212121212"+result.getOutput().getChoices().get(0).getMessage().getContent());

            String chunk = result.getOutput().getChoices().get(0).getMessage().getContent();
            System.out.print(chunk); // 逐字输出,模拟打字机效果
            sse.send(chunk);
           /* sse.send(SseEmitter.event()
                    .name("message")
                    .data(chunk));*/
        });
        /*sse.complete();*/
        return sse;

    }

html

html 复制代码
<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title>SSE 流式测试</title>
</head>
<body>
<h1>SSE 流式数据接收测试</h1>
<button onclick="startConnect()">开始连接</button>
<button onclick="stopConnect()">断开连接</button>
<hr/>
<div id="message-box" style="border:1px solid #ccc; padding:10px; min-height:100px;"></div>

<script>
    let eventSource = null;

    function startConnect() {
        const box = document.getElementById('message-box');
        box.innerText = "正在连接...\n";

        // 1. 创建 EventSource 对象,指向后端接口
        eventSource = new EventSource('/user/aiTestTwo');

        // 2. 监听消息事件 (默认事件名为 'message')
        eventSource.onmessage = function(event) {
            // event.data 就是后端 emitter.send() 发送的内容
            console.log("收到数据:", event.data);
            box.innerText += event.data;
        };

        // 3. 监听自定义事件 (如果后端用了 .name("error"))
        eventSource.addEventListener('error', function(event) {
            console.error("收到错误:", event.data);
            box.innerText += "\n[错误]: " + event.data;
        });

        // 4. 监听连接打开事件
        eventSource.onopen = function(event) {
            console.log("连接已建立");
        };

        // 5. 监听连接关闭/错误事件
        eventSource.onerror = function(event) {
            console.log("连接出错或关闭");
            // EventSource 会自动重连,如果需要手动停止,需调用 close()
            // eventSource.close();
        };
    }

    function stopConnect() {
        if (eventSource) {
            eventSource.close();
            eventSource = null;
            document.getElementById('message-box').innerText += "\n[连接已断开]";
        }
    }
</script>
</body>
</html>
相关推荐
云浪9 小时前
前端二进制数组完全指南:ArrayBuffer、TypedArray、DataView 一次讲透
前端·javascript
张风捷特烈9 小时前
Flutter 类库大揭秘#02 | path_provider 各平台实现
前端·flutter
铁皮饭盒10 小时前
26年bunjs, elysia+pg一把梭, redis都省了
前端·javascript·后端
plainGeekDev10 小时前
ButterKnife → ViewBinding
android·java·kotlin
lichenyang4531 天前
Docker 学习笔记(一):为什么需要镜像、容器和仓库?
前端
kyriewen1 天前
别再对着 TypeScript 报错发呆了:我把 10 个最常见的红色波浪线翻译成了人话
前端·javascript·typescript
IT_陈寒1 天前
SpringBoot自动配置的坑,我的API突然就404了
前端·人工智能·后端
奇奇怪怪的1 天前
Embedding 模型 10+ 横向评测
前端
陈广亮1 天前
Monorepo 从 0 到 1 实操指南 2026 版:pnpm catalogs + Turborepo 2.x + changesets 全链路
前端