diff --git a/src/main/java/com/guo/learningprogresstracker/service/impl/AiServiceClient.java b/src/main/java/com/guo/learningprogresstracker/service/impl/AiServiceClient.java
index d3ebcaf..7f2dd74 100644
--- a/src/main/java/com/guo/learningprogresstracker/service/impl/AiServiceClient.java
+++ b/src/main/java/com/guo/learningprogresstracker/service/impl/AiServiceClient.java
@@ -13,6 +13,7 @@ import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
+import java.time.Instant;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@@ -20,6 +21,10 @@ import java.util.Optional;
/**
* lpt-ai 独立 AI 服务客户端。
*
通过 {@code lpt.ai-service.url} 配置服务地址;未配置或调用失败时返回 empty,由调用方降级。
+ *
+ * 内部使用异步任务模式:提交任务到 lpt-ai 后轮询等待结果,
+ * 避免同步等待 LLM 响应时阻塞 HTTP 连接。
+ *
*/
@Slf4j
@Component
@@ -29,8 +34,8 @@ public class AiServiceClient {
/** lpt-ai 服务地址,如 http://localhost:5199 */
private String url;
- /** 超时秒数 */
- private int timeoutSeconds = 90;
+ /** 超时秒数(等待 AI 任务完成的最长时间) */
+ private int timeoutSeconds = 600;
private HttpClient httpClient;
private final ObjectMapper objectMapper = new ObjectMapper();
@@ -41,9 +46,9 @@ public class AiServiceClient {
.connectTimeout(Duration.ofSeconds(10))
.build();
if (isConfigured()) {
- log.info("AiServiceClient 已配置: {}", url);
+ log.info("AiServiceClient 已配置: {} (超时 {}s, 异步任务模式)", url, timeoutSeconds);
} else {
- log.info("AiServiceClient 未配置,AI 聚合功能不可用(将降级为拼接)");
+ log.info("AiServiceClient 未配置,AI 功能不可用(将降级为内置逻辑)");
}
}
@@ -51,10 +56,10 @@ public class AiServiceClient {
return url != null && !url.isBlank();
}
+ // ============ 公开 API(签名不变,内部改为 submit + poll)============
+
/**
* 调用 lpt-ai 将残片聚合为学习报告草稿。
- *
- * @return 聚合后的报告文本;服务未配置或调用失败时返回 empty
*/
public Optional aggregateReport(String taskName, List fragments, String expectation) {
if (!isConfigured() || fragments == null || fragments.isEmpty()) {
@@ -64,36 +69,20 @@ public class AiServiceClient {
List