随着大语言模型的广泛应用,如何高效地与其进行接口调用成为一个关键问题。传统的请求-响应模式在面对大模型生成大量文本时存在响应延迟高、用户体验差等问题。流式输出(Streaming)是解决该问题的重要手段。
本文将介绍基于 Server-Sent Events(SSE) 协议的大模型流式调用规范,并结合 Spring Boot 给出一个完整的服务端与客户端调用示例。
一、为什么选择SSE?
在与大模型进行对话时,模型通常会逐字逐句生成内容。如果采用传统的HTTP请求,需要等到模型生成完所有内容再响应给客户端,导致延迟较高。而使用SSE协议,可以做到边生成边推送,极大提升交互性和用户体验。
SSE的优势:
- 单向连接:服务端主动推送,客户端自动接收;
- 使用HTTP协议,浏览器原生支持;
- 实现简单,适用于流式文本输出场景。
二、流式调用接口规范(基于SSE)
请求方式
- 方法:POST
- Content-Type:application/json
- Accept:text/event-stream
请求示例
- POST /chat/stream
- {
- "prompt": "你好,请介绍一下三国演义。",
- "stream": true
- }
复制代码
响应格式(SSE流)
- data: {"id":"msg_001","content":"三国演义是中国古代四大名著之一..."}
- data: {"id":"msg_001","content":"它讲述了东汉末年群雄割据的故事..."}
- data: [DONE]
复制代码
- 每行以 data: 开头,后接JSON字符串;
- 最后一行以 data: [DONE] 表示流结束;
- 客户端需要实时解析接收到的 content 字段并展示。
三、Spring Boot服务端示例
下面是一个基于Spring Boot的SSE流式接口实现示例。
1. Controller层
- @RestController
- @RequestMapping("/chat")
- public class ChatController {
- @PostMapping(value = "/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
- public SseEmitter streamChat(@RequestBody ChatRequest request) {
- SseEmitter emitter = new SseEmitter(0L); // 不设置超时时间
- CompletableFuture.runAsync(() -> {
- try {
- // 模拟逐句生成的响应
- List<String> responses = mockModelResponse(request.getPrompt());
- for (String sentence : responses) {
- Map<String, String> data = new HashMap<>();
- data.put("id", "msg_001");
- data.put("content", sentence);
- emitter.send(SseEmitter.event()
- .data(new ObjectMapper().writeValueAsString(data)));
- Thread.sleep(500); // 模拟生成延迟
- }
- emitter.send("data: [DONE]\n\n");
- emitter.complete();
- } catch (Exception e) {
- emitter.completeWithError(e);
- }
- });
- return emitter;
- }
- private List<String> mockModelResponse(String prompt) {
- return List.of(
- "三国演义是中国古代四大名著之一。",
- "它讲述了东汉末年群雄割据的故事。",
- "主要人物包括刘备、关羽、张飞、曹操、孙权等。"
- );
- }
- }
复制代码
2. 请求类定义
- public class ChatRequest {
- private String prompt;
- private boolean stream;
- // getters and setters
- }
复制代码
四、客户端调用示例(Java)
使用Spring WebFlux进行客户端流式接收:- WebClient client = WebClient.create();
- client.post()
- .uri("http://localhost:8080/chat/stream")
- .header(HttpHeaders.ACCEPT, MediaType.TEXT_EVENT_STREAM_VALUE)
- .bodyValue(Map.of("prompt", "介绍一下三国演义", "stream", true))
- .retrieve()
- .bodyToFlux(String.class)
- .doOnNext(System.out::println)
- .blockLast();
复制代码
五、总结与建议
基于SSE的大模型流式调用,能显著提升响应速度与用户体验。在使用时需要注意:
- SSE适合文字类输出,若涉及音频/图片等内容建议使用WebSocket;
- 服务端处理时需考虑异常与资源释放;
- 客户端需具备实时处理与拼接能力。
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |