Java使用Langchai4j接入AI大模型的简单使用(五)--流式输出的实现
一、LLMs流式输出介绍
流式输出(Streaming Output)是大语言模型(LLMs)中一种重要的交互方式,它允许模型将生成的文本逐步返回给用户,而不是等待整个响应完成后再一次性返回。
二、流式输出的工作原理
分块生成:模型不是一次性生成完整回答,而是逐词或逐句生成
即时传输:每生成一部分内容就立即发送给客户端
持续处理:客户端可以即时显示或处理接收到的部分结果
三、流式输出的优势
1、用户体验提升
降低等待焦虑:用户不需要长时间等待就能看到部分结果
更自然的交互:模拟人类对话的逐步响应方式
响应感知:用户可以早期判断响应方向是否正确
2、技术优势
降低延迟:首个令牌(Token)的响应时间(TTFB)大幅缩短
内存效率:不需要缓存完整响应再发送
中断能力:用户可以在中途停止不想要的响应。
四、流式输出的应用场景
聊天应用:模拟真人对话体验
代码生成:逐步显示生成的代码
长文写作:分段显示生成内容
实时翻译:边听边翻译的场景
教育应用:逐步解释复杂概念
五、流式输出的技术挑战与解决方案
挑战 | 解决方案 |
---|---|
连接稳定性 | 心跳机制、自动重连 |
部分响应处理 | 客户端状态管理 |
错误处理 | 错误边界设计、重试机制 |
前后端协调 | 定义明确的数据协议 |
六、流式与一次性输出的对比
特性 | 流式输出 | 一次性输出 |
---|---|---|
响应时间 | 快(首个令牌) | 慢(完整响应) |
内存占用 | 低 | 高 |
用户体验 | 更优 | 一般 |
实现复杂度 | 较高 | 较低 |
适用场景 | 交互式应用 | 批处理任务 |
流式输出已成为现代LLM应用的标准功能,它能显著提升用户体验,特别是在需要长时间生成内容的场景中。
七、流式输出的实现
下面使用Langchain4j+阿里千问来实现:
1、引入依赖:
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.example</groupId><artifactId>langchain4j</artifactId><version>0.0.1-SNAPSHOT</version><name>langchain4j_springboot</name><description>langchain4j_springboot</description><properties><java.version>17</java.version><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target><spring-boot.version>3.4.3</spring-boot.version><langchain4j.version>1.0.0-beta1</langchain4j.version></properties><dependencies><dependency><groupId>dev.langchain4j</groupId><artifactId>langchain4j-community-dashscope-spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>${spring-boot.version}</version><type>pom</type><scope>import</scope></dependency><dependency><groupId>dev.langchain4j</groupId><artifactId>langchain4j-community-bom</artifactId><version>${langchain4j.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.8.1</version><configuration><source>17</source><target>17</target><encoding>UTF-8</encoding></configuration></plugin></plugins></build></project>
这里重点说一下需要引入webflux实现流式响应输出:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
2、在application.properties配置流式输出所需要的信息
langchain4j.community.dashscope.streaming-chat-model.api-key=配置key
langchain4j.community.dashscope.streaming-chat-model.model-name=qwq-32b
3、编码实现:
package com.example.langchain4j.controller;import com.fasterxml.jackson.databind.ObjectMapper;
import dev.langchain4j.community.model.dashscope.QwenChatModel;
import dev.langchain4j.community.model.dashscope.QwenStreamingChatModel;
import dev.langchain4j.model.chat.response.ChatResponse;
import dev.langchain4j.model.chat.response.StreamingChatResponseHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;/*** @author: * @Desc:* @create: 2025-07-13 12:40**/
@RestController
@RequestMapping("/ai")
public class ChatController {@Autowiredprivate QwenStreamingChatModel streamingChatModel;//须指定produces为stream输出,编码为utf-8,否则会乱码@RequestMapping(value = "/stream", produces = "text/stream;charset=UTF-8")public Flux<String> stream(@RequestParam(value="message",defaultValue = "你是谁") String message){Flux<String> flux = Flux.create(sink -> {streamingChatModel.chat(message, new StreamingChatResponseHandler() {@Overridepublic void onPartialResponse(String partialResponse) {sink.next(partialResponse);}@Overridepublic void onCompleteResponse(ChatResponse chatResponse) {sink.complete();}@Overridepublic void onError(Throwable throwable) {sink.error(throwable);}});});return flux;}}