Java 11下如何让Azure OpenAI返回流式事件?现有代码无流式效果
问题:Azure OpenAI流式响应未生效,一次性返回完整内容
我用以下Java代码调用Azure OpenAI API想实现流式响应,但代码运行后没有逐词返回效果,而是像普通HTTP请求一样一次性返回完整内容。Gradle依赖为implementation 'com.azure:azure-ai-openai:1.0.0-beta.2',代码如下:
public void getChatCompletion(SseEmitter emitter, String prompt, String azureOpenaiKey) { String endpoint = "https://xxxx.openai.azure.com/"; String deploymentOrModelId = "xxx-ai"; OpenAIClient client = new OpenAIClientBuilder() .endpoint(endpoint) .credential(new AzureKeyCredential(azureOpenaiKey)) .buildClient(); List<ChatMessage> chatMessages = new ArrayList<>(); chatMessages.add(new ChatMessage(ChatRole.SYSTEM).setContent("You are a helpful assistant.")); chatMessages.add(new ChatMessage(ChatRole.USER).setContent(prompt)); ChatCompletionsOptions options = new ChatCompletionsOptions(chatMessages); options.setStream(true); options.setModel("gpt-3.5-turbo-0613"); IterableStream<ChatCompletions> chatCompletions = client.getChatCompletionsStream(deploymentOrModelId, options); chatCompletions.forEach(completions->{ try { emitter.send(completions); } catch (Exception e) { log.error("send emit message error", e); } }); }
解决方案
导致流式效果失效的核心问题有以下几点,对应修正方案如下:
升级依赖版本:1.0.0-beta.2属于早期预览版本,对流式响应的支持存在缺陷,建议升级到最新的稳定版或较新预览版,比如:
implementation 'com.azure:azure-ai-openai:1.0.0'正确处理流式数据的遍历与发送:原代码中
forEach遍历IterableStream时,底层可能会先缓存所有响应块再统一处理,无法实现实时推送。需改用迭代器手动遍历,且提取每个响应块中的增量token内容发送,而非整个ChatCompletions对象。确认Azure模型部署配置:确保Azure门户中部署的
xxx-ai是支持流式的模型(如gpt-3.5-turbo系列),且部署配置未限制流式功能。
修正后的代码示例
public void getChatCompletion(SseEmitter emitter, String prompt, String azureOpenaiKey) { String endpoint = "https://xxxx.openai.azure.com/"; String deploymentOrModelId = "xxx-ai"; OpenAIClient client = new OpenAIClientBuilder() .endpoint(endpoint) .credential(new AzureKeyCredential(azureOpenaiKey)) .buildClient(); List<ChatMessage> chatMessages = new ArrayList<>(); chatMessages.add(new ChatMessage(ChatRole.SYSTEM).setContent("You are a helpful assistant.")); chatMessages.add(new ChatMessage(ChatRole.USER).setContent(prompt)); ChatCompletionsOptions options = new ChatCompletionsOptions(chatMessages); options.setStream(true); // 无需手动设置Model,deploymentOrModelId已对应Azure部署的模型 // options.setModel("gpt-3.5-turbo-0613"); IterableStream<ChatCompletions> chatCompletions = client.getChatCompletionsStream(deploymentOrModelId, options); // 用迭代器手动遍历,实时处理每个响应块 Iterator<ChatCompletions> iterator = chatCompletions.iterator(); while (iterator.hasNext()) { try { ChatCompletions completions = iterator.next(); // 提取当前响应块的增量token内容 String deltaContent = completions.getChoices().get(0).getDelta().getContent(); if (deltaContent != null && !deltaContent.isEmpty()) { // 发送增量内容到前端 emitter.send(SseEmitter.event().data(deltaContent)); // 可选:添加短暂延迟模拟逐词输出效果(按需调整) Thread.sleep(50); } } catch (Exception e) { log.error("发送流式消息失败", e); emitter.completeWithError(e); return; } } // 流式响应结束,关闭Sse连接 emitter.complete(); }
关键修改说明
- 移除了手动设置
Model的代码,deploymentOrModelId已对应Azure部署的模型,无需重复指定; - 改用
Iterator遍历流,确保每收到一个响应块就立即处理; - 提取
delta.content(增量token)发送,仅推送新增内容,而非整个响应对象; - 补充了流式结束后的连接关闭逻辑,以及异常时的错误处理,保证Sse连接生命周期完整。
内容的提问来源于stack exchange,提问作者Dolphin
相关产品推荐
相关产品推荐

