package com.guo.learningprogresstracker.service.impl; import com.guo.learningprogresstracker.entity.StudyReportsEntity; import com.guo.learningprogresstracker.entity.TaskApplicationEntity; import com.guo.learningprogresstracker.entity.TaskEntity; import com.guo.learningprogresstracker.service.MindMapAiClient; import com.guo.learningprogresstracker.utils.MindMapNode; import com.guo.learningprogresstracker.utils.MindMapTreeTool; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; /** * 远程 AI 思维导图生成客户端。 *

通过 lpt-ai 服务({@code lpt.ai-service.url})调用大语言模型生成思维导图。 * 未配置 lpt-ai 时不可用,会回退到 {@link BuiltinMindMapGenerator}。

*/ @Slf4j @Component @RequiredArgsConstructor public class RemoteAiMindMapClient implements MindMapAiClient { private final AiServiceClient aiServiceClient; @Override public boolean isAvailable() { return aiServiceClient.isConfigured(); } @Override public String generatorName() { return "AI"; } @Override public Optional generate(TaskEntity task, List reports, List applications, String clientHint) { if (!isAvailable()) { return Optional.empty(); } // 提取学习报告的内容文本 List reportTexts = reports.stream() .map(StudyReportsEntity::getContent) .filter(c -> c != null && !c.isBlank()) .collect(Collectors.toList()); if (reportTexts.isEmpty()) { return Optional.empty(); } Optional optOutline = aiServiceClient.generateMindMap( task.getTaskName(), task.getTaskDescription(), reportTexts ); if (optOutline.isEmpty() || optOutline.get().isBlank()) { log.warn("RemoteAiMindMapClient: lpt-ai 返回空大纲,降级"); return Optional.empty(); } String outline = optOutline.get(); MindMapNode root = MindMapTreeTool.parseOutline(outline); log.info("RemoteAiMindMapClient: 为任务[{}]生成 AI 导图,共 {} 个节点,{} 层", task.getTaskNum(), MindMapTreeTool.countNodes(root), MindMapTreeTool.maxDepth(root)); return Optional.of(root); } }