diff --git a/refine-app/src/main/java/com/achobeta/config/RagConfig.java b/refine-app/src/main/java/com/achobeta/config/RagConfig.java index 6cd9ebf..47ab998 100644 --- a/refine-app/src/main/java/com/achobeta/config/RagConfig.java +++ b/refine-app/src/main/java/com/achobeta/config/RagConfig.java @@ -100,14 +100,4 @@ public List retrieve(Query query) { }; } - // 注释掉PgVector相关的表操作方法 - // private void truncateEmbeddingTable() { - // // TODO: 使用Weaviate实现数据清理 - // log.warn("RagConfig暂未实现Weaviate数据清理"); - // } - - // private void deleteAllEmbeddingData() { - // // TODO: 使用Weaviate实现数据删除 - // log.warn("RagConfig暂未实现Weaviate数据删除"); - // } } \ No newline at end of file diff --git a/refine-domain/src/main/java/com/achobeta/domain/rag/service/impl/LearningAnalysisService.java b/refine-domain/src/main/java/com/achobeta/domain/rag/service/impl/LearningAnalysisService.java index b697c3e..cb539a2 100644 --- a/refine-domain/src/main/java/com/achobeta/domain/rag/service/impl/LearningAnalysisService.java +++ b/refine-domain/src/main/java/com/achobeta/domain/rag/service/impl/LearningAnalysisService.java @@ -1,5 +1,6 @@ package com.achobeta.domain.rag.service.impl; +import com.achobeta.domain.IRedisService; import com.achobeta.domain.rag.service.IVectorService; import com.achobeta.domain.rag.service.ILearningDynamicsService; import com.achobeta.domain.rag.model.valobj.LearningInsightVO; @@ -27,6 +28,9 @@ public class LearningAnalysisService { @Autowired private ILearningDynamicsService learningDynamicsService; + @Autowired + private IRedisService redisService; + /** * 用户登录时触发的学习动态分析 * @@ -42,10 +46,25 @@ public void onUserLogin(String userId) { if (dynamics != null && !dynamics.isEmpty()) { log.info("用户登录学习动态分析完成,userId:{} 动态数量:{}", userId, dynamics.size()); - - // 可以在这里将分析结果存储到缓存或数据库中,供前端查询使用 - // 例如:存储到Redis中,key为 "user_dynamics:" + userId - + + // 将分析结果存储到Redis缓存中,供前端快速查询使用 + String cacheKey = "user_dynamics:" + userId; + try { + // 提取描述信息并缓存 + List descriptions = dynamics.stream() + .map(LearningDynamicVO::getDescription) + .filter(desc -> desc != null && !desc.trim().isEmpty()) + .distinct() + .collect(Collectors.toList()); + + // 缓存2小时,避免数据过期 (7200秒 = 2小时) + redisService.setValue(cacheKey, descriptions, 7200 * 1000); + log.info("学习动态缓存成功,userId:{} 描述数量:{}", userId, descriptions.size()); + + } catch (Exception e) { + log.error("学习动态缓存失败,userId:{}", userId, e); + } + } else { log.info("用户登录学习动态分析完成,但未生成有效动态,userId:{}", userId); } diff --git a/refine-domain/src/main/java/com/achobeta/domain/rag/service/impl/LearningDynamicsServiceImpl.java b/refine-domain/src/main/java/com/achobeta/domain/rag/service/impl/LearningDynamicsServiceImpl.java index be3aa72..854853b 100644 --- a/refine-domain/src/main/java/com/achobeta/domain/rag/service/impl/LearningDynamicsServiceImpl.java +++ b/refine-domain/src/main/java/com/achobeta/domain/rag/service/impl/LearningDynamicsServiceImpl.java @@ -50,6 +50,7 @@ public List analyzeUserLearningDynamics(String userId) { // 3. 使用AI分析学习动态 List dynamics = new ArrayList<>(); StringBuilder responseBuilder = new StringBuilder(); + boolean hasProcessedResponse = false; // 防止重复处理 // 异步执行AI分析任务,解析题目并生成学习动态 CompletableFuture aiAnalysis = CompletableFuture.runAsync(() -> { @@ -60,14 +61,18 @@ public List analyzeUserLearningDynamics(String userId) { // 收集所有响应片段 responseBuilder.append(response); - // 检查是否收到完整的JSON响应 + // 检查是否收到完整的JSON响应,并且还没有处理过 String currentResponse = responseBuilder.toString(); - if (isCompleteJsonResponse(currentResponse)) { + if (!hasProcessedResponse && isCompleteJsonResponse(currentResponse)) { log.info("检测到完整JSON响应,开始解析"); // 解析完整的AI返回的JSON格式学习动态 List parsedDynamics = parseAIResponse(currentResponse); - dynamics.addAll(parsedDynamics); - log.info("成功解析AI响应,获得{}条动态", parsedDynamics.size()); + synchronized (dynamics) { + if (dynamics.isEmpty()) { // 确保只添加一次 + dynamics.addAll(parsedDynamics); + log.info("成功解析AI响应,获得{}条动态", parsedDynamics.size()); + } + } } } catch (Exception e) { log.error("解析AI分析结果失败:{}", response, e); diff --git a/refine-trigger/src/main/java/com/achobeta/trigger/http/LearningOverviewController.java b/refine-trigger/src/main/java/com/achobeta/trigger/http/LearningOverviewController.java index 3b48196..4bbe0a8 100644 --- a/refine-trigger/src/main/java/com/achobeta/trigger/http/LearningOverviewController.java +++ b/refine-trigger/src/main/java/com/achobeta/trigger/http/LearningOverviewController.java @@ -35,9 +35,11 @@ public class LearningOverviewController { private final ILearningOverviewService service; private final ILearningDynamicsService learningDynamicsService; + private final IRedisService redisService; /** * 获取学习概览 + * * @return 学习概览 */ @GetMapping("/get_overview") @@ -62,43 +64,89 @@ public Response getOverview() { /** * 获取学习动态 + * * @return 学习动态描述列表 */ @GetMapping("/get_study_dynamic") @GlobalInterception - public Response> getStudyDynamic(){ + public Response> getStudyDynamic() { String userId = UserContext.getUserId(); List result = null; try { log.info("用户获取学习动态,userId:{}", userId); + + // 优先从缓存获取数据 + String cacheKey = "user_dynamics:" + userId; + log.info("尝试从缓存获取数据,cacheKey: {}", cacheKey); - // 获取学习动态数据 - List dynamics = + Object cachedData = redisService.getValue(cacheKey); + log.info("缓存查询结果: {}", cachedData != null ? "有数据" : "无数据"); + + if (cachedData != null) { + log.info("从缓存获取学习动态,userId: {}, 数据类型: {}", userId, cachedData.getClass().getSimpleName()); + try { + if (cachedData instanceof List) { + result = (List) cachedData; + log.info("缓存命中,返回{}条学习动态描述", result.size()); + return Response.SYSTEM_SUCCESS(result); + } else if (cachedData instanceof String) { + // 如果是字符串,尝试解析为JSON + String jsonStr = (String) cachedData; + log.info("缓存数据为字符串,尝试解析JSON: {}", jsonStr); + // 这里可以添加JSON解析逻辑 + } else { + log.warn("缓存数据类型不匹配,期望List,实际: {}, 数据内容: {}", + cachedData.getClass().getSimpleName(), cachedData); + } + } catch (Exception e) { + log.error("处理缓存数据失败", e); + } + } + + log.info("缓存未命中,实时分析学习动态,userId: {}", userId); + + // 缓存未命中,实时获取学习动态数据 + List dynamics = learningDynamicsService.analyzeUserLearningDynamics(userId); - + log.info("获取到学习动态数量: {}", dynamics != null ? dynamics.size() : 0); - + if (dynamics == null || dynamics.isEmpty()) { log.warn("未获取到学习动态数据,userId: {}", userId); return Response.SYSTEM_SUCCESS(java.util.Collections.emptyList()); } - + // 提取描述信息 result = dynamics.stream() .map(dynamic -> { - log.debug("处理学习动态: type={}, title={}, description={}", + log.debug("处理学习动态: type={}, title={}, description={}", dynamic.getType(), dynamic.getTitle(), dynamic.getDescription()); return dynamic.getDescription(); }) .filter(description -> description != null && !description.trim().isEmpty()) + .distinct() // 去重,防止重复的描述 .collect(java.util.stream.Collectors.toList()); - + log.info("最终返回描述数量: {}", result.size()); - + + // 将结果缓存起来,缓存30分钟 (1800秒 = 30分钟) + try { + log.info("准备缓存学习动态结果,cacheKey: {}, 数据: {}", cacheKey, result); + redisService.setValue(cacheKey, result, 1800 * 1000); + log.info("学习动态结果已缓存,userId: {}, 缓存时间: 30分钟", userId); + + // 验证缓存是否成功 + Object verifyCache = redisService.getValue(cacheKey); + log.info("缓存验证结果: {}", verifyCache != null ? "缓存成功" : "缓存失败"); + } catch (Exception e) { + log.error("缓存学习动态结果失败,userId: {}", userId, e); + } + } catch (Exception e) { log.error("getStudyDynamic error", e); return Response.CUSTOMIZE_ERROR(GET_STUDY_DYNAMIC_FAIL); } return Response.SYSTEM_SUCCESS(result); } + }