一、核心目标
将基于 LangChain4j 的小芝(Xiaozhi)项目从 "一次性返回大模型结果" 改为 "通义千问流式输出",实现后端逐段向前端推送回答内容。
二、关键改动步骤
1. 添加流式输出核心依赖
xml
<!-- 流式输出核心依赖:Spring WebFlux(响应式编程) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<!-- LangChain4j 对 Reactor 响应式框架的适配,支持流式返回 -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-reactor</artifactId>
</dependency>
- 说明:
WebFlux提供Flux(流式响应)核心类,langchain4j-reactor是 LangChain4j 对接响应式框架的桥梁,二者缺一不可。
2. 配置通义千问流式大模型
在 application.properties 中添加流式模型配置:
properties
# 通义千问流式模型配置
langchain4j.community.dashscope.streaming-chat-model.api-key=${DASH_SCOPE_API_KEY}
langchain4j.community.dashscope.streaming-chat-model.model-name=qwen-plus
- 关键参数:
api-key:通义千问 API 密钥(需替换为自己的有效密钥);model-name:指定流式模型(如 qwen-plus 为通义千问增强版,支持流式输出);- 前缀
streaming-chat-model:明确指定使用 "流式聊天模型",区别于普通一次性模型。
3. 修改 AI 服务接口(XiaozhiAgent)
@AiService(
wiringMode = EXPLICIT,
// 核心改动:从普通 chatModel 改为流式 streamingChatModel
streamingChatModel = "qwenStreamingChatModel",
chatMemoryProvider = "chatMemoryProviderXiaozhi",
tools = "appointmentTools",
contentRetriever = "contentRetrieverXiaozhiPincone")
public interface XiaozhiAgent {
@SystemMessage(fromResource = "zhaozhi-prompt-template.txt")
// 核心改动:返回值从 String 改为 Flux<String>(流式字符串序列)
Flux<String> chat(@MemoryId Long memoryId, @UserMessage String userMessage);
}
- 核心改动点:
@AiService注解中:chatModel→streamingChatModel,指定使用流式模型;- 方法返回值:
String→Flux<String>,Flux代表 "0 到 N 个元素的流式序列",对应大模型逐段返回的结果。
4. 修改 Controller 接口
@Operation(summary = "对话")
// 核心改动:添加 produces 声明返回流式文本,指定 UTF-8 避免中文乱码
@PostMapping(value = "/chat", produces = "text/stream;charset=utf-8")
// 核心改动:返回值同步改为 Flux<String>,承接流式结果
public Flux<String> chat(@RequestBody ChatForm chatForm) {
return xiaozhiAgent.chat(chatForm.getMemoryId(), chatForm.getMessage());
}
- 核心改动点:
produces = "text/stream;charset=utf-8":告诉前端响应为流式文本,同时指定编码;- 返回值改为
Flux<String>,将 AI 服务的流式结果透传给前端。
5. 前端环境准备(辅助步骤)
- 安装 Node.js(推荐 v18.17.1):前端需基于 Node.js 运行,用于接收 / 展示流式数据(如通过 EventSource 接收 SSE 流)。
三、关键注意事项
- 编码问题:
produces中必须加charset=utf-8,否则前端接收中文会乱码; - 模型兼容性:确保配置的
model-name(如 qwen-plus)支持流式输出; - 前端对接:需用 SSE(EventSource)或支持流式的请求库(如 Axios)接收后端推送的流式数据。
四、核心逻辑总结
- 依赖层:引入 WebFlux + LangChain4j-Reactor 支撑响应式流式返回;
- 配置层:指定通义千问流式模型的 API 密钥和模型名称;
- 接口层:将 AI 服务和 Controller 的返回值改为
Flux<String>,并指定流式模型 / 响应类型; - 最终效果:后端逐段推送通义千问的回答内容,前端实时接收并展示