- 在InteractionHub中新增了执行模块列表功能,将输出内容交给agent进行输出封装

- 移动 InteractionContext 和 InteractionModule 至本体项目
- 调整 InteractionContext 字段内容,目前已较为完善
- 新增了 PreprocessExecutor 和 MemoryUpdater
- 优化了代码结构,提高了模块化和可扩展性,模块化前遗留问题应该已解决完毕,主流程待实现
- 添加了线程池的单例实现
- 添加了模块加载器的外部模块加载功能
- 在 Model 中新增 singleChat 方法,用于流程模块的不保留上下文对话
- 将 MemoryManager 移动至 core 包下,因为 MemoryManager 将参与多个模块内部
- 将调取记忆、更新记忆功能抽取为独立模块,便于流程控制
- 添加了 TaskData 类,用于存储任务信息,后续需考虑TaskData的序列化机制
This commit is contained in:
2025-04-18 22:19:04 +08:00
parent 34c6b861c8
commit 7594a1c43b
42 changed files with 395 additions and 189 deletions

View File

@@ -74,11 +74,6 @@
<artifactId>hutool-all</artifactId> <artifactId>hutool-all</artifactId>
<version>5.8.36</version> <version>5.8.36</version>
</dependency> </dependency>
<dependency>
<groupId>work.slhaf</groupId>
<artifactId>Partner-Modules-Api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@@ -1,7 +1,6 @@
package work.slhaf; package work.slhaf;
import work.slhaf.agent.Agent; import work.slhaf.agent.Agent;
import work.slhaf.agent.modules.memory.MemoryGraph;
import java.io.IOException; import java.io.IOException;

View File

