无法实现Ollama响应流式输出,请求RAG应用技术支持
实现流式响应的改造方案
要实现类似ChatGPT的流式输出,Spring MVC中可以通过**SSE(Server-Sent Events)**来实现,核心是使用SseEmitter逐步向客户端发送生成的token,而非等待全部内容生成后再返回。以下是改造后的完整代码:
import org.springframework.web.bind.annotation.*; import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; import dev.langchain4j.model.ollama.OllamaStreamingChatModel; import dev.langchain4j.model.StreamingResponseHandler; import dev.langchain4j.model.chat.StreamingChatLanguageModel; import dev.langchain4j.data.message.AiMessage; import dev.langchain4j.model.output.Response; import java.time.Duration; import java.util.concurrent.TimeUnit; @RestController @RequestMapping("/api") public class OllamaController { private final StreamingChatLanguageModel streamingChatModel; // SSE超时时间与模型超时保持一致 private static final long SSE_TIMEOUT = TimeUnit.MINUTES.toMillis(5); public OllamaController() { this.streamingChatModel = OllamaStreamingChatModel.builder() .baseUrl("你的Ollama服务地址") .modelName("llama3") .timeout(Duration.ofMinutes(5)) .temperature(0.6) .build(); } @PostMapping("/generate") public SseEmitter generateResponse(@RequestBody String userMessage) { // 初始化SseEmitter并设置超时时间 SseEmitter emitter = new SseEmitter(SSE_TIMEOUT); streamingChatModel.generate(userMessage, new StreamingResponseHandler<AiMessage>() { @Override public void onNext(String token) { try { // 实时发送单个生成的token emitter.send(token); } catch (Exception e) { // 发送失败时终止连接并传递错误 emitter.completeWithError(e); } } @Override public void onComplete(Response<AiMessage> response) { // 所有内容发送完毕,关闭SSE连接 emitter.complete(); } @Override public void onError(Throwable error) { // 模型生成出错时,终止连接并传递错误 emitter.completeWithError(error); } }); // 处理超时场景 emitter.onTimeout(() -> emitter.completeWithError(new RuntimeException("请求超时"))); return emitter; } }
关键改动说明
- 返回类型替换:将原方法的
String返回类型改为SseEmitter,这是Spring MVC实现SSE的核心类,负责维护客户端与服务器的长连接并逐步推送数据。 - 实时推送token:在
onNext方法中,不再将token缓存到StringBuilder,而是直接通过emitter.send(token)将每个生成的token实时发送给客户端。 - 连接生命周期管理:
onComplete中调用emitter.complete(),告知客户端响应已全部发送,主动关闭连接。onError中调用emitter.completeWithError(error),将错误传递给客户端并关闭连接。- 添加超时回调,处理请求超时的异常场景。
- 超时时间对齐:SSE的超时时间与Ollama模型的超时时间保持一致,避免出现模型仍在生成但连接已断开的情况。
客户端接收示例(JavaScript)
客户端需要支持SSE协议来接收流式响应,示例代码如下:
const response = await fetch('/api/generate', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify("你的问题内容") }); const reader = response.body.getReader(); const decoder = new TextDecoder('utf-8'); while (true) { const { done, value } = await reader.read(); if (done) break; // 实时将token追加到页面元素中 document.getElementById('response-container').textContent += decoder.decode(value); }
内容的提问来源于stack exchange,提问作者Rounak Chakraborty
相关产品推荐
相关产品推荐

