Browse Source

fix(app): 修复切换推理模型后对话流式超时

chatStreamOpenAi 流开始时立即发出首片 chunk(role=assistant),确保 SSE 响应头及时 flush,避免推理模型思考阶段无输出导致前端等待首字节触发 60s 超时;AI_READ_TIMEOUT 由 120s 放宽到 300s,给推理模型思考+生成留足总时长
Spring-AI-1.1.2
wanghanlin 3 weeks ago
parent
commit
377aad48db
  1. 13
      src/main/java/com/wok/supportbot/app/AssistantApp.java
  2. 4
      src/main/java/com/wok/supportbot/config/ChatModelFactory.java

13
src/main/java/com/wok/supportbot/app/AssistantApp.java

@ -44,7 +44,6 @@ import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
@ -519,11 +518,9 @@ public class AssistantApp {
});
// 聚合所有分片用于埋点 doFinally 时取完整回复文本
StringBuilder aggregated = new StringBuilder();
// 首片标记第一片 delta 需带 role=assistant后续片仅含 content
AtomicBoolean first = new AtomicBoolean(true);
return preserveTrailingWhitespace(rawStream)
.doOnNext(aggregated::append)
.map(chunk -> buildOpenAiChunk(completionId, model, created, chunk, first.getAndSet(false), null))
.map(chunk -> buildOpenAiChunk(completionId, model, created, chunk, false, null))
.doOnComplete(() -> aiCircuitBreaker.recordSuccess(AI_CIRCUIT_KEY))
.doOnError(e -> {
aiCircuitBreaker.recordFailure(AI_CIRCUIT_KEY);
@ -543,13 +540,17 @@ public class AssistantApp {
usage != null ? usage.getTotalTokens() : null,
events));
})
// 首片 role=assistant content在流订阅时立即发出确保 SSE 响应头/首字节及时 flush
// 推理模型 doubao-seed思考阶段 delta.content 为空 preserveTrailingWhitespace 吞掉
// 若不提前发首片思考阶段将无任何字节输出前端等待首字节会触发 60s 超时
.startWith(buildOpenAiChunk(completionId, model, created, "", true, null))
// 流正常结束时追加 finish_reason=stop chunk [DONE]
.concatWith(Flux.just(
buildOpenAiChunk(completionId, model, created, "", false, "stop"),
"[DONE]"))
// 错误兜底脱敏错误信息避免泄露内部细节role 是否出现取决于此前是否已发出过内容片
// 错误兜底脱敏错误信息避免泄露内部细节首片 role 已提前发出此处不再带 role
.onErrorResume(e -> openAiFallbackStream(completionId, model, created,
"抱歉,AI 服务调用失败:" + maskError(e.getMessage()), first.get()));
"抱歉,AI 服务调用失败:" + maskError(e.getMessage()), false));
}
/**

4
src/main/java/com/wok/supportbot/config/ChatModelFactory.java

@ -66,8 +66,8 @@ public class ChatModelFactory {
/** AI 模型调用连接超时 */
private static final Duration AI_CONNECT_TIMEOUT = Duration.ofSeconds(10);
/** AI 模型调用读取超时,含流式生成时间 */
private static final Duration AI_READ_TIMEOUT = Duration.ofSeconds(120);
/** AI 模型调用读取超时,含流式生成时间(推理模型思考+生成耗时较长,放宽到 300s) */
private static final Duration AI_READ_TIMEOUT = Duration.ofSeconds(300);
/**
* 构建带超时配置的 RestClient.Builder DashScope OpenAI 兼容路径共用

Loading…
Cancel
Save