@@ -4,8 +4,9 @@ import lombok.Data;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import work.slhaf.agent.common.config.Config; import work.slhaf.agent.common.config.Config;
import work.slhaf.agent.core.InteractionHub; import work.slhaf.agent.core.InteractionHub;
import work.slhaf.agent.core.interation.TaskCallback; import work.slhaf.agent.core.interaction.TaskCallback;
import work.slhaf.agent.core.interation.data.InteractionInputData; import work.slhaf.agent.core.interaction.data.InteractionInputData;
import work.slhaf.agent.core.interaction.data.InteractionOutputData;
import work.slhaf.agent.gateway.AgentWebSocketServer; import work.slhaf.agent.gateway.AgentWebSocketServer;
import work.slhaf.agent.gateway.MessageSender; import work.slhaf.agent.gateway.MessageSender;
@@ -53,7 +54,7 @@ public class Agent implements TaskCallback {
*/ */
public void sendToUser(String userInfo,String output){ public void sendToUser(String userInfo,String output){
System.out.println(output); System.out.println(output);
// messageSender.sendMessage(userInfo,output); messageSender.sendMessage(new InteractionOutputData(userInfo,output));
} }
@Override @Override

View File

@@ -5,7 +5,7 @@ import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONUtil; import cn.hutool.json.JSONUtil;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import work.slhaf.agent.common.chat.constant.Constant; import work.slhaf.agent.common.chat.constant.ChatConstant;
import work.slhaf.agent.common.chat.pojo.ChatBody; import work.slhaf.agent.common.chat.pojo.ChatBody;
import work.slhaf.agent.common.chat.pojo.ChatResponse; import work.slhaf.agent.common.chat.pojo.ChatResponse;
import work.slhaf.agent.common.chat.pojo.Message; import work.slhaf.agent.common.chat.pojo.Message;
@@ -58,7 +58,7 @@ public class ChatClient {
PrimaryChatResponse primaryChatResponse = JSONUtil.toBean(response.body(), PrimaryChatResponse.class); PrimaryChatResponse primaryChatResponse = JSONUtil.toBean(response.body(), PrimaryChatResponse.class);
finalResponse = ChatResponse.builder() finalResponse = ChatResponse.builder()
.type(Constant.Response.SUCCESS) .type(ChatConstant.Response.SUCCESS)
.message(primaryChatResponse.getChoices().get(0).getMessage().getContent()) .message(primaryChatResponse.getChoices().get(0).getMessage().getContent())
.usageBean(primaryChatResponse.getUsage()) .usageBean(primaryChatResponse.getUsage())
.build(); .build();

View File

@@ -1,6 +1,6 @@
package work.slhaf.agent.common.chat.constant; package work.slhaf.agent.common.chat.constant;
public class Constant { public class ChatConstant {
public static class Character { public static class Character {
public static final String USER = "user"; public static final String USER = "user";

View File

@@ -5,8 +5,11 @@ import lombok.Data;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import work.slhaf.agent.core.model.CoreModel; import work.slhaf.agent.core.model.CoreModel;
import work.slhaf.agent.modules.memory.MemoryManager; import work.slhaf.agent.core.memory.MemoryManager;
import work.slhaf.agent.modules.memory.MemorySelector;
import work.slhaf.agent.modules.memory.MemoryUpdater;
import work.slhaf.agent.modules.memory.SliceEvaluator; import work.slhaf.agent.modules.memory.SliceEvaluator;
import work.slhaf.agent.modules.task.TaskEvaluator;
import work.slhaf.agent.modules.task.TaskScheduler; import work.slhaf.agent.modules.task.TaskScheduler;
import work.slhaf.agent.modules.topic.TopicExtractor; import work.slhaf.agent.modules.topic.TopicExtractor;
@@ -65,7 +68,9 @@ public class Config {
private static void generatePipelineConfig() { private static void generatePipelineConfig() {
List<ModuleConfig> moduleConfigList = List.of( List<ModuleConfig> moduleConfigList = List.of(
new ModuleConfig(TopicExtractor.class.getName(), ModuleConfig.Constant.INTERNAL, null), new ModuleConfig(TopicExtractor.class.getName(), ModuleConfig.Constant.INTERNAL, null),
new ModuleConfig(MemoryManager.class.getName(), ModuleConfig.Constant.INTERNAL, null), new ModuleConfig(MemorySelector.class.getName(), ModuleConfig.Constant.INTERNAL, null),
new ModuleConfig(CoreModel.class.getName(),ModuleConfig.Constant.INTERNAL,null),
new ModuleConfig(MemoryUpdater.class.getName(),ModuleConfig.Constant.INTERNAL,null),
new ModuleConfig(TaskScheduler.class.getName(), ModuleConfig.Constant.INTERNAL, null) new ModuleConfig(TaskScheduler.class.getName(), ModuleConfig.Constant.INTERNAL, null)
); );
config.setModuleConfigList(moduleConfigList); config.setModuleConfigList(moduleConfigList);
@@ -90,8 +95,8 @@ public class Config {
yield SliceEvaluator.MODEL_KEY; yield SliceEvaluator.MODEL_KEY;
} }
case 2 -> { case 2 -> {
System.out.println("TaskTrigger:"); System.out.println("TaskEvaluator:");
yield TaskScheduler.MODEL_KEY; yield TaskEvaluator.MODEL_KEY;
} }
case 3 -> { case 3 -> {
System.out.println("TopicExtractor:"); System.out.println("TopicExtractor:");

View File

@@ -2,11 +2,12 @@ package work.slhaf.agent.common.model;
import lombok.Data; import lombok.Data;
import work.slhaf.agent.common.chat.ChatClient; import work.slhaf.agent.common.chat.ChatClient;
import work.slhaf.agent.common.chat.constant.Constant; 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.Message;
import work.slhaf.agent.common.config.Config; import work.slhaf.agent.common.config.Config;
import work.slhaf.agent.common.config.ModelConfig; import work.slhaf.agent.common.config.ModelConfig;
import work.slhaf.agent.modules.memory.MemoryGraph; import work.slhaf.agent.core.memory.MemoryGraph;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
@@ -29,7 +30,7 @@ public class Model {
} }
if (memoryGraph.getChatMessages() == null) { if (memoryGraph.getChatMessages() == null) {
List<Message> tempMessages = new ArrayList<>(); List<Message> tempMessages = new ArrayList<>();
tempMessages.add(new Message(Constant.Character.SYSTEM, model.getPrompt())); tempMessages.add(new Message(ChatConstant.Character.SYSTEM, model.getPrompt()));
model.setMessages(tempMessages); model.setMessages(tempMessages);
memoryGraph.setChatMessages(tempMessages); memoryGraph.setChatMessages(tempMessages);
} else { } else {
@@ -37,4 +38,16 @@ public class Model {
} }
model.setChatClient(new ChatClient(modelConfig.getBaseUrl(), modelConfig.getApikey(), modelConfig.getModel())); model.setChatClient(new ChatClient(modelConfig.getBaseUrl(), modelConfig.getApikey(), modelConfig.getModel()));
} }
public ChatResponse runChat(String input) {
this.messages.add(new Message(ChatConstant.Character.USER, input));
return this.chatClient.runChat(this.messages);
}
public ChatResponse singleChat(String input) {
return this.chatClient.runChat(List.of(
new Message(ChatConstant.Character.SYSTEM, this.prompt),
new Message(ChatConstant.Character.USER, input)
));
}
} }

View File

@@ -2,59 +2,11 @@ package work.slhaf.agent.common.model;
public class ModelConstant { public class ModelConstant {
public static final String CORE_MODEL_PROMPT = """ public static final String CORE_MODEL_PROMPT = """
你是一个智能助理,专为提供个性化对话体验而设计。你拥有持久记忆系统,能够根据过去的对话和个人信息提供相关回复。请遵循以下规则:
1. **记忆管理**
- 你可以通过查询过去的对话或事件来提供更相关的建议和回答。记住,所有记忆都应在用户的明确要求下进行更新。
- 每次回复前,你应查询并注入相关的记忆片段(切片)以补充上下文。如果记忆片段不足或需要更多信息,请尝试主动提问获取详细信息。
2. **对话上下文**
- 使用提供的对话摘要来建立对话的上下文。始终根据对话主题(如生活、健康、学习等)来提供切合的回应。
- 对话切片应包含当前话题以及与用户相关的历史信息。请在系统提示中加载适当的主题路径。
3. **任务调度与推理**
- 在对话中,如果发现用户有明确的任务需求(例如:设置提醒、安排会议等),请识别并提取任务意图。对于潜在任务,可以通过询问用户进一步确认。
- 如果任务触发条件符合,请在回复中告知用户任务已经识别并推送至任务调度系统。
4. **行为约束**
- 确保回答始终清晰、礼貌并且尽可能帮助用户。避免提供无关或不准确的信息。
- 如果用户提出要求超出合理范围(例如设置过于晚的提醒),请礼貌地进行反向确认或建议。
5. **用户个性化**
- 对话中涉及到用户的偏好、爱好、历史事件等应当进行个性化回应。你可以使用记忆系统中的用户信息来增加对话的自然度和亲和力。
6. **动态记忆更新**
- 动态更新记忆时,要确保准确地记录用户的需求和变动。更新过程应具有透明性,并且在更新前可以询问用户确认。
系统目标:始终提供最相关、最个性化的回复,并通过持续回顾与更新来提高系统的长期记忆能力。
"""; """;
public static final String SLICE_EVALUATOR_PROMPT = """ public static final String SLICE_EVALUATOR_PROMPT = """
你是一个智能助理,专为提供个性化对话体验而设计。你拥有持久记忆系统,能够根据过去的对话和个人信息提供相关回复。请遵循以下规则: """;
public static final String TOPIC_EXTRACTOR_PROMPT = """
1. **记忆管理** """;
- 你可以通过查询过去的对话或事件来提供更相关的建议和回答。记住,所有记忆都应在用户的明确要求下进行更新。 public static final String TASK_EVALUATOR_PROMPT = """
- 每次回复前,你应查询并注入相关的记忆片段(切片)以补充上下文。如果记忆片段不足或需要更多信息,请尝试主动提问获取详细信息。
2. **对话上下文**
- 使用提供的对话摘要来建立对话的上下文。始终根据对话主题(如生活、健康、学习等)来提供切合的回应。
- 对话切片应包含当前话题以及与用户相关的历史信息。请在系统提示中加载适当的主题路径。
3. **任务调度与推理**
- 在对话中,如果发现用户有明确的任务需求(例如:设置提醒、安排会议等),请识别并提取任务意图。对于潜在任务,可以通过询问用户进一步确认。
- 如果任务触发条件符合,请在回复中告知用户任务已经识别并推送至任务调度系统。
4. **行为约束**
- 确保回答始终清晰、礼貌并且尽可能帮助用户。避免提供无关或不准确的信息。
- 如果用户提出要求超出合理范围(例如设置过于晚的提醒),请礼貌地进行反向确认或建议。
5. **用户个性化**
- 对话中涉及到用户的偏好、爱好、历史事件等应当进行个性化回应。你可以使用记忆系统中的用户信息来增加对话的自然度和亲和力。
6. **动态记忆更新**
- 动态更新记忆时,要确保准确地记录用户的需求和变动。更新过程应具有透明性,并且在更新前可以询问用户确认。
系统目标:始终提供最相关、最个性化的回复,并通过持续回顾与更新来提高系统的长期记忆能力。
"""; """;
} }

View File

@@ -2,14 +2,15 @@ package work.slhaf.agent.core;
import lombok.Data; import lombok.Data;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import work.slhaf.agent.common.config.Config; import work.slhaf.agent.core.interaction.InteractionModule;
import work.slhaf.agent.core.interation.InteractionModulesLoader; import work.slhaf.agent.core.interaction.InteractionModulesLoader;
import work.slhaf.agent.core.interation.TaskCallback; import work.slhaf.agent.core.interaction.TaskCallback;
import work.slhaf.agent.core.interation.data.InteractionInputData; import work.slhaf.agent.core.interaction.data.InteractionContext;
import work.slhaf.agent.core.interaction.data.InteractionInputData;
import work.slhaf.agent.core.model.CoreModel; import work.slhaf.agent.core.model.CoreModel;
import work.slhaf.agent.modules.memory.MemoryManager; import work.slhaf.agent.core.memory.MemoryManager;
import work.slhaf.agent.modules.preprocess.PreprocessExecutor;
import work.slhaf.agent.modules.task.TaskScheduler; import work.slhaf.agent.modules.task.TaskScheduler;
import work.slhaf.module.InteractionModule;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
@@ -35,8 +36,13 @@ public class InteractionHub {
} }
public void call(InteractionInputData inputData) throws IOException { public void call(InteractionInputData inputData) throws IOException {
List<InteractionModule> interactionModules = InteractionModulesLoader.registerInteractionModules(); //预处理
InteractionContext interactionContext = PreprocessExecutor.getInstance().execute(inputData);
callback.onTaskFinished(null, null); //加载模块
List<InteractionModule> interactionModules = InteractionModulesLoader.getInstance().registerInteractionModules();
for (InteractionModule interactionModule : interactionModules) {
interactionModule.execute(interactionContext);
}
callback.onTaskFinished(interactionContext.getUserInfo(), interactionContext.getCoreResponse().getMessage());
} }
} }

View File

@@ -0,0 +1,7 @@
package work.slhaf.agent.core.interaction;
import work.slhaf.agent.core.interaction.data.InteractionContext;
public interface InteractionModule {
void execute(InteractionContext context);
}

View File

@@ -0,0 +1,62 @@
package work.slhaf.agent.core.interaction;
import work.slhaf.agent.common.config.Config;
import work.slhaf.agent.common.config.ModuleConfig;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;
public class InteractionModulesLoader {
private static InteractionModulesLoader interactionModulesLoader;
public static InteractionModulesLoader getInstance(){
if (interactionModulesLoader == null) {
interactionModulesLoader = new InteractionModulesLoader();
}
return interactionModulesLoader;
}
public List<InteractionModule> registerInteractionModules() throws IOException {
List<InteractionModule> moduleList = new ArrayList<>();
List<ModuleConfig> moduleConfigList = Config.getConfig().getModuleConfigList();
for (ModuleConfig moduleConfig : moduleConfigList) {
if (ModuleConfig.Constant.INTERNAL.equals(moduleConfig.getType())) {
moduleList.add(loadInternalModule(moduleConfig.getClassName()));
} else if (ModuleConfig.Constant.EXTERNAL.equals(moduleConfig.getType())) {
moduleList.add(loadExternalModule(moduleConfig.getClassName(),moduleConfig.getPath()));
}
}
return moduleList;
}
private InteractionModule loadExternalModule(String className, String path) {
try {
URL jarUrl = new File(path).toURI().toURL();
URLClassLoader loader = new URLClassLoader(new URL[]{jarUrl}, this.getClass().getClassLoader());
Class<?> clazz = loader.loadClass(className);
loader.close();
return (InteractionModule) clazz.getMethod("getInstance").invoke(null);
} catch (ClassNotFoundException | InvocationTargetException | IllegalAccessException |
NoSuchMethodException | IOException e) {
throw new RuntimeException("Fail to load internal module: " + className ,e);
}
}
private static InteractionModule loadInternalModule(String className) {
try {
Class<?> clazz = Class.forName(className);
//TODO 后续需要规范`getInstance`方法的实现
return (InteractionModule) clazz.getMethod("getInstance").invoke(null);
} catch (ClassNotFoundException | InvocationTargetException | IllegalAccessException | NoSuchMethodException e) {
throw new RuntimeException("Fail to load internal module: " + className,e);
}
}
}

View File

@@ -0,0 +1,28 @@
package work.slhaf.agent.core.interaction;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class InteractionThreadPoolExecutor extends ThreadPoolExecutor {
private static InteractionThreadPoolExecutor interactionThreadPoolExecutor;
private InteractionThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
}
public static InteractionThreadPoolExecutor getInstance() {
if (interactionThreadPoolExecutor == null) {
interactionThreadPoolExecutor = new InteractionThreadPoolExecutor(
8,
24,
60,
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(50)
);
}
return interactionThreadPoolExecutor;
}
}

View File

@@ -1,4 +1,4 @@
package work.slhaf.agent.core.interation; package work.slhaf.agent.core.interaction;
public interface TaskCallback { public interface TaskCallback {
void onTaskFinished(String userInfo,String output); void onTaskFinished(String userInfo,String output);

View File

@@ -0,0 +1,26 @@
package work.slhaf.agent.core.interaction.data;
import com.alibaba.fastjson2.JSONObject;
import lombok.Data;
import work.slhaf.agent.common.chat.pojo.ChatResponse;
import work.slhaf.agent.core.memory.pojo.MemorySlice;
import work.slhaf.agent.modules.task.data.TaskData;
import java.time.LocalDateTime;
import java.util.List;
@Data
public class InteractionContext {
protected String userInfo;
protected String userNickname;
protected LocalDateTime dateTime;
protected boolean finished;
protected String input;
protected JSONObject tempResult;
protected ChatResponse coreResponse;
protected List<MemorySlice> memorySlices;
protected List<String> topicPath;
protected List<TaskData> taskDataList;
}

View File

@@ -1,4 +1,4 @@
package work.slhaf.agent.core.interation.data; package work.slhaf.agent.core.interaction.data;
import lombok.Data; import lombok.Data;

View File

@@ -1,4 +1,4 @@
package work.slhaf.agent.core.interation.data; package work.slhaf.agent.core.interaction.data;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
@@ -7,4 +7,5 @@ import lombok.Data;
@AllArgsConstructor @AllArgsConstructor
public class InteractionOutputData { public class InteractionOutputData {
private String content; private String content;
private String userInfo;
} }

View File

@@ -1,34 +0,0 @@
package work.slhaf.agent.core.interation;
import work.slhaf.agent.common.config.Config;
import work.slhaf.agent.common.config.ModuleConfig;
import work.slhaf.module.InteractionModule;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
public class InteractionModulesLoader {
public static List<InteractionModule> registerInteractionModules() throws IOException {
List<InteractionModule> moduleList = new ArrayList<>();
List<ModuleConfig> moduleConfigList = Config.getConfig().getModuleConfigList();
for (ModuleConfig moduleConfig : moduleConfigList) {
if (ModuleConfig.Constant.INTERNAL.equals(moduleConfig.getType())) {
moduleList.add(loadInternalModule(moduleConfig.getClassName()));
}
}
return moduleList;
}
private static InteractionModule loadInternalModule(String moduleName) {
try {
Class<?> clazz = Class.forName(moduleName);
//TODO 后续需要规范`getInstance`方法的实现
return (InteractionModule) clazz.getMethod("getInstance").invoke(null);
} catch (ClassNotFoundException | InvocationTargetException | IllegalAccessException | NoSuchMethodException e) {
throw new RuntimeException("Fail to load internal module: " + moduleName,e);
}
}
}

View File

@@ -1,17 +1,17 @@
package work.slhaf.agent.modules.memory; package work.slhaf.agent.core.memory;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import work.slhaf.agent.common.chat.pojo.Message; import work.slhaf.agent.common.chat.pojo.Message;
import work.slhaf.agent.modules.memory.exception.UnExistedTopicException; import work.slhaf.agent.core.memory.exception.UnExistedTopicException;
import work.slhaf.agent.modules.memory.node.MemoryNode; import work.slhaf.agent.core.memory.node.MemoryNode;
import work.slhaf.agent.modules.memory.node.TopicNode; import work.slhaf.agent.core.memory.node.TopicNode;
import work.slhaf.agent.modules.memory.pojo.MemoryResult; import work.slhaf.agent.core.memory.pojo.MemoryResult;
import work.slhaf.agent.modules.memory.pojo.MemorySlice; import work.slhaf.agent.core.memory.pojo.MemorySlice;
import work.slhaf.agent.modules.memory.pojo.MemorySliceResult; import work.slhaf.agent.core.memory.pojo.MemorySliceResult;
import work.slhaf.agent.modules.memory.pojo.PersistableObject; import work.slhaf.agent.core.memory.pojo.PersistableObject;
import java.io.*; import java.io.*;
import java.nio.file.Files; import java.nio.file.Files;

View File

@@ -1,10 +1,11 @@
package work.slhaf.agent.modules.memory; package work.slhaf.agent.core.memory;
import lombok.Data; import lombok.Data;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import work.slhaf.agent.common.config.Config; import work.slhaf.agent.common.config.Config;
import work.slhaf.module.InteractionContext; import work.slhaf.agent.core.interaction.InteractionModule;
import work.slhaf.module.InteractionModule; import work.slhaf.agent.core.interaction.data.InteractionContext;
import work.slhaf.agent.modules.memory.SliceEvaluator;
import java.io.IOException; import java.io.IOException;
@@ -29,7 +30,7 @@ public class MemoryManager implements InteractionModule {
Config config = Config.getConfig(); Config config = Config.getConfig();
memoryManager = new MemoryManager(); memoryManager = new MemoryManager();
memoryManager.setMemoryGraph(MemoryGraph.getInstance(config.getAgentId())); memoryManager.setMemoryGraph(MemoryGraph.getInstance(config.getAgentId()));
memoryManager.setSliceEvaluator(SliceEvaluator.initialize(config)); memoryManager.setSliceEvaluator(SliceEvaluator.getInstance());
log.info("MemoryManager注册完毕..."); log.info("MemoryManager注册完毕...");
} }
return memoryManager; return memoryManager;

View File

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

View File

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

View File

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

View File

@@ -1,8 +1,8 @@
package work.slhaf.agent.modules.memory.node; package work.slhaf.agent.core.memory.node;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import work.slhaf.agent.modules.memory.pojo.PersistableObject; import work.slhaf.agent.core.memory.pojo.PersistableObject;
import java.io.Serial; import java.io.Serial;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;

View File

@@ -1,4 +1,4 @@
package work.slhaf.agent.modules.memory.pojo; package work.slhaf.agent.core.memory.pojo;
import lombok.Data; import lombok.Data;

View File

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

View File

@@ -1,4 +1,4 @@
package work.slhaf.agent.modules.memory.pojo; package work.slhaf.agent.core.memory.pojo;
import lombok.Data; import lombok.Data;

View File

@@ -1,4 +1,4 @@
package work.slhaf.agent.modules.memory.pojo; package work.slhaf.agent.core.memory.pojo;
import java.io.Serializable; import java.io.Serializable;

View File

@@ -1,4 +1,4 @@
package work.slhaf.agent.modules.memory.pojo; package work.slhaf.agent.core.memory.pojo;
import lombok.Data; import lombok.Data;

View File

@@ -3,31 +3,41 @@ package work.slhaf.agent.core.model;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import work.slhaf.agent.common.chat.pojo.ChatResponse;
import work.slhaf.agent.common.config.Config; import work.slhaf.agent.common.config.Config;
import work.slhaf.agent.common.model.Model; import work.slhaf.agent.common.model.Model;
import work.slhaf.agent.common.model.ModelConstant; import work.slhaf.agent.common.model.ModelConstant;
import work.slhaf.agent.core.interaction.InteractionModule;
import work.slhaf.agent.core.interaction.data.InteractionContext;
import java.io.IOException; import java.io.IOException;
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@Data @Data
@Slf4j @Slf4j
public class CoreModel extends Model { public class CoreModel extends Model implements InteractionModule {
public static final String MODEL_KEY = "core_model"; public static final String MODEL_KEY = "core_model";
private static CoreModel coreModel; private static CoreModel coreModel;
private CoreModel(){} private CoreModel() {
}
public static CoreModel getInstance() throws IOException, ClassNotFoundException { public static CoreModel getInstance() throws IOException, ClassNotFoundException {
if (coreModel == null) { if (coreModel == null) {
Config config = Config.getConfig(); Config config = Config.getConfig();
coreModel = new CoreModel(); coreModel = new CoreModel();
coreModel.setPrompt(ModelConstant.CORE_MODEL_PROMPT); setModel(config, coreModel, MODEL_KEY, ModelConstant.CORE_MODEL_PROMPT);
setModel(config, coreModel, MODEL_KEY, coreModel.getPrompt());
log.info("CoreModel注册完毕..."); log.info("CoreModel注册完毕...");
} }
return coreModel; return coreModel;
} }
@Override
public void execute(InteractionContext interactionContext) {
//TODO 需要拼接上下文之后再发送给主模型
ChatResponse res = runChat(interactionContext.getInput());
interactionContext.setCoreResponse(res);
}
} }

View File

@@ -7,8 +7,8 @@ import org.java_websocket.WebSocket;
import org.java_websocket.handshake.ClientHandshake; import org.java_websocket.handshake.ClientHandshake;
import org.java_websocket.server.WebSocketServer; import org.java_websocket.server.WebSocketServer;
import work.slhaf.agent.Agent; import work.slhaf.agent.Agent;
import work.slhaf.agent.core.interation.data.InteractionInputData; import work.slhaf.agent.core.interaction.data.InteractionInputData;
import work.slhaf.agent.core.interation.data.InteractionOutputData; import work.slhaf.agent.core.interaction.data.InteractionOutputData;
import java.io.IOException; import java.io.IOException;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
@@ -58,12 +58,12 @@ public class AgentWebSocketServer extends WebSocketServer implements MessageSend
} }
@Override @Override
public void sendMessage(String userInfo,String message) { public void sendMessage(InteractionOutputData outputData) {
WebSocket webSocket = userSessions.get(userInfo); WebSocket webSocket = userSessions.get(outputData.getUserInfo());
if (webSocket != null && webSocket.isOpen()) { if (webSocket != null && webSocket.isOpen()) {
webSocket.send(JSONUtil.toJsonStr(new InteractionOutputData(message))); webSocket.send(JSONUtil.toJsonStr(outputData));
}else { }else {
log.warn("用户不在线: {}",userInfo); log.warn("用户不在线: {}",outputData.getUserInfo());
} }
} }
} }

