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>