重构认知模块、着手感知模块相关开发

- 调整MemoryManager为CognationManager
- 由于CognationManager方法数量过多,根据能力分类抽取为四个主要接口CognationCapability、CacheCapability、MemoryCapability、PerceiveCapability
- 开始推进感知模块开发
This commit is contained in:
2025-06-11 16:48:55 +08:00
parent d11d39ea81
commit f5c37f26a5
33 changed files with 515 additions and 266 deletions

View File

@@ -3,8 +3,8 @@ package work.slhaf.agent.common.exception_handler.pojo;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j;
import work.slhaf.agent.core.cognation.CognationManager;
import work.slhaf.agent.core.interaction.data.context.InteractionContext;
import work.slhaf.agent.core.memory.MemoryManager;
import work.slhaf.agent.core.session.SessionManager;
@EqualsAndHashCode(callSuper = true)
@@ -20,7 +20,7 @@ public class GlobalException extends RuntimeException {
this.data = new GlobalExceptionData();
this.data.setExceptionTime(System.currentTimeMillis());
this.data.setSessionManager(SessionManager.getInstance());
this.data.setMemoryManager(MemoryManager.getInstance());
this.data.setCognationManager(CognationManager.getInstance());
this.data.setContext(InteractionContext.getInstance());
} catch (Exception e) {
log.error("[GlobalException] 捕获异常, 获取数据失败");

View File

@@ -3,8 +3,8 @@ package work.slhaf.agent.common.exception_handler.pojo;
import lombok.Data;
import lombok.EqualsAndHashCode;
import work.slhaf.agent.common.serialize.PersistableObject;
import work.slhaf.agent.core.cognation.CognationManager;
import work.slhaf.agent.core.interaction.data.context.InteractionContext;
import work.slhaf.agent.core.memory.MemoryManager;
import work.slhaf.agent.core.session.SessionManager;
import java.io.Serial;
@@ -21,6 +21,6 @@ public class GlobalExceptionData extends PersistableObject {
protected HashMap<String, InteractionContext> context;
protected SessionManager sessionManager;
protected MemoryManager memoryManager;
protected CognationManager cognationManager;
protected Long exceptionTime;
}

View File

@@ -0,0 +1,23 @@
package work.slhaf.agent.core.cognation;
import work.slhaf.agent.common.chat.pojo.Message;
import work.slhaf.agent.shared.memory.EvaluatedSlice;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;
public interface CognationCapability {
List<Message> getChatMessages();
void setChatMessages(List<Message> chatMessages);
void cleanMessage(List<Message> messages);
void updateActivatedSlices(String userId, List<EvaluatedSlice> memorySlices);
String getActivatedSlicesStr(String userId);
HashMap<String, List<EvaluatedSlice>> getActivatedSlices();
void clearActivatedSlices(String userId);
boolean hasActivatedSlices(String userId);
int getActivatedSlicesSize(String userId);
List<EvaluatedSlice> getActivatedSlices(String userId);
boolean isSingleUser();
ReentrantLock getMessageLock();
}

View File

@@ -1,4 +1,4 @@
package work.slhaf.agent.core.memory;
package work.slhaf.agent.core.cognation;
import lombok.Data;
import lombok.EqualsAndHashCode;
@@ -6,61 +6,62 @@ import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import work.slhaf.agent.common.chat.pojo.Message;
import work.slhaf.agent.common.serialize.PersistableObject;
import work.slhaf.agent.core.memory.submodule.cache.CacheCore;
import work.slhaf.agent.core.memory.submodule.graph.GraphCore;
import work.slhaf.agent.core.memory.submodule.perceive.PerceiveCore;
import work.slhaf.agent.core.cognation.submodule.cache.CacheCore;
import work.slhaf.agent.core.cognation.submodule.memory.MemoryCore;
import work.slhaf.agent.core.cognation.submodule.perceive.PerceiveCore;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.List;
@EqualsAndHashCode(callSuper = true)
@Data
@Slf4j
public class MemoryCore extends PersistableObject {
public class CognationCore extends PersistableObject {
@Serial
private static final long serialVersionUID = 1L;
private static final String STORAGE_DIR = "./data/memory/";
private static volatile MemoryCore memoryCore;
private static volatile CognationCore cognationCore;
private String id;
private GraphCore graphCore = new GraphCore();
private MemoryCore memoryCore = new MemoryCore();
private CacheCore cacheCore = new CacheCore();
private PerceiveCore perceiveCore = new PerceiveCore();
/**
* 主模型的聊天记录
*/
private List<Message> chatMessages;
private List<Message> chatMessages = new ArrayList<>();
public MemoryCore(String id) {
public CognationCore(String id) {
this.id = id;
}
public static MemoryCore getInstance(String id) throws IOException, ClassNotFoundException {
if (memoryCore == null) {
synchronized (MemoryCore.class) {
public static CognationCore getInstance(String id) throws IOException, ClassNotFoundException {
if (cognationCore == null) {
synchronized (CognationCore.class) {
// 检查存储目录是否存在不存在则创建
if (memoryCore == null) {
if (cognationCore == null) {
createStorageDirectory();
Path filePath = getFilePath(id);
if (Files.exists(filePath)) {
memoryCore = deserialize(id);
cognationCore = deserialize(id);
} else {
FileUtils.createParentDirectories(filePath.toFile().getParentFile());
memoryCore = new MemoryCore(id);
memoryCore.serialize();
cognationCore = new CognationCore(id);
cognationCore.serialize();
}
log.info("MemoryGraph注册完毕...");
log.info("CognationCore注册完毕...");
}
}
}
return memoryCore;
return cognationCore;
}
public void serialize() throws IOException {
@@ -73,19 +74,19 @@ public class MemoryCore extends PersistableObject {
oos.close();
Path path = getFilePath(this.id);
Files.move(filePath, path, StandardCopyOption.REPLACE_EXISTING);
log.info("MemoryCore 已保存到: {}", path);
log.info("CognationCore 已保存到: {}", path);
} catch (IOException e) {
Files.delete(filePath);
log.error("序列化保存失败: {}", e.getMessage());
}
}
private static MemoryCore deserialize(String id) throws IOException, ClassNotFoundException {
private static CognationCore deserialize(String id) throws IOException, ClassNotFoundException {
Path filePath = getFilePath(id);
try (ObjectInputStream ois = new ObjectInputStream(
new FileInputStream(filePath.toFile()))) {
MemoryCore graph = (MemoryCore) ois.readObject();
log.info("MemoryCore 已从文件加载: {}", filePath);
CognationCore graph = (CognationCore) ois.readObject();
log.info("CognationCore 已从文件加载: {}", filePath);
return graph;
}
}

View File

@@ -1,4 +1,4 @@
package work.slhaf.agent.core.memory;
package work.slhaf.agent.core.cognation;
import lombok.Data;
import lombok.EqualsAndHashCode;
@@ -9,13 +9,18 @@ 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.serialize.PersistableObject;
import work.slhaf.agent.core.memory.pojo.MemoryResult;
import work.slhaf.agent.core.memory.pojo.MemorySliceResult;
import work.slhaf.agent.core.memory.submodule.cache.CacheCore;
import work.slhaf.agent.core.memory.submodule.graph.GraphCore;
import work.slhaf.agent.core.memory.submodule.graph.pojo.MemorySlice;
import work.slhaf.agent.core.memory.submodule.perceive.PerceiveCore;
import work.slhaf.agent.core.memory.submodule.perceive.pojo.User;
import work.slhaf.agent.core.cognation.common.exception.UserNotExistsException;
import work.slhaf.agent.core.cognation.common.pojo.ActiveData;
import work.slhaf.agent.core.cognation.common.pojo.MemoryResult;
import work.slhaf.agent.core.cognation.common.pojo.MemorySliceResult;
import work.slhaf.agent.core.cognation.submodule.cache.CacheCapability;
import work.slhaf.agent.core.cognation.submodule.cache.CacheCore;
import work.slhaf.agent.core.cognation.submodule.memory.MemoryCapability;
import work.slhaf.agent.core.cognation.submodule.memory.MemoryCore;
import work.slhaf.agent.core.cognation.submodule.memory.pojo.MemorySlice;
import work.slhaf.agent.core.cognation.submodule.perceive.PerceiveCapability;
import work.slhaf.agent.core.cognation.submodule.perceive.PerceiveCore;
import work.slhaf.agent.core.cognation.submodule.perceive.pojo.User;
import work.slhaf.agent.shared.memory.EvaluatedSlice;
import java.io.IOException;
@@ -29,65 +34,65 @@ import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import static work.slhaf.agent.common.util.ExtractUtil.extractUserId;
@EqualsAndHashCode(callSuper = true)
@Data
@Slf4j
public class MemoryManager extends PersistableObject {
public class CognationManager extends PersistableObject implements CacheCapability, MemoryCapability, PerceiveCapability, CognationCapability {
@Serial
private static final long serialVersionUID = 1L;
private static volatile MemoryManager memoryManager;
private static volatile CognationManager cognationManager;
private final Lock sliceInsertLock = new ReentrantLock();
public final Lock messageLock = new ReentrantLock();
private MemoryCore memoryCore;
private CognationCore cognationCore;
private CacheCore cacheCore;
private GraphCore graphCore;
private MemoryCore memoryCore;
private PerceiveCore perceiveCore;
private HashMap<String, List<EvaluatedSlice>> activatedSlices;
private ActiveData activeData;
private MemoryManager() {
private CognationManager() {
}
public static MemoryManager getInstance() throws IOException, ClassNotFoundException {
if (memoryManager == null) {
synchronized (MemoryManager.class) {
if (memoryManager == null) {
public static CognationManager getInstance() throws IOException, ClassNotFoundException {
if (cognationManager == null) {
synchronized (CognationManager.class) {
if (cognationManager == null) {
Config config = Config.getConfig();
memoryManager = new MemoryManager();
memoryManager.setMemoryCore(MemoryCore.getInstance(config.getAgentId()));
memoryManager.setCores();
memoryManager.setActivatedSlices(new HashMap<>());
memoryManager.setShutdownHook();
log.info("[MemoryManager] MemoryManager注册完毕...");
cognationManager = new CognationManager();
cognationManager.setCognationCore(CognationCore.getInstance(config.getAgentId()));
cognationManager.setCores();
cognationManager.setActiveData(new ActiveData());
cognationManager.setShutdownHook();
log.info("[CognationManager] MemoryManager注册完毕...");
}
}
}
return memoryManager;
return cognationManager;
}
private void setCores() {
this.setCacheCore(this.getMemoryCore().getCacheCore());
this.setGraphCore(this.getMemoryCore().getGraphCore());
this.setPerceiveCore(this.getMemoryCore().getPerceiveCore());
this.setCacheCore(this.getCognationCore().getCacheCore());
this.setMemoryCore(this.getCognationCore().getMemoryCore());
this.setPerceiveCore(this.getCognationCore().getPerceiveCore());
}
private void setShutdownHook() {
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
try {
memoryManager.save();
log.info("[MemoryManager] MemoryGraph已保存");
cognationManager.save();
log.info("[CognationManager] MemoryGraph已保存");
} catch (IOException e) {
log.error("[MemoryManager] 保存MemoryGraph失败: ", e);
log.error("[CognationManager] 保存MemoryGraph失败: ", e);
}
}));
}
@Override
public MemoryResult selectMemory(String topicPathStr) {
MemoryResult memoryResult;
List<String> topicPath = List.of(topicPathStr.split("->"));
@@ -101,13 +106,13 @@ public class MemoryManager extends PersistableObject {
if ((memoryResult = cacheCore.selectCache(path)) != null) {
return memoryResult;
}
memoryResult = graphCore.selectMemory(path);
memoryResult = memoryCore.selectMemory(path);
//尝试更新缓存
cacheCore.updateCache(topicPath, memoryResult);
} catch (Exception e) {
log.error("[MemoryManager] selectMemory error: ", e);
log.error("[MemoryManager] 路径: {}", topicPathStr);
log.error("[MemoryManager] 主题树: {}", getTopicTree());
log.error("[CognationManager] selectMemory error: ", e);
log.error("[CognationManager] 路径: {}", topicPathStr);
log.error("[CognationManager] 主题树: {}", getTopicTree());
memoryResult = new MemoryResult();
memoryResult.setRelatedMemorySliceResult(new ArrayList<>());
memoryResult.setMemorySliceResult(new CopyOnWriteArrayList<>());
@@ -116,8 +121,9 @@ public class MemoryManager extends PersistableObject {
return cacheFilter(memoryResult);
}
@Override
public MemoryResult selectMemory(LocalDate date) throws IOException, ClassNotFoundException {
return cacheFilter(graphCore.selectMemory(date));
return cacheFilter(memoryCore.selectMemory(date));
}
private MemoryResult cacheFilter(MemoryResult memoryResult) {
@@ -131,55 +137,42 @@ public class MemoryManager extends PersistableObject {
return memoryResult;
}
@Override
public void cleanSelectedSliceFilter() {
graphCore.getSelectedSlices().clear();
memoryCore.getSelectedSlices().clear();
}
public String getUserId(String userInfo, String nickName) {
String userId = null;
for (User user : perceiveCore.getUsers()) {
if (user.getInfo().contains(userInfo)) {
userId = user.getUuid();
}
}
if (userId == null) {
User newUser = setNewUser(userInfo, nickName);
perceiveCore.getUsers().add(newUser);
userId = newUser.getUuid();
}
return userId;
@Override
public User getUser(String userInfo, String client) {
return perceiveCore.selectUser(userInfo, client);
}
@Override
public List<Message> getChatMessages() {
return memoryCore.getChatMessages();
return cognationCore.getChatMessages();
}
@Override
public void setChatMessages(List<Message> chatMessages) {
memoryCore.setChatMessages(chatMessages);
}
private static User setNewUser(String userInfo, String nickName) {
User newUser = new User();
newUser.setUuid(UUID.randomUUID().toString());
List<String> infoList = new ArrayList<>();
infoList.add(userInfo);
newUser.setInfo(infoList);
newUser.setNickName(nickName);
return newUser;
cognationCore.setChatMessages(chatMessages);
}
@Override
public String getTopicTree() {
return graphCore.getTopicTree();
return memoryCore.getTopicTree();
}
@Override
public HashMap<LocalDateTime, String> getDialogMap() {
return cacheCore.getDialogMap();
}
@Override
public ConcurrentHashMap<LocalDateTime, String> getUserDialogMap(String userId) {
return cacheCore.getUserDialogMap().get(userId);
}
@Override
public void insertSlice(MemorySlice memorySlice, String topicPath) {
sliceInsertLock.lock();
List<String> topicPathList = Arrays.stream(topicPath.split("->")).toList();
@@ -189,57 +182,55 @@ public class MemoryManager extends PersistableObject {
cacheCore.checkCacheDate();
//如果topicPath在memorySliceCache中存在对应缓存由于进行的插入操作则需要移除该缓存但不清除相关计数
cacheCore.clearCacheByTopicPath(topicPathList);
graphCore.insertMemory(topicPathList, memorySlice);
memoryCore.insertMemory(topicPathList, memorySlice);
if (!memorySlice.isPrivate()) {
cacheCore.updateUserDialogMap(memorySlice);
}
} catch (Exception e) {
log.error("[MemoryManager] 插入记忆时出错: ", e);
log.error("[CognationManager] 插入记忆时出错: ", e);
GlobalExceptionHandler.writeExceptionState(new GlobalException("插入记忆时出错: " + e.getLocalizedMessage()));
}
log.debug("[MemoryManager] 插入切片: {}, 路径: {}", memorySlice, topicPath);
log.debug("[CognationManager] 插入切片: {}, 路径: {}", memorySlice, topicPath);
sliceInsertLock.unlock();
}
@Override
public void cleanMessage(List<Message> messages) {
messageLock.lock();
memoryCore.getChatMessages().removeAll(messages);
cognationCore.getChatMessages().removeAll(messages);
messageLock.unlock();
}
@Override
public void updateDialogMap(LocalDateTime dateTime, String newDialogCache) {
cacheCore.updateDialogMap(dateTime, newDialogCache);
}
private void save() throws IOException {
memoryCore.serialize();
cognationCore.serialize();
}
@Override
public void updateActivatedSlices(String userId, List<EvaluatedSlice> memorySlices) {
memoryManager.getActivatedSlices().put(userId, memorySlices);
log.debug("[MemoryManager] 已更新激活切片, userId: {}", userId);
activeData.updateActivatedSlices(userId, memorySlices);
log.debug("[CognationManager] 已更新激活切片, userId: {}", userId);
}
@Override
public User getUser(String id) {
for (User user : perceiveCore.getUsers()) {
if (user.getUuid().equals(id)) {
User user = perceiveCore.selectUser(id);
if (user == null) {
throw new UserNotExistsException("[CognationManager] 用户不存在: " + id);
}
return user;
}
}
return null;
}
@Override
public String getActivatedSlicesStr(String userId) {
if (memoryManager.getActivatedSlices().containsKey(userId)) {
StringBuilder str = new StringBuilder();
memoryManager.getActivatedSlices().get(userId).forEach(slice -> str.append("\n\n").append("[").append(slice.getDate()).append("]\n")
.append(slice.getSummary()));
return str.toString();
} else {
return null;
}
return activeData.getActivatedSlicesStr(userId);
}
@Override
public String getDialogMapStr() {
StringBuilder str = new StringBuilder();
cacheCore.getDialogMap().forEach((dateTime, dialog) -> str.append("\n\n").append("[").append(dateTime).append("]\n")
@@ -247,6 +238,7 @@ public class MemoryManager extends PersistableObject {
return str.toString();
}
@Override
public String getUserDialogMapStr(String userId) {
if (cacheCore.getUserDialogMap().containsKey(userId)) {
StringBuilder str = new StringBuilder();
@@ -268,13 +260,14 @@ public class MemoryManager extends PersistableObject {
return cacheCore.getUserDialogMap().size() <= 1;
}
@Override
public boolean isSingleUser() {
return isCacheSingleUser() && isChatMessagesSingleUser();
}
private boolean isChatMessagesSingleUser() {
Set<String> userIdSet = new HashSet<>();
memoryManager.getChatMessages().forEach(m -> {
cognationManager.getChatMessages().forEach(m -> {
if (m.getRole().equals(ChatConstant.Character.ASSISTANT)) {
return;
}
@@ -286,4 +279,34 @@ public class MemoryManager extends PersistableObject {
});
return userIdSet.size() <= 1;
}
@Override
public User addUser(String userInfo, String platform, String userNickName) {
return perceiveCore.addUser(userInfo, platform, userNickName);
}
@Override
public HashMap<String, List<EvaluatedSlice>> getActivatedSlices() {
return activeData.getActivatedSlices();
}
@Override
public void clearActivatedSlices(String userId) {
activeData.clearActivatedSlices(userId);
}
@Override
public boolean hasActivatedSlices(String userId) {
return activeData.hasActivatedSlices(userId);
}
@Override
public int getActivatedSlicesSize(String userId) {
return activeData.getActivatedSlices().get(userId).size();
}
@Override
public List<EvaluatedSlice> getActivatedSlices(String userId) {
return activeData.getActivatedSlices().get(userId);
}
}

View File

@@ -1,4 +1,4 @@
package work.slhaf.agent.core.memory.exception;
package work.slhaf.agent.core.cognation.common.exception;
public class NullSliceListException extends RuntimeException {
public NullSliceListException(String message) {

View File

@@ -1,4 +1,4 @@
package work.slhaf.agent.core.memory.exception;
package work.slhaf.agent.core.cognation.common.exception;
public class UnExistedDateIndexException extends RuntimeException {
public UnExistedDateIndexException(String message) {

View File

@@ -1,4 +1,4 @@
package work.slhaf.agent.core.memory.exception;
package work.slhaf.agent.core.cognation.common.exception;
public class UnExistedTopicException extends RuntimeException {
public UnExistedTopicException(String message) {

View File

@@ -0,0 +1,7 @@
package work.slhaf.agent.core.cognation.common.exception;
public class UserNotExistsException extends RuntimeException {
public UserNotExistsException(String message) {
super(message);
}
}

View File

@@ -0,0 +1,38 @@
package work.slhaf.agent.core.cognation.common.pojo;
import lombok.Data;
import work.slhaf.agent.shared.memory.EvaluatedSlice;
import java.util.HashMap;
import java.util.List;
@Data
public class ActiveData {
private HashMap<String, List<EvaluatedSlice>> activatedSlices;
public void updateActivatedSlices(String userId, List<EvaluatedSlice> memorySlices) {
activatedSlices.put(userId, memorySlices);
}
public String getActivatedSlicesStr(String userId) {
if (activatedSlices.containsKey(userId)) {
StringBuilder str = new StringBuilder();
activatedSlices.get(userId).forEach(slice -> str.append("\n\n").append("[").append(slice.getDate()).append("]\n")
.append(slice.getSummary()));
return str.toString();
} else {
return null;
}
}
public void clearActivatedSlices(String userId) {
activatedSlices.remove(userId);
}
public boolean hasActivatedSlices(String userId) {
if (!activatedSlices.containsKey(userId)){
return false;
}
return !activatedSlices.get(userId).isEmpty();
}
}

View File

@@ -1,9 +1,9 @@
package work.slhaf.agent.core.memory.pojo;
package work.slhaf.agent.core.cognation.common.pojo;
import lombok.Data;
import lombok.EqualsAndHashCode;
import work.slhaf.agent.common.serialize.PersistableObject;
import work.slhaf.agent.core.memory.submodule.graph.pojo.MemorySlice;
import work.slhaf.agent.core.cognation.submodule.memory.pojo.MemorySlice;
import java.io.Serial;
import java.util.List;

View File

@@ -1,10 +1,10 @@
package work.slhaf.agent.core.memory.pojo;
package work.slhaf.agent.core.cognation.common.pojo;
import com.alibaba.fastjson2.annotation.JSONField;
import lombok.Data;
import lombok.EqualsAndHashCode;
import work.slhaf.agent.common.serialize.PersistableObject;
import work.slhaf.agent.core.memory.submodule.graph.pojo.MemorySlice;
import work.slhaf.agent.core.cognation.submodule.memory.pojo.MemorySlice;
import java.io.Serial;

View File

@@ -0,0 +1,13 @@
package work.slhaf.agent.core.cognation.submodule.cache;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;
public interface CacheCapability {
HashMap<LocalDateTime, String> getDialogMap();
ConcurrentHashMap<LocalDateTime, String> getUserDialogMap(String userId);
void updateDialogMap(LocalDateTime dateTime, String newDialogCache);
String getDialogMapStr();
String getUserDialogMapStr(String userId);
}

View File

@@ -1,11 +1,11 @@
package work.slhaf.agent.core.memory.submodule.cache;
package work.slhaf.agent.core.cognation.submodule.cache;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j;
import work.slhaf.agent.common.serialize.PersistableObject;
import work.slhaf.agent.core.memory.pojo.MemoryResult;
import work.slhaf.agent.core.memory.submodule.graph.pojo.MemorySlice;
import work.slhaf.agent.core.cognation.common.pojo.MemoryResult;
import work.slhaf.agent.core.cognation.submodule.memory.pojo.MemorySlice;
import java.io.Serial;
import java.time.LocalDate;

View File

@@ -0,0 +1,15 @@
package work.slhaf.agent.core.cognation.submodule.memory;
import work.slhaf.agent.core.cognation.common.pojo.MemoryResult;
import work.slhaf.agent.core.cognation.submodule.memory.pojo.MemorySlice;
import java.io.IOException;
import java.time.LocalDate;
public interface MemoryCapability {
MemoryResult selectMemory(String topicPathStr);
MemoryResult selectMemory(LocalDate date) throws IOException, ClassNotFoundException;
void insertSlice(MemorySlice memorySlice, String topicPath);
void cleanSelectedSliceFilter();
String getTopicTree();
}

View File

@@ -1,15 +1,15 @@
package work.slhaf.agent.core.memory.submodule.graph;
package work.slhaf.agent.core.cognation.submodule.memory;
import lombok.Data;
import lombok.EqualsAndHashCode;
import work.slhaf.agent.common.serialize.PersistableObject;
import work.slhaf.agent.core.memory.exception.UnExistedDateIndexException;
import work.slhaf.agent.core.memory.exception.UnExistedTopicException;
import work.slhaf.agent.core.memory.pojo.MemoryResult;
import work.slhaf.agent.core.memory.pojo.MemorySliceResult;
import work.slhaf.agent.core.memory.submodule.graph.pojo.MemorySlice;
import work.slhaf.agent.core.memory.submodule.graph.pojo.node.MemoryNode;
import work.slhaf.agent.core.memory.submodule.graph.pojo.node.TopicNode;
import work.slhaf.agent.core.cognation.common.exception.UnExistedDateIndexException;
import work.slhaf.agent.core.cognation.common.exception.UnExistedTopicException;
import work.slhaf.agent.core.cognation.common.pojo.MemoryResult;
import work.slhaf.agent.core.cognation.common.pojo.MemorySliceResult;
import work.slhaf.agent.core.cognation.submodule.memory.pojo.MemorySlice;
import work.slhaf.agent.core.cognation.submodule.memory.pojo.node.MemoryNode;
import work.slhaf.agent.core.cognation.submodule.memory.pojo.node.TopicNode;
import java.io.IOException;
import java.io.Serial;
@@ -20,7 +20,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
@EqualsAndHashCode(callSuper = true)
@Data
public class GraphCore extends PersistableObject {
public class MemoryCore extends PersistableObject {
@Serial
private static final long serialVersionUID = 1L;
@@ -77,9 +77,9 @@ public class GraphCore extends PersistableObject {
throw new UnExistedDateIndexException("不存在的日期索引: " + date);
}
List<List<MemorySlice>> list = new ArrayList<>();
for (String memoryId : dateIndex.get(date)) {
for (String memoryNodeId : dateIndex.get(date)) {
MemoryNode memoryNode = new MemoryNode();
memoryNode.setMemoryNodeId(memoryId);
memoryNode.setMemoryNodeId(memoryNodeId);
list.add(memoryNode.loadMemorySliceList());
}
return list;
@@ -202,7 +202,6 @@ public class GraphCore extends PersistableObject {
}
private void updateDateIndex(MemorySlice slice) {
String memoryId = slice.getMemoryId();
LocalDate date = LocalDate.now();

View File

@@ -1,4 +1,4 @@
package work.slhaf.agent.core.memory.submodule.graph.pojo;
package work.slhaf.agent.core.cognation.submodule.memory.pojo;
import lombok.Data;
import lombok.EqualsAndHashCode;

View File

@@ -1,11 +1,11 @@
package work.slhaf.agent.core.memory.submodule.graph.pojo.node;
package work.slhaf.agent.core.cognation.submodule.memory.pojo.node;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j;
import work.slhaf.agent.common.serialize.PersistableObject;
import work.slhaf.agent.core.memory.exception.NullSliceListException;
import work.slhaf.agent.core.memory.submodule.graph.pojo.MemorySlice;
import work.slhaf.agent.core.cognation.common.exception.NullSliceListException;
import work.slhaf.agent.core.cognation.submodule.memory.pojo.MemorySlice;
import java.io.*;
import java.nio.file.Files;

View File

@@ -1,4 +1,4 @@
package work.slhaf.agent.core.memory.submodule.graph.pojo.node;
package work.slhaf.agent.core.cognation.submodule.memory.pojo.node;
import lombok.Data;
import lombok.EqualsAndHashCode;

View File

@@ -0,0 +1,9 @@
package work.slhaf.agent.core.cognation.submodule.perceive;
import work.slhaf.agent.core.cognation.submodule.perceive.pojo.User;
public interface PerceiveCapability {
User getUser(String userInfo, String client);
User getUser(String id);
User addUser(String userInfo, String platform, String userNickName);
}

View File

@@ -0,0 +1,77 @@
package work.slhaf.agent.core.cognation.submodule.perceive;
import lombok.Data;
import lombok.EqualsAndHashCode;
import work.slhaf.agent.common.serialize.PersistableObject;
import work.slhaf.agent.core.cognation.submodule.perceive.pojo.User;
import java.io.Serial;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.locks.ReentrantLock;
@EqualsAndHashCode(callSuper = true)
@Data
public class PerceiveCore extends PersistableObject {
@Serial
private static final long serialVersionUID = 1L;
private static volatile PerceiveCore perceiveCore = new PerceiveCore();
private static final ReentrantLock usersLock = new ReentrantLock();
/**
* 用户列表
*/
private List<User> users = new ArrayList<>();
public static PerceiveCore getInstance() {
if (perceiveCore == null) {
synchronized (PerceiveCore.class) {
if (perceiveCore == null) {
perceiveCore = new PerceiveCore();
}
}
}
return perceiveCore;
}
public User selectUser(String userInfo, String platform) {
User resultUser = null;
usersLock.lock();
for (User user : users) {
HashMap<String, String> info = user.getInfo();
if (info.containsKey(platform)) {
if (info.get(platform).equals(userInfo)) {
resultUser = user;
}
}
}
usersLock.unlock();
return resultUser;
}
public User addUser(String userInfo, String platform, String userNickName) {
User user = new User();
user.addInfo(platform, userInfo);
user.setNickName(userNickName);
user.setUuid(UUID.randomUUID().toString());
usersLock.lock();
users.add(user);
usersLock.unlock();
return user;
}
public User selectUser(String id) {
usersLock.lock();
for (User user : users) {
if (user.getUuid().equals(id)) {
return user;
}
}
usersLock.unlock();
return null;
}
}

View File

@@ -0,0 +1,39 @@
package work.slhaf.agent.core.cognation.submodule.perceive.pojo;
import lombok.Data;
import lombok.EqualsAndHashCode;
import work.slhaf.agent.common.serialize.PersistableObject;
import java.io.Serial;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@EqualsAndHashCode(callSuper = true)
@Data
public class User extends PersistableObject {
@Serial
private static final long serialVersionUID = 1L;
private String uuid;
private String nickName;
private HashMap<String/*platform*/,String> info = new HashMap<>();
private String relation;
private HashMap<LocalDate, String> events = new HashMap<>();
private List<String> impressions = new ArrayList<>();
private List<String> attitude = new ArrayList<>();
private List<String> staticMemory = new ArrayList<>();
public void addInfo(String platform,String userInfo) {
this.info.put(platform, userInfo);
}
public static class Constant {
public static class Relation {
public static final String STRANGER = "stranger";
}
}
}

View File

@@ -1,24 +0,0 @@
package work.slhaf.agent.core.memory.submodule.perceive;
import lombok.Data;
import lombok.EqualsAndHashCode;
import work.slhaf.agent.common.serialize.PersistableObject;
import work.slhaf.agent.core.memory.submodule.perceive.pojo.User;
import java.io.Serial;
import java.util.ArrayList;
import java.util.List;
@EqualsAndHashCode(callSuper = true)
@Data
public class PerceiveCore extends PersistableObject {
@Serial
private static final long serialVersionUID = 1L;
/**
* 用户列表
*/
private List<User> users = new ArrayList<>();
}

View File

@@ -1,20 +0,0 @@
package work.slhaf.agent.core.memory.submodule.perceive.pojo;
import lombok.Data;
import lombok.EqualsAndHashCode;
import work.slhaf.agent.common.serialize.PersistableObject;
import java.io.Serial;
import java.util.List;
@EqualsAndHashCode(callSuper = true)
@Data
public class User extends PersistableObject {
@Serial
private static final long serialVersionUID = 1L;
private String uuid;
private List<String> info;
private String nickName;
}

View File

@@ -8,4 +8,5 @@ import work.slhaf.agent.core.interaction.data.context.InteractionContext;
public interface PreModuleActions {
void setAppendedPrompt(InteractionContext context);
void setActiveModule(InteractionContext context);
String getModuleName();
}

View File

@@ -8,9 +8,10 @@ import work.slhaf.agent.common.chat.constant.ChatConstant;
import work.slhaf.agent.common.chat.pojo.ChatResponse;
import work.slhaf.agent.common.chat.pojo.Message;
import work.slhaf.agent.common.chat.pojo.MetaMessage;
import work.slhaf.agent.core.cognation.CognationCapability;
import work.slhaf.agent.core.cognation.CognationManager;
import work.slhaf.agent.core.interaction.data.context.InteractionContext;
import work.slhaf.agent.core.interaction.module.InteractionModule;
import work.slhaf.agent.core.memory.MemoryManager;
import work.slhaf.agent.core.session.SessionManager;
import work.slhaf.agent.module.common.AppendPromptData;
import work.slhaf.agent.module.common.Model;
@@ -20,7 +21,6 @@ import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import static work.slhaf.agent.common.util.ExtractUtil.extractJson;
@@ -33,7 +33,7 @@ public class CoreModel extends Model implements InteractionModule {
public static final String MODEL_KEY = "core_model";
private static volatile CoreModel coreModel;
private MemoryManager memoryManager;
private CognationCapability cognationCapability;
private SessionManager sessionManager;
private List<Message> appendedMessages;
@@ -45,8 +45,8 @@ public class CoreModel extends Model implements InteractionModule {
synchronized (CoreModel.class) {
if (coreModel == null) {
coreModel = new CoreModel();
coreModel.memoryManager = MemoryManager.getInstance();
coreModel.chatMessages = coreModel.memoryManager.getChatMessages();
coreModel.cognationCapability = CognationManager.getInstance();
coreModel.chatMessages = coreModel.cognationCapability.getChatMessages();
coreModel.appendedMessages = new ArrayList<>();
coreModel.sessionManager = SessionManager.getInstance();
setModel(coreModel, MODEL_KEY, ModelConstant.Prompt.CORE, true);
@@ -145,7 +145,7 @@ public class CoreModel extends Model implements InteractionModule {
}
private void updateModuleContextAndChatMessages(InteractionContext interactionContext, String response, ChatResponse chatResponse) {
memoryManager.getMessageLock().lock();
cognationCapability.getMessageLock().lock();
this.chatMessages.removeIf(m -> {
if (m.getRole().equals(ChatConstant.Character.ASSISTANT)) {
return false;
@@ -163,7 +163,7 @@ public class CoreModel extends Model implements InteractionModule {
this.chatMessages.add(primaryUserMessage);
Message assistantMessage = new Message(ChatConstant.Character.ASSISTANT, response);
this.chatMessages.add(assistantMessage);
memoryManager.getMessageLock().unlock();
cognationCapability.getMessageLock().unlock();
//设置上下文
interactionContext.getModuleContext().getExtraContext().put("total_token", chatResponse.getUsageBean().getTotal_tokens());
//区分单人聊天场景

View File

@@ -3,13 +3,16 @@ package work.slhaf.agent.module.modules.memory.selector;
import com.alibaba.fastjson2.JSONObject;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import work.slhaf.agent.core.cognation.CognationCapability;
import work.slhaf.agent.core.cognation.CognationManager;
import work.slhaf.agent.core.cognation.common.exception.UnExistedDateIndexException;
import work.slhaf.agent.core.cognation.common.exception.UnExistedTopicException;
import work.slhaf.agent.core.cognation.common.pojo.MemoryResult;
import work.slhaf.agent.core.cognation.submodule.cache.CacheCapability;
import work.slhaf.agent.core.cognation.submodule.memory.MemoryCapability;
import work.slhaf.agent.core.cognation.submodule.memory.pojo.MemorySlice;
import work.slhaf.agent.core.interaction.data.context.InteractionContext;
import work.slhaf.agent.core.interaction.module.InteractionModule;
import work.slhaf.agent.core.memory.MemoryManager;
import work.slhaf.agent.core.memory.exception.UnExistedDateIndexException;
import work.slhaf.agent.core.memory.exception.UnExistedTopicException;
import work.slhaf.agent.core.memory.pojo.MemoryResult;
import work.slhaf.agent.core.memory.submodule.graph.pojo.MemorySlice;
import work.slhaf.agent.core.session.SessionManager;
import work.slhaf.agent.module.common.AppendPromptData;
import work.slhaf.agent.module.common.PreModuleActions;
@@ -32,9 +35,10 @@ import java.util.List;
public class MemorySelector implements InteractionModule, PreModuleActions {
private static volatile MemorySelector memorySelector;
private static final String MODULE_NAME = "[记忆模块]";
private MemoryManager memoryManager;
private CacheCapability cacheCapability;
private MemoryCapability memoryCapability;
private CognationCapability cognationCapability;
private SliceSelectEvaluator sliceSelectEvaluator;
private MemorySelectExtractor memorySelectExtractor;
private SessionManager sessionManager;
@@ -47,7 +51,9 @@ public class MemorySelector implements InteractionModule, PreModuleActions {
synchronized (MemorySelector.class) {
if (memorySelector == null) {
memorySelector = new MemorySelector();
memorySelector.setMemoryManager(MemoryManager.getInstance());
memorySelector.setCacheCapability(CognationManager.getInstance());
memorySelector.setMemoryCapability(CognationManager.getInstance());
memorySelector.setCognationCapability(CognationManager.getInstance());
memorySelector.setSliceSelectEvaluator(SliceSelectEvaluator.getInstance());
memorySelector.setMemorySelectExtractor(MemorySelectExtractor.getInstance());
memorySelector.setSessionManager(SessionManager.getInstance());
@@ -64,11 +70,9 @@ public class MemorySelector implements InteractionModule, PreModuleActions {
//获取主题路径
ExtractorResult extractorResult = memorySelectExtractor.execute(interactionContext);
if (extractorResult.isRecall() || !extractorResult.getMatches().isEmpty()) {
if (memoryManager.getActivatedSlices().get(userId) != null) {
memoryManager.getActivatedSlices().get(userId).clear();
}
cognationCapability.clearActivatedSlices(userId);
List<EvaluatedSlice> evaluatedSlices = selectAndEvaluateMemory(interactionContext, extractorResult);
memoryManager.updateActivatedSlices(userId, evaluatedSlices);
cognationCapability.updateActivatedSlices(userId, evaluatedSlices);
}
//设置追加提示词
setAppendedPrompt(interactionContext);
@@ -87,7 +91,7 @@ public class MemorySelector implements InteractionModule, PreModuleActions {
EvaluatorInput evaluatorInput = EvaluatorInput.builder()
.input(interactionContext.getInput())
.memoryResults(memoryResultList)
.messages(memoryManager.getChatMessages())
.messages(cognationCapability.getChatMessages())
.build();
log.debug("[MemorySelector] 切片评估输入: {}", JSONObject.toJSONString(evaluatorInput));
List<EvaluatedSlice> memorySlices = sliceSelectEvaluator.execute(evaluatorInput);
@@ -97,15 +101,10 @@ public class MemorySelector implements InteractionModule, PreModuleActions {
private void setModuleContextRecall(InteractionContext interactionContext) {
String userId = interactionContext.getUserId();
boolean recall;
if (memoryManager.getActivatedSlices().get(userId) == null) {
recall = false;
} else {
recall = !memoryManager.getActivatedSlices().get(userId).isEmpty();
}
boolean recall = cognationCapability.hasActivatedSlices(userId);
interactionContext.getModuleContext().getExtraContext().put("recall", recall);
if (recall) {
interactionContext.getModuleContext().getExtraContext().put("recall_count", memoryManager.getActivatedSlices().get(userId).size());
interactionContext.getModuleContext().getExtraContext().put("recall_count", cognationCapability.getActivatedSlicesSize(userId));
}
}
@@ -114,9 +113,9 @@ public class MemorySelector implements InteractionModule, PreModuleActions {
for (ExtractorMatchData match : matches) {
try {
MemoryResult memoryResult = switch (match.getType()) {
case ExtractorMatchData.Constant.TOPIC -> memoryManager.selectMemory(match.getText());
case ExtractorMatchData.Constant.TOPIC -> memoryCapability.selectMemory(match.getText());
case ExtractorMatchData.Constant.DATE ->
memoryManager.selectMemory(LocalDate.parse(match.getText()));
memoryCapability.selectMemory(LocalDate.parse(match.getText()));
default -> null;
};
if (memoryResult == null || memoryResult.isEmpty()) continue;
@@ -128,7 +127,7 @@ public class MemorySelector implements InteractionModule, PreModuleActions {
}
}
//清理切片记录
memoryManager.cleanSelectedSliceFilter();
memoryCapability.cleanSelectedSliceFilter();
//根据userInfo过滤是否为私人记忆
for (MemoryResult memoryResult : memoryResultList) {
@@ -140,7 +139,7 @@ public class MemorySelector implements InteractionModule, PreModuleActions {
}
private void removeDuplicateSlice(MemoryResult memoryResult) {
Collection<String> values = memoryManager.getDialogMap().values();
Collection<String> values = cacheCapability.getDialogMap().values();
memoryResult.getRelatedMemorySliceResult().removeIf(m -> values.contains(m.getSummary()));
memoryResult.getMemorySliceResult().removeIf(m -> values.contains(m.getMemorySlice().getSummary()));
}
@@ -157,29 +156,34 @@ public class MemorySelector implements InteractionModule, PreModuleActions {
String userId = context.getUserId();
HashMap<String, String> map = getPromptDataMap(userId);
AppendPromptData data = new AppendPromptData();
data.setModuleName(MODULE_NAME);
data.setModuleName(getModuleName());
data.setAppendedPrompt(map);
context.setAppendedPrompt(data);
}
@Override
public void setActiveModule(InteractionContext context) {
context.getCoreContext().addActiveModule(MODULE_NAME);
context.getCoreContext().addActiveModule(getModuleName());
}
@Override
public String getModuleName() {
return "[记忆模块]";
}
private HashMap<String, String> getPromptDataMap(String userId) {
HashMap<String, String> map = new HashMap<>();
String dialogMapStr = memoryManager.getDialogMapStr();
String dialogMapStr = cacheCapability.getDialogMapStr();
if (!dialogMapStr.isEmpty()) {
map.put("[记忆缓存] <你最近两日和所有聊天者的对话记忆印象>", dialogMapStr);
}
String userDialogMapStr = memoryManager.getUserDialogMapStr(userId);
if (userDialogMapStr != null && !userDialogMapStr.isEmpty() && !memoryManager.isSingleUser()) {
String userDialogMapStr = cacheCapability.getUserDialogMapStr(userId);
if (userDialogMapStr != null && !userDialogMapStr.isEmpty() && !cognationCapability.isSingleUser()) {
map.put("[用户记忆缓存] <与最新一条消息的发送者的近两天对话记忆印象, 可能与[记忆缓存]稍有重复>", userDialogMapStr);
}
String sliceStr = memoryManager.getActivatedSlicesStr(userId);
String sliceStr = cognationCapability.getActivatedSlicesStr(userId);
if (sliceStr != null && !sliceStr.isEmpty()) {
map.put("[记忆切片] <你与最新一条消息的发送者的相关回忆, 不会与[记忆缓存]重复, 如果有重复你也可以指出来()>", sliceStr);
}

View File

@@ -7,10 +7,9 @@ import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j;
import work.slhaf.agent.common.thread.InteractionThreadPoolExecutor;
import work.slhaf.agent.core.memory.MemoryManager;
import work.slhaf.agent.core.memory.pojo.MemoryResult;
import work.slhaf.agent.core.memory.pojo.MemorySliceResult;
import work.slhaf.agent.core.memory.submodule.graph.pojo.MemorySlice;
import work.slhaf.agent.core.cognation.common.pojo.MemoryResult;
import work.slhaf.agent.core.cognation.common.pojo.MemorySliceResult;
import work.slhaf.agent.core.cognation.submodule.memory.pojo.MemorySlice;
import work.slhaf.agent.module.common.Model;
import work.slhaf.agent.module.common.ModelConstant;
import work.slhaf.agent.module.modules.memory.selector.evaluator.data.EvaluatorBatchInput;
@@ -34,7 +33,6 @@ import static work.slhaf.agent.common.util.ExtractUtil.extractJson;
public class SliceSelectEvaluator extends Model {
public static final String MODEL_KEY = "slice_evaluator";
private static volatile SliceSelectEvaluator sliceSelectEvaluator;
private MemoryManager memoryManager;
private InteractionThreadPoolExecutor executor;
private SliceSelectEvaluator() {
@@ -45,7 +43,6 @@ public class SliceSelectEvaluator extends Model {
synchronized (SliceSelectEvaluator.class) {
if (sliceSelectEvaluator == null) {
sliceSelectEvaluator = new SliceSelectEvaluator();
sliceSelectEvaluator.setMemoryManager(MemoryManager.getInstance());
sliceSelectEvaluator.setExecutor(InteractionThreadPoolExecutor.getInstance());
setModel(sliceSelectEvaluator, MODEL_KEY, ModelConstant.Prompt.MEMORY, false);
log.info("SliceEvaluator注册完毕...");

View File

@@ -3,7 +3,7 @@ package work.slhaf.agent.module.modules.memory.selector.evaluator.data;
import lombok.Builder;
import lombok.Data;
import work.slhaf.agent.common.chat.pojo.Message;
import work.slhaf.agent.core.memory.pojo.MemoryResult;
import work.slhaf.agent.core.cognation.common.pojo.MemoryResult;
import java.util.List;

View File

@@ -9,8 +9,10 @@ import work.slhaf.agent.common.chat.pojo.Message;
import work.slhaf.agent.common.chat.pojo.MetaMessage;
import work.slhaf.agent.common.exception_handler.GlobalExceptionHandler;
import work.slhaf.agent.common.exception_handler.pojo.GlobalException;
import work.slhaf.agent.core.cognation.CognationCapability;
import work.slhaf.agent.core.cognation.CognationManager;
import work.slhaf.agent.core.cognation.submodule.memory.MemoryCapability;
import work.slhaf.agent.core.interaction.data.context.InteractionContext;
import work.slhaf.agent.core.memory.MemoryManager;
import work.slhaf.agent.core.session.SessionManager;
import work.slhaf.agent.module.common.Model;
import work.slhaf.agent.module.common.ModelConstant;
@@ -33,7 +35,8 @@ public class MemorySelectExtractor extends Model {
public static final String MODEL_KEY = "topic_extractor";
private static volatile MemorySelectExtractor memorySelectExtractor;
private MemoryManager memoryManager;
private MemoryCapability memoryCapability;
private CognationCapability cognationCapability;
private SessionManager sessionManager;
private MemorySelectExtractor() {
@@ -44,7 +47,8 @@ public class MemorySelectExtractor extends Model {
synchronized (MemorySelectExtractor.class) {
if (memorySelectExtractor == null) {
memorySelectExtractor = new MemorySelectExtractor();
memorySelectExtractor.setMemoryManager(MemoryManager.getInstance());
memorySelectExtractor.setMemoryCapability(CognationManager.getInstance());
memorySelectExtractor.setCognationCapability(CognationManager.getInstance());
memorySelectExtractor.setSessionManager(SessionManager.getInstance());
setModel(memorySelectExtractor, MODEL_KEY, ModelConstant.Prompt.MEMORY, false);
}
@@ -69,12 +73,12 @@ public class MemorySelectExtractor extends Model {
ExtractorResult extractorResult;
try {
List<EvaluatedSlice> activatedMemorySlices = memoryManager.getActivatedSlices().get(context.getUserId());
List<EvaluatedSlice> activatedMemorySlices = cognationCapability.getActivatedSlices(context.getUserId());
ExtractorInput extractorInput = ExtractorInput.builder()
.text(context.getInput())
.date(context.getDateTime().toLocalDate())
.history(chatMessages)
.topic_tree(memoryManager.getTopicTree())
.topic_tree(memoryCapability.getTopicTree())
.activatedMemorySlices(activatedMemorySlices)
.build();
log.debug("[MemorySelectExtractor] 主题提取输入: {}", JSONObject.toJSONString(extractorInput));

View File

@@ -6,10 +6,14 @@ import lombok.extern.slf4j.Slf4j;
import work.slhaf.agent.common.chat.constant.ChatConstant;
import work.slhaf.agent.common.chat.pojo.Message;
import work.slhaf.agent.common.thread.InteractionThreadPoolExecutor;
import work.slhaf.agent.core.cognation.CognationCapability;
import work.slhaf.agent.core.cognation.CognationManager;
import work.slhaf.agent.core.cognation.submodule.cache.CacheCapability;
import work.slhaf.agent.core.cognation.submodule.memory.MemoryCapability;
import work.slhaf.agent.core.cognation.submodule.memory.pojo.MemorySlice;
import work.slhaf.agent.core.cognation.submodule.perceive.PerceiveCapability;
import work.slhaf.agent.core.interaction.data.context.InteractionContext;
import work.slhaf.agent.core.interaction.module.InteractionModule;
import work.slhaf.agent.core.memory.MemoryManager;
import work.slhaf.agent.core.memory.submodule.graph.pojo.MemorySlice;
import work.slhaf.agent.core.session.SessionManager;
import work.slhaf.agent.module.modules.memory.selector.extractor.MemorySelectExtractor;
import work.slhaf.agent.module.modules.memory.updater.summarizer.MemorySummarizer;
@@ -36,7 +40,10 @@ public class MemoryUpdater implements InteractionModule {
private static final int TOKEN_PER_RECALL = 230;
private static final int TRIGGER_ROLL_LIMIT = 36;
private MemoryManager memoryManager;
private CognationCapability cognationCapability;
private MemoryCapability memoryCapability;
private CacheCapability cacheCapability;
private PerceiveCapability perceiveCapability;
private InteractionThreadPoolExecutor executor;
private MemorySelectExtractor memorySelectExtractor;
private MemorySummarizer memorySummarizer;
@@ -54,7 +61,10 @@ public class MemoryUpdater implements InteractionModule {
synchronized (MemoryUpdater.class) {
if (memoryUpdater == null) {
memoryUpdater = new MemoryUpdater();
memoryUpdater.setMemoryManager(MemoryManager.getInstance());
memoryUpdater.setCognationCapability(CognationManager.getInstance());
memoryUpdater.setMemoryCapability(CognationManager.getInstance());
memoryUpdater.setCacheCapability(CognationManager.getInstance());
memoryUpdater.setPerceiveCapability(CognationManager.getInstance());
memoryUpdater.setMemorySelectExtractor(MemorySelectExtractor.getInstance());
memoryUpdater.setMemorySummarizer(MemorySummarizer.getInstance());
memoryUpdater.setSessionManager(SessionManager.getInstance());
@@ -73,10 +83,10 @@ public class MemoryUpdater implements InteractionModule {
try {
long currentTime = System.currentTimeMillis();
long lastUpdatedTime = sessionManager.getLastUpdatedTime();
int chatCount = memoryManager.getChatMessages().size();
int chatCount = cognationCapability.getChatMessages().size();
if (lastUpdatedTime != 0 && currentTime - lastUpdatedTime > UPDATE_TRIGGER_INTERVAL && chatCount > 1) {
updateMemory();
memoryManager.getChatMessages().clear();
cognationCapability.getChatMessages().clear();
//重置MemoryId
sessionManager.refreshMemoryId();
log.info("[MemoryUpdater] 记忆更新: 自动触发");
@@ -105,7 +115,7 @@ public class MemoryUpdater implements InteractionModule {
int recallCount = moduleContext.getIntValue("recall_count");
log.debug("[MemoryUpdater] 记忆切片数量 [{}]", recallCount);
}
int messageCount = memoryManager.getChatMessages().size();
int messageCount = cognationCapability.getChatMessages().size();
if (messageCount >= TRIGGER_ROLL_LIMIT) {
try {
log.debug("[MemoryUpdater] 记忆更新: 已达{}轮", TRIGGER_ROLL_LIMIT);
@@ -121,7 +131,7 @@ public class MemoryUpdater implements InteractionModule {
private void updateMemory() {
log.debug("[MemoryUpdater] 记忆更新流程开始...");
tempMessage = new ArrayList<>(memoryManager.getChatMessages());
tempMessage = new ArrayList<>(cognationCapability.getChatMessages());
HashMap<String, String> singleMemorySummary = new HashMap<>();
//更新单聊记忆同时从chatMessages中去掉单聊记忆
updateSingleChatSlices(singleMemorySummary);
@@ -137,9 +147,9 @@ public class MemoryUpdater implements InteractionModule {
Callable<Void> task = () -> {
log.debug("[MemoryUpdater] 多人聊天记忆更新流程开始...");
List<Message> chatMessages;
memoryManager.getMessageLock().lock();
chatMessages = new ArrayList<>(memoryManager.getChatMessages());
memoryManager.getMessageLock().unlock();
cognationCapability.getMessageLock().lock();
chatMessages = new ArrayList<>(cognationCapability.getChatMessages());
cognationCapability.getMessageLock().unlock();
cleanMessage(chatMessages);
if (!chatMessages.isEmpty()) {
log.debug("[MemoryUpdater] 存在多人聊天记录, 流程正常进行...");
@@ -148,20 +158,20 @@ public class MemoryUpdater implements InteractionModule {
if (userId == null) {
throw new RuntimeException("未匹配到 userId!");
}
SummarizeInput summarizeInput = new SummarizeInput(chatMessages, memoryManager.getTopicTree());
SummarizeInput summarizeInput = new SummarizeInput(chatMessages, memoryCapability.getTopicTree());
log.debug("[MemoryUpdater] 多人聊天记忆更新-总结流程-输入: {}", summarizeInput);
SummarizeResult summarizeResult = memorySummarizer.execute(summarizeInput);
log.debug("[MemoryUpdater] 多人聊天记忆更新-总结流程-输出: {}", summarizeResult);
MemorySlice memorySlice = getMemorySlice(userId, summarizeResult, chatMessages);
//设置involvedUserId
setInvolvedUserId(userId, memorySlice, chatMessages);
memoryManager.insertSlice(memorySlice, summarizeResult.getTopicPath());
memoryCapability.insertSlice(memorySlice, summarizeResult.getTopicPath());
memoryManager.updateDialogMap(LocalDateTime.now(), summarizeResult.getSummary());
cacheCapability.updateDialogMap(LocalDateTime.now(), summarizeResult.getSummary());
} else {
log.debug("[MemoryUpdater] 不存在多人聊天记录, 将以单聊总结为对话缓存的主要输入: {}", singleMemorySummary);
memoryManager.updateDialogMap(LocalDateTime.now(), memorySummarizer.executeTotalSummary(singleMemorySummary));
cacheCapability.updateDialogMap(LocalDateTime.now(), memorySummarizer.executeTotalSummary(singleMemorySummary));
}
log.debug("[MemoryUpdater] 对话缓存更新完毕");
log.debug("[MemoryUpdater] 多人聊天记忆更新流程结束...");
@@ -184,11 +194,11 @@ public class MemoryUpdater implements InteractionModule {
private void clearChatMessages() {
//不全部清空,保留一部分输入防止上下文割裂
memoryManager.getMessageLock().lock();
cognationCapability.getMessageLock().lock();
List<Message> temp = new ArrayList<>(tempMessage.subList(tempMessage.size() - TRIGGER_ROLL_LIMIT / 6, tempMessage.size()));
memoryManager.getChatMessages().clear();
memoryManager.getChatMessages().addAll(temp);
memoryManager.getMessageLock().unlock();
cognationCapability.getChatMessages().clear();
cognationCapability.getChatMessages().addAll(temp);
cognationCapability.getMessageLock().unlock();
}
private void setInvolvedUserId(String startUserId, MemorySlice memorySlice, List<Message> chatMessages) {
@@ -224,17 +234,17 @@ public class MemoryUpdater implements InteractionModule {
log.debug("[MemoryUpdater] 单聊记忆[{}]更新: {}", thisCount, id);
try {
//单聊记忆更新
SummarizeInput summarizeInput = new SummarizeInput(messages, memoryManager.getTopicTree());
SummarizeInput summarizeInput = new SummarizeInput(messages, memoryCapability.getTopicTree());
log.debug("[MemoryUpdater] 单聊记忆[{}]更新-总结流程-输入: {}", thisCount, JSONObject.toJSONString(summarizeInput));
SummarizeResult summarizeResult = memorySummarizer.execute(summarizeInput);
log.debug("[MemoryUpdater] 单聊记忆[{}]更新-总结流程-输出: {}", thisCount, JSONObject.toJSONString(summarizeResult));
MemorySlice memorySlice = getMemorySlice(id, summarizeResult, messages);
//插入时userDialogMap已经进行更新
memoryManager.insertSlice(memorySlice, summarizeResult.getTopicPath());
memoryCapability.insertSlice(memorySlice, summarizeResult.getTopicPath());
//从chatMessages中移除单聊记录
memoryManager.cleanMessage(messages);
cognationCapability.cleanMessage(messages);
//添加至singleMemorySummary
String key = memoryManager.getUser(id).getNickName() + "[" + id + "]";
String key = perceiveCapability.getUser(id).getNickName() + "[" + id + "]";
singleMemorySummary.put(key, summarizeResult.getSummary());
log.debug("[MemoryUpdater] 单聊记忆[{}]更新成功: ", thisCount);
} catch (Exception e) {

View File

@@ -1,19 +1,28 @@
package work.slhaf.agent.module.modules.perceive.selector;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import work.slhaf.agent.core.interaction.data.context.InteractionContext;
import work.slhaf.agent.core.interaction.module.InteractionModule;
import work.slhaf.agent.module.common.PreModuleActions;
import java.io.IOException;
public class PerceiveSelector implements InteractionModule {
@Slf4j
@Setter
public class PerceiveSelector implements InteractionModule, PreModuleActions {
private static volatile PerceiveSelector perceiveSelector;
private static PerceiveSelector perceiveSelector;
public static PerceiveSelector getInstance() throws IOException, ClassNotFoundException {
if (perceiveSelector == null) {
synchronized (PerceiveSelector.class) {
if (perceiveSelector == null) {
perceiveSelector = new PerceiveSelector();
}
}
}
return perceiveSelector;
}
@@ -21,4 +30,19 @@ public class PerceiveSelector implements InteractionModule {
public void execute(InteractionContext context) throws IOException, ClassNotFoundException {
}
@Override
public void setAppendedPrompt(InteractionContext context) {
}
@Override
public void setActiveModule(InteractionContext context) {
}
@Override
public String getModuleName() {
return "";
}
}

View File

@@ -2,9 +2,12 @@ package work.slhaf.agent.module.modules.preprocess;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import work.slhaf.agent.core.cognation.CognationCapability;
import work.slhaf.agent.core.cognation.CognationManager;
import work.slhaf.agent.core.cognation.submodule.perceive.PerceiveCapability;
import work.slhaf.agent.core.cognation.submodule.perceive.pojo.User;
import work.slhaf.agent.core.interaction.data.InteractionInputData;
import work.slhaf.agent.core.interaction.data.context.InteractionContext;
import work.slhaf.agent.core.memory.MemoryManager;
import work.slhaf.agent.core.session.SessionManager;
import work.slhaf.agent.module.common.AppendPromptData;
@@ -19,7 +22,8 @@ public class PreprocessExecutor {
private static volatile PreprocessExecutor preprocessExecutor;
private MemoryManager memoryManager;
private CognationCapability cognationCapability;
private PerceiveCapability perceiveCapability;
private SessionManager sessionManager;
private PreprocessExecutor() {
@@ -30,7 +34,8 @@ public class PreprocessExecutor {
synchronized (PreprocessExecutor.class) {
if (preprocessExecutor == null) {
preprocessExecutor = new PreprocessExecutor();
preprocessExecutor.setMemoryManager(MemoryManager.getInstance());
preprocessExecutor.setCognationCapability(CognationManager.getInstance());
preprocessExecutor.setPerceiveCapability(CognationManager.getInstance());
preprocessExecutor.setSessionManager(SessionManager.getInstance());
}
}
@@ -45,7 +50,7 @@ public class PreprocessExecutor {
private void checkAndSetMemoryId() {
String currentMemoryId = sessionManager.getCurrentMemoryId();
if (currentMemoryId == null || memoryManager.getChatMessages().isEmpty()) {
if (currentMemoryId == null || cognationCapability.getChatMessages().isEmpty()) {
sessionManager.refreshMemoryId();
}
}
@@ -54,15 +59,19 @@ public class PreprocessExecutor {
log.debug("[PreprocessExecutor] 预处理原始输入: {}", inputData);
InteractionContext context = new InteractionContext();
String userId = memoryManager.getUserId(inputData.getUserInfo(), inputData.getUserNickName());
User user = perceiveCapability.getUser(inputData.getUserInfo(), inputData.getPlatform());
if (user == null) {
user = perceiveCapability.addUser(inputData.getUserInfo(), inputData.getPlatform(), inputData.getUserNickName());
}
String userId = user.getUuid();
context.setUserId(userId);
context.setUserNickname(inputData.getUserNickName());
context.setUserInfo(inputData.getUserInfo());
context.setDateTime(inputData.getLocalDateTime());
context.setSingle(inputData.isSingle());
String user = "[" + inputData.getUserNickName() + "(" + userId + ")]";
String input = user + " " + inputData.getContent();
String userStr = "[" + inputData.getUserNickName() + "(" + userId + ")]";
String input = userStr + " " + inputData.getContent();
context.setInput(input);
setAppendedPrompt(context);