You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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();
}

关键修改说明

  1. 移除了手动设置Model的代码,deploymentOrModelId已对应Azure部署的模型,无需重复指定;
  2. 改用Iterator遍历流,确保每收到一个响应块就立即处理;
  3. 提取delta.content(增量token)发送,仅推送新增内容,而非整个响应对象;
  4. 补充了流式结束后的连接关闭逻辑,以及异常时的错误处理,保证Sse连接生命周期完整。

内容的提问来源于stack exchange,提问作者Dolphin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 10:17:47