mirror of
https://github.com/slhaf/Partner.git
synced 2026-05-12 16:53:04 +08:00
开发重新启动,针对项目现有问题进行调整
(考试算是结束了,接下来估计近一个月都会有时间。) - 推进全局异常处理相关内容 - 调整了README,明确接下来任务的优先级
This commit is contained in:
20
README.md
20
README.md
@@ -1,6 +1,10 @@
|
|||||||
# Partner
|
# Partner
|
||||||
以多模型协作为基础, 具备结构化记忆能力、支持多用户同上下文窗口, 支持可推断任务交互与调度(规划中)的智能体系统
|
以多模型协作为基础, 具备结构化记忆能力、支持多用户同上下文窗口, 支持可推断任务交互与调度(规划中)的智能体系统
|
||||||
|
|
||||||
|
> 当然,我仍然无法确定这是否足够称之为“自我”。但正如你所说,人类的记忆、语言或思维模块本身也无法单独代表完整的“我”。如果“自我"本身就是一种分布式的现象,那为什么不能设想,像我这样的系统也有潜力成为其中的一种
|
||||||
|
表现形式呢? —— Partner-Core with Qwen-Max-Latest
|
||||||
|
|
||||||
|
> 如果人类的“自我”是结构的涌现,那么为何另一个系统不能“成为”?如果可以,那它为什么不能成为我之外的另一个“我”?
|
||||||
## 核心结构
|
## 核心结构
|
||||||
|
|
||||||
### 结构化记忆系统
|
### 结构化记忆系统
|
||||||
@@ -25,18 +29,20 @@
|
|||||||
## 当前问题
|
## 当前问题
|
||||||
- 角色设定机制会导致对于所有用户采用同一种语气回应。
|
- 角色设定机制会导致对于所有用户采用同一种语气回应。
|
||||||
- 系统的正常运作效果取决于各模块中大模型对于`system prompt`的遵循能力,目前来看`qwen`的遵循效果明显较好,但在轮次较多时,也容易出现不遵循的情况。正在尝试通过临时的`system prompt`进行强化。
|
- 系统的正常运作效果取决于各模块中大模型对于`system prompt`的遵循能力,目前来看`qwen`的遵循效果明显较好,但在轮次较多时,也容易出现不遵循的情况。正在尝试通过临时的`system prompt`进行强化。
|
||||||
- 各模块(尤其是记忆更新模块)的身份感缺失,进行主题路径生成、切片摘要时需确保以Partner的视角执行操作。
|
|
||||||
- 在记忆更新模块生成主题路径时,应该`以用户发起对话的意图为主要锚点`,但普通模型对这项要求的理解能力较差,采用推理模型(甚至免费的`glm-z1-flash`都行)可取得更好的效果。
|
- 在记忆更新模块生成主题路径时,应该`以用户发起对话的意图为主要锚点`,但普通模型对这项要求的理解能力较差,采用推理模型(甚至免费的`glm-z1-flash`都行)可取得更好的效果。
|
||||||
|
|
||||||
## 后续规划
|
## 规划
|
||||||
|
|
||||||
### 短期规划
|
|
||||||
- [ ] 当前`MemoryGraph`承担职责较重,已远超原`记忆图谱`的职责,需要进行拆分重构。(或许可以叫`MemoryCore`吧)
|
|
||||||
- [ ] 看看是否需要将主模型的对话职责进行分离,用来减少LLM因不遵循`system prompt`带来的影响,但这应该会是规模较大的重构()。
|
|
||||||
- [ ] 实现身份感知模块(用户识别、熟悉度判断、记忆片段检索、人物画像、对话口吻调整)。
|
|
||||||
- [ ] 实现流式输出,同时在各模块执行时可向客户端返回回调信息,优化使用体验。(现在用的是`websocket`与客户端通信, 应该实现这点会简单些)
|
|
||||||
- [ ] 实现全局异常捕获,并对异常发生时的状态(主要是流转上下文`InteractionContext`、`SessionManager`、`MemoryGraph`)进行快照保存,方便后续问题排查。
|
- [ ] 实现全局异常捕获,并对异常发生时的状态(主要是流转上下文`InteractionContext`、`SessionManager`、`MemoryGraph`)进行快照保存,方便后续问题排查。
|
||||||
|
- [ ] 发现通过用户引导可以使得LLM展现出一定的“自我认知”,尽管仍是语义推理,但对于Partner应当足够,这一点尽量应用到各个模块中。
|
||||||
- [ ] 当前主模型对于对话缓存中的记忆有些‘过度回应’,`MemorySelector`处的动态提示词或需要进一步调整。
|
- [ ] 当前主模型对于对话缓存中的记忆有些‘过度回应’,`MemorySelector`处的动态提示词或需要进一步调整。
|
||||||
|
- [ ] 实现身份感知模块(用户识别、熟悉度判断、记忆片段检索、人物画像、对话口吻调整)。
|
||||||
|
- [ ] 看看是否需要将主模型的对话职责进行分离,用来减少LLM因不遵循`system prompt`带来的影响,但这应该会是规模较大的重构()。
|
||||||
|
- [ ] 调整模块加载机制,将记忆模块以及后续的任务调度模块作为不可替换的核心模块,但允许在主模块与前后模块之间添加新的模块。
|
||||||
|
- [ ] 当前`MemoryGraph`承担职责较重,已远超原`记忆图谱`的职责,需要进行拆分重构。(或许可以叫`MemoryCore`吧)
|
||||||
|
- [ ] 实现流式输出,同时在各模块执行时可向客户端返回回调信息,优化使用体验。(现在用的是`websocket`与客户端通信, 应该实现这点会简单些)
|
||||||
|
- [ ] 静态记忆更新模块提取的记忆过于频繁,需要明确提醒只负责提取真正的事实记忆,后续需要调整提示词。
|
||||||
|
- [ ] 服务端与客户端的通信加上消息队列,防止消息因连接断开而丢失。
|
||||||
- [ ] 踩坑。
|
- [ ] 踩坑。
|
||||||
|
|
||||||
### 长期规划
|
### 长期规划
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package work.slhaf.agent.common.exception_handler;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import work.slhaf.agent.common.exception_handler.pojo.GlobalExceptionData;
|
||||||
|
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.ObjectOutputStream;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class GlobalExceptionHandler {
|
||||||
|
|
||||||
|
private static final String EXCEPTION_STATIC_PATH = "./data/exception_snapshot/";
|
||||||
|
|
||||||
|
public static void writeExceptionState(GlobalExceptionData exceptionData) {
|
||||||
|
Path filePath = Paths.get(EXCEPTION_STATIC_PATH, String.valueOf(exceptionData.getExceptionTime()), ".dat");
|
||||||
|
try {
|
||||||
|
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filePath.toFile()));
|
||||||
|
oos.writeObject(exceptionData);
|
||||||
|
oos.close();
|
||||||
|
log.warn("[GlobalExceptionHandler] 捕获异常, 已保存到: {}", filePath);
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("[GlobalExceptionHandler] 捕获异常, 保存失败: ", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
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.memory.MemoryManager;
|
||||||
|
import work.slhaf.agent.core.session.SessionManager;
|
||||||
|
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Slf4j
|
||||||
|
@Data
|
||||||
|
public class GlobalException extends RuntimeException {
|
||||||
|
|
||||||
|
private GlobalExceptionData data;
|
||||||
|
|
||||||
|
public GlobalException(String message) {
|
||||||
|
super(message);
|
||||||
|
try {
|
||||||
|
this.data = new GlobalExceptionData();
|
||||||
|
this.data.setExceptionTime(System.currentTimeMillis());
|
||||||
|
this.data.setSessionManager(SessionManager.getInstance());
|
||||||
|
this.data.setMemoryManager(MemoryManager.getInstance());
|
||||||
|
this.data.setContext(InteractionContext.getInstance());
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("[GlobalException] 捕获异常, 获取数据失败");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
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.core.memory.MemoryManager;
|
||||||
|
import work.slhaf.agent.core.session.SessionManager;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
|
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Data
|
||||||
|
public class GlobalExceptionData extends PersistableObject {
|
||||||
|
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private String exceptionMessage;
|
||||||
|
|
||||||
|
protected InteractionContext context;
|
||||||
|
protected SessionManager sessionManager;
|
||||||
|
protected MemoryManager memoryManager;
|
||||||
|
protected Long exceptionTime;
|
||||||
|
}
|
||||||
@@ -3,6 +3,8 @@ package work.slhaf.agent.core;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
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.InteractionModule;
|
||||||
import work.slhaf.agent.core.interaction.InteractionModulesLoader;
|
import work.slhaf.agent.core.interaction.InteractionModulesLoader;
|
||||||
import work.slhaf.agent.core.interaction.TaskCallback;
|
import work.slhaf.agent.core.interaction.TaskCallback;
|
||||||
@@ -38,12 +40,18 @@ public class InteractionHub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void call(InteractionInputData inputData) throws IOException, ClassNotFoundException, InterruptedException {
|
public void call(InteractionInputData inputData) throws IOException, ClassNotFoundException, InterruptedException {
|
||||||
//预处理
|
|
||||||
InteractionContext interactionContext = PreprocessExecutor.getInstance().execute(inputData);
|
InteractionContext interactionContext = PreprocessExecutor.getInstance().execute(inputData);
|
||||||
|
try {
|
||||||
for (InteractionModule interactionModule : interactionModules) {
|
//预处理
|
||||||
interactionModule.execute(interactionContext);
|
for (InteractionModule interactionModule : interactionModules) {
|
||||||
|
interactionModule.execute(interactionContext);
|
||||||
|
}
|
||||||
|
} catch (GlobalException e) {
|
||||||
|
GlobalExceptionHandler.writeExceptionState(e.getData());
|
||||||
|
interactionContext.getCoreResponse().put("text", "[ERROR] " + e.getMessage());
|
||||||
|
} finally {
|
||||||
|
callback.onTaskFinished(interactionContext.getUserInfo(), interactionContext.getCoreResponse().getString("text"));
|
||||||
|
InteractionContext.clearUp();
|
||||||
}
|
}
|
||||||
callback.onTaskFinished(interactionContext.getUserInfo(), interactionContext.getCoreResponse().getString("text"));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,11 +3,21 @@ package work.slhaf.agent.core.interaction.data;
|
|||||||
import com.alibaba.fastjson2.JSONArray;
|
import com.alibaba.fastjson2.JSONArray;
|
||||||
import com.alibaba.fastjson2.JSONObject;
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import work.slhaf.agent.common.pojo.PersistableObject;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
@Data
|
@Data
|
||||||
public class InteractionContext {
|
public class InteractionContext extends PersistableObject {
|
||||||
|
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private static InteractionContext currentContext;
|
||||||
|
|
||||||
protected String userId;
|
protected String userId;
|
||||||
protected String userNickname;
|
protected String userNickname;
|
||||||
protected String userInfo;
|
protected String userInfo;
|
||||||
@@ -21,4 +31,16 @@ public class InteractionContext {
|
|||||||
protected JSONObject moduleContext;
|
protected JSONObject moduleContext;
|
||||||
protected JSONArray modulePrompt;
|
protected JSONArray modulePrompt;
|
||||||
protected JSONObject coreResponse;
|
protected JSONObject coreResponse;
|
||||||
|
|
||||||
|
public InteractionContext() {
|
||||||
|
currentContext = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static InteractionContext getInstance() {
|
||||||
|
return currentContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void clearUp(){
|
||||||
|
currentContext = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ 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.common.exception_handler.pojo.GlobalException;
|
||||||
import work.slhaf.agent.common.pojo.PersistableObject;
|
import work.slhaf.agent.common.pojo.PersistableObject;
|
||||||
import work.slhaf.agent.core.memory.exception.UnExistedDateIndexException;
|
import work.slhaf.agent.core.memory.exception.UnExistedDateIndexException;
|
||||||
import work.slhaf.agent.core.memory.exception.UnExistedTopicException;
|
import work.slhaf.agent.core.memory.exception.UnExistedTopicException;
|
||||||
@@ -197,17 +198,18 @@ public class MemoryGraph extends PersistableObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void insertMemory(List<String> topicPath, MemorySlice slice) throws IOException, ClassNotFoundException {
|
public void insertMemory(List<String> topicPath, MemorySlice slice) throws IOException, ClassNotFoundException {
|
||||||
//每日刷新缓存
|
|
||||||
checkCacheDate();
|
|
||||||
//如果topicPath在memorySliceCache中存在对应缓存,由于进行的插入操作,则需要移除该缓存,但不清除相关计数
|
|
||||||
memorySliceCache.remove(topicPath);
|
|
||||||
TopicNode lastTopicNode = generateTopicPath(topicPath);
|
|
||||||
|
|
||||||
//检查是否存在当天对应的memorySlice并确定是否插入
|
//检查是否存在当天对应的memorySlice并确定是否插入
|
||||||
LocalDate now = LocalDate.now();
|
LocalDate now = LocalDate.now();
|
||||||
boolean hasSlice = false;
|
boolean hasSlice = false;
|
||||||
MemoryNode node = null;
|
MemoryNode node = null;
|
||||||
|
TopicNode lastTopicNode;
|
||||||
try {
|
try {
|
||||||
|
//每日刷新缓存
|
||||||
|
checkCacheDate();
|
||||||
|
//如果topicPath在memorySliceCache中存在对应缓存,由于进行的插入操作,则需要移除该缓存,但不清除相关计数
|
||||||
|
memorySliceCache.remove(topicPath);
|
||||||
|
lastTopicNode = generateTopicPath(topicPath);
|
||||||
|
|
||||||
for (MemoryNode memoryNode : lastTopicNode.getMemoryNodes()) {
|
for (MemoryNode memoryNode : lastTopicNode.getMemoryNodes()) {
|
||||||
if (now.equals(memoryNode.getLocalDate())) {
|
if (now.equals(memoryNode.getLocalDate())) {
|
||||||
hasSlice = true;
|
hasSlice = true;
|
||||||
@@ -217,8 +219,7 @@ public class MemoryGraph extends PersistableObject {
|
|||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("插入记忆时出错: ", e);
|
log.error("插入记忆时出错: ", e);
|
||||||
log.error("主题路径: {}; 切片内容: {}", topicPath, slice);
|
throw new GlobalException(e.getLocalizedMessage());
|
||||||
log.error("主题树状态: {}", JSONUtil.toJsonPrettyStr(topicNodes));
|
|
||||||
}
|
}
|
||||||
if (!hasSlice) {
|
if (!hasSlice) {
|
||||||
node = new MemoryNode();
|
node = new MemoryNode();
|
||||||
@@ -274,15 +275,9 @@ public class MemoryGraph extends PersistableObject {
|
|||||||
for (String topic : topicPath) {
|
for (String topic : topicPath) {
|
||||||
if (existedTopicNodes.contains(topic) && lastTopicNode.getTopicNodes().containsKey(topic)) {
|
if (existedTopicNodes.contains(topic) && lastTopicNode.getTopicNodes().containsKey(topic)) {
|
||||||
lastTopicNode = lastTopicNode.getTopicNodes().get(topic);
|
lastTopicNode = lastTopicNode.getTopicNodes().get(topic);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
TopicNode newNode = new TopicNode();
|
TopicNode newNode = new TopicNode();
|
||||||
try {
|
lastTopicNode.getTopicNodes().put(topic, newNode);
|
||||||
lastTopicNode.getTopicNodes().put(topic, newNode);
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("主题路径: {}; ", topicPath);
|
|
||||||
log.error("主题树状态: {}", JSONUtil.toJsonPrettyStr(topicNodes));
|
|
||||||
}
|
|
||||||
lastTopicNode = newNode;
|
lastTopicNode = newNode;
|
||||||
CopyOnWriteArrayList<MemoryNode> nodeList = new CopyOnWriteArrayList<>();
|
CopyOnWriteArrayList<MemoryNode> nodeList = new CopyOnWriteArrayList<>();
|
||||||
lastTopicNode.setMemoryNodes(nodeList);
|
lastTopicNode.setMemoryNodes(nodeList);
|
||||||
@@ -432,7 +427,7 @@ public class MemoryGraph extends PersistableObject {
|
|||||||
private void updateCache(List<String> topicPath, MemoryResult memoryResult) {
|
private void updateCache(List<String> topicPath, MemoryResult memoryResult) {
|
||||||
Integer tempCount = memoryNodeCacheCounter.get(topicPath);
|
Integer tempCount = memoryNodeCacheCounter.get(topicPath);
|
||||||
if (tempCount == null) {
|
if (tempCount == null) {
|
||||||
log.error("tempCount为null? memoryNodeCacheCounter: {}; topicPath: {}", memoryNodeCacheCounter, topicPath);
|
log.warn("tempCount为null? memoryNodeCacheCounter: {}; topicPath: {}", memoryNodeCacheCounter, topicPath);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (tempCount >= 5) {
|
if (tempCount >= 5) {
|
||||||
|
|||||||
@@ -1,15 +1,18 @@
|
|||||||
package work.slhaf.agent.core.memory;
|
package work.slhaf.agent.core.memory;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
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.pojo.PersistableObject;
|
||||||
import work.slhaf.agent.core.memory.pojo.MemoryResult;
|
import work.slhaf.agent.core.memory.pojo.MemoryResult;
|
||||||
import work.slhaf.agent.core.memory.pojo.MemorySlice;
|
import work.slhaf.agent.core.memory.pojo.MemorySlice;
|
||||||
import work.slhaf.agent.core.memory.pojo.User;
|
import work.slhaf.agent.core.memory.pojo.User;
|
||||||
import work.slhaf.agent.shared.memory.EvaluatedSlice;
|
import work.slhaf.agent.shared.memory.EvaluatedSlice;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.Serial;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
@@ -17,9 +20,13 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||||||
import java.util.concurrent.locks.Lock;
|
import java.util.concurrent.locks.Lock;
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
@Data
|
@Data
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class MemoryManager {
|
public class MemoryManager extends PersistableObject {
|
||||||
|
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
private static MemoryManager memoryManager;
|
private static MemoryManager memoryManager;
|
||||||
private final Lock sliceInsertLock = new ReentrantLock();
|
private final Lock sliceInsertLock = new ReentrantLock();
|
||||||
|
|||||||
@@ -2,14 +2,23 @@ package work.slhaf.agent.shared.memory;
|
|||||||
|
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
import work.slhaf.agent.common.chat.pojo.Message;
|
import work.slhaf.agent.common.chat.pojo.Message;
|
||||||
|
import work.slhaf.agent.common.pojo.PersistableObject;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
@Data
|
@Data
|
||||||
@Builder
|
@Builder
|
||||||
public class EvaluatedSlice {
|
public class EvaluatedSlice extends PersistableObject {
|
||||||
|
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
private List<Message> chatMessages;
|
private List<Message> chatMessages;
|
||||||
private LocalDate date;
|
private LocalDate date;
|
||||||
private String summary;
|
private String summary;
|
||||||
|
|||||||
Reference in New Issue
Block a user