diff --git a/README.md b/README.md index 6b997db3..a49af646 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ ## 规划 -- [ ] 实现全局异常捕获,并对异常发生时的状态(主要是流转上下文`InteractionContext`、`SessionManager`、`MemoryGraph`)进行快照保存,方便后续问题排查。 +- [ ] 抽取提示词到resources文件夹中 - [ ] 发现通过用户引导可以使得LLM展现出一定的“自我认知”,尽管仍是语义推理,但对于Partner应当足够,这一点尽量应用到各个模块中。 - [ ] 当前主模型对于对话缓存中的记忆有些‘过度回应’,`MemorySelector`处的动态提示词或需要进一步调整。 - [ ] 实现身份感知模块(用户识别、熟悉度判断、记忆片段检索、人物画像、对话口吻调整)。 diff --git a/src/main/java/work/slhaf/agent/common/exception_handler/GlobalExceptionHandler.java b/src/main/java/work/slhaf/agent/common/exception_handler/GlobalExceptionHandler.java index 063ca8aa..521a1f72 100644 --- a/src/main/java/work/slhaf/agent/common/exception_handler/GlobalExceptionHandler.java +++ b/src/main/java/work/slhaf/agent/common/exception_handler/GlobalExceptionHandler.java @@ -1,12 +1,10 @@ package work.slhaf.agent.common.exception_handler; import lombok.extern.slf4j.Slf4j; +import work.slhaf.agent.common.exception_handler.pojo.GlobalException; import work.slhaf.agent.common.exception_handler.pojo.GlobalExceptionData; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.ObjectOutputStream; +import java.io.*; import java.nio.file.Path; import java.nio.file.Paths; @@ -15,7 +13,8 @@ public class GlobalExceptionHandler { private static final String EXCEPTION_STATIC_PATH = "./data/exception_snapshot/"; - public static void writeExceptionState(GlobalExceptionData exceptionData) { + public static void writeExceptionState(GlobalException exception) { + GlobalExceptionData exceptionData = exception.getData(); Path filePath = Paths.get(EXCEPTION_STATIC_PATH, String.valueOf(exceptionData.getExceptionTime()), ".dat"); try { ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filePath.toFile())); @@ -26,4 +25,17 @@ public class GlobalExceptionHandler { log.error("[GlobalExceptionHandler] 捕获异常, 保存失败: ", e); } } + + public static GlobalExceptionData readExceptionState(String filePath) { + try { + ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filePath)); + GlobalExceptionData exceptionData = (GlobalExceptionData) ois.readObject(); + ois.close(); + log.info("[GlobalExceptionHandler] 已从: {} 读取异常快照", filePath); + return exceptionData; + } catch (IOException | ClassNotFoundException e) { + log.error("[GlobalExceptionHandler] 读取异常, 读取失败: ", e); + return null; + } + } } diff --git a/src/main/java/work/slhaf/agent/core/InteractionHub.java b/src/main/java/work/slhaf/agent/core/InteractionHub.java index 303a9431..646a6831 100644 --- a/src/main/java/work/slhaf/agent/core/InteractionHub.java +++ b/src/main/java/work/slhaf/agent/core/InteractionHub.java @@ -47,7 +47,7 @@ public class InteractionHub { interactionModule.execute(interactionContext); } } catch (GlobalException e) { - GlobalExceptionHandler.writeExceptionState(e.getData()); + GlobalExceptionHandler.writeExceptionState(e); interactionContext.getCoreResponse().put("text", "[ERROR] " + e.getMessage()); } finally { callback.onTaskFinished(interactionContext.getUserInfo(), interactionContext.getCoreResponse().getString("text")); diff --git a/src/main/java/work/slhaf/agent/core/memory/MemoryGraph.java b/src/main/java/work/slhaf/agent/core/memory/MemoryGraph.java index 0fab4da6..fed34f67 100644 --- a/src/main/java/work/slhaf/agent/core/memory/MemoryGraph.java +++ b/src/main/java/work/slhaf/agent/core/memory/MemoryGraph.java @@ -6,6 +6,7 @@ import lombok.EqualsAndHashCode; import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.FileUtils; import work.slhaf.agent.common.chat.pojo.Message; +import work.slhaf.agent.common.exception_handler.GlobalExceptionHandler; import work.slhaf.agent.common.exception_handler.pojo.GlobalException; import work.slhaf.agent.common.pojo.PersistableObject; import work.slhaf.agent.core.memory.exception.UnExistedDateIndexException; @@ -198,18 +199,17 @@ public class MemoryGraph extends PersistableObject { } public void insertMemory(List topicPath, MemorySlice slice) throws IOException, ClassNotFoundException { - //检查是否存在当天对应的memorySlice并确定是否插入 - LocalDate now = LocalDate.now(); - boolean hasSlice = false; - MemoryNode node = null; - TopicNode lastTopicNode; + try { + //检查是否存在当天对应的memorySlice并确定是否插入 + LocalDate now = LocalDate.now(); + boolean hasSlice = false; + MemoryNode node = null; //每日刷新缓存 checkCacheDate(); //如果topicPath在memorySliceCache中存在对应缓存,由于进行的插入操作,则需要移除该缓存,但不清除相关计数 memorySliceCache.remove(topicPath); - lastTopicNode = generateTopicPath(topicPath); - + TopicNode lastTopicNode = generateTopicPath(topicPath); for (MemoryNode memoryNode : lastTopicNode.getMemoryNodes()) { if (now.equals(memoryNode.getLocalDate())) { hasSlice = true; @@ -217,32 +217,32 @@ public class MemoryGraph extends PersistableObject { break; } } + if (!hasSlice) { + node = new MemoryNode(); + node.setLocalDate(now); + node.setMemoryNodeId(UUID.randomUUID().toString()); + node.setMemorySliceList(new CopyOnWriteArrayList<>()); + lastTopicNode.getMemoryNodes().add(node); + lastTopicNode.getMemoryNodes().sort(null); + } + node.loadMemorySliceList().add(slice); + + //生成relatedTopicPath + for (List relatedTopic : slice.getRelatedTopics()) { + generateTopicPath(relatedTopic); + } + + updateSlicePrecedent(slice); + updateDateIndex(slice); + + if (!slice.isPrivate()) { + updateUserDialogMap(slice); + } + node.saveMemorySliceList(); } catch (Exception e) { log.error("插入记忆时出错: ", e); - throw new GlobalException(e.getLocalizedMessage()); + GlobalExceptionHandler.writeExceptionState(new GlobalException("插入记忆时出错: " + e.getLocalizedMessage())); } - if (!hasSlice) { - node = new MemoryNode(); - node.setLocalDate(now); - node.setMemoryNodeId(UUID.randomUUID().toString()); - node.setMemorySliceList(new CopyOnWriteArrayList<>()); - lastTopicNode.getMemoryNodes().add(node); - lastTopicNode.getMemoryNodes().sort(null); - } - node.loadMemorySliceList().add(slice); - - //生成relatedTopicPath - for (List relatedTopic : slice.getRelatedTopics()) { - generateTopicPath(relatedTopic); - } - - updateSlicePrecedent(slice); - updateDateIndex(slice); - - if (!slice.isPrivate()) { - updateUserDialogMap(slice); - } - node.saveMemorySliceList(); } private void updateDateIndex(MemorySlice slice) { @@ -407,6 +407,7 @@ public class MemoryGraph extends PersistableObject { memoryResult = new MemoryResult(); memoryResult.setRelatedMemorySliceResult(new ArrayList<>()); memoryResult.setMemorySliceResult(new CopyOnWriteArrayList<>()); + GlobalExceptionHandler.writeExceptionState(new GlobalException(e.getLocalizedMessage())); } return memoryResult; } @@ -532,7 +533,6 @@ public class MemoryGraph extends PersistableObject { public void updateDialogMap(LocalDateTime dateTime, String newDialogCache) { List keysToRemove = new ArrayList<>(); - dialogMap.forEach((k, v) -> { if (dateTime.minusDays(2).isAfter(k)) { keysToRemove.add(k); @@ -544,7 +544,6 @@ public class MemoryGraph extends PersistableObject { keysToRemove.clear(); //放入新缓存 dialogMap.put(dateTime, newDialogCache); - } } diff --git a/src/main/java/work/slhaf/agent/modules/memory/selector/MemorySelector.java b/src/main/java/work/slhaf/agent/modules/memory/selector/MemorySelector.java index bb648d91..6ed2c39e 100644 --- a/src/main/java/work/slhaf/agent/modules/memory/selector/MemorySelector.java +++ b/src/main/java/work/slhaf/agent/modules/memory/selector/MemorySelector.java @@ -2,6 +2,8 @@ package work.slhaf.agent.modules.memory.selector; import lombok.Data; import lombok.extern.slf4j.Slf4j; +import work.slhaf.agent.common.exception_handler.GlobalExceptionHandler; +import work.slhaf.agent.common.exception_handler.pojo.GlobalException; import work.slhaf.agent.core.interaction.InteractionModule; import work.slhaf.agent.core.interaction.data.InteractionContext; import work.slhaf.agent.core.memory.MemoryManager; @@ -115,7 +117,7 @@ public class MemorySelector implements InteractionModule { if (recall) { interactionContext.getModuleContext().put("recall_count", memoryManager.getActivatedSlices().get(userId).size()); } - interactionContext.getModulePrompt().add( modulePrompt); + interactionContext.getModulePrompt().add(modulePrompt); log.debug("[MemorySelector] 记忆回溯结果: {}", interactionContext); } @@ -131,7 +133,8 @@ public class MemorySelector implements InteractionModule { if (memoryResult == null) continue; memoryResultList.add(memoryResult); } catch (UnExistedDateIndexException | UnExistedTopicException e) { - log.error("[MemorySelector] 不存在的记忆索引! 请尝试更换更合适的主题提取LLM!"); + log.error("[MemorySelector] 不存在的记忆索引! 请尝试更换更合适的主题提取LLM!", e); + GlobalExceptionHandler.writeExceptionState(new GlobalException(e.getMessage())); } } //清理切片记录 diff --git a/src/main/java/work/slhaf/agent/modules/memory/selector/extractor/MemorySelectExtractor.java b/src/main/java/work/slhaf/agent/modules/memory/selector/extractor/MemorySelectExtractor.java index 2c6591ea..933601ac 100644 --- a/src/main/java/work/slhaf/agent/modules/memory/selector/extractor/MemorySelectExtractor.java +++ b/src/main/java/work/slhaf/agent/modules/memory/selector/extractor/MemorySelectExtractor.java @@ -8,6 +8,8 @@ import lombok.extern.slf4j.Slf4j; import work.slhaf.agent.common.chat.pojo.Message; import work.slhaf.agent.common.chat.pojo.MetaMessage; import work.slhaf.agent.common.config.Config; +import work.slhaf.agent.common.exception_handler.GlobalExceptionHandler; +import work.slhaf.agent.common.exception_handler.pojo.GlobalException; import work.slhaf.agent.common.model.Model; import work.slhaf.agent.common.model.ModelConstant; import work.slhaf.agent.core.interaction.data.InteractionContext; @@ -77,7 +79,8 @@ public class MemorySelectExtractor extends Model { extractorResult = JSONObject.parseObject(responseStr, ExtractorResult.class); log.debug("[MemorySelectExtractor] 主题提取结果: {}",extractorResult); } catch (Exception e) { - log.error("[MemorySelectExtractor] 主题提取出错: {}", e.getLocalizedMessage()); + log.error("[MemorySelectExtractor] 主题提取出错: ", e); + GlobalExceptionHandler.writeExceptionState(new GlobalException(e.getLocalizedMessage())); extractorResult = new ExtractorResult(); extractorResult.setRecall(false); extractorResult.setMatches(List.of()); @@ -85,10 +88,4 @@ public class MemorySelectExtractor extends Model { return extractorResult; } - public static class Constant { - public static final String NONE = "none"; - public static final String DATE = "date"; - public static final String TOPIC = "topic"; - } - } diff --git a/src/main/java/work/slhaf/agent/modules/memory/updater/MemoryUpdater.java b/src/main/java/work/slhaf/agent/modules/memory/updater/MemoryUpdater.java index 6c56fb9b..b9879ffa 100644 --- a/src/main/java/work/slhaf/agent/modules/memory/updater/MemoryUpdater.java +++ b/src/main/java/work/slhaf/agent/modules/memory/updater/MemoryUpdater.java @@ -103,6 +103,7 @@ public class MemoryUpdater implements InteractionModule { log.debug("[MemoryUpdater] 记忆切片数量 [{}]",recallCount); tokenLimit += recallCount * TOKEN_PER_RECALL; } + //TODO 调整为根据轮次触发记忆插入 if (moduleContext.getIntValue("total_token") > tokenLimit) { try { log.debug("[MemoryUpdater] 记忆更新: token超限"); @@ -161,7 +162,7 @@ public class MemoryUpdater implements InteractionModule { log.debug("[MemoryUpdater] 对话缓存更新完毕"); log.debug("[MemoryUpdater] 多人聊天记忆更新流程结束..."); } catch (IOException | ClassNotFoundException | InterruptedException e) { - log.error("[MemoryUpdater] 多人场景记忆更新失败: {}", e.getLocalizedMessage()); + log.error("[MemoryUpdater] 多人场景记忆更新失败: ", e); } }); }