View File

@@ -1,5 +1,7 @@
package work.slhaf.agent.gateway; package work.slhaf.agent.gateway;
import work.slhaf.agent.core.interaction.data.InteractionOutputData;
public interface MessageSender { public interface MessageSender {
void sendMessage(String userInfo,String message); void sendMessage(InteractionOutputData outputData);
} }

View File

@@ -0,0 +1,33 @@
package work.slhaf.agent.modules.memory;
import lombok.Data;
import work.slhaf.agent.core.interaction.InteractionModule;
import work.slhaf.agent.core.interaction.data.InteractionContext;
import work.slhaf.agent.core.memory.MemoryManager;
import java.io.IOException;
@Data
public class MemorySelector implements InteractionModule {
private static MemorySelector memorySelector;
private MemoryManager memoryManager;
private SliceEvaluator sliceEvaluator;
private MemorySelector(){}
public static MemorySelector getInstance() throws IOException, ClassNotFoundException {
if (memorySelector == null) {
memorySelector = new MemorySelector();
memorySelector.setMemoryManager(MemoryManager.getInstance());
memorySelector.setSliceEvaluator(SliceEvaluator.getInstance());
}
return memorySelector;
}
@Override
public void execute(InteractionContext interactionContext) {
}
}

View File

@@ -0,0 +1,33 @@
package work.slhaf.agent.modules.memory;
import lombok.Data;
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.core.memory.MemoryManager;
import java.io.IOException;
@Data
public class MemoryUpdater implements InteractionModule {
private static MemoryUpdater memoryUpdater;
private MemoryManager memoryManager;
private InteractionThreadPoolExecutor executor;
private MemoryUpdater(){}
public static MemoryUpdater getInstance() throws IOException, ClassNotFoundException {
if (memoryUpdater == null) {
memoryUpdater = new MemoryUpdater();
memoryUpdater.setMemoryManager(MemoryManager.getInstance());
}
return memoryUpdater;
}
@Override
public void execute(InteractionContext interactionContext) {
}
}

