独立开发者日常:Java大模型流式输出教程
前言
最近在开发一个建筑行业的AI智能体应用,使用到了流式输出,总结一下。
随着AI大模型的普及,越来越多的应用需要将模型的生成内容“边生成边输出”,即流式输出。这样可以显著提升用户体验,尤其是在聊天、文案生成等场景。本文将介绍如何在Java项目中实现大模型流式输出,包括原理、主流API对接方式、代码实战和常见问题。
图片上的感兴趣的底部联系我
一、流式输出原理
流式输出(Streaming Output)指的是大模型生成内容时,服务端将已生成的部分内容立即推送给客户端,客户端实时显示,无需等待全部生成完毕。常用的技术实现方式有:
- HTTP SSE(Server-Sent Events)
- WebSocket
- HTTP 长连接分段响应
大多数主流大模型API(如OpenAI、阿里Qwen、百度文心一言等)都支持流式接口,一般通过HTTP SSE或WebSocket实现。
二、主流大模型流式API示例
以OpenAI GPT-4接口为例,流式输出参数为stream=true
,响应为SSE格式。
POST https://api.openai.com/v1/chat/completions
Headers:Authorization: Bearer YOUR_API_KEY
Body:{"model": "gpt-4","messages": [...],"stream": true}
响应内容类似:
data: {"choices":[{"delta":{"content":"你好"},"index":0,"finish_reason":null}]}
data: {"choices":[{"delta":{"content":","},"index":0,"finish_reason":null}]}
data: {"choices":[{"delta":{"content":"世界!"},"index":0,"finish_reason":"stop"}]}
三、Java流式输出实现方案
1. 使用HttpClient处理SSE流
Java 11+自带的HttpClient
不直接支持SSE,需要手动读取流。推荐用okhttp
、spring-webflux
、SseEmitter
等。
方案一:OkHttp处理流式响应
import okhttp3.*;public class OpenAIStreamDemo {public static void main(String[] args) throws Exception {OkHttpClient client = new OkHttpClient();Request request = new Request.Builder().url("https://api.openai.com/v1/chat/completions").addHeader("Authorization", "Bearer YOUR_API_KEY").post(RequestBody.create(MediaType.parse("application/json"),"{ \"model\": \"gpt-4\", \"messages\": [...], \"stream\": true }")).build();Call call = client.newCall(request);Response response = call.execute();BufferedReader reader = new BufferedReader(new InputStreamReader(response.body().byteStream()));String line;while ((line = reader.readLine()) != null) {if (line.startsWith("data: ")) {String json = line.substring(6);System.out.println("收到片段: " + json);// 可解析json,拼接输出}}reader.close();}
}
方案二:Spring Boot + SseEmitter
适合在后端接口转发流式内容给前端。
@GetMapping("/stream-chat")
public SseEmitter streamChat(@RequestParam String prompt) {SseEmitter emitter = new SseEmitter();new Thread(() -> {// 调用大模型API,逐步读取流内容try (BufferedReader reader = ...) {String line;while ((line = reader.readLine()) != null) {emitter.send(line);}emitter.complete();} catch (Exception e) {emitter.completeWithError(e);}}).start();return emitter;
}
前端用 EventSource 或 fetch/ReadableStream 实时显示。
四、前端流式显示(配合Java后端)
前端可用如下方式接收SSE流:
const source = new EventSource('/stream-chat?prompt=你好');
source.onmessage = function(event) {console.log('收到片段:', event.data);// 追加显示到页面
};
五、常见问题与优化建议
- 流断开/重连处理:后端需捕获异常,前端可自动重连。
- 内容拼接:后端/前端需按API协议拼接完整内容。
- 超时与心跳:流式连接较长,注意设置合理超时和心跳包。
- 并发与资源释放:合理管理线程、连接,防止资源泄漏。
六、其他主流模型流式接入参考
- Qwen/Qianwen(阿里/字节):接口参数和OpenAI类似,流式响应格式一致。
- 文心一言(百度):支持流式,Java代码实现同上。
- 自部署模型(如llama.cpp服务):支持WebSocket或HTTP分段,Java可用
javax.websocket
或okhttp
实现。