mirror of
https://github.com/slhaf/Partner.git
synced 2026-05-12 08:43:02 +08:00
进行第二阶段调试修复:边聊边修挺有意思的
- 由于更改了上下文认知补充机制,所以将原来的CoreContext、ModuleContext从单一的jsonObject重构为了独立的类 - 移除了CoreModel中的baseMessageCache,当前消息分为三段,baseMessage固定,不再需要缓存 - 在CoreModel中添加了新的认知注入机制,并且模块状态也会显示给Partner(是否活跃) - 在MemoryManager挑取记忆时,将在获取到MemoryResult后与dialogMap对比,去重切片,但还是有较多重复,单用户时应该可以去掉userDialogMap的展示? - 在MemoryManager中添加了几个获取相应字符串的方法,为了适应新的上下文注入机制 - 调整对话列表更新为保留前1/3,确保防止上下文断裂,但应该改为1/4也行 - log.debug输出日志时将先包装为json对象,防止换行导致影响控制台效果 - 调整了MemoryUpdater中清理互动消息列表的逻辑 - PreprocessExecutor适配新的上下文注入机制 - InteractionContext的某些字段应提供默认值而非创建对象后手动赋值,已调整 - 移除了挺多目前用不到的注释,反正还有版本控制
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -48,3 +48,4 @@ build/
|
||||
/src/test/java/memory/result/input4.json
|
||||
/src/test/java/memory/result/primary_input.json
|
||||
/src/main/resources/prompt/module/memory/topic_extractor.json.bak
|
||||
/backup/
|
||||
|
||||
31
qodana.yaml
Normal file
31
qodana.yaml
Normal file
@@ -0,0 +1,31 @@
|
||||
#-------------------------------------------------------------------------------#
|
||||
# Qodana analysis is configured by qodana.yaml file #
|
||||
# https://www.jetbrains.com/help/qodana/qodana-yaml.html #
|
||||
#-------------------------------------------------------------------------------#
|
||||
version: "1.0"
|
||||
|
||||
#Specify inspection profile for code analysis
|
||||
profile:
|
||||
name: qodana.starter
|
||||
|
||||
#Enable inspections
|
||||
#include:
|
||||
# - name: <SomeEnabledInspectionId>
|
||||
|
||||
#Disable inspections
|
||||
#exclude:
|
||||
# - name: <SomeDisabledInspectionId>
|
||||
# paths:
|
||||
# - <path/where/not/run/inspection>
|
||||
|
||||
projectJDK: "21" #(Applied in CI/CD pipeline)
|
||||
|
||||
#Execute shell command before Qodana execution (Applied in CI/CD pipeline)
|
||||
#bootstrap: sh ./prepare-qodana.sh
|
||||
|
||||
#Install IDE plugins before Qodana execution (Applied in CI/CD pipeline)
|
||||
#plugins:
|
||||
# - id: <plugin.id> #(plugin id can be found at https://plugins.jetbrains.com)
|
||||
|
||||
#Specify Qodana linter for analysis (Applied in CI/CD pipeline)
|
||||
linter: jetbrains/qodana-jvm:2025.1
|
||||
@@ -5,8 +5,8 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import work.slhaf.agent.common.config.Config;
|
||||
import work.slhaf.agent.common.monitor.DebugMonitor;
|
||||
import work.slhaf.agent.core.InteractionHub;
|
||||
import work.slhaf.agent.core.interaction.InputReceiver;
|
||||
import work.slhaf.agent.core.interaction.TaskCallback;
|
||||
import work.slhaf.agent.core.interaction.agent_interface.InputReceiver;
|
||||
import work.slhaf.agent.core.interaction.agent_interface.TaskCallback;
|
||||
import work.slhaf.agent.core.interaction.data.InteractionInputData;
|
||||
import work.slhaf.agent.core.interaction.data.InteractionOutputData;
|
||||
import work.slhaf.agent.gateway.AgentWebSocketServer;
|
||||
@@ -36,7 +36,6 @@ public class Agent implements TaskCallback, InputReceiver {
|
||||
server.launch();
|
||||
agent.setMessageSender(server);
|
||||
log.info("Agent 加载完毕..");
|
||||
|
||||
//启动监测线程
|
||||
DebugMonitor.initialize();
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package work.slhaf.agent.common.chat.pojo;
|
||||
|
||||
import lombok.*;
|
||||
import work.slhaf.agent.common.pojo.PersistableObject;
|
||||
import work.slhaf.agent.common.serialize.PersistableObject;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package work.slhaf.agent.common.chat.pojo;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import work.slhaf.agent.common.pojo.PersistableObject;
|
||||
import work.slhaf.agent.common.serialize.PersistableObject;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
|
||||
@@ -48,9 +48,6 @@ public class Config {
|
||||
System.out.print("输入智能体名称: ");
|
||||
config.setAgentId(scanner.nextLine());
|
||||
|
||||
// System.out.print("输入智能体基础角色设定: ");
|
||||
// config.setBasicCharacter(scanner.nextLine());
|
||||
|
||||
System.out.println("(注意! 设定角色之后修改主配置文件将不会影响现有记忆,除非同时更换agentId)");
|
||||
|
||||
System.out.println("\r\n--------模型配置--------\r\n");
|
||||
|
||||
@@ -3,7 +3,7 @@ package work.slhaf.agent.common.exception_handler.pojo;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import work.slhaf.agent.core.interaction.data.InteractionContext;
|
||||
import work.slhaf.agent.core.interaction.data.context.InteractionContext;
|
||||
import work.slhaf.agent.core.memory.MemoryManager;
|
||||
import work.slhaf.agent.core.session.SessionManager;
|
||||
|
||||
|
||||
@@ -2,12 +2,13 @@ package work.slhaf.agent.common.exception_handler.pojo;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import work.slhaf.agent.common.pojo.PersistableObject;
|
||||
import work.slhaf.agent.core.interaction.data.InteractionContext;
|
||||
import work.slhaf.agent.common.serialize.PersistableObject;
|
||||
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;
|
||||
import java.util.HashMap;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
@@ -18,7 +19,7 @@ public class GlobalExceptionData extends PersistableObject {
|
||||
|
||||
private String exceptionMessage;
|
||||
|
||||
protected InteractionContext context;
|
||||
protected HashMap<String, InteractionContext> context;
|
||||
protected SessionManager sessionManager;
|
||||
protected MemoryManager memoryManager;
|
||||
protected Long exceptionTime;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package work.slhaf.agent.common.monitor;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import work.slhaf.agent.core.interaction.InteractionThreadPoolExecutor;
|
||||
import work.slhaf.agent.common.thread.InteractionThreadPoolExecutor;
|
||||
|
||||
@Slf4j
|
||||
public class DebugMonitor {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package work.slhaf.agent.common.pojo;
|
||||
package work.slhaf.agent.common.serialize;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package work.slhaf.agent.core.interaction;
|
||||
package work.slhaf.agent.common.thread;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
@@ -5,11 +5,11 @@ import lombok.ToString;
|
||||
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.InteractionModulesLoader;
|
||||
import work.slhaf.agent.core.interaction.TaskCallback;
|
||||
import work.slhaf.agent.core.interaction.data.InteractionContext;
|
||||
import work.slhaf.agent.core.interaction.agent_interface.TaskCallback;
|
||||
import work.slhaf.agent.core.interaction.data.InteractionInputData;
|
||||
import work.slhaf.agent.core.interaction.data.context.InteractionContext;
|
||||
import work.slhaf.agent.core.interaction.module.InteractionModule;
|
||||
import work.slhaf.agent.core.interaction.module.InteractionModulesLoader;
|
||||
import work.slhaf.agent.module.modules.core.CoreModel;
|
||||
import work.slhaf.agent.module.modules.preprocess.PreprocessExecutor;
|
||||
import work.slhaf.agent.module.modules.task.TaskScheduler;
|
||||
@@ -43,7 +43,7 @@ public class InteractionHub {
|
||||
return interactionHub;
|
||||
}
|
||||
|
||||
public void call(InteractionInputData inputData) throws IOException, ClassNotFoundException, InterruptedException {
|
||||
public void call(InteractionInputData inputData) throws IOException, ClassNotFoundException {
|
||||
InteractionContext interactionContext = PreprocessExecutor.getInstance().execute(inputData);
|
||||
try {
|
||||
//预处理
|
||||
@@ -55,7 +55,7 @@ public class InteractionHub {
|
||||
interactionContext.getCoreResponse().put("text", "[ERROR] " + e.getMessage());
|
||||
} finally {
|
||||
callback.onTaskFinished(interactionContext.getUserInfo(), interactionContext.getCoreResponse().getString("text"));
|
||||
InteractionContext.clearUp();
|
||||
interactionContext.clearUp();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
package work.slhaf.agent.core.interaction;
|
||||
|
||||
import work.slhaf.agent.core.interaction.data.InteractionContext;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public interface InteractionModule {
|
||||
void execute(InteractionContext context) throws IOException, ClassNotFoundException, InterruptedException;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package work.slhaf.agent.core.interaction;
|
||||
package work.slhaf.agent.core.interaction.agent_interface;
|
||||
|
||||
import work.slhaf.agent.core.interaction.data.InteractionInputData;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package work.slhaf.agent.core.interaction;
|
||||
package work.slhaf.agent.core.interaction.agent_interface;
|
||||
|
||||
public interface TaskCallback {
|
||||
void onTaskFinished(String userInfo,String output);
|
||||
@@ -1,76 +0,0 @@
|
||||
package work.slhaf.agent.core.interaction.data;
|
||||
|
||||
import com.alibaba.fastjson2.JSONArray;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import work.slhaf.agent.common.pojo.PersistableObject;
|
||||
import work.slhaf.agent.module.common.AppendPromptData;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
public class InteractionContext extends PersistableObject {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static InteractionContext currentContext;
|
||||
|
||||
protected String userId;
|
||||
protected String userNickname;
|
||||
protected String userInfo;
|
||||
protected LocalDateTime dateTime;
|
||||
protected boolean single;
|
||||
|
||||
protected String input;
|
||||
|
||||
protected JSONObject coreContext;
|
||||
protected JSONObject moduleContext;
|
||||
protected JSONObject coreResponse;
|
||||
|
||||
public InteractionContext() {
|
||||
currentContext = this;
|
||||
this.moduleContext = new JSONObject();
|
||||
this.moduleContext.put(Constant.APPENDED_PROMPT,new JSONArray());
|
||||
}
|
||||
|
||||
public void setFinished(boolean finished) {
|
||||
moduleContext.put(Constant.FINISHED,finished);
|
||||
}
|
||||
|
||||
public boolean isFinished(){
|
||||
return moduleContext.getBooleanValue(Constant.FINISHED);
|
||||
}
|
||||
|
||||
public void setAppendedPrompt(AppendPromptData appendedPrompt){
|
||||
moduleContext.getJSONArray(Constant.APPENDED_PROMPT).add(appendedPrompt);
|
||||
}
|
||||
|
||||
public List<AppendPromptData> getAppendedPrompt(){
|
||||
List<AppendPromptData> list = new ArrayList<>();
|
||||
for (Object o : moduleContext.getJSONArray(Constant.APPENDED_PROMPT)) {
|
||||
JSONObject object = (JSONObject) o;
|
||||
list.add(object.to(AppendPromptData.class));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public static InteractionContext getInstance() {
|
||||
return currentContext;
|
||||
}
|
||||
|
||||
public static void clearUp(){
|
||||
currentContext = null;
|
||||
}
|
||||
|
||||
private static class Constant{
|
||||
private static final String FINISHED = "finished";
|
||||
private static final String APPENDED_PROMPT = "appendedPrompt";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package work.slhaf.agent.core.interaction.data.context;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import work.slhaf.agent.common.serialize.PersistableObject;
|
||||
import work.slhaf.agent.core.interaction.data.context.subcontext.CoreContext;
|
||||
import work.slhaf.agent.core.interaction.data.context.subcontext.ModuleContext;
|
||||
import work.slhaf.agent.module.common.AppendPromptData;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
public class InteractionContext extends PersistableObject {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static HashMap<String, InteractionContext> activeContext = new HashMap<>();
|
||||
|
||||
protected String userId;
|
||||
protected String userNickname;
|
||||
protected String userInfo;
|
||||
protected LocalDateTime dateTime;
|
||||
protected boolean single;
|
||||
|
||||
protected String input;
|
||||
|
||||
protected CoreContext coreContext = new CoreContext();
|
||||
protected ModuleContext moduleContext = new ModuleContext();
|
||||
protected JSONObject coreResponse = new JSONObject();
|
||||
|
||||
public InteractionContext() {
|
||||
activeContext.put(userId, this);
|
||||
}
|
||||
|
||||
public void setFinished(boolean finished) {
|
||||
moduleContext.setFinished(finished);
|
||||
}
|
||||
|
||||
public boolean isFinished() {
|
||||
return moduleContext.isFinished();
|
||||
}
|
||||
|
||||
public void setAppendedPrompt(AppendPromptData appendedPrompt) {
|
||||
List<AppendPromptData> appendPromptList = moduleContext.getAppendedPrompt();
|
||||
appendPromptList.addFirst(appendedPrompt);
|
||||
}
|
||||
|
||||
public static HashMap<String, InteractionContext> getInstance() {
|
||||
return activeContext;
|
||||
}
|
||||
|
||||
public void clearUp() {
|
||||
activeContext.remove(userId);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package work.slhaf.agent.core.interaction.data.context.subcontext;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
@Data
|
||||
public class CoreContext {
|
||||
private String text;
|
||||
private String dateTime;
|
||||
private String userNick;
|
||||
private String userId;
|
||||
private HashMap<String, Boolean> activeModules = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return JSONObject.toJSONString(this);
|
||||
}
|
||||
|
||||
public void addActiveModule(String moduleName) {
|
||||
activeModules.put(moduleName, false);
|
||||
}
|
||||
|
||||
public void activateModule(String moduleName){
|
||||
activeModules.put(moduleName, true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package work.slhaf.agent.core.interaction.data.context.subcontext;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import lombok.Data;
|
||||
import work.slhaf.agent.module.common.AppendPromptData;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class ModuleContext {
|
||||
private List<AppendPromptData> appendedPrompt = new ArrayList<>();
|
||||
private JSONObject extraContext = new JSONObject();
|
||||
private boolean finished = false;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package work.slhaf.agent.core.interaction.module;
|
||||
|
||||
import work.slhaf.agent.core.interaction.data.context.InteractionContext;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public interface InteractionModule {
|
||||
void execute(InteractionContext context) throws IOException, ClassNotFoundException;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package work.slhaf.agent.core.interaction;
|
||||
package work.slhaf.agent.core.interaction.module;
|
||||
|
||||
import work.slhaf.agent.common.config.Config;
|
||||
import work.slhaf.agent.common.config.ModuleConfig;
|
||||
@@ -7,7 +7,7 @@ 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.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.node.MemoryNode;
|
||||
@@ -72,17 +72,6 @@ public class MemoryGraph extends PersistableObject {
|
||||
*/
|
||||
private ConcurrentHashMap<String/*userId*/, ConcurrentHashMap<LocalDateTime, String>> userDialogMap;
|
||||
|
||||
/**
|
||||
* 当前对话的活动性总结, 拥有比dialogMap更丰富的全文细节, 作为当前对话token超限时的必要上下文压缩存储
|
||||
*/
|
||||
// private List<String> currentCompressedSessionContext;
|
||||
|
||||
/**
|
||||
* 存储确定性记忆, 如'用户爱好'等确定性信息
|
||||
* 该部分作为'主LLM'system prompt常驻
|
||||
*/
|
||||
// private HashMap<String /*userId*/, ConcurrentHashMap<String /*memoryKey*/, String /*memoryValue*/>> staticMemory;
|
||||
|
||||
/**
|
||||
* memorySliceCache计数器,每日清空
|
||||
*/
|
||||
@@ -104,8 +93,6 @@ public class MemoryGraph extends PersistableObject {
|
||||
*/
|
||||
private HashMap<String, String> modelPrompt;
|
||||
|
||||
// private String character;
|
||||
|
||||
/**
|
||||
* 主模型的聊天记录
|
||||
*/
|
||||
@@ -126,17 +113,15 @@ public class MemoryGraph extends PersistableObject {
|
||||
this.topicNodes = new HashMap<>();
|
||||
this.existedTopics = new HashMap<>();
|
||||
this.currentDateDialogSlices = new HashMap<>();
|
||||
// this.staticMemory = new HashMap<>();
|
||||
this.memoryNodeCacheCounter = new ConcurrentHashMap<>();
|
||||
this.memorySliceCache = new ConcurrentHashMap<>();
|
||||
this.modelPrompt = new HashMap<>();
|
||||
this.selectedSlices = new HashSet<>();
|
||||
this.users = new ArrayList<>();
|
||||
this.userDialogMap = new ConcurrentHashMap<>();
|
||||
// this.currentCompressedSessionContext = new ArrayList<>();
|
||||
this.dialogMap = new HashMap<>();
|
||||
// this.character = basicCharacter;
|
||||
this.dateIndex = new HashMap<>();
|
||||
this.chatMessages = new ArrayList<>();
|
||||
}
|
||||
|
||||
public static MemoryGraph getInstance(String id) throws IOException, ClassNotFoundException {
|
||||
@@ -200,7 +185,7 @@ public class MemoryGraph extends PersistableObject {
|
||||
}
|
||||
}
|
||||
|
||||
public void insertMemory(List<String> topicPath, MemorySlice slice) throws IOException, ClassNotFoundException {
|
||||
public void insertMemory(List<String> topicPath, MemorySlice slice) {
|
||||
|
||||
try {
|
||||
//检查是否存在当天对应的memorySlice并确定是否插入
|
||||
@@ -297,17 +282,13 @@ public class MemoryGraph extends PersistableObject {
|
||||
//更新userDialogMap
|
||||
//移除两天前上下文缓存(切片总结)
|
||||
List<LocalDateTime> keysToRemove = new ArrayList<>();
|
||||
userDialogMap.forEach((k, v) -> {
|
||||
v.forEach((i, j) -> {
|
||||
userDialogMap.forEach((k, v) -> v.forEach((i, j) -> {
|
||||
if (now.minusDays(2).isAfter(i)) {
|
||||
keysToRemove.add(i);
|
||||
}
|
||||
});
|
||||
});
|
||||
}));
|
||||
for (LocalDateTime dateTime : keysToRemove) {
|
||||
userDialogMap.forEach((k, v) -> {
|
||||
v.remove(dateTime);
|
||||
});
|
||||
userDialogMap.forEach((k, v) -> v.remove(dateTime));
|
||||
}
|
||||
//放入新缓存
|
||||
userDialogMap
|
||||
@@ -342,7 +323,7 @@ public class MemoryGraph extends PersistableObject {
|
||||
|
||||
}
|
||||
|
||||
public MemoryResult selectMemory(String topicPathStr) throws IOException, ClassNotFoundException {
|
||||
public MemoryResult selectMemory(String topicPathStr) {
|
||||
MemoryResult memoryResult = new MemoryResult();
|
||||
List<String> topicPath = List.of(topicPathStr.split("->"));
|
||||
try {
|
||||
|
||||
@@ -5,9 +5,10 @@ import lombok.EqualsAndHashCode;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import work.slhaf.agent.common.chat.pojo.Message;
|
||||
import work.slhaf.agent.common.config.Config;
|
||||
import work.slhaf.agent.common.pojo.PersistableObject;
|
||||
import work.slhaf.agent.common.serialize.PersistableObject;
|
||||
import work.slhaf.agent.core.memory.pojo.MemoryResult;
|
||||
import work.slhaf.agent.core.memory.pojo.MemorySlice;
|
||||
import work.slhaf.agent.core.memory.pojo.MemorySliceResult;
|
||||
import work.slhaf.agent.core.memory.pojo.User;
|
||||
import work.slhaf.agent.shared.memory.EvaluatedSlice;
|
||||
|
||||
@@ -17,6 +18,7 @@ import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
@@ -66,12 +68,23 @@ public class MemoryManager extends PersistableObject {
|
||||
}));
|
||||
}
|
||||
|
||||
public MemoryResult selectMemory(String path) throws IOException, ClassNotFoundException {
|
||||
return memoryGraph.selectMemory(path);
|
||||
public MemoryResult selectMemory(String path) {
|
||||
return cacheFilter(memoryGraph.selectMemory(path));
|
||||
}
|
||||
|
||||
public MemoryResult selectMemory(LocalDate date) throws IOException, ClassNotFoundException {
|
||||
return memoryGraph.selectMemory(date);
|
||||
return cacheFilter(memoryGraph.selectMemory(date));
|
||||
}
|
||||
|
||||
private MemoryResult cacheFilter(MemoryResult memoryResult) {
|
||||
//过滤掉与缓存重复的切片
|
||||
CopyOnWriteArrayList<MemorySliceResult> memorySliceResult = memoryResult.getMemorySliceResult();
|
||||
List<MemorySlice> relatedMemorySliceResult = memoryResult.getRelatedMemorySliceResult();
|
||||
getDialogMap().forEach((k,v) -> {
|
||||
memorySliceResult.removeIf(m -> m.getMemorySlice().getSummary().equals(v));
|
||||
relatedMemorySliceResult.removeIf(m -> m.getSummary().equals(v));
|
||||
});
|
||||
return memoryResult;
|
||||
}
|
||||
|
||||
public void cleanSelectedSliceFilter() {
|
||||
@@ -115,10 +128,6 @@ public class MemoryManager extends PersistableObject {
|
||||
return memoryGraph.getTopicTree();
|
||||
}
|
||||
|
||||
/* public ConcurrentHashMap<String, String> getStaticMemory(String userId) {
|
||||
return memoryGraph.getStaticMemory().get(userId);
|
||||
}*/
|
||||
|
||||
public HashMap<LocalDateTime, String> getDialogMap() {
|
||||
return memoryGraph.getDialogMap();
|
||||
}
|
||||
@@ -127,11 +136,7 @@ public class MemoryManager extends PersistableObject {
|
||||
return memoryGraph.getUserDialogMap().get(userId);
|
||||
}
|
||||
|
||||
/* public String getCharacter() {
|
||||
return memoryGraph.getCharacter();
|
||||
}*/
|
||||
|
||||
public void insertSlice(MemorySlice memorySlice, String topicPath) throws IOException, ClassNotFoundException {
|
||||
public void insertSlice(MemorySlice memorySlice, String topicPath) {
|
||||
sliceInsertLock.lock();
|
||||
List<String> topicPathList = Arrays.stream(topicPath.split("->")).toList();
|
||||
memoryGraph.insertMemory(topicPathList, memorySlice);
|
||||
@@ -145,13 +150,6 @@ public class MemoryManager extends PersistableObject {
|
||||
messageCleanLock.unlock();
|
||||
}
|
||||
|
||||
/* public void insertStaticMemory(String userId, Map<String, String> newStaticMemory) {
|
||||
if (!memoryGraph.getStaticMemory().containsKey(userId)) {
|
||||
memoryGraph.getStaticMemory().put(userId, new ConcurrentHashMap<>());
|
||||
}
|
||||
memoryGraph.getStaticMemory().get(userId).putAll(newStaticMemory);
|
||||
}*/
|
||||
|
||||
public void updateDialogMap(LocalDateTime dateTime, String newDialogCache) {
|
||||
memoryGraph.updateDialogMap(dateTime, newDialogCache);
|
||||
}
|
||||
@@ -175,26 +173,25 @@ public class MemoryManager extends PersistableObject {
|
||||
}
|
||||
|
||||
public String getActivatedSlicesStr(String userId) {
|
||||
StringBuilder str = new StringBuilder();
|
||||
if (memoryManager.getActivatedSlices().containsKey(userId)) {
|
||||
memoryManager.getActivatedSlices().get(userId).forEach(slice -> {
|
||||
str.append("\n\n").append("[").append(slice.getDate()).append("]\n")
|
||||
.append(slice.getSummary());
|
||||
});
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
public String getDialogMapStr() {
|
||||
StringBuilder str = new StringBuilder();
|
||||
memoryGraph.getDialogMap().forEach((dateTime, dialog) -> {
|
||||
str.append("\n\n").append("[").append(dateTime).append("]\n")
|
||||
.append(dialog);
|
||||
});
|
||||
memoryGraph.getDialogMap().forEach((dateTime, dialog) -> str.append("\n\n").append("[").append(dateTime).append("]\n")
|
||||
.append(dialog));
|
||||
return str.toString();
|
||||
}
|
||||
|
||||
public String getUserDialogMapStr(String userId) {
|
||||
if (memoryGraph.getUserDialogMap().containsKey(userId)) {
|
||||
StringBuilder str = new StringBuilder();
|
||||
Collection<String> dialogMapValues = memoryGraph.getDialogMap().values();
|
||||
memoryGraph.getUserDialogMap().get(userId).forEach((dateTime, dialog) -> {
|
||||
@@ -205,5 +202,8 @@ public class MemoryManager extends PersistableObject {
|
||||
.append(dialog);
|
||||
});
|
||||
return str.toString();
|
||||
}else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ package work.slhaf.agent.core.memory.node;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import work.slhaf.agent.common.pojo.PersistableObject;
|
||||
import work.slhaf.agent.common.serialize.PersistableObject;
|
||||
import work.slhaf.agent.core.memory.exception.NullSliceListException;
|
||||
import work.slhaf.agent.core.memory.pojo.MemorySlice;
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ package work.slhaf.agent.core.memory.node;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import work.slhaf.agent.common.pojo.PersistableObject;
|
||||
import work.slhaf.agent.common.serialize.PersistableObject;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@@ -2,7 +2,7 @@ package work.slhaf.agent.core.memory.pojo;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import work.slhaf.agent.common.pojo.PersistableObject;
|
||||
import work.slhaf.agent.common.serialize.PersistableObject;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.util.List;
|
||||
@@ -17,4 +17,10 @@ public class MemoryResult extends PersistableObject {
|
||||
|
||||
private CopyOnWriteArrayList<MemorySliceResult> memorySliceResult;
|
||||
private List<MemorySlice> relatedMemorySliceResult;
|
||||
|
||||
public boolean isEmpty(){
|
||||
boolean a = memorySliceResult == null || memorySliceResult.isEmpty();
|
||||
boolean b = relatedMemorySliceResult == null || relatedMemorySliceResult.isEmpty();
|
||||
return a && b;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
import work.slhaf.agent.common.chat.pojo.Message;
|
||||
import work.slhaf.agent.common.pojo.PersistableObject;
|
||||
import work.slhaf.agent.common.serialize.PersistableObject;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.util.List;
|
||||
|
||||
@@ -1,9 +1,18 @@
|
||||
package work.slhaf.agent.core.memory.pojo;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import work.slhaf.agent.common.serialize.PersistableObject;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
public class MemorySliceResult {
|
||||
public class MemorySliceResult extends PersistableObject {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private MemorySlice sliceBefore;
|
||||
private MemorySlice memorySlice;
|
||||
private MemorySlice sliceAfter;
|
||||
|
||||
@@ -2,7 +2,7 @@ package work.slhaf.agent.core.memory.pojo;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import work.slhaf.agent.common.pojo.PersistableObject;
|
||||
import work.slhaf.agent.common.serialize.PersistableObject;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.util.List;
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
package work.slhaf.agent.core.session;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
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.pojo.PersistableObject;
|
||||
import work.slhaf.agent.common.serialize.PersistableObject;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.file.Files;
|
||||
@@ -67,14 +68,14 @@ public class SessionManager extends PersistableObject {
|
||||
}
|
||||
|
||||
public void addMetaMessage(String userId, MetaMessage metaMessage) {
|
||||
log.debug("[SessionManager] 当前会话历史: {}", singleMetaMessageMap);
|
||||
log.debug("[SessionManager] 当前会话历史: {}", JSONObject.toJSONString(singleMetaMessageMap));
|
||||
if (singleMetaMessageMap.containsKey(userId)) {
|
||||
singleMetaMessageMap.get(userId).add(metaMessage);
|
||||
} else {
|
||||
singleMetaMessageMap.put(userId, new java.util.ArrayList<>());
|
||||
singleMetaMessageMap.get(userId).add(metaMessage);
|
||||
}
|
||||
log.debug("[SessionManager] 会话历史更新: {}", singleMetaMessageMap);
|
||||
log.debug("[SessionManager] 会话历史更新: {}", JSONObject.toJSONString(singleMetaMessageMap));
|
||||
}
|
||||
|
||||
public List<Message> unpackAndClear(String userId) {
|
||||
|
||||
@@ -8,8 +8,8 @@ import org.java_websocket.WebSocket;
|
||||
import org.java_websocket.framing.Framedata;
|
||||
import org.java_websocket.handshake.ClientHandshake;
|
||||
import org.java_websocket.server.WebSocketServer;
|
||||
import work.slhaf.agent.core.interaction.InputReceiver;
|
||||
import work.slhaf.agent.core.interaction.InteractionThreadPoolExecutor;
|
||||
import work.slhaf.agent.common.thread.InteractionThreadPoolExecutor;
|
||||
import work.slhaf.agent.core.interaction.agent_interface.InputReceiver;
|
||||
import work.slhaf.agent.core.interaction.data.InteractionInputData;
|
||||
import work.slhaf.agent.core.interaction.data.InteractionOutputData;
|
||||
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
package work.slhaf.agent.module.common;
|
||||
|
||||
import work.slhaf.agent.core.interaction.data.InteractionContext;
|
||||
|
||||
/**
|
||||
* 用于在前置模块设置追加提示词
|
||||
*/
|
||||
public interface AppendPrompt {
|
||||
void setAppendedPrompt(InteractionContext context);
|
||||
}
|
||||
@@ -6,6 +6,6 @@ import java.util.HashMap;
|
||||
|
||||
@Data
|
||||
public class AppendPromptData {
|
||||
private String comment;
|
||||
private String moduleName;
|
||||
private HashMap<String,String> appendedPrompt;
|
||||
}
|
||||
|
||||
@@ -20,20 +20,6 @@ public class Model {
|
||||
protected static void setModel(Model model, String model_key, String promptModule, boolean withAwareness) {
|
||||
ModelConfig modelConfig = ModelConfig.load(model_key);
|
||||
|
||||
/*if (memoryGraph.getModelPrompt().containsKey(model_key)) {
|
||||
model.setPrompt(memoryGraph.getModelPrompt().get(model_key));
|
||||
} else {
|
||||
model.setPrompt(prompt);
|
||||
memoryGraph.getModelPrompt().put(model_key, prompt);
|
||||
}
|
||||
if (memoryGraph.getChatMessages() == null) {
|
||||
List<Message> tempMessages = new ArrayList<>();
|
||||
tempMessages.add(new Message(ChatConstant.Character.SYSTEM, model.getPrompt()));
|
||||
model.setMessages(tempMessages);
|
||||
memoryGraph.setChatMessages(tempMessages);
|
||||
} else {
|
||||
model.setMessages(memoryGraph.getChatMessages());
|
||||
}*/
|
||||
model.setBaseMessages(withAwareness ? ResourcesUtil.Prompt.loadPromptWithSelfAwareness(model_key, promptModule) : ResourcesUtil.Prompt.loadPrompt(model_key, promptModule));
|
||||
model.setChatClient(new ChatClient(modelConfig.getBaseUrl(), modelConfig.getApikey(), modelConfig.getModel()));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
package work.slhaf.agent.module.common;
|
||||
|
||||
import work.slhaf.agent.core.interaction.data.context.InteractionContext;
|
||||
|
||||
/**
|
||||
* 用于在前置模块设置追加提示词
|
||||
*/
|
||||
public interface PreModuleActions {
|
||||
void setAppendedPrompt(InteractionContext context);
|
||||
void setActiveModule(InteractionContext context);
|
||||
}
|
||||
@@ -8,8 +8,8 @@ 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.interaction.InteractionModule;
|
||||
import work.slhaf.agent.core.interaction.data.InteractionContext;
|
||||
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;
|
||||
@@ -17,7 +17,10 @@ import work.slhaf.agent.module.common.Model;
|
||||
import work.slhaf.agent.module.common.ModelConstant;
|
||||
|
||||
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;
|
||||
@@ -29,7 +32,6 @@ public class CoreModel extends Model implements InteractionModule {
|
||||
|
||||
public static final String MODEL_KEY = "core_model";
|
||||
private static volatile CoreModel coreModel;
|
||||
private static List<Message> baseMessagesCache;
|
||||
|
||||
private MemoryManager memoryManager;
|
||||
private SessionManager sessionManager;
|
||||
@@ -45,9 +47,9 @@ public class CoreModel extends Model implements InteractionModule {
|
||||
coreModel = new CoreModel();
|
||||
coreModel.memoryManager = MemoryManager.getInstance();
|
||||
coreModel.chatMessages = coreModel.memoryManager.getChatMessages();
|
||||
coreModel.appendedMessages = new ArrayList<>();
|
||||
coreModel.sessionManager = SessionManager.getInstance();
|
||||
setModel(coreModel, MODEL_KEY, ModelConstant.Prompt.CORE, true);
|
||||
baseMessagesCache = coreModel.getBaseMessages();
|
||||
coreModel.updateChatClientSettings();
|
||||
log.info("[CoreModel] CoreModel注册完毕...");
|
||||
}
|
||||
@@ -58,18 +60,20 @@ public class CoreModel extends Model implements InteractionModule {
|
||||
|
||||
@Override
|
||||
public void execute(InteractionContext interactionContext) {
|
||||
log.debug("[CoreModel] 主对话流程开始...");
|
||||
List<AppendPromptData> appendedPrompt = interactionContext.getAppendedPrompt();
|
||||
if (!appendedPrompt.isEmpty()) {
|
||||
String userId = interactionContext.getUserId();
|
||||
log.debug("[CoreModel] 主对话流程开始: {}", userId);
|
||||
List<AppendPromptData> appendedPrompt = interactionContext.getModuleContext().getAppendedPrompt();
|
||||
int appendedPromptSize = getAppendedPromptSize(appendedPrompt);
|
||||
if (appendedPromptSize > 0) {
|
||||
setAppendedPromptMessage(appendedPrompt);
|
||||
}
|
||||
activateModule(interactionContext);
|
||||
setMessageCount(interactionContext);
|
||||
|
||||
log.debug("[CoreModel] 当前消息列表大小: {}", this.chatMessages.size());
|
||||
log.debug("[CoreModel] 当前核心prompt内容: {}", interactionContext.getCoreContext().toString());
|
||||
|
||||
// Message strengthenMessage = new Message(ChatConstant.Character.SYSTEM, STRENGTHEN_PROMPT);
|
||||
setMessage(/*strengthenMessage, */interactionContext.getCoreContext().toString());
|
||||
setMessage(interactionContext.getCoreContext().toString());
|
||||
JSONObject response = new JSONObject();
|
||||
|
||||
int count = 0;
|
||||
@@ -81,10 +85,9 @@ public class CoreModel extends Model implements InteractionModule {
|
||||
} catch (Exception e) {
|
||||
log.warn("主模型回复格式出错, 将直接作为消息返回, 建议尝试更换主模型...");
|
||||
handleExceptionResponse(response, chatResponse.getMessage(), interactionContext);
|
||||
break;
|
||||
}
|
||||
log.debug("[CoreModel] CoreModel 响应内容: {}", response);
|
||||
handleResponse(interactionContext, response, chatResponse);
|
||||
updateModuleContextAndChatMessages(interactionContext, response.getString("text"), chatResponse);
|
||||
break;
|
||||
} catch (Exception e) {
|
||||
count++;
|
||||
@@ -95,18 +98,35 @@ public class CoreModel extends Model implements InteractionModule {
|
||||
break;
|
||||
}
|
||||
} finally {
|
||||
// this.chatMessages.remove(strengthenMessage);
|
||||
interactionContext.setCoreResponse(response);
|
||||
resetBaseAndAppendedMessages();
|
||||
updateCoreResponse(interactionContext, response);
|
||||
resetAppendedMessages();
|
||||
log.debug("[CoreModel] 消息列表更新大小: {}", this.chatMessages.size());
|
||||
}
|
||||
}
|
||||
log.debug("[CoreModel] 主对话流程结果: {}", interactionContext);
|
||||
log.debug("[CoreModel] 主对话流程({})结束...", userId);
|
||||
}
|
||||
|
||||
private void resetBaseAndAppendedMessages() {
|
||||
this.baseMessages.clear();
|
||||
this.baseMessages.addAll(baseMessagesCache);
|
||||
private int getAppendedPromptSize(List<AppendPromptData> appendedPrompt) {
|
||||
int size = 0;
|
||||
for (AppendPromptData data : appendedPrompt) {
|
||||
size += data.getAppendedPrompt().size();
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
private void activateModule(InteractionContext context) {
|
||||
HashMap<String, Boolean> activeModules = context.getCoreContext().getActiveModules();
|
||||
for (AppendPromptData data : context.getModuleContext().getAppendedPrompt()) {
|
||||
if (data.getAppendedPrompt().isEmpty()) continue;
|
||||
activeModules.put(data.getModuleName(), true);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateCoreResponse(InteractionContext interactionContext, JSONObject response) {
|
||||
interactionContext.getCoreResponse().put("text", response.getString("text"));
|
||||
}
|
||||
|
||||
private void resetAppendedMessages() {
|
||||
this.appendedMessages.clear();
|
||||
}
|
||||
|
||||
@@ -118,14 +138,16 @@ public class CoreModel extends Model implements InteractionModule {
|
||||
return this.chatClient.runChat(temp);
|
||||
}
|
||||
|
||||
private void handleResponse(InteractionContext interactionContext, JSONObject response, ChatResponse chatResponse) {
|
||||
private void updateModuleContextAndChatMessages(InteractionContext interactionContext, String response, ChatResponse chatResponse) {
|
||||
this.chatMessages.removeLast();
|
||||
Message primaryUserMessage = new Message(ChatConstant.Character.USER, interactionContext.getCoreContext().getString("text"));
|
||||
//添加时间标志
|
||||
String dateTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("\r\n**[yyyy-MM-dd HH:mm:ss]"));
|
||||
Message primaryUserMessage = new Message(ChatConstant.Character.USER, interactionContext.getCoreContext().getText() + dateTime);
|
||||
this.chatMessages.add(primaryUserMessage);
|
||||
Message assistantMessage = new Message(ChatConstant.Character.ASSISTANT, response.getString("text"));
|
||||
Message assistantMessage = new Message(ChatConstant.Character.ASSISTANT, response);
|
||||
this.chatMessages.add(assistantMessage);
|
||||
//设置上下文
|
||||
interactionContext.getModuleContext().put("total_token", chatResponse.getUsageBean().getTotal_tokens());
|
||||
interactionContext.getModuleContext().getExtraContext().put("total_token", chatResponse.getUsageBean().getTotal_tokens());
|
||||
//区分单人聊天场景
|
||||
if (interactionContext.isSingle()) {
|
||||
MetaMessage metaMessage = new MetaMessage(primaryUserMessage, assistantMessage);
|
||||
@@ -133,8 +155,7 @@ public class CoreModel extends Model implements InteractionModule {
|
||||
}
|
||||
}
|
||||
|
||||
private void setMessage(/*Message strengthenMessage,*/ String coreContextStr) {
|
||||
// this.chatMessages.add(strengthenMessage);
|
||||
private void setMessage(String coreContextStr) {
|
||||
Message userMessage = new Message(ChatConstant.Character.USER, coreContextStr);
|
||||
this.chatMessages.add(userMessage);
|
||||
}
|
||||
@@ -142,25 +163,24 @@ public class CoreModel extends Model implements InteractionModule {
|
||||
private void handleExceptionResponse(JSONObject response, String chatResponse, InteractionContext interactionContext) {
|
||||
response.put("text", chatResponse);
|
||||
interactionContext.setFinished(true);
|
||||
|
||||
}
|
||||
|
||||
private void setMessageCount(InteractionContext interactionContext) {
|
||||
int moduleMessageCount = appendedMessages.size();
|
||||
int messageCount = chatMessages.size() - moduleMessageCount;
|
||||
interactionContext.getModuleContext().put("message_count", messageCount);
|
||||
interactionContext.getModuleContext().getExtraContext().put("message_count", chatMessages.size());
|
||||
}
|
||||
|
||||
private void setAppendedPromptMessage(List<AppendPromptData> appendPrompt) {
|
||||
Message appendDeclareMessage = Message.builder()
|
||||
.role(ChatConstant.Character.USER)
|
||||
// .content(ModelConstant.CharacterPrefix.SYSTEM + "以下为追加字段声明,可能包含用户的输入字段和你需要在回应中添加的输出字段.")
|
||||
.content(ModelConstant.CharacterPrefix.SYSTEM + "以下为你的相关认知内容,可在对话中参考")
|
||||
.content(ModelConstant.CharacterPrefix.SYSTEM + "以下为‘你’的相关认知内容,可在对话中参考")
|
||||
.build();
|
||||
this.appendedMessages.add(appendDeclareMessage);
|
||||
for (AppendPromptData data : appendPrompt) {
|
||||
setStartMessage(data);
|
||||
setContentMessage(data);
|
||||
setEndMessage(data);
|
||||
setAssistantMessage();
|
||||
}
|
||||
Message appendEndMessage = Message.builder()
|
||||
.role(ChatConstant.Character.USER)
|
||||
@@ -169,10 +189,17 @@ public class CoreModel extends Model implements InteractionModule {
|
||||
this.appendedMessages.add(appendEndMessage);
|
||||
}
|
||||
|
||||
private void setAssistantMessage() {
|
||||
appendedMessages.add(Message.builder()
|
||||
.role(ChatConstant.Character.ASSISTANT)
|
||||
.content("明白了")
|
||||
.build());
|
||||
}
|
||||
|
||||
private void setEndMessage(AppendPromptData data) {
|
||||
Message endMessage = Message.builder()
|
||||
.role(ChatConstant.Character.USER)
|
||||
.content(ModelConstant.CharacterPrefix.SYSTEM + data.getComment() + "认知补充结束.")
|
||||
.content(ModelConstant.CharacterPrefix.SYSTEM + data.getModuleName() + "认知补充结束.")
|
||||
.build();
|
||||
appendedMessages.add(endMessage);
|
||||
}
|
||||
@@ -181,7 +208,7 @@ public class CoreModel extends Model implements InteractionModule {
|
||||
data.getAppendedPrompt().forEach((k, v) -> {
|
||||
Message contentMessage = Message.builder()
|
||||
.role(ChatConstant.Character.USER)
|
||||
.content(ModelConstant.CharacterPrefix.SYSTEM + k + v)
|
||||
.content(ModelConstant.CharacterPrefix.SYSTEM + k + v + "\r\n")
|
||||
.build();
|
||||
appendedMessages.add(contentMessage);
|
||||
});
|
||||
@@ -190,7 +217,7 @@ public class CoreModel extends Model implements InteractionModule {
|
||||
private void setStartMessage(AppendPromptData data) {
|
||||
Message startMessage = Message.builder()
|
||||
.role(ChatConstant.Character.USER)
|
||||
.content(ModelConstant.CharacterPrefix.SYSTEM + data.getComment() + "以下为" + data.getComment() + "相关认知.")
|
||||
.content(ModelConstant.CharacterPrefix.SYSTEM + data.getModuleName() + "以下为" + data.getModuleName() + "相关认知.")
|
||||
.build();
|
||||
appendedMessages.add(startMessage);
|
||||
}
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
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.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.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.pojo.MemorySlice;
|
||||
import work.slhaf.agent.module.common.AppendPrompt;
|
||||
import work.slhaf.agent.module.common.AppendPromptData;
|
||||
import work.slhaf.agent.module.common.PreModuleActions;
|
||||
import work.slhaf.agent.module.modules.memory.selector.evaluator.SliceSelectEvaluator;
|
||||
import work.slhaf.agent.module.modules.memory.selector.evaluator.data.EvaluatorInput;
|
||||
import work.slhaf.agent.module.modules.memory.selector.extractor.MemorySelectExtractor;
|
||||
@@ -29,38 +30,10 @@ import java.util.List;
|
||||
|
||||
@Data
|
||||
@Slf4j
|
||||
public class MemorySelector implements InteractionModule, AppendPrompt {
|
||||
public class MemorySelector implements InteractionModule, PreModuleActions {
|
||||
|
||||
private static volatile MemorySelector memorySelector;
|
||||
/* public static final String appendPrompt = """
|
||||
新增输入字段示例:
|
||||
|
||||
"memory_slices": [{ //记忆切片,可能为多个
|
||||
"chatMessages": [{
|
||||
"role": "user"/"assistant", //该信息发送者
|
||||
"content": "消息内容"
|
||||
}],
|
||||
"date": "2024-03-20", //切片日期
|
||||
"summary": "切片总结"
|
||||
}],
|
||||
"static_memory": "对于该用户的常识性记忆,如爱好、住处、生日",
|
||||
"dialog_map": { //近两日的与所有用户的对话缓存
|
||||
"2023-01-01T11:30": "用户a[dawgbi-dwa-ccc] 尝试分享生活点滴并营造氛围感",
|
||||
"2023-01-02T11:30": "用户b[dawgbi-dwa-ccc] 尝试分享生活点滴并营造氛围感"
|
||||
}
|
||||
"user_dialog_map": { //与当前用户的近两日对话缓存
|
||||
"2023-01-01T11:30": "与用户讨论了...",
|
||||
"2023-01-02T11:30": "与用户讨论了..."
|
||||
}
|
||||
|
||||
无新增输出字段
|
||||
|
||||
##注意
|
||||
a. 这些字段中可能出现的第一人称描述都是指`Partner`,即你所属的智能体,当前用户正在对话的对象
|
||||
b. `dialog_map`和`user_dialog_map`中,值都将以`用户昵称[用户uuid]`开头,你需要正确区分不同用户
|
||||
c. 若`text`字段,即用户的真正输入内容未涉及`dialog_map`, `user_dialog_map`等字段中的内容,你需要仅根据用户的输入来确定如何回复.当用户未提及时,这两个字段中的内容时,你不需要主动提起.
|
||||
d. 做出回应时,你需要考虑上述新增字段与当前的时间差异
|
||||
""";*/
|
||||
private static final String MODULE_NAME = "[记忆模块]";
|
||||
|
||||
private MemoryManager memoryManager;
|
||||
private SliceSelectEvaluator sliceSelectEvaluator;
|
||||
@@ -84,25 +57,26 @@ public class MemorySelector implements InteractionModule, AppendPrompt {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(InteractionContext interactionContext) throws IOException, ClassNotFoundException, InterruptedException {
|
||||
public void execute(InteractionContext interactionContext) throws IOException, ClassNotFoundException {
|
||||
log.debug("[MemorySelector] 记忆回溯流程开始...");
|
||||
String userId = interactionContext.getUserId();
|
||||
//获取主题路径
|
||||
ExtractorResult extractorResult = memorySelectExtractor.execute(interactionContext);
|
||||
if (extractorResult.isRecall() || !extractorResult.getMatches().isEmpty()) {
|
||||
if (memoryManager.getActivatedSlices().get(userId) != null) {
|
||||
memoryManager.getActivatedSlices().get(userId).clear();
|
||||
}
|
||||
List<EvaluatedSlice> evaluatedSlices = selectAndEvaluateMemory(interactionContext, extractorResult);
|
||||
memoryManager.updateActivatedSlices(userId, evaluatedSlices);
|
||||
}
|
||||
//设置上下文
|
||||
// setCoreContext(interactionContext);
|
||||
//设置追加提示词
|
||||
setAppendedPrompt(interactionContext);
|
||||
setModuleContextRecall(interactionContext);
|
||||
log.debug("[MemorySelector] 记忆回溯结果: {}", interactionContext);
|
||||
setActiveModule(interactionContext);
|
||||
log.debug("[MemorySelector] 记忆回溯完成...");
|
||||
}
|
||||
|
||||
private List<EvaluatedSlice> selectAndEvaluateMemory(InteractionContext interactionContext, ExtractorResult extractorResult) throws IOException, ClassNotFoundException, InterruptedException {
|
||||
private List<EvaluatedSlice> selectAndEvaluateMemory(InteractionContext interactionContext, ExtractorResult extractorResult) throws IOException, ClassNotFoundException {
|
||||
log.debug("[MemorySelector] 触发记忆回溯...");
|
||||
//查找切片
|
||||
String userId = interactionContext.getUserId();
|
||||
@@ -114,20 +88,12 @@ public class MemorySelector implements InteractionModule, AppendPrompt {
|
||||
.memoryResults(memoryResultList)
|
||||
.messages(memoryManager.getChatMessages())
|
||||
.build();
|
||||
log.debug("[MemorySelector] 切片评估输入: {}", evaluatorInput);
|
||||
log.debug("[MemorySelector] 切片评估输入: {}", JSONObject.toJSONString(evaluatorInput));
|
||||
List<EvaluatedSlice> memorySlices = sliceSelectEvaluator.execute(evaluatorInput);
|
||||
log.debug("[MemorySelector] 切片评估结果: {}", memorySlices);
|
||||
log.debug("[MemorySelector] 切片评估结果: {}", JSONObject.toJSONString(memorySlices));
|
||||
return memorySlices;
|
||||
}
|
||||
|
||||
/*private void setCoreContext(InteractionContext interactionContext) {
|
||||
String userId = interactionContext.getUserId();
|
||||
interactionContext.getCoreContext().put("memory_slices", memoryManager.getActivatedSlices().get(userId));
|
||||
// interactionContext.getCoreContext().put("static_memory", memoryManager.getStaticMemory(userId));
|
||||
interactionContext.getCoreContext().put("dialog_map", memoryManager.getDialogMap());
|
||||
interactionContext.getCoreContext().put("user_dialog_map", memoryManager.getUserDialogMap(userId));
|
||||
}*/
|
||||
|
||||
private void setModuleContextRecall(InteractionContext interactionContext) {
|
||||
String userId = interactionContext.getUserId();
|
||||
boolean recall;
|
||||
@@ -136,9 +102,9 @@ public class MemorySelector implements InteractionModule, AppendPrompt {
|
||||
} else {
|
||||
recall = !memoryManager.getActivatedSlices().get(userId).isEmpty();
|
||||
}
|
||||
interactionContext.getModuleContext().put("recall", recall);
|
||||
interactionContext.getModuleContext().getExtraContext().put("recall", recall);
|
||||
if (recall) {
|
||||
interactionContext.getModuleContext().put("recall_count", memoryManager.getActivatedSlices().get(userId).size());
|
||||
interactionContext.getModuleContext().getExtraContext().put("recall_count", memoryManager.getActivatedSlices().get(userId).size());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,7 +118,7 @@ public class MemorySelector implements InteractionModule, AppendPrompt {
|
||||
memoryManager.selectMemory(LocalDate.parse(match.getText()));
|
||||
default -> null;
|
||||
};
|
||||
if (memoryResult == null) continue;
|
||||
if (memoryResult == null || memoryResult.isEmpty()) continue;
|
||||
removeDuplicateSlice(memoryResult);
|
||||
memoryResultList.add(memoryResult);
|
||||
} catch (UnExistedDateIndexException | UnExistedTopicException e) {
|
||||
@@ -190,11 +156,16 @@ public class MemorySelector implements InteractionModule, AppendPrompt {
|
||||
String userId = context.getUserId();
|
||||
HashMap<String, String> map = getPromptDataMap(userId);
|
||||
AppendPromptData data = new AppendPromptData();
|
||||
data.setComment("[记忆模块]");
|
||||
data.setModuleName(MODULE_NAME);
|
||||
data.setAppendedPrompt(map);
|
||||
context.setAppendedPrompt(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setActiveModule(InteractionContext context) {
|
||||
context.getCoreContext().addActiveModule(MODULE_NAME);
|
||||
}
|
||||
|
||||
private HashMap<String, String> getPromptDataMap(String userId) {
|
||||
HashMap<String, String> map = new HashMap<>();
|
||||
String dialogMapStr = memoryManager.getDialogMapStr();
|
||||
@@ -203,12 +174,12 @@ public class MemorySelector implements InteractionModule, AppendPrompt {
|
||||
}
|
||||
|
||||
String userDialogMapStr = memoryManager.getUserDialogMapStr(userId);
|
||||
if (!userDialogMapStr.isEmpty()) {
|
||||
map.put("[用户记忆缓存] <与最新一条消息的发送者的近两天对话记忆印象, 可能与[记忆缓存]稍有重复>", "与当前用户的近两日对话缓存");
|
||||
if (userDialogMapStr != null && !userDialogMapStr.isEmpty()) {
|
||||
map.put("[用户记忆缓存] <与最新一条消息的发送者的近两天对话记忆印象, 可能与[记忆缓存]稍有重复>", userDialogMapStr);
|
||||
}
|
||||
|
||||
String sliceStr = memoryManager.getActivatedSlicesStr(userId);
|
||||
if (!sliceStr.isEmpty()){
|
||||
if (sliceStr != null && !sliceStr.isEmpty()) {
|
||||
map.put("[记忆切片] <你与最新一条消息的发送者的相关回忆, 不会与[记忆缓存]重复, 如果有重复你也可以指出来()>", sliceStr);
|
||||
}
|
||||
return map;
|
||||
|
||||
@@ -6,7 +6,7 @@ import com.alibaba.fastjson2.JSONObject;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import work.slhaf.agent.core.interaction.InteractionThreadPoolExecutor;
|
||||
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.MemorySlice;
|
||||
@@ -55,7 +55,7 @@ public class SliceSelectEvaluator extends Model {
|
||||
return sliceSelectEvaluator;
|
||||
}
|
||||
|
||||
public List<EvaluatedSlice> execute(EvaluatorInput evaluatorInput) throws InterruptedException {
|
||||
public List<EvaluatedSlice> execute(EvaluatorInput evaluatorInput) {
|
||||
log.debug("[SliceSelectEvaluator] 切片评估模块开始...");
|
||||
List<MemoryResult> memoryResultList = evaluatorInput.getMemoryResults();
|
||||
List<Callable<Void>> tasks = new ArrayList<>();
|
||||
@@ -78,9 +78,9 @@ public class SliceSelectEvaluator extends Model {
|
||||
.memory_slices(sliceSummaryList)
|
||||
.history(evaluatorInput.getMessages())
|
||||
.build();
|
||||
log.debug("[SliceSelectEvaluator] 评估[{}]输入: {}", thisCount, batchInput);
|
||||
log.debug("[SliceSelectEvaluator] 评估[{}]输入: {}", thisCount, JSONObject.toJSONString(batchInput));
|
||||
EvaluatorResult evaluatorResult = JSONObject.parseObject(extractJson(singleChat(JSONUtil.toJsonStr(batchInput)).getMessage()), EvaluatorResult.class);
|
||||
log.debug("[SliceSelectEvaluator] 评估[{}]结果: {}", thisCount, evaluatorResult);
|
||||
log.debug("[SliceSelectEvaluator] 评估[{}]结果: {}", thisCount, JSONObject.toJSONString(evaluatorResult));
|
||||
for (Long result : evaluatorResult.getResults()) {
|
||||
SliceSummary sliceSummary = map.get(result);
|
||||
EvaluatedSlice evaluatedSlice = EvaluatedSlice.builder()
|
||||
@@ -99,25 +99,10 @@ public class SliceSelectEvaluator extends Model {
|
||||
|
||||
executor.invokeAll(tasks, 30, TimeUnit.SECONDS);
|
||||
log.debug("[SliceSelectEvaluator] 评估模块结束, 输出队列: {}", queue);
|
||||
return queue.stream().toList();
|
||||
List<EvaluatedSlice> temp = queue.stream().toList();
|
||||
return new ArrayList<>(temp);
|
||||
}
|
||||
|
||||
/* private void setEvaluatedSliceMessages(EvaluatedSlice evaluatedSlice, MemoryResult memoryResult, Long id) {
|
||||
//补充消息列表
|
||||
for (MemorySliceResult memorySliceResult : memoryResult.getMemorySliceResult()) {
|
||||
if (memorySliceResult.getMemorySlice().getTimestamp().equals(id)) {
|
||||
evaluatedSlice.setChatMessages(memorySliceResult.getMemorySlice().getChatMessages());
|
||||
return;
|
||||
}
|
||||
}
|
||||
for (MemorySlice memorySlice : memoryResult.getRelatedMemorySliceResult()) {
|
||||
if (memorySlice.getTimestamp().equals(id)) {
|
||||
evaluatedSlice.setChatMessages(memorySlice.getChatMessages());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
private void setSliceSummaryList(MemoryResult memoryResult, List<SliceSummary> sliceSummaryList, Map<Long, SliceSummary> map) {
|
||||
for (MemorySliceResult memorySliceResult : memoryResult.getMemorySliceResult()) {
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ 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.interaction.data.InteractionContext;
|
||||
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;
|
||||
@@ -75,7 +75,7 @@ public class MemorySelectExtractor extends Model {
|
||||
.topic_tree(memoryManager.getTopicTree())
|
||||
.activatedMemorySlices(activatedMemorySlices)
|
||||
.build();
|
||||
log.debug("[MemorySelectExtractor] 主题提取输入: {}", extractorInput);
|
||||
log.debug("[MemorySelectExtractor] 主题提取输入: {}", JSONObject.toJSONString(extractorInput));
|
||||
String responseStr = extractJson(singleChat(JSONUtil.toJsonPrettyStr(extractorInput)).getMessage());
|
||||
extractorResult = JSONObject.parseObject(responseStr, ExtractorResult.class);
|
||||
log.debug("[MemorySelectExtractor] 主题提取结果: {}", extractorResult);
|
||||
|
||||
@@ -5,14 +5,13 @@ import lombok.Data;
|
||||
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.core.interaction.InteractionModule;
|
||||
import work.slhaf.agent.core.interaction.InteractionThreadPoolExecutor;
|
||||
import work.slhaf.agent.core.interaction.data.InteractionContext;
|
||||
import work.slhaf.agent.common.thread.InteractionThreadPoolExecutor;
|
||||
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.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.exception.UnExpectedMessageCountException;
|
||||
import work.slhaf.agent.module.modules.memory.updater.summarizer.MemorySummarizer;
|
||||
import work.slhaf.agent.module.modules.memory.updater.summarizer.data.SummarizeInput;
|
||||
import work.slhaf.agent.module.modules.memory.updater.summarizer.data.SummarizeResult;
|
||||
@@ -22,6 +21,7 @@ import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@@ -33,18 +33,21 @@ public class MemoryUpdater implements InteractionModule {
|
||||
|
||||
private static final String USERID_REGEX = "\\[.*\\(([^)]+)\\)\\]";
|
||||
private static final long SCHEDULED_UPDATE_INTERVAL = 10 * 1000;
|
||||
private static final long UPDATE_TRIGGER_INTERVAL = 30 * 60 * 1000;
|
||||
private static final long UPDATE_TRIGGER_INTERVAL = 60 * 60 * 1000;
|
||||
// private static final int TRIGGER_TOKEN_LIMIT = 5 * 1000;
|
||||
private static final int TOKEN_PER_RECALL = 230;
|
||||
private static final int TRIGGER_ROLL_LIMIT = 32;
|
||||
private static final int TRIGGER_ROLL_LIMIT = 24;
|
||||
|
||||
private MemoryManager memoryManager;
|
||||
private InteractionThreadPoolExecutor executor;
|
||||
private MemorySelectExtractor memorySelectExtractor;
|
||||
private MemorySummarizer memorySummarizer;
|
||||
private SessionManager sessionManager;
|
||||
// private StaticMemoryExtractor staticMemoryExtractor;
|
||||
private int moduleMessageCount = 0;
|
||||
/**
|
||||
* 用于临时存储完整对话记录,在MemoryManager的分离后
|
||||
*/
|
||||
private List<Message> tempMessage;
|
||||
private final ReentrantLock messageUpdateLock = new ReentrantLock();
|
||||
|
||||
private MemoryUpdater() {
|
||||
}
|
||||
@@ -58,7 +61,6 @@ public class MemoryUpdater implements InteractionModule {
|
||||
memoryUpdater.setMemorySelectExtractor(MemorySelectExtractor.getInstance());
|
||||
memoryUpdater.setMemorySummarizer(MemorySummarizer.getInstance());
|
||||
memoryUpdater.setSessionManager(SessionManager.getInstance());
|
||||
// memoryUpdater.setStaticMemoryExtractor(StaticMemoryExtractor.getInstance());
|
||||
memoryUpdater.setExecutor(InteractionThreadPoolExecutor.getInstance());
|
||||
memoryUpdater.setScheduledUpdater();
|
||||
}
|
||||
@@ -77,13 +79,14 @@ public class MemoryUpdater implements InteractionModule {
|
||||
int chatCount = memoryManager.getChatMessages().size();
|
||||
if (lastUpdatedTime != 0 && currentTime - lastUpdatedTime > UPDATE_TRIGGER_INTERVAL && chatCount > 1) {
|
||||
updateMemory();
|
||||
memoryManager.getChatMessages().clear();
|
||||
//重置MemoryId
|
||||
sessionManager.refreshMemoryId();
|
||||
log.info("[MemoryUpdater] 记忆更新: 自动触发");
|
||||
}
|
||||
Thread.sleep(SCHEDULED_UPDATE_INTERVAL);
|
||||
} catch (Exception e) {
|
||||
log.error("[MemoryUpdater] 记忆自动更新线程出错: {}", e.getLocalizedMessage());
|
||||
log.error("[MemoryUpdater] 记忆自动更新线程出错: ", e);
|
||||
}
|
||||
}
|
||||
log.info("[MemoryUpdater] 记忆自动更新线程结束");
|
||||
@@ -98,7 +101,7 @@ public class MemoryUpdater implements InteractionModule {
|
||||
}
|
||||
executor.execute(() -> {
|
||||
//如果token 大于阈值,则更新记忆
|
||||
JSONObject moduleContext = interactionContext.getModuleContext();
|
||||
JSONObject moduleContext = interactionContext.getModuleContext().getExtraContext();
|
||||
boolean recall = moduleContext.getBoolean("recall");
|
||||
if (recall) {
|
||||
log.debug("[MemoryUpdater] 存在回忆");
|
||||
@@ -106,10 +109,12 @@ public class MemoryUpdater implements InteractionModule {
|
||||
log.debug("[MemoryUpdater] 记忆切片数量 [{}]", recallCount);
|
||||
}
|
||||
int messageCount = memoryManager.getChatMessages().size();
|
||||
if (messageCount > TRIGGER_ROLL_LIMIT) {
|
||||
if (messageCount >= TRIGGER_ROLL_LIMIT) {
|
||||
try {
|
||||
log.debug("[MemoryUpdater] 记忆更新: 已达{}轮", TRIGGER_ROLL_LIMIT);
|
||||
updateMemory();
|
||||
//清空chatMessages
|
||||
clearChatMessages();
|
||||
} catch (Exception e) {
|
||||
log.error("[MemoryUpdater] 记忆更新线程出错: ", e);
|
||||
}
|
||||
@@ -120,13 +125,12 @@ public class MemoryUpdater implements InteractionModule {
|
||||
|
||||
private void updateMemory() {
|
||||
log.debug("[MemoryUpdater] 记忆更新流程开始...");
|
||||
tempMessage = new ArrayList<>(memoryManager.getChatMessages());
|
||||
HashMap<String, String> singleMemorySummary = new HashMap<>();
|
||||
//更新单聊记忆以及该场景中对应的确定性记忆,同时从chatMessages中去掉单聊记忆
|
||||
//更新单聊记忆,同时从chatMessages中去掉单聊记忆
|
||||
updateSingleChatSlices(singleMemorySummary);
|
||||
//更新多人场景下的记忆及相关的确定性记忆
|
||||
updateMultiChatSlices(singleMemorySummary);
|
||||
//清空chatMessages
|
||||
clearChatMessages();
|
||||
}
|
||||
|
||||
private void updateMultiChatSlices(HashMap<String, String> singleMemorySummary) {
|
||||
@@ -134,9 +138,11 @@ public class MemoryUpdater implements InteractionModule {
|
||||
//对剩下的多人聊天记录进行进行摘要
|
||||
executor.execute(() -> {
|
||||
log.debug("[MemoryUpdater] 多人聊天记忆更新流程开始...");
|
||||
try {
|
||||
List<Message> chatMessages = new ArrayList<>(memoryManager.getChatMessages());
|
||||
chatMessages.removeFirst();
|
||||
List<Message> chatMessages;
|
||||
messageUpdateLock.lock();
|
||||
chatMessages = new ArrayList<>(memoryManager.getChatMessages());
|
||||
messageUpdateLock.unlock();
|
||||
cleanMessage(chatMessages);
|
||||
if (!chatMessages.isEmpty()) {
|
||||
log.debug("[MemoryUpdater] 存在多人聊天记录, 流程正常进行...");
|
||||
//以第一条user对应的id为发起用户
|
||||
@@ -163,17 +169,27 @@ public class MemoryUpdater implements InteractionModule {
|
||||
}
|
||||
log.debug("[MemoryUpdater] 对话缓存更新完毕");
|
||||
log.debug("[MemoryUpdater] 多人聊天记忆更新流程结束...");
|
||||
} catch (IOException | ClassNotFoundException | InterruptedException e) {
|
||||
log.error("[MemoryUpdater] 多人场景记忆更新失败: ", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void clearChatMessages() {
|
||||
if (moduleMessageCount < 1) {
|
||||
throw new UnExpectedMessageCountException("ModuleMessageCount 异常: " + moduleMessageCount);
|
||||
private void cleanMessage(List<Message> chatMessages) {
|
||||
//清理时间标识
|
||||
for (Message message : chatMessages) {
|
||||
if (message.getRole().equals(ChatConstant.Character.ASSISTANT)) {
|
||||
continue;
|
||||
}
|
||||
String time = Arrays.stream(message.getContent().split("\\*\\*")).toList().getLast();
|
||||
message.getContent().replace("\r\n**" + time, "");
|
||||
}
|
||||
}
|
||||
|
||||
private void clearChatMessages() {
|
||||
//不全部清空,保留前1/3的输入防止上下文割裂
|
||||
messageUpdateLock.lock();
|
||||
List<Message> temp = new ArrayList<>(tempMessage.subList(0, TRIGGER_ROLL_LIMIT / 3));
|
||||
memoryManager.getChatMessages().clear();
|
||||
memoryManager.getChatMessages().addAll(temp);
|
||||
messageUpdateLock.unlock();
|
||||
}
|
||||
|
||||
private void setInvolvedUserId(String startUserId, MemorySlice memorySlice, List<Message> chatMessages) {
|
||||
@@ -213,9 +229,9 @@ public class MemoryUpdater implements InteractionModule {
|
||||
try {
|
||||
//单聊记忆更新
|
||||
SummarizeInput summarizeInput = new SummarizeInput(messages, memoryManager.getTopicTree());
|
||||
log.debug("[MemoryUpdater] 单聊记忆[{}]更新-总结流程-输入: {}", thisCount, summarizeInput);
|
||||
log.debug("[MemoryUpdater] 单聊记忆[{}]更新-总结流程-输入: {}", thisCount, JSONObject.toJSONString(summarizeInput));
|
||||
SummarizeResult summarizeResult = memorySummarizer.execute(summarizeInput);
|
||||
log.debug("[MemoryUpdater] 单聊记忆[{}]更新-总结流程-输出: {}", thisCount, summarizeResult);
|
||||
log.debug("[MemoryUpdater] 单聊记忆[{}]更新-总结流程-输出: {}", thisCount, JSONObject.toJSONString(summarizeResult));
|
||||
MemorySlice memorySlice = getMemorySlice(id, summarizeResult, messages);
|
||||
//插入时userDialogMap已经进行更新
|
||||
memoryManager.insertSlice(memorySlice, summarizeResult.getTopicPath());
|
||||
@@ -231,19 +247,6 @@ public class MemoryUpdater implements InteractionModule {
|
||||
return null;
|
||||
});
|
||||
|
||||
/*tasks.add(() -> {
|
||||
log.debug("[MemoryUpdater] 静态记忆更新开始...");
|
||||
StaticMemoryExtractInput input = StaticMemoryExtractInput.builder()
|
||||
.userId(id)
|
||||
.messages(messages)
|
||||
.existedStaticMemory(memoryManager.getStaticMemory(id))
|
||||
.build();
|
||||
log.debug("[MemoryUpdater] 静态记忆更新输入: {}", input);
|
||||
Map<String, String> staticMemoryResult = staticMemoryExtractor.execute(input);
|
||||
log.debug("[MemoryUpdater] 静态记忆更新结果: {}", staticMemoryResult);
|
||||
memoryManager.insertStaticMemory(id, staticMemoryResult);
|
||||
return null;
|
||||
});*/
|
||||
}
|
||||
executor.invokeAll(tasks);
|
||||
log.debug("[MemoryUpdater] 单聊记忆更新结束...");
|
||||
|
||||
@@ -2,11 +2,10 @@ package work.slhaf.agent.module.modules.memory.updater.summarizer;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import work.slhaf.agent.core.interaction.InteractionThreadPoolExecutor;
|
||||
import work.slhaf.agent.common.thread.InteractionThreadPoolExecutor;
|
||||
import work.slhaf.agent.module.modules.memory.updater.summarizer.data.SummarizeInput;
|
||||
import work.slhaf.agent.module.modules.memory.updater.summarizer.data.SummarizeResult;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
|
||||
@Data
|
||||
@@ -21,7 +20,7 @@ public class MemorySummarizer {
|
||||
private MultiSummarizer multiSummarizer;
|
||||
private TotalSummarizer totalSummarizer;
|
||||
|
||||
public static MemorySummarizer getInstance() throws IOException, ClassNotFoundException {
|
||||
public static MemorySummarizer getInstance() {
|
||||
if (memorySummarizer == null) {
|
||||
synchronized (MemorySummarizer.class) {
|
||||
if (memorySummarizer == null) {
|
||||
@@ -36,11 +35,11 @@ public class MemorySummarizer {
|
||||
return memorySummarizer;
|
||||
}
|
||||
|
||||
public SummarizeResult execute(SummarizeInput input) throws InterruptedException {
|
||||
public SummarizeResult execute(SummarizeInput input) {
|
||||
//进行长文本批量摘要
|
||||
singleSummarizer.execute(input.getChatMessages());
|
||||
//进行整体摘要并返回结果
|
||||
return memorySummarizer.execute(input);
|
||||
return multiSummarizer.execute(input);
|
||||
}
|
||||
|
||||
public String executeTotalSummary(HashMap<String, String> singleMemorySummary) {
|
||||
|
||||
@@ -37,7 +37,7 @@ public class MultiSummarizer extends Model {
|
||||
public SummarizeResult execute(SummarizeInput input) {
|
||||
log.debug("[MemorySummarizer] 整体摘要开始...");
|
||||
ChatResponse response = this.singleChat(JSONUtil.toJsonPrettyStr(input));
|
||||
log.debug("[MemorySummarizer] 整体摘要结果: {}", response);
|
||||
log.debug("[MemorySummarizer] 整体摘要结果: {}", JSONObject.toJSONString(response));
|
||||
return JSONObject.parseObject(extractJson(response.getMessage()), SummarizeResult.class);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||
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.core.interaction.InteractionThreadPoolExecutor;
|
||||
import work.slhaf.agent.common.thread.InteractionThreadPoolExecutor;
|
||||
import work.slhaf.agent.module.common.Model;
|
||||
import work.slhaf.agent.module.common.ModelConstant;
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@ import work.slhaf.agent.module.common.Model;
|
||||
import work.slhaf.agent.module.common.ModelConstant;
|
||||
import work.slhaf.agent.module.modules.perceive.static_extractor.data.StaticExtractInput;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -22,7 +21,7 @@ public class StaticPerceiveExtractor extends Model {
|
||||
public static final String MODEL_KEY = "static_extractor";
|
||||
|
||||
|
||||
public static StaticPerceiveExtractor getInstance() throws IOException, ClassNotFoundException {
|
||||
public static StaticPerceiveExtractor getInstance() {
|
||||
if (staticPerceiveExtractor == null) {
|
||||
synchronized (StaticPerceiveExtractor.class) {
|
||||
if (staticPerceiveExtractor == null) {
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
package work.slhaf.agent.module.modules.preprocess;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import lombok.Data;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import work.slhaf.agent.core.interaction.data.InteractionContext;
|
||||
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;
|
||||
@@ -60,19 +59,14 @@ public class PreprocessExecutor {
|
||||
context.setUserNickname(inputData.getUserNickName());
|
||||
context.setUserInfo(inputData.getUserInfo());
|
||||
context.setDateTime(inputData.getLocalDateTime());
|
||||
context.setSingle(inputData.isSingle());
|
||||
|
||||
context.setFinished(false);
|
||||
String user = "[" + inputData.getUserNickName() + "(" + userId + ")]";
|
||||
String input = user + " " + inputData.getContent();
|
||||
context.setInput(input);
|
||||
|
||||
context.setCoreContext(new JSONObject());
|
||||
setCoreContext(inputData, context, input, userId);
|
||||
setAppendedPrompt(context);
|
||||
context.setModuleContext(new JSONObject());
|
||||
|
||||
context.setSingle(inputData.isSingle());
|
||||
context.setFinished(false);
|
||||
setCoreContext(inputData, context, input, userId);
|
||||
|
||||
log.debug("[PreprocessExecutor] 预处理结果: {}", context);
|
||||
return context;
|
||||
@@ -81,20 +75,21 @@ public class PreprocessExecutor {
|
||||
private void setAppendedPrompt(InteractionContext context) {
|
||||
HashMap<String, String> map = new HashMap<>();
|
||||
map.put("text", "用户输入内容");
|
||||
map.put("datetime", "当前时间");
|
||||
map.put("datetime", "本次用户输入对应的当前时间");
|
||||
map.put("user_nick", "用户昵称");
|
||||
map.put("user_id", "用户id, 与user_nick区分, 这是用户的唯一标识");
|
||||
map.put("active_modules","已激活的模块, 为false时为激活但未活跃; 为true时为激活且活跃");
|
||||
map.put("其他", "历史对话中将在用户消息的最后一行标注时间");
|
||||
AppendPromptData data = new AppendPromptData();
|
||||
data.setComment("[system] 基础字段");
|
||||
data.setModuleName("[基础模块]");
|
||||
data.setAppendedPrompt(map);
|
||||
context.setAppendedPrompt(data);
|
||||
}
|
||||
|
||||
private void setCoreContext(InteractionInputData inputData, InteractionContext context, String input, String userId) {
|
||||
context.getCoreContext().put("text", input);
|
||||
context.getCoreContext().put("datetime", LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
|
||||
// context.getCoreContext().put("character", memoryManager.getCharacter());
|
||||
context.getCoreContext().put("user_nick", inputData.getUserNickName());
|
||||
context.getCoreContext().put("user_id", userId);
|
||||
context.getCoreContext().setText(input);
|
||||
context.getCoreContext().setDateTime(LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
|
||||
context.getCoreContext().setUserNick(inputData.getUserNickName());
|
||||
context.getCoreContext().setUserId(userId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,8 +5,6 @@ import lombok.EqualsAndHashCode;
|
||||
import work.slhaf.agent.module.common.Model;
|
||||
import work.slhaf.agent.module.common.ModelConstant;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
public class TaskEvaluator extends Model {
|
||||
@@ -15,7 +13,7 @@ public class TaskEvaluator extends Model {
|
||||
|
||||
private TaskEvaluator (){}
|
||||
|
||||
public static TaskEvaluator getInstance() throws IOException, ClassNotFoundException {
|
||||
public static TaskEvaluator getInstance() {
|
||||
if (taskEvaluator == null) {
|
||||
taskEvaluator = new TaskEvaluator();
|
||||
setModel(taskEvaluator,MODEL_KEY, ModelConstant.Prompt.SCHEDULE,true);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package work.slhaf.agent.module.modules.task;
|
||||
|
||||
import lombok.Data;
|
||||
import work.slhaf.agent.core.interaction.InteractionThreadPoolExecutor;
|
||||
import work.slhaf.agent.common.thread.InteractionThreadPoolExecutor;
|
||||
|
||||
@Data
|
||||
public class TaskExecutor {
|
||||
|
||||
@@ -2,10 +2,8 @@ package work.slhaf.agent.module.modules.task;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import work.slhaf.agent.core.interaction.InteractionModule;
|
||||
import work.slhaf.agent.core.interaction.data.InteractionContext;
|
||||
|
||||
import java.io.IOException;
|
||||
import work.slhaf.agent.core.interaction.data.context.InteractionContext;
|
||||
import work.slhaf.agent.core.interaction.module.InteractionModule;
|
||||
|
||||
@Data
|
||||
@Slf4j
|
||||
@@ -14,7 +12,7 @@ public class TaskScheduler implements InteractionModule {
|
||||
|
||||
private TaskScheduler(){}
|
||||
|
||||
public static TaskScheduler getInstance() throws IOException, ClassNotFoundException {
|
||||
public static TaskScheduler getInstance() {
|
||||
if (taskScheduler == null) {
|
||||
taskScheduler = new TaskScheduler();
|
||||
log.info("TaskScheduler注册完毕...");
|
||||
|
||||
@@ -3,7 +3,7 @@ package work.slhaf.agent.shared.memory;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import work.slhaf.agent.common.pojo.PersistableObject;
|
||||
import work.slhaf.agent.common.serialize.PersistableObject;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.time.LocalDate;
|
||||
|
||||
@@ -33,6 +33,6 @@
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"content": "谢谢。接下来的这些输入将来自真正的‘Partner’,务必按照上面的要求回应,但请铭记:以‘你’的感受或者用户的意图出发——因为‘你’也是Partner."
|
||||
"content": "谢谢。接下来这些输入将是真正的输入,务必按照上面的要求回应,但请铭记:以‘你’的感受或者用户的意图出发——因为‘你’也是Partner."
|
||||
}
|
||||
]
|
||||
Reference in New Issue
Block a user