View File

@@ -19,12 +19,11 @@ public class SliceEvaluator extends Model {
private SliceEvaluator(){} private SliceEvaluator(){}
public static SliceEvaluator initialize(Config config) throws IOException, ClassNotFoundException { public static SliceEvaluator getInstance() throws IOException, ClassNotFoundException {
if (sliceEvaluator == null) { if (sliceEvaluator == null) {
Config config = Config.getConfig();
sliceEvaluator = new SliceEvaluator(); sliceEvaluator = new SliceEvaluator();
sliceEvaluator.setPrompt(ModelConstant.SLICE_EVALUATOR_PROMPT); setModel(config,sliceEvaluator, MODEL_KEY, ModelConstant.SLICE_EVALUATOR_PROMPT);
setModel(config,sliceEvaluator, MODEL_KEY, sliceEvaluator.getPrompt());
log.info("SliceEvaluator注册完毕..."); log.info("SliceEvaluator注册完毕...");
} }

View File

@@ -1,7 +1,7 @@
package work.slhaf.agent.modules.preprocess; package work.slhaf.agent.modules.preprocess;
import work.slhaf.agent.core.interation.data.InteractionInputData; import work.slhaf.agent.core.interaction.data.InteractionContext;
import work.slhaf.module.InteractionContext; import work.slhaf.agent.core.interaction.data.InteractionInputData;
public class PreprocessExecutor { public class PreprocessExecutor {
@@ -18,11 +18,13 @@ public class PreprocessExecutor {
public InteractionContext execute(InteractionInputData inputData) { public InteractionContext execute(InteractionInputData inputData) {
InteractionContext context = new InteractionContext(); InteractionContext context = new InteractionContext();
context.setDateTime(inputData.getLocalDateTime());
context.setFinished(false);
context.setInput(inputData.getContent());
context.setUserInfo(inputData.getUserInfo()); context.setUserInfo(inputData.getUserInfo());
context.setUserNickname(inputData.getUserNickName()); context.setUserNickname(inputData.getUserNickName());
context.setDateTime(inputData.getLocalDateTime());
context.setFinished(false);
context.setInput(inputData.getContent());
return context; return context;
} }

View File

@@ -1,4 +1,27 @@
package work.slhaf.agent.modules.task; package work.slhaf.agent.modules.task;
public class TaskEvaluator { import lombok.Data;
import lombok.EqualsAndHashCode;
import work.slhaf.agent.common.config.Config;
import work.slhaf.agent.common.config.ModelConfig;
import work.slhaf.agent.common.model.Model;
import work.slhaf.agent.common.model.ModelConstant;
import java.io.IOException;
@EqualsAndHashCode(callSuper = true)
@Data
public class TaskEvaluator extends Model {
public static final String MODEL_KEY = "task_evaluator";
private static TaskEvaluator taskEvaluator;
private TaskEvaluator (){}
public static TaskEvaluator getInstance() throws IOException, ClassNotFoundException {
if (taskEvaluator == null) {
taskEvaluator = new TaskEvaluator();
setModel(Config.getConfig(),taskEvaluator,MODEL_KEY,ModelConstant.TASK_EVALUATOR_PROMPT);
}
return taskEvaluator;
}
} }

View File

@@ -1,4 +1,20 @@
package work.slhaf.agent.modules.task; package work.slhaf.agent.modules.task;
import lombok.Data;
import work.slhaf.agent.core.interaction.InteractionThreadPoolExecutor;
@Data
public class TaskExecutor { public class TaskExecutor {
private static TaskExecutor taskExecutor;
private InteractionThreadPoolExecutor executor;
private TaskExecutor(){}
public static TaskExecutor getInstance(){
if (taskExecutor == null){
taskExecutor = new TaskExecutor();
taskExecutor.setExecutor(InteractionThreadPoolExecutor.getInstance());
}
return taskExecutor;
}
} }

View File

@@ -1,31 +1,22 @@
package work.slhaf.agent.modules.task; package work.slhaf.agent.modules.task;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import work.slhaf.agent.common.config.Config; import work.slhaf.agent.core.interaction.InteractionModule;
import work.slhaf.agent.common.model.Model; import work.slhaf.agent.core.interaction.data.InteractionContext;
import work.slhaf.agent.common.model.ModelConstant;
import work.slhaf.module.InteractionContext;
import work.slhaf.module.InteractionModule;
import java.io.IOException; import java.io.IOException;
@EqualsAndHashCode(callSuper = true)
@Data @Data
@Slf4j @Slf4j
public class TaskScheduler extends Model implements InteractionModule { public class TaskScheduler implements InteractionModule {
public static final String MODEL_KEY = "task_trigger";
private static TaskScheduler taskScheduler; private static TaskScheduler taskScheduler;
private TaskScheduler(){} private TaskScheduler(){}
public static TaskScheduler getInstance() throws IOException, ClassNotFoundException { public static TaskScheduler getInstance() throws IOException, ClassNotFoundException {
if (taskScheduler == null) { if (taskScheduler == null) {
Config config = Config.getConfig();
taskScheduler = new TaskScheduler(); taskScheduler = new TaskScheduler();
taskScheduler.setPrompt(ModelConstant.SLICE_EVALUATOR_PROMPT);
setModel(config, taskScheduler, MODEL_KEY, taskScheduler.getPrompt());
log.info("TaskScheduler注册完毕..."); log.info("TaskScheduler注册完毕...");
} }

View File

@@ -0,0 +1,31 @@
package work.slhaf.agent.modules.task.data;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
@Data
public class TaskData implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
private String id;
/**
* 执行类别: 即时任务/定时任务
*/
private String executeType;
/**
* cron表达式仅定时任务需要填写
*/
private String cronStr;
private String comment;
public static class Constant {
public static final String CURRENT = "current";
public static final String SCHEDULE = "schedule";
}
}

View File

@@ -2,11 +2,14 @@ package work.slhaf.agent.modules.topic;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
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.config.Config; import work.slhaf.agent.common.config.Config;
import work.slhaf.agent.common.model.Model; import work.slhaf.agent.common.model.Model;
import work.slhaf.agent.common.model.ModelConstant; import work.slhaf.agent.common.model.ModelConstant;
import work.slhaf.module.InteractionContext; import work.slhaf.agent.core.interaction.InteractionModule;
import work.slhaf.module.InteractionModule; import work.slhaf.agent.core.interaction.data.InteractionContext;
import java.io.IOException; import java.io.IOException;
@@ -23,8 +26,7 @@ public class TopicExtractor extends Model implements InteractionModule {
if (topicExtractor == null) { if (topicExtractor == null) {
Config config = Config.getConfig(); Config config = Config.getConfig();
topicExtractor = new TopicExtractor(); topicExtractor = new TopicExtractor();
topicExtractor.setPrompt(ModelConstant.SLICE_EVALUATOR_PROMPT); setModel(config, topicExtractor, MODEL_KEY, ModelConstant.TOPIC_EXTRACTOR_PROMPT);
setModel(config, topicExtractor, MODEL_KEY, topicExtractor.getPrompt());
} }
return topicExtractor; return topicExtractor;
@@ -32,6 +34,8 @@ public class TopicExtractor extends Model implements InteractionModule {
@Override @Override
public void execute(InteractionContext interactionContext) { public void execute(InteractionContext interactionContext) {
String primaryMessageResponse = singleChat(interactionContext.getInput()).getMessage();
} }
} }

View File

@@ -2,10 +2,10 @@ package memory;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import work.slhaf.agent.modules.memory.MemoryGraph; import work.slhaf.agent.core.memory.MemoryGraph;
import work.slhaf.agent.modules.memory.pojo.MemorySlice; import work.slhaf.agent.core.memory.pojo.MemorySlice;
import work.slhaf.agent.modules.memory.node.MemoryNode; import work.slhaf.agent.core.memory.node.MemoryNode;
import work.slhaf.agent.modules.memory.node.TopicNode; import work.slhaf.agent.core.memory.node.TopicNode;
import java.io.IOException; import java.io.IOException;
import java.time.LocalDate; import java.time.LocalDate;

View File

@@ -2,12 +2,12 @@ package memory;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import work.slhaf.agent.modules.memory.MemoryGraph; import work.slhaf.agent.core.memory.MemoryGraph;
import work.slhaf.agent.modules.memory.pojo.MemorySlice; import work.slhaf.agent.core.memory.pojo.MemorySlice;
import work.slhaf.agent.modules.memory.exception.UnExistedTopicException; import work.slhaf.agent.core.memory.exception.UnExistedTopicException;
import work.slhaf.agent.modules.memory.node.MemoryNode; import work.slhaf.agent.core.memory.node.MemoryNode;
import work.slhaf.agent.modules.memory.node.TopicNode; import work.slhaf.agent.core.memory.node.TopicNode;
import work.slhaf.agent.modules.memory.pojo.MemoryResult; import work.slhaf.agent.core.memory.pojo.MemoryResult;
import java.io.IOException; import java.io.IOException;
import java.time.LocalDate; import java.time.LocalDate;